[U-Boot] [PATCH v2 2/2][for v2018.03] efi_loader: provide new doc/README.efi

Heinrich Schuchardt xypron.glpk at gmx.de
Fri Feb 16 11:44:27 UTC 2018


Provides information about

- usage of the bootefi command
- overview of UEFI
- interaction between U-Boot and EFI drivers

Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
---
 doc/README.efi | 323 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 323 insertions(+)

diff --git a/doc/README.efi b/doc/README.efi
index e69de29bb2d..92f7587a1af 100644
--- a/doc/README.efi
+++ b/doc/README.efi
@@ -0,0 +1,323 @@
+<!--
+    Copyright (c) 2018 Heinrich Schuchardt
+
+    SPDX-License-Identifier:     GPL-2.0+
+-->
+
+# EFI 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.
+
+## Building for EFI
+
+The UEFI standard supports only little endian systems. The EFI 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 EFI application [3], requires
+
+    CONFIG_BLK=y
+    CONFIG_PARTITIONS=y
+
+### Executing an EFI binary
+
+The bootefi command is used to start EFI applications or to install EFI drivers.
+It takes two parameters
+
+    bootefi <image address> [fdt address]
+
+* image address - the memory address of the EFI 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 EFI system
+table. The Linux kernel EFI stub uses the load options as command line
+arguments.
+
+### Executing the boot manager
+
+The UEFI specfication foresees to define boot entries and boot sequence via EFI
+variables. Booting according to these variables is possible via
+
+    bootefi bootmgr [fdt address]
+
+As of U-Boot v2018.03 EFI variables are not persisted and cannot be set at
+runtime.
+
+### Executing the built in hello world application
+
+A hello world EFI 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-Boots internal device tree
+(if available).
+
+### Executing the built-in selftest
+
+An EFI selftest suite can be embedded in U-Boot by building with
+
+    CONFIG_SELFTEST=y
+
+For testing the EFI implementation the bootefi command can be used to start the
+selftest.
+
+    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 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 EFI 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 EFI drivers which come in two variants
+
+* boot drivers and
+* runtime drivers.
+
+EFI drivers are installed with U-Boot's bootefi command. With the same command
+EFI applications can be executed.
+
+Loaded images of EFI drivers stay in memory after returning to U-Boot while
+loaded images of applications are removed from memory.
+
+An EFI application (e.g. an operating system) that wants to take full control
+of the system calls ExitBootServices. After an EFI 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 EFI application can only return
+to U-Boot by rebooting.
+
+## The EFI object model
+
+EFI offers a flexible and expandable object model. The objects in the EFI 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 EFI 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 (not yet implemented in U-Boot)
+* events that are only triggered programmatically
+
+Events can be created with the CreateEvent service and deleted with CloseEvent
+service.
+
+## The EFI 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 EFI devices
+
+Some of the U-Boot devices are mapped as EFI 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 EFI 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 EFI driver then would be attached by calling ConnectController.
+When a U-Boot device is removed DisconnectController should be called.
+
+## EFI devices mapped as U-Boot devices
+
+EFI drivers binaries and applications may create new (virtual) devices, install
+a protocol and call the ConnectController service. Now the matching EFI driver
+is determined by iterating over the implementations of the
+EFI_DRIVER_BINDING_PROTOCOL.
+
+It is the task of the EFI 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.
+
+### EFI uclass
+
+An EFI uclass driver (lib/efi_driver/efi_uclass.c) has been created that
+takes care of initializing the EFI drivers and providing the
+EFI_DRIVER_BINDING_PROTOCOL implementation for the EFI drivers.
+
+A linker created list is used to keep track of the EFI drivers. To create an
+entry in the list the EFI driver uses the U_BOOT_DRIVER macro specifying
+UCLASS_EFI as the ID of its uclass, e.g.
+
+    /* Identify as EFI 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 EFI driver.
+In the start() function the bind() function of the EFI driver is called after
+checking the GUID.
+The stop() function of the EFI_DRIVER_BINDING_PROTOCOL disconnects the child
+controllers created by the EFI driver and the EFI driver. (In U-Boot v2013.03
+this is not yet completely implemented.)
+
+### EFI block IO driver
+
+The EFI 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
+
+## Open issues as of U-Boot 2018.03
+
+* unimplemented or incompletely implemented boot services
+  * Exit - call unload function, unload applications only
+  * ReinstallProtocolInterface
+  * UnloadImage
+
+* unimplemented events
+  * EVT_RUNTIME
+  * EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
+  * event groups
+
+* data model
+  * manage events in a linked list
+  * manage configuration tables in a linked list
+
+* EFI drivers
+  * support DisconnectController for EFI block devices.
+
+* Sandbox support for CONFIG_EFI_LOADER
+
+* persisted EFI variables
+
+## 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
-- 
2.14.2



More information about the U-Boot mailing list