1<!-- 2SPDX-License-Identifier: GPL-2.0+ 3 4Copyright (c) 2018 Heinrich Schuchardt 5--> 6 7# UEFI on U-Boot 8 9The Unified Extensible Firmware Interface Specification (UEFI) [1] has become 10the default for booting on AArch64 and x86 systems. It provides a stable API for 11the interaction of drivers and applications with the firmware. The API comprises 12access to block storage, network, and console to name a few. The Linux kernel 13and boot loaders like GRUB or the FreeBSD loader can be executed. 14 15## Development target 16 17The implementation of UEFI in U-Boot strives to reach the minimum requirements 18described in "Server Base Boot Requirements System Software on ARM Platforms - 19Version 1.1" [4]. 20 21A full blown UEFI implementation would contradict the U-Boot design principle 22"keep it small". 23 24## Building for UEFI 25 26The UEFI standard supports only little-endian systems. The UEFI support can be 27activated for ARM and x86 by specifying 28 29 CONFIG_CMD_BOOTEFI=y 30 CONFIG_EFI_LOADER=y 31 32in the .config file. 33 34Support for attaching virtual block devices, e.g. iSCSI drives connected by the 35loaded UEFI application [3], requires 36 37 CONFIG_BLK=y 38 CONFIG_PARTITIONS=y 39 40### Executing a UEFI binary 41 42The bootefi command is used to start UEFI applications or to install UEFI 43drivers. It takes two parameters 44 45 bootefi <image address> [fdt address] 46 47* image address - the memory address of the UEFI binary 48* fdt address - the memory address of the flattened device tree 49 50Below you find the output of an example session starting GRUB. 51 52 => load mmc 0:2 ${fdt_addr_r} boot/dtb 53 29830 bytes read in 14 ms (2 MiB/s) 54 => load mmc 0:1 ${kernel_addr_r} efi/debian/grubaa64.efi 55 reading efi/debian/grubaa64.efi 56 120832 bytes read in 7 ms (16.5 MiB/s) 57 => bootefi ${kernel_addr_r} ${fdt_addr_r} 58 59The environment variable 'bootargs' is passed as load options in the UEFI system 60table. The Linux kernel EFI stub uses the load options as command line 61arguments. 62 63### Executing the boot manager 64 65The UEFI specification foresees to define boot entries and boot sequence via UEFI 66variables. Booting according to these variables is possible via 67 68 bootefi bootmgr [fdt address] 69 70As of U-Boot v2018.03 UEFI variables are not persisted and cannot be set at 71runtime. 72 73### Executing the built in hello world application 74 75A hello world UEFI application can be built with 76 77 CONFIG_CMD_BOOTEFI_HELLO_COMPILE=y 78 79It can be embedded into the U-Boot binary with 80 81 CONFIG_CMD_BOOTEFI_HELLO=y 82 83The bootefi command is used to start the embedded hello world application. 84 85 bootefi hello [fdt address] 86 87Below you find the output of an example session. 88 89 => bootefi hello ${fdtcontroladdr} 90 ## Starting EFI application at 01000000 ... 91 WARNING: using memory device/image path, this may confuse some payloads! 92 Hello, world! 93 Running on UEFI 2.7 94 Have SMBIOS table 95 Have device tree 96 Load options: root=/dev/sdb3 init=/sbin/init rootwait ro 97 ## Application terminated, r = 0 98 99The environment variable fdtcontroladdr points to U-Boot's internal device tree 100(if available). 101 102### Executing the built-in self-test 103 104An UEFI self-test suite can be embedded in U-Boot by building with 105 106 CONFIG_CMD_BOOTEFI_SELFTEST=y 107 108For testing the UEFI implementation the bootefi command can be used to start the 109self-test. 110 111 bootefi selftest [fdt address] 112 113The environment variable 'efi_selftest' can be used to select a single test. If 114it is not provided all tests are executed except those marked as 'on request'. 115If the environment variable is set to 'list' a list of all tests is shown. 116 117Below you can find the output of an example session. 118 119 => setenv efi_selftest simple network protocol 120 => bootefi selftest 121 Testing EFI API implementation 122 Selected test: 'simple network protocol' 123 Setting up 'simple network protocol' 124 Setting up 'simple network protocol' succeeded 125 Executing 'simple network protocol' 126 DHCP Discover 127 DHCP reply received from 192.168.76.2 (52:55:c0:a8:4c:02) 128 as broadcast message. 129 Executing 'simple network protocol' succeeded 130 Tearing down 'simple network protocol' 131 Tearing down 'simple network protocol' succeeded 132 Boot services terminated 133 Summary: 0 failures 134 Preparing for reset. Press any key. 135 136## The UEFI life cycle 137 138After the U-Boot platform has been initialized the UEFI API provides two kinds 139of services 140 141* boot services and 142* runtime services. 143 144The API can be extended by loading UEFI drivers which come in two variants 145 146* boot drivers and 147* runtime drivers. 148 149UEFI drivers are installed with U-Boot's bootefi command. With the same command 150UEFI applications can be executed. 151 152Loaded images of UEFI drivers stay in memory after returning to U-Boot while 153loaded images of applications are removed from memory. 154 155An UEFI application (e.g. an operating system) that wants to take full control 156of the system calls ExitBootServices. After a UEFI application calls 157ExitBootServices 158 159* boot services are not available anymore 160* timer events are stopped 161* the memory used by U-Boot except for runtime services is released 162* the memory used by boot time drivers is released 163 164So this is a point of no return. Afterwards the UEFI application can only return 165to U-Boot by rebooting. 166 167## The UEFI object model 168 169UEFI offers a flexible and expandable object model. The objects in the UEFI API 170are devices, drivers, and loaded images. These objects are referenced by 171handles. 172 173The interfaces implemented by the objects are referred to as protocols. These 174are identified by GUIDs. They can be installed and uninstalled by calling the 175appropriate boot services. 176 177Handles are created by the InstallProtocolInterface or the 178InstallMultipleProtocolinterfaces service if NULL is passed as handle. 179 180Handles are deleted when the last protocol has been removed with the 181UninstallProtocolInterface or the UninstallMultipleProtocolInterfaces service. 182 183Devices offer the EFI_DEVICE_PATH_PROTOCOL. A device path is the concatenation 184of device nodes. By their device paths all devices of a system are arranged in a 185tree. 186 187Drivers offer the EFI_DRIVER_BINDING_PROTOCOL. This protocol is used to connect 188a driver to devices (which are referenced as controllers in this context). 189 190Loaded images offer the EFI_LOADED_IMAGE_PROTOCOL. This protocol provides meta 191information about the image and a pointer to the unload callback function. 192 193## The UEFI events 194 195In the UEFI terminology an event is a data object referencing a notification 196function which is queued for calling when the event is signaled. The following 197types of events exist: 198 199* periodic and single shot timer events 200* exit boot services events, triggered by calling the ExitBootServices() service 201* virtual address change events 202* memory map change events 203* read to boot events 204* reset system events 205* system table events 206* events that are only triggered programmatically 207 208Events can be created with the CreateEvent service and deleted with CloseEvent 209service. 210 211Events can be assigned to an event group. If any of the events in a group is 212signaled, all other events in the group are also set to the signaled state. 213 214## The UEFI driver model 215 216A driver is specific for a single protocol installed on a device. To install a 217driver on a device the ConnectController service is called. In this context 218controller refers to the device for which the driver is installed. 219 220The relevant drivers are identified using the EFI_DRIVER_BINDING_PROTOCOL. This 221protocol has has three functions: 222 223* supported - determines if the driver is compatible with the device 224* start - installs the driver by opening the relevant protocol with 225 attribute EFI_OPEN_PROTOCOL_BY_DRIVER 226* stop - uninstalls the driver 227 228The driver may create child controllers (child devices). E.g. a driver for block 229IO devices will create the device handles for the partitions. The child 230controllers will open the supported protocol with the attribute 231EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. 232 233A driver can be detached from a device using the DisconnectController service. 234 235## U-Boot devices mapped as UEFI devices 236 237Some of the U-Boot devices are mapped as UEFI devices 238 239* block IO devices 240* console 241* graphical output 242* network adapter 243 244As of U-Boot 2018.03 the logic for doing this is hard coded. 245 246The development target is to integrate the setup of these UEFI devices with the 247U-Boot driver model. So when a U-Boot device is discovered a handle should be 248created and the device path protocol and the relevant IO protocol should be 249installed. The UEFI driver then would be attached by calling ConnectController. 250When a U-Boot device is removed DisconnectController should be called. 251 252## UEFI devices mapped as U-Boot devices 253 254UEFI drivers binaries and applications may create new (virtual) devices, install 255a protocol and call the ConnectController service. Now the matching UEFI driver 256is determined by iterating over the implementations of the 257EFI_DRIVER_BINDING_PROTOCOL. 258 259It is the task of the UEFI driver to create a corresponding U-Boot device and to 260proxy calls for this U-Boot device to the controller. 261 262In U-Boot 2018.03 this has only been implemented for block IO devices. 263 264### UEFI uclass 265 266An UEFI uclass driver (lib/efi_driver/efi_uclass.c) has been created that 267takes care of initializing the UEFI drivers and providing the 268EFI_DRIVER_BINDING_PROTOCOL implementation for the UEFI drivers. 269 270A linker created list is used to keep track of the UEFI drivers. To create an 271entry in the list the UEFI driver uses the U_BOOT_DRIVER macro specifying 272UCLASS_EFI as the ID of its uclass, e.g. 273 274 /* Identify as UEFI driver */ 275 U_BOOT_DRIVER(efi_block) = { 276 .name = "EFI block driver", 277 .id = UCLASS_EFI, 278 .ops = &driver_ops, 279 }; 280 281The available operations are defined via the structure struct efi_driver_ops. 282 283 struct efi_driver_ops { 284 const efi_guid_t *protocol; 285 const efi_guid_t *child_protocol; 286 int (*bind)(efi_handle_t handle, void *interface); 287 }; 288 289When the supported() function of the EFI_DRIVER_BINDING_PROTOCOL is called the 290uclass checks if the protocol GUID matches the protocol GUID of the UEFI driver. 291In the start() function the bind() function of the UEFI driver is called after 292checking the GUID. 293The stop() function of the EFI_DRIVER_BINDING_PROTOCOL disconnects the child 294controllers created by the UEFI driver and the UEFI driver. (In U-Boot v2013.03 295this is not yet completely implemented.) 296 297### UEFI block IO driver 298 299The UEFI block IO driver supports devices exposing the EFI_BLOCK_IO_PROTOCOL. 300 301When connected it creates a new U-Boot block IO device with interface type 302IF_TYPE_EFI, adds child controllers mapping the partitions, and installs the 303EFI_SIMPLE_FILE_SYSTEM_PROTOCOL on these. This can be used together with the 304software iPXE to boot from iSCSI network drives [3]. 305 306This driver is only available if U-Boot is configured with 307 308 CONFIG_BLK=y 309 CONFIG_PARTITIONS=y 310 311## TODOs as of U-Boot 2019.04 312 313* unimplemented or incompletely implemented boot services 314 * Exit - call unload function, unload applications only 315 * ProtocolRegisterNotify 316 * UnloadImage 317 318* unimplemented or incompletely implemented runtime services 319 * SetVariable() ignores attribute EFI_VARIABLE_APPEND_WRITE 320 * QueryVariableInfo is not implemented 321 322* unimplemented events 323 * EVT_RUNTIME 324 * EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 325 326* data model 327 * manage configuration tables in a linked list 328 329* UEFI drivers 330 * support DisconnectController for UEFI block devices. 331 332* support for CONFIG_EFI_LOADER in the sandbox (CONFIG_SANDBOX=y) 333 334* UEFI variables 335 * persistence 336 * runtime support 337 338* incompletely implemented protocols 339 * support version 0x00020000 of the EFI file protocol 340 341## Links 342 343* [1](http://uefi.org/specifications) 344 http://uefi.org/specifications - UEFI specifications 345* [2](./driver-model/README.txt) doc/driver-model/README.txt - Driver model 346* [3](./README.iscsi) doc/README.iscsi - iSCSI booting with U-Boot and iPXE 347* [4](https://developer.arm.com/docs/den0044/latest/server-base-boot-requirements-system-software-on-arm-platforms-version-11) 348 Server Base Boot Requirements System Software on ARM Platforms - Version 1.1 349