
Hi Heinrich,
On Fri, Jul 26, 2019 at 12:56 PM Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Change the UEFI documentation to Sphinx style and integrate it into the rest of the Sphinx generated documentation.
Remove the inaccurate TODO list in doc/uefi/uefi.rst.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de
MAINTAINERS | 4 +- doc/README.iscsi | 170 ------------------ doc/README.u-boot_on_efi | 252 -------------------------- doc/README.uefi | 352 ------------------------------------- doc/index.rst | 13 ++ doc/uefi/index.rst | 11 ++ doc/uefi/iscsi.rst | 180 +++++++++++++++++++ doc/uefi/u-boot_on_efi.rst | 235 +++++++++++++++++++++++++ doc/uefi/uefi.rst | 334 +++++++++++++++++++++++++++++++++++ 9 files changed, 774 insertions(+), 777 deletions(-) delete mode 100644 doc/README.iscsi delete mode 100644 doc/README.u-boot_on_efi delete mode 100644 doc/README.uefi create mode 100644 doc/uefi/index.rst create mode 100644 doc/uefi/iscsi.rst create mode 100644 doc/uefi/u-boot_on_efi.rst create mode 100644 doc/uefi/uefi.rst
diff --git a/MAINTAINERS b/MAINTAINERS index a72ccd0b58..12ad127adc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -477,9 +477,7 @@ M: Heinrich Schuchardt xypron.glpk@gmx.de R: Alexander Graf agraf@csgraf.de S: Maintained T: git https://gitlab.denx.de/u-boot/custodians/u-boot-efi.git -F: doc/README.uefi -F: doc/README.iscsi -F: doc/efi.rst +F: doc/uefi/* F: include/capitalization.h F: include/charset.h F: include/cp1250.h diff --git a/doc/README.iscsi b/doc/README.iscsi deleted file mode 100644 index 3a12438f90..0000000000 --- a/doc/README.iscsi +++ /dev/null @@ -1,170 +0,0 @@ -# iSCSI booting with U-Boot and iPXE
-## Motivation
-U-Boot has only a reduced set of supported network protocols. The focus for -network booting has been on UDP based protocols. A TCP stack and HTTP support -are expected to be integrated in 2018 together with a wget command.
-For booting a diskless computer this leaves us with BOOTP or DHCP to get the -address of a boot script. TFTP or NFS can be used to load the boot script, the -operating system kernel and the initial file system (initrd).
-These protocols are insecure. The client cannot validate the authenticity -of the contacted servers. And the server cannot verify the identity of the -client.
-Furthermore the services providing the operating system loader or kernel are -not the ones that the operating system typically will use. Especially in a SAN -environment this makes updating the operating system a hassle. After installing -a new kernel version the boot files have to be copied to the TFTP server -directory.
-The HTTPS protocol provides certificate based validation of servers. Sensitive -data like passwords can be securely transmitted.
-The iSCSI protocol is used for connecting storage attached networks. It -provides mutual authentication using the CHAP protocol. It typically runs on -a TCP transport.
-Thus a better solution than DHCP/TFTP/NFS boot would be to load a boot script -via HTTPS and to download any other files needed for booting via iSCSI from the -same target where the operating system is installed.
-An alternative to implementing these protocols in U-Boot is to use an existing -software that can run on top of U-Boot. iPXE[1] is the "swiss army knife" of -network booting. It supports both HTTPS and iSCSI. It has a scripting engine for -fine grained control of the boot process and can provide a command shell.
-iPXE can be built as an EFI application (named snp.efi) which can be loaded and -run by U-Boot.
-## Boot sequence
-U-Boot loads the EFI application iPXE snp.efi using the bootefi command. This -application has network access via the simple network protocol offered by -U-Boot.
-iPXE executes its internal script. This script may optionally chain load a -secondary boot script via HTTPS or open a shell.
-For the further boot process iPXE connects to the iSCSI server. This includes -the mutual authentication using the CHAP protocol. After the authentication iPXE -has access to the iSCSI targets.
-For a selected iSCSI target iPXE sets up a handle with the block IO protocol. It -uses the ConnectController boot service of U-Boot to request U-Boot to connect a -file system driver. U-Boot reads from the iSCSI drive via the block IO protocol -offered by iPXE. It creates the partition handles and installs the simple file -protocol. Now iPXE can call the simple file protocol to load GRUB[2]. U-Boot -uses the block IO protocol offered by iPXE to fulfill the request.
-Once GRUB is started it uses the same block IO protocol to load Linux. Via -the EFI stub Linux is called as an EFI application::
+--------+ +--------+
| | Runs | |
| U-Boot |========>| iPXE |
| EFI | | snp.efi|
- +--------+ | | DHCP | |
- | |<===|********|<========| |
- | DHCP | | | Get IP | |
- | Server | | | Address | |
- | |===>|********|========>| |
- +--------+ | | Response| |
| | | |
| | | |
- +--------+ | | HTTPS | |
- | |<===|********|<========| |
- | HTTPS | | | Load | |
- | Server | | | Script | |
- | |===>|********|========>| |
- +--------+ | | | |
| | | |
| | | |
- +--------+ | | iSCSI | |
- | |<===|********|<========| |
- | iSCSI | | | Auth | |
- | Server |===>|********|========>| |
- | | | | | |
- | | | | Loads | |
- | |<===|********|<========| | +--------+
- | | | | GRUB | | Runs | |
- | |===>|********|========>| |======>| GRUB |
- | | | | | | | |
- | | | | | | | |
- | | | | | | Loads | |
- | |<===|********|<========|********|<======| | +--------+
- | | | | | | Linux | | Runs | |
- | |===>|********|========>|********|======>| |=====>| Linux |
- | | | | | | | | | |
- +--------+ +--------+ +--------+ +--------+ | |
| |
| |
| ~ ~ ~ ~|
-## Security
-The iSCSI protocol is not encrypted. The traffic could be secured using IPsec -but neither U-Boot nor iPXE does support this. So we should at least separate -the iSCSI traffic from all other network traffic. This can be achieved using a -virtual local area network (VLAN).
-## Configuration
-### iPXE
-For running iPXE on arm64 the bin-arm64-efi/snp.efi build target is needed::
- git clone http://git.ipxe.org/ipxe.git
- cd ipxe/src
- make bin-arm64-efi/snp.efi -j6 EMBED=myscript.ipxe
-The available commands for the boot script are documented at:
-Credentials are managed as environment variables. These are described here:
-iPXE by default will put the CPU to rest when waiting for input. U-Boot does -not wake it up due to missing interrupt support. To avoid this behavior create -file src/config/local/nap.h::
- /* nap.h */
- #undef NAP_EFIX86
- #undef NAP_EFIARM
- #define NAP_NULL
-The supported commands in iPXE are controlled by an include, too. Putting the -following into src/config/local/general.h is sufficient for most use cases::
- /* general.h */
- #define NSLOOKUP_CMD /* Name resolution command */
- #define PING_CMD /* Ping command */
- #define NTP_CMD /* NTP commands */
- #define VLAN_CMD /* VLAN commands */
- #define IMAGE_EFI /* EFI image support */
- #define DOWNLOAD_PROTO_HTTPS /* Secure Hypertext Transfer Protocol */
- #define DOWNLOAD_PROTO_FTP /* File Transfer Protocol */
- #define DOWNLOAD_PROTO_NFS /* Network File System Protocol */
- #define DOWNLOAD_PROTO_FILE /* Local file system access */
-### Open-iSCSI
-When the root file system is on an iSCSI drive you should disable pings and set -the replacement timer to a high value [3]:
- node.conn[0].timeo.noop_out_interval = 0
- node.conn[0].timeo.noop_out_timeout = 0
- node.session.timeo.replacement_timeout = 86400
-## Links
-* [1](https://ipxe.org) https://ipxe.org - iPXE open source boot firmware -* [2](https://www.gnu.org/software/grub/) https://www.gnu.org/software/grub/ -
GNU GRUB (Grand Unified Bootloader)
-* [3](https://github.com/open-iscsi/open-iscsi/blob/master/README)
https://github.com/open-iscsi/open-iscsi/blob/master/README -
Open-iSCSI README
diff --git a/doc/README.u-boot_on_efi b/doc/README.u-boot_on_efi deleted file mode 100644 index e12dd4e3e6..0000000000 --- a/doc/README.u-boot_on_efi +++ /dev/null @@ -1,252 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0+ -# -# Copyright (C) 2015 Google, Inc
-U-Boot on EFI
-This document provides information about U-Boot running on top of EFI, either -as an application or just as a means of getting U-Boot onto a new platform.
-=========== Table of Contents ===========
-Motivation -Status -Build Instructions -Trying it out -Inner workings -EFI Application -EFI Payload -Tables -Interrupts -32/64-bit -Future work -Where is the code?
-Motivation
-Running U-Boot on EFI is useful in several situations:
-- You have EFI running on a board but U-Boot does not natively support it -fully yet. You can boot into U-Boot from EFI and use that until U-Boot is -fully ported
-- You need to use an EFI implementation (e.g. UEFI) because your vendor -requires it in order to provide support
-- You plan to use coreboot to boot into U-Boot but coreboot support does -not currently exist for your platform. In the meantime you can use U-Boot -on EFI and then move to U-Boot on coreboot when ready
-- You use EFI but want to experiment with a simpler alternative like U-Boot
-Status
-Only x86 is supported at present. If you are using EFI on another architecture -you may want to reconsider. However, much of the code is generic so could be -ported.
-U-Boot supports running as an EFI application for 32-bit EFI only. This is -not very useful since only a serial port is provided. You can look around at -memory and type 'help' but that is about it.
-More usefully, U-Boot supports building itself as a payload for either 32-bit -or 64-bit EFI. U-Boot is packaged up and loaded in its entirety by EFI. Once -started, U-Boot changes to 32-bit mode (currently) and takes over the -machine. You can use devices, boot a kernel, etc.
-Build Instructions
-First choose a board that has EFI support and obtain an EFI implementation -for that board. It will be either 32-bit or 64-bit. Alternatively, you can -opt for using QEMU [1] and the OVMF [2], as detailed below.
-To build U-Boot as an EFI application (32-bit EFI required), enable CONFIG_EFI -and CONFIG_EFI_APP. The efi-x86_app config (efi-x86_app_defconfig) is set up -for this. Just build U-Boot as normal, e.g.
- make efi-x86_app_defconfig
- make
-To build U-Boot as an EFI payload (32-bit or 64-bit EFI can be used), enable -CONFIG_EFI, CONFIG_EFI_STUB, and select either CONFIG_EFI_STUB_32BIT or -CONFIG_EFI_STUB_64BIT. The efi-x86_payload configs (efi-x86_payload32_defconfig -and efi-x86_payload32_defconfig) are set up for this. Then build U-Boot as -normal, e.g.
- make efi-x86_payload32_defconfig (or efi-x86_payload64_defconfig)
- make
-You will end up with one of these files depending on what you build for:
- u-boot-app.efi - U-Boot EFI application
- u-boot-payload.efi - U-Boot EFI payload application
-Trying it out
-QEMU is an emulator and it can emulate an x86 machine. Please make sure your -QEMU version is 2.3.0 or above to test this. You can run the payload with -something like this:
- mkdir /tmp/efi
- cp /path/to/u-boot*.efi /tmp/efi
- qemu-system-x86_64 -bios bios.bin -hda fat:/tmp/efi/
-Add -nographic if you want to use the terminal for output. Once it starts -type 'fs0:u-boot-payload.efi' to run the payload or 'fs0:u-boot-app.efi' to -run the application. 'bios.bin' is the EFI 'BIOS'. Check [2] to obtain a -prebuilt EFI BIOS for QEMU or you can build one from source as well.
-To try it on real hardware, put u-boot-app.efi on a suitable boot medium, -such as a USB stick. Then you can type something like this to start it:
- fs0:u-boot-payload.efi
-(or fs0:u-boot-app.efi for the application)
-This will start the payload, copy U-Boot into RAM and start U-Boot. Note -that EFI does not support booting a 64-bit application from a 32-bit -EFI (or vice versa). Also it will often fail to print an error message if -you get this wrong.
-Inner workings
-Here follow a few implementation notes for those who want to fiddle with -this and perhaps contribute patches.
-The application and payload approaches sound similar but are in fact -implemented completely differently.
-EFI Application
-For the application the whole of U-Boot is built as a shared library. The -efi_main() function is in lib/efi/efi_app.c. It sets up some basic EFI -functions with efi_init(), sets up U-Boot global_data, allocates memory for -U-Boot's malloc(), etc. and enters the normal init sequence (board_init_f() -and board_init_r()).
-Since U-Boot limits its memory access to the allocated regions very little -special code is needed. The CONFIG_EFI_APP option controls a few things -that need to change so 'git grep CONFIG_EFI_APP' may be instructive. -The CONFIG_EFI option controls more general EFI adjustments.
-The only available driver is the serial driver. This calls back into EFI -'boot services' to send and receive characters. Although it is implemented -as a serial driver the console device is not necessarilly serial. If you -boot EFI with video output then the 'serial' device will operate on your -target devices's display instead and the device's USB keyboard will also -work if connected. If you have both serial and video output, then both -consoles will be active. Even though U-Boot does the same thing normally, -These are features of EFI, not U-Boot.
-Very little code is involved in implementing the EFI application feature. -U-Boot is highly portable. Most of the difficulty is in modifying the -Makefile settings to pass the right build flags. In particular there is very -little x86-specific code involved - you can find most of it in -arch/x86/cpu. Porting to ARM (which can also use EFI if you are brave -enough) should be straightforward.
-Use the 'reset' command to get back to EFI.
-EFI Payload
-The payload approach is a different kettle of fish. It works by building -U-Boot exactly as normal for your target board, then adding the entire -image (including device tree) into a small EFI stub application responsible -for booting it. The stub application is built as a normal EFI application -except that it has a lot of data attached to it.
-The stub application is implemented in lib/efi/efi_stub.c. The efi_main() -function is called by EFI. It is responsible for copying U-Boot from its -original location into memory, disabling EFI boot services and starting -U-Boot. U-Boot then starts as normal, relocates, starts all drivers, etc.
-The stub application is architecture-dependent. At present it has some -x86-specific code and a comment at the top of efi_stub.c describes this.
-While the stub application does allocate some memory from EFI this is not -used by U-Boot (the payload). In fact when U-Boot starts it has all of the -memory available to it and can operate as it pleases (but see the next -section).
-Tables
-The payload can pass information to U-Boot in the form of EFI tables. At -present this feature is used to pass the EFI memory map, an inordinately -large list of memory regions. You can use the 'efi mem all' command to -display this list. U-Boot uses the list to work out where to relocate -itself.
-Although U-Boot can use any memory it likes, EFI marks some memory as used -by 'run-time services', code that hangs around while U-Boot is running and -is even present when Linux is running. This is common on x86 and provides -a way for Linux to call back into the firmware to control things like CPU -fan speed. U-Boot uses only 'conventional' memory, in EFI terminology. It -will relocate itself to the top of the largest block of memory it can find -below 4GB.
-Interrupts
-U-Boot drivers typically don't use interrupts. Since EFI enables interrupts -it is possible that an interrupt will fire that U-Boot cannot handle. This -seems to cause problems. For this reason the U-Boot payload runs with -interrupts disabled at present.
-32/64-bit
-While the EFI application can in principle be built as either 32- or 64-bit, -only 32-bit is currently supported. This means that the application can only -be used with 32-bit EFI.
-The payload stub can be build as either 32- or 64-bits. Only a small amount -of code is built this way (see the extra- line in lib/efi/Makefile). -Everything else is built as a normal U-Boot, so is always 32-bit on x86 at -present.
-Future work
-This work could be extended in a number of ways:
-- Add ARM support
-- Add 64-bit application support
-- Figure out how to solve the interrupt problem
-- Add more drivers to the application side (e.g. video, block devices, USB, -environment access). This would mostly be an academic exercise as a strong -use case is not readily apparent, but it might be fun.
-- Avoid turning off boot services in the stub. Instead allow U-Boot to make -use of boot services in case it wants to. It is unclear what it might want -though.
-Where is the code?
-lib/efi
payload stub, application, support code. Mostly arch-neutral
-arch/x86/cpu/efi
x86 support code for running as an EFI application and payload
-board/efi/efi-x86_app/efi.c
x86 board code for running as an EFI application
-board/efi/efi-x86_payload
generic x86 EFI payload board support code
-common/cmd_efi.c
the 'efi' command
-Ben Stoltz, Simon Glass -Google, Inc -July 2015
-[1] http://www.qemu.org -[2] http://www.tianocore.org/ovmf/ diff --git a/doc/README.uefi b/doc/README.uefi deleted file mode 100644 index 1d1039a6ae..0000000000 --- a/doc/README.uefi +++ /dev/null @@ -1,352 +0,0 @@ -<!-- -SPDX-License-Identifier: GPL-2.0+
-Copyright (c) 2018 Heinrich Schuchardt --->
-# UEFI on U-Boot
-The Unified Extensible Firmware Interface Specification (UEFI) [1] has become -the default for booting on AArch64 and x86 systems. It provides a stable API for -the interaction of drivers and applications with the firmware. The API comprises -access to block storage, network, and console to name a few. The Linux kernel -and boot loaders like GRUB or the FreeBSD loader can be executed.
-## Development target
-The implementation of UEFI in U-Boot strives to reach the requirements described -in the "Embedded Base Boot Requirements (EBBR) Specification - Release v1.0" -[4]. The "Server Base Boot Requirements System Software on ARM Platforms" [5] -describes a superset of the EBBR specification and may be used as further -reference.
-A full blown UEFI implementation would contradict the U-Boot design principle -"keep it small".
-## Building for UEFI
-The UEFI standard supports only little-endian systems. The UEFI support can be -activated for ARM and x86 by specifying
- CONFIG_CMD_BOOTEFI=y
- CONFIG_EFI_LOADER=y
-in the .config file.
-Support for attaching virtual block devices, e.g. iSCSI drives connected by the -loaded UEFI application [3], requires
- CONFIG_BLK=y
- CONFIG_PARTITIONS=y
-### Executing a UEFI binary
-The bootefi command is used to start UEFI applications or to install UEFI -drivers. It takes two parameters
- bootefi <image address> [fdt address]
-* image address - the memory address of the UEFI binary -* fdt address - the memory address of the flattened device tree
-Below you find the output of an example session starting GRUB.
- => load mmc 0:2 ${fdt_addr_r} boot/dtb
- 29830 bytes read in 14 ms (2 MiB/s)
- => load mmc 0:1 ${kernel_addr_r} efi/debian/grubaa64.efi
- reading efi/debian/grubaa64.efi
- 120832 bytes read in 7 ms (16.5 MiB/s)
- => bootefi ${kernel_addr_r} ${fdt_addr_r}
-The environment variable 'bootargs' is passed as load options in the UEFI system -table. The Linux kernel EFI stub uses the load options as command line -arguments.
-### Executing the boot manager
-The UEFI specification foresees to define boot entries and boot sequence via UEFI -variables. Booting according to these variables is possible via
- bootefi bootmgr [fdt address]
-As of U-Boot v2018.03 UEFI variables are not persisted and cannot be set at -runtime.
-### Executing the built in hello world application
-A hello world UEFI application can be built with
- CONFIG_CMD_BOOTEFI_HELLO_COMPILE=y
-It can be embedded into the U-Boot binary with
- CONFIG_CMD_BOOTEFI_HELLO=y
-The bootefi command is used to start the embedded hello world application.
- bootefi hello [fdt address]
-Below you find the output of an example session.
- => bootefi hello ${fdtcontroladdr}
- ## Starting EFI application at 01000000 ...
- WARNING: using memory device/image path, this may confuse some payloads!
- Hello, world!
- Running on UEFI 2.7
- Have SMBIOS table
- Have device tree
- Load options: root=/dev/sdb3 init=/sbin/init rootwait ro
- ## Application terminated, r = 0
-The environment variable fdtcontroladdr points to U-Boot's internal device tree -(if available).
-### Executing the built-in self-test
-An UEFI self-test suite can be embedded in U-Boot by building with
- CONFIG_CMD_BOOTEFI_SELFTEST=y
-For testing the UEFI implementation the bootefi command can be used to start the -self-test.
- bootefi selftest [fdt address]
-The environment variable 'efi_selftest' can be used to select a single test. If -it is not provided all tests are executed except those marked as 'on request'. -If the environment variable is set to 'list' a list of all tests is shown.
-Below you can find the output of an example session.
- => setenv efi_selftest simple network protocol
- => bootefi selftest
- Testing EFI API implementation
- Selected test: 'simple network protocol'
- Setting up 'simple network protocol'
- Setting up 'simple network protocol' succeeded
- Executing 'simple network protocol'
- DHCP Discover
- DHCP reply received from 192.168.76.2 (52:55:c0:a8:4c:02)
as broadcast message.
- Executing 'simple network protocol' succeeded
- Tearing down 'simple network protocol'
- Tearing down 'simple network protocol' succeeded
- Boot services terminated
- Summary: 0 failures
- Preparing for reset. Press any key.
-## The UEFI life cycle
-After the U-Boot platform has been initialized the UEFI API provides two kinds -of services
-* boot services and -* runtime services.
-The API can be extended by loading UEFI drivers which come in two variants
-* boot drivers and -* runtime drivers.
-UEFI drivers are installed with U-Boot's bootefi command. With the same command -UEFI applications can be executed.
-Loaded images of UEFI drivers stay in memory after returning to U-Boot while -loaded images of applications are removed from memory.
-An UEFI application (e.g. an operating system) that wants to take full control -of the system calls ExitBootServices. After a UEFI application calls -ExitBootServices
-* boot services are not available anymore -* timer events are stopped -* the memory used by U-Boot except for runtime services is released -* the memory used by boot time drivers is released
-So this is a point of no return. Afterwards the UEFI application can only return -to U-Boot by rebooting.
-## The UEFI object model
-UEFI offers a flexible and expandable object model. The objects in the UEFI API -are devices, drivers, and loaded images. These objects are referenced by -handles.
-The interfaces implemented by the objects are referred to as protocols. These -are identified by GUIDs. They can be installed and uninstalled by calling the -appropriate boot services.
-Handles are created by the InstallProtocolInterface or the -InstallMultipleProtocolinterfaces service if NULL is passed as handle.
-Handles are deleted when the last protocol has been removed with the -UninstallProtocolInterface or the UninstallMultipleProtocolInterfaces service.
-Devices offer the EFI_DEVICE_PATH_PROTOCOL. A device path is the concatenation -of device nodes. By their device paths all devices of a system are arranged in a -tree.
-Drivers offer the EFI_DRIVER_BINDING_PROTOCOL. This protocol is used to connect -a driver to devices (which are referenced as controllers in this context).
-Loaded images offer the EFI_LOADED_IMAGE_PROTOCOL. This protocol provides meta -information about the image and a pointer to the unload callback function.
-## The UEFI events
-In the UEFI terminology an event is a data object referencing a notification -function which is queued for calling when the event is signaled. The following -types of events exist:
-* periodic and single shot timer events -* exit boot services events, triggered by calling the ExitBootServices() service -* virtual address change events -* memory map change events -* read to boot events -* reset system events -* system table events -* events that are only triggered programmatically
-Events can be created with the CreateEvent service and deleted with CloseEvent -service.
-Events can be assigned to an event group. If any of the events in a group is -signaled, all other events in the group are also set to the signaled state.
-## The UEFI driver model
-A driver is specific for a single protocol installed on a device. To install a -driver on a device the ConnectController service is called. In this context -controller refers to the device for which the driver is installed.
-The relevant drivers are identified using the EFI_DRIVER_BINDING_PROTOCOL. This -protocol has has three functions:
-* supported - determines if the driver is compatible with the device -* start - installs the driver by opening the relevant protocol with
- attribute EFI_OPEN_PROTOCOL_BY_DRIVER
-* stop - uninstalls the driver
-The driver may create child controllers (child devices). E.g. a driver for block -IO devices will create the device handles for the partitions. The child -controllers will open the supported protocol with the attribute -EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
-A driver can be detached from a device using the DisconnectController service.
-## U-Boot devices mapped as UEFI devices
-Some of the U-Boot devices are mapped as UEFI devices
-* block IO devices -* console -* graphical output -* network adapter
-As of U-Boot 2018.03 the logic for doing this is hard coded.
-The development target is to integrate the setup of these UEFI devices with the -U-Boot driver model. So when a U-Boot device is discovered a handle should be -created and the device path protocol and the relevant IO protocol should be -installed. The UEFI driver then would be attached by calling ConnectController. -When a U-Boot device is removed DisconnectController should be called.
-## UEFI devices mapped as U-Boot devices
-UEFI drivers binaries and applications may create new (virtual) devices, install -a protocol and call the ConnectController service. Now the matching UEFI driver -is determined by iterating over the implementations of the -EFI_DRIVER_BINDING_PROTOCOL.
-It is the task of the UEFI driver to create a corresponding U-Boot device and to -proxy calls for this U-Boot device to the controller.
-In U-Boot 2018.03 this has only been implemented for block IO devices.
-### UEFI uclass
-An UEFI uclass driver (lib/efi_driver/efi_uclass.c) has been created that -takes care of initializing the UEFI drivers and providing the -EFI_DRIVER_BINDING_PROTOCOL implementation for the UEFI drivers.
-A linker created list is used to keep track of the UEFI drivers. To create an -entry in the list the UEFI driver uses the U_BOOT_DRIVER macro specifying -UCLASS_EFI as the ID of its uclass, e.g.
- /* Identify as UEFI driver */
- U_BOOT_DRIVER(efi_block) = {
.name = "EFI block driver",
.id = UCLASS_EFI,
.ops = &driver_ops,
- };
-The available operations are defined via the structure struct efi_driver_ops.
- struct efi_driver_ops {
const efi_guid_t *protocol;
const efi_guid_t *child_protocol;
int (*bind)(efi_handle_t handle, void *interface);
- };
-When the supported() function of the EFI_DRIVER_BINDING_PROTOCOL is called the -uclass checks if the protocol GUID matches the protocol GUID of the UEFI driver. -In the start() function the bind() function of the UEFI driver is called after -checking the GUID. -The stop() function of the EFI_DRIVER_BINDING_PROTOCOL disconnects the child -controllers created by the UEFI driver and the UEFI driver. (In U-Boot v2013.03 -this is not yet completely implemented.)
-### UEFI block IO driver
-The UEFI block IO driver supports devices exposing the EFI_BLOCK_IO_PROTOCOL.
-When connected it creates a new U-Boot block IO device with interface type -IF_TYPE_EFI, adds child controllers mapping the partitions, and installs the -EFI_SIMPLE_FILE_SYSTEM_PROTOCOL on these. This can be used together with the -software iPXE to boot from iSCSI network drives [3].
-This driver is only available if U-Boot is configured with
- CONFIG_BLK=y
- CONFIG_PARTITIONS=y
-## TODOs as of U-Boot 2019.04
-* unimplemented or incompletely implemented boot services
- Exit - call unload function, unload applications only
- ProtocolRegisterNotify
- UnloadImage
-* unimplemented or incompletely implemented runtime services
- SetVariable() ignores attribute EFI_VARIABLE_APPEND_WRITE
- QueryVariableInfo is not implemented
-* unimplemented events
- EVT_RUNTIME
- EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
-* data model
- manage configuration tables in a linked list
-* UEFI drivers
- support DisconnectController for UEFI block devices.
-* support for CONFIG_EFI_LOADER in the sandbox (CONFIG_SANDBOX=y)
-* UEFI variables
- persistence
- runtime support
-* incompletely implemented protocols
- support version 0x00020000 of the EFI file protocol
-## Links
-* [1](http://uefi.org/specifications)
- http://uefi.org/specifications - UEFI specifications
-* [2](./driver-model/README.txt) doc/driver-model/README.txt - Driver model -* [3](./README.iscsi) doc/README.iscsi - iSCSI booting with U-Boot and iPXE -* [4](https://github.com/ARM-software/ebbr/releases/download/v1.0/ebbr-v1.0.pdf)
- Embedded Base Boot Requirements (EBBR) Specification - Release v1.0
-* [5](https://developer.arm.com/docs/den0044/latest/server-base-boot-requirements-...)
- Server Base Boot Requirements System Software on ARM Platforms - Version 1.1
diff --git a/doc/index.rst b/doc/index.rst index 9ae2e167bc..458f0d2d0e 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -15,8 +15,21 @@ if you want to help out. .. toctree:: :maxdepth: 2
+Unified Extensible Firmware (UEFI) +----------------------------------
+U-Boot provides an implementation of the UEFI API allowing to run UEFI +compliant software like Linux, GRUB, and iPXE. Furthermore U-Boot itself +can be run an UEFI payload.
+.. toctree::
- :maxdepth: 2
- uefi/index
Driver-Model documentation
The following holds information on the U-Boot device driver framework: driver-model, including the design details of itself and several driver subsystems. diff --git a/doc/uefi/index.rst b/doc/uefi/index.rst new file mode 100644 index 0000000000..b790a91f17 --- /dev/null +++ b/doc/uefi/index.rst @@ -0,0 +1,11 @@ +.. SPDX-License-Identifier: GPL-2.0+
+Unified Extensible Firmware (UEFI) +==================================
+.. toctree::
- :maxdepth: 2
- uefi.rst
- u-boot_on_efi.rst
- iscsi.rst
diff --git a/doc/uefi/iscsi.rst b/doc/uefi/iscsi.rst new file mode 100644 index 0000000000..aa844a7cc3 --- /dev/null +++ b/doc/uefi/iscsi.rst @@ -0,0 +1,180 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright (c) 2018 Heinrich Schuchardt
+iSCSI booting with U-Boot and iPXE +==================================
+Motivation +----------
+U-Boot has only a reduced set of supported network protocols. The focus for +network booting has been on UDP based protocols. A TCP stack and HTTP support +are expected to be integrated in 2018 together with a wget command.
+For booting a diskless computer this leaves us with BOOTP or DHCP to get the +address of a boot script. TFTP or NFS can be used to load the boot script, the +operating system kernel and the initial file system (initrd).
+These protocols are insecure. The client cannot validate the authenticity +of the contacted servers. And the server cannot verify the identity of the +client.
+Furthermore the services providing the operating system loader or kernel are +not the ones that the operating system typically will use. Especially in a SAN +environment this makes updating the operating system a hassle. After installing +a new kernel version the boot files have to be copied to the TFTP server +directory.
+The HTTPS protocol provides certificate based validation of servers. Sensitive +data like passwords can be securely transmitted.
+The iSCSI protocol is used for connecting storage attached networks. It +provides mutual authentication using the CHAP protocol. It typically runs on +a TCP transport.
+Thus a better solution than DHCP/TFTP/NFS boot would be to load a boot script +via HTTPS and to download any other files needed for booting via iSCSI from the +same target where the operating system is installed.
+An alternative to implementing these protocols in U-Boot is to use an existing +software that can run on top of U-Boot. iPXE[1] is the "swiss army knife" of +network booting. It supports both HTTPS and iSCSI. It has a scripting engine for +fine grained control of the boot process and can provide a command shell.
+iPXE can be built as an EFI application (named snp.efi) which can be loaded and +run by U-Boot.
+Boot sequence +-------------
+U-Boot loads the EFI application iPXE snp.efi using the bootefi command. This +application has network access via the simple network protocol offered by +U-Boot.
+iPXE executes its internal script. This script may optionally chain load a +secondary boot script via HTTPS or open a shell.
+For the further boot process iPXE connects to the iSCSI server. This includes +the mutual authentication using the CHAP protocol. After the authentication iPXE +has access to the iSCSI targets.
+For a selected iSCSI target iPXE sets up a handle with the block IO protocol. It +uses the ConnectController boot service of U-Boot to request U-Boot to connect a +file system driver. U-Boot reads from the iSCSI drive via the block IO protocol +offered by iPXE. It creates the partition handles and installs the simple file +protocol. Now iPXE can call the simple file protocol to load GRUB[2]. U-Boot +uses the block IO protocol offered by iPXE to fulfill the request.
+Once GRUB is started it uses the same block IO protocol to load Linux. Via +the EFI stub Linux is called as an EFI application::
+--------+ +--------+
| | Runs | |
| U-Boot |========>| iPXE |
| EFI | | snp.efi|
- +--------+ | | DHCP | |
- | |<===|********|<========| |
- | DHCP | | | Get IP | |
- | Server | | | Address | |
- | |===>|********|========>| |
- +--------+ | | Response| |
| | | |
| | | |
- +--------+ | | HTTPS | |
- | |<===|********|<========| |
- | HTTPS | | | Load | |
- | Server | | | Script | |
- | |===>|********|========>| |
- +--------+ | | | |
| | | |
| | | |
- +--------+ | | iSCSI | |
- | |<===|********|<========| |
- | iSCSI | | | Auth | |
- | Server |===>|********|========>| |
- | | | | | |
- | | | | Loads | |
- | |<===|********|<========| | +--------+
- | | | | GRUB | | Runs | |
- | |===>|********|========>| |======>| GRUB |
- | | | | | | | |
- | | | | | | | |
- | | | | | | Loads | |
- | |<===|********|<========|********|<======| | +--------+
- | | | | | | Linux | | Runs | |
- | |===>|********|========>|********|======>| |=====>| Linux |
- | | | | | | | | | |
- +--------+ +--------+ +--------+ +--------+ | |
| |
| |
| ~ ~ ~ ~|
+Security +--------
+The iSCSI protocol is not encrypted. The traffic could be secured using IPsec +but neither U-Boot nor iPXE does support this. So we should at least separate +the iSCSI traffic from all other network traffic. This can be achieved using a +virtual local area network (VLAN).
+Configuration +-------------
+iPXE +~~~~
+For running iPXE on arm64 the bin-arm64-efi/snp.efi build target is needed::
- git clone http://git.ipxe.org/ipxe.git
- cd ipxe/src
- make bin-arm64-efi/snp.efi -j6 EMBED=myscript.ipxe
+The available commands for the boot script are documented at:
+Credentials are managed as environment variables. These are described here:
+iPXE by default will put the CPU to rest when waiting for input. U-Boot does +not wake it up due to missing interrupt support. To avoid this behavior create +file src/config/local/nap.h::
Instead of using ::, we can use
.. code-block:: c
that can do some language specific keyword highlighting
- /* nap.h */
- #undef NAP_EFIX86
- #undef NAP_EFIARM
- #define NAP_NULL
+The supported commands in iPXE are controlled by an include, too. Putting the +following into src/config/local/general.h is sufficient for most use cases::
ditto
- /* general.h */
- #define NSLOOKUP_CMD /* Name resolution command */
- #define PING_CMD /* Ping command */
- #define NTP_CMD /* NTP commands */
- #define VLAN_CMD /* VLAN commands */
- #define IMAGE_EFI /* EFI image support */
- #define DOWNLOAD_PROTO_HTTPS /* Secure Hypertext Transfer Protocol */
- #define DOWNLOAD_PROTO_FTP /* File Transfer Protocol */
- #define DOWNLOAD_PROTO_NFS /* Network File System Protocol */
- #define DOWNLOAD_PROTO_FILE /* Local file system access */
+Open-iSCSI +~~~~~~~~~~
+When the root file system is on an iSCSI drive you should disable pings and set +the replacement timer to a high value [3]:
Missing .. code-block:: c
- node.conn[0].timeo.noop_out_interval = 0
- node.conn[0].timeo.noop_out_timeout = 0
- node.session.timeo.replacement_timeout = 86400
+Links +-----
+* [1] https://ipxe.org - iPXE open source boot firmware +* [2] https://www.gnu.org/software/grub/ -
- GNU GRUB (Grand Unified Bootloader)
+* [3] https://github.com/open-iscsi/open-iscsi/blob/master/README -
- Open-iSCSI README
diff --git a/doc/uefi/u-boot_on_efi.rst b/doc/uefi/u-boot_on_efi.rst new file mode 100644 index 0000000000..139173bc7a --- /dev/null +++ b/doc/uefi/u-boot_on_efi.rst @@ -0,0 +1,235 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright (C) 2015 Google, Inc
+U-Boot on EFI +============= +This document provides information about U-Boot running on top of EFI, either +as an application or just as a means of getting U-Boot onto a new platform.
+Motivation +---------- +Running U-Boot on EFI is useful in several situations:
+- You have EFI running on a board but U-Boot does not natively support it
- fully yet. You can boot into U-Boot from EFI and use that until U-Boot is
- fully ported
+- You need to use an EFI implementation (e.g. UEFI) because your vendor
- requires it in order to provide support
+- You plan to use coreboot to boot into U-Boot but coreboot support does
- not currently exist for your platform. In the meantime you can use U-Boot
- on EFI and then move to U-Boot on coreboot when ready
+- You use EFI but want to experiment with a simpler alternative like U-Boot
+Status +------ +Only x86 is supported at present. If you are using EFI on another architecture +you may want to reconsider. However, much of the code is generic so could be +ported.
+U-Boot supports running as an EFI application for 32-bit EFI only. This is +not very useful since only a serial port is provided. You can look around at +memory and type 'help' but that is about it.
+More usefully, U-Boot supports building itself as a payload for either 32-bit +or 64-bit EFI. U-Boot is packaged up and loaded in its entirety by EFI. Once +started, U-Boot changes to 32-bit mode (currently) and takes over the +machine. You can use devices, boot a kernel, etc.
+Build Instructions +------------------ +First choose a board that has EFI support and obtain an EFI implementation +for that board. It will be either 32-bit or 64-bit. Alternatively, you can +opt for using QEMU [1] and the OVMF [2], as detailed below.
+To build U-Boot as an EFI application (32-bit EFI required), enable CONFIG_EFI +and CONFIG_EFI_APP. The efi-x86_app config (efi-x86_app_defconfig) is set up +for this. Just build U-Boot as normal, e.g.
The above should be in preformatting blocks, by adding :: after e.g.
- make efi-x86_app_defconfig
- make
+To build U-Boot as an EFI payload (32-bit or 64-bit EFI can be used), enable +CONFIG_EFI, CONFIG_EFI_STUB, and select either CONFIG_EFI_STUB_32BIT or +CONFIG_EFI_STUB_64BIT. The efi-x86_payload configs (efi-x86_payload32_defconfig +and efi-x86_payload32_defconfig) are set up for this. Then build U-Boot as +normal, e.g.
ditto
- make efi-x86_payload32_defconfig (or efi-x86_payload64_defconfig)
- make
+You will end up with one of these files depending on what you build for:
- u-boot-app.efi - U-Boot EFI application
- u-boot-payload.efi - U-Boot EFI payload application
The above are poorly formatted
+Trying it out +------------- +QEMU is an emulator and it can emulate an x86 machine. Please make sure your +QEMU version is 2.3.0 or above to test this. You can run the payload with +something like this:
adding one more : to make the following pre-formatted
- mkdir /tmp/efi
- cp /path/to/u-boot*.efi /tmp/efi
- qemu-system-x86_64 -bios bios.bin -hda fat:/tmp/efi/
+Add -nographic if you want to use the terminal for output. Once it starts +type 'fs0:u-boot-payload.efi' to run the payload or 'fs0:u-boot-app.efi' to +run the application. 'bios.bin' is the EFI 'BIOS'. Check [2] to obtain a +prebuilt EFI BIOS for QEMU or you can build one from source as well.
+To try it on real hardware, put u-boot-app.efi on a suitable boot medium, +such as a USB stick. Then you can type something like this to start it:
ditto
- fs0:u-boot-payload.efi
+(or fs0:u-boot-app.efi for the application)
+This will start the payload, copy U-Boot into RAM and start U-Boot. Note +that EFI does not support booting a 64-bit application from a 32-bit +EFI (or vice versa). Also it will often fail to print an error message if +you get this wrong.
+Inner workings +-------------- +Here follow a few implementation notes for those who want to fiddle with +this and perhaps contribute patches.
+The application and payload approaches sound similar but are in fact +implemented completely differently.
+EFI Application +~~~~~~~~~~~~~~~ +For the application the whole of U-Boot is built as a shared library. The +efi_main() function is in lib/efi/efi_app.c. It sets up some basic EFI +functions with efi_init(), sets up U-Boot global_data, allocates memory for +U-Boot's malloc(), etc. and enters the normal init sequence (board_init_f() +and board_init_r()).
+Since U-Boot limits its memory access to the allocated regions very little +special code is needed. The CONFIG_EFI_APP option controls a few things +that need to change so 'git grep CONFIG_EFI_APP' may be instructive. +The CONFIG_EFI option controls more general EFI adjustments.
+The only available driver is the serial driver. This calls back into EFI +'boot services' to send and receive characters. Although it is implemented +as a serial driver the console device is not necessarilly serial. If you +boot EFI with video output then the 'serial' device will operate on your +target devices's display instead and the device's USB keyboard will also +work if connected. If you have both serial and video output, then both +consoles will be active. Even though U-Boot does the same thing normally, +These are features of EFI, not U-Boot.
+Very little code is involved in implementing the EFI application feature. +U-Boot is highly portable. Most of the difficulty is in modifying the +Makefile settings to pass the right build flags. In particular there is very +little x86-specific code involved - you can find most of it in +arch/x86/cpu. Porting to ARM (which can also use EFI if you are brave +enough) should be straightforward.
+Use the 'reset' command to get back to EFI.
+EFI Payload +~~~~~~~~~~~ +The payload approach is a different kettle of fish. It works by building +U-Boot exactly as normal for your target board, then adding the entire +image (including device tree) into a small EFI stub application responsible +for booting it. The stub application is built as a normal EFI application +except that it has a lot of data attached to it.
+The stub application is implemented in lib/efi/efi_stub.c. The efi_main() +function is called by EFI. It is responsible for copying U-Boot from its +original location into memory, disabling EFI boot services and starting +U-Boot. U-Boot then starts as normal, relocates, starts all drivers, etc.
+The stub application is architecture-dependent. At present it has some +x86-specific code and a comment at the top of efi_stub.c describes this.
+While the stub application does allocate some memory from EFI this is not +used by U-Boot (the payload). In fact when U-Boot starts it has all of the +memory available to it and can operate as it pleases (but see the next +section).
+Tables +~~~~~~ +The payload can pass information to U-Boot in the form of EFI tables. At +present this feature is used to pass the EFI memory map, an inordinately +large list of memory regions. You can use the 'efi mem all' command to +display this list. U-Boot uses the list to work out where to relocate +itself.
+Although U-Boot can use any memory it likes, EFI marks some memory as used +by 'run-time services', code that hangs around while U-Boot is running and +is even present when Linux is running. This is common on x86 and provides +a way for Linux to call back into the firmware to control things like CPU +fan speed. U-Boot uses only 'conventional' memory, in EFI terminology. It +will relocate itself to the top of the largest block of memory it can find +below 4GB.
+Interrupts +~~~~~~~~~~ +U-Boot drivers typically don't use interrupts. Since EFI enables interrupts +it is possible that an interrupt will fire that U-Boot cannot handle. This +seems to cause problems. For this reason the U-Boot payload runs with +interrupts disabled at present.
+32/64-bit +~~~~~~~~~ +While the EFI application can in principle be built as either 32- or 64-bit, +only 32-bit is currently supported. This means that the application can only +be used with 32-bit EFI.
+The payload stub can be build as either 32- or 64-bits. Only a small amount +of code is built this way (see the extra- line in lib/efi/Makefile). +Everything else is built as a normal U-Boot, so is always 32-bit on x86 at +present.
+Future work +----------- +This work could be extended in a number of ways:
+- Add ARM support
+- Add 64-bit application support
+- Figure out how to solve the interrupt problem
+- Add more drivers to the application side (e.g. video, block devices, USB,
- environment access). This would mostly be an academic exercise as a strong
- use case is not readily apparent, but it might be fun.
+- Avoid turning off boot services in the stub. Instead allow U-Boot to make
- use of boot services in case it wants to. It is unclear what it might want
- though.
+Where is the code? +------------------ +lib/efi
payload stub, application, support code. Mostly arch-neutral
+arch/x86/cpu/efi
x86 support code for running as an EFI application and payload
+board/efi/efi-x86_app/efi.c
x86 board code for running as an EFI application
+board/efi/efi-x86_payload
generic x86 EFI payload board support code
+common/cmd_efi.c
the 'efi' command
+-- +Ben Stoltz, Simon Glass +Google, Inc +July 2015
+[1] http://www.qemu.org +[2] http://www.tianocore.org/ovmf/
A bullet should be added before [1] and [2]
diff --git a/doc/uefi/uefi.rst b/doc/uefi/uefi.rst new file mode 100644 index 0000000000..476117bfc5 --- /dev/null +++ b/doc/uefi/uefi.rst @@ -0,0 +1,334 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright (c) 2018 Heinrich Schuchardt
+UEFI on U-Boot +==============
+The Unified Extensible Firmware Interface Specification (UEFI) [1] has become +the default for booting on AArch64 and x86 systems. It provides a stable API for +the interaction of drivers and applications with the firmware. The API comprises +access to block storage, network, and console to name a few. The Linux kernel +and boot loaders like GRUB or the FreeBSD loader can be executed.
+Development target +------------------
+The implementation of UEFI in U-Boot strives to reach the requirements described +in the "Embedded Base Boot Requirements (EBBR) Specification - Release v1.0" +[4]. The "Server Base Boot Requirements System Software on ARM Platforms" [5] +describes a superset of the EBBR specification and may be used as further +reference.
+A full blown UEFI implementation would contradict the U-Boot design principle +"keep it small".
+Building U-Boot for UEFI +------------------------
+The UEFI standard supports only little-endian systems. The UEFI support can be +activated for ARM and x86 by specifying::
- CONFIG_CMD_BOOTEFI=y
- CONFIG_EFI_LOADER=y
+in the .config file.
+Support for attaching virtual block devices, e.g. iSCSI drives connected by the +loaded UEFI application [3], requires::
- CONFIG_BLK=y
- CONFIG_PARTITIONS=y
+Executing a UEFI binary +~~~~~~~~~~~~~~~~~~~~~~~
+The bootefi command is used to start UEFI applications or to install UEFI +drivers. It takes two parameters::
- bootefi <image address> [fdt address]
+* image address - the memory address of the UEFI binary +* fdt address - the memory address of the flattened device tree
+Below you find the output of an example session starting GRUB::
- => load mmc 0:2 ${fdt_addr_r} boot/dtb
- 29830 bytes read in 14 ms (2 MiB/s)
- => load mmc 0:1 ${kernel_addr_r} efi/debian/grubaa64.efi
- reading efi/debian/grubaa64.efi
- 120832 bytes read in 7 ms (16.5 MiB/s)
- => bootefi ${kernel_addr_r} ${fdt_addr_r}
+The environment variable 'bootargs' is passed as load options in the UEFI system +table. The Linux kernel EFI stub uses the load options as command line +arguments.
+Executing the boot manager +~~~~~~~~~~~~~~~~~~~~~~~~~~
+The UEFI specification foresees to define boot entries and boot sequence via UEFI +variables. Booting according to these variables is possible via::
- bootefi bootmgr [fdt address]
+As of U-Boot v2018.03 UEFI variables are not persisted and cannot be set at +runtime.
+Executing the built in hello world application +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+A hello world UEFI application can be built with::
- CONFIG_CMD_BOOTEFI_HELLO_COMPILE=y
+It can be embedded into the U-Boot binary with::
- CONFIG_CMD_BOOTEFI_HELLO=y
+The bootefi command is used to start the embedded hello world application::
- bootefi hello [fdt address]
+Below you find the output of an example session::
- => bootefi hello ${fdtcontroladdr}
- ## Starting EFI application at 01000000 ...
- WARNING: using memory device/image path, this may confuse some payloads!
- Hello, world!
- Running on UEFI 2.7
- Have SMBIOS table
- Have device tree
- Load options: root=/dev/sdb3 init=/sbin/init rootwait ro
- ## Application terminated, r = 0
+The environment variable fdtcontroladdr points to U-Boot's internal device tree +(if available).
+Executing the built-in self-test +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+An UEFI self-test suite can be embedded in U-Boot by building with::
- CONFIG_CMD_BOOTEFI_SELFTEST=y
+For testing the UEFI implementation the bootefi command can be used to start the +self-test::
- bootefi selftest [fdt address]
+The environment variable 'efi_selftest' can be used to select a single test. If +it is not provided all tests are executed except those marked as 'on request'. +If the environment variable is set to 'list' a list of all tests is shown.
+Below you can find the output of an example session::
- => setenv efi_selftest simple network protocol
- => bootefi selftest
- Testing EFI API implementation
- Selected test: 'simple network protocol'
- Setting up 'simple network protocol'
- Setting up 'simple network protocol' succeeded
- Executing 'simple network protocol'
- DHCP Discover
- DHCP reply received from 192.168.76.2 (52:55:c0:a8:4c:02)
as broadcast message.
- Executing 'simple network protocol' succeeded
- Tearing down 'simple network protocol'
- Tearing down 'simple network protocol' succeeded
- Boot services terminated
- Summary: 0 failures
- Preparing for reset. Press any key.
+The UEFI life cycle +-------------------
+After the U-Boot platform has been initialized the UEFI API provides two kinds +of services
+* boot services and
nits: remove and
+* runtime services.
nits: remove the ending period
+The API can be extended by loading UEFI drivers which come in two variants
+* boot drivers and
nits: remove and
+* runtime drivers.
nits: remove the ending period
+UEFI drivers are installed with U-Boot's bootefi command. With the same command +UEFI applications can be executed.
+Loaded images of UEFI drivers stay in memory after returning to U-Boot while +loaded images of applications are removed from memory.
+An UEFI application (e.g. an operating system) that wants to take full control +of the system calls ExitBootServices. After a UEFI application calls +ExitBootServices
+* boot services are not available anymore +* timer events are stopped +* the memory used by U-Boot except for runtime services is released +* the memory used by boot time drivers is released
+So this is a point of no return. Afterwards the UEFI application can only return +to U-Boot by rebooting.
+The UEFI object model +---------------------
+UEFI offers a flexible and expandable object model. The objects in the UEFI API +are devices, drivers, and loaded images. These objects are referenced by +handles.
+The interfaces implemented by the objects are referred to as protocols. These +are identified by GUIDs. They can be installed and uninstalled by calling the +appropriate boot services.
+Handles are created by the InstallProtocolInterface or the +InstallMultipleProtocolinterfaces service if NULL is passed as handle.
+Handles are deleted when the last protocol has been removed with the +UninstallProtocolInterface or the UninstallMultipleProtocolInterfaces service.
+Devices offer the EFI_DEVICE_PATH_PROTOCOL. A device path is the concatenation +of device nodes. By their device paths all devices of a system are arranged in a +tree.
+Drivers offer the EFI_DRIVER_BINDING_PROTOCOL. This protocol is used to connect +a driver to devices (which are referenced as controllers in this context).
+Loaded images offer the EFI_LOADED_IMAGE_PROTOCOL. This protocol provides meta +information about the image and a pointer to the unload callback function.
+The UEFI events +---------------
+In the UEFI terminology an event is a data object referencing a notification +function which is queued for calling when the event is signaled. The following +types of events exist:
+* periodic and single shot timer events +* exit boot services events, triggered by calling the ExitBootServices() service +* virtual address change events +* memory map change events +* read to boot events +* reset system events +* system table events +* events that are only triggered programmatically
+Events can be created with the CreateEvent service and deleted with CloseEvent +service.
+Events can be assigned to an event group. If any of the events in a group is +signaled, all other events in the group are also set to the signaled state.
+The UEFI driver model +---------------------
+A driver is specific for a single protocol installed on a device. To install a +driver on a device the ConnectController service is called. In this context +controller refers to the device for which the driver is installed.
+The relevant drivers are identified using the EFI_DRIVER_BINDING_PROTOCOL. This +protocol has has three functions:
+* supported - determines if the driver is compatible with the device +* start - installs the driver by opening the relevant protocol with
- attribute EFI_OPEN_PROTOCOL_BY_DRIVER
+* stop - uninstalls the driver
+The driver may create child controllers (child devices). E.g. a driver for block +IO devices will create the device handles for the partitions. The child +controllers will open the supported protocol with the attribute +EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+A driver can be detached from a device using the DisconnectController service.
+U-Boot devices mapped as UEFI devices +-------------------------------------
+Some of the U-Boot devices are mapped as UEFI devices
+* block IO devices +* console +* graphical output +* network adapter
+As of U-Boot 2018.03 the logic for doing this is hard coded.
+The development target is to integrate the setup of these UEFI devices with the +U-Boot driver model. So when a U-Boot device is discovered a handle should be +created and the device path protocol and the relevant IO protocol should be +installed. The UEFI driver then would be attached by calling ConnectController. +When a U-Boot device is removed DisconnectController should be called.
+UEFI devices mapped as U-Boot devices +-------------------------------------
+UEFI drivers binaries and applications may create new (virtual) devices, install +a protocol and call the ConnectController service. Now the matching UEFI driver +is determined by iterating over the implementations of the +EFI_DRIVER_BINDING_PROTOCOL.
+It is the task of the UEFI driver to create a corresponding U-Boot device and to +proxy calls for this U-Boot device to the controller.
+In U-Boot 2018.03 this has only been implemented for block IO devices.
+UEFI uclass +~~~~~~~~~~~
+An UEFI uclass driver (lib/efi_driver/efi_uclass.c) has been created that +takes care of initializing the UEFI drivers and providing the +EFI_DRIVER_BINDING_PROTOCOL implementation for the UEFI drivers.
+A linker created list is used to keep track of the UEFI drivers. To create an +entry in the list the UEFI driver uses the U_BOOT_DRIVER macro specifying +UCLASS_EFI as the ID of its uclass, e.g::
- /* Identify as UEFI driver */
- U_BOOT_DRIVER(efi_block) = {
.name = "EFI block driver",
.id = UCLASS_EFI,
.ops = &driver_ops,
- };
+The available operations are defined via the structure struct efi_driver_ops::
- struct efi_driver_ops {
const efi_guid_t *protocol;
const efi_guid_t *child_protocol;
int (*bind)(efi_handle_t handle, void *interface);
- };
+When the supported() function of the EFI_DRIVER_BINDING_PROTOCOL is called the +uclass checks if the protocol GUID matches the protocol GUID of the UEFI driver. +In the start() function the bind() function of the UEFI driver is called after +checking the GUID. +The stop() function of the EFI_DRIVER_BINDING_PROTOCOL disconnects the child +controllers created by the UEFI driver and the UEFI driver. (In U-Boot v2013.03 +this is not yet completely implemented.)
+UEFI block IO driver +~~~~~~~~~~~~~~~~~~~~
+The UEFI block IO driver supports devices exposing the EFI_BLOCK_IO_PROTOCOL.
+When connected it creates a new U-Boot block IO device with interface type +IF_TYPE_EFI, adds child controllers mapping the partitions, and installs the +EFI_SIMPLE_FILE_SYSTEM_PROTOCOL on these. This can be used together with the +software iPXE to boot from iSCSI network drives [3].
+This driver is only available if U-Boot is configured with
- CONFIG_BLK=y
- CONFIG_PARTITIONS=y
+Links +-----
+* [1] http://uefi.org/specifications - UEFI specifications +* [2] :doc:`../driver-model/index`
Looks this is not referenced anywhere in the documentation.
+* [3] :doc:`iscsi` +* [4] https://github.com/ARM-software/ebbr/releases/download/v1.0/ebbr-v1.0.pdf -
- Embedded Base Boot Requirements (EBBR) Specification - Release v1.0
+* [5] https://developer.arm.com/docs/den0044/latest/server-base-boot-requirements-... -
- Server Base Boot Requirements System Software on ARM Platforms - Version 1.1
nits: these docs are not referenced in their orders, eg: [1] [4] [5] [3]
--
Regards, Bin