Das U-Boot Logo
  • Build U-Boot
  • Learn about U-Boot
  • Use U-Boot
  • Develop U-Boot
  • U-Boot API documentation
  • Architecture-specific doc
  • Board-specific doc
    • ACER
    • Actions
    • Advantech
    • Andes Tech
    • Allwinner (sunxi) boards
    • Amlogic
    • Anbernic
    • Apple
    • Arm Ltd
    • Aspeed
    • ASUS
    • Atmel
    • Beacon
    • BeagleBoard.org
    • Broadcom
    • BSH Hausgeraete GmbH
    • Canaan
    • Cloos
    • Congatec
    • Cool Pi
    • Coreboot
    • Emcraft
    • Emulation
    • Gateworks
    • Google
    • Highbank
    • HiSilicon
    • HTC
    • Intel
    • Kontron
    • Lenovo
    • LG
    • Liebherr
    • Mediatek
    • Microchip
    • Microsoft
    • Motorola
    • NVIDIA
    • NXP Semiconductors
    • OpenPiton
    • OUYA
    • Pegatron
    • PHYTEC
    • Purism SPC
    • Qualcomm
    • Qnap
    • Renesas
    • Rockchip
    • Samsung
      • Samsung 2017 A series phones
      • WinLink E850-96 board
        • Overview
        • Boot Flow
        • Boot Device Configuration
        • Building U-Boot
        • Flashing Overview
        • Flashing U-Boot from LK (Initial)
        • Flashing Linux Images
        • Flashing Android Images
        • Flashing Bootloaders using DFU
        • Flashing Bootloaders using Fastboot
        • Updating BLs using Capsule Update
        • Booting Overview
        • Booting with efi_mgr Method
        • Booting with efi Method
        • Booting with extlinux Method
        • Booting with script Method
        • Booting with pxe Method
        • Booting from USB Flash Drive
        • Booting Android with GBL
        • EFI System Partition
        • Loadable Firmware
        • Ethernet and USB Host Support
        • References
      • Samsung Exynos Generic ARMv8 Boards (for mobile devices)
      • U-Boot for the Samsung N1 device family
    • Schneider Electric
    • Sielaff
    • Siemens
    • SiFive
    • Sipeed
    • Socionext
    • Sophgo
    • SpacemiT
    • STMicroelectronics
    • StarFive
    • ST-Ericsson
    • TBS
    • T-HEAD
    • Theobroma Systems
    • Texas Instruments
    • Toradex
    • Variscite
    • WEXLER
    • XenGuestARM64
    • Xiaomi
    • Xilinx
  • Android-specific doc
  • Chromium OS-specific doc
  • Index
Das U-Boot
  • Board-specific doc
  • Samsung
  • WinLink E850-96 board
  • View page source

WinLink E850-96 board

Overview

WinLink’s E850-96 board [1] is based on the Samsung Exynos850 SoC and follows the 96Boards Consumer Edition specification [2]. This makes it possible to use 96Boards mezzanine boards [3] with it. It’s an open-hardware board, and the hardware design files were published [4] along with supported software and related documentation [5].

U-Boot can be used on E850-96 instead of the original (factory pre-flashed) Samsung’s LittleKernel based bootloader [6]. Because the E850-96’s version of FWBL1 [7] doesn’t verify bootloader’s signature, there is no need to sign the U-Boot binary. This means the U-Boot binary can be flashed to eMMC instead of the LittleKernel bootloader, and it will just work.

The BL2 bootloader sets up DRAM and runs the final bootloader (U-Boot) from DRAM, so there is no need for U-Boot SPL. It’s enough to have only U-Boot proper (u-boot.bin).

Boot Flow

The boot path for Exynos850 is shown in Figure 1.

../../_images/exynos850-boot-architecture.svg

Figure 1: Exynos850 SoC boot architecture

Legend:

  • BL0: Boot ROM code

  • BL1: Software part of Boot ROM

  • EPBL: Exynos Primary Boot Loader

  • BL2: Initializes CMU and DRAM and runs the final bootloader

  • Bootloader: The final bootloader (e.g. U-Boot); it’s also called BL33 in terms of ARM boot flow

  • EL3_MON: EL3 monitor (trusted firmware, handles SMC calls); it’s also called BL31 in terms of ARM boot flow

  • LDFW: Loadable Firmware (loaded by U-Boot)

On a “power-on” event, the processor starts executing code at address 0x00000000 where the internal ROM (iROM) is mapped. iROM contains the Boot ROM code (BL0). All other bootloaders are stored in external storage (usually eMMC), so the user can update those later.

By default the board is configured to boot from eMMC. On power-on, the Boot ROM code (BL0) jumps to the beginning of eMMC boot partition 0 (mmc0boot0) where BL1 must reside. The boot flow then progresses through multiple various bootloaders (as shown in Figure 1), eventually ending up executing U-Boot (designated as “Bootloader” in the figure).

Boot Device Configuration

The boot device can be chosen using the SW1 DIP switch. It controls the eXternal Operating Mode (XOM) SoC pins. Table 1 shows how the boot source can be configured using the SW1.

Table 1: Boot device configuration using the SW1 DIP switch

SW1 pin positions (1234)

Boot order

0000

1st: eMMC, 2nd: USB

1000

1st: USB, 2nd: -

0100

1st: SD card, 2nd: USB

1100

1st: eMMC, 2nd: SD card

The default boot source is eMMC (all SW1 pins are “OFF”, i.e. in “down” position). USB boot method can be useful for unbricking the board (in case some incorrect or broken bootloader was flashed to eMMC by mistake), which allows one to upload and execute all bootloaders over USB. See the dltool [8] README file for details. SD card boot was never tested on E850-96, so it leaves two options: eMMC boot (regular boot) or USB boot (mainly used for unbricking the board and during the bootloader development process).

Building U-Boot

Build U-Boot binary from source code (using AArch64 baremetal GCC toolchain):

export PATH=<toolchain path>/bin:$PATH
export CROSS_COMPILE=<toolchain prefix>
make e850-96_defconfig
make

The output file is u-boot.bin.

Flashing Overview

Note

In case the board is bricked for some reason, the dltool [8] can be used to unbrick and revive it. This tool performs USB boot and uploads all E850-96 bootloaders over USB, which are then executed on the board. The loaded bootloader (e.g. LittleKernel or U-Boot) further enters fastboot mode, so that the user can flash the functional bootloader binary (U-Boot or LittleKernel [7]) to eMMC using fastboot tool. See the dltool README file for more details about the procedure.

eMMC layout on E850-96 looks like this:

  • User area of eMMC: contains GPT partition table with OS partitions (either Linux or Android)

  • Boot Partition 0 (mmc0boot0): contains all bootloaders (firmware)

  • Boot Partition 1 (mmc0boot1): contains U-Boot environment

There are several methods enabled in U-Boot for flashing software to eMMC on E850-96:

  • fastboot (USB): most useful for flashing OS partitions (Linux or Android)

  • DFU (USB): convenient for flashing bootloaders (firmware) to boot partition 0

  • Capsule Update: EFI mechanism, can update bootloaders without the need to use USB

Flashing U-Boot from LK (Initial)

The original E850-96 board is shipped with the LittleKernel-based bootloader flashed in eMMC. This LK bootloader allows flashing images in the bootloader area of eMMC boot partition 0 using fastboot just like flashing a regular partition in the user area of eMMC.

So to replace the original bootloader with U-Boot, first boot into fastboot mode (as described in the board software documentation [9], in section 6 “Flashing the Software”):

  • Connect the power cable to your E850-96 board

  • Press the “POWER” button (SW2) for 1 sec to start booting the bootloader

  • Press and hold the “VOL_UP” button (SW4) for 7 seconds

Flash the U-Boot binary:

fastboot flash bootloader u-boot.bin
fastboot reboot

U-Boot will boot up to the shell. Configure the default U-Boot environment before starting to work with U-Boot:

env default -f -a
env save

Flashing Linux Images

The Linux partition table contains only two partitions:

  1. esp (EFI System Partition)

  2. rootfs

Format eMMC to have Linux partition table (using the default $partitions definitions):

gpt write mmc 0 $partitions

…or do the same using fastboot:

fastboot oem format

Enter fastboot mode on your device:

fastboot usb 0

And then flash the images:

fastboot flash esp esp.img
fastboot flash rootfs rootfs.img

Flashing Android Images

Use $partitions_android as current partition definitions:

setenv partitions_linux $partitions
setenv partitions $partitions_android
env save

Format eMMC to have Android partition table:

gpt write mmc 0 $partitions

…or do the same using fastboot:

fastboot oem format

Currently, flashing Android images using U-Boot’s fastboot implementation doesn’t work on E850-96. Instead it’s recommended to boot the GBL EFI app (Android Generic Bootloader) [10] and use its fastboot implementation. See Booting Android with GBL section for details. But first the ESP image containing the GBL app has to be flashed.

Enter fastboot mode on your device:

fastboot usb 0

And flash the ESP image:

fastboot flash esp esp.img
fastboot reboot

Now configure EFI boot variables (from U-Boot shell) to boot GBL app by default, as described in the Booting Overview section. Boot GBL and enter fastboot mode.

The Android flashing procedure is complex and may vary across different Android versions. So there is usually a flashing script (or flashing instructions) provided with AOSP images for the E850-96 board to flash all Android images to eMMC. Run it:

./flash-all.sh

Flashing Bootloaders using DFU

All bootloaders are stored in eMMC boot partition 0 (mmc0boot0), which doesn’t have any partition table (it’s a raw storage area). Hence the most convenient way to update bootloaders over USB on E850-96 board is using DFU (Device Firmware Upgrade) protocol, because it allows one to flash images to a particular area of boot0.

DFU uses only USB endpoint 0 (EP0), which means this flashing method is quite slow. That’s why it’s better to limit its usage for flashing only bootloaders (which are relatively small binaries), and not use it for flashing rootfs and other big images.

eMMC boot partition 0 (mmc0boot0) on E850-96 board has the next layout (all offsets on the left are specified in 512B blocks):

             boot0 partition (4 MiB)
   0x0 +----------------------------------+
       |         fwbl1 (12 KiB)           |    // BL1 bootloader
  0x18 +----------------------------------+
       |         epbl (76 KiB)            |    // EPBL bootloader
  0xb0 +----------------------------------+
       |         bl2 (256 KiB)            |    // BL2 bootloader
 0x2b0 +----------------------------------+
       |         dram_train (16 KiB)      |    // (not a bootloader)
 0x2d0 +----------------------------------+
       |         ect_test (50 KiB)        |    // (not a bootloader)
 0x334 +----------------------------------+
       |         acpm_test (130 KiB)      |    // (not a bootloader)
 0x438 +----------------------------------+
       |         bootloader (2 MiB)       |    // U-Boot
0x1438 +----------------------------------+
       |         el3_mon (256 KiB)        |    // EL3 monitor firmware
0x1638 +----------------------------------+

This layout information is stored in the $dfu_alt_info U-Boot environment variable, so one can provide a particular bootloader name to dfu-util tool to update it.

Enter DFU mode on the board:

dfu 0 mmc 0

To update U-Boot via DFU:

dfu-util -D u-boot.bin -a bootloader

To update another bootloader just use the names from the boot0 partition layout above in -a option.

Flashing Bootloaders using Fastboot

It’s also possible to use fastboot to flash the whole mmc0boot0 HW partition. It might not be as convenient as using the DFU method though, as an image containing all binaries has to be prepared first.

One way to generate such an image is to use dd tool, e.g.:

# $1: output image file
# $2: input image file to append
# $3: offset to append after, in LBA (512 bytes)
# $4: size to append, in LBA (512 bytes)
append() {
    dd if="$2" of="$1" bs=512 conv=notrunc seek=$(($3)) count=$(($4))
}

# Create boot0 image
dd if=/dev/zero of=$img bs=4M count=1
append boot0.img fwbl1.img    0x0     0x18
append boot0.img epbl.img     0x18    0x98
append boot0.img bl2.img      0xb0    0x200
append boot0.img u-boot.bin   0x438   0x1000
append boot0.img el3_mon.img  0x1438  0x200

Once the image is generated, it can be flashed like this:

fastboot flash mmc0boot0 boot0.img

Updating BLs using Capsule Update

The bootloaders (in eMMC boot partition 0) can be updated using the EFI Capsule Update mechanism. It doesn’t require using USB, so it can be useful in some scenarios.

It works like this:

  1. Generate the “capsule” file for the desired bootloader binary

  2. Copy this capsule file to a particular location in ESP partition

  3. Reboot the board

U-Boot will handle it automatically, using the next procedure:

  1. Locate the capsule file and update the corresponding bootloader

  2. Remove the capsule file from ESP after updating

  3. Reboot again to make use of the updated bootloader

To generate capsule files, some extra information is needed for each bootloader, which is provided in Table 2 below.

Table 2: Image indexes and GUIDs for Capsule Update

Image index

Image name

GUID

1

fwbl1

181cd3f2-e375-44d2-8078-3221e1dfb95e

2

epbl

66c1a54d-d149-415d-aada-b8aee499b370

3

bl2

89471c2a-6c8d-4158-acad-23d3b2873d35

4

bootloader

629578c3-ffb3-4a89-ac0c-611840727779

5

el3_mon

df5718a2-930a-4916-bb19-3213214d8486

The kernel also exposes this information via the EFI ESRT table in SysFS, in /sys/firmware/efi/esrt/entries.

For example, to update the U-Boot binary, the capsule file can be generated like this:

./tools/mkeficapsule --index 4 \
                       --guid 629578c3-ffb3-4a89-ac0c-611840727779 \
                       u-boot.bin capsule4.bin

The resulting capsule4.bin should be copied to ESP partition, in this directory:

/EFI/UpdateCapsule/

Then after reboot U-Boot will update the bootloader area in eMMC boot partition 0 (boot0) and remove the capsule file. It’s done by the EFI boot manager executed as a part of Standard Boot. To confirm the bootloader was updated U-Boot will print the next message in the serial console:

Applying capsule capsule4.bin succeeded.
Reboot after firmware update.

Booting Overview

OS booting is performed using a U-Boot mechanism called Standard Boot. The Standard Boot resembles the BIOS boot menu on a PC: it allows one to choose which boot source to use, specify the desired boot order, etc. All OS booting related information (like the next bootloader file, kernel image location, device tree blob location, kernel parameters, etc.) is provided in corresponding files in EFI System Partition (see EFI System Partition section for details), or in rootfs partition. This way there is no need to modify U-Boot (or U-Boot environment) each time the OS is modified or replaced.

With EFI enabled in U-Boot, that covers the requirements of ARM SystemReady compliance program [11], making it easy for end users to install and run different OSes on the same device, and be able to do that in a similar manner across different devices. For example, using Standard Boot and EFI capabilities enabled in U-Boot it should be possible for the user to insert a USB media drive with a Debian installer into the E850-96 board and install Debian OS to eMMC, the same way it’s done on a PC (or do the network installation).

When the autoboot happens on U-Boot countdown timeout, this command (bootcmd) is automatically executed:

bootflow scan -lb

It goes through all present storage devices, and searches for all available boot methods on all partitions that have the bootable flag, and boots the first found method. Next partitions will be searched:

  • Linux: both esp and rootfs partitions are bootable

  • Android: only esp is bootable

Next boot methods are currently enabled in E850-86 U-Boot:

Table 3: Standard Boot methods

Method

Description

efi_mgr

EFI boot manager flow (booting using Boot* EFI variables)

efi

EFI boot from /EFI/BOOT/BOOTAA64.EFI file

extlinux

Booting using /boot/extlinux/extlinux.conf file from rootfs

script

Booting using /boot/boot.scr U-Boot script from rootfs

pxe

Network boot using PXE protocol

The most flexible, convenient and modern boot method is efi_mgr. It will be used by default (if EFI Boot* variables are configured properly). If another boot method or boot device should be used by default, the desired boot ordering can be controlled with $boot_targets and $bootmeths environment variables, as described in Standard Boot Overview documentation.

Booting with efi_mgr Method

The 'efi_mgr' boot method can run EFI apps by using the configuration from Boot* EFI variables. It’s a recommended boot method and should be preferred if there are no other requirements.

For example it can run:

  • GRUB EFI app (booting Debian OS further)

  • Android GBL EFI app (booting Android OS)

  • Linux kernel image (EFI stub), mounting further Debian rootfs from eMMC

The most convenient way to configure Boot* EFI variables is by using the eficonfig U-Boot command. It’s an interactive pseudo-graphic menu-like boot configurator.

For example, let’s configure EFI boot variables for booting GRUB EFI app from ESP partition. First, run eficonfig command:

eficonfig

Add GRUB EFI app to the boot list, and make it the highest priority boot source:

  1. Select “Add Boot Option” menu item

  2. Set “Description:” to “GRUB”

  3. Press “File:” -> “Select File” -> “mmc 0:1”, and select the GRUB EFI app (e.g. /EFI\debian\grubaa64.efi)

  4. The created entry should look like this:

    Description: GRUB
    File: mmc 0:1/EFI\debian\grubaa64.efi
    
  5. Press “Save”

  6. Press “Change Boot Order” and move the “GRUB” item on the top (using “+” key)

  7. Press “Save”

  8. Press “Quit”

Now reboot the board (with reset command); U-Boot will run GRUB, which should boot Debian OS. So the whole execution chain will look like this:

U-Boot -> 'bootflow scan -lb' (bootcmd) -> efi_mgr -> GRUB -> Debian

The same way Android GBL can be booted:

Description: Android GBL
File: mmc 0:1/EFI\android\gbl_aarch64.efi

Linux kernel can be booted directly, as modern kernel images usually have EFI stub format (when CONFIG_EFI_STUB=y kernel option is enabled). An example of such boot configuration:

Description: Debian
File: mmc 0:1/EFI\Linux\Image
Fdt File: mmc 0:1/EFI\Linux\exynos850-e850-96.dtb
Optional Data: root=/dev/mmcblk0p2 rootwait rw console=ttySAC0,115200n8

Booting with efi Method

The 'efi' boot method just executes the /EFI/BOOT/BOOTAA64.EFI file from the ESP partition, which should be some kind of an OS loader. For example it can be systemd-boot UEFI boot manager, which is provided by systemd-boot Debian package. This method is probably only useful if the system has an EFI bootloader which resides at the fixed path mentioned above. It’s not very flexible and usually the 'efi_mgr' method should be preferred for running EFI apps.

To run the 'efi' boot method (assuming it has Seq=1 order in 'bootflow scan -l' output):

bootflow scan -l
bootflow select 1
bootflow boot

Booting with extlinux Method

The 'extlinux' boot method looks for the extlinux.conf configuration file, reads it and uses the obtained information to find Linux kernel and dtb, and run it with kernel parameters also supplied by extlinux.conf. This method is useful if it’s not possible to do EFI boot.

The extlinux.conf file can be generated automatically with u-boot-update command (from Linux). An example of /boot/extlinux/extlinux.conf (stored in rootfs):

default l0
menu title U-Boot menu
prompt 0
timeout 50

label l0
    menu label Debian GNU/Linux 6.16.0-09930-gecbe0323440c
    linux /boot/vmlinuz-6.16.0-09930-gecbe0323440c
    fdt /usr/lib/linux-image-6.16.0-09930-gecbe0323440c/exynos/exynos850-e850-96.dtb
    append root=/dev/mmcblk0p2 rootwait rw console=ttySAC0,115200n8

To run the extlinux boot method (assuming it has Seq=2 order in 'bootflow scan -l' output):

bootflow scan -l
bootflow select 2
bootflow boot

Booting with script Method

The 'script' boot method looks for the boot.scr file, reads it and executes U-Boot commands specified there. It can be useful for debugging and development purposes, but it’s outdated and not very secure, and should be avoided in production.

First, prepare the boot.txt file with OS boot instructions, for example:

setenv mmcroot     2
setenv console     ttySAC0,115200n8
setenv kernel_file Image
setenv fdtfile     exynos/exynos850-e850-96.dtb
setenv loadaddr    0x80000000
setenv fdt_addr_r  0x8c000000

echo Booting Linux from eMMC...
mmc dev $mmcdev
mmc rescan
setenv bootargs console=$console root=/dev/mmcblk${mmcdev}p${mmcroot} rootwait rw
load mmc $mmcdev:$mmcroot $fdt_addr_r /boot/$fdtfile
load mmc $mmcdev:$mmcroot $loadaddr /boot/$kernel_file
booti $loadaddr - $fdt_addr_r

Generate boot.scr file (in legacy U-Boot image format) like this:

mkimage -A arm64 -O linux -T script -n "E850-96 Debian bootscript" -C none \
          -d boot.txt boot.scr

Then copy it to rootfs, e.g. at /boot/boot.scr path. The Standard Boot will be able to find it by its name, and execute it to boot the OS.

Booting with pxe Method

The 'pxe' boot method implements PXE protocol, and performs network boot over Ethernet. When used together with NFS for mounting the rootfs over the network, it may be one of the most convenient boot methods for development. That’s because it makes it possible to modify rootfs files (like kernel modules or programs that are being developed) on the host machine, which is instantly reflected on the board side due to the network-transparent nature of NFS.

PXE protocol requires TFTP and DHCP servers to be configured on the host machine:

  • DHCP server should be configured to provide an IP address to your board

  • TFTP server should be configured to hand out the configuration file (in extlinux format) specifying loadable binaries.

    An example of a server-side TFTP directory:

    /srv/tftp/
    |-- exynos
    |   `-- exynos850-e850-96.dtb
    |-- Image
    `-- pxelinux.cfg
        `-- 01-02-36-f5-1c-81-13
    

    where '01-02-36-f5-1c-81-13' file contains extlinux configuration for TFTP to load and boot. The name of this file has to be in the format of '01-MAC-address'. The Ethernet MAC address in this case is 02-36-f5-1c-81-13, and it can be looked up in the $ethaddr environment variable in U-Boot:

    => env print ethaddr
    ethaddr=02:36:f5:1c:81:13
    

    An example of such configuration file is:

    prompt 0
    timeout 5
    default local
    
    menu title PXE Boot Menu serving from joe-pc
    
    label local
        menu label Debian GNU/Linux
        linux Image
        fdt exynos/exynos850-e850-96.dtb
        append console=ttySAC0,115200n8 root=/dev/nfs nfsroot=${serverip}:/srv/nfs/debian,nolock,nfsvers=4 rw ip=dhcp
    
  • If it’s desired to mount the rootfs over NFS (instead of mounting it from eMMC or using an initrd ramdisk) – NFS server should be configured accordingly. E.g. it can share Debian rootfs in /srv/nfs/debian/ directory.

    NFS support should also be enabled in the kernel. Although NFS options are already enabled in ARM64 defconfig, the USB PHY and LAN9514 (Ethernet) drivers must be made built-in, so the next change is needed:

    arch/arm64/configs/defconfig
    ----------------------------
    
    # Keep USB PHY driver built-in, as the Ethernet controller sits on USB bus
    CONFIG_PHY_EXYNOS5_USBDRD=y
    CONFIG_TYPEC=y
    
    # Keep Ethernet driver built-in
    CONFIG_USB_NET_SMSC95XX=y
    CONFIG_USB_USBNET=y
    

To enable PXE boot:

  1. First, make sure to enable USB host mode in U-Boot, as discussed in Ethernet and USB Host Support section

  2. Check if 'pxe' boot method is present in 'bootflow scan -l' output. It should look like this:

    Seq  Method       State   Uclass    Part  Name                      Filename
    ---  -----------  ------  --------  ----  ------------------------  ----------------
      5  pxe          ready   ethernet     0  smsc95xx_eth.bootdev.0    extlinux/extlinux.conf
    
  3. Select and boot it:

    bootflow select 5
    bootflow boot
    

It’ll run the network boot process which works like this:

  • U-Boot will obtain an IP address over DHCP from the host

  • U-Boot will obtain the extlinux configuration file over TFTP from the host

  • U-Boot will use the information from extlinux file to consequently obtain the Linux kernel image and device tree blob from the host

  • U-Boot will boot the Linux kernel, providing kernel parameters from the extlinux file

  • Linux kernel will use the kernel parameters to mount the rootfs over NFS

The Ethernet MAC address ($ethaddr) will be passed from U-Boot to Linux kernel via device tree.

Booting from USB Flash Drive

It’s possible to boot an OS from a USB flash drive. That might be useful to prevent eMMC part wearing off, or for development reasons.

eMMC will still be used for its boot0 and boot1 partitions (where all bootloaders and a U-Boot environment are stored, respectively). But it’s possible to make U-Boot load the LDFW firmware from USB media by setting $bootdev* environment variables accordingly. There are three environment variables that can be used to specify the storage where the loadable firmware should be loaded from:

  • bootdev: block device interface name ("mmc" or "usb")

  • bootdevnum: block device number

  • bootdevpart: partition number

Assuming that the USB drive layout follows the same partitioning scheme as defined in $partitions, it’s enough to only set $bootdev like this:

setenv bootdev usb
env save

Another thing to be aware of: in order to perform USB boot the USB PHY kernel driver has to be built-in. For example, in ARM64 defconfig it’s specified as a loadable module, not a built-in one. So the next change to the kernel config might be needed:

arch/arm64/configs/defconfig
----------------------------

# Needed for boot from USB storage (mounting rootfs from USB drive)
CONFIG_PHY_EXYNOS5_USBDRD=y
CONFIG_TYPEC=y

Follow the instructions below to boot from a USB storage device:

  1. First, make sure to enable USB host mode in U-Boot, as discussed in Ethernet and USB Host Support section

  2. Format your USB stick to follow the $partitions layout:

    Zero /dev/sdX:
    # dd if=/dev/zero of=/dev/sdX bs=1M count=100
    
    Create GPT table matching eMMC:
    # cfdisk
        - 1st partition: EFI System (128 MiB)
        - 2nd partition: Linux filesystem (all remaining space)
    
    Set ESP partition (#1) type to EFI System (0xEF00):
    # sgdisk --typecode=1:ef00 /dev/sdX
    # partprobe /dev/sdX
    
    Format both partitions:
    # mkfs.fat -F 32 /dev/sdX1
    # mkfs.ext4 /dev/sdX2
    
    Set FS labels for partitions:
    # fatlabel /dev/sdX1 ESP
    # e2label /dev/sdX2 rootfs
    
    Set GPT names for partitions:
    # gdisk /dev/sdX
    c          - change a partition's name
    1          - partition number
    esp        - new name
    c          - change a partition's name
    2          - partition number
    rootfs     - new name
    w          - write table to disk and exit
    
    Set bootable flag for rootfs partition:
    # gdisk /dev/sdX
    x           - extra functionality (experts only)
    a           - set attributes
    2           - partition number
    2           - legacy BIOS bootable
    Enter       - exit
    w           - write table to the disk and exit
    y           - yes, want to proceed
    
  3. Copy Debian rootfs and ESP to your USB flash drive:

    dd if=esp.img of=/dev/sdX1 bs=64M
    dd if=rootfs.img of=/dev/sdX2 bs=64M status=progress
    
  4. Insert the prepared USB media into the E850-96 USB port

  5. Tell U-Boot to search for LDFW firmware on USB stick:

    setenv bootdev usb
    env save
    
  6. Erase eMMC partition table to make U-Boot use ESP from USB drive:

    mmc dev 0
    mmc erase 0 0x2400
    reset
    
  7. Make sure 'bootflow scan -l' is able to detect boot methods on your USB stick

  8. Setup EFI variables (using eficonfig command) for booting from USB stick with efi_mgr boot method, as described in Booting Overview section

Now U-Boot will be able to boot the OS from the USB drive using Standard Boot.

Booting Android with GBL

Warning

Android GBL support for E850-96 in U-Boot is experimental at the moment, and it requires additional actions from the user to make GBL work with U-Boot.

Android GBL (Generic Bootloader) [10] is an EFI app that acts as an Android OS bootloader. It’s able to recognize and boot different versions of Android OS, and provides its own fastboot protocol implementation. Nowadays GBL is a preferred method of running Android, and it’s recommended to use it instead of U-Boot Android booting capabilities.

Unfortunately, GBL support in U-Boot hasn’t been upstreamed yet. The reference U-Boot tree for GBL is Vim3 U-Boot [12]. There was also some independent GBL work done in “Devboards for Android” U-Boot tree [13]. In order to be able to run GBL with upstream U-Boot, next two patches have to be cherry-picked:

  • ANDROID: [efi] Implement EFI_ANDROID_BOOT_PROTOCOL

  • ANDROID: [efi] EFI_ANDROID_BOOT_PROTOCOL: Fixup usb_gadget_handle_interrupts()

They can be found in “Devboards for Android” U-Boot tree [13], in wip/sm8x50-gbl-fastboot branch. Cherry-pick those patches:

git remote add db4a https://gerrit.devboardsforandroid.linaro.org/platform/external/u-boot
git fetch db4a
git cherry-pick cdc73ef81fdc
git cherry-pick 7d60b5bbe434

As GBL’s EFI_FASTBOOT_USB_PROTOCOL was recently changed (and it’s not supported in the cherry-picked patches above), GBL source code should be modified by reverting the latest changes and built manually. Follow GBL deployment instructions [14] to obtain GBL source code, and then introduce next changes before building it:

cd bootable/libbootloader
git checkout -b e850-96-functional-fb
git reset --hard f1bc0ca523e1
git cherry-pick 5cd4ad9999ab

Now build GBL and copy the built GBL binary (gbl_aarch64.efi) to your ESP partition, at this path:

/EFI/android/gbl_aarch64.efi

Configure EFI manager to boot GBL EFI app by default, as described in Booting with efi_mgr Method section, and run efi_mgr boot method:

bootflow scan -lb

U-Boot will execute the GBL app. GBL also prints messages to the serial console, starting with:

****Generic Bootloader Application****

Let’s use GBL capabilities to flash and boot Android images (assuming eMMC already has an Android partition table created as described in Flashing Android Images section).

  1. Press Backspace to enter GBL’s fastboot mode. Flash E850-96 Android images as described in corresponding documentation.

  2. Reboot the board and run GBL again. It will boot Android automatically.

GBL was successfully used to run AOSP/main on the E850-96 board using AOSP projects from “Devboards for Android” [15].

EFI System Partition

EFI System Partition (ESP) is required by UEFI specification and needed for EFI boot methods in U-Boot to be functional. Because EFI boot is now the recommended way of booting operating systems (see SystemReady [11]), it has to be properly prepared and flashed to eMMC on the E850-96. It’s needed for both Linux and Android boot (at least when using GBL).

ESP is the first partition in the E850-96 partition table, 128 MiB in size. It must be formatted as FAT, and the bootable flag (“Legacy BIOS bootable” GPT partition attribute, which is 0x4) has to be set for it, to make Standard Boot look for boot methods on it.

The initial ESP image can be prepared like this:

dd if=/dev/zero of=esp.img bs=1M count=128
/sbin/mkfs.fat -F 32 -n ESP esp.img
mmd -i esp.img EFI EFI/BOOT EFI/firmware
mcopy -i esp.img ldfw.bin ::EFI/firmware
mdir -i esp.img ::EFI/firmware

The created ESP image will contain only LDFW firmware (see Loadable Firmware section for details). The same way other files can be added to it.

Here is an example of an ESP partition for E850-96:

/
|-- EFI
|   |-- BOOT
|   |   `-- BOOTAA64.EFI              // systemd-boot
|   |-- Linux
|   |   |-- Image                     // Linux kernel image
|   |   `-- exynos850-e850-96.dtb     // Linux device tree
|   |-- UpdateCapsule
|   |-- android
|   |   `-- gbl_aarch64.efi           // Android GBL
|   |-- debian
|   |   |-- BOOTAA64.CSV              // GRUB
|   |   |-- fbaa64.efi                // GRUB
|   |   |-- grub.cfg                  // GRUB
|   |   |-- grubaa64.efi              // GRUB: EFI app
|   |   |-- mmaa64.efi                // GRUB
|   |   `-- shimaa64.efi              // GRUB
|   |-- firmware
|   |   `-- ldfw.bin                  // Exynos loadable firmware
|   |-- systemd
|       `-- systemd-bootaa64.efi      // systemd-boot
|-- loader
|   |-- entries
|   |   |-- debian.conf               // systemd-boot (created manually)
|   |   `-- grub.conf                 // systemd-boot (created manually)
|   |-- entries.srel                  // systemd-boot
|   |-- loader.conf                   // systemd-boot (modified manually)
|   `-- random-seed                   // systemd-boot
`-- ubootefi.var                      // EFI variables (created by U-Boot)

A simple way to start is to copy only 3 files to the ESP:

  • /EFI/firmware/ldfw.bin

  • /EFI/Linux/Image

  • /EFI/Linux/exynos850-e850-96.dtb

and then run the Linux kernel image (/EFI/Linux/Image) using U-Boot’s efi_mgr boot method, supplying "root=/dev/mmcblk0p2" kernel param to mount Debian rootfs from eMMC. Once in Debian shell, it should be easy to install and configure other bootloaders (like GRUB, systemd-boot, etc.) in ESP.

Once the image with desired files is prepared, it can be flashed to eMMC as described in Flashing Linux Images.

Loadable Firmware

For the E850-96 system to function properly, loadable firmware (LDFW) has to be loaded using an SMC call to the EL3 monitor. It’s needed for both bootloader and kernel, as it makes features like TRNG (true random number generator) functional. U-Boot looks for this firmware on ESP partition, where it should be present at this path:

/EFI/firmware/ldfw.bin

If LDFW binary is present at that location, U-Boot will read and load it during its initialization stage. LDFW binary can be obtained from E850-96 images repository [7].

In case of booting from a media different than eMMC, the location of LDFW can be specified using $bootdev* environment variables. The details are discussed in Booting from USB Flash Drive.

Ethernet and USB Host Support

Warning

With changes suggested in this section, all USB gadget functionality (like fastboot and DFU) will be disabled in U-Boot. This won’t affect the dynamic role switching later in the Linux kernel, as a separate (different) device tree blob is provided to the kernel.

E850-96 has only one USB controller, so it can only work in one role at a time: either USB peripheral, or USB host role. It makes it impossible to use both host ports and the device (micro-USB) port simultaneously. Also, the Ethernet bridge chip (LAN9514) is controlled by the USB host bus, so USB host mode has to be enabled to make Ethernet functional. U-Boot doesn’t support dynamic USB role switching, so in order to enable USB host and Ethernet support, U-Boot’s device tree has to be modified accordingly. And then the micro-USB cable has to be disconnected to make the board circuitry switch the USB lines to a correct USB connector.

By default U-Boot configures the USB controller in peripheral mode. To enable USB host mode, do the following two things:

  1. Modify dts/upstream/src/arm64/exynos/exynos850-e850-96.dts file like this:

     &usbdrd_dwc3 {
    -       dr_mode = "otg";
    +       dr_mode = "host";
            usb-role-switch;
            role-switch-default-mode = "host";
    

    Rebuild and flash the updated U-Boot binary.

  2. Disconnect the micro-USB cable from the board.

To re-enable USB peripheral mode, just revert the above changes.

References

[1]

https://www.96boards.org/product/e850-96b/

[2]

https://www.96boards.org/products/ce/

[3]

https://www.96boards.org/products/mezzanine/

[4]

https://www.96boards.org/documentation/consumer/e850-96b/hardware-docs/

[5]

https://gitlab.com/Linaro/96boards/e850-96/

[6]

https://gitlab.com/Linaro/96boards/e850-96/lk

[7] (1,2,3)

https://gitlab.com/LinaroLtd/e850-96/images.git

[8] (1,2)

https://gitlab.com/LinaroLtd/e850-96/tools/dltool.git

[9]

https://gitlab.com/Linaro/96boards/e850-96/doc

[10] (1,2)

https://source.android.com/docs/core/architecture/bootloader/generic-bootloader

[11] (1,2)

https://www.arm.com/architecture/system-architectures/systemready-compliance-program/systemready-devicetree-band

[12]

https://third-party-mirror.googlesource.com/u-boot/+log/refs/heads/vim3

[13] (1,2)

https://source.devboardsforandroid.linaro.org/platform/external/u-boot/+log/refs/heads/wip/sm8x50-gbl-fastboot

[14]

https://source.android.com/docs/core/architecture/bootloader/generic-bootloader/gbl-dev

[15]

https://source.devboardsforandroid.linaro.org/platform/manifest/

Previous Next

© Copyright The U-Boot development community.

Built with Sphinx using a theme provided by Read the Docs.