[PATCH] doc: samsung: Extend E850-96 documentation to be comprehensive

Sam Protsenko semen.protsenko at linaro.org
Thu Oct 2 04:51:34 CEST 2025


Add more bootloading details for E850-96 board. New sections cover next
topics:

  - Hardware configuration of the boot device
  - Flashing and updating the software (multiple methods)
  - Booting with Standard Boot (multiple methods)
  - EFI System Partition structure for E850-96
  - Loadable firmware (LDFW) note
  - Ethernet and USB Host Support

That documents all recently enabled U-Boot features for E850-96, which
can hopefully make U-Boot more useful for the users and developers of
this platform.

Signed-off-by: Sam Protsenko <semen.protsenko at linaro.org>
---
 doc/board/samsung/e850-96.rst | 1023 +++++++++++++++++++++++++++++++--
 1 file changed, 966 insertions(+), 57 deletions(-)

diff --git a/doc/board/samsung/e850-96.rst b/doc/board/samsung/e850-96.rst
index b435fa8b3533..b449a7f4e354 100644
--- a/doc/board/samsung/e850-96.rst
+++ b/doc/board/samsung/e850-96.rst
@@ -10,26 +10,30 @@ Overview
 WinLink's E850-96 board [1]_ is based on Samsung Exynos850 SoC and follows
 96Boards Consumer Edition specification [2]_. That makes it possible to use
 96Boards mezzanine boards [3]_ along with it. It's an open-hardware board and
-the hardware design files [4]_ were published, along with the supported
-software [5]_ and related documentation.
+the hardware design files were published [4]_, along with the supported
+software and related documentation [5]_.
 
-U-Boot can be used on E850-96 instead of the original Samsung LittleKernel based
-bootloader [6]_. Because FWBL1 [7]_ doesn't verify bootloader's signature, there
-is no need to sign a U-Boot binary. That means U-Boot binary can be flashed into
-``bootloader`` partition (instead of LittleKernel bootloader) and it will just
-work.
+U-Boot can be used on E850-96 instead of the original (factory pre-flashed)
+Samsung's LittleKernel based bootloader [6]_. Because E850-96's version of
+FWBL1 [7]_ doesn't verify bootloader's signature, there is no need to sign the
+U-Boot binary. That means the U-Boot binary can be flashed to eMMC instead of
+the LittleKernel bootloader and it will just work.
 
-Because BL2 bootloader already sets up DRAM and runs the final bootloader
-(U-Boot) from DRAM, there is no need in U-Boot SPL. It's enough to have only
-U-Boot proper (``u-boot.bin``).
+BL2 bootloader sets up DRAM and runs the final bootloader (U-Boot) from
+DRAM, so there is no need in U-Boot SPL. It's enough to have only U-Boot proper
+(``u-boot.bin``).
 
 Boot Flow
 ---------
 
-The boot path for Exynos850 is shown on the figure below.
+The boot path for Exynos850 is shown in :ref:`Figure 1 <figure1>`.
 
-.. image:: img/exynos850-boot-architecture.svg
-  :alt: Exynos850 SoC boot flow
+.. _figure1:
+
+.. figure:: img/exynos850-boot-architecture.svg
+   :align: center
+
+   Figure 1: Exynos850 SoC boot architecture
 
 Legend:
 
@@ -37,24 +41,52 @@ Legend:
 * ``BL1``: Software part of Boot ROM
 * ``EPBL``: Exynos Primary Boot Loader
 * ``BL2``: Initializes CMU and DRAM and runs the final bootloader
-* ``Bootloader``: Final bootloader (e.g. U-Boot); also called BL33 in terms of
-  ARM boot flow
-* ``EL3_MON``: EL3 monitor (trusted firmware, handles SMC calls); also called
-  BL31 in terms of ARM boot flow
-* ``LDFW``: Loadable Firmware
+* ``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)
 
-Unbricking Note
----------------
+On power on the processor starts executing the code at 0x00000000 address where
+the internal ROM (iROM) is mapped. iROM contains the Boot ROM code (BL0). All
+other bootloaders are stored in an external storage (usually eMMC), so the user
+can update those later.
 
-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 the LittleKernel
-bootloader over USB, which is then being executed on the board. The loaded
-bootloader further enters fastboot mode, so that the user can flash the
-functional bootloader binary (U-Boot or LittleKernel [7]_) to eMMC using
-``fastboot`` tool. Please read the ``dltool`` README file for more details about
-the procedure.
+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 :ref:`Figure 1 <figure1>`), eventually ending up
+executing U-Boot (designated as "Bootloader" in the figure).
 
-Build Procedure
+Boot Device Configuration
+-------------------------
+
+The boot device can be chosen with SW1 DIP switch on E850-96 board. It controls
+the eXternal Operating Mode (XOM) SoC pins. :ref:`Table 1 <table1>` shows how
+the boot source can be configured using SW1.
+
+.. _table1:
+
+.. table:: Table 1: Boot device configuration using 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 ``dltool`` [8]_
+README file for details. SD card boot was never tested on E850-96, so it's
+basically a choice between eMMC boot (regular boot) and USB boot (usually 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):
@@ -66,49 +98,92 @@ Build U-Boot binary from source code (using AArch64 baremetal GCC toolchain):
   make e850-96_defconfig
   make
 
-The original E850-96 board is shipped with LittleKernel-based bootloader flashed
-in eMMC. To replace it with U-Boot, boot into fastboot mode (as described in
-the board software documentation [9]_), and flash U-Boot binary:
+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 being 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. Please read 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 the
+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 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 "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:
 
 .. prompt:: bash $
 
   fastboot flash bootloader u-boot.bin
   fastboot reboot
 
-U-Boot will boot up to the shell.
-
-Flashing
---------
-
-User area of eMMC contains GPT partition table (either Linux or Android). Boot
-Partition A (``mmc0boot0``) contains all firmware/bootloaders. Boot Partition
-B (``mmc0boot1``) contains U-Boot environment.
-
-First make sure to format eMMC accordingly. Prepare the initial environment:
+U-Boot will boot up to the shell. Configure the default U-Boot environment
+before starting working with U-Boot:
 
 .. prompt:: bash =>
 
   env default -f -a
   env save
 
-For Linux, just format eMMC using default ``$partitions`` definitions:
+.. _flashing-linux-label:
+
+Flashing Linux Images
+---------------------
+
+Linux partition table has only two partitions:
+
+1. ``esp`` (EFI System Partition)
+2. ``rootfs``
+
+Format eMMC to have Linux partition table (using the default ``$partitions``
+definitions):
 
 .. prompt:: bash =>
 
   gpt write mmc 0 $partitions
 
-For Android, use ``$partitions_android`` instead:
+...or do the same using fastboot:
 
-.. prompt:: bash =>
+.. prompt:: bash $
 
-  setenv partitions_linux $partitions
-  setenv partitions $partitions_android
-  env save
-  gpt write mmc 0 $partitions
+  fastboot oem format
 
-In case of Linux, there are two partitions available: ``esp`` (EFI System
-Partition) and ``rootfs``. It is recommended to use fastboot to flash images to
-those partitions. Enter fastboot mode on your device:
+Enter fastboot mode on your device:
 
 .. prompt:: bash =>
 
@@ -121,21 +196,849 @@ And then flash the images:
   fastboot flash esp esp.img
   fastboot flash rootfs rootfs.img
 
-To update the firmware, it's easier to use DFU. Enter DFU mode on the board:
+.. _flashing-android-label:
+
+Flashing Android Images
+-----------------------
+
+Use ``$partitions_android`` as current partition definitions:
+
+.. prompt:: bash =>
+
+  setenv partitions_linux $partitions
+  setenv partitions $partitions_android
+  env save
+
+Format eMMC to have Android partition table:
+
+.. prompt:: bash =>
+
+  gpt write mmc 0 $partitions
+
+...or do the same using fastboot:
+
+.. prompt:: bash $
+
+  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 GBL EFI app (Android Generic
+Bootloader) [10]_ and use its fastboot implementation. See
+:ref:`booting-android-gbl-label` section for details. But first the ESP image
+containing GBL app has to be flashed.
+
+Enter fastboot mode on your device:
+
+.. prompt:: bash =>
+
+  fastboot usb 0
+
+And flash the ESP image:
+
+.. prompt:: bash $
+
+  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 :ref:`booting-label` section. Boot GBL and enter fastboot mode.
+
+Android flashing procedure is quite elaborate and bulky, and can vary for
+different Android versions. So there is usually a flashing script (or flashing
+instructions) provided with AOSP images for E850-96 board to flash all Android
+images to eMMC. Run it:
+
+.. prompt:: bash $
+
+   ./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 only uses 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 the 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 ``$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:
 
 .. prompt:: bash =>
 
   dfu 0 mmc 0
 
-To update U-Boot:
+To update U-Boot via DFU:
 
 .. prompt:: bash $
 
   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, but it's not so straightforward, as one have to prepare the image for
-the whole ``boot0`` partition containing all firmware binaries first.
+partition. It might be not as convenient as using DFU method though, as the
+image containing all binaries has to be prepared first.
+
+One way to generate such an image is to use ``dd`` tool, e.g.:
+
+.. code-block:: bash
+
+  # $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:
+
+.. prompt:: bash $
+
+  fastboot flash mmc0boot0 boot0.img
+
+Updating BLs using Capsule Update
+---------------------------------
+
+The bootloaders (in eMMC boot partition 0) can be updated using 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 :ref:`Table 2 <table2>` below.
+
+.. _table2:
+
+.. table:: 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 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:
+
+.. prompt:: bash $
+
+  ./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
+``/boot/efi/EFI/UpdateCapsule/`` directory. 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 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-label:
+
+Booting Overview
+----------------
+
+The OS booting is performed using a U-Boot mechanism called
+:doc:`/develop/bootstd/index`. 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 :ref:`esp-label`
+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 the end user 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 possible for the user to insert USB media drive with
+Debian installer into E850-96 board and install Debian OS to eMMC, the same way
+it's done on the PC (or do the network installation).
+
+When the autoboot happens on U-Boot countdown timeout, this command (bootcmd) is
+automatically executed:
+
+.. prompt:: bash =>
+
+  bootflow scan -lb
+
+It goes through all present storage devices, and searches for all available boot
+methods on all partitions that have **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:
+
+.. _table3:
+
+.. table:: 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 :doc:`/develop/bootstd/overview` documentation.
+
+.. _booting-efi-mgr-label:
+
+Booting with ``efi_mgr`` Method
+-------------------------------
+
+``'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:
+
+.. prompt:: bash =>
+
+  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
+---------------------------
+
+``'efi'`` boot method just executes ``/EFI/BOOT/BOOTAA64.EFI`` file from 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 ``'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):
+
+.. prompt:: bash =>
+
+  bootflow scan -l
+  bootflow select 1
+  bootflow boot
+
+Booting with ``extlinux`` Method
+--------------------------------
+
+``'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):
+
+.. prompt:: bash =>
+
+  bootflow scan -l
+  bootflow select 2
+  bootflow boot
+
+Booting with ``script`` Method
+------------------------------
+
+``'script'`` boot method looks for ``boot.scr`` file, reads it and executes
+U-Boot commands specified there. It can be useful for debugging and development
+purposes, but it's an outdated and not very secure method, and should be avoided
+in production.
+
+First, prepare the ``boot.txt`` file with OS boot instructions, for example:
+
+.. code-block:: bash
+
+  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:
+
+.. prompt:: bash $
+
+  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
+---------------------------
+
+``'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 the 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 the 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 is the Ethernet MAC address,
+  which can be looked up in ``$ethaddr`` environment variable in U-Boot.
+
+  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 be also enabled in kernel. Although NFS options are already
+  enabled in ARM64 defconfig, the USB PHY and LAN9514 (Ethernet) drivers must be
+  made builtin, so the next change is needed::
+
+    arch/arm64/configs/defconfig
+    ----------------------------
+
+    # Needed for boot from USB storage (mounting rootfs from USB drive)
+    CONFIG_PHY_EXYNOS5_USBDRD=y
+    CONFIG_TYPEC=y
+
+    # Needed for NFS boot
+    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
+   :ref:`usb-host-label` 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:
+
+   .. prompt:: bash =>
+
+     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 consequenly 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-label:
+
+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 U-Boot environment are stored, respectfully). 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:
+
+.. prompt:: bash =>
+
+  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 builtin. For example, in ARM64 defconfig it's specified as a
+loadable module, not a builtin 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 next instructions to implement booting from USB storage device:
+
+1. First, make sure to enable USB host mode in U-Boot, as discussed in
+   :ref:`usb-host-label` 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:
+
+   .. prompt:: bash #
+
+     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 E850-96 USB port
+5. Tell U-Boot to search for LDFW firmware on USB stick:
+
+   .. prompt:: bash =>
+
+     setenv bootdev usb
+     env save
+
+6. Erase eMMC partition table to make U-Boot use ESP from USB drive:
+
+   .. prompt:: bash =>
+
+    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 :ref:`booting-label` section
+
+Now U-Boot will be able to boot the OS from the USB drive using Standard Boot.
+
+.. _booting-android-gbl-label:
+
+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 wasn't 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:
+
+.. prompt:: bash $
+
+  git remote add db4a https://gerrit.devboardsforandroid.linaro.org/platform/external/u-boot
+  git fetch db4a
+  git cherry-pick cdc73ef81fdc
+  git cherry-pick 7d60b5bbe434
+
+Also, the next patch should be reverted (if it's still not fixed in upstream
+U-Boot), as it was found to break GBL functioning:
+
+.. prompt:: bash $
+
+  # Revert "fdt: Make sure there is no stale initrd left"
+  git revert 9fe2e4b46458
+
+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:
+
+.. prompt:: bash $
+
+  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
+:ref:`booting-efi-mgr-label` section, and run ``efi_mgr`` boot method:
+
+.. prompt:: bash =>
+
+  bootflow scan -lb
+
+U-Boot will execute 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 Android partition table created as described in
+:ref:`flashing-android-label` 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 E850-96 board using AOSP projects
+from "Devboards for Android" [15]_.
+
+.. _esp-label:
+
+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 nowadays EFI boot is the
+recommended way of booting operating systems (see SystemReady [11]_), it has to
+be properly prepared and flashed to eMMC on E850-96. It's needed for both Linux
+and Android boot (at least when using GBL).
+
+ESP is the first partition in E850-96 partition table, 128 MiB in size. It must
+be formatted as FAT, and ``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:
+
+.. prompt:: bash $
+
+  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
+:ref:`loadable-firmware-label` 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 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 Debain 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 :ref:`flashing-linux-label`.
+
+.. _loadable-firmware-label:
+
+Loadable Firmware
+-----------------
+
+For E850-96 system to function properly the 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 :ref:`booting-from-usb-label`.
+
+.. _usb-host-label:
+
+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 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 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 USB controller in peripheral mode. To enable USB
+host mode do next two things:
+
+1. Modify ``dts/upstream/src/arm64/exynos/exynos850-e850-96.dts`` file like
+   this:
+
+   .. code-block:: diff
+
+      &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.
+
+In order to enable USB peripheral mode again, just revert the above actions.
 
 References
 ----------
@@ -146,6 +1049,12 @@ References
 .. [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] https://gitlab.com/Linaro/96boards/e850-96/images
-.. [8] https://gitlab.com/Linaro/96boards/e850-96/tools/dltool
+.. [7] https://gitlab.com/LinaroLtd/e850-96/images.git
+.. [8] https://gitlab.com/LinaroLtd/e850-96/tools/dltool.git
 .. [9] https://gitlab.com/Linaro/96boards/e850-96/doc
+.. [10] https://source.android.com/docs/core/architecture/bootloader/generic-bootloader
+.. [11] 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] 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/
-- 
2.39.5



More information about the U-Boot mailing list