From: Philippe Coval Date: Mon, 11 Aug 2014 08:36:00 +0000 (+0200) Subject: Make tizen generic (rename "ivi" by "scripts") X-Git-Tag: submit/tizen/20140814.121617^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fc66f580643ea38a56a5e29ae49536381b86a73f;p=platform%2Fadaptation%2Fsetup-scripts.git Make tizen generic (rename "ivi" by "scripts") Bug-Tizen: TINF-650 Change-Id: I13a018d30cd42f5b67197a7c323acc96930832a3 Signed-off-by: Philippe Coval --- diff --git a/efi-environment b/efi-environment index d5105ab..8ac4eb0 100644 --- a/efi-environment +++ b/efi-environment @@ -1,9 +1,9 @@ -# This file can be used for testing setup-ivi-* scripts. This file corresponds +# This file can be used for testing setup-scripts-* 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 +# touch /tmp/boot/vmlinuz-* # mkdir -p /tmp/usr/lib/gummiboot # touch /tmp/usr/lib/gummiboot/gummibootia32.efi # mkdir /tmp/etc diff --git a/installerfw-sh-functions b/installerfw-sh-functions index bee4a19..985904c 100644 --- a/installerfw-sh-functions +++ b/installerfw-sh-functions @@ -2,7 +2,7 @@ # Author: Artem Bityutskiy # License: GPLv2 -# This file contains common functions for setup-ivi-* programs +# This file contains common functions for setup-scripts-* programs # Own name __PROG="${PROG:-installerfw-sh-functions}" diff --git a/ivi-clone.service b/ivi-clone.service deleted file mode 100644 index 10a8d6f..0000000 --- a/ivi-clone.service +++ /dev/null @@ -1,9 +0,0 @@ -[Unit] -Description=Cloning of the Tizen IVI OS to a non-removable media - -[Service] -Type=oneshot -StandardOutput=journal+console -StandardInput=tty -ExecStart=/usr/sbin/setup-ivi-clone-service -ExecStartPost=/usr/sbin/reboot diff --git a/mbr-environment b/mbr-environment index ca1ea84..6bfcb4d 100644 --- a/mbr-environment +++ b/mbr-environment @@ -1,8 +1,8 @@ -# This file can be used for testing setup-ivi-* scripts. This file corresponds +# This file can be used for testing setup-scripts-* 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 +# touch /tmp/boot/vmlinux-* # mkdir -p /tmp/usr/share/syslinux/ # touch /tmp/usr/share/syslinux/gptmbr.bin # mkdir /tmp/etc diff --git a/packaging/setup-ivi.changes b/packaging/setup-ivi.changes deleted file mode 100644 index e7c266e..0000000 --- a/packaging/setup-ivi.changes +++ /dev/null @@ -1,16 +0,0 @@ -* Thu Jul 31 2014 Mikko Ylinen accepted/tizen/ivi/20140730.121044-4-g00273ab -- setup-gummiboot-conf: Set background to black -- Enable i915.fastboot=1 for the splash boot entry -- packaging: minor change to set tizen as HEAD - -* Fri Feb 14 2014 Artem Bityutskiy 1.0 -- Fix TIVI-2652 - now a long chain of cloning the OS works fine and does not - fail at the third step. - -* Fri Jan 31 2014 Artem Bityutskiy 1.0 -- Generate kernel entries for debugging the splash screen work. These are - separate entries now, and only work for the gummiboot bloot-loader. Once - splash screen works well, it becomes part of the default boot entry. - -* Wed Jan 15 10:15:26 UTC 2014 Artem Bityutskiy 1.0 -- Initial implementation. diff --git a/packaging/setup-ivi.manifest b/packaging/setup-ivi.manifest deleted file mode 100644 index 017d22d..0000000 --- a/packaging/setup-ivi.manifest +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/packaging/setup-ivi.spec b/packaging/setup-ivi.spec deleted file mode 100644 index d9054e6..0000000 --- a/packaging/setup-ivi.spec +++ /dev/null @@ -1,117 +0,0 @@ -Name: setup-ivi -Version: 1.1 -Release: 0 -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: /usr/bin/tr -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 - -%package -n setup-ivi-clone -Summary: A tool for cloning a Tizen IVI system -Requires: %{name} -Requires: /usr/bin/mount -Requires: /usr/bin/udevadm -Requires: /usr/bin/uuidgen -Requires: /usr/bin/sync -Requires: /usr/bin/tail -Requires: systemd -Requires: gptfdisk -Requires: e2fsprogs -Requires: dosfstools -Requires: rsync - -%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. - -%description -n setup-ivi-clone -This package provides a command line tool for cloning a Tizen IVI system to a -different disk. - -### -### PREP -### -%prep -%setup -q -n %{name}-%{version} - -%build - -### -### INSTALL -### -%install -install -d %{buildroot}/%{_sbindir} -install -d %{buildroot}/%{_prefix}/share/setup-ivi -install -d %{buildroot}/%{_unitdir} - -install -m755 setup-ivi-boot %{buildroot}/%{_sbindir} -install -m755 setup-ivi-fstab %{buildroot}/%{_sbindir} -install -m755 setup-ivi-bootloader-conf %{buildroot}/%{_sbindir} -install -m755 setup-ivi-clone %{buildroot}/%{_sbindir} -install -m755 setup-ivi-clone-service %{buildroot}/%{_sbindir} -install -m644 ivi-clone.service %{buildroot}/%{_unitdir} -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-fstab -%{_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 - -%files -n setup-ivi-clone -%defattr(-,root,root) -%{_sbindir}/setup-ivi-clone -%{_sbindir}/setup-ivi-clone-service -# Note, we do not need to run 'systemctl enable ivi-clone' for this one because -# it is activated by the 'systemd.unit=ivi-clone.service' kernel parameter. -%{_unitdir}/ivi-clone.service diff --git a/packaging/setup-scripts.changes b/packaging/setup-scripts.changes new file mode 100644 index 0000000..e7c266e --- /dev/null +++ b/packaging/setup-scripts.changes @@ -0,0 +1,16 @@ +* Thu Jul 31 2014 Mikko Ylinen accepted/tizen/ivi/20140730.121044-4-g00273ab +- setup-gummiboot-conf: Set background to black +- Enable i915.fastboot=1 for the splash boot entry +- packaging: minor change to set tizen as HEAD + +* Fri Feb 14 2014 Artem Bityutskiy 1.0 +- Fix TIVI-2652 - now a long chain of cloning the OS works fine and does not + fail at the third step. + +* Fri Jan 31 2014 Artem Bityutskiy 1.0 +- Generate kernel entries for debugging the splash screen work. These are + separate entries now, and only work for the gummiboot bloot-loader. Once + splash screen works well, it becomes part of the default boot entry. + +* Wed Jan 15 10:15:26 UTC 2014 Artem Bityutskiy 1.0 +- Initial implementation. diff --git a/packaging/setup-scripts.manifest b/packaging/setup-scripts.manifest new file mode 100644 index 0000000..017d22d --- /dev/null +++ b/packaging/setup-scripts.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/setup-scripts.spec b/packaging/setup-scripts.spec new file mode 100644 index 0000000..ec37bc7 --- /dev/null +++ b/packaging/setup-scripts.spec @@ -0,0 +1,121 @@ +Name: setup-scripts +Version: 1.1 +Release: 0 +License: GPL-2.0 +Summary: Various early setup programs +Url: http://www.tizen.org +Group: System/Configuration +Source: %{name}_%{version}.tar.gz +Provides: setup-ivi = %{version}-%{release} +Obsoletes: setup-ivi < %{version}-%{release} +Requires: /usr/bin/sed +Requires: /usr/bin/grep +Requires: /usr/bin/printf +Requires: /usr/bin/printenv +Requires: /usr/bin/sort +Requires: /usr/bin/tr +Requires: virtual-setup-scripts-bootloader +BuildArchitectures: noarch + +%package -n %{name}-gummiboot +Summary: Command-line tool for tweaking gummiboot configuration +Provides: virtual-%{name}-bootloader +Requires: %{name} = %{version}-%{release} +Requires: gummiboot + +%package -n %{name}-extlinux +Summary: Command-line tool for tweaking extlinux configuration +Provides: virtual-%{name}-bootloader +Requires: %{name} = %{version}-%{release} +Requires: syslinux-extlinux + +%package -n %{name}-clone +Summary: A tool for cloning a Tizen system +Provides: setup-ivi-clone = %{version}-%{release} +Obsoletes: setup-ivi-clone < %{version}-%{release} +Requires: %{name} = %{version}-%{release} +Requires: /usr/bin/mount +Requires: /usr/bin/udevadm +Requires: /usr/bin/uuidgen +Requires: /usr/bin/sync +Requires: /usr/bin/tail +Requires: systemd +Requires: gptfdisk +Requires: e2fsprogs +Requires: dosfstools +Requires: rsync + +%description +This package provides various early system setup programs + +%description -n %{name}-gummiboot +This package provides a command-line tool for changing the gummiboot bootloader +configuration files. + +%description -n %{name}-extlinux +This package provides a command-line tool for changing the extlinux bootloader +configuration file. + +%description -n %{name}-clone +This package provides a command line tool for cloning a Tizen system to a +different disk. + +### +### PREP +### +%prep +%setup -q -n %{name}-%{version} + +%build + +### +### INSTALL +### +%install +install -d %{buildroot}/%{_sbindir} +install -d %{buildroot}/%{_prefix}/share/setup-scripts +install -d %{buildroot}/%{_unitdir} + +install -m755 setup-scripts-boot %{buildroot}/%{_sbindir} +install -m755 setup-scripts-fstab %{buildroot}/%{_sbindir} +install -m755 setup-scripts-bootloader-conf %{buildroot}/%{_sbindir} +install -m755 setup-scripts-clone %{buildroot}/%{_sbindir} +install -m755 setup-scripts-clone-service %{buildroot}/%{_sbindir} +install -m644 scripts-clone.service %{buildroot}/%{_unitdir} +install -m755 setup-gummiboot-conf %{buildroot}/%{_sbindir} +install -m755 setup-extlinux-conf %{buildroot}/%{_sbindir} +install -m644 setup-scripts-sh-functions %{buildroot}/%{_prefix}/share/setup-scripts +install -m644 installerfw-sh-functions %{buildroot}/%{_prefix}/share/setup-scripts + +### +### CLEAN +### +%clean +rm -rf %{buildroot} + +### +### FILES +### +%files +%defattr(-,root,root) +%{_sbindir}/setup-scripts-boot +%{_sbindir}/setup-scripts-fstab +%{_sbindir}/setup-scripts-bootloader-conf +%{_prefix}/share/setup-scripts/setup-scripts-sh-functions +%{_prefix}/share/setup-scripts/installerfw-sh-functions + +%files -n %{name}-gummiboot +%defattr(-,root,root) +%{_sbindir}/setup-gummiboot-conf + +%files -n %{name}-extlinux +%defattr(-,root,root) +%{_sbindir}/setup-extlinux-conf + +%files -n setup-scripts-clone +%defattr(-,root,root) +%{_sbindir}/setup-scripts-clone +%{_sbindir}/setup-scripts-clone-service +# Note, we do not need to run 'systemctl enable scripts-clone' for this one because +# it is activated by the 'systemd.unit=scripts-clone.service' kernel parameter. +%{_unitdir}/scripts-clone.service diff --git a/scripts-clone.service b/scripts-clone.service new file mode 100644 index 0000000..600c343 --- /dev/null +++ b/scripts-clone.service @@ -0,0 +1,9 @@ +[Unit] +Description=Cloning of the Tizen OS to a non-removable media + +[Service] +Type=oneshot +StandardOutput=journal+console +StandardInput=tty +ExecStart=/usr/sbin/setup-scripts-clone-service +ExecStartPost=/usr/sbin/reboot diff --git a/setup-extlinux-conf b/setup-extlinux-conf index 4a45152..f06c95e 100755 --- a/setup-extlinux-conf +++ b/setup-extlinux-conf @@ -8,10 +8,10 @@ PROG="setup-extlinux-conf" VER="1.0" srcdir="$(readlink -ev -- ${0%/*})" -if [ -f "$srcdir/setup-ivi-sh-functions" ]; then - . "$srcdir/setup-ivi-sh-functions" +if [ -f "$srcdir/setup-scripts-sh-functions" ]; then + . "$srcdir/setup-scripts-sh-functions" else - . /usr/share/setup-ivi/setup-ivi-sh-functions + . /usr/share/setup-scripts/setup-scripts-sh-functions fi # This is a small trick which I use to make sure my scripts are portable - diff --git a/setup-gummiboot-conf b/setup-gummiboot-conf index 83f5719..8119f47 100755 --- a/setup-gummiboot-conf +++ b/setup-gummiboot-conf @@ -8,10 +8,10 @@ PROG="setup-gummiboot-conf" VER="1.0" srcdir="$(readlink -ev -- ${0%/*})" -if [ -f "$srcdir/setup-ivi-sh-functions" ]; then - . "$srcdir/setup-ivi-sh-functions" +if [ -f "$srcdir/setup-scripts-sh-functions" ]; then + . "$srcdir/setup-scripts-sh-functions" else - . /usr/share/setup-ivi/setup-ivi-sh-functions + . /usr/share/setup-scripts/setup-scripts-sh-functions fi # This is a small trick which I use to make sure my scripts are portable - diff --git a/setup-ivi-boot b/setup-ivi-boot deleted file mode 100755 index 428443b..0000000 --- a/setup-ivi-boot +++ /dev/null @@ -1,184 +0,0 @@ -#!/bin/sh -euf - -# Copyright 2013-2014 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" - -if [ -f "$srcdir/setup-ivi-sh-functions" ]; then - . "$srcdir/setup-ivi-sh-functions" - . "$srcdir/installerfw-sh-functions" -else - . /usr/share/setup-ivi/setup-ivi-sh-functions - . /usr/share/setup-ivi/installerfw-sh-functions -fi - -# 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() -{ - local installdir="$bootdir/extlinux" - local extlinux="extlinux" - local output - - # 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 - verbose "installing extlinux to $bootdir, boot device node is" \ - "\"$boot_devnode\"" - mkdir -p $verbose -- "$installdir" >&2 - output="$("$extlinux" --device "$boot_devnode" -i "$installdir" 2>&1)" \ - || fatal "cannot install extlinux to \"$installdir\" (note," \ - "extlinux version 5 or greater is required)" \ - "${br}${output}" - - # 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")" - verbose "setting up MBR, writing \"$mbr_bin\" to \"$mbr_devnode\"" - output="$(dd if="$mbr_bin" of="$mbr_devnode" count=1 2>&1)" || \ - fatal "cannot install MBR, dd if=$mbr_bin of=$mbr_devnode" \ - "failed${br}${output}" - - 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")" - -if installerfw_available; then - installerfw_save_env -else - installerfw_restore_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" - -# And finally, create the /etc/fstab file -setup-ivi-fstab $verbose --force diff --git a/setup-ivi-bootloader-conf b/setup-ivi-bootloader-conf deleted file mode 100755 index 3403b6c..0000000 --- a/setup-ivi-bootloader-conf +++ /dev/null @@ -1,455 +0,0 @@ -#!/bin/sh -euf - -# Copyright 2013-2014 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" - -if [ -f "$srcdir/setup-ivi-sh-functions" ]; then - . "$srcdir/setup-ivi-sh-functions" - . "$srcdir/installerfw-sh-functions" -else - . /usr/share/setup-ivi/setup-ivi-sh-functions - . /usr/share/setup-ivi/installerfw-sh-functions -fi - -# 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 - - rootdir="$(installerfw_mnt_prefix "/")" - 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] - -Add bootloader entries for kernel . - -Options: - -f, --force if bootloader entries for already exist in bootloader's - config file(s) - re-write them, if 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 default bootloader entry - setup-$boot-conf $verbose --bootdir "$bootdir" add $force \ - "$kernel" "$os_name" "$kernel" "$options" - - # Add the debug bootloader entry. If there is the "quiet" option, - # create a non-quiet configuration. - local verbose_opts="$(printf "%s" "$options" | LC_ALL=C \ - sed -e "s/[[:blank:]]\+quiet[[:blank:]]\+/ / - s/^quiet[[:blank:]]\+// - s/[[:blank:]]\+quiet$// - s/^quiet$//")" - - local debug_opts="$verbose_opts ignore_loglevel log_buf_len=2M" - local debug_opts="$debug_opts initcall_debug" - - - setup-$boot-conf $verbose --bootdir "$bootdir" add \ - $force "$kernel-debug" "Debug $os_name" \ - "$kernel" "$verbose_opts" - - # Add the clone bootloader entry, but only if the cloning tool is - # installed - if [ -f "$rootdir/usr/sbin/setup-ivi-clone" ]; then - clone_opts="$options systemd.unit=ivi-clone.service" - clone_opts="$clone_opts ivi-clone-target=autodetect" - setup-$boot-conf $verbose --bootdir "$bootdir" add \ - $force "$kernel-clone" "Clone $os_name" \ - "$kernel" "$clone_opts" - fi - - # Use default gummiboot-splash file - local splash_path="$rootdir/usr/share/gummiboot/splash.bmp" - - # Add a splash entry for fastboot testing and disable fbcon - if [ "$boot" = "gummiboot" ] && [ -f "$splash_path" ]; then - splash_opts="$options i915.fastboot=1 fbcon=map:9" - setup-$boot-conf $verbose --bootdir "$bootdir" add \ - $force --splash "$splash_path" "$kernel-splash" \ - "Splash $os_name" "$kernel" "$splash_opts" - fi -} - -# -# ----------------------------------------------------------------------------- -# The "remove" subcommand -# ----------------------------------------------------------------------------- -# - -show_remove_usage() -{ - cat <<-EOF -Usage: $PROG remove [options] - -Delete bootloader entries for kernel (only those which were previously -created with "$PROG add"). - -Options: - -f, --force do not fail if 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-debug" || \ - fatal "setup-$boot-conf failed to remove" \ - "entry \"$kernel-verbose\"" - # The "clone" entry does not necessary exist, so use --force - setup-$boot-conf $verbose --bootdir "$bootdir" \ - remove --force "$kernel-clone" || \ - fatal "setup-$boot-conf failed to remove" \ - "entry \"$kernel-clone\"" - # Ditto for "splash" - setup-$boot-conf $verbose --bootdir "$bootdir" \ - remove --force "$kernel-splash" || \ - fatal "setup-$boot-conf failed to remove" \ - "entry \"$kernel-splash\"" - - # 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 "" - 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] - -Set the default boot kernel to . If is omited, print the -current default boot kernel name. - -Options: - -f, --force do not fail if 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] [options] - -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 " 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-clone b/setup-ivi-clone deleted file mode 100755 index e36c313..0000000 --- a/setup-ivi-clone +++ /dev/null @@ -1,541 +0,0 @@ -#!/bin/sh -euf - -# Copyright 2013-2014 Intel Corporation -# Author: Artem Bityutskiy -# License: GPLv2 - -PROG="setup-ivi-clone" -VER="1.0" - -srcdir="$(readlink -ev -- ${0%/*})" - -if [ -f "$srcdir/setup-ivi-sh-functions" ]; then - . "$srcdir/setup-ivi-sh-functions" - . "$srcdir/installerfw-sh-functions" -else - . /usr/share/setup-ivi/setup-ivi-sh-functions - . /usr/share/setup-ivi/installerfw-sh-functions -fi - -# 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 - -# These are used in the cleanup handler, so have to be defined before the -# function -tmpdir= -unmount_list= -automount_status= - -# Unmount all partitions which we possibly mounted -unmount_partitions() -{ - printf "%s\n" "$unmount_list" | while IFS= read -r dir; do - if [ -n "$dir" ]; then - verbose "unmount \"$dir\"" - umount $verbose -- "$dir" >&2 ||: - fi - done -} - -# This function is called on exit, crashes, interrupts, etc. We clean up -# everything here before the program is terminated -cleanup_handler() -{ - local exitcode="$1" - - # Restore the default exit handler - trap - EXIT - - verbose "cleanup and exit with code $exitcode" - - unmount_partitions - rm -r $verbose -- "$tmpdir" >&2 - - if [ "$automount_status" = "active" ]; then - message "re-enabling udisks-automount-agent" - systemctl --user start udisks-automount-agent || \ - warning "cannot start udisks-automount-agent" - fi - - exit "$exitcode" -} - -# Append a line to a list, which is just text where each line is considered to -# be an element of the list. The first parameter is the line to append, the -# second parameter is the variable name to append to (the variable is defined -# outside of this function and contains the text to prepend the line to). -list_append() -{ - local __value="$1"; shift - local __list_name="$1" - eval local "__list=\$$__list_name" - - [ -z "$__list" ] && eval "$__list_name=\"\$__value\"" || \ - eval "$__list_name=\"\${__list}\${br}\${__value}\"" -} - -# Similar to 'list_append()', but prepends a list with a line. -list_prepend() -{ - local __value="$1"; shift - local __list_name="$1" - eval local "__list=\$$__list_name" - - [ -z "$__list" ] && eval "$__list_name=\"\$__value\"" || \ - eval "$__list_name=\"\${__value}\${br}\${__list}\"" -} - -# Create partitions on the destination disk. This function also updates the -# following installer framework environment variables: -# o INSTALLERFW_PARTx_PARTUUID -# o INSTALLERFW_PARTx_TYPE_ID -create_partitions() -{ - # The GPT partition type GUID for Linux partitions - local linuxfs_type_id="0fc63daf-8483-4772-8e79-3d69d8477de4" - - verbose "destroying all partitions at \"$dstdisk\"" - sgdisk -z "$dstdisk" -- > /dev/null 2>&1 ||: - sgdisk -Z "$dstdisk" -- > /dev/null 2>&1 ||: - - # Create all partitions one-by-one - local pnum=0 - local gdisk_pnum=1 - while [ "$pnum" -lt "$part_count" ]; do - installerfw_verify_defined "INSTALLERFW_PART${pnum}_SIZE" - - eval local size="\$INSTALLERFW_PART${pnum}_SIZE" - eval local bootflag="\${INSTALLERFW_PART${pnum}_BOOTFLAG:-}" - eval local type_id="\${INSTALLERFW_PART${pnum}_TYPE_ID:-$linuxfs_type_id}" - - if [ "$gdisk_pnum" -eq "$part_count" ]; then - # Make the last partition take the rest of the space - verbose "creating the last partition $pnum" - sgdisk -n "$gdisk_pnum:+0:-1s" -- "$dstdisk" > /dev/null - else - verbose "creating partition $pnum of size $size MiB" - sgdisk -n "$gdisk_pnum:+0:+${size}M" -- "$dstdisk" > /dev/null - fi - - # Re-set the UUID - local partuuid="$(uuidgen)" - verbose "setting partition $pnum PARTUUID to $partuuid" - sgdisk -u "$gdisk_pnum:$partuuid" -- "$dstdisk" > /dev/null - - # Take care of the boot flag - if [ "$bootflag" = "True" ]; then - verbose "setting the boot flag for partition $pnum" - sgdisk -A "$gdisk_pnum:set:2" -- "$dstdisk" > /dev/null - fi - - verbose "setting partition $pnum type ID to $type_id" - sgdisk -t "$gdisk_pnum:$type_id" -- "$dstdisk" > /dev/null - - # Re-define some installer framework variables - eval "export INSTALLERFW_PART${pnum}_PARTUUID=$partuuid" - eval "export INSTALLERFW_PART${pnum}_TYPE_ID=$type_id" - - pnum="$(($pnum + 1))" - gdisk_pnum="$(($gdisk_pnum + 1))" - done -} - -# Find the device node name by its major:minor numbers ($1:$2). -find_devnode_by_nums() -{ - local major="$1"; shift - local minor="$1" - - ls -1 /dev | while IFS= read -r node; do - local ma="$(printf "%d" "0x$(stat -c '%t' -- "/dev/$node")")" - local mi="$(printf "%d" "0x$(stat -c '%T' -- "/dev/$node")")" - - if [ -b "/dev/$node" ] && [ "$ma" -eq "$major" ] && \ - [ "$mi" -eq "$minor" ]; then - printf "%s" "/dev/$node" - break - fi - done -} - -# Find the device node name by a file name. In other words, for a given file, -# fine the device node of the partition this file resides on. -find_devnode_by_file() -{ - local file="$1" - local devnum="$(stat -c '%d' -- "$file")" - local major=$((($devnum / 256) % 256)) - local minor=$(($devnum % 256)) - - find_devnode_by_nums "$major" "$minor" -} - -# Find all the source and destination device nodes and declare change the -# following installer framework environment variables: -# o INSTALLERFW_PARTx_DEVNODE_NOW -# o INSTALLERFW_PARTx_DISK_DEVNODE_NOW -# And for the source partitions, the device node names are stored in -# "srcpartX_devnode" variables (X is the partition number). -find_devnodes() -{ - # Find source device nodes - - local pnum=0 - while [ "$pnum" -lt "$part_count" ]; do - installerfw_verify_defined "INSTALLERFW_PART${pnum}_MOUNTPOINT" - - eval local mountpoint="\$INSTALLERFW_PART${pnum}_MOUNTPOINT" - local devnode="$(find_devnode_by_file "$mountpoint")" - - [ -n "$devnode" ] || fatal "cannot find device node for" \ - "source partition $mountpoint" - - verbose "source partition $mountpoint device node is: $devnode" - - eval "srcpart${pnum}_devnode=$devnode" - - pnum="$(($pnum + 1))" - done - - # Find destination device nodes - - local major="$(printf "%d" "0x$(stat -c '%t' -- "$dstdisk")")" - local minor="$(printf "%d" "0x$(stat -c '%T' -- "$dstdisk")")" - - pnum=0 - while [ "$pnum" -lt "$part_count" ]; do - local part_minor="$(($minor + $pnum + 1))" - devnode="$(find_devnode_by_nums "$major" "$part_minor")" - - [ -n "$devnode" ] || fatal "cannot find device node for" \ - "destination partition $pnum" - - verbose "destination partition $pnum device node is: $devnode" - - eval "export INSTALLERFW_PART${pnum}_DEVNODE_NOW=$devnode" - eval "export INSTALLERFW_PART${pnum}_DISK_DEVNODE_NOW=$dstdisk" - - pnum="$(($pnum + 1))" - done - -} - -# Format all the destination partitions and changes the -# "INSTALLERFW_PARTx_UUID" installer framework environment variables. -format_dst_partitions() -{ - local pnum=0 - while [ "$pnum" -lt "$part_count" ]; do - installerfw_verify_defined "INSTALLERFW_PART${pnum}_FSTYPE" - eval local fstype="\$INSTALLERFW_PART${pnum}_FSTYPE" - eval local label="\${INSTALLERFW_PART${pnum}_LABEL:-}" - eval local devnode="\$INSTALLERFW_PART${pnum}_DEVNODE_NOW" - - local uuid="$(uuidgen)" - - verbose "format partition $pnum ($devnode) with mkfs.$fstype" - - if [ "$fstype" != "vfat" ]; then - verbose "partition $pnum label is \"$label\", UUID is \"$uuid\"" - - [ -z "$label" ] || label="-L $label" - - mkfs.$fstype $verbose $quiet $label -U "$uuid" -- "$devnode" >&2 - else - # FATFS Volume ID is an XXXXXXXX (32-bit) string, where - # X is are uppercase hex digits. - uuid="$(printf "%s" "$uuid" | head -c8 | \ - tr "[:lower:]" "[:upper:]")" - - verbose "partition $pnum label is \"$label\", UUID is \"$uuid\"" - - [ -z "$label" ] || label="-n $label" - - if [ -n "$verbose" ]; then - mkfs.vfat $verbose $label -i "$uuid" -- "$devnode" >&2 - else - # mkfs.vfat does not accept -q - mkfs.vfat $label -i "$uuid" -- "$devnode" > /dev/null - fi - - # However, the installer framework variable has to have - # the XXXX-XXXX format, not XXXXXXXX. Unfortunately, - # mkfs.vfat does not like the "-", while 'mount' - # requires the "-". - uuid="$(printf "%s" "$uuid" | LC_ALL=C sed -e 's/.\{4\}/&-/')" - fi - - eval "export INSTALLERFW_PART${pnum}_UUID=$uuid" - - pnum="$(($pnum+1))" - done -} - -# Mount source and destination partition -mount_partitions() -{ - local pnum=0 - while [ "$pnum" -lt "$part_count" ]; do - eval local mountpoint="\$INSTALLERFW_PART${pnum}_MOUNTPOINT" - - # Mount the source partition - eval local devnode="\$srcpart${pnum}_devnode" - local mntdir="$srcbase/$pnum" - - verbose "mounting source partition $pnum" \ - "($devnode, $mountpoint) to $mntdir" - - mkdir -p $verbose -- "$mntdir" >&2 - mount $verbose -- "$devnode" "$mntdir" >&2 - list_prepend "$mntdir" "unmount_list" - - # Mount the destination partition - eval devnode="\$INSTALLERFW_PART${pnum}_DEVNODE_NOW" - mntdir="$dstbase/$pnum" - - verbose "mounting destination partition $pnum" \ - "($devnode, $mountpoint) to $mntdir" - - mkdir -p $verbose -- "$mntdir" >&2 - mount $verbose -- "$devnode" "$mntdir" >&2 - list_prepend "$mntdir" "unmount_list" - - pnum="$(($pnum + 1))" - done -} - -# Copy data from all the source partitions to destination partitions -copy_the_data() -{ - local pnum=0 - while [ "$pnum" -lt "$part_count" ]; do - local src_mntdir="$srcbase/$pnum" - local dst_mntdir="$dstbase/$pnum" - - verbose "copy partition $pnum:" \ - "\"$src_mntdir\" -> \"$dst_mntdir\"" - - rsync -WaHXSh --exclude "${tmpdir}" "$src_mntdir/" "$dst_mntdir/" - - pnum="$(($pnum + 1))" - done -} - -# This function creates proper target hierarchy by mounting destination -# partition under the right mount points. By the time this function is called, -# all the destination partitions are mounted under "$dstbase/$pnum", so "/boot" -# is not under "/", etc. This function mounts them under "$dstbase/root" -create_dst_hierarchy() -{ - # Create a sorted list of mount points - local list= - local mountpoint= - local pnum=0 - while [ "$pnum" -lt "$part_count" ]; do - eval mountpoint="\$INSTALLERFW_PART${pnum}_MOUNTPOINT" - list_append "$mountpoint" "list" - pnum="$(($pnum+1))" - done - - list="$(printf "%s" "$list" | sort)" - - mkdir $verbose -- "$dstbase/root" >&2 - - local devnode= - local mntdir= - local IFS="$br" - for mountpoint in $list; do - installerfw_get_part_info "$mountpoint" "DEVNODE_NOW" "devnode" - mntdir="$dstbase/root$mountpoint" - - verbose "mounting \"$devnode\" under \"$mntdir\"" - mount $verbose -- "$devnode" "$mntdir" >&2 - - list_prepend "$mntdir" "unmount_list" - done -} - -# Amend the /etc/installerfw-environment file at the destination. -amend_installerfw_environment() -{ - # Most of the variables were already changed, let's take care about the - # rest. - export INSTALLERFW_INSTALLER_NAME="$PROG" - export INSTALLERFW_MOUNT_PREFIX="$dstbase/root" - - local pnum=0 - while [ "$pnum" -lt "$part_count" ]; do - eval "unset INSTALLERFW_PART${pnum}_DEVNODE" - eval "unset INSTALLERFW_PART${pnum}_DISK_DEVNODE" - pnum="$(($pnum+1))" - done - - installerfw_save_env -} - -# Check if the block device is mounted -# TODO: the much better way to do this is to use the open(2) "O_EXCL" flag -# which has special meaning for block devices. This would need to write a -# C helper program, something like setup-ivi-open-helper. -is_mounted() -{ - local devnode="$(esc_regexp "$1")" - - grep -q -e "^$devnode[p0-9]* " /proc/mounts -} - -show_usage() -{ - cat <<-EOF -Usage: $PROG [options] - -Clone a running Tizen IVI system to a different disk. The mandatory argument -"" is the device node name to clone to (e.g., /dev/sda). Be careful, -this program will destroy all the "" data! - -The program roughly works like this. - -1. Reads the "/etc/installerfw-environment" file to get information about the - partitions of the running system. -2. Partitions "" according to "/etc/installerfw-environment" (the last - partition gets re-sized to consume all the space on ""). -3. Formats all the newly created partitions on "". -4. Copies all the data from the disk Tizen IVI currently runs from to - "", partition-by-partition. -5. Configures the cloned system on "" by "setup-ivi-boot". -6. Reboots the system. - -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" - -dstdisk= -verbose= -quiet="-q" -while true; do - case "$1" in - -v|--verbose) - verbose="-v" - quiet= - ;; - --version) - printf "%s\n" "$VER" - exit 0 - ;; - -h|--help) - show_usage - exit 0 - ;; - --) shift; break - ;; - *) show_usage_fail "unrecognized option \"$1\"" - ;; - esac - shift -done - -[ "$#" -eq 1 ] || \ - show_usage_fail "please, provide exactly one \"disk\" argument" - -dstdisk="$1" -[ -b "$dstdisk" ] || \ - fatal "\"$dstdisk\" does not exist or is not a block device node" - -is_mounted "$dstdisk" && fatal "\"$dstdisk\" is mounted" - -# Load the installer framework data -if ! installerfw_available; then - installerfw_restore_env -fi - -# Install the cleanup handler (the first parameter will be our exit code) -trap 'cleanup_handler $?' EXIT -trap 'cleanup_handler 1' HUP PIPE INT QUIT TERM - -# Create our work directory -tmpdir="$(mktemp --tmpdir="/tmp" -d -t -- "$PROG.XXXX")" -verbose "tmpdir is \"$tmpdir\"" - -srcbase="$tmpdir/src" -dstbase="$tmpdir/dst" -mkdir $verbose -- "$srcbase" >&2 -mkdir $verbose -- "$dstbase" >&2 - -# Fetch some installer framework variables -installerfw_verify_defined "INSTALLERFW_PTABLE_FORMAT" -installerfw_verify_defined "INSTALLERFW_PART_COUNT" - -ptable_format="$INSTALLERFW_PTABLE_FORMAT" -part_count="$INSTALLERFW_PART_COUNT" - -# Some general checks -if [ "$ptable_format" != "gpt" ]; then - fatal "partition table type \"$ptable_format\" is not supported" -fi - -# Disable the Tizen IVI automount agent, otherwise it may start mounting the -# $dstdisk partitions that we are going to create -automount_status="$(systemctl --user is-active udisks-automount-agent 2>/dev/null ||:)" -if [ "$automount_status" = "active" ]; then - message "disabling udisks-automount-agent" - if ! systemctl --user stop udisks-automount-agent; then - warning "cannot stop udisks-automount-agent" - automount_status="dunno" - fi -fi - -# Create partitions on the destination disk -message "partitioning $dstdisk" -create_partitions - -# Make sure the device nodes are created -udevadm settle > /dev/null 2>&1 ||: - -# Find device nodes for source and destination partitions -find_devnodes - -# Format the destination partitions -message "formatting $dstdisk" -format_dst_partitions - -# Mount the source and destination partitions -mount_partitions - -# Copy all the data -message "copying all the data to $dstdisk" -copy_the_data - -# Create proper target file-system hierarchy in order to be able to execute -# installer framework scripts for the target. -create_dst_hierarchy - -message "finished copying, configuring the cloned OS" - -# Amend the /etc/installerfw-environment file on the destination -amend_installerfw_environment - -# Configure the target system -$srcdir/setup-ivi-boot $verbose - -# Note, unmount happens in 'cleanup_handler()' -message "done, synchronizing the data" -sync diff --git a/setup-ivi-clone-service b/setup-ivi-clone-service deleted file mode 100755 index 775f382..0000000 --- a/setup-ivi-clone-service +++ /dev/null @@ -1,180 +0,0 @@ -#!/bin/sh -euf - -# Copyright 2013-2014 Intel Corporation -# Author: Artem Bityutskiy -# License: GPLv2 - -PROG="setup-ivi-clone-service" -VER="1.0" - -srcdir="$(readlink -ev -- ${0%/*})" -PATH="/usr/share/setup-ivi:$srcdir:$PATH" - -if [ -f "$srcdir/setup-ivi-sh-functions" ]; then - . "$srcdir/setup-ivi-sh-functions" - . "$srcdir/installerfw-sh-functions" -else - . /usr/share/setup-ivi/setup-ivi-sh-functions - . /usr/share/setup-ivi/installerfw-sh-functions -fi - -# 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 - -# Find the first non-removable device and prints its device node name. -find_an_internal_disk() -{ - local dir - - ls -1 "/sys/block" | while IFS= read -r name; do - local removable="$(cat "/sys/block/$name/removable")" - local size="$(cat "/sys/block/$name/size")" - - if [ "$removable" -eq "0" ] && [ "$size" -ne "0" ]; then - verbose "found removable disk \"$name\"" - printf "%s" "/dev/$name" - break - fi - done -} - -# Get user-readable information about a disk. -get_disk_info() -{ - local name="${1##*/}" - local path="/sys/block/$name" - - local size="$(LC_ALL=C sed -n -e "s/[[:blank:]]*$//p" -- "$path/size")" - local info="size $(($size/2048))MiB" - - if [ -f "$path/device/vendor" ]; then - local vendor="$(LC_ALL=C sed -n -e "s/[[:blank:]]*$//p" -- \ - "$path/device/vendor")" - info="${info}, $vendor" - fi - - if [ -f "$path/device/model" ]; then - local model="$(LC_ALL=C sed -n -e "s/[[:blank:]]*$//p" -- \ - "$path/device/model")" - info="${info} $model" - fi - - printf "%s" "$info" -} - -# Get user confirmation about whether it is OK to proceed. -get_confirmation() -{ - printf "%s\n" "WARNING! All the disk data will be destroyed!" - - while true; do - printf "%s\n" "Type \"yes\" to proceed, type \"no\" to exit" - - local input - read input - - if printf "%s" "$input" | grep -q -I -e "^yes$"; then - return - elif printf "%s" "$input" | grep -q -I -e "^no$"; then - exit 0 - fi - done -} - -show_usage() -{ - cat <<-EOF -Usage: $PROG [options] - -This program is a wrapper over the 'setup-ivi-clone' program and it is intended -to be executed from a systemd service when the system boots up. - -By default, this program finds the first non-removable device in the system and -installs the OS there. However, if the 'ivi-clone-target=' kernel boot -option is present (see "/proc/cmdline"), then this program installs the OS to -the disk represented by "" (e.g., "/dev/sda"). - -The 'ivi-clone-target=autodetect' kernel option causes the default behaviour. - -Options: - -f, --force do not ask for confirmation, just proceed with cloning the OS - --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 -} - -# Parse the options -tmp=`getopt -n $PROG -o f,v,h --long force,verbose,version,help -- "$@"` || - show_usage_fail "cannot parse command-line options" -eval set -- "$tmp" - -verbose= -force= -while true; do - case "$1" in - -f|--force) - force="-f" - ;; - --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 - -[ "$#" -eq 0 ] || \ - show_usage_fail "this program does not take any arguments" - -# Sleep for a while to make sure other tasks finish and our messages appear the -# last on the console. -sleep 2 - -devnode="$(sed -n -e "s/^.*ivi-clone-target=\([^ ]\+\).*$/\1/p" /proc/cmdline)" -if [ -z "$devnode" ] || [ "$devnode" = "autodetect" ]; then - devnode="$(find_an_internal_disk)" - - [ -n "$devnode" ] || fatal "cannot find an internal disk" -fi - -# Make sure all device nodes are created -udevadm settle > /dev/null 2>&1 ||: - -[ -b "$devnode" ] || fatal "intended to clone the OS to \"$devnode\"," \ - "but it does not exist" - -disk_info="$(get_disk_info "$devnode")" -if [ -n "$disk_info" ]; then - disk_info="$devnode ($disk_info)" -else - disk_info="$devnode" -fi - -printf "%s\n" "cloning the Tizen IVI OS to \"$disk_info\"" -[ -z "$force" ] && get_confirmation -printf "%s\n" "this may take a while, be patient" - -setup-ivi-clone $verbose "$devnode" || fatal "failed to clone to $devnode" diff --git a/setup-ivi-fstab b/setup-ivi-fstab deleted file mode 100755 index c130e5f..0000000 --- a/setup-ivi-fstab +++ /dev/null @@ -1,125 +0,0 @@ -#!/bin/sh -euf - -# Copyright 2013-2014 Intel Corporation -# Author: Artem Bityutskiy -# License: GPLv2 - -PROG="setup-ivi-fstab" -VER="1.0" - -srcdir="$(readlink -ev -- ${0%/*})" -PATH="/usr/share/setup-ivi:$srcdir:$PATH" - -if [ -f "$srcdir/setup-ivi-sh-functions" ]; then - . "$srcdir/setup-ivi-sh-functions" - . "$srcdir/installerfw-sh-functions" -else - . /usr/share/setup-ivi/setup-ivi-sh-functions - . /usr/share/setup-ivi/installerfw-sh-functions -fi - -# 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 - -show_usage() -{ - cat <<-EOF -Usage: $PROG [options] - -Create the default Tizen IVI /etc/fstab file. - -Options: - -f, --force re-write /etc/fstab if it exists - -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 f,v,h --long force,verbose,version,help -- "$@"` || - show_usage_fail "cannot parse command-line options" -eval set -- "$tmp" - -force= -verbose= -while true; do - case "$1" in - -f|--force) - force="-f" - ;; - -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 - -if ! installerfw_available; then - installerfw_restore_env -fi - -fstab="$(installerfw_mnt_prefix "/etc/fstab")" - -if [ -s "$fstab" ] && [ -z "$force" ]; then - fatal "\"$fstab\" already exists, use -f to re-write it" -fi - -installerfw_verify_defined "INSTALLERFW_PART_COUNT" - -contents="# Generated by $PROG -devpts /dev/pts devpts gid=5,mode=620 0 0 -tmpfs /dev/shm tmpfs defaults 0 0 -proc /proc proc defaults 0 0 -sysfs /sys sysfs defaults 0 0" - -pnum=0 -while [ "$pnum" -lt "$INSTALLERFW_PART_COUNT" ]; do - installerfw_verify_defined "INSTALLERFW_PART${pnum}_UUID" - installerfw_verify_defined "INSTALLERFW_PART${pnum}_MOUNTPOINT" - installerfw_verify_defined "INSTALLERFW_PART${pnum}_FSTYPE" - - eval uuid="\${INSTALLERFW_PART${pnum}_UUID:-}" - eval mountpoint="\${INSTALLERFW_PART${pnum}_MOUNTPOINT:-}" - eval fsopts="\${INSTALLERFW_PART${pnum}_FSOPTS:-defaults}" - eval fstype="\${INSTALLERFW_PART${pnum}_FSTYPE:-}" - - if [ "$fstype" = "vfat" ]; then - # FAT FS's short UUID has to be uppercase - uuid="$(printf "%s" "$uuid" | tr "[:lower:]" "[:upper:]")" - else - # Normal UUID has to be lowercase - uuid="$(printf "%s" "$uuid" | tr "[:upper:]" "[:lower:]")" - fi - - contents="${contents}${br}UUID=$uuid $mountpoint $fstype $fsopts 0 0" - - pnum="$((pnum+1))" -done - -verbose "writing the followint to \"$fstab\": $contents" - -printf "%s" "$contents" > "$fstab" diff --git a/setup-ivi-sh-functions b/setup-ivi-sh-functions deleted file mode 100644 index f1aa2c6..0000000 --- a/setup-ivi-sh-functions +++ /dev/null @@ -1,135 +0,0 @@ -# Copyright 2013-2014 Intel Corporation -# Author: Artem Bityutskiy -# License: GPLv2 - -# This file contains common functions for setup-ivi-* programs - -# Own name -__PROG="$PROG:-setup-ivi-sh-functions" - -# Just a useful variable for the newline character(s) -br=" -" - -fatal() -{ - IFS= printf "%s\n" "$PROG: error: $*" 1>&2 - exit 1 -} - -warning() -{ - IFS= printf "%s\n" "$PROG: Warning!: $*" >&2 -} - -message() -{ - IFS= printf "%s\n" "$PROG: $*" -} - -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 -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" -} diff --git a/setup-scripts-boot b/setup-scripts-boot new file mode 100755 index 0000000..60b42f8 --- /dev/null +++ b/setup-scripts-boot @@ -0,0 +1,184 @@ +#!/bin/sh -euf + +# Copyright 2013-2014 Intel Corporation +# Author: Artem Bityutskiy +# License: GPLv2 + +PROG="setup-scripts-boot" +VER="1.0" + +srcdir="$(readlink -ev -- ${0%/*})" +PATH="/usr/share/setup-scripts:$srcdir:$PATH" + +if [ -f "$srcdir/setup-scripts-sh-functions" ]; then + . "$srcdir/setup-scripts-sh-functions" + . "$srcdir/installerfw-sh-functions" +else + . /usr/share/setup-scripts/setup-scripts-sh-functions + . /usr/share/setup-scripts/installerfw-sh-functions +fi + +# 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() +{ + local installdir="$bootdir/extlinux" + local extlinux="extlinux" + local output + + # 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 + verbose "installing extlinux to $bootdir, boot device node is" \ + "\"$boot_devnode\"" + mkdir -p $verbose -- "$installdir" >&2 + output="$("$extlinux" --device "$boot_devnode" -i "$installdir" 2>&1)" \ + || fatal "cannot install extlinux to \"$installdir\" (note," \ + "extlinux version 5 or greater is required)" \ + "${br}${output}" + + # 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")" + verbose "setting up MBR, writing \"$mbr_bin\" to \"$mbr_devnode\"" + output="$(dd if="$mbr_bin" of="$mbr_devnode" count=1 2>&1)" || \ + fatal "cannot install MBR, dd if=$mbr_bin of=$mbr_devnode" \ + "failed${br}${output}" + + 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")" + +if installerfw_available; then + installerfw_save_env +else + installerfw_restore_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-scripts-bootloader-conf $verbose add --force "$kernel" +done + +# Set the default kernel to the kernel with highest version +newest_kernel="$(get_newest_kernel "$bootdir")" +setup-scripts-bootloader-conf $verbose default "$newest_kernel" + +# And finally, create the /etc/fstab file +setup-scripts-fstab $verbose --force diff --git a/setup-scripts-bootloader-conf b/setup-scripts-bootloader-conf new file mode 100755 index 0000000..6c56f8b --- /dev/null +++ b/setup-scripts-bootloader-conf @@ -0,0 +1,455 @@ +#!/bin/sh -euf + +# Copyright 2013-2014 Intel Corporation +# Author: Artem Bityutskiy +# License: GPLv2 + +PROG="setup-scripts-bootloader-conf" +VER="1.0" + +srcdir="$(readlink -ev -- ${0%/*})" +PATH="/usr/share/setup-scripts:$srcdir:$PATH" + +if [ -f "$srcdir/setup-scripts-sh-functions" ]; then + . "$srcdir/setup-scripts-sh-functions" + . "$srcdir/installerfw-sh-functions" +else + . /usr/share/setup-scripts/setup-scripts-sh-functions + . /usr/share/setup-scripts/installerfw-sh-functions +fi + +# 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 + + rootdir="$(installerfw_mnt_prefix "/")" + 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] + +Add bootloader entries for kernel . + +Options: + -f, --force if bootloader entries for already exist in bootloader's + config file(s) - re-write them, if 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 default bootloader entry + setup-$boot-conf $verbose --bootdir "$bootdir" add $force \ + "$kernel" "$os_name" "$kernel" "$options" + + # Add the debug bootloader entry. If there is the "quiet" option, + # create a non-quiet configuration. + local verbose_opts="$(printf "%s" "$options" | LC_ALL=C \ + sed -e "s/[[:blank:]]\+quiet[[:blank:]]\+/ / + s/^quiet[[:blank:]]\+// + s/[[:blank:]]\+quiet$// + s/^quiet$//")" + + local debug_opts="$verbose_opts ignore_loglevel log_buf_len=2M" + local debug_opts="$debug_opts initcall_debug" + + + setup-$boot-conf $verbose --bootdir "$bootdir" add \ + $force "$kernel-debug" "Debug $os_name" \ + "$kernel" "$verbose_opts" + + # Add the clone bootloader entry, but only if the cloning tool is + # installed + if [ -f "$rootdir/usr/sbin/setup-scripts-clone" ]; then + clone_opts="$options systemd.unit=scripts-clone.service" + clone_opts="$clone_opts scripts-clone-target=autodetect" + setup-$boot-conf $verbose --bootdir "$bootdir" add \ + $force "$kernel-clone" "Clone $os_name" \ + "$kernel" "$clone_opts" + fi + + # Use default gummiboot-splash file + local splash_path="$rootdir/usr/share/gummiboot/splash.bmp" + + # Add a splash entry for fastboot testing and disable fbcon + if [ "$boot" = "gummiboot" ] && [ -f "$splash_path" ]; then + splash_opts="$options i915.fastboot=1 fbcon=map:9" + setup-$boot-conf $verbose --bootdir "$bootdir" add \ + $force --splash "$splash_path" "$kernel-splash" \ + "Splash $os_name" "$kernel" "$splash_opts" + fi +} + +# +# ----------------------------------------------------------------------------- +# The "remove" subcommand +# ----------------------------------------------------------------------------- +# + +show_remove_usage() +{ + cat <<-EOF +Usage: $PROG remove [options] + +Delete bootloader entries for kernel (only those which were previously +created with "$PROG add"). + +Options: + -f, --force do not fail if 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-debug" || \ + fatal "setup-$boot-conf failed to remove" \ + "entry \"$kernel-verbose\"" + # The "clone" entry does not necessary exist, so use --force + setup-$boot-conf $verbose --bootdir "$bootdir" \ + remove --force "$kernel-clone" || \ + fatal "setup-$boot-conf failed to remove" \ + "entry \"$kernel-clone\"" + # Ditto for "splash" + setup-$boot-conf $verbose --bootdir "$bootdir" \ + remove --force "$kernel-splash" || \ + fatal "setup-$boot-conf failed to remove" \ + "entry \"$kernel-splash\"" + + # 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 "" + 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] + +Set the default boot kernel to . If is omited, print the +current default boot kernel name. + +Options: + -f, --force do not fail if 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] [options] + +This program adds or removes a kernel to/from the bootloader configuration +file(s). This is a Tizen 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 " 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-scripts-clone b/setup-scripts-clone new file mode 100755 index 0000000..193a0c2 --- /dev/null +++ b/setup-scripts-clone @@ -0,0 +1,541 @@ +#!/bin/sh -euf + +# Copyright 2013-2014 Intel Corporation +# Author: Artem Bityutskiy +# License: GPLv2 + +PROG="setup-scripts-clone" +VER="1.0" + +srcdir="$(readlink -ev -- ${0%/*})" + +if [ -f "$srcdir/setup-scripts-sh-functions" ]; then + . "$srcdir/setup-scripts-sh-functions" + . "$srcdir/installerfw-sh-functions" +else + . /usr/share/setup-scripts/setup-scripts-sh-functions + . /usr/share/setup-scripts/installerfw-sh-functions +fi + +# 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 + +# These are used in the cleanup handler, so have to be defined before the +# function +tmpdir= +unmount_list= +automount_status= + +# Unmount all partitions which we possibly mounted +unmount_partitions() +{ + printf "%s\n" "$unmount_list" | while IFS= read -r dir; do + if [ -n "$dir" ]; then + verbose "unmount \"$dir\"" + umount $verbose -- "$dir" >&2 ||: + fi + done +} + +# This function is called on exit, crashes, interrupts, etc. We clean up +# everything here before the program is terminated +cleanup_handler() +{ + local exitcode="$1" + + # Restore the default exit handler + trap - EXIT + + verbose "cleanup and exit with code $exitcode" + + unmount_partitions + rm -r $verbose -- "$tmpdir" >&2 + + if [ "$automount_status" = "active" ]; then + message "re-enabling udisks-automount-agent" + systemctl --user start udisks-automount-agent || \ + warning "cannot start udisks-automount-agent" + fi + + exit "$exitcode" +} + +# Append a line to a list, which is just text where each line is considered to +# be an element of the list. The first parameter is the line to append, the +# second parameter is the variable name to append to (the variable is defined +# outside of this function and contains the text to prepend the line to). +list_append() +{ + local __value="$1"; shift + local __list_name="$1" + eval local "__list=\$$__list_name" + + [ -z "$__list" ] && eval "$__list_name=\"\$__value\"" || \ + eval "$__list_name=\"\${__list}\${br}\${__value}\"" +} + +# Similar to 'list_append()', but prepends a list with a line. +list_prepend() +{ + local __value="$1"; shift + local __list_name="$1" + eval local "__list=\$$__list_name" + + [ -z "$__list" ] && eval "$__list_name=\"\$__value\"" || \ + eval "$__list_name=\"\${__value}\${br}\${__list}\"" +} + +# Create partitions on the destination disk. This function also updates the +# following installer framework environment variables: +# o INSTALLERFW_PARTx_PARTUUID +# o INSTALLERFW_PARTx_TYPE_ID +create_partitions() +{ + # The GPT partition type GUID for Linux partitions + local linuxfs_type_id="0fc63daf-8483-4772-8e79-3d69d8477de4" + + verbose "destroying all partitions at \"$dstdisk\"" + sgdisk -z "$dstdisk" -- > /dev/null 2>&1 ||: + sgdisk -Z "$dstdisk" -- > /dev/null 2>&1 ||: + + # Create all partitions one-by-one + local pnum=0 + local gdisk_pnum=1 + while [ "$pnum" -lt "$part_count" ]; do + installerfw_verify_defined "INSTALLERFW_PART${pnum}_SIZE" + + eval local size="\$INSTALLERFW_PART${pnum}_SIZE" + eval local bootflag="\${INSTALLERFW_PART${pnum}_BOOTFLAG:-}" + eval local type_id="\${INSTALLERFW_PART${pnum}_TYPE_ID:-$linuxfs_type_id}" + + if [ "$gdisk_pnum" -eq "$part_count" ]; then + # Make the last partition take the rest of the space + verbose "creating the last partition $pnum" + sgdisk -n "$gdisk_pnum:+0:-1s" -- "$dstdisk" > /dev/null + else + verbose "creating partition $pnum of size $size MiB" + sgdisk -n "$gdisk_pnum:+0:+${size}M" -- "$dstdisk" > /dev/null + fi + + # Re-set the UUID + local partuuid="$(uuidgen)" + verbose "setting partition $pnum PARTUUID to $partuuid" + sgdisk -u "$gdisk_pnum:$partuuid" -- "$dstdisk" > /dev/null + + # Take care of the boot flag + if [ "$bootflag" = "True" ]; then + verbose "setting the boot flag for partition $pnum" + sgdisk -A "$gdisk_pnum:set:2" -- "$dstdisk" > /dev/null + fi + + verbose "setting partition $pnum type ID to $type_id" + sgdisk -t "$gdisk_pnum:$type_id" -- "$dstdisk" > /dev/null + + # Re-define some installer framework variables + eval "export INSTALLERFW_PART${pnum}_PARTUUID=$partuuid" + eval "export INSTALLERFW_PART${pnum}_TYPE_ID=$type_id" + + pnum="$(($pnum + 1))" + gdisk_pnum="$(($gdisk_pnum + 1))" + done +} + +# Find the device node name by its major:minor numbers ($1:$2). +find_devnode_by_nums() +{ + local major="$1"; shift + local minor="$1" + + ls -1 /dev | while IFS= read -r node; do + local ma="$(printf "%d" "0x$(stat -c '%t' -- "/dev/$node")")" + local mi="$(printf "%d" "0x$(stat -c '%T' -- "/dev/$node")")" + + if [ -b "/dev/$node" ] && [ "$ma" -eq "$major" ] && \ + [ "$mi" -eq "$minor" ]; then + printf "%s" "/dev/$node" + break + fi + done +} + +# Find the device node name by a file name. In other words, for a given file, +# fine the device node of the partition this file resides on. +find_devnode_by_file() +{ + local file="$1" + local devnum="$(stat -c '%d' -- "$file")" + local major=$((($devnum / 256) % 256)) + local minor=$(($devnum % 256)) + + find_devnode_by_nums "$major" "$minor" +} + +# Find all the source and destination device nodes and declare change the +# following installer framework environment variables: +# o INSTALLERFW_PARTx_DEVNODE_NOW +# o INSTALLERFW_PARTx_DISK_DEVNODE_NOW +# And for the source partitions, the device node names are stored in +# "srcpartX_devnode" variables (X is the partition number). +find_devnodes() +{ + # Find source device nodes + + local pnum=0 + while [ "$pnum" -lt "$part_count" ]; do + installerfw_verify_defined "INSTALLERFW_PART${pnum}_MOUNTPOINT" + + eval local mountpoint="\$INSTALLERFW_PART${pnum}_MOUNTPOINT" + local devnode="$(find_devnode_by_file "$mountpoint")" + + [ -n "$devnode" ] || fatal "cannot find device node for" \ + "source partition $mountpoint" + + verbose "source partition $mountpoint device node is: $devnode" + + eval "srcpart${pnum}_devnode=$devnode" + + pnum="$(($pnum + 1))" + done + + # Find destination device nodes + + local major="$(printf "%d" "0x$(stat -c '%t' -- "$dstdisk")")" + local minor="$(printf "%d" "0x$(stat -c '%T' -- "$dstdisk")")" + + pnum=0 + while [ "$pnum" -lt "$part_count" ]; do + local part_minor="$(($minor + $pnum + 1))" + devnode="$(find_devnode_by_nums "$major" "$part_minor")" + + [ -n "$devnode" ] || fatal "cannot find device node for" \ + "destination partition $pnum" + + verbose "destination partition $pnum device node is: $devnode" + + eval "export INSTALLERFW_PART${pnum}_DEVNODE_NOW=$devnode" + eval "export INSTALLERFW_PART${pnum}_DISK_DEVNODE_NOW=$dstdisk" + + pnum="$(($pnum + 1))" + done + +} + +# Format all the destination partitions and changes the +# "INSTALLERFW_PARTx_UUID" installer framework environment variables. +format_dst_partitions() +{ + local pnum=0 + while [ "$pnum" -lt "$part_count" ]; do + installerfw_verify_defined "INSTALLERFW_PART${pnum}_FSTYPE" + eval local fstype="\$INSTALLERFW_PART${pnum}_FSTYPE" + eval local label="\${INSTALLERFW_PART${pnum}_LABEL:-}" + eval local devnode="\$INSTALLERFW_PART${pnum}_DEVNODE_NOW" + + local uuid="$(uuidgen)" + + verbose "format partition $pnum ($devnode) with mkfs.$fstype" + + if [ "$fstype" != "vfat" ]; then + verbose "partition $pnum label is \"$label\", UUID is \"$uuid\"" + + [ -z "$label" ] || label="-L $label" + + mkfs.$fstype $verbose $quiet $label -U "$uuid" -- "$devnode" >&2 + else + # FATFS Volume ID is an XXXXXXXX (32-bit) string, where + # X is are uppercase hex digits. + uuid="$(printf "%s" "$uuid" | head -c8 | \ + tr "[:lower:]" "[:upper:]")" + + verbose "partition $pnum label is \"$label\", UUID is \"$uuid\"" + + [ -z "$label" ] || label="-n $label" + + if [ -n "$verbose" ]; then + mkfs.vfat $verbose $label -i "$uuid" -- "$devnode" >&2 + else + # mkfs.vfat does not accept -q + mkfs.vfat $label -i "$uuid" -- "$devnode" > /dev/null + fi + + # However, the installer framework variable has to have + # the XXXX-XXXX format, not XXXXXXXX. Unfortunately, + # mkfs.vfat does not like the "-", while 'mount' + # requires the "-". + uuid="$(printf "%s" "$uuid" | LC_ALL=C sed -e 's/.\{4\}/&-/')" + fi + + eval "export INSTALLERFW_PART${pnum}_UUID=$uuid" + + pnum="$(($pnum+1))" + done +} + +# Mount source and destination partition +mount_partitions() +{ + local pnum=0 + while [ "$pnum" -lt "$part_count" ]; do + eval local mountpoint="\$INSTALLERFW_PART${pnum}_MOUNTPOINT" + + # Mount the source partition + eval local devnode="\$srcpart${pnum}_devnode" + local mntdir="$srcbase/$pnum" + + verbose "mounting source partition $pnum" \ + "($devnode, $mountpoint) to $mntdir" + + mkdir -p $verbose -- "$mntdir" >&2 + mount $verbose -- "$devnode" "$mntdir" >&2 + list_prepend "$mntdir" "unmount_list" + + # Mount the destination partition + eval devnode="\$INSTALLERFW_PART${pnum}_DEVNODE_NOW" + mntdir="$dstbase/$pnum" + + verbose "mounting destination partition $pnum" \ + "($devnode, $mountpoint) to $mntdir" + + mkdir -p $verbose -- "$mntdir" >&2 + mount $verbose -- "$devnode" "$mntdir" >&2 + list_prepend "$mntdir" "unmount_list" + + pnum="$(($pnum + 1))" + done +} + +# Copy data from all the source partitions to destination partitions +copy_the_data() +{ + local pnum=0 + while [ "$pnum" -lt "$part_count" ]; do + local src_mntdir="$srcbase/$pnum" + local dst_mntdir="$dstbase/$pnum" + + verbose "copy partition $pnum:" \ + "\"$src_mntdir\" -> \"$dst_mntdir\"" + + rsync -WaHXSh --exclude "${tmpdir}" "$src_mntdir/" "$dst_mntdir/" + + pnum="$(($pnum + 1))" + done +} + +# This function creates proper target hierarchy by mounting destination +# partition under the right mount points. By the time this function is called, +# all the destination partitions are mounted under "$dstbase/$pnum", so "/boot" +# is not under "/", etc. This function mounts them under "$dstbase/root" +create_dst_hierarchy() +{ + # Create a sorted list of mount points + local list= + local mountpoint= + local pnum=0 + while [ "$pnum" -lt "$part_count" ]; do + eval mountpoint="\$INSTALLERFW_PART${pnum}_MOUNTPOINT" + list_append "$mountpoint" "list" + pnum="$(($pnum+1))" + done + + list="$(printf "%s" "$list" | sort)" + + mkdir $verbose -- "$dstbase/root" >&2 + + local devnode= + local mntdir= + local IFS="$br" + for mountpoint in $list; do + installerfw_get_part_info "$mountpoint" "DEVNODE_NOW" "devnode" + mntdir="$dstbase/root$mountpoint" + + verbose "mounting \"$devnode\" under \"$mntdir\"" + mount $verbose -- "$devnode" "$mntdir" >&2 + + list_prepend "$mntdir" "unmount_list" + done +} + +# Amend the /etc/installerfw-environment file at the destination. +amend_installerfw_environment() +{ + # Most of the variables were already changed, let's take care about the + # rest. + export INSTALLERFW_INSTALLER_NAME="$PROG" + export INSTALLERFW_MOUNT_PREFIX="$dstbase/root" + + local pnum=0 + while [ "$pnum" -lt "$part_count" ]; do + eval "unset INSTALLERFW_PART${pnum}_DEVNODE" + eval "unset INSTALLERFW_PART${pnum}_DISK_DEVNODE" + pnum="$(($pnum+1))" + done + + installerfw_save_env +} + +# Check if the block device is mounted +# TODO: the much better way to do this is to use the open(2) "O_EXCL" flag +# which has special meaning for block devices. This would need to write a +# C helper program, something like setup-scripts-open-helper. +is_mounted() +{ + local devnode="$(esc_regexp "$1")" + + grep -q -e "^$devnode[p0-9]* " /proc/mounts +} + +show_usage() +{ + cat <<-EOF +Usage: $PROG [options] + +Clone a running Tizen system to a different disk. The mandatory argument +"" is the device node name to clone to (e.g., /dev/sda). Be careful, +this program will destroy all the "" data! + +The program roughly works like this. + +1. Reads the "/etc/installerfw-environment" file to get information about the + partitions of the running system. +2. Partitions "" according to "/etc/installerfw-environment" (the last + partition gets re-sized to consume all the space on ""). +3. Formats all the newly created partitions on "". +4. Copies all the data from the disk Tizen currently runs from to + "", partition-by-partition. +5. Configures the cloned system on "" by "setup-scripts-boot". +6. Reboots the system. + +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" + +dstdisk= +verbose= +quiet="-q" +while true; do + case "$1" in + -v|--verbose) + verbose="-v" + quiet= + ;; + --version) + printf "%s\n" "$VER" + exit 0 + ;; + -h|--help) + show_usage + exit 0 + ;; + --) shift; break + ;; + *) show_usage_fail "unrecognized option \"$1\"" + ;; + esac + shift +done + +[ "$#" -eq 1 ] || \ + show_usage_fail "please, provide exactly one \"disk\" argument" + +dstdisk="$1" +[ -b "$dstdisk" ] || \ + fatal "\"$dstdisk\" does not exist or is not a block device node" + +is_mounted "$dstdisk" && fatal "\"$dstdisk\" is mounted" + +# Load the installer framework data +if ! installerfw_available; then + installerfw_restore_env +fi + +# Install the cleanup handler (the first parameter will be our exit code) +trap 'cleanup_handler $?' EXIT +trap 'cleanup_handler 1' HUP PIPE INT QUIT TERM + +# Create our work directory +tmpdir="$(mktemp --tmpdir="/tmp" -d -t -- "$PROG.XXXX")" +verbose "tmpdir is \"$tmpdir\"" + +srcbase="$tmpdir/src" +dstbase="$tmpdir/dst" +mkdir $verbose -- "$srcbase" >&2 +mkdir $verbose -- "$dstbase" >&2 + +# Fetch some installer framework variables +installerfw_verify_defined "INSTALLERFW_PTABLE_FORMAT" +installerfw_verify_defined "INSTALLERFW_PART_COUNT" + +ptable_format="$INSTALLERFW_PTABLE_FORMAT" +part_count="$INSTALLERFW_PART_COUNT" + +# Some general checks +if [ "$ptable_format" != "gpt" ]; then + fatal "partition table type \"$ptable_format\" is not supported" +fi + +# Disable the Tizen automount agent, otherwise it may start mounting the +# $dstdisk partitions that we are going to create +automount_status="$(systemctl --user is-active udisks-automount-agent 2>/dev/null ||:)" +if [ "$automount_status" = "active" ]; then + message "disabling udisks-automount-agent" + if ! systemctl --user stop udisks-automount-agent; then + warning "cannot stop udisks-automount-agent" + automount_status="dunno" + fi +fi + +# Create partitions on the destination disk +message "partitioning $dstdisk" +create_partitions + +# Make sure the device nodes are created +udevadm settle > /dev/null 2>&1 ||: + +# Find device nodes for source and destination partitions +find_devnodes + +# Format the destination partitions +message "formatting $dstdisk" +format_dst_partitions + +# Mount the source and destination partitions +mount_partitions + +# Copy all the data +message "copying all the data to $dstdisk" +copy_the_data + +# Create proper target file-system hierarchy in order to be able to execute +# installer framework scripts for the target. +create_dst_hierarchy + +message "finished copying, configuring the cloned OS" + +# Amend the /etc/installerfw-environment file on the destination +amend_installerfw_environment + +# Configure the target system +$srcdir/setup-scripts-boot $verbose + +# Note, unmount happens in 'cleanup_handler()' +message "done, synchronizing the data" +sync diff --git a/setup-scripts-clone-service b/setup-scripts-clone-service new file mode 100755 index 0000000..3702b28 --- /dev/null +++ b/setup-scripts-clone-service @@ -0,0 +1,180 @@ +#!/bin/sh -euf + +# Copyright 2013-2014 Intel Corporation +# Author: Artem Bityutskiy +# License: GPLv2 + +PROG="setup-scripts-clone-service" +VER="1.0" + +srcdir="$(readlink -ev -- ${0%/*})" +PATH="/usr/share/setup-scripts:$srcdir:$PATH" + +if [ -f "$srcdir/setup-scripts-sh-functions" ]; then + . "$srcdir/setup-scripts-sh-functions" + . "$srcdir/installerfw-sh-functions" +else + . /usr/share/setup-scripts/setup-scripts-sh-functions + . /usr/share/setup-scripts/installerfw-sh-functions +fi + +# 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 + +# Find the first non-removable device and prints its device node name. +find_an_internal_disk() +{ + local dir + + ls -1 "/sys/block" | while IFS= read -r name; do + local removable="$(cat "/sys/block/$name/removable")" + local size="$(cat "/sys/block/$name/size")" + + if [ "$removable" -eq "0" ] && [ "$size" -ne "0" ]; then + verbose "found removable disk \"$name\"" + printf "%s" "/dev/$name" + break + fi + done +} + +# Get user-readable information about a disk. +get_disk_info() +{ + local name="${1##*/}" + local path="/sys/block/$name" + + local size="$(LC_ALL=C sed -n -e "s/[[:blank:]]*$//p" -- "$path/size")" + local info="size $(($size/2048))MiB" + + if [ -f "$path/device/vendor" ]; then + local vendor="$(LC_ALL=C sed -n -e "s/[[:blank:]]*$//p" -- \ + "$path/device/vendor")" + info="${info}, $vendor" + fi + + if [ -f "$path/device/model" ]; then + local model="$(LC_ALL=C sed -n -e "s/[[:blank:]]*$//p" -- \ + "$path/device/model")" + info="${info} $model" + fi + + printf "%s" "$info" +} + +# Get user confirmation about whether it is OK to proceed. +get_confirmation() +{ + printf "%s\n" "WARNING! All the disk data will be destroyed!" + + while true; do + printf "%s\n" "Type \"yes\" to proceed, type \"no\" to exit" + + local input + read input + + if printf "%s" "$input" | grep -q -I -e "^yes$"; then + return + elif printf "%s" "$input" | grep -q -I -e "^no$"; then + exit 0 + fi + done +} + +show_usage() +{ + cat <<-EOF +Usage: $PROG [options] + +This program is a wrapper over the 'setup-scripts-clone' program and it is intended +to be executed from a systemd service when the system boots up. + +By default, this program finds the first non-removable device in the system and +installs the OS there. However, if the 'scripts-clone-target=' kernel boot +option is present (see "/proc/cmdline"), then this program installs the OS to +the disk represented by "" (e.g., "/dev/sda"). + +The 'scripts-clone-target=autodetect' kernel option causes the default behaviour. + +Options: + -f, --force do not ask for confirmation, just proceed with cloning the OS + --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 +} + +# Parse the options +tmp=`getopt -n $PROG -o f,v,h --long force,verbose,version,help -- "$@"` || + show_usage_fail "cannot parse command-line options" +eval set -- "$tmp" + +verbose= +force= +while true; do + case "$1" in + -f|--force) + force="-f" + ;; + --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 + +[ "$#" -eq 0 ] || \ + show_usage_fail "this program does not take any arguments" + +# Sleep for a while to make sure other tasks finish and our messages appear the +# last on the console. +sleep 2 + +devnode="$(sed -n -e "s/^.*scripts-clone-target=\([^ ]\+\).*$/\1/p" /proc/cmdline)" +if [ -z "$devnode" ] || [ "$devnode" = "autodetect" ]; then + devnode="$(find_an_internal_disk)" + + [ -n "$devnode" ] || fatal "cannot find an internal disk" +fi + +# Make sure all device nodes are created +udevadm settle > /dev/null 2>&1 ||: + +[ -b "$devnode" ] || fatal "intended to clone the OS to \"$devnode\"," \ + "but it does not exist" + +disk_info="$(get_disk_info "$devnode")" +if [ -n "$disk_info" ]; then + disk_info="$devnode ($disk_info)" +else + disk_info="$devnode" +fi + +printf "%s\n" "cloning the Tizen OS to \"$disk_info\"" +[ -z "$force" ] && get_confirmation +printf "%s\n" "this may take a while, be patient" + +setup-scripts-clone $verbose "$devnode" || fatal "failed to clone to $devnode" diff --git a/setup-scripts-fstab b/setup-scripts-fstab new file mode 100755 index 0000000..2f69579 --- /dev/null +++ b/setup-scripts-fstab @@ -0,0 +1,125 @@ +#!/bin/sh -euf + +# Copyright 2013-2014 Intel Corporation +# Author: Artem Bityutskiy +# License: GPLv2 + +PROG="setup-scripts-fstab" +VER="1.0" + +srcdir="$(readlink -ev -- ${0%/*})" +PATH="/usr/share/setup-scripts:$srcdir:$PATH" + +if [ -f "$srcdir/setup-scripts-sh-functions" ]; then + . "$srcdir/setup-scripts-sh-functions" + . "$srcdir/installerfw-sh-functions" +else + . /usr/share/setup-scripts/setup-scripts-sh-functions + . /usr/share/setup-scripts/installerfw-sh-functions +fi + +# 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 + +show_usage() +{ + cat <<-EOF +Usage: $PROG [options] + +Create the default Tizen /etc/fstab file. + +Options: + -f, --force re-write /etc/fstab if it exists + -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 f,v,h --long force,verbose,version,help -- "$@"` || + show_usage_fail "cannot parse command-line options" +eval set -- "$tmp" + +force= +verbose= +while true; do + case "$1" in + -f|--force) + force="-f" + ;; + -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 + +if ! installerfw_available; then + installerfw_restore_env +fi + +fstab="$(installerfw_mnt_prefix "/etc/fstab")" + +if [ -s "$fstab" ] && [ -z "$force" ]; then + fatal "\"$fstab\" already exists, use -f to re-write it" +fi + +installerfw_verify_defined "INSTALLERFW_PART_COUNT" + +contents="# Generated by $PROG +devpts /dev/pts devpts gid=5,mode=620 0 0 +tmpfs /dev/shm tmpfs defaults 0 0 +proc /proc proc defaults 0 0 +sysfs /sys sysfs defaults 0 0" + +pnum=0 +while [ "$pnum" -lt "$INSTALLERFW_PART_COUNT" ]; do + installerfw_verify_defined "INSTALLERFW_PART${pnum}_UUID" + installerfw_verify_defined "INSTALLERFW_PART${pnum}_MOUNTPOINT" + installerfw_verify_defined "INSTALLERFW_PART${pnum}_FSTYPE" + + eval uuid="\${INSTALLERFW_PART${pnum}_UUID:-}" + eval mountpoint="\${INSTALLERFW_PART${pnum}_MOUNTPOINT:-}" + eval fsopts="\${INSTALLERFW_PART${pnum}_FSOPTS:-defaults}" + eval fstype="\${INSTALLERFW_PART${pnum}_FSTYPE:-}" + + if [ "$fstype" = "vfat" ]; then + # FAT FS's short UUID has to be uppercase + uuid="$(printf "%s" "$uuid" | tr "[:lower:]" "[:upper:]")" + else + # Normal UUID has to be lowercase + uuid="$(printf "%s" "$uuid" | tr "[:upper:]" "[:lower:]")" + fi + + contents="${contents}${br}UUID=$uuid $mountpoint $fstype $fsopts 0 0" + + pnum="$((pnum+1))" +done + +verbose "writing the followint to \"$fstab\": $contents" + +printf "%s" "$contents" > "$fstab" diff --git a/setup-scripts-sh-functions b/setup-scripts-sh-functions new file mode 100644 index 0000000..7c0f239 --- /dev/null +++ b/setup-scripts-sh-functions @@ -0,0 +1,135 @@ +# Copyright 2013-2014 Intel Corporation +# Author: Artem Bityutskiy +# License: GPLv2 + +# This file contains common functions for setup-scripts-* programs + +# Own name +__PROG="$PROG:-setup-scripts-sh-functions" + +# Just a useful variable for the newline character(s) +br=" +" + +fatal() +{ + IFS= printf "%s\n" "$PROG: error: $*" 1>&2 + exit 1 +} + +warning() +{ + IFS= printf "%s\n" "$PROG: Warning!: $*" >&2 +} + +message() +{ + IFS= printf "%s\n" "$PROG: $*" +} + +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 +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" +}