[U-Boot] [PATCH v2 0/2] efi_loader: update README.efi

Split README.efi into two separate documents. One for U-Boot on EFI and one for EFI on U-Boot.
Provide information about
- usage of the bootefi command - overview of UEFI - interaction between U-Boot and EFI drivers
in README.efi --- v2 Provide new README.efi --- Heinrich Schuchardt (2): efi_loader: split README.efi into two separate documents efi_loader: rewrite README.efi
MAINTAINERS | 1 + doc/README.efi | 535 +++++++++++++++++++++-------------------------- doc/README.u-boot_on_efi | 259 +++++++++++++++++++++++ 3 files changed, 504 insertions(+), 291 deletions(-) create mode 100644 doc/README.u-boot_on_efi

README.efi describes two different concepts: * U-Boot exposing the UEFI API * U-Boot running on top of UEFI.
This patch splits the document in two. Religious references are removed.
The separation of the concepts makes sense before detailing the internals of U-Boot exposing the UEFI API in a future patch.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de --- v2 Do not set maintainer for README.u-boot_on_efi --- MAINTAINERS | 1 + doc/README.efi | 275 ++--------------------------------------------- doc/README.u-boot_on_efi | 259 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 271 insertions(+), 264 deletions(-) create mode 100644 doc/README.u-boot_on_efi
diff --git a/MAINTAINERS b/MAINTAINERS index 0aecc18a6c..6d4f335d4a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -289,6 +289,7 @@ EFI PAYLOAD M: Alexander Graf agraf@suse.de S: Maintained T: git git://github.com/agraf/u-boot.git +F: doc/README.efi F: doc/README.iscsi F: include/efi* F: lib/efi*/ diff --git a/doc/README.efi b/doc/README.efi index 66259f3e26..956f5bfa0c 100644 --- a/doc/README.efi +++ b/doc/README.efi @@ -4,279 +4,24 @@ # SPDX-License-Identifier: GPL-2.0+ #
-=========== Table of Contents =========== - - 1 U-Boot on EFI - 1.1 In God's Name, Why? - 1.2 Status - 1.3 Build Instructions - 1.4 Trying it out - 1.5 Inner workings - 1.6 EFI Application - 1.7 EFI Payload - 1.8 Tables - 1.9 Interrupts - 1.10 32/64-bit - 1.11 Future work - 1.12 Where is the code? - - 2 EFI on U-Boot - 2.1 In God's Name, Why? - 2.2 How do I get it? - 2.3 Status - 2.4 Future work - -U-Boot on EFI +EFI on U-Boot ============= -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. - - -In God's Name, Why? -------------------- -This 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 +This document provides information about the implementation of the UEFI API [1] +in U-Boot.
-- 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
+=========== Table of Contents ===========
+Motivation +How do I get it? 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 config (efi-x86_defconfig) is set up for this. -Just build U-Boot as normal, e.g. - - make efi-x86_defconfig - make - -To build U-Boot as an EFI payload (32-bit or 64-bit EFI can be used), adjust an -existing config (like qemu-x86_defconfig) to enable CONFIG_EFI, CONFIG_EFI_STUB -and either CONFIG_EFI_STUB_32BIT or CONFIG_EFI_STUB_64BIT. All of these are -boolean Kconfig options. Then build U-Boot as normal, e.g. - - make qemu-x86_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 a generic x86 EFI payload configuration. At present you need to modify -an existing one, but mostly the low-level x86 code is disabled when booting -on EFI anyway, so a generic 'EFI' board could be created with a suitable set -of drivers enabled.
-- 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/lib/efi - helper functions for the fake DRAM init, etc. These can be used by - any board that runs as a payload. - -arch/x86/cpu/efi - x86 support code for running as an EFI application - -board/efi/efi-x86/efi.c - x86 board code for running as an EFI application - -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/ - -------------------------------------------------------------------------------- - -EFI on U-Boot -============= - -In addition to support for running U-Boot as a UEFI application, U-Boot itself -can also expose the UEFI interfaces and thus allow UEFI payloads to run under -it. - -In God's Name, Why? -------------------- +Motivation +----------
-With this support in place, you can run any UEFI payload (such as the Linux +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. @@ -337,3 +82,5 @@ have) - Network device support - Support for payload exit - Payload Watchdog support + +[1] http://uefi.org/ diff --git a/doc/README.u-boot_on_efi b/doc/README.u-boot_on_efi new file mode 100644 index 0000000000..298b94e342 --- /dev/null +++ b/doc/README.u-boot_on_efi @@ -0,0 +1,259 @@ +# +# Copyright (C) 2015 Google, Inc +# +# SPDX-License-Identifier: GPL-2.0+ +# + +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 config (efi-x86_defconfig) is set up for this. +Just build U-Boot as normal, e.g. + + make efi-x86_defconfig + make + +To build U-Boot as an EFI payload (32-bit or 64-bit EFI can be used), adjust an +existing config (like qemu-x86_defconfig) to enable CONFIG_EFI, CONFIG_EFI_STUB +and either CONFIG_EFI_STUB_32BIT or CONFIG_EFI_STUB_64BIT. All of these are +boolean Kconfig options. Then build U-Boot as normal, e.g. + + make qemu-x86_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 a generic x86 EFI payload configuration. At present you need to modify +an existing one, but mostly the low-level x86 code is disabled when booting +on EFI anyway, so a generic 'EFI' board could be created with a suitable set +of drivers enabled. + +- 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/lib/efi + helper functions for the fake DRAM init, etc. These can be used by + any board that runs as a payload. + +arch/x86/cpu/efi + x86 support code for running as an EFI application + +board/efi/efi-x86/efi.c + x86 board code for running as an EFI application + +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/

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 --- 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
-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. 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
- 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
-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. So +this development is not usable yet. + +### Executing the built in hello world application + +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 + +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 + +* boot drivers and +* runtime drivers. + +EFI drivers are installed with U-Boot's bootefi command. With the same command +EFI applications can be run. + +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 + +* 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. + +## 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 +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 + +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). + +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

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

Hi Alex,
On 9 February 2018 at 11:55, Alexander Graf agraf@suse.de wrote:
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.
That doesn't make a lot of sense to me. Can you not just apply the patch locally and read it?
Regards, Simon

Am 12.02.2018 um 15:35 schrieb Simon Glass sjg@chromium.org:
Hi Alex,
On 9 February 2018 at 11:55, Alexander Graf agraf@suse.de wrote:
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.
That doesn't make a lot of sense to me. Can you not just apply the patch locally and read it?
That‘s what I did, but I doubt the occasional reviewer does it. He also rewrites the file completely, even changing copyright. So IMHO remove+add is the better way to express what is happening here.
Alex

Hi Alex,
On 12 February 2018 at 12:41, Alexander Graf agraf@suse.de wrote:
Am 12.02.2018 um 15:35 schrieb Simon Glass sjg@chromium.org:
Hi Alex,
On 9 February 2018 at 11:55, Alexander Graf agraf@suse.de wrote:
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.
That doesn't make a lot of sense to me. Can you not just apply the patch locally and read it?
That‘s what I did, but I doubt the occasional reviewer does it. He also rewrites the file completely, even changing copyright. So IMHO remove+add is the better way to express what is happening here.
Then perhaps the changes should be multiple patches? I agree it is hard to review this sort of thing. But if you are happy with a complete rewrite, then why not add a review tag? It doesn't much matter that others cannot be bothered to review it properly. There is some benefit to having a change history, I think.
Regards, Simon

Am 12.02.2018 um 21:42 schrieb Simon Glass sjg@chromium.org:
Hi Alex,
On 12 February 2018 at 12:41, Alexander Graf agraf@suse.de wrote:
Am 12.02.2018 um 15:35 schrieb Simon Glass sjg@chromium.org:
Hi Alex,
On 9 February 2018 at 11:55, Alexander Graf agraf@suse.de wrote:
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.
That doesn't make a lot of sense to me. Can you not just apply the patch locally and read it?
That‘s what I did, but I doubt the occasional reviewer does it. He also rewrites the file completely, even changing copyright. So IMHO remove+add is the better way to express what is happening here.
Then perhaps the changes should be multiple patches? I agree it is hard to review this sort of thing. But if you are happy with a complete rewrite, then why not add a review tag?
Because I had another ~10 comments inline :).
Alex
It doesn't much matter that others cannot be bothered to review it properly. There is some benefit to having a change history, I think.
Regards, Simon
participants (3)
-
Alexander Graf
-
Heinrich Schuchardt
-
Simon Glass