- Muchas notas - Fran Acién

20230805 - U-Boot process

U-Boot is the piece of software that boot an operating system. It is the one that is run on the MangoPi/lichee. I am trying to understand it in order to add overlays to it.

The order of loading different files in U-Boot is generally as follows:

  1. U-Boot Binary: This is the first thing that gets loaded. It contains the U-Boot bootloader, which is responsible for initiating the boot process. In your case, this could be handled by variables like boot_efi_binary or boot_efi_bootmgr in the environment variables you’ve provided.

  2. Device Tree Blob (DTB): The device tree is a data structure for describing hardware. It is not specific to any particular operating system. Instead, a device tree can provide a boot program with the information it needs to boot the system. The variable load_efi_dtb or fdtfile would handle loading the base device tree.

  3. Overlays: Overlays are a way of modifying the device tree structure to customize or specialize the hardware configuration without modifying the base DTB. According to the script you’ve provided, overlays are loaded after the base DTB, following the list from the /boot/overlay.txt file. The load_overlays_from_file function is doing this.

  4. Kernel Image: This is the operating system kernel that will be loaded and executed. The variable kernel_addr_r seems to be the one for the kernel address.

  5. Ramdisk (optional): A Ramdisk or initrd (initial ramdisk) is a scheme employed by various Unix-like operating systems to load a temporary root file system into memory. ramdisk_addr_r would be the relevant variable in your environment.

  6. Boot Command or Boot Script: This is the last part of the boot process where the boot command is executed or the boot script is run, which eventually boots into the operating system. This could be handled by bootcmd, bootcmd_dhcp, bootcmd_fel or other similar environment variables. In your case, it seems the boot.scr U-Boot script is being used.

while (get next bootdev)
   while (get next bootmeth)
       while (get next bootflow)
           try to boot it
  • bootdevs -> boot_targets (mmc0 mmc1 usb pxe)
  • bootmeths -> bootmeths (extlinux efi)
  • bootflow -> distro_bootcmd. It specifies a kernel, a ramdisk (initrd) and a directory from which to load devicetree files

Modifying variables of U-Boot

printenv
setenv scan_dev_for_boot "echo Sscanning ${devtype} ${devnum}:${distro_bootpart}...; for prefix in ${boot_prefixes}; do echo "SDSD"; run scan_dev_for_extlinux; echo "GHGHG"; run scan_dev_for_scripts; done;run scan_dev_for_efi;"
boot

Load overlays with U-Boot

This document explains how to modify U-Boot in order to load custom overlays on startup. It is by adding some info to the boot.scr of U-Boot. This works in the bast ammount of OS, but not in the official ubuntu becuase the overlay is run by Ubuntu. In that case read 20230806 - How to add your overlay to any Linux and 20230805 - Grub for adding devicetree overlays

Code from th U-Boot of Lichee human readable

# Define the function for scanning the device for boot
scan_dev_for_boot = 
    # Echo the details of the device being scanned
    echo "Scanning ${devtype} ${devnum}:${distro_bootpart}..."; 

    # Loop through the prefixes for the boot
    for prefix in ${boot_prefixes}; do 
        
        echo "Looking into prefix ${prefix}";
        # Run the function for scanning the device for extlinux
        run scan_dev_for_extlinux; 
        
        echo "Looking into dev scripts";
        # Run the function for scanning the device for scripts
        run scan_dev_for_scripts; 
    done;
    
    echo "Done with prefixes, now booting efi"
    
    # Run the function for scanning the device for EFI (Extensible Firmware Interface)
    run scan_dev_for_efi;


# Define function for scanning the boot partition of the device
scan_dev_for_boot_part = 
    # List the bootable partition of the device
    part list ${devtype} ${devnum} -bootable devplist;

    # If 'devplist' environment variable doesn't exist, then set 'devplist' to 1
    env exists devplist || setenv devplist 1; 

    # Loop through the boot partitions in 'devplist'
    for distro_bootpart in ${devplist}; do 
        # If the filesystem type of the boot partition is valid,
        # then run the function for scanning the device for boot
        if fstype ${devtype} ${devnum}:${distro_bootpart} bootfstype; then 
            run scan_dev_for_boot; 
        fi; 
    done; 

    # Set 'devplist' environment variable
    setenv devplist

# Define function for scanning the device for EFI (Extensible Firmware Interface)
scan_dev_for_efi = 
    setenv efi_fdtfile ${fdtfile};
    
    # Loop through the prefixes in efi_dtb_prefixes
    for prefix in ${efi_dtb_prefixes}; do 
    
          # If the specific device tree file exists in the devices boot partition, 
          # then load the EFI Device Tree Blob (DTB)
          if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${efi_fdtfile}; then 
                echo \"Loading dtb ${prefix}${efi_fdtfile}\";
                run load_efi_dtb; 
          fi;
    
          # End the loop
    done;
    
    echo \"Running boot_efi_bootmgr\";
    # Run the function for booting the EFI Boot Manager
    run boot_efi_bootmgr;
    
    echo \"Testing if EFI file exists\";
    
    # If the EFI removable media binary exists in the devices boot partition,
    # then echo a message indicating it was found, run the function for booting 
    # the EFI binary, and echo a message indicating the EFI load failed, before continuing
    if test -e ${devtype} ${devnum}:${distro_bootpart} efi/boot/bootriscv64.efi; then 
          echo \"Found EFI removable media binary efi/boot/bootriscv64.efi\"; 
          run boot_efi_binary; 
          echo \"EFI LOAD FAILED: continuing...\"; 
    fi; 
    
    # Reset the efi_fdtfile environment variable
    setenv efi_fdtfile


# Define function for scanning the device for extlinux (a bootloader)
scan_dev_for_extlinux = 
    # If the specific extlinux configuration file exists in the device's boot partition, 
    # then echo a message indicating it was found, run the function for booting 
    # extlinux, and echo a message indicating the script failed, before continuing
    if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${boot_syslinux_conf}; then 
        echo "Found ${prefix}${boot_syslinux_conf}"; 
        run boot_extlinux; 
        echo "SCRIPT FAILED: continuing..."; 
    fi


# Define function for scanning the device for scripts
scan_dev_for_scripts = 
    # For each script in the boot scripts list
    for script in ${boot_scripts}; do
        # If the specific script file exists in the device's boot partition
        if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${script}; then 
            # Echo a message indicating the U-Boot script was found
            echo "Found U-Boot script ${prefix}${script}"; 
            # Run the function for booting a script
            run boot_a_script; 
            # Echo a message indicating the script failed before continuing
            echo "SCRIPT FAILED: continuing..."; 
        fi; 
    done


# Define function for scanning the serial flash for scripts
scan_sf_for_scripts = 
    # Read from the serial flash memory at the specified offset and size, storing the result at the script address
    ${devtype} read ${scriptaddr} ${script_offset_f} ${script_size_f}; 
    # Source the script stored at the script address
    source ${scriptaddr}; 
    # If the script fails to run or complete, print "SCRIPT FAILED: continuing..."
    echo "SCRIPT FAILED: continuing...";

The output is:

witch to partitions #0, OK
mmc0 is current device
"Scanning ${devtype} ${devnum}:${distro_bootpart}..."
"Looking into prefix ${prefix}"
"Looking into dev scripts"
"Done with prefixes, now booting efi"
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
Scanning disk mmc@4020000.blk...
Scanning disk mmc@4021000.blk...
Disk mmc@4021000.blk not ready
Found 7 disks
** Unable to read file ubootefi.var **
Failed to load EFI variables
BootOrder not defined
EFI boot manager: Cannot load any image
Found EFI removable media binary efi/boot/bootriscv64.efi
151552 bytes read in 28 ms (5.2 MiB/s)
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
Booting /efi\boot\bootriscv64.efi

V2

> boot
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:f...
Loading dtb 
Failed to load '/allwinner/sun20i-d1-lichee-rv.dtb'
Loading dtb 
Failed to load '/dtb/allwinner/sun20i-d1-lichee-rv.dtb'
Loading dtb 
Failed to load '/dtb/current/allwinner/sun20i-d1-lichee-rv.dtb'
Running boot_efi_bootmgr
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
Scanning disk mmc@4020000.blk...
Scanning disk mmc@4021000.blk...
Disk mmc@4021000.blk not ready
Found 7 disks
** Unable to read file ubootefi.var **
Failed to load EFI variables
BootOrder not defined
EFI boot manager: Cannot load any image
Testing if EFI file exists
Found EFI removable media binary efi/boot/bootriscv64.efi
151552 bytes read in 28 ms (5.2 MiB/s)
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
Booting /efi\boot\bootriscv64.efi

From ths output I discovered important things! The overlays are loaded on the EFI. And the EFI us loading grub.… so the device tree is being loaded by the grub!

Extlinux

Extlinux is a bootloader that is part of the SYSLINUX Project. SYSLINUX is a suite of lightweight IBM PC MBR bootloaders for starting up computers with the Linux kernel.

In the context of the U-Boot script provided, scan_dev_for_extlinux is a function that checks for the existence of a SYSLINUX configuration file on the boot partition. If it finds the configuration file, it attempts to boot using extlinux. This provides flexibility for different boot scenarios, depending on the available filesystem and setup.

EFI

EFI, which stands for Extensible Firmware Interface, is a specification that defines a software interface between an operating system and platform firmware.

In the U-Boot script provided, scan_dev_for_efi is a function that sets up and attempts to boot an EFI application if one is found on the boot partition. This shows that the system has the ability to boot from an EFI application, providing flexibility in how the system is started.

Boot script

In the project of Armbian, they give some U-Boot script examples