U-Boot SPL framework becomes generic
The 2012.10 release of U-Boot comes with an interesting change: the SPL framework that U-Boot has been using specifically for the OMAP SoC has become generic, and is now being used for other architectures and other ARM SoCs. Read on for a detailed explanation on why SPL is needed, what it is, and how it works in U-Boot.
Most modern SoCs contain a ROM code that is capable of loading a boot code from a non-volatile storage such as a NAND flash or a file located inside of SD card filesystem or USB storage filesystem. This feature removes the need for a flash that can be read directly by the CPU for code execution, such as a NOR flash, and allows to boot directly from cheaper and larger storage devices (NAND flash, SD cards, eMMC, etc.).
However, this ROM code typically creates two important constraints on the boot code:
- A limit in the total size of the boot code. Sometimes the boot code must be as small as a few kilo-bytes, usually a few dozens of kilo-bytes are now possible.
- The boot code cannot be loaded directly into the external RAM, because the ROM code has no idea what are the parameters to configure the SoC memory controller according to the external RAM being used on a particular board. Therefore, the ROM code generally loads the boot code in an SoC-internal memory, often called SRAM.
For those two reasons, the popular open-source bootloaders U-Boot orBarebox usually cannot be directly loaded by the ROM code of such SoCs. SoC vendors have therefore developed their own primary boot loaders, who job is to:
- Comply with the requirement of the ROM code of a particular SoC
- Initialize the memory controller in order to allow access to the external RAM
- Load the second stage bootloader, typically U-Boot or Barebox, into RAM, and execute them.
A few examples of first stage bootloaders in the ARM world are: AT91Bootstrap for AT91SAM9 SoCs from Atmel, X-Loader for OMAP SoCs from TI, imx-bootlets for some i.MX SoCs from Freescale, etc.
Unfortunately, many of those projects are not real open-source projects. Their source code is generally available in order to allow companies making custom boards to re-use them, but there is no version control system for them, no community, everybody keeps his local hacks and modifications and nobody benefits from changes done by others. A sad situation, indeed.
Amongst those first stage bootloaders, X-Loader (for OMAP SoCs) was a special beast: it is by itself a stripped-down version of U-Boot. It re-uses the existing U-Boot code, but removes enough feature (such as the shell, command interaction, and much more) in order to fit within the limitations of the ROM code. Originally, X-Loader was however a separate project from U-Boot, so it was a one-time fork and further improvements to U-Boot did not benefit to X-Loader and the X-Loader did not have a big community behind it.
Fortunately, over time the X-Loader mechanism, which mainly consists of selectively disabling parts of U-Boot, has been integrated into the mainline U-Boot. However, it has been done in an OMAP-specific way. This mechanism is called “SPL” as in “Secondary Program Loader”.
The recently released U-Boot version 2012.10 however contains changes from Tom Rini, the OMAP maintainer in U-Boot, and also the interim U-Boot maintainer, that make this SPL mechanism generic and usable by other SoC than OMAP and even other architectures.
After some preparation patches, the core of Tom Rini’s changes is to move the SPL code from arch/arm/cpu/armv7/omap-common/ to common/spl/(see this commit), which makes it usable by more platforms.
So for example, when you do:
make CROSS_COMPILE=arm-linux-gnueabi- omap3_beagle_config make CROSS_COMPILE=arm-linux-gnueabi- -j4
The U-Boot build process will actually run twice. First to generate the U-Boot image itself (stored as u-boot.bin):
[...] arm-linux-gnueabi-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin [...]
Second to generate the U-Boot SPL (stored as spl/u-boot-spl.bin):
[...] arm-linux-gnueabi-objcopy --gap-fill=0xff -O binary \ /home/thomas/projets/u-boot/spl/u-boot-spl \ /home/thomas/projets/u-boot/spl/u-boot-spl.bin [...]
Of course, the SPL is considerably smaller than the main U-Boot binary. The size of the SPL in the OMAP case is still quite large because it has support for a big number of devices, and support for the FAT filesystem as well.
$ ls -l u-boot.bin spl/u-boot-spl.bin -rwxrwxr-x 1 thomas thomas 46252 oct. 30 20:19 spl/u-boot-spl.bin -rw-rw-r-- 1 thomas thomas 344528 oct. 30 20:19 u-boot.bin
The SPL is built by compiling the code from common/spl/ and a few drivers and core infrastructure, but most of the U-Boot doesn’t get compiled. In particular, all the shell and commands are not compiled in. The SPL has a completely hardcoded behavior: it will load an image from a fixed location, to a fixed location in RAM, all those parameters being defined at compile time in the U-Boot board configuration file (include/configs/foo.h). The core of
the SPL logic is implemented in common/spl/spl.c:board_init_r(). For example,
if CONFIG_SPL_NAND_SUPPORT is enabled, it will try to load a secondary bootloader image from NAND using the spl_nand_load_image() function, implemented in common/spl/spl_nand.c. In the typical case, the secondary boot loader is loaded from
offset CONFIG_SYS_NAND_U_BOOT_OFFS in the NAND flash. Finally, execution is transferred to the secondary bootloader usingjump_to_image_no_args(). Of course, there are many other possibilities, like directly loading a Linux kernel from the SPL, without having to go through a full-featured second stage bootloader (see the CONFIG_SPL_OS_BOOTconfiguration variable), or loading a file from a FAT filesystem located on a SD card.
Besides the OMAP support which was already using SPL, this mechanism is now being used for more U-Boot platforms:
- Used in the preliminary support for the Altera socfpga Cyclone 5 platform
- Stefan Roese has worked on making the SPL framework usable on PowerPC
- Allen Martin has worked to use the SPL framework for the Tegra ARM SoC family
- Stefano Babic has worked on using the SPL framework for MX35 boards
Hopefully, the existence of a proper SPL framework in U-Boot will encourage more SoC vendors to use this generic mechanism rather than relying on custom first stage bootloader that are very often poorly written and badly maintained.