Initial commit
authorArtem Bityutskiy <artem.bityutskiy@linux.intel.com>
Thu, 19 Dec 2013 12:02:11 +0000 (14:02 +0200)
committerArtem Bityutskiy <artem.bityutskiy@linux.intel.com>
Mon, 30 Dec 2013 14:23:18 +0000 (16:23 +0200)
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
12 files changed:
README [new file with mode: 0644]
efi-environment [new file with mode: 0644]
installerfw-sh-functions [new file with mode: 0644]
mbr-environment [new file with mode: 0644]
packaging/setup-ivi.changes [new file with mode: 0644]
packaging/setup-ivi.manifest [new file with mode: 0644]
packaging/setup-ivi.spec [new file with mode: 0644]
setup-extlinux-conf [new file with mode: 0755]
setup-gummiboot-conf [new file with mode: 0755]
setup-ivi-boot [new file with mode: 0755]
setup-ivi-bootloader-conf [new file with mode: 0755]
setup-ivi-sh-functions [new file with mode: 0644]

diff --git a/README b/README
new file mode 100644 (file)
index 0000000..b181983
--- /dev/null
+++ b/README
@@ -0,0 +1,19 @@
+The documentaion can be found here:
+https://wiki.tizen.org/wiki/IVI/artem-setup-ivi
+
+Some coding style notes for the shell scripts
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1. Do not use bashisms, install 'dash' and use it to verify that the
+   scripts are free of bashisms.
+
+2. Do not use all capitals for variables
+
+3. For shared files, prefix all symbols which are not supposed to be
+   used from outside with "__".
+
+4. Be consistent with my style. If you see that something makes no sense
+   or could be improved, change that globally.
+
+--
+Artem Bityutskiy
diff --git a/efi-environment b/efi-environment
new file mode 100644 (file)
index 0000000..fa9a614
--- /dev/null
@@ -0,0 +1,35 @@
+# This file can be used for testing setup-ivi-* scripts. This file corresponds
+# to an EFI boot image (boot partition has the EFS type GUID). Do the following
+# to start debugging
+#
+# mkdir /tmp/boot
+# touch /tmp/boot/vmlinuz-3.12-x86-ivi
+# mkdir -p /tmp/usr/lib/gummiboot
+# touch /tmp/usr/lib/gummiboot/gummibootia32.efi
+# mkdir /tmp/etc
+# echo 'PRETTY_NAME="My test OS"' > /tmp/etc/os-release
+
+export INSTALLERFW_MOUNT_PREFIX="/tmp"
+export INSTALLERFW_KERNEL_OPTS="rootwait rootfstype=ext4 quiet"
+export INSTALLERFW_PART0_ALIGN=1024
+export INSTALLERFW_PART0_BOOTFLAG=True
+export INSTALLERFW_PART0_FSOPTS=defaults,noatime
+export INSTALLERFW_PART0_FSTYPE=vfat
+export INSTALLERFW_PART0_LABEL=boot
+export INSTALLERFW_PART0_MOUNTPOINT=/boot
+export INSTALLERFW_PART0_PARTUUID=AC5A15ED-743A-42DC-88DD-97837EB802FD
+export INSTALLERFW_PART0_SIZE=64
+export INSTALLERFW_PART0_TYPE_ID=C12A7328-F81F-11D2-BA4B-00A0C93EC93B
+export INSTALLERFW_PART0_UUID=89A6-BDC8
+export INSTALLERFW_PART1_ALIGN=1024
+export INSTALLERFW_PART1_BOOTFLAG=False
+export INSTALLERFW_PART1_FSOPTS=defaults,noatime
+export INSTALLERFW_PART1_FSTYPE=ext4
+export INSTALLERFW_PART1_LABEL=platform
+export INSTALLERFW_PART1_MOUNTPOINT=/
+export INSTALLERFW_PART1_PARTUUID=7D723C77-2EB1-4AD6-B585-54D8E243CD87
+export INSTALLERFW_PART1_SIZE=3748
+export INSTALLERFW_PART1_TYPE_ID=
+export INSTALLERFW_PART1_UUID=a9bf2448-17b6-4113-99d7-061435a0a8a6
+export INSTALLERFW_PART_COUNT=2
+export INSTALLERFW_PTABLE_FORMAT=gpt
diff --git a/installerfw-sh-functions b/installerfw-sh-functions
new file mode 100644 (file)
index 0000000..d087c42
--- /dev/null
@@ -0,0 +1,179 @@
+# Copyright 2013 Intel Corporation
+# Author: Artem Bityutskiy
+# License: GPLv2
+
+# This file contains common functions for setup-ivi-* programs
+
+# Own name
+__PROG="${PROG:-installerfw-sh-functions}"
+
+# Installer framework variables are saved in this file
+__installerfw_file="/etc/installerfw-environment"
+# The OS release information file
+__osrelease_file="/etc/os-release"
+# EFI System Partition PARTUUID
+__esp_ptypeid="C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
+
+# Mount prefix is assumed to be "/" if it is not defined
+[ -n "${INSTALLERFW_MOUNT_PREFIX:-}" ] || export INSTALLERFW_MOUNT_PREFIX="/"
+
+__fatal()
+{
+       IFS= printf "%s\n" "$__PROG: error: $*" 1>&2
+       exit 1
+}
+
+__verbose()
+{
+       if [ -n "$verbose" ]; then
+               IFS= printf "%s\n" "$__PROG (verbose): $*" >&2
+       fi
+}
+
+# Verify that an environment variable is defined
+__verify_defined()
+{
+       local variable="$1"
+
+       printenv "$variable" > /dev/null ||
+               __fatal "cannot find required environment variable" \
+                       "\"$variable\""
+}
+
+# Add the INSTALLERFW_MOUNT_PREFIX prefix to a path. This does not really
+# require a separate function unless we want to be fancy and avoid double or
+# tripple "/" in the resulting path.
+installerfw_mnt_prefix()
+{
+       __verify_defined "INSTALLERFW_MOUNT_PREFIX"
+
+       local path="$INSTALLERFW_MOUNT_PREFIX/$1"
+
+       printf "%s" "$path" | LC_ALL=C sed -e 's/\/\+/\//g'
+}
+
+# Return full path to the file which contains the installer framework
+# environment variables.
+installerfw_get_env_file_name()
+{
+       printf "%s" "$(installerfw_mnt_prefix "$__installerfw_file")"
+}
+
+# Save installer framework environment variables. Note, all the variables can
+# be split on 2 classes - those which make sense only inside the particular
+# installer and those which make sense in the OS environment. We only save the
+# latter.
+installerfw_save_env()
+{
+       local file="$(installerfw_get_env_file_name)"
+       local opts="\
+-e '^INSTALLERFW_KERNEL_OPTS=' \
+-e '^INSTALLERFW_PART[[:digit:]]\+_ALIGN=' \
+-e '^INSTALLERFW_PART[[:digit:]]\+_BOOTFLAG=' \
+-e '^INSTALLERFW_PART[[:digit:]]\+_FSOPTS=' \
+-e '^INSTALLERFW_PART[[:digit:]]\+_FSTYPE=' \
+-e '^INSTALLERFW_PART[[:digit:]]\+_LABEL=' \
+-e '^INSTALLERFW_PART[[:digit:]]\+_MOUNTPOINT=' \
+-e '^INSTALLERFW_PART[[:digit:]]\+_PARTUUID=' \
+-e '^INSTALLERFW_PART[[:digit:]]\+_SIZE=' \
+-e '^INSTALLERFW_PART[[:digit:]]\+_TYPE_ID=' \
+-e '^INSTALLERFW_PART[[:digit:]]\+_UUID=' \
+-e '^INSTALLERFW_PART_COUNT=' \
+-e '^INSTALLERFW_PTABLE_FORMAT=' \
+"
+
+       local variables="$(printenv | eval "LC_ALL=C grep $opts")"
+
+       if [ "$(printf "%s" "$variables" | wc -l)" -eq "0" ]; then
+               __fatal "no installer framework environment variables" \
+                       "found, nothing to save"
+       fi
+
+       printf "%s" "$variables" | LC_ALL=C sed -n -e \
+               "s/\(^INSTALLERFW_[^=]\+\)=\(.*\)/\1=\"\2\"/p" > "$file"
+       __verbose "installerfw_save_env(): saved installer framework" \
+                 "environment in \"$file\""
+}
+
+# Restore installer framework environment variables.
+installerfw_restore_env()
+{
+       local file="$(installerfw_get_env_file_name)"
+
+       [ -f "$file" ] || \
+               __fatal "installerfw_restore_env(): can't restore the" \
+                       "installer framework environment: can't find" \
+                       "\"$file\""
+
+       while IFS= read -r line; do
+               eval "export $line"
+       done < "$file"
+
+       __verbose "installerfw_restore_env(): restored installer" \
+                 "framework environment from \"$file\""
+}
+
+# Check if the system is an EFI boot system by checking whether the boot
+# partition is a FAT 32 partition with the magic EFI type GUID.
+installerfw_is_efi_boot_system()
+{
+       installerfw_get_part_info "/boot" "TYPE_ID" "__ptypeid"
+
+       # Make sure the UUID uses capital letters
+       __ptypeid="$(printf "%s" "$__ptypeid" | tr "[:lower:]" "[:upper:]")"
+
+       __verify_defined "INSTALLERFW_PTABLE_FORMAT"
+
+       if [ "${INSTALLERFW_PTABLE_FORMAT:-}" = "gpt" ] && \
+          [ "$__ptypeid" = "$__esp_ptypeid" ]; then
+               __verbose "installerfw_is_efi_boot_system(): /boot is" \
+                         "the EFI system partition (type is" "\"$__ptypeid\")"
+               return 0
+       else
+               __verbose "installerfw_is_efi_boot_system(): no EFI" \
+                         "system partition found (type is" "\"$__ptypeid\")"
+               return 1
+       fi
+}
+
+# Get a piece of installer framework data for a partition. At the moment the
+# partition is specified by it's mount point (in $1), but this can be extended
+# to also accept the partition number, if needed.
+#
+# The second parameter ($2) is the a partial installer framework variable name
+# which should be returned. For example, "PARTUUID" would correspond to
+# "INSTALLERFW_PARTx_PARTUUID", and so on.
+#
+# The third parameter ($3) is name of the variable to store the result at. If
+# the requested installer framework variable is undefined or null, the shell
+# variable with name stored in $3 will have null value upon exit.
+installerfw_get_part_info()
+{
+       local __mntpoint="$1"; shift
+       local __var="$1"; shift
+       local __res_var="$1"; shift
+       local __pnum="0"
+
+       __verify_defined "INSTALLERFW_PART_COUNT"
+
+       while [ "$__pnum" -lt "$INSTALLERFW_PART_COUNT" ]; do
+               local __mp="INSTALLERFW_PART${__pnum}_MOUNTPOINT"
+               __verify_defined "$__mp"
+
+               __mp="$(eval printf "%s" "\"\$$__mp\"")"
+
+               [ "$__mp" != "$__mntpoint" ] || break
+
+               __pnum="$((__pnum+1))"
+       done
+
+       local installerfw_var="INSTALLERFW_PART${__pnum}_${__var}"
+
+       local __value=
+       if printenv "$installerfw_var" > /dev/null; then
+               __value="$(eval printf "%s" "\"\$$installerfw_var\"")"
+       fi
+
+       __verbose "installerfw_get_part_info(): $__res_var=$__value"
+       eval "$__res_var"="\"\$__value\""
+}
diff --git a/mbr-environment b/mbr-environment
new file mode 100644 (file)
index 0000000..139e5f8
--- /dev/null
@@ -0,0 +1,36 @@
+# This file can be used for testing setup-ivi-* scripts. This file corresponds
+# to an MBR boot image. Do the following to start debugging:
+#
+# mkdir /tmp/boot
+# touch /tmp/boot/vmlinux-3.12-x86-ivi
+# mkdir -p /tmp/usr/share/syslinux/
+# touch /tmp/usr/share/syslinux/gptmbr.bin
+# mkdir /tmp/etc
+# echo 'PRETTY_NAME="My test OS"' > /tmp/etc/os-release
+
+export INSTALLERFW_MOUNT_PREFIX="/tmp"
+export INSTALLERFW_KERNEL_OPTS="rootwait rootfstype=ext4 quiet"
+export INSTALLERFW_PART0_ALIGN=1024
+export INSTALLERFW_PART0_BOOTFLAG=True
+export INSTALLERFW_PART0_FSOPTS=defaults,noatime
+export INSTALLERFW_PART0_FSTYPE=ext4
+export INSTALLERFW_PART0_LABEL=boot
+export INSTALLERFW_PART0_MOUNTPOINT=/boot
+export INSTALLERFW_PART0_PARTUUID=FC86A97B-3E8F-46F7-82F8-995A397A0523
+export INSTALLERFW_PART0_SIZE=64
+export INSTALLERFW_PART0_DEVNODE_NOW=/dev/null
+export INSTALLERFW_PART0_DISK_DEVNODE_NOW=/dev/null
+unset INSTALLERFW_PART0_TYPE_ID
+export INSTALLERFW_PART0_UUID=A775922D-D42F-4114-9089-35332B6F896E
+export INSTALLERFW_PART1_ALIGN=1024
+export INSTALLERFW_PART1_BOOTFLAG=False
+export INSTALLERFW_PART1_FSOPTS=defaults,noatime
+export INSTALLERFW_PART1_FSTYPE=ext4
+export INSTALLERFW_PART1_LABEL=platform
+export INSTALLERFW_PART1_MOUNTPOINT=/
+export INSTALLERFW_PART1_PARTUUID=B3EA5880-0737-4B0B-8858-B8933A50E44D
+export INSTALLERFW_PART1_SIZE=3748
+unset INSTALLERFW_PART1_TYPE_ID
+export INSTALLERFW_PART1_UUID=50C898EF-DC27-4CA2-A48C-326A2DE8E018
+export INSTALLERFW_PART_COUNT=2
+export INSTALLERFW_PTABLE_FORMAT=mbr
diff --git a/packaging/setup-ivi.changes b/packaging/setup-ivi.changes
new file mode 100644 (file)
index 0000000..94f588c
--- /dev/null
@@ -0,0 +1,2 @@
+* Thu Dec 19 14:29:23 UTC 2013 Artem Bityutskiy <artem.bityutskiy@linux.intel.com> 1.0
+- Initial implementation
diff --git a/packaging/setup-ivi.manifest b/packaging/setup-ivi.manifest
new file mode 100644 (file)
index 0000000..017d22d
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+ <request>
+    <domain name="_"/>
+ </request>
+</manifest>
diff --git a/packaging/setup-ivi.spec b/packaging/setup-ivi.spec
new file mode 100644 (file)
index 0000000..9592a10
--- /dev/null
@@ -0,0 +1,84 @@
+Name:     setup-ivi
+Version:  1.0
+Release:  1
+License:  GPL-2.0
+Summary:  Various early setup programs
+Url:      http://www.tizen.org
+Group:    System/Configuration
+Source:   %{name}_%{version}.tar.gz
+Requires: /usr/bin/sed
+Requires: /usr/bin/grep
+Requires: /usr/bin/printf
+Requires: /usr/bin/printenv
+Requires: /usr/bin/sort
+Requires: virtual-setup-ivi-bootloader
+BuildArchitectures: noarch
+
+%package -n setup-gummiboot
+Summary:  Command-line tool for tweaking gummiboot configuration
+Provides: virtual-setup-ivi-bootloader
+Requires: %{name}
+Requires: gummiboot
+
+%package -n setup-extlinux
+Summary:  Command-line tool for tweaking extlinux configuration
+Provides: virtual-setup-ivi-bootloader
+Requires: %{name}
+Requires: syslinux-extlinux
+
+%description
+This package provides various early system setup programs
+
+%description -n setup-gummiboot
+This package provides a command-line tool for changing the gummiboot bootloader
+configuration files.
+
+%description -n setup-extlinux
+This package provides a command-line tool for changing the extlinux bootloader
+configuration file.
+
+###
+### PREP
+###
+%prep
+%setup -q -n %{name}-%{version}
+
+%build
+
+###
+### INSTALL
+###
+%install
+install -d %{buildroot}/%{_sbindir}
+install -d %{buildroot}/%{_prefix}/share/setup-ivi
+
+install -m755 setup-ivi-boot %{buildroot}/%{_sbindir}
+install -m755 setup-ivi-bootloader-conf %{buildroot}/%{_sbindir}
+install -m755 setup-gummiboot-conf %{buildroot}/%{_sbindir}
+install -m755 setup-extlinux-conf %{buildroot}/%{_sbindir}
+install -m644 setup-ivi-sh-functions %{buildroot}/%{_prefix}/share/setup-ivi
+install -m644 installerfw-sh-functions %{buildroot}/%{_prefix}/share/setup-ivi
+
+###
+### CLEAN
+###
+%clean
+rm -rf %{buildroot}
+
+###
+### FILES
+###
+%files
+%defattr(-,root,root)
+%{_sbindir}/setup-ivi-boot
+%{_sbindir}/setup-ivi-bootloader-conf
+%{_prefix}/share/setup-ivi/setup-ivi-sh-functions
+%{_prefix}/share/setup-ivi/installerfw-sh-functions
+
+%files -n setup-gummiboot
+%defattr(-,root,root)
+%{_sbindir}/setup-gummiboot-conf
+
+%files -n setup-extlinux
+%defattr(-,root,root)
+%{_sbindir}/setup-extlinux-conf
diff --git a/setup-extlinux-conf b/setup-extlinux-conf
new file mode 100755 (executable)
index 0000000..060d4fc
--- /dev/null
@@ -0,0 +1,517 @@
+#!/bin/sh -euf
+
+# Copyright 2013 Intel Corporation
+# Author: Artem Bityutskiy
+# License: GPLv2
+
+PROG="setup-extlinux-conf"
+VER="1.0"
+
+srcdir="$(readlink -ev -- ${0%/*})"
+PATH="/usr/share/setup-ivi:$srcdir:$PATH"
+
+. setup-ivi-sh-functions
+
+# This is a small trick which I use to make sure my scripts are portable -
+# check if 'dash' is present, and if yes - use it.
+if can_switch_to_dash; then
+       exec dash -euf "$srcdir/$PROG" "$@"
+       exit $?
+fi
+
+# Common preparations for all subcommands.
+prepare()
+{
+       verbose "Boot directory is $bootdir"
+       [ -d "$bootdir" ] || \
+               fatal "boot directory path \"$bootdir\" does not exist"
+
+       # The extlinux configuration directory
+       conf_dir="$bootdir/extlinux"
+       # The extlinux configuration file
+       conf_file="$conf_dir/extlinux.conf"
+}
+
+# Create the default extlinux configuration file.
+create_default_conf_file()
+{
+       verbose "creating the default configuration file \"$conf_file\""
+
+       mkdir -p $verbose "$conf_dir" >&2
+       cat > "$conf_file" <<-EOF
+       ui vesamenu.c32
+       prompt 0
+       timeout 1
+       default $1
+       EOF
+}
+
+# Check wheter the extlinux configuration file exist and if not:
+#   o create the default one if --force option was specified
+#   o fail if no --force option was specified
+check_and_create_default_conf_file()
+{
+       if [ -s "$conf_file" ]; then
+               return 0
+       fi
+
+       if [ -n "$force" ]; then
+               create_default_conf_file "$1"
+       else
+               fatal "cannot find the extlinux configuration file" \
+                     "(\"$conf_file\") (use -f to force creating the" \
+                     "default one)"
+       fi
+}
+
+# Get a regular expression for matching extlinux configuration file option "$1"
+get_regexp()
+{
+       local opt="$(esc_regexp "$1")"
+
+       opt="$(case_insensitive_regexp "$opt")"
+       printf "%s" "\(^[[:blank:]]*$opt[[:blank:]]\+\)\([^[:blank:]]\+\)\([[:blank:]]*$\)"
+}
+
+# Return a regular expression for matching label with name "$1".
+label_regexp()
+{
+       local opt="$(case_insensitive_regexp "label")"
+       local label="$(esc_regexp "$1")"
+
+       printf "%s" "\(^[[:blank:]]*$opt[[:blank:]]\+\)\($label\)\([[:blank:]]*$\)"
+}
+
+remove_label()
+{
+       local label="$1"
+       local l_regexp="$(label_regexp "$label")"
+       local anyl_regexp="$(get_regexp "label")"
+
+       LC_ALL=C sed -i -n -e "/$l_regexp/ { # mathes our label line
+                       :l n;                # get the next line
+                       /$l_regexp/bl        # same label again, keep skipping
+                       /$anyl_regexp/!bl    # a different label, stop skipping
+                   }
+                   /$l_regexp/!p            # print all other lines
+                   " "$conf_file"
+
+       remove_trailing_empty_lines "$conf_file"
+}
+
+#
+# -----------------------------------------------------------------------------
+# The "add" subcommand
+# -----------------------------------------------------------------------------
+#
+
+show_add_usage()
+{
+       cat <<-EOF
+Usage: $PROG add [options] <label> <title> <kernel> <options>
+
+Add a new extlinux boot menu entry. The mandatory arguments are:
+
+    <label>   - a unique name of the boot menu entry to add, the entry will be
+                further refurred by the label
+    <title>   - the boot menu entry title
+    <kernel>  - name of the kernel binary corresponding to the entry
+    <options> - kernel boot options
+
+Options:
+  -f, --force  if <label> already exists - re-create it, if
+               <bootdir>/extlinux/extlinux.conf does not exist - create it, if
+              <bootdir>/<kernel> does not exist - do not fail
+  -h, --help   show this text and exit
+EOF
+}
+
+show_add_usage_fail()
+{
+       IFS= printf "%s\n\n" "$PROG: error: $*" >&2
+       show_add_usage >&2
+       exit 1
+}
+
+add_subcommand()
+{
+       if [ "$#" -eq 0  ]; then
+               show_add_usage
+               exit 0
+       fi
+
+       local tmp
+       tmp=`getopt -n $PROG -o f,h --long force,help -- "$@"` ||
+               show_add_usage_fail "cannot parse command-line options"
+       eval set -- "$tmp"
+
+       local force=
+       while true; do
+               case "$1" in
+               -f|--force)
+                       force="-f"
+                       ;;
+               -h|--help)
+                       show_add_usage
+                       exit 0
+                       ;;
+               --) shift; break
+                       ;;
+               *) show_add_usage_fail "unrecognized option \"$1\""
+                       ;;
+               esac
+               shift
+       done
+
+       if [ "$#" -lt 4 ]; then
+               show_add_usage_fail "too little arguments"
+       fi
+       if [ "$#" -gt 4 ]; then
+               show_add_usage_fail "too many arguments: \"$1\""
+       fi
+
+       prepare
+
+       local label="$1"; shift
+       local title="$1"; shift
+       local kernel="$1"; shift
+       local options="$1"; shift
+       local kernel_path="$bootdir/$kernel"
+
+       verbose "label is \"$label\""
+       verbose "title is \"$title\""
+       verbose "kernel is \"$kernel\""
+       verbose "options are \"$options\""
+
+       if ! [ -f "$kernel_path" ] && [ -z "$force" ]; then
+               fatal "cannot find kernel \"$kernel_path\"" \
+                     "(use -f to ignore this error)"
+       fi
+
+       # Make sure the extlinux configuration file exists
+       check_and_create_default_conf_file "$label"
+
+       if LC_ALL=C grep -q -e "$(label_regexp "$label")" "$conf_file" && \
+          [ -z "$force" ]; then
+               fatal "extlinux boot menu label \"$label\" already exists" \
+                     "(use -f to force re-creating it)"
+       fi
+
+       # Find out the kernel version from its name
+       local kernel_version="$(printf "%s" "$kernel" | LC_ALL=C \
+                  sed -e 's/[^[:digit:]]\+-\([[:digit:]]\+.*\)/\1/')"
+       [ -n "$kernel_version" ] || \
+               fatal "cannot fetch kernel version from \"$kernel\""
+
+       # Remove the label if it exists, since we are going to add a new one
+       remove_label "$label"
+
+       local block="label $label
+       menu label $title ($kernel_version)
+       linux /$kernel
+       append $options"
+
+       printf "\n%s\n" "$block" >> "$conf_file"
+
+       if [ -n "$verbose" ]; then
+               verbose "Added the following to \"$conf_file\":"
+               printf "%s\n" "$block" >&2
+       fi
+}
+
+#
+# -----------------------------------------------------------------------------
+# The "remove" subcommand
+# -----------------------------------------------------------------------------
+#
+
+show_remove_usage()
+{
+       cat <<-EOF
+Usage: $PROG remove [options] <label>
+
+Delete extlinux boot entry which has label <label>.
+
+Options:
+  -f, --force  do not fail if the entry doesn't exist
+  -h, --help   show this text and exit
+EOF
+}
+
+show_remove_usage_fail()
+{
+       IFS= printf "%s\n\n" "$PROG: error: $*" >&2
+       show_remove_usage >&2
+       exit 1
+}
+
+remove_subcommand()
+{
+       if [ "$#" -eq 0  ]; then
+               show_remove_usage
+               exit 0
+       fi
+
+       local tmp
+       tmp=`getopt -n $PROG -o f,h --long force,help -- "$@"` ||
+               show_remove_usage_fail "cannot parse command-line options"
+       eval set -- "$tmp"
+
+       local force=
+       while true; do
+               case "$1" in
+               -f|--force)
+                       force="-f"
+                       ;;
+               -h|--help)
+                       show_remove_usage
+                       exit 0
+                       ;;
+               --) shift; break
+                       ;;
+               *) show_remove_usage_fail "unrecognized option \"$1\""
+                       ;;
+               esac
+               shift
+       done
+
+       if [ "$#" -lt 1 ]; then
+               show_remove_usage_fail "too little arguments"
+       fi
+       if [ "$#" -gt 1 ]; then
+               show_remove_usage_fail "too many arguments: \"$1\""
+       fi
+
+       prepare
+
+       local label="$1"
+
+       if ! LC_ALL=C grep -q -e "$(label_regexp "$label")" "$conf_file" && \
+          [ -z "$force" ]; then
+               fatal "cannot find label \"$label\" in \"$conf_file\"" \
+                     "(use -f to ignore this error)"
+       fi
+
+       remove_label "$label"
+       verbose "removed $label"
+}
+
+#
+# -----------------------------------------------------------------------------
+# The "default" subcommand
+# -----------------------------------------------------------------------------
+#
+
+# Get the kernel binary name by its extlinux.conf label name
+get_kernel_by_label()
+{
+       local label="$1"
+       local l_regexp="$(label_regexp "$label")"  # Regexp for our label
+       local anyl_regexp="$(get_regexp "label")"  # Regexp for any label
+       local linux_regexp="$(get_regexp "linux")"
+       local kernel_regexp="$(get_regexp "kernel")"
+       local result
+
+       [ -z "$label" ] && return 0
+
+       result="$(LC_ALL=C sed -n -e "/$l_regexp/ {
+               :l n;
+               /$linux_regexp/ { s/$linux_regexp/\2/p }
+               /$kernel_regexp/ { s/$kernel_regexp/\2/p }
+               /$anyl_regexp/!bl # Loop till the next label
+       }" "$conf_file")"
+
+       printf "%s" "${result##*/}"
+}
+
+show_default_usage()
+{
+       cat <<-EOF
+Usage: $PROG default [options] <label>
+
+Set the default boot kernel to be the kernel which is marked with label <label>
+the extlinux configuration file. If <label> is omited, this command prints the
+currently default entry name.
+
+Options:
+  -f, --force  <bootdir>/extlinux/extlinux.conf does not exist - create it, if
+               <label> does not exist - do not fail
+  -h, --help   show this text and exit
+EOF
+}
+
+show_default_usage_fail()
+{
+       IFS= printf "%s\n\n" "$PROG: error: $*" >&2
+       show_default_usage >&2
+       exit 1
+}
+
+default_subcommand()
+{
+       local tmp
+       tmp=`getopt -n $PROG -o f,h --long force,help -- "$@"` ||
+               show_default_usage_fail "cannot parse command-line options"
+       eval set -- "$tmp"
+
+       local force=
+       while true; do
+               case "$1" in
+               -f|--force)
+                       force="-f"
+                       ;;
+               -h|--help)
+                       show_default_usage
+                       exit 0
+                       ;;
+               --) shift; break
+                       ;;
+               *) show_default_usage_fail "unrecognized option \"$1\""
+                       ;;
+               esac
+               shift
+       done
+
+       if [ "$#" -gt 1 ]; then
+               show_default_usage_fail "too many arguments: \"$1\""
+       fi
+
+       prepare
+
+       local label="${1:-}";
+
+       # Make sure the extlinux configuration file exists
+       check_and_create_default_conf_file "$label"
+
+       # Find the current default label
+       local regexp="$(get_regexp "default")"
+       local default_label="$(LC_ALL=C sed -n -e "s/$regexp/\2/p" "$conf_file")"
+
+       if [ -z "$label" ]; then
+               printf "%s\n" "label: $default_label"
+               printf "%s\n" "kernel: $(get_kernel_by_label "$default_label")"
+               return 0
+       fi
+
+       local l_regexp="$(label_regexp "$label")"
+       local labels="$(LC_ALL=C grep -e "$l_regexp" "$conf_file" | wc -l)"
+
+       if [ "$labels" -eq "0" ] && [ -z "$force" ]; then
+               fatal "cannot find label \"$label\" in \"$conf_file\"" \
+                     "(use -f to ignore this error)"
+       fi
+
+       if [ "$labels" -gt "1" ]; then
+               fatal "more than one labels \"$label\" in \"$conf_file\""
+       fi
+
+       if [ -z "$default_label" ]; then
+               verbose "no default label found, adding \"$label\""
+
+               local def="$(esc_sed_replacement "default $label")"
+               local anyl_regexp="$(get_regexp "label")"
+
+               LC_ALL=C sed -i -e "
+                       $                 { s/.*/&\n$def/; q }
+                       /^[[:blank:]]*$/  { s/.*/$def\n&/; q }
+                       /$(anyl_regexp)/  { s/.*/$def\n&/; q }
+                       " "$conf_file"
+               return 0
+       fi
+
+       # Escape special sed characters in "$entry" and replace the old default
+       # entry with the new one
+       local esc_label="$(esc_sed_replacement "$label")"
+       LC_ALL=C sed -i -e "s/$regexp/\1$esc_label\3/" "$conf_file"
+       verbose "set the default boot kernel to \"$label"\"
+}
+
+#
+# -----------------------------------------------------------------------------
+#
+
+show_usage()
+{
+       cat <<-EOF
+Usage: $PROG [options] <subcommand> [options] <arguments>
+
+This program changes the extlinux bootloader configuration. Supported
+subcommands are:
+   add     - add an extlinux boot menu entry for a kernel
+   remove  - remove an extlinux boot menu entry
+   default - get or set the default extlinux boot menu entry
+
+Run "$PROG <subcommand>" to see subcommand-specific help.
+
+Options:
+  -b, --bootdir  path to the boot directory (default is "/boot")
+  --version      show the program version and exit
+  -v, --verbose  be verbose
+  -h, --help     show this text and exit
+EOF
+}
+
+show_usage_fail()
+{
+       IFS= printf "%s\n\n" "$PROG: error: $*" >&2
+       show_usage >&2
+       exit 1
+}
+
+bootdir="/boot"
+verbose=
+while [ -n "${1:-""}" ] && [ -z "${1##-*}" ]; do
+       case "$1" in
+       -b|--bootdir)
+               shift
+               # If there is no argument or it starts with "-", complain
+               if [ -z "${1:-""}" ] || [ -z "${1##-*}" ]; then
+                       fatal "--bootdir requires an argument"
+               fi
+               bootdir="$1"
+               ;;
+       --version)
+               printf "%s\n" "$VER"
+               exit 0
+               ;;
+       -v|--verbose)
+               verbose="-v"
+               ;;
+       -h|--help)
+               show_usage
+               exit 0
+               ;;
+       --) shift; break
+               ;;
+       *) show_usage_fail "unrecognized option \"$1\""
+               ;;
+       esac
+       shift
+done
+
+# Parse subcommands
+
+if [ "$#" -eq 0 ]; then
+       show_usage
+       exit 0
+fi
+
+
+subcommand="$1"; shift
+
+case "$subcommand" in
+add)
+       add_subcommand "$@"
+       break
+       ;;
+remove)
+       remove_subcommand "$@"
+       break
+       ;;
+default)
+       default_subcommand "$@"
+       break
+       ;;
+*) show_usage_fail "unrecognized subcommand \"$subcommand\""
+       ;;
+esac
diff --git a/setup-gummiboot-conf b/setup-gummiboot-conf
new file mode 100755 (executable)
index 0000000..dbd4dfc
--- /dev/null
@@ -0,0 +1,483 @@
+#!/bin/sh -euf
+
+# Copyright 2013 Intel Corporation
+# Author: Artem Bityutskiy
+# License: GPLv2
+
+PROG="setup-gummiboot-conf"
+VER="1.0"
+
+srcdir="$(readlink -ev -- ${0%/*})"
+PATH="/usr/share/setup-ivi:$srcdir:$PATH"
+
+. setup-ivi-sh-functions
+
+# This is a small trick which I use to make sure my scripts are portable -
+# check if 'dash' is present, and if yes - use it.
+if can_switch_to_dash; then
+       exec dash -euf "$srcdir/$PROG" "$@"
+       exit $?
+fi
+
+# Common preparations for all subcommands.
+prepare()
+{
+       verbose "Boot directory is $bootdir"
+       [ -d "$bootdir" ] || \
+               fatal "boot directory path \"$bootdir\" does not exist"
+
+       # The gummiboot configuration directory
+       conf_dir="$bootdir/loader"
+       # The gummiboot configuration file
+       conf_file="$conf_dir/loader.conf"
+       # The gummiboot kernel entries directory
+       entries_dir="$bootdir/loader/entries"
+}
+
+# Get a regular expression for matching gummiboot configuration file option
+# "$1"
+get_regexp()
+{
+       local opt="$(esc_regexp "$1")"
+
+       opt="$(case_insensitive_regexp "$opt")"
+       printf "%s" "\(^[[:blank:]]*$opt[[:blank:]]\+\)\([^[:blank:]]\+\)\([[:blank:]]*$\)"
+}
+
+# Create the default gummiboot configuration file.
+create_default_conf_file()
+{
+       verbose "creating the default configuration file \"$conf_file\""
+
+       mkdir -p $verbose "$conf_dir" >&2
+       cat > "$conf_file" <<-EOF
+       timeout 0
+       default $1
+       EOF
+}
+
+# Check wheter the gummiboot configuration file exist, and if not:
+#   o create the default one if --force option was specified
+#   o fail if no --force option was specified
+check_and_create_default_conf_file()
+{
+       if [ -s "$conf_file" ]; then
+               return 0
+       fi
+
+       if [ -n "$force" ]; then
+               create_default_conf_file "$1"
+       else
+               fatal "cannot find the gummiboot configuration file" \
+                     "(\"$conf_file\") (use -f to create the default" \
+                     "one)"
+       fi
+}
+
+#
+# -----------------------------------------------------------------------------
+# The "add" subcommand
+# -----------------------------------------------------------------------------
+#
+
+show_add_usage()
+{
+       cat <<-EOF
+Usage: $PROG add [options] <entry> <title> <kernel> <options>
+
+Add a new gummiboot entry. The mandatory arguments are:
+
+    <entry>   - name of the gummiboot entry to add
+                (<bootdir>/loader/entries/<entry>.conf)
+    <title>   - the title of the entry
+    <kernel>  - name of the kernel binary to add the entry for
+                (<bootdir>/<kernel>)
+    <options> - kernel boot options
+
+Options:
+  -f, --force  if the entry already exists - re-write it, if
+              <bootdir>/loader/loader.conf does not exist - create one,
+              if <bootdir>/<kernel> does not exist - do not fail
+  -h, --help   show this text and exit
+EOF
+}
+
+show_add_usage_fail()
+{
+       IFS= printf "%s\n\n" "$PROG: error: $*" >&2
+       show_add_usage >&2
+       exit 1
+}
+
+add_subcommand()
+{
+       if [ "$#" -eq 0  ]; then
+               show_add_usage
+               exit 0
+       fi
+
+       local tmp
+       tmp=`getopt -n $PROG -o f,h --long force,help -- "$@"` ||
+               show_add_usage_fail "cannot parse command-line options"
+       eval set -- "$tmp"
+
+       local force=
+       while true; do
+               case "$1" in
+               -f|--force)
+                       force="-f"
+                       ;;
+               -h|--help)
+                       show_add_usage
+                       exit 0
+                       ;;
+               --) shift; break
+                       ;;
+               *) show_add_usage_fail "unrecognized option \"$1\""
+                       ;;
+               esac
+               shift
+       done
+
+       if [ "$#" -lt 4 ]; then
+               show_add_usage_fail "too little arguments"
+       fi
+       if [ "$#" -gt 4 ]; then
+               show_add_usage_fail "too many arguments: \"$1\""
+       fi
+
+       prepare
+
+       local entry="$1"; shift
+       local title="$1"; shift
+       local kernel="$1"; shift
+       local options="$1"; shift
+       local kernel_path="$bootdir/$kernel"
+       local entry_path="$entries_dir/${entry}.conf"
+
+       verbose "entry is \"$entry\""
+       verbose "title is \"$title\""
+       verbose "kernel is \"$kernel\""
+       verbose "options are \"$options\""
+
+       if [ -f "$entry_path" ] && [ -z "$force" ]; then
+               fatal "gummiboot entry \"$entry_path\" already exists" \
+                     "(use -f to force re-creating it)"
+       fi
+
+       if ! [ -f "$kernel_path" ] && [ -z "$force" ]; then
+               fatal "cannot find kernel \"$kernel_path\"" \
+                     "(use -f to ignore this error)"
+       fi
+
+       # Make sure the gummiboot configuration file exists
+       check_and_create_default_conf_file "$entry"
+
+       # Find out the kernel version from its name
+       local kernel_version="$(printf "%s" "$kernel" | LC_ALL=C \
+                  sed -e 's/[^[:digit:]]\+-\([[:digit:]]\+.*\)/\1/')"
+       [ -n "$kernel_version" ] || \
+               fatal "cannot fetch kernel version from \"$kernel\""
+
+       # Create the new entry
+       mkdir -p $verbose "$entries_dir" >&2
+       cat > "$entry_path" <<-EOF
+       title $title
+       version $kernel_version
+       efi /$kernel
+       options $options
+       EOF
+
+       if [ -n "$verbose" ]; then
+               verbose "contents of \"$entry_path\":"
+               cat "$entry_path" >&2
+       fi
+}
+
+#
+# -----------------------------------------------------------------------------
+# The "remove" subcommand
+# -----------------------------------------------------------------------------
+#
+
+show_remove_usage()
+{
+       cat <<-EOF
+Usage: $PROG remove [options] <entry>
+
+Delete gummiboot entry <entry> (<bootdir>/loader/entries/<entry>.conf).
+
+Options:
+  -f, --force  do not fail if the entry doesn't exist
+  -h, --help   show this text and exit
+EOF
+}
+
+show_remove_usage_fail()
+{
+       IFS= printf "%s\n\n" "$PROG: error: $*" >&2
+       show_remove_usage >&2
+       exit 1
+}
+
+remove_subcommand()
+{
+       if [ "$#" -eq 0  ]; then
+               show_remove_usage
+               exit 0
+       fi
+
+       local tmp
+       tmp=`getopt -n $PROG -o f,h --long force,help -- "$@"` ||
+               show_remove_usage_fail "cannot parse command-line options"
+       eval set -- "$tmp"
+
+       local force=
+       while true; do
+               case "$1" in
+               -f|--force)
+                       force="-f"
+                       ;;
+               -h|--help)
+                       show_remove_usage
+                       exit 0
+                       ;;
+               --) shift; break
+                       ;;
+               *) show_remove_usage_fail "unrecognized option \"$1\""
+                       ;;
+               esac
+               shift
+       done
+
+       if [ "$#" -lt 1 ]; then
+               show_remove_usage_fail "too little arguments"
+       fi
+       if [ "$#" -gt 1 ]; then
+               show_remove_usage_fail "too many arguments: \"$1\""
+       fi
+
+       prepare
+
+       local entry="$1"
+       local entry_path="$entries_dir/${entry}.conf"
+
+       if ! [ -f "$entry_path" ] && [ -z "$force" ]; then
+               fatal "gummiboot entry \"$entry_path\" doesn't exist" \
+                     "(use -f to ignore this error)"
+       fi
+
+       rm -rf $verbose "$entry_path" >&2
+       verbose "removed $entry_path"
+}
+
+#
+# -----------------------------------------------------------------------------
+# The "default" subcommand
+# -----------------------------------------------------------------------------
+#
+
+# Get the kernel name from a gummiboot entry
+get_kernel_from_entry()
+{
+       local result=
+       local entry="$entries_dir/$1.conf"
+
+       if [ -f "$entry" ]; then
+               local regexp="$(get_regexp "efi")"
+               local result="$(LC_ALL=C sed -n -e "s/$regexp/\2/p" "$entry")"
+
+               if [ -z "$result" ]; then
+                       regexp="$(get_regexp "linux")"
+                       result="$(LC_ALL=C sed -n -e "s/$regexp/\2/p" "$entry")"
+
+                       [ -n "$result" ] || return 0
+               fi
+       fi
+
+       printf "%s" "${result##*/}"
+}
+
+show_default_usage()
+{
+       cat <<-EOF
+Usage: $PROG default [options] <entry>
+
+Set the default boot kernel to <entry>, which is the gummiboot entry name to
+become the default (without the ".conf" suffix, like in
+<bootdir>/loader/entries/<entry>.conf). If <entry> is omited, this command
+prints the currently default entry name.
+
+Options:
+  -f, --force  if <bootdir>/loader/loader.conf does not exist - create the
+               default one, if <bootdir>/loader/entries/<entry>.conf does not
+              exist - do not fail
+  -h, --help   show this text and exit
+EOF
+}
+
+show_default_usage_fail()
+{
+       IFS= printf "%s\n\n" "$PROG: error: $*" >&2
+       show_default_usage >&2
+       exit 1
+}
+
+default_subcommand()
+{
+       local tmp
+       tmp=`getopt -n $PROG -o f,h --long force,help -- "$@"` ||
+               show_default_usage_fail "cannot parse command-line options"
+       eval set -- "$tmp"
+
+       local force=
+       while true; do
+               case "$1" in
+               -f|--force)
+                       force="-f"
+                       ;;
+               -h|--help)
+                       show_default_usage
+                       exit 0
+                       ;;
+               --) shift; break
+                       ;;
+               *) show_default_usage_fail "unrecognized option \"$1\""
+                       ;;
+               esac
+               shift
+       done
+
+       if [ "$#" -gt 1 ]; then
+               show_default_usage_fail "too many arguments: \"$1\""
+       fi
+
+       prepare
+
+       local entry="${1:-}";
+
+       # Make sure the gummiboot configuration file exists
+       check_and_create_default_conf_file "$entry"
+
+       # Find the current default entry
+       local regexp="$(get_regexp "default")"
+       local default_entry="$(LC_ALL=C sed -n -e "s/$regexp/\2/p" "$conf_file")"
+
+       if [ -z "$entry" ]; then
+               printf "%s\n" "entry: $default_entry"
+               printf "%s\n" "kernel: $(get_kernel_from_entry "$default_entry")"
+               return 0
+       fi
+
+       local entry_path="$entries_dir/${entry}.conf"
+       if ! [ -f "$entry_path" ] && [ -z "$force" ]; then
+               fatal "cannot find the gummiboot entry \"$entry_path\"" \
+                     "(use -f to ignore this error)"
+       fi
+
+       if [ -z "$default_entry" ]; then
+               verbose "no default entry found, adding \"$entry\""
+               printf "%s" "default $entry" >> "$conf_file"
+               return 0
+       fi
+
+       [ "$(printf "%s\n" "$default_entry" | wc -l)" -eq "1" ] || \
+               fatal "more than one default entry in \"$conf_file\""
+
+       # Escape special sed characters in "$entry" and replace the old default
+       # entry with the new one
+       local entry_esc="$(esc_sed_replacement "$entry")"
+       LC_ALL=C sed -i -e "s/$regexp/\1$entry_esc\3/" "$conf_file"
+
+       verbose "set the default boot kernel to \"$entry"\"
+}
+
+#
+# -----------------------------------------------------------------------------
+#
+
+show_usage()
+{
+       cat <<-EOF
+Usage: $PROG [options] <subcommand> [options] <arguments>
+
+This program changes the gummiboot bootloader configuration. Supported
+subcommands are:
+   add     - add a gummiboot entry for a kernel
+   remove  - remove a gummiboot entry
+   default - get or set the default gummiboot entry
+
+Run "$PROG <subcommand>" to see subcommand-specific help.
+
+Options:
+  -b, --bootdir  path to the boot directory (default is "/boot")
+  --version      show the program version and exit
+  -v, --verbose  be verbose
+  -h, --help     show this text and exit
+EOF
+}
+
+show_usage_fail()
+{
+       IFS= printf "%s\n\n" "$PROG: error: $*" >&2
+       show_usage >&2
+       exit 1
+}
+
+bootdir="/boot"
+verbose=
+while [ -n "${1:-""}" ] && [ -z "${1##-*}" ]; do
+       case "$1" in
+       -b|--bootdir)
+               shift
+               # If there is no argument or it starts with "-", complain
+               if [ -z "${1:-""}" ] || [ -z "${1##-*}" ]; then
+                       fatal "--bootdir requires an argument"
+               fi
+               bootdir="$1"
+               ;;
+       --version)
+               printf "%s\n" "$VER"
+               exit 0
+               ;;
+       -v|--verbose)
+               verbose="-v"
+               ;;
+       -h|--help)
+               show_usage
+               exit 0
+               ;;
+       --) shift; break
+               ;;
+       *) show_usage_fail "unrecognized option \"$1\""
+               ;;
+       esac
+       shift
+done
+
+# Parse subcommands
+
+if [ "$#" -eq 0 ]; then
+       show_usage
+       exit 0
+fi
+
+
+subcommand="$1"; shift
+
+case "$subcommand" in
+add)
+       add_subcommand "$@"
+       break
+       ;;
+remove)
+       remove_subcommand "$@"
+       break
+       ;;
+default)
+       default_subcommand "$@"
+       break
+       ;;
+*) show_usage_fail "unrecognized subcommand \"$subcommand\""
+       ;;
+esac
diff --git a/setup-ivi-boot b/setup-ivi-boot
new file mode 100755 (executable)
index 0000000..fd8ce47
--- /dev/null
@@ -0,0 +1,174 @@
+#!/bin/sh -euf
+
+# Copyright 2013 Intel Corporation
+# Author: Artem Bityutskiy
+# License: GPLv2
+
+PROG="setup-ivi-boot"
+VER="1.0"
+
+srcdir="$(readlink -ev -- ${0%/*})"
+PATH="/usr/share/setup-ivi:$srcdir:$PATH"
+
+. setup-ivi-sh-functions
+. installerfw-sh-functions
+
+# This is a small trick which I use to make sure my scripts are portable -
+# check if 'dash' is present, and if yes - use it.
+if can_switch_to_dash; then
+       exec dash -euf "$srcdir/$PROG" "$@"
+       exit $?
+fi
+
+install_gummiboot()
+{
+       verbose "installing gummiboot to $bootdir"
+
+       local installdir="$bootdir/EFI/boot"
+       local gummiboot_path="$(installerfw_mnt_prefix "/usr/lib/gummiboot")"
+
+       # Make sure gummiboot is installed in the system
+       if ! ([ -f $gummiboot_path/gummibootia32.efi ] || \
+             [ -f $gummiboot_path/gummibootx64.efi ]); then
+               fatal "\"$gummiboot_path/gummiboot*.efi\" files not found!"
+       fi
+
+       # Install gummiboot
+       mkdir -p $verbose "$installdir" >&2
+       [ -f "$gummiboot_path/gummibootia32.efi" ] && \
+               cp $verbose "$gummiboot_path/gummibootia32.efi" \
+                           "$installdir/bootia32.efi" >&2
+       [ -f "$gummiboot_path/gummibootx64.efi" ] && \
+               cp $verbose "$gummiboot_path/gummibootx64.efi" \
+                           "$installdir/bootx64.efi"
+
+       verbose "installed gummiboot to $bootdir"
+}
+
+install_extlinux()
+{
+       verbose "installing extlinux to $bootdir"
+
+       local installdir="$bootdir/extlinux"
+       local extlinux="extlinux"
+
+       # Check if extlinux is available
+        if ! command -v "extlinux" >/dev/null 2>&1; then
+               extlinux="$(installerfw_mnt_prefix "/sbin/extlinux")"
+               [ -f "$extlinux" ] ||
+                       fatal "cannot find \"$extlinux\""
+       fi
+
+       # Get device node name for the boot partition
+       local boot_devnode
+       installerfw_get_part_info "/boot" "DEVNODE_NOW" "boot_devnode"
+       [ -n "$boot_devnode" ] || \
+               fatal "cannot find device node of the boot disk, probably" \
+                     "INSTALLERFW_PARTx_DEVNODE_NOW environment" \
+                     "variable is not defined"
+
+       # Install extlinux
+       mkdir -p $verbose "$installdir" >&2
+       "$extlinux" --device "$boot_devnode" -i "$installdir" || \
+               fatal "cannot install extlinux to \"$installdir\"" \
+                     "(requires extlinux version 5 or greater)"
+
+
+       # Get device node name for the boot disk
+       local mbr_devnode
+       installerfw_get_part_info "/boot" "DISK_DEVNODE_NOW" "mbr_devnode"
+       [ -n "$mbr_devnode" ] || \
+               fatal "cannot find device node of the boot disk, probably" \
+                     "INSTALLERFW_PARTx_DISK_DEVNODE_NOW environment" \
+                     "variable is not defined"
+
+       # Install the MBR part of extlinux
+       local mbr_bin="$(installerfw_mnt_prefix "/usr/share/syslinux/gptmbr.bin")"
+       dd if="$mbr_bin" of="$mbr_devnode" count=1 || \
+               fatal "cannot install MBR: dd if=$mbr_bin of=$mbr_devnode"
+
+       verbose "installed extlinux to $bootdir"
+}
+
+show_usage()
+{
+       cat <<-EOF
+Usage: $PROG [options]
+
+Install the EFI bootloader (gummiboot) and create the initial configuration
+for all the currently installed kernels. This program depends on various
+"installer framework" variables.
+
+Options:
+  -v, --verbose  be verbose
+  --version      show the program version and exit
+  -h, --help     show this text and exit
+EOF
+}
+
+show_usage_fail()
+{
+       IFS= printf "%s\n\n" "$PROG: error: $*" >&2
+       show_usage >&2
+       exit 1
+}
+
+# Parse the options
+tmp=`getopt -n $PROG -o v,h --long verbose,version,help -- "$@"` ||
+       show_usage_fail "cannot parse command-line options"
+eval set -- "$tmp"
+
+verbose=
+while true; do
+       case "$1" in
+       -v|--verbose)
+               verbose="-v"
+               ;;
+       --version)
+               printf "%s\n" "$VER"
+               exit 0
+               ;;
+       -h|--help)
+               show_usage
+               exit 0
+               ;;
+       --) shift; break
+               ;;
+       *) show_usage_fail "unrecognized option \"$1\""
+               ;;
+       esac
+       shift
+done
+
+bootdir="$(installerfw_mnt_prefix "/boot")"
+
+# Save the installer framework variables
+installerfw_file="$(installerfw_get_env_file_name)"
+if [ -f "$installerfw_file" ]; then
+       installerfw_restore_env
+else
+       installerfw_save_env
+fi
+
+# Get OS name
+get_os_name "os_name"
+
+if installerfw_is_efi_boot_system; then
+       install_gummiboot
+else
+       install_extlinux
+fi
+
+# Create bootloader entries for each kernel
+kernels="$(ls -1 "$bootdir" | LC_ALL=C grep "^vmlinuz-" | sort -r)"
+
+[ -n "$kernels" ] || \
+       fatal "no kernels (vmlinuz-*) found in \"$bootdir\""
+
+printf "%s\n" "$kernels" | while IFS= read -r kernel; do
+       setup-ivi-bootloader-conf $verbose add --force "$kernel"
+done
+
+# Set the default kernel to the kernel with highest version
+newest_kernel="$(get_newest_kernel "$bootdir")"
+setup-ivi-bootloader-conf $verbose default "$newest_kernel"
diff --git a/setup-ivi-bootloader-conf b/setup-ivi-bootloader-conf
new file mode 100755 (executable)
index 0000000..ac59db2
--- /dev/null
@@ -0,0 +1,415 @@
+#!/bin/sh -euf
+
+# Copyright 2013 Intel Corporation
+# Author: Artem Bityutskiy
+# License: GPLv2
+
+PROG="setup-ivi-bootloader-conf"
+VER="1.0"
+
+srcdir="$(readlink -ev -- ${0%/*})"
+PATH="/usr/share/setup-ivi:$srcdir:$PATH"
+
+. setup-ivi-sh-functions
+. installerfw-sh-functions
+
+# This is a small trick which I use to make sure my scripts are portable -
+# check if 'dash' is present, and if yes - use it.
+if can_switch_to_dash; then
+       exec dash -euf "$srcdir/$PROG" "$@"
+       exit $?
+fi
+
+# Preparation stuff common for all subcommands
+prepare()
+{
+       # Get the installer framework environment
+       installerfw_restore_env
+
+       bootdir="$(installerfw_mnt_prefix "/boot")"
+
+       if installerfw_is_efi_boot_system; then
+               boot="gummiboot"
+       else
+               boot="extlinux"
+       fi
+}
+
+#
+# -----------------------------------------------------------------------------
+# The "add" subcommand
+# -----------------------------------------------------------------------------
+#
+
+show_add_usage()
+{
+       cat <<-EOF
+Usage: $PROG add [options] <kernel>
+
+Add bootloader entries for kernel <kernel>.
+
+Options:
+  -f, --force  if bootloader entries for <kernel> already exist in bootloader's
+               config file(s) - re-write them, if <kernel> does not exist - do
+              not fail
+  -h, --help   show this text and exit
+EOF
+}
+
+show_add_usage_fail()
+{
+       IFS= printf "%s\n\n" "$PROG: error: $*" >&2
+       show_add_usage >&2
+       exit 1
+}
+
+add_subcommand()
+{
+       if [ "$#" -eq 0  ]; then
+               show_add_usage
+               exit 0
+       fi
+
+       local tmp
+       tmp=`getopt -n $PROG -o f,h --long force,help -- "$@"` ||
+               show_add_usage_fail "cannot parse command-line options"
+       eval set -- "$tmp"
+
+       local force=
+       while true; do
+               case "$1" in
+               -f|--force)
+                       force="-f"
+                       ;;
+               -h|--help)
+                       show_add_usage
+                       exit 0
+                       ;;
+               --) shift; break
+                       ;;
+               *) show_add_usage_fail "unrecognized option \"$1\""
+                       ;;
+               esac
+               shift
+       done
+
+       if [ "$#" -lt 1 ]; then
+               show_add_usage_fail "please, specify the kernel"
+       fi
+       if [ "$#" -gt 1 ]; then
+               show_add_usage_fail "too many arguments: \"$1\""
+       fi
+
+       prepare
+
+       local kernel="$1"
+       local kernel_path="$bootdir/$kernel"
+
+       if ! [ -f "$kernel_path" ] && [ -z "$force" ]; then
+               fatal "cannot find kernel \"$kernel_path\"" \
+                     "(use -f to ignore this error)"
+       fi
+
+       # Get root partition PARTUUID
+       installerfw_get_part_info "/" "PARTUUID" "root_partuuid"
+       [ -n "$root_partuuid" ] || \
+               fatal "cannot find PARTUUID of the root partition"
+
+       # Get kernel options
+       local options="${INSTALLERFW_KERNEL_OPTS:-} root=PARTUUID=$root_partuuid"
+
+       # Get OS name
+       local os_name=
+       get_os_name "os_name"
+
+       # Add the bootloader entry
+       setup-$boot-conf $verbose --bootdir "$bootdir" add $force \
+               "$kernel" "$os_name" "$kernel" "$options"
+
+       # If there is the "quiet" option, create a non-quiet configuration
+       local dbgopts="$(printf "%s" "$options" | LC_ALL=C \
+                               sed -e "s/[[:blank:]]\+quiet[[:blank:]]\+/ /
+                                       s/^quiet[[:blank:]]\+//
+                                       s/[[:blank:]]\+quiet$//
+                                       s/^quiet$//")"
+
+       dbgopts="$dbgopts ignore_loglevel initcall_debug log_buf_len=2M"
+
+       setup-$boot-conf $verbose --bootdir "$bootdir" add \
+               $force "$kernel-debug" "$os_name (debug)" \
+               "$kernel" "$dbgopts"
+}
+
+#
+# -----------------------------------------------------------------------------
+# The "remove" subcommand
+# -----------------------------------------------------------------------------
+#
+
+show_remove_usage()
+{
+       cat <<-EOF
+Usage: $PROG remove [options] <kernel>
+
+Delete bootloader entries for kernel <kernel> (only those which were previously
+created with "$PROG add").
+
+Options:
+  -f, --force  do not fail if <kernel> does not have corresponding bootloader
+               entries
+  -h, --help   show this text and exit
+EOF
+}
+
+show_remove_usage_fail()
+{
+       IFS= printf "%s\n\n" "$PROG: error: $*" >&2
+       show_remove_usage >&2
+       exit 1
+}
+
+remove_subcommand()
+{
+       if [ "$#" -eq 0  ]; then
+               show_remove_usage
+               exit 0
+       fi
+
+       local tmp
+       tmp=`getopt -n $PROG -o f,h --long force,help -- "$@"` ||
+               show_remove_usage_fail "cannot parse command-line options"
+       eval set -- "$tmp"
+
+       local force=
+       while true; do
+               case "$1" in
+               -f|--force)
+                       force="-f"
+                       ;;
+               -h|--help)
+                       show_remove_usage
+                       exit 0
+                       ;;
+               --) shift; break
+                       ;;
+               *) show_remove_usage_fail "unrecognized option \"$1\""
+                       ;;
+               esac
+               shift
+       done
+
+       if [ "$#" -lt 1 ]; then
+               show_add_usage_fail "please, specify the kernel"
+       fi
+       if [ "$#" -gt 1 ]; then
+               show_remove_usage_fail "too many arguments: \"$1\""
+       fi
+
+       local kernel="$1"
+
+       prepare
+
+       # Get the current default entry
+       local default="$(setup-$boot-conf $verbose --bootdir "$bootdir" \
+                                             default $force)"
+       [ $? -eq 0 ] || \
+               fatal "cannot get the default kernel, setup-$boot-conf failed"
+
+       local default_kernel="$(printf "%s" "$default" | LC_ALL=C \
+                        sed -n -e 's/^kernel: \(.\+\)$/\1/p')"
+
+       if [ -n "$default_kernel" ]; then
+               verbose "current default boot kernel is " \
+                       "\"$default_kernel\""
+       else
+               verbose "did not find the default kernel," \
+                     "setup-$boot-conf returned: $default"
+       fi
+
+       # Remove the kernel
+       setup-$boot-conf $verbose --bootdir "$bootdir" \
+                            remove $force "$kernel" || \
+               fatal "setup-$boot-conf failed to remove" \
+                     "entry \"$kernel\""
+       setup-$boot-conf $verbose --bootdir "$bootdir" \
+                            remove $force "$kernel-verbose" || \
+               fatal "setup-$boot-conf failed to remove" \
+                     "entry \"$kernel-verbose\""
+
+       # If this is not the default kernel, we are done
+       [ "$kernel" = "$default_kernel" ] || return 0
+
+       # We've just removed the default kernel, find the kernel with the
+       # latest version and make it to be the default
+
+       verbose "removed the default kernel, find the newest available"
+
+       local newest_kernel="$(get_newest_kernel "$bootdir" "$kernel")"
+
+       if [ -z "$newest_kernel" ]; then
+               verbose "no more kernels, set the kernel to none"
+               setup-$boot-conf $verbose --bootdir "$bootdir" \
+                                    default --force "<none>"
+       else
+               verbose "new default kernel is \"$newest_kernel\""
+               setup-$boot-conf $verbose --bootdir "$bootdir" \
+                                    default "$newest_kernel"
+       fi
+
+       if [ "$?" -ne 0 ]; then
+               fatal "cannot set default kernel, \"setup-$boot-conf\" failed"
+       fi
+}
+
+#
+# -----------------------------------------------------------------------------
+# The "default" subcommand
+# -----------------------------------------------------------------------------
+#
+
+show_default_usage()
+{
+       cat <<-EOF
+Usage: $PROG default [options] <kernel>
+
+Set the default boot kernel to <kernel>. If <kernel> is omited, print the
+current default boot kernel name.
+
+Options:
+  -f, --force  do not fail if <kernel> doesn't exist
+  -h, --help   show this text and exit
+EOF
+}
+
+show_default_usage_fail()
+{
+       IFS= printf "%s\n\n" "$PROG: error: $*" >&2
+       show_default_usage >&2
+       exit 1
+}
+
+default_subcommand()
+{
+       local tmp
+       tmp=`getopt -n $PROG -o f,h --long force,help -- "$@"` ||
+               show_default_usage_fail "cannot parse command-line options"
+       eval set -- "$tmp"
+
+       local force=
+       while true; do
+               case "$1" in
+               -f|--force)
+                       force="-f"
+                       ;;
+               -h|--help)
+                       show_default_usage
+                       exit 0
+                       ;;
+               --) shift; break
+                       ;;
+               *) show_default_usage_fail "unrecognized option \"$1\""
+                       ;;
+               esac
+               shift
+       done
+
+       if [ "$#" -gt 1 ]; then
+               show_default_usage_fail "too many arguments: \"$1\""
+       fi
+
+       prepare
+
+       local kernel="${1:-}"
+       local kernel_path="$bootdir/$kernel"
+
+       if [ -n "$kernel" ] && ! [ -f "$kernel_path" ] && [ -z "$force" ]; then
+               fatal "cannot find kernel \"$kernel_path\"" \
+                     "(use -f to ignore this error)"
+       fi
+
+       setup-$boot-conf $verbose --bootdir "$bootdir" default $force "$kernel"
+}
+
+#
+# -----------------------------------------------------------------------------
+#
+
+show_usage()
+{
+       cat <<-EOF
+Usage: $PROG [options] <subcommand> [options] <arguments>
+
+This program adds or removes a kernel to/from the bootloader configuration
+file(s). This is a Tizen IVI-specific program and it currently supports only 2
+bootloader types - extlinux and gummiboot. Each new kernel gets 2 boot menu
+entries - the default and verbose, and both of these are removed by the
+"remove" subcommand.
+
+The supported subcommands are:
+   add     - add bootloader entries for a kernel
+   remove  - remove bootloader entries for a kernel
+   default - get or set the default boot kernel
+
+Run "$PROG <subcommand>" to see subcommand-specific help.
+
+Options:
+  --version      show the program version and exit
+  -v, --verbose  be verbose
+  -h, --help     show this text and exit
+EOF
+}
+
+show_usage_fail()
+{
+       IFS= printf "%s\n\n" "$PROG: error: $*" >&2
+       show_usage >&2
+       exit 1
+}
+
+verbose=
+while [ -n "${1:-""}" ] && [ -z "${1##-*}" ]; do
+       case "$1" in
+       --version)
+               printf "%s\n" "$VER"
+               exit 0
+               ;;
+       -v|--verbose)
+               verbose="-v"
+               ;;
+       -h|--help)
+               show_usage
+               exit 0
+               ;;
+       --) shift; break
+               ;;
+       *) show_usage_fail "unrecognized option \"$1\""
+               ;;
+       esac
+       shift
+done
+
+if [ "$#" -eq 0 ]; then
+       show_usage
+       exit 0
+fi
+
+# Parse subcommands
+
+subcommand="$1"; shift
+
+case "$subcommand" in
+add)
+       add_subcommand "$@"
+       break
+       ;;
+remove)
+       remove_subcommand "$@"
+       break
+       ;;
+default)
+       default_subcommand "$@"
+       break
+       ;;
+*) show_usage_fail "unrecognized subcommand \"$subcommand\""
+       ;;
+esac
diff --git a/setup-ivi-sh-functions b/setup-ivi-sh-functions
new file mode 100644 (file)
index 0000000..b817e13
--- /dev/null
@@ -0,0 +1,118 @@
+# Copyright 2013 Intel Corporation
+# Author: Artem Bityutskiy
+# License: GPLv2
+
+# This file contains common functions for setup-ivi-* programs
+
+# Own name
+__PROG="$PROG:-setup-ivi-sh-functions"
+
+fatal()
+{
+       IFS= printf "%s\n" "$PROG: error: $*" 1>&2
+       exit 1
+}
+
+verbose()
+{
+       if [ -n "$verbose" ]; then
+               IFS= printf "%s\n" "$PROG (verbose): $*" >&2
+       fi
+}
+
+# Finds out the OS name and sets the "$1" variable to the OS name upon exit.
+get_os_name()
+{
+       local osrelease_path="$(installerfw_mnt_prefix "$__osrelease_file")"
+
+       # Make sure the OS release information file is present
+       [ -f "$osrelease_path" ] ||
+               fatal "the \"$osrelease_path\" file not found"
+
+       # Get the OS name
+       local __os_name="$(LC_ALL=C sed -n -e 's/^PRETTY_NAME="\(.*\)"$/\1/p' "$osrelease_path")"
+       [ -n "$__os_name" ] || \
+               fatal "cannot find \"PRETTY_NAME\" variable in \"$osrelease_path\""
+
+       if [ "${1:-%}" != "%" ]; then
+               eval $1="\$__os_name"
+               verbose "get_os_name(): OS name: $1=$__os_name"
+       fi
+}
+
+# Escape a string which is going to be used in a regexp. Shuould work for both
+# sed and grep regexps.
+esc_regexp()
+{
+       local regexp="$1";
+
+       printf "%s" "$regexp" | LC_ALL=C sed -e 's/[]\/()$*.^|[]/\\&/g'
+}
+
+# Escape a string which is going to be used at the "replacement" part of the
+# sed "substitute" command (as in s/regexp/replacement/flags')
+# Usage: esc_sed_replacement <replacement>
+esc_sed_replacement()
+{
+       local replacement="$1";
+
+       printf "%s" "$replacement" | LC_ALL=C sed -e "s/[\&/]/\\&/g"
+}
+
+# Turn strings "abc" into "[Aa][Bb][Cc]" for case-insensitive matching in
+# regular expressions.
+case_insensitive_regexp()
+{
+       local regexp="$1"
+
+       printf "%s" "$regexp" | LC_ALL=C sed -e 's/[[:alpha:]]/[\U&\l&]/g'
+}
+
+# Check if dash is available and we are not running in dash
+can_switch_to_dash()
+{
+        if command -v "dash" >/dev/null 2>&1; then
+               if [ -n "${BASH_VERSION:-}" ]; then
+                       return 0
+               fi
+       fi
+
+       return 1
+}
+
+# Get the newest kernel, "$1" is the directory to search at, "$2" is an
+# optional argument, and if it present, it tells which kernel should not be
+# returned by this function.
+get_newest_kernel()
+{
+       local bootdir="$1"; shift
+
+       # Generate the list of installed kernels
+       local kernels="$(ls -1 "$bootdir" | LC_ALL=C grep "^vmlinuz-" | sort -r)"
+
+       # Exclude the unwanted kernel, if any
+       if [ -n "${1:-}" ]; then
+               local kernel="$(esc_regexp "$1")"
+               kernels="$(printf "%s" "$kernels" | LC_ALL=C grep -v "^$kernel$")"
+       fi
+
+       printf "%s" "$kernels" | head -n1
+}
+
+# Remove all empty lines from the end of file, including lines which contain
+# nothing but blanks (tabs and spaces).
+remove_trailing_empty_lines()
+{
+       local file="$1"
+
+       LC_ALL=C sed -i -n -e '
+           :l                   # sed jump lable named "l"
+           /^[[:blank:]\n]*$/ { # matches multiple blank lines with any
+                                # number of spaces or tabs
+                $d              # if these are last lines, delete them
+                N;              # otherwise append to the current pattern buf
+                bl              # and start over
+           }
+           /^[[:blank:]]*$/!p   # print the pattern buffer for non-blank lines
+           ' "$file"
+}