Search by Tags

Linux - Booting

 

Article updated at 19 Jul 2022
Compare with Revision




Introduction

In order to boot a linux image on any of the supported modules, three elements are required:

  • A bootloader (we use an extended version of U-Boot)
  • A linux kernel (and additionally the corresponding device trees)
  • A root filesystem with the OS files, binaries and libraries

In a standard scenario, all of these elements are stored in the flash memory of the device. The bootloader is already configured through environment variables to automatically load the kernel from its memory location in flash. The bootloader also passes the memory addresses of the device trees and the root filesystem as well as any extra parameters to the kernel before handing over control to it. This is how our images are set up by default and no further configuration is needed for these cases. However, it is possible for each of the elements to be stored in separate media. For instance, U-boot could be stored either in flash memory, an SD card or a USB memory stick. The kernel could be stored either in flash memory, an SD card, a USB memory stick or remotely in a TFTP server. Finally, the root filesystem could be stored either in flash memory, an SD card, a USB memory stick or remotely in a TFTP server or a NFS server.

There are combinations of these element locations that are commonly used for different purposes:

  • Everything in flash. This is the standard configuration for production and testing
  • U-Boot in flash, kernel and rootfs in a SD card / USB / SATA drive. This configuation is used for kernel/application development and debugging in isolated or offline systems. It is also helpful for systems with scarce resources (e.g. low flash capacity)
  • U-Boot in flash, kernel in a remote TFTP server and rootfs in a remote NFS server. This configuation is common for kernel/application development and debugging from a connected host machine

In this article we describe how to set up each of the above scenarios, as well as certain eMMC booting configurations. We also comment (and refer to) the Distro Boot way to boot.

Requirements

In order to set up the different boot scenarios, it is important to understand how to enter the U-Boot console and modify and store the environment variables that tell the bootloader how to find and load the rest of the elements. This is explained in U-Boot.

Boot Scenarios

U-Boot, Kernel and Rootfs in Flash

This is the standard configuration and the one which all our images default to. The variable bootcmd is properly set to load the kernel and pass the addresses of the device trees and the root filesystem, as well as additional kernel command line arguments. After installing an image (ideally through the Toradex Easy Installer) in any of our supported modules the booting sequence will automatically proceed.

U-Boot in Flash, Kernel and Rootfs in SD Card / USB / SATA drive

In order to boot the kernel and root filesystem from a removable media such an SD card, a USB stick or a SATA hard drive, refer to the article on how to Boot From an SD Card.

Note: SATA is not supported in the Toradex-provided bootloader. Supporting SATA boot will require a modified U-Boot and this functionality has not been validated by Toradex.

U-Boot in Flash, Kernel in TFTP server and Rootfs from NFS server

In order to boot the kernel from a remote TFTP server and retrieve the root filesystem from a remote NFS server refer to the article on how to Boot From a TFTP/NFS Server

Additional Configuration

Changing the Default Boot Scenario

After a timeout U-Boot automatically executes the statements stored in the environment variable bootcmd. By default this loads the kernel and rootfs from the internal Flash storage. Thus, if you want to boot with an alternative configuration, you usually have to stop autoboot manually and run the corresponding variable for your boot configuration (e.g. run nfsboot or run sdboot). If you want to make this configuration the default booting method, simply overwrite the bootcmd variable with your alternative command. For example,

setenv bootcmd 'run sdboot'
saveenv

USB High Speed

To enable USB high speed have a look here: USB 2.0 High Speed (480Mbps)

Ethernet MAC Address

If no environment variable ethaddr exists the Ethernet MAC address is read from the Config Block, a data structure shared with WinCE that contains information written during manufacturing and configuration for the WinCE boot loader. If you want to force an Ethernet MAC address of your own simply modify the ethaddr environment variable.

Tegra2 # setenv ethaddr 00:01:02:03:04:05
Tegra2 # saveenv

Distro Boot

Distro Boot is an attempt to standardize a way for OS distributions to boot in a board-agnostic manner. When Distro Boot is enabled in U-Boot, you can boot any supported distribution for your platform simply by placing an image in a conveniently partitioned removable device with the corresponding boot configuration file. A use case for Toradex could be booting a Toradex Easy Installer image to make an upgrade of your system. Refer to the Distro Boot article for detailed information on how to use this feature.

Note: The previous Boot Scenarios can work with or without Distro Boot, as the latter is simply a standardized way to provide the link between the firmware (U-Boot) and the OS via configuration files.

eMMC Fast Boot Mode (Apalis/Colibri iMX6)

The Embedded Multi Media Card Specification (eMMC 4.3) adds a fast boot feature during the ROM stages that requires hardware support. The iMX6 family of SoCs provides it. Not only does the eMMC fast boot mode allow for faster booting but it also proves more robust across various operating conditions.

Our Embedded Linux BSP V2.6b1 release automatically migrates to eMMC fast boot mode when updating. Since these images need an updated U-Boot, images can not directly be downgraded anymore! Otherwise no further manual actions are needed. This section provides detailed about the eMMC fast boot mode in case custom migration/scripts are necessary.

In a not yet migrated module the fuse 0 5 has the value 00005062:

Apalis iMX6 # fuse sense 0 5
Sensing bank 0:
Word 0x00000005: 00005062

The eMMC fast boot mode can be enabled as a one-time-only fuse setting on the i.MX 6 SoC side and this mode requires an updated U-Boot to avoid a boot hang:

Apalis iMX6 # fuse prog 0 5 0x00005072
Programming bank 0 word 0x00000005 to 0x00005072...
Warning: Programming fuses is an irreversible operation!
This may brick your system.
Use this command only if you are sure of what you are doing!
Really perform this fuse programming? <y/N>

Please note that for an unattended update procedure one could avoid the confirmation question by adding an additional -y argument (e.g. fuse prog -y 0 5 0x00005072).

Please pay attention to the following:

  • Programming the i.MX 6 SoC fuses is an irreversible operation!
  • Both the i.MX 6 SoC as well as the eMMC have to be configured to the exact same matching boot settings, otherwise booting will fail!
  • On the eMMC side one has to configure the hardware boot area partition settings as outlined below. So far none of our BSPs configures those settings!
  • The boot loader has to be programmed into the hardware boot area partition as automatically done since BSP V2.5 beta 2 and as outlined below. This implies that one can not easily downgrade to a BSP before V2.5 beta 2. But remember a yet unpublished U-Boot boot loader is anyway required!
  • To allow for seamless use of hardware/software system resets together with the eMMC fast boot mode one has to enable the eMMC hardware reset as well like outlined further below.

eMMC Hardware Boot Area Partitions (Apalis/Colibri iMX6 and Apalis/Colibri T30)

As part of our Embedded Linux BSPs V2.5b2 (released on November 6, 2015) we unified the way all our modules with eMMC flashes are booting:

  • U-Boot now supports eMMC boot support commands (e.g. mmc bootbus and partconf).
  • U-Boot is now booted off the primary eMMC hardware boot area partition (e.g. /dev/mmcblk0boot0 in Linux).
  • The U-Boot environment is located at the end of the primary eMMC hardware boot area partition just before the config block (see below).
  • The Toradex factory configuration block (e.g. containing the serial number used for the MAC address) is located in the very last block thereof.
  • When updating from an older BSP version the config block is migrated to its new location and the relevant changes to the eMMC's configuration are done.

Boot Area Partitions Technical Background

Some pointers to further reading and how one can examine and alter the involved eMMC configuration from Linux or U-Boot.

A good overview about the thematic can be found in Micron’s TN-FC-06: Booting from Embedded MMC (e.MMC) - JEDEC v. 4.41.

Which supersedes TN-29-18.

Which in term supersedes TN-52-06.

As follows the relevant EXT_CSD registers:

BOOT_BUS_WIDTH Register (EXT_CSD [177]) = 0x16 (needed to set DDR mode and ACK at boot)
PARTITION_CONFIG Register (EXT_CSD [179]) = 0x48 (needed to enable booting from boot partition)

Boot Area Partitions Linux

Booting from boot partition disabled:

root@colibri-imx6:~# cat /sys/kernel/debug/mmc0/ios
clock: 52000000 Hz
actual clock: 49500000 Hz
vdd: 21 (3.3 ~ 3.4 V)
bus mode: 2 (push-pull)
chip select: 0 (don't care)
power mode: 2 (on)
bus width: 3 (8 bits)
timing spec: 7 (sd uhs DDR50)
signal voltage: 0 (3.30 V)
root@apalis-imx6:~# mmc extcsd read /dev/mmcblk0 | grep -e BOOT_INFO -e BOOT_SIZE_MULTI -e PARTITION_CONFIG -e BOOT_BUS_CONDITIONS
Boot Information [BOOT_INFO: 0x07]
Boot partition size [BOOT_SIZE_MULTI: 0x10]
Boot configuration bytes [PARTITION_CONFIG: 0x00]
Boot bus Conditions [BOOT_BUS_CONDITIONS: 0x00]

Former BSPs still allowed accessing the same via sysfs interface:

root@colibri-imx6:~# cat /sys/devices/soc0/soc.0/2100000.aips-bus/2198000.usdhc/mmc_host/mmc0/mmc0\:0001/boot_info
[ 1502.828197] mmc0: BKOPS_EN bit is not set
boot_info:0x07;
ALT_BOOT_MODE:1 - Supports alternate boot method
DDR_BOOT_MODE:1 - Supports alternate dual data rate during boot
HS_BOOTMODE:1 - Supports high speed timing during boot
boot_size:4096KB
boot_partition:0x00;
BOOT_ACK:0 - No boot acknowledge sent
BOOT_PARTITION-ENABLE: 0 - Device not boot enabled
boot_bus:0x00
BOOT_MODE:0 - Use single data rate + backward compatible timings in boot operation
RESET_BOOT_BUS_WIDTH:0 - Reset bus width to x1, single data rate and backwardcompatible timings after boot operation
BOOT_BUS_WIDTH:0 - x1 (sdr) or x4 (ddr) bus width in boot operation mode

For i.MX6 based modules, migrating to booting off the primary hardware boot area partition incl. flashing a new U-Boot there:

root@colibri-imx6:~# echo 0 > /sys/block/mmcblk0boot0/force_ro
root@colibri-imx6:~# dd if=u-boot.imx of=/dev/mmcblk0boot0 bs=512 seek=2
[ 222.394014] mmcblk0boot0: unknown partition table
598+0 records in
598+0 records out
root@colibri-imx6:~# echo 1 > /sys/block/mmcblk0boot0/force_ro
root@apalis-imx6:~# mmc bootpart enable 1 1 /dev/mmcblk0
root@apalis-imx6:~# mmc bootbus set single_hs x1 x8 /dev/mmcblk0
Changing ext_csd[BOOT_BUS_CONDITIONS] from 0x00 to 0x0a

Former BSPs still allowed accessing the same via sysfs interface:

root@colibri-imx6:~# echo 10 > /sys/devices/soc0/soc.0/2100000.aips-bus/2198000.usdhc/mmc_host/mmc0/mmc0\:0001/boot_bus_config
root@colibri-imx6:~# echo 8 > /sys/devices/soc0/soc.0/2100000.aips-bus/2198000.usdhc/mmc_host/mmc0/mmc0\:0001/boot_config

Booting from boot partition enabled:

root@apalis-imx6:~# mmc extcsd read /dev/mmcblk0 | grep -e BOOT_INFO -e BOOT_SIZE_MULTI -e PARTITION_CONFIG -e BOOT_BUS_CONDITIONS
Boot Information [BOOT_INFO: 0x07]
Boot partition size [BOOT_SIZE_MULTI: 0x10]
Boot configuration bytes [PARTITION_CONFIG: 0x48]
Boot bus Conditions [BOOT_BUS_CONDITIONS: 0x0a]

Former BSPs still allowed accessing the same via sysfs interface:

root@colibri-imx6:~# cat /sys/devices/soc0/soc.0/2100000.aips-bus/2198000.usdhc/mmc_host/mmc0/mmc0\:0001/boot_info
[ 76.145225] mmc0: BKOPS_EN bit is not set
boot_info:0x07;
ALT_BOOT_MODE:1 - Supports alternate boot method
DDR_BOOT_MODE:1 - Supports alternate dual data rate during boot
HS_BOOTMODE:1 - Supports high speed timing during boot
boot_size:4096KB
boot_partition:0x48;
BOOT_ACK:1 - Boot acknowledge sent during boot operation
BOOT_PARTITION-ENABLE: 1 - Boot partition 1 enabled
boot_bus:0x0a
BOOT_MODE:1 - Use single data rate + high speed timings in boot operation mode
RESET_BOOT_BUS_WIDTH:0 - Reset bus width to x1, single data rate and backwardcompatible timings after boot operation
BOOT_BUS_WIDTH:2 - x8 (sdr/ddr) bus width in boot operation mode

Note: Please pay attention to the following:

  • Changing boot_config takes effect immediately and does not require any power-cycle or the like.
  • Setting boot_partition back to 0x00 actually allows switching back to our current way of booting.
  • By default eMMC boot partitions are read-only and disabling via force_ro is only temporary and does not persist.
  • The Toradex Easy Installer does this configuration in a so-called wrap-up script.
  • Linux kernels used in later BSPs do no longer allow accessing the boot_info via sysfs and you may use the mmc binary from the mmc-utils-cos package instead. Syntax is compatible to the U-Boot mmc command as explained below.

Boot Area Partitions U-Boot

Enable boot partition from within U-Boot (requires enabling CONFIG_SUPPORT_EMMC_BOOT first):

mmc bootbus dev boot_bus_width reset_boot_bus_width boot_mode
- Set the BOOT_BUS_WIDTH field of the specified device

Configure the eMMC to 8-bit, reset bus width settings to default after boot operation, single data rate and high-speed timings in boot operation mode:

Colibri iMX6 # mmc bootbus 0 2 0 1
mmc partconf dev boot_ack boot_partition partition_access
- Change the bits of the PARTITION_CONFIG field of the specified device

Enable booting from the (hardware) boot area partition 1 and the boot acknowledge to be sent during boot operation:

Colibri iMX6 # mmc partconf 0 1 1 0

Resetting to old behaviour:

Colibri iMX6 # mmc bootbus 0 0 0 0
Colibri iMX6 # mmc partconf 0 0 0 0

eMMC Hardware Reset (Apalis/Colibri iMX6)

By default the eMMC hardware reset signal RST_n is not enabled. Whether or not it should be permanently disabled or enabled can be configured one-time-only from within U-Boot:

mmc rst-function dev value
- Change the RST_n_FUNCTION field of the specified device
WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.

The following one-time-only setting permanently enables the eMMC hardware reset signal:

Colibri iMX6 # mmc rst-function 0 1

Or from within Linux:

root@apalis-imx6:~# mmc hwreset enable /dev/mmcblk0