diff options
| author | Simon Glass <[email protected]> | 2021-03-18 20:25:11 +1300 |
|---|---|---|
| committer | Simon Glass <[email protected]> | 2021-03-26 17:03:10 +1300 |
| commit | d1ceeeff6c2ee1e55b7140654c8d6de44b60dab6 (patch) | |
| tree | 7abee7a0ca0e6c1b7e8d12ff9b20340b8888baf7 /doc/uefi | |
| parent | cad7b6b2519a275d79085bbdff0227492cd8ee48 (diff) | |
doc: Move UEFI under develop/
Much of the content here is useful only for development. Move it under
that section.
Signed-off-by: Simon Glass <[email protected]>
Reviewed-by: Heinrich Schuchardt <[email protected]>
Diffstat (limited to 'doc/uefi')
| -rw-r--r-- | doc/uefi/index.rst | 11 | ||||
| -rw-r--r-- | doc/uefi/iscsi.rst | 184 | ||||
| -rw-r--r-- | doc/uefi/u-boot_on_efi.rst | 235 | ||||
| -rw-r--r-- | doc/uefi/uefi.rst | 498 |
4 files changed, 0 insertions, 928 deletions
diff --git a/doc/uefi/index.rst b/doc/uefi/index.rst deleted file mode 100644 index b790a91f174..00000000000 --- a/doc/uefi/index.rst +++ /dev/null @@ -1,11 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0+ - -Unified Extensible Firmware (UEFI) -================================== - -.. toctree:: - :maxdepth: 2 - - uefi.rst - u-boot_on_efi.rst - iscsi.rst diff --git a/doc/uefi/iscsi.rst b/doc/uefi/iscsi.rst deleted file mode 100644 index 51d38cde243..00000000000 --- a/doc/uefi/iscsi.rst +++ /dev/null @@ -1,184 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0+ -.. Copyright (c) 2018 Heinrich Schuchardt - -iSCSI booting with U-Boot and iPXE -================================== - -Motivation ----------- - -U-Boot has only a reduced set of supported network protocols. The focus for -network booting has been on UDP based protocols. A TCP stack and HTTP support -are expected to be integrated in 2018 together with a wget command. - -For booting a diskless computer this leaves us with BOOTP or DHCP to get the -address of a boot script. TFTP or NFS can be used to load the boot script, the -operating system kernel and the initial file system (initrd). - -These protocols are insecure. The client cannot validate the authenticity -of the contacted servers. And the server cannot verify the identity of the -client. - -Furthermore the services providing the operating system loader or kernel are -not the ones that the operating system typically will use. Especially in a SAN -environment this makes updating the operating system a hassle. After installing -a new kernel version the boot files have to be copied to the TFTP server -directory. - -The HTTPS protocol provides certificate based validation of servers. Sensitive -data like passwords can be securely transmitted. - -The iSCSI protocol is used for connecting storage attached networks. It -provides mutual authentication using the CHAP protocol. It typically runs on -a TCP transport. - -Thus a better solution than DHCP/TFTP/NFS boot would be to load a boot script -via HTTPS and to download any other files needed for booting via iSCSI from the -same target where the operating system is installed. - -An alternative to implementing these protocols in U-Boot is to use an existing -software that can run on top of U-Boot. iPXE[1] is the "swiss army knife" of -network booting. It supports both HTTPS and iSCSI. It has a scripting engine for -fine grained control of the boot process and can provide a command shell. - -iPXE can be built as an EFI application (named snp.efi) which can be loaded and -run by U-Boot. - -Boot sequence -------------- - -U-Boot loads the EFI application iPXE snp.efi using the bootefi command. This -application has network access via the simple network protocol offered by -U-Boot. - -iPXE executes its internal script. This script may optionally chain load a -secondary boot script via HTTPS or open a shell. - -For the further boot process iPXE connects to the iSCSI server. This includes -the mutual authentication using the CHAP protocol. After the authentication iPXE -has access to the iSCSI targets. - -For a selected iSCSI target iPXE sets up a handle with the block IO protocol. It -uses the ConnectController boot service of U-Boot to request U-Boot to connect a -file system driver. U-Boot reads from the iSCSI drive via the block IO protocol -offered by iPXE. It creates the partition handles and installs the simple file -protocol. Now iPXE can call the simple file protocol to load GRUB[2]. U-Boot -uses the block IO protocol offered by iPXE to fulfill the request. - -Once GRUB is started it uses the same block IO protocol to load Linux. Via -the EFI stub Linux is called as an EFI application:: - - +--------+ +--------+ - | | Runs | | - | U-Boot |========>| iPXE | - | EFI | | snp.efi| - +--------+ | | DHCP | | - | |<===|********|<========| | - | DHCP | | | Get IP | | - | Server | | | Address | | - | |===>|********|========>| | - +--------+ | | Response| | - | | | | - | | | | - +--------+ | | HTTPS | | - | |<===|********|<========| | - | HTTPS | | | Load | | - | Server | | | Script | | - | |===>|********|========>| | - +--------+ | | | | - | | | | - | | | | - +--------+ | | iSCSI | | - | |<===|********|<========| | - | iSCSI | | | Auth | | - | Server |===>|********|========>| | - | | | | | | - | | | | Loads | | - | |<===|********|<========| | +--------+ - | | | | GRUB | | Runs | | - | |===>|********|========>| |======>| GRUB | - | | | | | | | | - | | | | | | | | - | | | | | | Loads | | - | |<===|********|<========|********|<======| | +--------+ - | | | | | | Linux | | Runs | | - | |===>|********|========>|********|======>| |=====>| Linux | - | | | | | | | | | | - +--------+ +--------+ +--------+ +--------+ | | - | | - | | - | ~ ~ ~ ~| - -Security --------- - -The iSCSI protocol is not encrypted. The traffic could be secured using IPsec -but neither U-Boot nor iPXE does support this. So we should at least separate -the iSCSI traffic from all other network traffic. This can be achieved using a -virtual local area network (VLAN). - -Configuration -------------- - -iPXE -~~~~ - -For running iPXE on arm64 the bin-arm64-efi/snp.efi build target is needed:: - - git clone http://git.ipxe.org/ipxe.git - cd ipxe/src - make bin-arm64-efi/snp.efi -j6 EMBED=myscript.ipxe - -The available commands for the boot script are documented at: - -http://ipxe.org/cmd - -Credentials are managed as environment variables. These are described here: - -http://ipxe.org/cfg - -iPXE by default will put the CPU to rest when waiting for input. U-Boot does -not wake it up due to missing interrupt support. To avoid this behavior create -file src/config/local/nap.h: - -.. code-block:: c - - /* nap.h */ - #undef NAP_EFIX86 - #undef NAP_EFIARM - #define NAP_NULL - -The supported commands in iPXE are controlled by an include, too. Putting the -following into src/config/local/general.h is sufficient for most use cases: - -.. code-block:: c - - /* general.h */ - #define NSLOOKUP_CMD /* Name resolution command */ - #define PING_CMD /* Ping command */ - #define NTP_CMD /* NTP commands */ - #define VLAN_CMD /* VLAN commands */ - #define IMAGE_EFI /* EFI image support */ - #define DOWNLOAD_PROTO_HTTPS /* Secure Hypertext Transfer Protocol */ - #define DOWNLOAD_PROTO_FTP /* File Transfer Protocol */ - #define DOWNLOAD_PROTO_NFS /* Network File System Protocol */ - #define DOWNLOAD_PROTO_FILE /* Local file system access */ - -Open-iSCSI -~~~~~~~~~~ - -When the root file system is on an iSCSI drive you should disable pings and set -the replacement timer to a high value in the configuration file [3]:: - - node.conn[0].timeo.noop_out_interval = 0 - node.conn[0].timeo.noop_out_timeout = 0 - node.session.timeo.replacement_timeout = 86400 - -Links ------ - -* [1] https://ipxe.org - iPXE open source boot firmware -* [2] https://www.gnu.org/software/grub/ - - GNU GRUB (Grand Unified Bootloader) -* [3] https://github.com/open-iscsi/open-iscsi/blob/master/README - - Open-iSCSI README diff --git a/doc/uefi/u-boot_on_efi.rst b/doc/uefi/u-boot_on_efi.rst deleted file mode 100644 index c9a41bc919f..00000000000 --- a/doc/uefi/u-boot_on_efi.rst +++ /dev/null @@ -1,235 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0+ -.. Copyright (C) 2015 Google, Inc - -U-Boot on EFI -============= -This document provides information about U-Boot running on top of EFI, either -as an application or just as a means of getting U-Boot onto a new platform. - - -Motivation ----------- -Running U-Boot on EFI is useful in several situations: - -- You have EFI running on a board but U-Boot does not natively support it - fully yet. You can boot into U-Boot from EFI and use that until U-Boot is - fully ported - -- You need to use an EFI implementation (e.g. UEFI) because your vendor - requires it in order to provide support - -- You plan to use coreboot to boot into U-Boot but coreboot support does - not currently exist for your platform. In the meantime you can use U-Boot - on EFI and then move to U-Boot on coreboot when ready - -- You use EFI but want to experiment with a simpler alternative like U-Boot - - -Status ------- -Only x86 is supported at present. If you are using EFI on another architecture -you may want to reconsider. However, much of the code is generic so could be -ported. - -U-Boot supports running as an EFI application for 32-bit EFI only. This is -not very useful since only a serial port is provided. You can look around at -memory and type 'help' but that is about it. - -More usefully, U-Boot supports building itself as a payload for either 32-bit -or 64-bit EFI. U-Boot is packaged up and loaded in its entirety by EFI. Once -started, U-Boot changes to 32-bit mode (currently) and takes over the -machine. You can use devices, boot a kernel, etc. - - -Build Instructions ------------------- -First choose a board that has EFI support and obtain an EFI implementation -for that board. It will be either 32-bit or 64-bit. Alternatively, you can -opt for using QEMU [1] and the OVMF [2], as detailed below. - -To build U-Boot as an EFI application (32-bit EFI required), enable CONFIG_EFI -and CONFIG_EFI_APP. The efi-x86_app config (efi-x86_app_defconfig) is set up -for this. Just build U-Boot as normal, e.g.:: - - make efi-x86_app_defconfig - make - -To build U-Boot as an EFI payload (32-bit or 64-bit EFI can be used), enable -CONFIG_EFI, CONFIG_EFI_STUB, and select either CONFIG_EFI_STUB_32BIT or -CONFIG_EFI_STUB_64BIT. The efi-x86_payload configs (efi-x86_payload32_defconfig -and efi-x86_payload32_defconfig) are set up for this. Then build U-Boot as -normal, e.g.:: - - make efi-x86_payload32_defconfig (or efi-x86_payload64_defconfig) - make - -You will end up with one of these files depending on what you build for: - -* u-boot-app.efi - U-Boot EFI application -* u-boot-payload.efi - U-Boot EFI payload application - - -Trying it out -------------- -QEMU is an emulator and it can emulate an x86 machine. Please make sure your -QEMU version is 2.3.0 or above to test this. You can run the payload with -something like this:: - - mkdir /tmp/efi - cp /path/to/u-boot*.efi /tmp/efi - qemu-system-x86_64 -bios bios.bin -hda fat:/tmp/efi/ - -Add -nographic if you want to use the terminal for output. Once it starts -type 'fs0:u-boot-payload.efi' to run the payload or 'fs0:u-boot-app.efi' to -run the application. 'bios.bin' is the EFI 'BIOS'. Check [2] to obtain a -prebuilt EFI BIOS for QEMU or you can build one from source as well. - -To try it on real hardware, put u-boot-app.efi on a suitable boot medium, -such as a USB stick. Then you can type something like this to start it:: - - fs0:u-boot-payload.efi - -(or fs0:u-boot-app.efi for the application) - -This will start the payload, copy U-Boot into RAM and start U-Boot. Note -that EFI does not support booting a 64-bit application from a 32-bit -EFI (or vice versa). Also it will often fail to print an error message if -you get this wrong. - - -Inner workings --------------- -Here follow a few implementation notes for those who want to fiddle with -this and perhaps contribute patches. - -The application and payload approaches sound similar but are in fact -implemented completely differently. - -EFI Application -~~~~~~~~~~~~~~~ -For the application the whole of U-Boot is built as a shared library. The -efi_main() function is in lib/efi/efi_app.c. It sets up some basic EFI -functions with efi_init(), sets up U-Boot global_data, allocates memory for -U-Boot's malloc(), etc. and enters the normal init sequence (board_init_f() -and board_init_r()). - -Since U-Boot limits its memory access to the allocated regions very little -special code is needed. The CONFIG_EFI_APP option controls a few things -that need to change so 'git grep CONFIG_EFI_APP' may be instructive. -The CONFIG_EFI option controls more general EFI adjustments. - -The only available driver is the serial driver. This calls back into EFI -'boot services' to send and receive characters. Although it is implemented -as a serial driver the console device is not necessarilly serial. If you -boot EFI with video output then the 'serial' device will operate on your -target devices's display instead and the device's USB keyboard will also -work if connected. If you have both serial and video output, then both -consoles will be active. Even though U-Boot does the same thing normally, -These are features of EFI, not U-Boot. - -Very little code is involved in implementing the EFI application feature. -U-Boot is highly portable. Most of the difficulty is in modifying the -Makefile settings to pass the right build flags. In particular there is very -little x86-specific code involved - you can find most of it in -arch/x86/cpu. Porting to ARM (which can also use EFI if you are brave -enough) should be straightforward. - -Use the 'reset' command to get back to EFI. - -EFI Payload -~~~~~~~~~~~ -The payload approach is a different kettle of fish. It works by building -U-Boot exactly as normal for your target board, then adding the entire -image (including device tree) into a small EFI stub application responsible -for booting it. The stub application is built as a normal EFI application -except that it has a lot of data attached to it. - -The stub application is implemented in lib/efi/efi_stub.c. The efi_main() -function is called by EFI. It is responsible for copying U-Boot from its -original location into memory, disabling EFI boot services and starting -U-Boot. U-Boot then starts as normal, relocates, starts all drivers, etc. - -The stub application is architecture-dependent. At present it has some -x86-specific code and a comment at the top of efi_stub.c describes this. - -While the stub application does allocate some memory from EFI this is not -used by U-Boot (the payload). In fact when U-Boot starts it has all of the -memory available to it and can operate as it pleases (but see the next -section). - -Tables -~~~~~~ -The payload can pass information to U-Boot in the form of EFI tables. At -present this feature is used to pass the EFI memory map, an inordinately -large list of memory regions. You can use the 'efi mem all' command to -display this list. U-Boot uses the list to work out where to relocate -itself. - -Although U-Boot can use any memory it likes, EFI marks some memory as used -by 'run-time services', code that hangs around while U-Boot is running and -is even present when Linux is running. This is common on x86 and provides -a way for Linux to call back into the firmware to control things like CPU -fan speed. U-Boot uses only 'conventional' memory, in EFI terminology. It -will relocate itself to the top of the largest block of memory it can find -below 4GB. - -Interrupts -~~~~~~~~~~ -U-Boot drivers typically don't use interrupts. Since EFI enables interrupts -it is possible that an interrupt will fire that U-Boot cannot handle. This -seems to cause problems. For this reason the U-Boot payload runs with -interrupts disabled at present. - -32/64-bit -~~~~~~~~~ -While the EFI application can in principle be built as either 32- or 64-bit, -only 32-bit is currently supported. This means that the application can only -be used with 32-bit EFI. - -The payload stub can be build as either 32- or 64-bits. Only a small amount -of code is built this way (see the extra- line in lib/efi/Makefile). -Everything else is built as a normal U-Boot, so is always 32-bit on x86 at -present. - -Future work ------------ -This work could be extended in a number of ways: - -- Add ARM support - -- Add 64-bit application support - -- Figure out how to solve the interrupt problem - -- Add more drivers to the application side (e.g. video, block devices, USB, - environment access). This would mostly be an academic exercise as a strong - use case is not readily apparent, but it might be fun. - -- Avoid turning off boot services in the stub. Instead allow U-Boot to make - use of boot services in case it wants to. It is unclear what it might want - though. - -Where is the code? ------------------- -lib/efi - payload stub, application, support code. Mostly arch-neutral - -arch/x86/cpu/efi - x86 support code for running as an EFI application and payload - -board/efi/efi-x86_app/efi.c - x86 board code for running as an EFI application - -board/efi/efi-x86_payload - generic x86 EFI payload board support code - -common/cmd_efi.c - the 'efi' command - --- -Ben Stoltz, Simon Glass -Google, Inc -July 2015 - -* [1] http://www.qemu.org -* [2] http://www.tianocore.org/ovmf/ diff --git a/doc/uefi/uefi.rst b/doc/uefi/uefi.rst deleted file mode 100644 index 5a67737c157..00000000000 --- a/doc/uefi/uefi.rst +++ /dev/null @@ -1,498 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0+ -.. Copyright (c) 2018 Heinrich Schuchardt - -UEFI on U-Boot -============== - -The Unified Extensible Firmware Interface Specification (UEFI) [1] has become -the default for booting on AArch64 and x86 systems. It provides a stable API for -the interaction of drivers and applications with the firmware. The API comprises -access to block storage, network, and console to name a few. The Linux kernel -and boot loaders like GRUB or the FreeBSD loader can be executed. - -Development target ------------------- - -The implementation of UEFI in U-Boot strives to reach the requirements described -in the "Embedded Base Boot Requirements (EBBR) Specification - Release v1.0" -[2]. The "Server Base Boot Requirements System Software on ARM Platforms" [3] -describes a superset of the EBBR specification and may be used as further -reference. - -A full blown UEFI implementation would contradict the U-Boot design principle -"keep it small". - -Building U-Boot for UEFI ------------------------- - -The UEFI standard supports only little-endian systems. The UEFI support can be -activated for ARM and x86 by specifying:: - - CONFIG_CMD_BOOTEFI=y - CONFIG_EFI_LOADER=y - -in the .config file. - -Support for attaching virtual block devices, e.g. iSCSI drives connected by the -loaded UEFI application [4], 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} - -When booting from a memory location it is unknown from which file it was loaded. -Therefore the bootefi command uses the device path of the block device partition -or the network adapter and the file name of the most recently loaded PE-COFF -file when setting up the loaded image protocol. - -Launching a UEFI binary from a FIT image -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A signed FIT image can be used to securely boot a UEFI image via the -bootm command. This feature is available if U-Boot is configured with:: - - CONFIG_BOOTM_EFI=y - -A sample configuration is provided as file doc/uImage.FIT/uefi.its. - -Below you find the output of an example session starting GRUB:: - - => load mmc 0:1 ${kernel_addr_r} image.fit - 4620426 bytes read in 83 ms (53.1 MiB/s) - => bootm ${kernel_addr_r}#config-grub-nofdt - ## Loading kernel from FIT Image at 40400000 ... - Using 'config-grub-nofdt' configuration - Verifying Hash Integrity ... sha256,rsa2048:dev+ OK - Trying 'efi-grub' kernel subimage - Description: GRUB EFI Firmware - Created: 2019-11-20 8:18:16 UTC - Type: Kernel Image (no loading done) - Compression: uncompressed - Data Start: 0x404000d0 - Data Size: 450560 Bytes = 440 KiB - Hash algo: sha256 - Hash value: 4dbee00021112df618f58b3f7cf5e1595533d543094064b9ce991e8b054a9eec - Verifying Hash Integrity ... sha256+ OK - XIP Kernel Image (no loading done) - ## Transferring control to EFI (at address 404000d0) ... - Welcome to GRUB! - -See doc/uImage.FIT/howto.txt for an introduction to FIT images. - -Configuring UEFI secure boot -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The UEFI specification[1] defines a secure way of executing UEFI images -by verifying a signature (or message digest) of image with certificates. -This feature on U-Boot is enabled with:: - - CONFIG_UEFI_SECURE_BOOT=y - -To make the boot sequence safe, you need to establish a chain of trust; -In UEFI secure boot the chain trust is defined by the following UEFI variables - -* PK - Platform Key -* KEK - Key Exchange Keys -* db - white list database -* dbx - black list database - -An in depth description of UEFI secure boot is beyond the scope of this -document. Please, refer to the UEFI specification and available online -documentation. Here is a simple example that you can follow for your initial -attempt (Please note that the actual steps will depend on your system and -environment.): - -Install the required tools on your host - -* openssl -* efitools -* sbsigntool - -Create signing keys and the key database on your host: - -The platform key - -.. code-block:: bash - - openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_PK/ \ - -keyout PK.key -out PK.crt -nodes -days 365 - cert-to-efi-sig-list -g 11111111-2222-3333-4444-123456789abc \ - PK.crt PK.esl; - sign-efi-sig-list -c PK.crt -k PK.key PK PK.esl PK.auth - -The key exchange keys - -.. code-block:: bash - - openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_KEK/ \ - -keyout KEK.key -out KEK.crt -nodes -days 365 - cert-to-efi-sig-list -g 11111111-2222-3333-4444-123456789abc \ - KEK.crt KEK.esl - sign-efi-sig-list -c PK.crt -k PK.key KEK KEK.esl KEK.auth - -The whitelist database - -.. code-block:: bash - - openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_db/ \ - -keyout db.key -out db.crt -nodes -days 365 - cert-to-efi-sig-list -g 11111111-2222-3333-4444-123456789abc \ - db.crt db.esl - sign-efi-sig-list -c KEK.crt -k KEK.key db db.esl db.auth - -Copy the \*.auth files to media, say mmc, that is accessible from U-Boot. - -Sign an image with one of the keys in "db" on your host - -.. code-block:: bash - - sbsign --key db.key --cert db.crt helloworld.efi - -Now in U-Boot install the keys on your board:: - - fatload mmc 0:1 <tmpaddr> PK.auth - setenv -e -nv -bs -rt -at -i <tmpaddr>:$filesize PK - fatload mmc 0:1 <tmpaddr> KEK.auth - setenv -e -nv -bs -rt -at -i <tmpaddr>:$filesize KEK - fatload mmc 0:1 <tmpaddr> db.auth - setenv -e -nv -bs -rt -at -i <tmpaddr>:$filesize db - -Set up boot parameters on your board:: - - efidebug boot add 1 HELLO mmc 0:1 /helloworld.efi.signed "" - -Now your board can run the signed image via the boot manager (see below). -You can also try this sequence by running Pytest, test_efi_secboot, -on the sandbox - -.. code-block:: bash - - cd <U-Boot source directory> - pytest.py test/py/tests/test_efi_secboot/test_signed.py --bd sandbox - -UEFI binaries may be signed by Microsoft using the following certificates: - -* KEK: Microsoft Corporation KEK CA 2011 - http://go.microsoft.com/fwlink/?LinkId=321185. -* db: Microsoft Windows Production PCA 2011 - http://go.microsoft.com/fwlink/p/?linkid=321192. -* db: Microsoft Corporation UEFI CA 2011 - http://go.microsoft.com/fwlink/p/?linkid=321194. - -Using OP-TEE for EFI variables -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Instead of implementing UEFI variable services inside U-Boot they can -also be provided in the secure world by a module for OP-TEE[1]. The -interface between U-Boot and OP-TEE for variable services is enabled by -CONFIG_EFI_MM_COMM_TEE=y. - -Tianocore EDK II's standalone management mode driver for variables can -be linked to OP-TEE for this purpose. This module uses the Replay -Protected Memory Block (RPMB) of an eMMC device for persisting -non-volatile variables. When calling the variable services via the -OP-TEE API U-Boot's OP-TEE supplicant relays calls to the RPMB driver -which has to be enabled via CONFIG_SUPPORT_EMMC_RPMB=y. - -[1] https://optee.readthedocs.io/ - OP-TEE documentation - -Executing the boot manager -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The UEFI specification foresees to define boot entries and boot sequence via -UEFI variables. Booting according to these variables is possible via:: - - bootefi bootmgr [fdt address] - -As of U-Boot v2020.10 UEFI variables cannot be set at runtime. The U-Boot -command 'efidebug' can be used to set the variables. - -Executing the built in hello world application -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A hello world UEFI application can be built with:: - - CONFIG_CMD_BOOTEFI_HELLO_COMPILE=y - -It can be embedded into the U-Boot binary with:: - - CONFIG_CMD_BOOTEFI_HELLO=y - -The bootefi command is used to start the embedded hello world application:: - - bootefi hello [fdt address] - -Below you find the output of an example session:: - - => bootefi hello ${fdtcontroladdr} - ## Starting EFI application at 01000000 ... - WARNING: using memory device/image path, this may confuse some payloads! - Hello, world! - Running on UEFI 2.7 - Have SMBIOS table - Have device tree - Load options: root=/dev/sdb3 init=/sbin/init rootwait ro - ## Application terminated, r = 0 - -The environment variable fdtcontroladdr points to U-Boot's internal device tree -(if available). - -Executing the built-in self-test -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -An UEFI self-test suite can be embedded in U-Boot by building with:: - - CONFIG_CMD_BOOTEFI_SELFTEST=y - -For testing the UEFI implementation the bootefi command can be used to start the -self-test:: - - bootefi selftest [fdt address] - -The environment variable 'efi_selftest' can be used to select a single test. If -it is not provided all tests are executed except those marked as 'on request'. -If the environment variable is set to 'list' a list of all tests is shown. - -Below you can find the output of an example session:: - - => setenv efi_selftest simple network protocol - => bootefi selftest - Testing EFI API implementation - Selected test: 'simple network protocol' - Setting up 'simple network protocol' - Setting up 'simple network protocol' succeeded - Executing 'simple network protocol' - DHCP Discover - DHCP reply received from 192.168.76.2 (52:55:c0:a8:4c:02) - as broadcast message. - Executing 'simple network protocol' succeeded - Tearing down 'simple network protocol' - Tearing down 'simple network protocol' succeeded - Boot services terminated - Summary: 0 failures - Preparing for reset. Press any key. - -The UEFI life cycle -------------------- - -After the U-Boot platform has been initialized the UEFI API provides two kinds -of services: - -* boot services -* runtime services - -The API can be extended by loading UEFI drivers which come in two variants: - -* boot drivers -* 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 [5]. 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 [4]. - -This driver is only available if U-Boot is configured with:: - - CONFIG_BLK=y - CONFIG_PARTITIONS=y - -Miscellaneous -------------- - -Load file 2 protocol -~~~~~~~~~~~~~~~~~~~~ - -The load file 2 protocol can be used by the Linux kernel to load the initial -RAM disk. U-Boot can be configured to provide an implementation with:: - - EFI_LOAD_FILE2_INITRD=y - EFI_INITRD_FILESPEC=interface dev:part path_to_initrd - -Links ------ - -* [1] http://uefi.org/specifications - UEFI specifications -* [2] https://github.com/ARM-software/ebbr/releases/download/v1.0/ebbr-v1.0.pdf - - Embedded Base Boot Requirements (EBBR) Specification - Release v1.0 -* [3] https://developer.arm.com/docs/den0044/latest/server-base-boot-requirements-system-software-on-arm-platforms-version-11 - - Server Base Boot Requirements System Software on ARM Platforms - Version 1.1 -* [4] :doc:`iscsi` -* [5] :doc:`../driver-model/index` |
