This pages provides information related to using the industry standard "distro boot" boot flow for U-boot as it's been implemented by Xilinx.
Table of Contents
Table of Contents | ||
---|---|---|
|
Introduction
While x86-based platforms have a de facto standardization of how boot operates from BIOS/UEFI during initial power-on until hand-off to a robust operating system like Linux or Microsoft Windows, this is largely incidental and has much to do with the limited number of x86-based vendors in the market. By contrast, the number of Arm-based SoC platforms numbers in the dozens and virtually every SoC has some form of unique boot process.
...
For example, a simple TFTP-based boot is illustrated below.
Code Block | theme | Midnight
---|
bootcmd=echo Booting from network ...; usb start; setenv ethact asx0; if dhcp && tftp $loadaddr $bootfile && tftp $f |
...
Distro boot extends this functionality by redirecting the call to bootcmd to a call to the distro_bootcmd variable.
Code Block | ||
---|---|---|
| ||
bootcmd=run distro_bootcmd |
...
How the distro_bootcmd variable is defined and used differs by vendor but it typically contains a sequence of commands that scans a pre-defined list of potential boot targets in search of boot collateral as shown below.
Code Block | ||
---|---|---|
| ||
boot_targets=mmc0 jtag mmc0 mmc1 qspi0 nand0 usb0 usb1 scsi0 pxe dhcp distro_bootcmd=scsi_need_init=; for target in ${boot_targets}; do run bootcmd_${target}; done |
The command loops through the contents of the boot_targets list and scans the media in order looking for additional boot collateral. The boot_targets list is defined in the platform definition in the U-Boot source tree.
Depending on the specifics of the target platform, the distro boot infrastructure can either use the boot_targets list to explicitly find specific boot collateral (eg, hard-coded loading once a valid boot target is located) or it can be used to locate some kind of decoupled configuration information.
...
Specifically, the distro boot infrastructure will first scan for a file named extlinux.conf at the pre-defined locations (ex: /extlinux/extlinux.conf or /boot/extlinux/extlinux.conf) in the default U-Boot environment. The basic syntax of the extlinux.conf file is as show below.
Code Block | ||
---|---|---|
| ||
LABEL Linux KERNEL Image FDT system.dtb INITRD rootfs.cpio.gz.u-boot |
...
In the absence of a valid extlinux.conf file, U-Boot will scan the boot_targets list looking for a file named boot.scr.uimg or boot.scr (in that order) and run any commands located in the script file. An example of the script file syntax is seen below. If your environment requires a different sequence of commands or behavior, you can edit the boot.scr file to suit your needs.
Code Block | theme | Midnight
---|
for boot_target in ${boot_targets}; do if test "${boot_target}" = "jtag" ; then . . . <COMMANDS> . . . fi if test "${boot_target}" = "mmc0" || test "${boot_target}" = "mmc1" ; then . . . <COMMANDS> . . . fi if test "${boot_target}" = "xspi0"; then . . . <COMMANDS> . . . fi done |
It's important to note that this syntax is standard U-Boot HUSH scripting syntax. The only change being made here is that this script is loaded into the environment during the boot process rather than being compiled in to the binaries.
Packaging the boot.scr File
Prior to use in a distro boot environment, the boot script must be compiled using mkimage as noted in the examples below.
The recommended method for packaging the boot.scr image is to use the U-Boot FIT format with a script similar to:
Code Block | theme | Midnight
---|
/dts-v1/; / { description = "Boot script"; images { default = "script"; script { description = "Boot script"; data = /incbin/("./boot.scr"); type = "script"; compression = "none"; hash { algo = "sha1"; }; }; }; }; |
...
Packaging a FIT image is similar to the legacy method in that it uses mkimage but the syntax is much simpler:
Code Block | theme | Midnight
---|
mkimage -f boot.fit boot.scr.uimg |
If your design does not require the additional features provided in the FIT description method seen above, the image can be packaged simply with the mkimage command directly:
Code Block | theme | Midnight
---|
mkimage -C none -A arm -T script -d boot.scr boot.scr.uimg |
Modifying an Existing boot.scr.uimg/boot.scr File
If you need to edit an existing packaged boot.scr file (or boot.scr.uimg), you can extract the plain ASCII text format using the following command line:
Code Block | ||
---|---|---|
| ||
tail -c+73 < boot.scr.uimg > out |
...
Starting with the 2020.1 release, Xilinx has switched to using the distro boot infrastructure by default for all SoC platform. The default mechanism in the Xilinx-provided software stack utilizes the boot.scr framework. Support is still present for using extlinux.conf files and they will be used if present. The platform files which define the boot_targets list and the Xilinx-specific default U-Boot environment are:
SoC Platform | Path in U-Boot Source Tree |
---|---|
Zynq-7000 | include/configs/zynq-common.h |
Zynq UltraScale+ MPSoC | include/configs/xilinx_zynqmp.h |
Versal | include/configs/xilinx_versal.h |
On Xilinx platforms, the boot_targets list always prepends the current primary boot mode as configured on the MODE pins. Thus, it is expected to see a given target more than once in the boot_targets variable. For example, on a Zynq UltraScale+ MPSoC device booting from SD card, the boot_targets list appears as:
Code Block | |
---|---|
Midnight | boot_targets=mmc0 jtag mmc0 mmc1 qspi0 nand0 usb0 usb1 scsi0 pxe dhcp |
...
For example, when booting from MMC devices (SD card or eMMC), the following script is run from the boot.scr file by default in the Xilinx-provided U-Boot environment. This can be modified based on your needs.
Code Block | ||
---|---|---|
| ||
if test "${boot_target}" = "mmc0" || test "${boot_target}" = "mmc1" ; then if test -e ${devtype} ${devnum}:${distro_bootpart} /image.ub; then fatload ${devtype} ${devnum}:${distro_bootpart} 0x10000000 image.ub; bootm 0x10000000; exit; fi if test -e ${devtype} ${devnum}:${distro_bootpart} /Image; then fatload ${devtype} ${devnum}:${distro_bootpart} 0x00200000 Image;; fi if test -e ${devtype} ${devnum}:${distro_bootpart} /system.dtb; then fatload ${devtype} ${devnum}:${distro_bootpart} 0x00100000 system.dtb; fi if test -e ${devtype} ${devnum}:${distro_bootpart} /rootfs.cpio.gz.u-boot; then fatload ${devtype} ${devnum}:${distro_bootpart} 0x04000000 rootfs.cpio.gz.u-boot; booti 0x00200000 0x04000000 0x00100000 exit; fi booti 0x00200000 - 0x00100000 exit; fi |
For additional details on the usage of the bootm
and booti
commands, see the U-Boot page.
Of note in this scheme is that the files must be found in the root of the filesystem and follow the naming scheme:
Component | File Name | Load Address |
U-Boot combined image file (image.ub) | image.ub | 0x10000000 |
Linux kernel image file (if image.ub is not found) | Image | 0x00200000 |
Linux device tree file (if image.ub is not found) | system.dtb | 0x00100000 |
Linux root filesystem image (if image.ub is not found) | rootfs.cpio.gz.u-boot | 0x04000000 |
Booting from QSPI
When the boot mode detected is QSPI, the following script is run from the boot.scr file by default in the Xilinx-provided U-Boot environment. This can be modified based on your needs.
Code Block | theme | Midnight
---|
if test "${boot_target}" = "xspi0" || test "${boot_target}" = "qspi" || test "${boot_target}" = "qspi0"; then sf probe 0 0 0; if test "image.ub" = "image.ub"; then sf read 0x10000000 0xF00000 0x6400000; bootm 0x10000000; exit; fi if test "image.ub" = "Image"; then sf read 0x00200000 0xF00000 0x1D00000; sf read 0x04000000 0x4000000 0x4000000 booti 0x00200000 0x04000000 0x00100000 exit; fi exit; fi |
When booting from a QSPI device, care must be taken to maintain a very specific scheme for where files are located both in the nonvolatile flash device as well as where they are loaded into DDR prior to hand-off to the robust operating system.
Component | Flash Address | Load Address |
U-Boot combined image file (image.ub) | 0xF00000 | 0x10000000 |
Linux kernel image file (if image.ub is not found) | 0xF00000 | 0x00200000 |
Linux device tree file (if image.ub is not found) | Pre-loaded by BOOT.BIN | 0x00100000 |
Linux root filesystem image (if image.ub is not found) | 0x4000000 | 0x04000000 |
Note: The table above presents default values as found in the pre-built collateral. The PetaLinux tools will automatically adjust the flash and load addresses as appropriate to fit the relative sizes of each payload partition.
...
In summary, the order of precedence for searching for boot components is as follows
extlinux.conf file (located in /extlinux/ or /boot/extlinux/)
boot.scr file + image.ub file
boot.scr file + individual files (Image, system.dtb, etc.)
References
https://gitlab.denx.de/u-boot/u-boot/blob/master/doc/README.distro
https://www.denx.de/wiki/view/DULG/UBootEnvVariables
https://wiki.syslinux.org/wiki/index.php?title=Config
http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/
...