
On 30.01.18 20:03, Heinrich Schuchardt wrote:
Provide information about
- usage of the bootefi command
- overview of UEFI
- interaction between U-Boot and EFI drivers
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de
v2 new file
The patch is very hard to read. Please just make this 2 patches. One that removes the old file, one that adds the rewrite.
doc/README.efi | 322 ++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 264 insertions(+), 58 deletions(-)
diff --git a/doc/README.efi b/doc/README.efi index 956f5bfa0c..ea1facc431 100644 --- a/doc/README.efi +++ b/doc/README.efi @@ -1,86 +1,292 @@ -# -# Copyright (C) 2015 Google, Inc -# -# SPDX-License-Identifier: GPL-2.0+ -# +<!--
- Copyright (c) 2018 Heinrich Schuchardt
-EFI on U-Boot
-This document provides information about the implementation of the UEFI API [1] -in U-Boot.
- SPDX-License-Identifier: GPL-2.0+
+-->
+# EFI on U-Boot
-=========== Table of Contents =========== +## Motivation
Just remove the "Motivation" line. The text below is just the starting paragraph for "EFI on U-Boot".
-Motivation -How do I get it? -Status -Future work +The Unified Extensible Firmware Interface Specification (UEFI) has become the +default for booting on AArch64 and x86 systems. It provides a stable API for the +interaction between the firmware and the drivers and applications loaded by the
firmware, drivers and applications
+firmware. The API provides 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
-Motivation
+The UEFI standard supports only little endian systems. The EFI support can be +activated for ARM and x86 by specifying
-With this API support in place, you can run any UEFI payload (such as the Linux -kernel, grub2 or gummiboot) on U-Boot. This dramatically simplifies boot loader -configuration, as U-Boot based systems now look and feel (almost) the same way -as TianoCore based systems.
- CONFIG_CMD_BOOTEFI=y
- CONFIG_EFI_LOADER=y
-How do I get it?
+in the .config file.
-EFI support for 32bit ARM and AArch64 is already included in U-Boot. All you -need to do is enable +Support for attaching virtual block devices, e.g. iSCSI drives connected by the +loaded EFI application, requires
Please provide a link to the README.iscsi file here.
- CONFIG_CMD_BOOTEFI=y
- CONFIG_EFI_LOADER=y
- CONFIG_BLK=y
- CONFIG_PARTITIONS=y
-in your .config file and you will automatically get a bootefi command to run -an efi application as well as snippet in the default distro boot script that -scans for removable media efi binaries as fallback. +A hello world EFI application can be built with
All those hello world and selftest etc. things should be covered in their own section IMHO. So you want to have a section on selftest (which you have) and shortly mention the CONFIG option to enable it in there.
-Status
- CONFIG_CMD_BOOTEFI_HELLO_COMPILE=y
-I am successfully able to run grub2 and Linux EFI binaries with this code on -ARMv7 as well as AArch64 systems. +It can be embedded into the U-Boot binary for starting with command +'bootefi hello' with
-When enabled, the resulting U-Boot binary only grows by ~10KB, so it's very -light weight.
- CONFIG_CMD_BOOTEFI_HELLO=y
-All storage devices are directly accessible from the uEFI payload +A test suite that can be executed with command 'bootefi selftest' is provided +by
-Removable media booting (search for /efi/boot/boota{a64,arm}.efi) is supported.
- CONFIG_SELFTEST=y
-Simple use cases like "Plug this SD card into my ARM device and it just -boots into grub which boots into Linux", work very well. +## The bootefi command
+### Executing an EFI binary
-Running HelloWord.efi
+The bootefi command is used to start EFI applications or to install EFI drivers. +It takes two parameters
-You can run a simple 'hello world' EFI program in U-Boot. -Enable the option CONFIG_CMD_BOOTEFI_HELLO.
- bootefi <image address> [fdt address]
-Then you can boot into U-Boot and type: +* image address - the memory address of the EFI binary +* fdt address - the memory address of the flattened device tree
bootefi hello+Below you find the output of an example session starting Grub.
-The 'hello world EFI' program will then run, print a message and exit.
- => 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.
-Future work
+### Executing the boot manager
-Of course, there are still a few things one could do on top: +The UEFI specfication forsees to define boot entries and boot sequence via EFI +variables. Booting according to these variables is possible via
- Improve disk media detection (don't scan, use what information we
-have)
- Add EFI variable support using NVRAM
- Add GFX support
- Make EFI Shell work
- Network device support
- Support for payload exit
- Payload Watchdog support
- bootefi bootmgr [fdt address]
-[1] http://uefi.org/ +As of U-Boot v2018.03 EFI variables cannot be set by the operating system.
Depends on your scope of OS. This is a mine field to document correctly. Just leave it out?
So this development is not usable yet.
That's only half-true. Just remove the last sentence.
+### Executing the built in hello world application
Here I would just mention that this depends on CONFIG_CMD_BOOTEFI_HELLO
+For testing the bootefi command can be used to start a hello world application.
- bootefi hello [fdt address]
+Below you find the output of an example session.
- => bootefi hello
- ## Starting EFI application at 01000000 ...
- WARNING: Invalid device tree, expect boot to fail
- Hello, world!
- Have SMBIOS table
- Load options: root=/dev/sdb3 init=/sbin/init rootwait ro
- ## Application terminated, r = 0
+### Executing the built in hello world application
This does not describe the hello world application :). Same comment with the CONFIG_ option applies here too.
+For testing the EFI implementation bootefi command can be used to start a 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 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 enhanced by loading EFI drivers which come in two variants
s/enhanced/extended/
+* boot drivers and +* runtime drivers.
+EFI drivers are installed with U-Boot's bootefi command. With the same command +EFI applications can be run.
s/run/executed/
+Loaded images of EFI drivers stay in memory after returning to U-Boot while +loaded images of applications are removed from memory.
+After an EFI application calls ExitBootServices
This is missing a sentence mentioning when someone would call 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 the point of no return where the EFI application takes charge of the +system. Afterwards it 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 drivers 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 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
+The device for which a driver is installed is called the controller.
+A driver is specific for a single protocol installed on a device. To install a +driver on a device the ConnectController service is called.
+The EFI_DRIVER_BINDING_PROTOCOL of the driver 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 attribute +EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+A driver can be detached from a device with the DisconnectController service.
+## EFI uclass
+An EFI uclass driver (lib/efi_driver/efi_uclass.c) has been created that +maintains a list of all EFI drivers supplied by U-Boot. The uclass is +responsible for creating a handle for each of the drivers and installing and +handling the EFI_DRIVER_BINDING_PROTOCOL.
This is the one thing you can't read up in the UEFI specification, so this is definitely a section that needs a good chunk of extension :).
+## 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 an U-Boot device is discovered a handle should be
When you pronounce U-Boot, the first sound is a Y which is a consonant, so you have to write "a U-Boot" :).
Yes, English is weird.
+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 an U-Boot device is removed DisconnectController should be called.
+## EFI devices mapped as U-Boot devices
Ah, there is the section on the EFI_UCLASS. Please just move it into this section and explain the *flow* that happens. Which entity creates what when.
+EFI drivers and applications may create new (virtual) devices, install a +protocol and call the ConnectController service. Now the matching EFI driver can +be determined.
+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 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 (see doc/README.iscsi).
Since you're using md syntax throughout, just use inter-file md links here as well.
+The 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
+* 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
+## Links
+http://uefi.org/specifications - UEFI specifications +doc/driver-model/README.txt - Driver model +doc/README.iscsi - iSCSI booting with U-Boot and iPXE
Mark them with md link tags and refer to them throughout the text when you need it :)
Alex