3 # Copyright 2013 Intel Corporation
4 # Author: Artem Bityutskiy
7 PROG="setup-extlinux-conf"
10 srcdir="$(readlink -ev -- ${0%/*})"
11 if [ -f "$srcdir/setup-ivi-sh-functions" ]; then
12 . "$srcdir/setup-ivi-sh-functions"
14 . /usr/share/setup-ivi/setup-ivi-sh-functions
17 # This is a small trick which I use to make sure my scripts are portable -
18 # check if 'dash' is present, and if yes - use it.
19 if can_switch_to_dash; then
20 exec dash -euf "$srcdir/$PROG" "$@"
24 # Common preparations for all subcommands.
27 verbose "Boot directory is $bootdir"
28 [ -d "$bootdir" ] || \
29 fatal "boot directory path \"$bootdir\" does not exist"
31 # The extlinux configuration directory
32 conf_dir="$bootdir/extlinux"
33 # The extlinux configuration file
34 conf_file="$conf_dir/extlinux.conf"
37 # Create the default extlinux configuration file.
38 create_default_conf_file()
40 verbose "creating the default configuration file \"$conf_file\""
42 mkdir -p $verbose "$conf_dir" >&2
43 cat > "$conf_file" <<-EOF
52 # Check wheter the extlinux configuration file exist and if not:
53 # o create the default one if --force option was specified
54 # o fail if no --force option was specified
55 check_and_create_default_conf_file()
57 if [ -s "$conf_file" ]; then
61 if [ -n "$force" ]; then
62 create_default_conf_file "$1"
64 fatal "cannot find the extlinux configuration file" \
65 "(\"$conf_file\") (use -f to force creating the" \
70 # Get a regular expression for matching extlinux configuration file option "$1"
73 local opt="$(esc_regexp "$1")"
75 opt="$(case_insensitive_regexp "$opt")"
76 printf "%s" "\(^[[:blank:]]*$opt[[:blank:]]\+\)\([^[:blank:]]\+\)\([[:blank:]]*$\)"
79 # Return a regular expression for matching label with name "$1".
82 local opt="$(case_insensitive_regexp "label")"
83 local label="$(esc_regexp "$1")"
85 printf "%s" "\(^[[:blank:]]*$opt[[:blank:]]\+\)\($label\)\([[:blank:]]*$\)"
91 local l_regexp="$(label_regexp "$label")"
92 local anyl_regexp="$(get_regexp "label")"
94 LC_ALL=C sed -i -n -e "/$l_regexp/ { # mathes our label line
95 :l n; # get the next line
96 /$l_regexp/bl # same label again, keep skipping
97 /$anyl_regexp/!bl # a different label, stop skipping
99 /$l_regexp/!p # print all other lines
102 remove_trailing_empty_lines "$conf_file"
106 # -----------------------------------------------------------------------------
107 # The "add" subcommand
108 # -----------------------------------------------------------------------------
114 Usage: $PROG add [options] <label> <title> <kernel> <options>
116 Add a new extlinux boot menu entry. The mandatory arguments are:
118 <label> - a unique name of the boot menu entry to add, the entry will be
119 further refurred by the label
120 <title> - the boot menu entry title
121 <kernel> - name of the kernel binary corresponding to the entry
122 <options> - kernel boot options
125 -f, --force if <label> already exists - re-create it, if
126 <bootdir>/extlinux/extlinux.conf does not exist - create it, if
127 <bootdir>/<kernel> does not exist - do not fail
128 -h, --help show this text and exit
132 show_add_usage_fail()
134 IFS= printf "%s\n\n" "$PROG: error: $*" >&2
141 if [ "$#" -eq 0 ]; then
147 tmp=`getopt -n $PROG -o f,h --long force,help -- "$@"` ||
148 show_add_usage_fail "cannot parse command-line options"
163 *) show_add_usage_fail "unrecognized option \"$1\""
169 if [ "$#" -lt 4 ]; then
170 show_add_usage_fail "too little arguments"
172 if [ "$#" -gt 4 ]; then
173 show_add_usage_fail "too many arguments: \"$1\""
178 local label="$1"; shift
179 local title="$1"; shift
180 local kernel="$1"; shift
181 local options="$1"; shift
182 local kernel_path="$bootdir/$kernel"
184 verbose "label is \"$label\""
185 verbose "title is \"$title\""
186 verbose "kernel is \"$kernel\""
187 verbose "options are \"$options\""
189 if ! [ -f "$kernel_path" ] && [ -z "$force" ]; then
190 fatal "cannot find kernel \"$kernel_path\"" \
191 "(use -f to ignore this error)"
194 # Make sure the extlinux configuration file exists
195 check_and_create_default_conf_file "$label"
197 if LC_ALL=C grep -q -e "$(label_regexp "$label")" "$conf_file" && \
198 [ -z "$force" ]; then
199 fatal "extlinux boot menu label \"$label\" already exists" \
200 "(use -f to force re-creating it)"
203 # Find out the kernel version from its name
204 local kernel_version="$(printf "%s" "$kernel" | LC_ALL=C \
205 sed -e 's/[^[:digit:]]\+-\([[:digit:]]\+.*\)/\1/')"
206 [ -n "$kernel_version" ] || \
207 fatal "cannot fetch kernel version from \"$kernel\""
209 # Remove the label if it exists, since we are going to add a new one
210 remove_label "$label"
212 local block="label $label
213 menu label $title ($kernel_version)
217 printf "\n%s\n" "$block" >> "$conf_file"
219 if [ -n "$verbose" ]; then
220 verbose "Added the following to \"$conf_file\":"
221 printf "%s\n" "$block" >&2
226 # -----------------------------------------------------------------------------
227 # The "remove" subcommand
228 # -----------------------------------------------------------------------------
234 Usage: $PROG remove [options] <label>
236 Delete extlinux boot entry which has label <label>.
239 -f, --force do not fail if the entry doesn't exist
240 -h, --help show this text and exit
244 show_remove_usage_fail()
246 IFS= printf "%s\n\n" "$PROG: error: $*" >&2
247 show_remove_usage >&2
253 if [ "$#" -eq 0 ]; then
259 tmp=`getopt -n $PROG -o f,h --long force,help -- "$@"` ||
260 show_remove_usage_fail "cannot parse command-line options"
275 *) show_remove_usage_fail "unrecognized option \"$1\""
281 if [ "$#" -lt 1 ]; then
282 show_remove_usage_fail "too little arguments"
284 if [ "$#" -gt 1 ]; then
285 show_remove_usage_fail "too many arguments: \"$1\""
292 if ! LC_ALL=C grep -q -e "$(label_regexp "$label")" "$conf_file" && \
293 [ -z "$force" ]; then
294 fatal "cannot find label \"$label\" in \"$conf_file\"" \
295 "(use -f to ignore this error)"
298 remove_label "$label"
299 verbose "removed $label"
303 # -----------------------------------------------------------------------------
304 # The "default" subcommand
305 # -----------------------------------------------------------------------------
308 # Get the kernel binary name by its extlinux.conf label name
309 get_kernel_by_label()
312 local l_regexp="$(label_regexp "$label")" # Regexp for our label
313 local anyl_regexp="$(get_regexp "label")" # Regexp for any label
314 local linux_regexp="$(get_regexp "linux")"
315 local kernel_regexp="$(get_regexp "kernel")"
318 [ -z "$label" ] && return 0
320 result="$(LC_ALL=C sed -n -e "/$l_regexp/ {
322 /$linux_regexp/ { s/$linux_regexp/\2/p }
323 /$kernel_regexp/ { s/$kernel_regexp/\2/p }
324 /$anyl_regexp/!bl # Loop till the next label
327 printf "%s" "${result##*/}"
333 Usage: $PROG default [options] <label>
335 Set the default boot kernel to be the kernel which is marked with label <label>
336 the extlinux configuration file. If <label> is omited, this command prints the
337 currently default entry name.
340 -f, --force <bootdir>/extlinux/extlinux.conf does not exist - create it, if
341 <label> does not exist - do not fail
342 -h, --help show this text and exit
346 show_default_usage_fail()
348 IFS= printf "%s\n\n" "$PROG: error: $*" >&2
349 show_default_usage >&2
356 tmp=`getopt -n $PROG -o f,h --long force,help -- "$@"` ||
357 show_default_usage_fail "cannot parse command-line options"
372 *) show_default_usage_fail "unrecognized option \"$1\""
378 if [ "$#" -gt 1 ]; then
379 show_default_usage_fail "too many arguments: \"$1\""
384 local label="${1:-}";
386 # Make sure the extlinux configuration file exists
387 check_and_create_default_conf_file "$label"
389 # Find the current default label
390 local regexp="$(get_regexp "default")"
391 local default_label="$(LC_ALL=C sed -n -e "s/$regexp/\2/p" "$conf_file")"
393 if [ -z "$label" ]; then
394 printf "%s\n" "label: $default_label"
395 printf "%s\n" "kernel: $(get_kernel_by_label "$default_label")"
399 local l_regexp="$(label_regexp "$label")"
400 local labels="$(LC_ALL=C grep -e "$l_regexp" "$conf_file" | wc -l)"
402 if [ "$labels" -eq "0" ] && [ -z "$force" ]; then
403 fatal "cannot find label \"$label\" in \"$conf_file\"" \
404 "(use -f to ignore this error)"
407 if [ "$labels" -gt "1" ]; then
408 fatal "more than one labels \"$label\" in \"$conf_file\""
411 if [ -z "$default_label" ]; then
412 verbose "no default label found, adding \"$label\""
414 local def="$(esc_sed_replacement "default $label")"
415 local anyl_regexp="$(get_regexp "label")"
418 $ { s/.*/&\n$def/; q }
419 /^[[:blank:]]*$/ { s/.*/$def\n&/; q }
420 /$(anyl_regexp)/ { s/.*/$def\n&/; q }
425 # Escape special sed characters in "$entry" and replace the old default
426 # entry with the new one
427 local esc_label="$(esc_sed_replacement "$label")"
428 LC_ALL=C sed -i -e "s/$regexp/\1$esc_label\3/" "$conf_file"
429 verbose "set the default boot kernel to \"$label"\"
433 # -----------------------------------------------------------------------------
439 Usage: $PROG [options] <subcommand> [options] <arguments>
441 This program changes the extlinux bootloader configuration. Supported
443 add - add an extlinux boot menu entry for a kernel
444 remove - remove an extlinux boot menu entry
445 default - get or set the default extlinux boot menu entry
447 Run "$PROG <subcommand>" to see subcommand-specific help.
450 -b, --bootdir path to the boot directory (default is "/boot")
451 --version show the program version and exit
452 -v, --verbose be verbose
453 -h, --help show this text and exit
459 IFS= printf "%s\n\n" "$PROG: error: $*" >&2
466 while [ -n "${1:-""}" ] && [ -z "${1##-*}" ]; do
470 # If there is no argument or it starts with "-", complain
471 if [ -z "${1:-""}" ] || [ -z "${1##-*}" ]; then
472 fatal "--bootdir requires an argument"
489 *) show_usage_fail "unrecognized option \"$1\""
497 if [ "$#" -eq 0 ]; then
503 subcommand="$1"; shift
505 case "$subcommand" in
511 remove_subcommand "$@"
515 default_subcommand "$@"
518 *) show_usage_fail "unrecognized subcommand \"$subcommand\""