Last edited 2 months ago

U-Boot overview: Difference between revisions


Latest revision as of 11:03, 8 November 2024


1. Das U-Boot[edit | edit source]

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

U-Boot Logo.png

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 | edit source]

Zoom out to STM32MPU Embedded Software

The STM32 MPU boot chain uses Trusted Firmware-A (TF-A) as FSBL and U-Boot as SSBL, included in a TF-A FIP.


2.1. SPL[edit | edit source]

U-Boot SPL is not supported in OpenSTLinux.

2.2. U-Boot: SSBL[edit | edit source]

2.2.1. U-Boot description[edit | edit source]

U-Boot is the second-stage bootloader (SSBL) of boot chain for STM32 Arm® Cortex® MPUs More info.png.

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.2.2. U-Boot execution sequence[edit | edit source]

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

  • Pre-relocation initialization (common/board_f.c ): minimal initialization (such as CPU, clock, reset, DDR and console) running at the CONFIG_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 (by default bootcmd=CONFIG_BOOTCOMMAND):
      for example, execution of the command bootm (for uImage or FIT) or booti (for Image.giz) to:
      • load and check images (such as kernel, device tree and ramdisk)
      • fixup the kernel device tree
      • install the secure monitor (optional) or
      • pass the control to the Linux kernel (or to another target application)

3. U-Boot configuration[edit | edit source]

The U-Boot binary configuration is based on

  • DeviceTree: U-Boot binaries include a device tree blob that is parsed at runtime

All the configuration flags (prefixed by CONFIG_) are described in the source code, either in the README file or in the documentation directory .

For example, CONFIG_CMD_CLK activates the command clk compilation (cmd.clk.c ).

Hence to compile U-Boot, select the <target> and the device tree for the board in order to choose a predefined configuration.
Refer to #U-Boot_build for examples.

3.1. Kbuild[edit | edit source]

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

  • Select a predefined configuration (defconfig file in configs directory ) and generate the first .config:
 make <config>_defconfig.
  • Change the U-Boot compile configuration (modify .config) by using one of the following five make commands:
 make menuconfig --> menu based program
 make config  --> line-oriented configuration
 make xconfig --> QT program
 make gconfig --> GTK program
 make nconfig --> ncurse menu based program

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

Warning: the modification is performed locally in the build directory. It will be lost after a make distclean.

Save your configuration to be able to use it as a defconfig file:

  make savedefconfig

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

The other makefile targets are the following:

  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 | edit source]

Refer to U-Boot Documentation or doc/develop/devicetree/control.rst for details.

The board device tree has the same binding as the kernel. By default it is integrated within the U-Boot binaries: u-boot.bin: appended at the end of the code (CONFIG_OF_SEPARATE) or embedded in the U-Boot binary (CONFIG_OF_EMBED).

In OpenSTLinux, the U-Boot device tree (u-boot.dtb) is present inside a FIP and provided to U-Boot as external file loaded by FSBL=TF-A when U-Boot code is started (u-boot-nodtb.bin: code without device tree): the U-Boot device tree address is provided as boot parameter (in r2 register).

A default device tree is available in the defconfig file (by setting CONFIG_DEFAULT_DEVICE_TREE).

You can either select another supported device tree present in U-Boot directories by using the DEVICE_TREE make flag. For STM32 Arm® Cortex® MPUs More info.png boards, the corresponding file is <dts-file-name>.dts in arch/arm/dts/stm32mp*.dts , with <dts-file-name> set to the full name of the board:

  make DEVICE_TREE=<dts-file-name>

or provide a device tree blob (dtb file) resulting from the dts file compilation, by using the EXT_DTB option:

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

To obtain a device tree file <dts-file-name>.dts that is identical to the Linux kernel one, these U-Boot properties are only added for STMicroelectronics boards in the add-on file <dts-file-name>-u-boot.dtsi. This file is automatically included in <dts-file-name>.dts during device tree compilation (the needed "#include" is added during the pre-processing phasis).

This is a generic U-Boot Makefile behavior defined in scripts/Makefile.lib that does not generate a compilation error if this file <dts-file-name>-u-boot.dtsi needed for OpenSTLinux is absent.

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

  • bootph-all => initialized before relocation in U-Boot, present in SPL
  • bootph-some-ram => initialized before relocation in U-Boot, not in SPL
  • bootph-pre-ram => present in SPL

In the device tree used by U-Boot, these flags bootph-all need to be added in all the nodes used in U-Boot before relocation (or in SPL) and for all used handles (clock, reset, pincontrol).

See example for console configuration for example.

Device tree in SPL (not used in OpenSTLinux):

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

Refer to U-Boot Documentation or doc/usage/cmdline.rst .

U-Boot has a command line interface, the U-Boot console, in which you work with U-Boot commands and environment variables to create a customized boot process.

4.1. Commands[edit | edit source]

U-Boot has a set of built-in commands for managing the system and booting the device.By modifying U-Boot source code, you can create your own built-in commands.

The commands are defined in cmd/*.c . They are activated through the corresponding CONFIG_CMD_* configuration flag.

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

 help

The U-Boot usage is described in U-Boot Documentation but only few commands are described here.

Below the list of all commands extracted from an old U-Boot Manual] (obsolete and not-exhaustive):

  • Information Commands
    • bdinfo - prints Board Info structure
    • coninfo - prints console devices and information
    • flinfo - prints Flash memory information
    • iminfo - prints header information for application image
    • help - prints online help
  • Memory Commands
    • base - prints or sets the 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 - prints Flash memory information
    • erase - erases Flash memory
    • protect - enables or disables Flash memory write protection
    • mtdparts - defines a Linux compatible MTD partition scheme
  • Execution Control Commands
    • source - runs a script from memory
    • bootm - boots application image from memory
    • go - starts application at address 'addr'
  • Download Commands
    • bootp - boots image via network using BOOTP/TFTP protocol
    • dhcp - invokes DHCP client to obtain IP/boot params
    • loadb - loads binary file over serial line (kermit mode)
    • loads - loads S-Record file over serial line
    • rarpboot- boots image via network using RARP/TFTP protocol
    • tftpboot- boots image via network using TFTP protocol
  • Environment Variables Commands
    • printenv- prints environment variables
    • saveenv - saves environment variables to persistent storage
    • setenv - sets environment variables
    • run - runs commands in an environment variable
    • bootd - default boot, that is run 'bootcmd'
  • Flattened Device Tree support
    • fdt addr - selects the FDT to work on
    • fdt list - prints one level
    • fdt print - recursive printing
    • fdt mknode - creates new nodes
    • fdt set - sets node properties
    • fdt rm - removes nodes or properties
    • fdt move - moves FDT blob to new address
    • fdt chosen - fixup dynamic information
  • Special Commands
    • i2c - I2C sub-system
  • Storage devices
  • Miscellaneous Commands
    • echo - echoes args to console
    • reset - performs a CPU reset
    • sleep - delays the execution for a predefined time
    • version - prints the monitor version

To add a new command, refer to U-Boot Documentation or to doc/develop/commands.rst .

4.2. U-Boot environment variables[edit | edit source]

The U-Boot behavior is configured through environment variables.

Refer to README / Environment Variables and to U-Boot Documentation.

On the 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. When it is present, it is loaded during U-Boot initialization.

For STMicroelectronics boards the environment location is automatically selected to support multiple boot device on the same board:

  • To boot from eMMC/SD card (CONFIG_ENV_IS_IN_MMC): at the end of the partition indicated by config field "u-boot,mmc-env-partition" in device-tree (for STMicroelectronics boards, this partition is named "u-boot-env").
  • To boot from NAND Flash memory (CONFIG_ENV_IS_IN_UBI): in the two UBI volumes "config" (CONFIG_ENV_UBI_VOLUME) and "config_r" (CONFIG_ENV_UBI_VOLUME_REDUND).
  • To boot from NOR Flash memory (CONFIG_ENV_IS_IN_SPI_FLASH): the "u-boot-env" mtd partition at offset CONFIG_ENV_OFFSET.

4.2.1. env command[edit | edit source]

The env command allows displaying, modifying and saving 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 ...]

See U-Boot Documentation for details.

Example: proceed as follows to restore the default environment and save it. This is useful after a U-Boot upgrade:

 env default -a
 env save

You can also use the command activated by CONFIG_CMD_ERASEENV:

 env erase

4.2.2. bootcmd[edit | edit source]

"bootcmd" variable is the autoboot command (see doc/README.autoboot ). It defines the command executed when U-Boot starts (CONFIG_BOOTCOMMAND).

In generic stm32mp defconfig, CONFIG_BOOTCOMMAND="run bootcmd_stm32mp":

 env print bootcmd    
  bootcmd=run bootcmd_stm32mp

"bootcmd_stm32mp" is a script that selects the command to be executed for each boot device (see files in include/configs/: stm32mp13_st_common.h, stm32mp15_st_common.h, stm32mp21_st_common.h orstm32mp23_st_common.h or stm32mp25_st_common.h for STMicroelectronics board), based on generic distro scripts:

  • To boot from a serial/usb device: execute the stm32prog command.
  • To boot from an eMMC, SD card: boot only on the same device (bootcmd_mmc...).
  • To boot from a NOR Flash memory: use the SD-Card (on SDMMC 0 on STMicroelectronics boards with bootcmd_mmc0).
  • To boot from a NAND Flash memory: boot on ubifs partition on the NAND memory (bootcmd_ubi0) or on the SD-Card (bootcmd_mmc0).
 env print bootcmd_stm32mp

You can then change this configuration:

  • either permanently in your board file
    • default environment by CONFIG_EXTRA_ENV_SETTINGS (see ./include/configs/stm32mp*.h files)
    • change CONFIG_BOOTCOMMAND value in your defconfig

E.g:

 CONFIG_BOOTCOMMAND="run bootcmd_mmc0"
 CONFIG_BOOTCOMMAND="run distro_bootcmd"
  • or temporarily in the saved environment:
 env set bootcmd run bootcmd_mmc0
 env save

Note: To reset the environment to its default value, use the command:

 env default bootcmd
 env save

4.3. U-Boot scripting capabilities[edit | edit source]

"Script" is made up of variables (bootcmd for example) that contain a set of commands that are executed by the U-Boot command interpreter one after another. You run this script with the run command, for example:

 run bootcmd

"Script image" is external binary file with U-Boot header and containing a sequence of commands. It is loaded by U-Boot in memory and executed using the source command, it allows the user to execute a set of predefined U-Boot commands automatically.

To convert an text file commands.txt into a script image for U-Boot, you have to use the mkimage tool as follows:

 mkimage -T script -C none -n 'Demo Script File' -d commands.txt setenv.img

These feature are particularly useful when U-Boot use a the hush shell (similar to Bourne shell) as command interpreter; it is the default configuration in OpenSTLinux (CONFIG_HUSH_PARSER).

4.4. Autoboot[edit | edit source]

If CONFIG_AUTOBOOT is activated, you have some delay established in bootdelay variable or CONFIG_BOOTDELAY (2s by default, 1s for ST configuration) to enter the console by pressing any key, after the line below is displayed.

 Hit any key to stop autoboot:  2

If U-Boot is not interrupted, bootcmd is executed (CONFIG_BOOTCOMMAND), in other words automatic booting have the same effect that the command:

 run bootcmd

or

 boot

4.5. Generic Distro configuration[edit | edit source]

Refer to documentation or to doc/develop/distro.rst for details.

This feature is activated by default on STMicroelectronics boards (CONFIG_DISTRO_DEFAULTS):

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

When DISTRO is enabled, the command that is executed by default is include/config_distro_bootcmd.h :

 bootcmd=run distro_bootcmd

This script tries any device found in the 'boot_targets' variable and executes the associated bootcmd.

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

 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 searches for an extlinux.conf configuration file for each bootable device. This file defines the files and the kernel configuration used to start the OS with bootm command:

  • KERNEL = kernel image (uImage or Image.gz)
    or FIT image, including all these needed files (for details see doc/uImage.FIT/howto.txt )
  • FDT = device tree (optional)
    FDTDIR = path for device tree, name of device tree is indicated by the variable fdtfile, build from the board compatible in U-Boot device tree for STMicroelectronics boards in the board_late_init() function, under CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG.
  • KERNEL = ramdisk files (optional)
  • APPEND = bootargs, the Linux kernel’s command-line parameter (admin-guide/kernel-parameters.html)

5. U-Boot build[edit | edit source]

See U-Boot Documentation.

5.1. Prerequisites[edit | edit source]

  • a PC with Linux and tools:
  • U-Boot source code
    • the latest STMicroelectronics U-Boot version
      • tar.xz file from Developer Package (for example STM32MP1) or from latest release on ST github [3]
      • from GITHUB[2], with git command
 git clone https://github.com/STMicroelectronics/u-boot
  • from the Mainline U-Boot in official GIT repository [1]
 git clone https://source.denx.de/u-boot/u-boot.git

5.2. ARM cross compiler[edit | edit source]

A cross compiler [5] must be installed on your Host (X86_64, i686, ...) for the ARM targeted Device architecture, AArch32 for STM32MP1 series or AArch64 for STM32MP2 series. In addition, the $PATH and $CROSS_COMPILE environment variables must 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, install gcc-arm-linux-gnueabihf on Ubuntu/Debian:
    sudo apt-get install gcc-arm-linux-gnueabihf

5.3. Compilation[edit | edit source]

In the U-Boot source directory, select the defconfig for the <target> and the <device tree> for your board and then execute the make all command:

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

Use help to list other targets than all:

 make help
 

Optionally

  • KBUILD_OUTPUT can be used to change the output build directory in order to compile several targets in the source directory. For example:
 export KBUILD_OUTPUT=<path>
  • DEVICE_TREE can also be exported to your environment when only one board is supported. For example:
 export DEVICE_TREE=<device-tree>

The result is the following:

 export KBUILD_OUTPUT=<path>
 export DEVICE_TREE=<device tree>
 make <target>_defconfig
 make all

DEVICE_TREE can also select a device trees present in the Unsupported domain! directory of the OpenSTLinux seperate Git: https://github.com/STMicroelectronics/dt-stm32mp by

  • using submodule in U-Boot directory arch/arm/dts/external-dt, the default path for external device tree.
   git submodule add https://github.com/STMicroelectronics/dt-stm32mp arch/arm/dts/external-dt
   make DEVICE_TREE=<dts-file-name> all
  • cloning this Git in any location indicated with EXT_DTSin make command
   git clone https://github.com/STMicroelectronics/dt-stm32mp <DTS_PATH>
   make DEVICE_TREE=<dts-file-name> EXT_DTS=<DTS_PATH>  all

See examples in

5.4. Output files[edit | edit source]

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

For OpenSTLinux, two U-Boot files are used by STMicroelectronics boards to generate the FIP file used byTF-A BL2:

  • BL33_CFG=u-boot.dtb : the U-Boot device tree, selected by DEVICE_TREE, loaded by TF-A BL2
  • BL33=u-boot-nodtb.bin: the U-Boot executable, loaded by TF-A BL2 started by secure world = OP-TEE with BL33_CFG as parameter

Nota: All the compiled device tree are available in $KBUILD_OUTPUT/arch/arm/dts/*.dtb.
You can select them as BL33_CFG parameter without U-Boot recompilation.

See TF-A BL2 overview for FIP details.

The file used to debug with gdb is u-boot, the elf file for U-Boot.

The file u-boot.stm32, i.e. the U-Boot binary with STM32 header, is no more generated and used in OpenSTlinux.

6. U-Boot integration in FIP[edit | edit source]

U-Boot binary and its associated device tree are part of the FIP binary, created with TF-A Makefile option :

  • BL33_CFG = u-boot.dtb
  • BL33 = u-boot-nodtb.bin

or updated with fiptools:

  • --hw-config u-boot.dtb
  • --nt-fw u-boot-nodtb.bin

Example for FIP update :

 fiptool --verbose update --nt-fw u-boot-nodtb.bin \
             --hw-config  u-boot.dtb \
             fip-<board>.bin
 
 DEBUG: Replacing nt-fw with.../u-boot-nodtb.bin
 DEBUG: Replacing hw-config with .../u-boot.dtb
 DEBUG: Metadata size: ... bytes
 DEBUG: Payload size: ... bytes

See How_to_configure_TF-A_FIP for details.

7. References[edit | edit source]