HowTo

This section describes various practical aspects of the "setup-ivi" project.
Please, check further sections for the design and implementation details.

How to get the boot menu

The default Tizen IVI behaviour is to boot as quickly as possible,
so no boot menu is shown.
You have to press the "space" button during the boot process
to get the boot-loader menu.
Keep in mind that the time window when the boot-loader reads
the keyboard input is very short,
so your best bet is to press the "space" key many times at boot,
until you see the menu.

How to boot in debug mode

Tizen IVI boots with the "quiet" kernel boot argument by default,
which significantly speeds up the boot process.
The downside of this is lack of important early boot information on the console.
You can the debug boot mode to see more information on the console,
just select the "Debug" boot menu entry.
This will also add few other useful kernel debugging options.

How to change kernel boot options

Get to the boot menu.
Press the "Tab" key in case of the "extlinux" bootloader ("mbr" images)
and the "e" key in case of the "gummiboot" bootloader (efi images).

Edit the kernel boot options and press "enter".

How to clone Tizen IVI from a USB stick to the internal SSD

Get to the boot menu and select the "Clone" menu entry.
This will start the "ivi-clone" systemd service.
It will clone the Tizen IVI OS from your boot media to the first non-removable media.
All the current reference IVI hardware includes a single SSD,
so it will be picked as the destination disk for OS cloning.

How to clone Tizen IVI to any other disk

Get to the boot menu, find the "clone" menu entry, and start editing it.
You'll notice that the last kernel boot option is "ivi-clone-target=autodetect".
Remove the "autodetect" part and put the destination device node name.
For example, to clone the OS to "/dev/sdc",
put "ivi-clone-target=/dev/sdc" there.

The other (less preferable) way is to boot the Tizen IVI system, get a console,
and run "setup-ivi-clone <devnode>".

For example :

setup-ivi-clone /dev/sdc

You can use the "-v" option
to see the details of what the script is doing.

How to add a custom boot-loader menu entry

Normally, when you install a kernelRPM package,
it gets added to the boot-loader menu's list.

However, developers may compile custom kernels and manually install them to the system.
In this case one can use the "setup-ivi-bootloader-conf" script
to add the corresponding boot-loader menu entry.

For example, if the kernel binary in question is
"/boot/vmlinuz-3.12-custom+",
then the following can used.

The idea was that instead of hard-coding system-specific things to MIC,
we'd rather teach MIC invoking external programs which would know all the system specifics.

Thus, MIC is the installer, which implements the installer framework,
and invokes external programs called "installer plugins"
to do distribution-specific things like setting up the boot-loader,
or creating "/etc/fstab".
The framework allows for supplying the plugins with essential
information about partitions, device node names, etc.

At the moment the whole thing is very trivial,
and the installer framework is nothing more than a set of environment variables
starting with "INSTALLERFW_" prefix,
and installer framework plugins are nothing more than shell scripts
which are invoked from the "%post" section of the MIC kickstart files.
But the theory is that this may become fancier in the future if a need arises.

Here are the installer framework environment variables that MIC currently defines.

INSTALLERFW_KERNEL_OPTS - Kernel options from the KS file

INSTALLERFW_MOUNT_PREFIX - "/" , in case of pc-installer it will be the target disk root directory, for example "/mnt/target_system/"

INSTALLERFW_INSTALLER_NAME - "mic", in case of pc-installer it will be "pc-installer"

When a kernel RPM package is installed, the new kernel should be added to the boot-loader configuration and become the default boot kernel

When a kernel RPM package is removed, the new kernel should be removed from the boot-loader configuration and if it was the default boot kernel, an different existing kernel should become the default boot kernel.

And there are a couple of requirements to keep in mind :

It should be possible to relatively easily add a new boot-loader support or drop one of the boot-loaders.

Every kernel should have at least 3 entries in the boot menu - the default entry, the debug entry, and the clone entry (see this section). In the future we may need to add a more, and this should be relatively easy to do.

Regarding the boot menu :
we do not have any in Tizen IVI by default in order to facilitate faster boot,
but if users press special key at the right time during the boot process,
the boot-loader shows the boot menu which lists all available boot options.

At the moment, the "space" key works for both gummiboot and extlinux.

With the above in mind, we can now discuss the implementation.

Overview

The "setup-ivi" project has the following scripts related to the boot process setup.

setup-ivi-sh-functions - Just commonly used functions, no specialization

All the scripts are written in POSIX shell (no bashisms inside, tested with "dash"). The idea is that
these are essential scripts which will be required even in very very minimal configurations, so they
cannot be Python/Perl/Ruby/etc scripts. Thus, we use plain POSIX shell.

Regarding the naming. Tizen IVI-specific scripts start with "setup-ivi-", and IVI-independent ones
do not have "ivi" in the name.

The "setup-extlinux-conf" script is a generic script which manipulates the
"extlinux.conf" file. In theory, it could be part of the general "setup" package.
However, we keep it in "setup-ivi" since it only implements the minimal amount of functionality
required for the IVI setup scripts. This "setup-gummiboot-conf" story is similar.

The "setup-ivi-bootloader-conf" is IVI-specific since it makes some assumptions
which may not be necessarily hold outside of the IVI profile. For example, when adding a kernel to
the bootloader menu, it actually adds 3 records - the default, the debug, and the
"clone" one. When removing a kernel, it removes all 3 records.

All the "setup-*" scripts have support the "--help" option which provides
the usage information.

setup-ivi-boot

The "setup-ivi-boot" script is executed from the MIC kickstart file and
depending on the image type, it installs either extlinux or gummiboot to the image.
Then it creates the boot-loader configuration by invoking the
"setup-ivi-bootloader-conf" script for every kernel installed in the system.
And then it creates the "/etc/fstab" file by calling the
"setup-ivi-fstab" script.

The "setup-ivi-boot" script is an installer framework plugin,
meaning that it depends on various "INSTALLERFW_*" environment variables. This script reads
"/etc/installerfw-environment" if installer framework variables are not in the environment.
However, if they are defined in the environment, and "/etc/installerfw-environment" does
not exist, the "setup-ivi-boot" script creates "/etc/installerfw-environment"
and populates it with the data.

setup-ivi-bootloader-conf

The "setup-ivi-bootloader-conf" manipulates the boot-loader configuration.
Depending on the system, it invokes either "setup-extlinux-conf" or
"setup-gummiboot-conf" do deal with the boot-loader specifics.

Currently "setup-ivi-bootloader-conf" supports the following three commands:

Add - add a kernel to the bootloader configuration

Remove - remove a kernel from the bootloader configuration

Default - get or set the default boot kernel

The "add" command actually adds three bootloader menu entries for the kernel - the default,
debug, and "clone" entries. The difference is in the kernel boot
arguments. In all the cases the "INSTALLERFW_KERNEL_OPTS variable is used
as the base, and the debug version has the "quiet" kernel argument removed,
as well as several debug arguments like "initcall_debug" added. The "clone"
entry will be described later in this document.

The "remove" command removes all three entries.

The "default" command returns the current default boot kernel when invoked without
additional arguments, or sets the default boot kernel if it was specified.

The "setup-ivi-bootloader-conf" script used but the Tizen IVI kernel
RPM package in order to update the boot-loader configuration when a kernel RPM
is installed or removed (e.g., when doing "zypper install kernel-x86-ivi).

Namely, the "%post" section of the kernel RPM spec file has something
like this (simplified):

# Add the kernel to the bootloader menu
setup-ivi-bootloader-conf add vmlinuz-%{kernel_full_version}
# Make it to be the default boot kernel
setup-ivi-bootloader-conf default vmlinuz-%{kernel_full_version}

So what?

So these scripts nicely encapsulate all the specifics of a particular boot-loader,
hide all the related complexities, provide a framework for supporting a new boot-loader,
and provide a single place for changing the boot-loader menu. See the next section for
an example of how "setup-ivi-boot" is useful for cloning Tizen IVI from one
one disk to another.

Cloning the OS

This section describes the Tizen IVI OS cloning scripts which are also part of
the "setup-ivi" project.

Introduction

Tizen IVI is distributed in form of raw image files which can be copied to a disk,
be that an internal SSD/HDD or a USB stick. The IVI system then can boot off this
disk into the Tizen IVI OS.

Traditionally people copy Tizen IVI images to USB stick using "dd"
(slow) or "bmaptool
(fast). Then they boot the IVI system off the USB stick and work with the OS this way.

The problem is that USB sticks are usually a lot slower than the internal disk, and there
is no easy way of installing the OS to the internal disk (we use SSDs, so I'll refer the
internal disk as SSD in this document). In order to install the OS to the internal SSD,
people usually have to first copy the image to a USB stick, than mount the USB stick
on the host, copy the image file to one of the Tizen IVI partitions, unmount, boot
the IVI system off the USB stick, and then copy the image file to the internal SSD.

It becomes a lot more inconvenient if you need to modify the OS, and then deploy it
to several IVI systems (e.g., for making a Tizen IVI demo).

The 'setup-ivi-clone' script is created to close this gap and simplify the process of
installing the Tizen IVI system to the internal SSD.

Overview

The "setup-ivi" project has the following scripts related to OS cloning.

setup-ivi-clone - implements most of the cloning logic

setup-ivi-clone-service - a wrapper over setup-ivi-clone which is intended to run as a systemd service early at boot

And just like the boot setup scripts, the cloning scripts use the following
common files: installerfw-sh-functions and setup-ivi-sh-functions.

Similarly, the scripts support the "--help option which provides
usage information.

The cloning scripts have IVI-specific logic, so they contain "ivi" in their names.

setup-ivi-clone

The "setup-ivi-clone" script clones the currently running Tizen IVI
OS to a different disk. For example, the following command installs the OS to
"/dev/sda", which is usually the internal SSD.

setup-ivi-clone /dev/sda

It is possible to clone from SSD to an USB stick, or from USB stick to another
USB stick, and so on. The cloning may be chained, so that you clone from disk A
to disk B, then from disk B to disk C, and so on.

It is OK to first configure the OS (e.g., setup proxies, networking, prepare
a demo), and then clone it to one or several IVI systems. The cloned system
will contain all the changes.

Similarly to "setup-ivi-boot", "setup-ivi-clone"
is an installer framework plugin, so it requires various
installer framework environment variables to be defined.

But "setup-ivi-clone" is also an installer, because at some stage
it sets up it own installer framework environment and executes installer framework
scripts like "setup-ivi-boot". See step number 7 below for more
details.

Below is a step-by-step description of how "setup-ivi-clone" works.

1. Get the installer framework environment variables

First of all, "setup-ivi-clone" checks if the installer framework
environment variable are defined, and if no, it reads the
"/etc/installerfw-environment" file.

2. Partition the destination disk

The next step is partitioning the destination disk ("/dev/sda" in the
example above). The script takes a simple approach and just uses the installer
framework information for this purpose (e.g., "INSTALLERFW_PART_COUNT",
"INSTALLERFW_PARTx_SIZE", etc). The last partition is always resized
to cover the rest of the space on the destination disk.

Note, the destination disk and partitions UUIDs are randomly generated, so the
"INSTALLERFW_PARTx_UUID" and "INSTALLERFW_PARTx_PARTUUID"
variables are not used.

The reason for this is that we use UUIDs in "/etc/fstab" and in the kernel
options, so when there are 2 different block devices or file-systems with the same UUID,
it becomes not very predictable which one will be mounted.

3. Format the destination partitions

Then next step is formatting the destination partitions using tools like
"mkfs.ext4", depending on "INSTALLERFW_PARTx_FSTYPE".

4. Mount all partitions

All the source and destination partitions are mounted under a temporary directory
(something like "/tmp/<random_name>/src/1" for the source partition number
1 and "/tmp/<random_name>/dst/1" for the destination partition number 1).

Note, the source partitions are already mounted under "/", "/boot",
and so on. However, it is very convenient to have them mounted uder separate sub-directories
at this stage. For example, the script does not have to care about things like virtual
file-systems mounted under "/proc", etc.

The "INSTALLERFW_PARTx_SIZE" installer framework variable is very handy at
at this stage.

5. Copy all the data

All data from source partitions are copied to the destination partitions using
"rsync". The "/tmp/<random_name>" temporary directory
is excluded from copying.

Unfortunately, this is not the last step, because there are certain files on the
destination file-systems which have to be amended. For example, the
"/etc/fstab" file. This is taken care of at the following steps.

6. Mounting destination partitions hierarchically

The destination partitions are mounted under another temporary directory, but this time
hierarchically. This means that the root partition is mounted under something like
"/tmp/<random_name>/dst/root", the boot partition is mounted under
"/tmp/<random_name>/dst/root/boot", etc. The hierarchy is derived from
the installer framework variables.

At the end of this step we have the destination partitions mounted the same way they
are mounted when the system boots off the destination disk.

7. Turning into an installer

The "setup-ivi-clone" script starts as an installer framework plugin, and
uses the "/etc/installerfw-environment" data. But at this stage, it
changes the installer framework variables to match the target system, and becomes
an installer. Namely, the script performs the following steps.

Update UUID-related environment variables ("INSTALLERFW_PARTx_UUID" and "INSTALLERFW_PARTx_PARTUUID") with new data which match the destination partitions and file-systems

Set the "INSTALLERFW_MOUNT_PREFIX" variable to the destination system root directory ("/tmp/<random_name>/dst/root")

Save the updated environment at the destination disk (at "/tmp/<random_name>/dst/root/etc/installerfw-environment")

8. Configuring the target system

Run the "setup-ivi-boot" script which will configure the target system,
because the installer framework environment is set up so that it matches the target
system, not the source system. This will install and configure the boot-loader,
create the "fstab" file, etc.

9. Clean-up and exit

Everything is unmounted, temporary data are removed. Note, the script also gracefully
cleans everything up on failure, interrupt, etc.

Caveats

One of the caveats is the "udisks-automount-agent" deamon. If you clone the system
to a removable media like an USB stick. The problem is that when you plug the destination
USB stick, "udisks-automount-agent" mounts it, which makes "setup-ivi-clone"
fail.

The other caveat is that when "setup-ivi-clone" partitions the USB stick,
"udisks-automount-agent" mounts new partitions again, and cloning fails.

Thus, when cloning the OS to a removable media with "setup-ivi-clone",
please, stop the "udisks-automount-agent" service:

systemctl --user stop udisks-automount-agent

Integration with systemd

The "setup-ivi" project provides the "ivi-clone.service" systemd unit which
implement the OS cloning service. This service is not executed during "normal" system
startup.

The current expected way to execute it is to add the
"systemd.unit=ivi-clone.service" kernel boot option. And this is exactly
what the "clone" boot menu entry does (see here).

setup-ivi-clone-service

The "setup-ivi-clone-service" script is a rather simple wrapper over
"setup-ivi-clone". This script implements the "ivi-clone"
systemd service, and it is started from the "ivi-clone.service" systemd
unit very early at boot.

The default "setup-ivi-clone-service" behaviour is to find the first
non-removable media and pass it to "setup-ivi-clone" as the destination
device. In case of IVI systems this results in cloning the OS to the internal
SSD.

The "setup-ivi-clone-service" script checks for the
"ivi-clone-target=<devnode>" kernel option and if it is present,
it clonse the OS to <devnode>, e.g., "/dev/sde". The
special "autodetect" keyword causes the default behaviour described above.

The "setup-ivi-clone-service" script also warns the user about
the fact that the destination disk data will be destroyed and requires user's
confirmation.