U-Boot overview

Revision as of 14:59, 5 August 2019 by Registered User (→‎U-Boot phases)

1. Das U-Boot[edit source]

Das U-Boot (universal bootloader or U-Boot) is an open-source bootloader that can be used on ST boards to initialize the platform and load the Linux® kernel.

  git clone https://gitlab.denx.de/u-boot/u-boot.git

Read the README file before starting using U-Boot. It covers the following topics:

  • source file tree structure
  • description of CONFIG defines
  • instructions for building U-Boot
  • brief description of the Hush shell
  • list of common environment variables

2. U-Boot overview[edit source]

Zoom out to STM32MPU Embedded Software

The same U-Boot source can generate two pieces of firmware used in SPL and U-Boot STM32 MPU boot chain:

  • Trusted boot chain: TF-A as FSBL and U-Boot as SSBL
  • Basic boot chain: SPL as FSBL and U-Boot as SSBL


Warning white.png Warning
The basic boot chain cannot be used for product development (see Boot chains overview for details).

It is provided only as an example of the simplest SSBL and to support upstream U-Boot development. However, several known limitations have been identified when SPL is used in conjunction with the minimal secure monitor provided within U-Boot for basic boot chain. They apply to:

  • power
  • secure access to registers
  • limited features (STM32CubeProgrammer / boot from NAND Flash memory).

No fix is planned for these limitations.

2.1. SPL: FSBL for basic boot[edit source]

The U-Boot SPL or SPL is the first stage bootloader (FSBL) for the basic boot chain.
It is a small binary (bootstrap utility) generated from the U-Boot source and stored in the internal limited-size embedded RAM. SPL main features are the following:

  • It is loaded by the ROM code.
  • It performs the initial CPU and board configuration (clocks and DDR memory).
  • It loads the SSBL (U-Boot) into the DDR memory.

2.2. U-Boot: SSBL[edit source]

U-Boot is the default second-stage bootloader (SSBL) for STM32 MPU platforms. It is used both for trusted and basic boot chains. SSBL main features are the following:

  • It is configurable and expendable.
  • It features a simple command line interface (CLI), allowing users to interact over a serial port console.
  • It provides scripting capabilities
  • It loads the kernel into RAM and gives control to the kernel
  • It manages several internal and external devices such as NAND and NOR Flash memories, Ethernet and USB.
  • It supports the following features and commands:
    • File systems: FAT, UBI/UBIFS, JFFS
    • IP stack: FTP
    • Display: LCD, HDMI, BMP for splashcreen
    • USB: host (mass storage) or device (DFU stack)

2.3. SPL phases[edit source]

SPL executes the following main phases in SYSRAM:

  • board_init_f(): driver initialization including DDR initialization (mininimal stack and heap: CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN)
  • configuration of heap in DDR memory (CONFIG_SPL_SYS_MALLOC_F_LEN)
  • board_init_r(): initialization of the other drivers activated in the SPL device tree
  • loading and execution of U-Boot (or Kernel in Falcon mode[1]: README.falcon ).

2.4. U-Boot phases[edit source]

U-Boot executes the following main phases in DDR memory:

  • Pre-relocation initialization (common/board_f.c): minimal initialization (such as CPU, clock, reset, DDR and console) running at the CONFIG_SYS_TEXT_BASE load address.
  • Relocation: copy of the code to the end of DDR memory.
  • Post-relocation initialization:(common/board_r.c): initialization of all the drivers.
  • Command execution through autoboot (CONFIG_AUTOBOOT) or console shell
    • Execution of the boot command (bootcmd=CONFIG_BOOTCOMMAND by default):
      for example, execute the command 'bootm' to:
      • Image loading and checking (such as kernel, device tree and ramdisk)
      • Fixup of the kernel device tree
      • Secure monitor installation (optional)
      • Control passing to the Linux kernel (or to another target application)

3. U-Boot configuration[edit source]

The U-Boot binary configuration is based on

  • DeviceTree = U-Boot and SPL binaries include a device tree blob which is parsed at run time

All the configuration flags (CONFIG_) are described in the source code: the README file or documentation directory
example: CONFIG_SPL => activate the SPL compilation.
Hence to compile U-Boot, you need to select the <target> and the device tree for the board to select a predefined configuration.
See #U-Boot_build for examples.

3.1. Kbuild[edit source]

The U-Boot build system is based on configuration symbols as the kernel (defined in Kconfig files), and selected values are stored in a .config file in the build directory, with the same makefile target.

  • select pre-defined configuration (defconfig file, in configs directory ) and generate the first .config
  make <config>_defconfig
  • change U-Boot compile configuration (modify .config) using one of the 5 make command
  make menuconfig --> menu based program
  make config  --> line-oriented configuration
  make xconfig --> QT program[2]
  make gconfig --> GTK program
  make nconfig --> ncurse menu based program

You can then compile U-Boot with the updated .config.

Warning: modification is only done locally in the build directory, it is lost after a "make distclean"

So if you want to use your configuration as defconfig:

   make savedefconfig

This target saves the current config as a defconfig file in the build directory, and can be compared with the predefined configuration (configs/stm32mp*defconfig).

The other makefile targets are :

  make help
 ....
 Configuration targets:
   config	  - Update current config utilising a line-oriented program
   nconfig         - Update current config utilising a ncurses menu based
                     program
   menuconfig	  - Update current config utilising a menu based program
   xconfig	  - Update current config utilising a Qt based front-end
   gconfig	  - Update current config utilising a GTK+ based front-end
   oldconfig	  - Update current config utilising a provided .config as base
   localmodconfig  - Update current config disabling modules not loaded
   localyesconfig  - Update current config converting local mods to core
   defconfig	  - New config with default from ARCH supplied defconfig
   savedefconfig   - Save current config as ./defconfig (minimal config)
   allnoconfig	  - New config where all options are answered with no
   allyesconfig	  - New config where all options are accepted with yes
   allmodconfig	  - New config selecting modules when possible
   alldefconfig    - New config with all symbols set to default
   randconfig	  - New config with random answer to all options
   listnewconfig   - List new options
   olddefconfig	  - Same as oldconfig but sets new symbols to their
                    default value without prompting

3.2. Device tree[edit source]

See doc/README.fdt-control

The board device tree, with the same binding as the kernel, is integrated with the SPL and U-Boot binaries:

  • appended at the end of the code by default (CONFIG_OF_SEPARATE)
  • embedded in binary (CONFIG_OF_EMBED): useful for debug, allows easy elf file loading

A default device tree is defined in the defconfig file (with CONFIG_DEFAULT_DEVICE_TREE).

You can also select another supported device tree with the make flag DEVICE_TREE
for stm32mp32 boards the file are: arch/arm/dts/stm32mp*.dts

   make DEVICE_TREE=<dts-file-name>

or you can provide a precompiled device tree blob (with EXT_DTB option)

   make EXT_DTB=boot/<dts-file-name>.dtb

The SPL device tree is also generated from this device tree; but to reduce its size, the U-Boot makefile uses the fdtgrep tool to parse the full U-Boot DTB and identify all the drivers needed by SPL.

To do this, U-Boot uses some specific device-tree flags to specify if the associated driver is initialized prior to U-Boot relocation and/or if the associated node is present in SPL :

  • u-boot,dm-pre-reloc => present in SPL, initialized before relocation in U-Boot
  • u-boot,dm-pre-proper => initialized before relocation in U-Boot
  • u-boot,dm-spl => present in SPL

In the device tree used by U-Boot, these flags need to be added in each node used in SPL or in U-Boot before relocation but also for each used handle (clock, reset, pincontrol).

4. U-Boot command line interface (CLI)[edit source]

see U-Boot Command Line Interface

If CONFIG_AUTOBOOT is activated, to enter in this console, you have CONFIG_BOOTDELAY seconds (2s by default) before bootcmd execution (CONFIG_BOOTCOMMAND) by pressing any key when the line below is displayed.

 Hit any key to stop autoboot:  2

4.1. Commands[edit source]

The commands are defined cmd/*.c , they are activated under associated configuration flag CONFIG_CMD_*.

Use the command help in the U-Boot shell to list the available commands on your device.

  help

List of commands extracted from U-Boot Manual (not-exhaustive):

  • Information Commands
    • bdinfo - print Board Info structure
    • coninfo - print console devices and informations
    • flinfo - print FLASH memory information
    • iminfo - print header information for application image
    • help - print online help
  • Memory Commands
    • base - print or set address offset
    • crc32 - checksum calculation
    • cmp - memory compare
    • cp - memory copy
    • md - memory display
    • mm - memory modify (auto-incrementing)
    • mtest - simple RAM test
    • mw - memory write (fill)
    • nm - memory modify (constant address)
    • loop - infinite loop on address range
  • Flash Memory Commands
    • cp - memory copy
    • flinfo - print FLASH memory information
    • erase - erase FLASH memory
    • protect - enable or disable FLASH write protection
    • mtdparts - define a Linux compatible MTD partition scheme
  • Execution Control Commands
    • source - run script from memory
    • bootm - boot application image from memory
    • go - start application at address 'addr'
  • Download Commands
    • bootp - boot image via network using BOOTP/TFTP protocol
    • dhcp - invoke DHCP client to obtain IP/boot params
    • loadb - load binary file over serial line (kermit mode)
    • loads - load S-Record file over serial line
    • rarpboot- boot image via network using RARP/TFTP protocol
    • tftpboot- boot image via network using TFTP protocol
  • Environment Variables Commands
    • printenv- print environment variables
    • saveenv - save environment variables to persistent storage
    • setenv - set environment variables
    • run - run commands in an environment variable
    • bootd - boot default, i.e., run 'bootcmd'
  • Flattened Device Tree support
    • fdt addr - select FDT to work on
    • fdt list - print one level
    • fdt print - recursive print
    • fdt mknode - create new nodes
    • fdt set - set node properties
    • fdt rm - remove nodes or properties
    • fdt move - move FDT blob to new address
    • fdt chosen - fixup dynamic info
  • Special Commands
    • i2c - I2C sub-system
  • Storage devices
  • Miscellaneous Commands
    • echo - echo args to console
    • reset - Perform RESET of the CPU
    • sleep - delay execution for some time
    • version - print monitor version

To add a new command, see doc/README.commands

4.2. U-Boot environment variables[edit source]

The U-Boot behavior is configured with environment variables.

see Manual and README / Environment Variables

On first boot, U-Boot uses a default environment embedded in the U-Boot binary. You can modify it by changing the content of CONFIG_EXTRA_ENV_SETTINGS in your configuration file (for example ./include/configs/stm32mp1.h) (see README / - Default Environment).

This environment can be modified and saved in the boot device; it is loaded during U-Boot initialization when it is present:

  • for eMMC/SDCARD boot (CONFIG_ENV_IS_IN_EXT4), in the bootable ext4 partition "bootfs" :
    in file CONFIG_ENV_EXT4_FILE="uboot.env"
  • for NAND boot (CONFIG_ENV_IS_IN_UBI), in the two UBI volumes "config" (CONFIG_ENV_UBI_VOLUME) and "config_r" (CONFIG_ENV_UBI_VOLUME_REDUND).
  • for NOR boot (CONFIG_ENV_IS_IN_SPI_FLASH), in the u-boot_env mtd parttion (at offset CONFIG_ENV_OFFSET)

4.2.1. env command[edit source]

The "env" command allows to display, modify and save the environment in U-Boot console.

  help env
 env - environment handling commands
 
 Usage:
 env default [-f] -a - [forcibly] reset default environment
 env default [-f] var [...] - [forcibly] reset variable(s) to their default values
 env delete [-f] var [...] - [forcibly] delete variable(s)
 env edit name - edit environment variable
 env exists name - tests for existence of variable
 env print [-a | name ...] - print environment
 env print -e [name ...] - print UEFI environment
 env run var [...] - run commands in an environment variable
 env save - save environment
 env set -e name [arg ...] - set UEFI variable; unset if 'arg' not specified
 env set [-f] name [arg ...]

Example: restore the default environment and save it, useful after U-Boot upgrade

  env default -a
  env save

4.2.2. bootcmd[edit source]

"bootcmd" is the autoboot command; it defines the command executed when U-Boot starts (CONFIG_BOOTCOMMAND).

For stm32mp, we define CONFIG_BOOTCOMMAND="run bootcmd_stm32mp"

  env print bootcmd    
  bootcmd=run bootcmd_stm32mp

"bootcmd_stm32mp" is a script that selects the command to execute for each boot device (see ./include/configs/stm32mp1.h), based on generic distro scripts

  • for serial/usb: execute the stm32prog command
  • for mmc boot (eMMC, SD card), boot only on the same device (bootcmd_mmc...)
  • for nand boot, boot with on ubifs partition on nand (bootcmd_ubi0)
  • for nor boot, use the default order eMMC (SDMMC 1)/ NAND / SDCARD (SDMMC 0) / SDMMC2 (the default bootcmd: distro_bootcmd)
  env print bootcmd_stm32mp

But you can change this configuration:

  • permanently in your board file (default environment by CONFIG_EXTRA_ENV_SETTINGS or change CONFIG_BOOTCOMMAND value).
  • temporally in saved environment:
  env set bootcmd run bootcmd_mmc0 
  env save

PS: to reset default value

  env default bootcmd
  env save

4.3. Generic Distro configuration[edit source]

see doc/README.distro

This feature is activated for ST boards (CONFIG_DISTRO_DEFAULTS):

  • one boot command (bootmcd_xxx) exists for each bootable device
  • U-Boot is independent of the Linux distribution used.
  • bootcmd is defined in ./include/config_distro_bootcmd.h

With DISTRO the default command executed: include/config_distro_bootcmd.h

 bootcmd=run distro_bootcmd

This script will try any device found in the variable 'boot_targets' and execute the associated bootcmd.

Example for device mmc0, mmc1, mmc2, pxe and ubifs:

 bootcmd_mmc0=setenv devnum 0; run mmc_boot
 bootcmd_mmc1=setenv devnum 1; run mmc_boot
 bootcmd_mmc2=setenv devnum 2; run mmc_boot
 bootcmd_pxe=run boot_net_usb_start; dhcp; if pxe get; then pxe boot; fi
 bootcmd_ubifs0=setenv devnum 0; run ubifs_boot

U-Boot searchs for a configuration file extlinux.conf in a bootable device, this file defines the kernel configuration to use:

  • bootargs
  • kernel + device tree + ramdisk files (optional)
  • FIT image

4.4. U-Boot scripting capabilities[edit source]

"Script files" are command sequences that will be executed by U-Boot's command interpreter; this feature is especially useful when you configure U-Boot to use a real shell (hush) as command interpreter.

See U-Boot script manual for example.

5. U-Boot build[edit source]

5.1. Prerequisites[edit source]

You need:

  git clone https://github.com/STMicroelectronics/u-boot
  • from the Mainline U-Boot in official GIT repository [4]
  git clone https://gitlab.denx.de/u-boot/u-boot.git

5.1.1. ARM cross compiler[edit source]

You need to have a cross compiler [5] installed on your Host (X86_64, i686, ...) for the targeted Device architecture = ARM, the environment variables ($PATH and $CROSS_COMPILE) need to be configured in your shell.

You can use gcc for ARM, available in:

  1. the SDK toolchain
    See Cross-compile with OpenSTLinux SDK, PATH and CROSS_COMPILE are automatically updated.
  2. an existing package (for example, on Ubuntu/Debian: ( sudo apt-get install gcc-arm-linux-gnueabihf)
  3. an existing toolchain:

for example: gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi.tar.xz
from https://releases.linaro.org/components/toolchain/binaries/7.2-2017.11/arm-linux-gnueabi/
unzip the toolchain in $HOME and update your environment with:

  export PATH=$HOME/gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi/bin:$PATH
  export CROSS_COMPILE=arm-linux-gnueabi-

5.2. Compilation[edit source]

In the U-Boot source directory, you need to select the <target> and the <device tree> for your configuration and then execute the "make all" command.

  make <target>_defconfig
  make DEVICE_TREE=<device-tree> all

KBUILD_OUTPUT can be used optionally to change the output directory if you want to compile several targets or don't compile in the source directory, for example:

  export KBUILD_OUTPUT=../build/basic

DEVICE_TREE can be also exported to your environment when you support only one board, for example:

  export DEVICE_TREE=stm32mp157c-ev1

For all the stm32mp15 family, we manage 3 configurations:

  • stm32mp15_trusted_defconfig: trusted boot chain, U-Boot (without SPL) is unsecure and uses Secure monitor from TF-A
  • stm32mp15_optee_defconfig: trusted boot chain, U-Boot (without SPL) is unsecure and uses Secure monitor from SecureOS = OP-TEE
  • stm32mp15_basic_defconfig: basic boot chain, with an SPL as FSBL, U-BOOT is secure and installs monitor with PSCI

The board diversity is only managed with the device tree.

Examples from STM32MP15 U-Boot:

  export KBUILD_OUTPUT=../build/trusted
  make stm32mp15_trusted_defconfig
  make DEVICE_TREE=stm32mp157c-<board> all
  export KBUILD_OUTPUT=../build/optee
  export DEVICE_TREE=stm32mp157c-<board>
  make stm32mp15_optee_defconfig
  make all
  make stm32mp15_basic_defconfig
  make DEVICE_TREE=stm32mp157c-<board>  all

Use help to list other targets:

  make help

5.3. Output files[edit source]

The resulting U-Boot files are present in your build directory (U-Boot or KBUILD_OUTPUT).

Two binary format is used for stm32mp product:

  • STM32 image format (*.stm32), managed by mkimage U-Boot tools and Signing_tool ; it is requested by ROM code and by TF-A; see STM32 header for details.
  • uImage (*.img) format, file with U-Boot header, managed by SPL and U-Boot (for kernel load)

The U-Boot generated files for

  • Trusted boot chain (TF-A is used as FSBL, with or without OP-TEE)
    • u-boot.stm32 : U-Boot binary with STM32 image header, loaded by TF-A
  • Basic boot chain (SPL is used as FSBL)
    • u-boot-spl.stm32 : SPL binary with STM32 image header, loaded by ROM code
    • u-boot.img : U-Boot binary with uImage header, loaded by SPL

The files used to debug with gdb are

  • u-boot : elf file for U-Boot
  • spl/u-boot-spl : elf file for SPL

6. References[edit source]