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