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.
- Official website: https://www.denx.de/wiki/U-Boot
- Official manual: project documentation and https://www.denx.de/wiki/DULG/Manual
- Official source code is available under git repository at [1]
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]
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 | The basic boot chain cannot be used for product development (see Boot chains No fix is planned. }} 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 supported 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 init (cpu, clock, reset, ddr, console,...) running at the load address CONFIG_SYS_TEXT_BASE
- Relocation: copy the code to the end of DDR
- Post-relocation initialization:(common/board_r.c): init all the drivers
- Command execution through autoboot (CONFIG_AUTOBOOT) or console shell
- execute the boot command (bootcmd=CONFIG_BOOTCOMMAND by default):
for example, execute the command 'bootm' to:- load and check images (kernel, device tree, ramdisk....)
- fixup kernel device tree
- install secure monitor (optional)
- pass control to the Linux kernel (or other target application)
- execute the boot command (bootcmd=CONFIG_BOOTCOMMAND by default):
3. U-Boot configuration[edit source]
The U-Boot binary configuration is based on
- Kbuild infrastructure (as in Linux Kernel, you can use "make menuconfig" in U-Boot)
The configurations are based on:- options defined in Kconfig files (CONFIG_ compilation flags)
- the selected configuration file = configs/stm32mp*_defconfig
- other compilation flags defines in include/configs/stm32mp*.h
the file name is configured by CONFIG_SYS_CONFIG_NAME
(these flags are progressively migrating to Kconfig)
for stm32mp157: we use include/configs/stm32mp1.h file
- 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]
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]
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:
- a PC with Linux and tools:
- U-Boot source code
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:
- the SDK toolchain
See Cross-compile with OpenSTLinux SDK, PATH and CROSS_COMPILE are automatically updated. - an existing package (for example, on Ubuntu/Debian: ( sudo apt-get install gcc-arm-linux-gnueabihf)
- an existing toolchain:
- gcc v8 toolchain provided by arm (https://developer.arm.com/open-source/gnu-toolchain/gnu-a/downloads/)
- gcc v7 toolchain provided by linaro: (https://www.linaro.org/downloads/)
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]
- ↑ https://www.denx.de/wiki/pub/U-Boot/MiniSummitELCE2013/2013-ELCE-U-Boot-Falcon-Boot.pdf
- ↑ https://en.wikipedia.org/wiki/Xconfig
- ↑ https://github.com/STMicroelectronics/u-boot
- ↑ https://gitlab.denx.de/u-boot/u-boot.git or https://github.com/u-boot/u-boot
- ↑ https://en.wikipedia.org/wiki/Cross_compiler