[U-Boot] [PATCH v3 2/2] efi_loader: provide new doc/README.uefi

Leif Lindholm leif.lindholm at linaro.org
Fri Mar 2 20:02:19 UTC 2018


On Fri, Mar 02, 2018 at 07:58:50PM +0100, Heinrich Schuchardt wrote:
> 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>

Well, from my point of view:
Reviewed-by: Leif Lindholm <leif.lindholm at linaro.org>
or
Acked-by: Leif Lindholm <leif.lindholm at linaro.org>
(whichever makes more sense).

Many thanks!

/
    Leif

> ---
> v3
> 	rename README.efi to README.uefi
> 	use UEFI instead of EFI where applicable
> v2
> 	split the patch in two: one deleteing all old lines, the other
> 	adding the new ones
> 	update README contents
> ---
>  MAINTAINERS     |   2 +-
>  doc/README.efi  |   0
>  doc/README.uefi | 332 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 333 insertions(+), 1 deletion(-)
>  delete mode 100644 doc/README.efi
>  create mode 100644 doc/README.uefi
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 077828cf1d4..da799b551d9 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -290,7 +290,7 @@ EFI PAYLOAD
>  M:	Alexander Graf <agraf at suse.de>
>  S:	Maintained
>  T:	git git://github.com/agraf/u-boot.git
> -F:	doc/README.efi
> +F:	doc/README.uefi
>  F:	doc/README.iscsi
>  F:	include/efi*
>  F:	include/pe.h
> diff --git a/doc/README.efi b/doc/README.efi
> deleted file mode 100644
> index e69de29bb2d..00000000000
> diff --git a/doc/README.uefi b/doc/README.uefi
> new file mode 100644
> index 00000000000..7403be36146
> --- /dev/null
> +++ b/doc/README.uefi
> @@ -0,0 +1,332 @@
> +<!--
> +    Copyright (c) 2018 Heinrich Schuchardt
> +
> +    SPDX-License-Identifier:     GPL-2.0+
> +-->
> +
> +# 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.
> +
> +## 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 specfication 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 selftest
> +
> +An UEFI selftest 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
> +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 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 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
> +
> +* UEFI drivers
> +  * support DisconnectController for UEFI block devices.
> +
> +* support for CONFIG_EFI_LOADER in the sandbox (CONFIG_SANDBOX=y)
> +
> +* UEFI variables
> +  * persistence
> +  * runtime support
> +
> +## 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.16.1
> 


More information about the U-Boot mailing list