1.. SPDX-License-Identifier: GPL-2.0+ 2.. Copyright (c) 2018 Heinrich Schuchardt 3 4UEFI on U-Boot 5============== 6 7The Unified Extensible Firmware Interface Specification (UEFI) [1] has become 8the default for booting on AArch64 and x86 systems. It provides a stable API for 9the interaction of drivers and applications with the firmware. The API comprises 10access to block storage, network, and console to name a few. The Linux kernel 11and boot loaders like GRUB or the FreeBSD loader can be executed. 12 13Development target 14------------------ 15 16The implementation of UEFI in U-Boot strives to reach the requirements described 17in the "Embedded Base Boot Requirements (EBBR) Specification - Release v2.1.0" 18[2]. The "Server Base Boot Requirements System Software on ARM Platforms" [3] 19describes a superset of the EBBR specification and may be used as further 20reference. 21 22A full blown UEFI implementation would contradict the U-Boot design principle 23"keep it small". 24 25Building U-Boot for UEFI 26------------------------ 27 28The UEFI standard supports only little-endian systems. The UEFI support can be 29activated for ARM and x86 by specifying:: 30 31 CONFIG_CMD_BOOTEFI=y 32 CONFIG_EFI_LOADER=y 33 34in the .config file. 35 36Support for attaching virtual block devices, e.g. iSCSI drives connected by the 37loaded UEFI application [4], requires:: 38 39 CONFIG_BLK=y 40 CONFIG_PARTITIONS=y 41 42Executing a UEFI binary 43~~~~~~~~~~~~~~~~~~~~~~~ 44 45The bootefi command is used to start UEFI applications or to install UEFI 46drivers. It takes two parameters:: 47 48 bootefi <image address> [fdt address] 49 50* image address - the memory address of the UEFI binary 51* fdt address - the memory address of the flattened device tree 52 53Below you find the output of an example session starting GRUB:: 54 55 => load mmc 0:2 ${fdt_addr_r} boot/dtb 56 29830 bytes read in 14 ms (2 MiB/s) 57 => load mmc 0:1 ${kernel_addr_r} efi/debian/grubaa64.efi 58 reading efi/debian/grubaa64.efi 59 120832 bytes read in 7 ms (16.5 MiB/s) 60 => bootefi ${kernel_addr_r} ${fdt_addr_r} 61 62When booting from a memory location it is unknown from which file it was loaded. 63Therefore the bootefi command uses the device path of the block device partition 64or the network adapter and the file name of the most recently loaded PE-COFF 65file when setting up the loaded image protocol. 66 67Launching a UEFI binary from a FIT image 68~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 69 70A signed FIT image can be used to securely boot a UEFI image via the 71bootm command. This feature is available if U-Boot is configured with:: 72 73 CONFIG_BOOTM_EFI=y 74 75A sample configuration is provided as file doc/uImage.FIT/uefi.its. 76 77Below you find the output of an example session starting GRUB:: 78 79 => load mmc 0:1 ${kernel_addr_r} image.fit 80 4620426 bytes read in 83 ms (53.1 MiB/s) 81 => bootm ${kernel_addr_r}#config-grub-nofdt 82 ## Loading kernel from FIT Image at 40400000 ... 83 Using 'config-grub-nofdt' configuration 84 Verifying Hash Integrity ... sha256,rsa2048:dev+ OK 85 Trying 'efi-grub' kernel subimage 86 Description: GRUB EFI Firmware 87 Created: 2019-11-20 8:18:16 UTC 88 Type: Kernel Image (no loading done) 89 Compression: uncompressed 90 Data Start: 0x404000d0 91 Data Size: 450560 Bytes = 440 KiB 92 Hash algo: sha256 93 Hash value: 4dbee00021112df618f58b3f7cf5e1595533d543094064b9ce991e8b054a9eec 94 Verifying Hash Integrity ... sha256+ OK 95 XIP Kernel Image (no loading done) 96 ## Transferring control to EFI (at address 404000d0) ... 97 Welcome to GRUB! 98 99See doc/uImage.FIT/howto.txt for an introduction to FIT images. 100 101Configuring UEFI secure boot 102~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 103 104The UEFI specification[1] defines a secure way of executing UEFI images 105by verifying a signature (or message digest) of image with certificates. 106This feature on U-Boot is enabled with:: 107 108 CONFIG_EFI_SECURE_BOOT=y 109 110To make the boot sequence safe, you need to establish a chain of trust; 111In UEFI secure boot the chain trust is defined by the following UEFI variables 112 113* PK - Platform Key 114* KEK - Key Exchange Keys 115* db - white list database 116* dbx - black list database 117 118An in depth description of UEFI secure boot is beyond the scope of this 119document. Please, refer to the UEFI specification and available online 120documentation. Here is a simple example that you can follow for your initial 121attempt (Please note that the actual steps will depend on your system and 122environment.): 123 124Install the required tools on your host 125 126* openssl 127* efitools 128* sbsigntool 129 130Create signing keys and the key database on your host: 131 132The platform key 133 134.. code-block:: bash 135 136 openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_PK/ \ 137 -keyout PK.key -out PK.crt -nodes -days 365 138 cert-to-efi-sig-list -g 11111111-2222-3333-4444-123456789abc \ 139 PK.crt PK.esl; 140 sign-efi-sig-list -c PK.crt -k PK.key PK PK.esl PK.auth 141 142The key exchange keys 143 144.. code-block:: bash 145 146 openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_KEK/ \ 147 -keyout KEK.key -out KEK.crt -nodes -days 365 148 cert-to-efi-sig-list -g 11111111-2222-3333-4444-123456789abc \ 149 KEK.crt KEK.esl 150 sign-efi-sig-list -c PK.crt -k PK.key KEK KEK.esl KEK.auth 151 152The whitelist database 153 154.. code-block:: bash 155 156 openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_db/ \ 157 -keyout db.key -out db.crt -nodes -days 365 158 cert-to-efi-sig-list -g 11111111-2222-3333-4444-123456789abc \ 159 db.crt db.esl 160 sign-efi-sig-list -c KEK.crt -k KEK.key db db.esl db.auth 161 162Copy the \*.auth files to media, say mmc, that is accessible from U-Boot. 163 164Sign an image with one of the keys in "db" on your host 165 166.. code-block:: bash 167 168 sbsign --key db.key --cert db.crt helloworld.efi 169 170Now in U-Boot install the keys on your board:: 171 172 fatload mmc 0:1 <tmpaddr> PK.auth 173 setenv -e -nv -bs -rt -at -i <tmpaddr>:$filesize PK 174 fatload mmc 0:1 <tmpaddr> KEK.auth 175 setenv -e -nv -bs -rt -at -i <tmpaddr>:$filesize KEK 176 fatload mmc 0:1 <tmpaddr> db.auth 177 setenv -e -nv -bs -rt -at -i <tmpaddr>:$filesize db 178 179Set up boot parameters on your board:: 180 181 efidebug boot add -b 1 HELLO mmc 0:1 /helloworld.efi.signed "" 182 183Since kernel 5.7 there's an alternative way of loading an initrd using 184LoadFile2 protocol if CONFIG_EFI_LOAD_FILE2_INITRD is enabled. 185The initrd path can be specified with:: 186 187 efidebug boot add -b ABE0 'kernel' mmc 0:1 Image -i mmc 0:1 initrd 188 189Now your board can run the signed image via the boot manager (see below). 190You can also try this sequence by running Pytest, test_efi_secboot, 191on the sandbox 192 193.. code-block:: bash 194 195 cd <U-Boot source directory> 196 pytest.py test/py/tests/test_efi_secboot/test_signed.py --bd sandbox 197 198UEFI binaries may be signed by Microsoft using the following certificates: 199 200* KEK: Microsoft Corporation KEK CA 2011 201 http://go.microsoft.com/fwlink/?LinkId=321185. 202* db: Microsoft Windows Production PCA 2011 203 http://go.microsoft.com/fwlink/p/?linkid=321192. 204* db: Microsoft Corporation UEFI CA 2011 205 http://go.microsoft.com/fwlink/p/?linkid=321194. 206 207Using OP-TEE for EFI variables 208~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 209 210Instead of implementing UEFI variable services inside U-Boot they can 211also be provided in the secure world by a module for OP-TEE[1]. The 212interface between U-Boot and OP-TEE for variable services is enabled by 213CONFIG_EFI_MM_COMM_TEE=y. 214 215Tianocore EDK II's standalone management mode driver for variables can 216be linked to OP-TEE for this purpose. This module uses the Replay 217Protected Memory Block (RPMB) of an eMMC device for persisting 218non-volatile variables. When calling the variable services via the 219OP-TEE API U-Boot's OP-TEE supplicant relays calls to the RPMB driver 220which has to be enabled via CONFIG_SUPPORT_EMMC_RPMB=y. 221 222EDK2 Build instructions 223*********************** 224 225.. code-block:: bash 226 227 $ git clone https://github.com/tianocore/edk2.git 228 $ git clone https://github.com/tianocore/edk2-platforms.git 229 $ cd edk2 230 $ git submodule init && git submodule update --init --recursive 231 $ cd .. 232 $ export WORKSPACE=$(pwd) 233 $ export PACKAGES_PATH=$WORKSPACE/edk2:$WORKSPACE/edk2-platforms 234 $ export ACTIVE_PLATFORM="Platform/StandaloneMm/PlatformStandaloneMmPkg/PlatformStandaloneMmRpmb.dsc" 235 $ export GCC5_AARCH64_PREFIX=aarch64-linux-gnu- 236 $ source edk2/edksetup.sh 237 $ make -C edk2/BaseTools 238 $ build -p $ACTIVE_PLATFORM -b RELEASE -a AARCH64 -t GCC5 -n `nproc` 239 240OP-TEE Build instructions 241************************* 242 243.. code-block:: bash 244 245 $ git clone https://github.com/OP-TEE/optee_os.git 246 $ cd optee_os 247 $ ln -s ../Build/MmStandaloneRpmb/RELEASE_GCC5/FV/BL32_AP_MM.fd 248 $ export ARCH=arm 249 $ CROSS_COMPILE32=arm-linux-gnueabihf- make -j32 CFG_ARM64_core=y \ 250 PLATFORM=<myboard> CFG_STMM_PATH=BL32_AP_MM.fd CFG_RPMB_FS=y \ 251 CFG_RPMB_FS_DEV_ID=0 CFG_CORE_HEAP_SIZE=524288 CFG_RPMB_WRITE_KEY=y \ 252 CFG_CORE_DYN_SHM=y CFG_RPMB_TESTKEY=y CFG_REE_FS=n \ 253 CFG_CORE_ARM64_PA_BITS=48 CFG_TEE_CORE_LOG_LEVEL=1 \ 254 CFG_TEE_TA_LOG_LEVEL=1 CFG_SCTLR_ALIGNMENT_CHECK=n 255 256U-Boot Build instructions 257************************* 258 259Although the StandAloneMM binary comes from EDK2, using and storing the 260variables is currently available in U-Boot only. 261 262.. code-block:: bash 263 264 $ git clone https://github.com/u-boot/u-boot.git 265 $ cd u-boot 266 $ export CROSS_COMPILE=aarch64-linux-gnu- 267 $ export ARCH=<arch> 268 $ make <myboard>_defconfig 269 $ make menuconfig 270 271Enable ``CONFIG_OPTEE``, ``CONFIG_CMD_OPTEE_RPMB`` and ``CONFIG_EFI_MM_COMM_TEE`` 272 273.. warning:: 274 275 - Your OP-TEE platform port must support Dynamic shared memory, since that's 276 the only kind of memory U-Boot supports for now. 277 278[1] https://optee.readthedocs.io/en/latest/building/efi_vars/stmm.html 279 280.. _uefi_capsule_update_ref: 281 282Enabling UEFI Capsule Update feature 283~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 284 285Support has been added for the UEFI capsule update feature which 286enables updating the U-Boot image using the UEFI firmware management 287protocol (FMP). The capsules are not passed to the firmware through 288the UpdateCapsule runtime service. Instead, capsule-on-disk 289functionality is used for fetching capsules from the EFI System 290Partition (ESP) by placing capsule files under the directory:: 291 292 \EFI\UpdateCapsule 293 294The directory is checked for capsules only within the 295EFI system partition on the device specified in the active boot option, 296which is determined by BootXXXX variable in BootNext, or if not, the highest 297priority one within BootOrder. Any BootXXXX variables referring to devices 298not present are ignored when determining the active boot option. 299 300Please note that capsules will be applied in the alphabetic order of 301capsule file names. 302 303Creating a capsule file 304*********************** 305 306A capsule file can be created by using tools/mkeficapsule. 307To build this tool, enable:: 308 309 CONFIG_TOOLS_MKEFICAPSULE=y 310 CONFIG_TOOLS_LIBCRYPTO=y 311 312Run the following command 313 314.. code-block:: console 315 316 $ mkeficapsule \ 317 --index <index> --instance 0 \ 318 --guid <image GUID> \ 319 <capsule_file_name> 320 321Performing the update 322********************* 323 324Put capsule files under the directory mentioned above. 325Then, following the UEFI specification, you'll need to set 326the EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED 327bit in OsIndications variable with 328 329.. code-block:: console 330 331 => setenv -e -nv -bs -rt -v OsIndications =0x0000000000000004 332 333Since U-boot doesn't currently support SetVariable at runtime, its value 334won't be taken over across the reboot. If this is the case, you can skip 335this feature check with the Kconfig option (CONFIG_EFI_IGNORE_OSINDICATIONS) 336set. 337 338A few values need to be defined in the board file for performing the 339capsule update. These values are defined in the board file by 340initialisation of a structure which provides information needed for 341capsule updates. The following structures have been defined for 342containing the image related information 343 344.. code-block:: c 345 346 struct efi_fw_image { 347 efi_guid_t image_type_id; 348 u16 *fw_name; 349 u8 image_index; 350 }; 351 352 struct efi_capsule_update_info { 353 const char *dfu_string; 354 struct efi_fw_image *images; 355 }; 356 357 358A string is defined which is to be used for populating the 359dfu_alt_info variable. This string is used by the function 360set_dfu_alt_info. Instead of taking the variable from the environment, 361the capsule update feature requires that the variable be set through 362the function, since that is more robust. Allowing the user to change 363the location of the firmware updates is not a very secure 364practice. Getting this information from the firmware itself is more 365secure, assuming the firmware has been verified by a previous stage 366boot loader. 367 368The firmware images structure defines the GUID values, image index 369values and the name of the images that are to be updated through 370the capsule update feature. These values are to be defined as part of 371an array. These GUID values would be used by the Firmware Management 372Protocol(FMP) to populate the image descriptor array and also 373displayed as part of the ESRT table. The image index values defined in 374the array should be one greater than the dfu alt number that 375corresponds to the firmware image. So, if the dfu alt number for an 376image is 2, the value of image index in the fw_images array for that 377image should be 3. The dfu alt number can be obtained by running the 378following command:: 379 380 dfu list 381 382When the FWU Multi Bank Update feature is enabled on the platform, the 383image index is used only to identify the image index with the image 384GUID. The image index would not correspond to the dfu alt number. This 385is because the FWU feature supports multiple partitions(banks) of 386updatable images, and the actual dfu alt number to which the image is 387to be written to is determined at runtime, based on the value of the 388update bank to which the image is to be written. For more information 389on the FWU Multi Bank Update feature, please refer to 390:doc:`/develop/uefi/fwu_updates`. 391 392When using the FMP for FIT images, the image index value needs to be 393set to 1. 394 395Finally, the capsule update can be initiated by rebooting the board. 396 397An example of setting the values in the struct efi_fw_image and 398struct efi_capsule_update_info is shown below 399 400.. code-block:: c 401 402 struct efi_fw_image fw_images[] = { 403 { 404 .image_type_id = DEVELOPERBOX_UBOOT_IMAGE_GUID, 405 .fw_name = u"DEVELOPERBOX-UBOOT", 406 .image_index = 1, 407 }, 408 { 409 .image_type_id = DEVELOPERBOX_FIP_IMAGE_GUID, 410 .fw_name = u"DEVELOPERBOX-FIP", 411 .image_index = 2, 412 }, 413 { 414 .image_type_id = DEVELOPERBOX_OPTEE_IMAGE_GUID, 415 .fw_name = u"DEVELOPERBOX-OPTEE", 416 .image_index = 3, 417 }, 418 }; 419 420 struct efi_capsule_update_info update_info = { 421 .dfu_string = "mtd nor1=u-boot.bin raw 200000 100000;" 422 "fip.bin raw 180000 78000;" 423 "optee.bin raw 500000 100000", 424 .images = fw_images, 425 }; 426 427Platforms must declare a variable update_info of type struct 428efi_capsule_update_info as shown in the example above. The platform 429will also define a fw_images array which contains information of all 430the firmware images that are to be updated through capsule update 431mechanism. The dfu_string is the string that is to be set as 432dfu_alt_info. In the example above, the image index to be set for 433u-boot.bin binary is 0x1, for fip.bin is 0x2 and for optee.bin is 0x3. 434 435As an example, for generating the capsule for the optee.bin image, the 436following command can be issued 437 438.. code-block:: bash 439 440 $ ./tools/mkeficapsule \ 441 --index 0x3 --instance 0 \ 442 --guid c1b629f1-ce0e-4894-82bf-f0a38387e630 \ 443 optee.bin optee.capsule 444 445 446Enabling Capsule Authentication 447******************************* 448 449The UEFI specification defines a way of authenticating the capsule to 450be updated by verifying the capsule signature. The capsule signature 451is computed and prepended to the capsule payload at the time of 452capsule generation. This signature is then verified by using the 453public key stored as part of the X509 certificate. This certificate is 454in the form of an efi signature list (esl) file, which is embedded in 455a device tree. 456 457The capsule authentication feature can be enabled through the 458following config, in addition to the configs listed above for capsule 459update:: 460 461 CONFIG_EFI_CAPSULE_AUTHENTICATE=y 462 463The public and private keys used for the signing process are generated 464and used by the steps highlighted below. 465 4661. Install utility commands on your host 467 * openssl 468 * efitools 469 4702. Create signing keys and certificate files on your host 471 472.. code-block:: console 473 474 $ openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=CRT/ \ 475 -keyout CRT.key -out CRT.crt -nodes -days 365 476 $ cert-to-efi-sig-list CRT.crt CRT.esl 477 4783. Run the following command to create and sign the capsule file 479 480.. code-block:: console 481 482 $ mkeficapsule --monotonic-count 1 \ 483 --private-key CRT.key \ 484 --certificate CRT.crt \ 485 --index 1 --instance 0 \ 486 [--fit | --raw | --guid <guid-string] \ 487 <image_blob> <capsule_file_name> 488 4894. Insert the signature list into a device tree in the following format:: 490 491 { 492 signature { 493 capsule-key = [ <binary of signature list> ]; 494 } 495 ... 496 } 497 498You can do step-4 manually with 499 500.. code-block:: console 501 502 $ dtc -@ -I dts -O dtb -o signature.dtbo signature.dts 503 $ fdtoverlay -i orig.dtb -o new.dtb -v signature.dtbo 504 505where signature.dts looks like:: 506 507 &{/} { 508 signature { 509 capsule-key = /incbin/("CRT.esl"); 510 }; 511 }; 512 513Executing the boot manager 514~~~~~~~~~~~~~~~~~~~~~~~~~~ 515 516The UEFI specification foresees to define boot entries and boot sequence via 517UEFI variables. Booting according to these variables is possible via:: 518 519 bootefi bootmgr [fdt address] 520 521As of U-Boot v2020.10 UEFI variables cannot be set at runtime. The U-Boot 522command 'efidebug' can be used to set the variables. 523 524Executing the built in hello world application 525~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 526 527A hello world UEFI application can be built with:: 528 529 CONFIG_CMD_BOOTEFI_HELLO_COMPILE=y 530 531It can be embedded into the U-Boot binary with:: 532 533 CONFIG_CMD_BOOTEFI_HELLO=y 534 535The bootefi command is used to start the embedded hello world application:: 536 537 bootefi hello [fdt address] 538 539Below you find the output of an example session:: 540 541 => bootefi hello ${fdtcontroladdr} 542 ## Starting EFI application at 01000000 ... 543 WARNING: using memory device/image path, this may confuse some payloads! 544 Hello, world! 545 Running on UEFI 2.7 546 Have SMBIOS table 547 Have device tree 548 Load options: root=/dev/sdb3 init=/sbin/init rootwait ro 549 ## Application terminated, r = 0 550 551The environment variable fdtcontroladdr points to U-Boot's internal device tree 552(if available). 553 554Executing the built-in self-test 555~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 556 557An UEFI self-test suite can be embedded in U-Boot by building with:: 558 559 CONFIG_CMD_BOOTEFI_SELFTEST=y 560 561For testing the UEFI implementation the bootefi command can be used to start the 562self-test:: 563 564 bootefi selftest [fdt address] 565 566The environment variable 'efi_selftest' can be used to select a single test. If 567it is not provided all tests are executed except those marked as 'on request'. 568If the environment variable is set to 'list' a list of all tests is shown. 569 570Below you can find the output of an example session:: 571 572 => setenv efi_selftest simple network protocol 573 => bootefi selftest 574 Testing EFI API implementation 575 Selected test: 'simple network protocol' 576 Setting up 'simple network protocol' 577 Setting up 'simple network protocol' succeeded 578 Executing 'simple network protocol' 579 DHCP Discover 580 DHCP reply received from 192.168.76.2 (52:55:c0:a8:4c:02) 581 as broadcast message. 582 Executing 'simple network protocol' succeeded 583 Tearing down 'simple network protocol' 584 Tearing down 'simple network protocol' succeeded 585 Boot services terminated 586 Summary: 0 failures 587 Preparing for reset. Press any key. 588 589The UEFI life cycle 590------------------- 591 592After the U-Boot platform has been initialized the UEFI API provides two kinds 593of services: 594 595* boot services 596* runtime services 597 598The API can be extended by loading UEFI drivers which come in two variants: 599 600* boot drivers 601* runtime drivers 602 603UEFI drivers are installed with U-Boot's bootefi command. With the same command 604UEFI applications can be executed. 605 606Loaded images of UEFI drivers stay in memory after returning to U-Boot while 607loaded images of applications are removed from memory. 608 609An UEFI application (e.g. an operating system) that wants to take full control 610of the system calls ExitBootServices. After a UEFI application calls 611ExitBootServices 612 613* boot services are not available anymore 614* timer events are stopped 615* the memory used by U-Boot except for runtime services is released 616* the memory used by boot time drivers is released 617 618So this is a point of no return. Afterwards the UEFI application can only return 619to U-Boot by rebooting. 620 621The UEFI object model 622--------------------- 623 624UEFI offers a flexible and expandable object model. The objects in the UEFI API 625are devices, drivers, and loaded images. These objects are referenced by 626handles. 627 628The interfaces implemented by the objects are referred to as protocols. These 629are identified by GUIDs. They can be installed and uninstalled by calling the 630appropriate boot services. 631 632Handles are created by the InstallProtocolInterface or the 633InstallMultipleProtocolinterfaces service if NULL is passed as handle. 634 635Handles are deleted when the last protocol has been removed with the 636UninstallProtocolInterface or the UninstallMultipleProtocolInterfaces service. 637 638Devices offer the EFI_DEVICE_PATH_PROTOCOL. A device path is the concatenation 639of device nodes. By their device paths all devices of a system are arranged in a 640tree. 641 642Drivers offer the EFI_DRIVER_BINDING_PROTOCOL. This protocol is used to connect 643a driver to devices (which are referenced as controllers in this context). 644 645Loaded images offer the EFI_LOADED_IMAGE_PROTOCOL. This protocol provides meta 646information about the image and a pointer to the unload callback function. 647 648The UEFI events 649--------------- 650 651In the UEFI terminology an event is a data object referencing a notification 652function which is queued for calling when the event is signaled. The following 653types of events exist: 654 655* periodic and single shot timer events 656* exit boot services events, triggered by calling the ExitBootServices() service 657* virtual address change events 658* memory map change events 659* read to boot events 660* reset system events 661* system table events 662* events that are only triggered programmatically 663 664Events can be created with the CreateEvent service and deleted with CloseEvent 665service. 666 667Events can be assigned to an event group. If any of the events in a group is 668signaled, all other events in the group are also set to the signaled state. 669 670The UEFI driver model 671--------------------- 672 673A driver is specific for a single protocol installed on a device. To install a 674driver on a device the ConnectController service is called. In this context 675controller refers to the device for which the driver is installed. 676 677The relevant drivers are identified using the EFI_DRIVER_BINDING_PROTOCOL. This 678protocol has has three functions: 679 680* supported - determines if the driver is compatible with the device 681* start - installs the driver by opening the relevant protocol with 682 attribute EFI_OPEN_PROTOCOL_BY_DRIVER 683* stop - uninstalls the driver 684 685The driver may create child controllers (child devices). E.g. a driver for block 686IO devices will create the device handles for the partitions. The child 687controllers will open the supported protocol with the attribute 688EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. 689 690A driver can be detached from a device using the DisconnectController service. 691 692U-Boot devices mapped as UEFI devices 693------------------------------------- 694 695Some of the U-Boot devices are mapped as UEFI devices 696 697* block IO devices 698* console 699* graphical output 700* network adapter 701 702As of U-Boot 2018.03 the logic for doing this is hard coded. 703 704The development target is to integrate the setup of these UEFI devices with the 705U-Boot driver model [5]. So when a U-Boot device is discovered a handle should 706be created and the device path protocol and the relevant IO protocol should be 707installed. The UEFI driver then would be attached by calling ConnectController. 708When a U-Boot device is removed DisconnectController should be called. 709 710UEFI devices mapped as U-Boot devices 711------------------------------------- 712 713UEFI drivers binaries and applications may create new (virtual) devices, install 714a protocol and call the ConnectController service. Now the matching UEFI driver 715is determined by iterating over the implementations of the 716EFI_DRIVER_BINDING_PROTOCOL. 717 718It is the task of the UEFI driver to create a corresponding U-Boot device and to 719proxy calls for this U-Boot device to the controller. 720 721In U-Boot 2018.03 this has only been implemented for block IO devices. 722 723UEFI uclass 724~~~~~~~~~~~ 725 726An UEFI uclass driver (lib/efi_driver/efi_uclass.c) has been created that 727takes care of initializing the UEFI drivers and providing the 728EFI_DRIVER_BINDING_PROTOCOL implementation for the UEFI drivers. 729 730A linker created list is used to keep track of the UEFI drivers. To create an 731entry in the list the UEFI driver uses the U_BOOT_DRIVER macro specifying 732UCLASS_EFI_LOADER as the ID of its uclass, e.g:: 733 734 /* Identify as UEFI driver */ 735 U_BOOT_DRIVER(efi_block) = { 736 .name = "EFI block driver", 737 .id = UCLASS_EFI_LOADER, 738 .ops = &driver_ops, 739 }; 740 741The available operations are defined via the structure struct efi_driver_ops:: 742 743 struct efi_driver_ops { 744 const efi_guid_t *protocol; 745 const efi_guid_t *child_protocol; 746 int (*bind)(efi_handle_t handle, void *interface); 747 }; 748 749When the supported() function of the EFI_DRIVER_BINDING_PROTOCOL is called the 750uclass checks if the protocol GUID matches the protocol GUID of the UEFI driver. 751In the start() function the bind() function of the UEFI driver is called after 752checking the GUID. 753The stop() function of the EFI_DRIVER_BINDING_PROTOCOL disconnects the child 754controllers created by the UEFI driver and the UEFI driver. (In U-Boot v2013.03 755this is not yet completely implemented.) 756 757UEFI block IO driver 758~~~~~~~~~~~~~~~~~~~~ 759 760The UEFI block IO driver supports devices exposing the EFI_BLOCK_IO_PROTOCOL. 761 762When connected it creates a new U-Boot block IO device with interface type 763UCLASS_EFI_LOADER, adds child controllers mapping the partitions, and installs 764the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL on these. This can be used together with the 765software iPXE to boot from iSCSI network drives [4]. 766 767This driver is only available if U-Boot is configured with:: 768 769 CONFIG_BLK=y 770 CONFIG_PARTITIONS=y 771 772Miscellaneous 773------------- 774 775Load file 2 protocol 776~~~~~~~~~~~~~~~~~~~~ 777 778The load file 2 protocol can be used by the Linux kernel to load the initial 779RAM disk. U-Boot can be configured to provide an implementation with:: 780 781 EFI_LOAD_FILE2_INITRD=y 782 783When the option is enabled the user can add the initrd path with the efidebug 784command. 785 786Load options Boot#### have a FilePathList[] member. The first element of 787the array (FilePathList[0]) is the EFI binary to execute. When an initrd 788is specified the Device Path for the initrd is denoted by a VenMedia node 789with the EFI_INITRD_MEDIA_GUID. Each entry of the array is terminated by the 790'end of entire device path' subtype (0xff). If a user wants to define multiple 791initrds, those must by separated by the 'end of this instance' identifier of 792the end node (0x01). 793 794So our final format of the FilePathList[] is:: 795 796 Loaded image - end node (0xff) - VenMedia - initrd_1 - [end node (0x01) - initrd_n ...] - end node (0xff) 797 798Links 799----- 800 801* [1] http://uefi.org/specifications - UEFI specifications 802* [2] https://github.com/ARM-software/ebbr/releases/download/v2.1.0/ebbr-v2.1.0.pdf - 803 Embedded Base Boot Requirements (EBBR) Specification - Release v2.1.0 804* [3] https://developer.arm.com/docs/den0044/latest/server-base-boot-requirements-system-software-on-arm-platforms-version-11 - 805 Server Base Boot Requirements System Software on ARM Platforms - Version 1.1 806* [4] :doc:`iscsi` 807* [5] :doc:`../driver-model/index` 808