IVI/artem-setup-ivi

From Tizen Wiki
< IVI
Jump to: navigation, search

Summary

The "setup-ivi" project contains various early Tizen IVI setup scripts like installing and configuring the boot-loader.

The original author of wiki this page is Artem Bityutskiy <artem.bityutskiy@linux.intel.com>.


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 kernel RPM 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.

setup-ivi-bootloader-conf --help      # Optionally check help text
setup-ivi-bootloader-conf add --help  # Optionally check help text for the "add" command
setup-ivi-bootloader-conf add vmlinuz-3.12-custom+


Installer framework

This section describes the "installer framework" concept because it is required for understanding of how "setup-ivi" is implemented.

Installer framework is something that was initially created to improve MIC ( https://source.tizen.org/documentation/articles/mic-image-creator ), which was hard-coded to install the extlinux boot-loader to images it generated.

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"
  • INSTALLERFW_PTABLE_FORMAT - "msdos" or "gpt"
  • INSTALLERFW_PART_COUNT - Count of partitions
  • For every partition x (from 0 to INSTALLERFW_PART_COUNT-1)
    • INSTALLERFW_PARTx_FSTYPE - "ext4", "btrfs", "vfat", etc (must be suitable for the "mount" tool)
    • INSTALLERFW_PARTx_FSOPTS - File-system mount options (must be suitable for the "mount" tool)
    • INSTALLERFW_PARTx_UUID - File-system UUID
    • INSTALLERFW_PARTx_BOOTFLAG - Whether the partition has the "boot" flag set, "True" of "False"
    • INSTALLERFW_PARTx_PARTUUID - Partition UUID (GUID) in case of the GPT partition table
    • INSTALLERFW_PARTx_SIZE - Partition size in MiB (1024*1024 bytes)
    • INSTALLERFW_PARTx_MOUNTPOINT - Partition mount-point relative to INSTALLERFW_MOUNT_PREFIX
    • INSTALLERFW_PARTx_DEVNODE - Device node of the partition (invalid in the installer environment, but supposed to be valid in the OS environment when it actually runs)
    • INSTALLERFW_PARTx_DISK_DEVNODE - Device node of the entire disk the partition belongs to (invalid in the installer environment, but supposed to be valid in the OS environment when it actually runs)
    • INSTALLERFW_PARTx_DEVNODE_NOW - Device node of the partition (valid only in the installer environment, invalid in the actual OS environment)
    • INSTALLERFW_PARTx_DISK_DEVNODE_NOW - Device node of the entire disk the partition belongs to (valid only in the installer environment, invalid in the actual OS environment)
    • INSTALLERFW_PARTx_LABEL - File-system label
    • INSTALLERFW_PARTx_TYPE_ID - File-system type GUID in case of GPT partitions
    • INSTALLERFW_PARTx_ALIGN - Partition alignment in KiB (1024 bytes)

The installer does not have to be MIC.

Another example of the installer is the "setup-ivi-clone" program.


/etc/installerfw-environment

In Tizen IVI we save some of the installer framework environment variables in the "/etc/installerfw-environment" file.

This makes it simpler to get information about the image in the actual OS environment (when running the image).

This also makes it possible to re-create things like "/etc/fstab" at any point.

Only those environment variables are saved in "/etc/installerfw-environment", which make sense outside of the installer environment.

Here is the full list :

  • INSTALLERFW_KERNEL_OPTS
  • INSTALLERFW_PARTx_ALIGN
  • INSTALLERFW_PARTx_BOOTFLAG
  • INSTALLERFW_PARTx_FSOPTS
  • INSTALLERFW_PARTx_FSTYPE
  • INSTALLERFW_PARTx_LABEL
  • INSTALLERFW_PARTx_MOUNTPOINT
  • INSTALLERFW_PARTx_PARTUUID
  • INSTALLERFW_PARTx_SIZE
  • INSTALLERFW_PARTx_TYPE_ID
  • INSTALLERFW_PARTx_UUID
  • INSTALLERFW_PART_COUNT
  • INSTALLERFW_PTABLE_FORMAT
  • INSTALLERFW_INSTALLER_NAME

Bootloader setup

This section describes the boot-loader setup scripts, which are part of the "setup-ivi" project.


Introduction

At the moment Tizen IVI is distributed in two different forms : "efi" and "mbr" images.

Efi images are supposed to be used on EFI systems, and mbr images are for legacy BIOS systems.

We use the "gummiboot" boot-loader in efi images and the "extlinux" boot-loader in mbr images.

These two boot-loaders have very different configuration file formats, and should be installed differently.

Here is a list of tasks we have to do at various points :

  • MIC should correctly install the boot-loader to the image
  • 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-extlinux-conf - Understands the extlinux configuration file format, can add or remove records to the extlinux boot menu, etc
  • setup-gummiboot-conf - Similar, but for the gummiboot boot-loader
  • setup-ivi-bootloader-conf - Can add/remove/etc kernel records to the boot-loader boot menu irrespectively of its type
  • setup-ivi-fstab - Creates the "/etc/fstab" file
  • setup-ivi-boot - Makes sure the system becomes bootable (installs and confugures the boot-loader, etc)

And there are two more files which contain common functions which are used by the above scripts.

  • installerfw-sh-functions - Manipulating the installer framework data
  • 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}

Similarly, the "%postun" section contains:

# Remove the kernel from the bootloader menu
setup-ivi-bootloader-conf remove 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
  • ivi-clone.service - the systemd unit file which executes setup-ivi-clone-service

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.

  1. Update UUID-related environment variables ("INSTALLERFW_PARTx_UUID" and "INSTALLERFW_PARTx_PARTUUID") with new data which match the destination partitions and file-systems
  2. Set the "INSTALLERFW_MOUNT_PREFIX" variable to the destination system root directory ("/tmp/<random_name>/dst/root")
  3. 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.