Blame view

doc/README.uefi 11.9 KB
1914e5b5d   Heinrich Schuchardt   efi_loader: provi...
1
  <!--
f739fcd83   Tom Rini   SPDX: Convert a f...
2
  SPDX-License-Identifier: GPL-2.0+
1914e5b5d   Heinrich Schuchardt   efi_loader: provi...
3

f739fcd83   Tom Rini   SPDX: Convert a f...
4
  Copyright (c) 2018 Heinrich Schuchardt
1914e5b5d   Heinrich Schuchardt   efi_loader: provi...
5
6
7
8
9
10
11
12
13
  -->
  
  # 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.
9ba712dc8   Heinrich Schuchardt   efi_loader: defin...
14
15
16
17
18
19
20
21
  ## Development target
  
  The implementation of UEFI in U-Boot strives to reach the minimum requirements
  described in "Server Base Boot Requirements System Software on ARM Platforms -
  Version 1.1" [4].
  
  A full blown UEFI implementation would contradict the U-Boot design principle
  "keep it small".
1914e5b5d   Heinrich Schuchardt   efi_loader: provi...
22
  ## Building for UEFI
4f3cb4d57   Heinrich Schuchardt   doc: README.uefi:...
23
  The UEFI standard supports only little-endian systems. The UEFI support can be
1914e5b5d   Heinrich Schuchardt   efi_loader: provi...
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
  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 [3], 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}
  
  The environment variable 'bootargs' is passed as load options in the UEFI system
  table. The Linux kernel EFI stub uses the load options as command line
  arguments.
  
  ### Executing the boot manager
4f3cb4d57   Heinrich Schuchardt   doc: README.uefi:...
61
  The UEFI specification foresees to define boot entries and boot sequence via UEFI
1914e5b5d   Heinrich Schuchardt   efi_loader: provi...
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  variables. Booting according to these variables is possible via
  
      bootefi bootmgr [fdt address]
  
  As of U-Boot v2018.03 UEFI variables are not persisted and cannot be set at
  runtime.
  
  ### 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).
4f3cb4d57   Heinrich Schuchardt   doc: README.uefi:...
97
  ### Executing the built-in self-test
1914e5b5d   Heinrich Schuchardt   efi_loader: provi...
98

4f3cb4d57   Heinrich Schuchardt   doc: README.uefi:...
99
  An UEFI self-test suite can be embedded in U-Boot by building with
1914e5b5d   Heinrich Schuchardt   efi_loader: provi...
100
101
102
103
  
      CONFIG_CMD_BOOTEFI_SELFTEST=y
  
  For testing the UEFI implementation the bootefi command can be used to start the
4f3cb4d57   Heinrich Schuchardt   doc: README.uefi:...
104
  self-test.
1914e5b5d   Heinrich Schuchardt   efi_loader: provi...
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
  
      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 and
  * runtime services.
  
  The API can be extended by loading UEFI drivers which come in two variants
  
  * boot drivers and
  * 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. 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 [3].
  
  This driver is only available if U-Boot is configured with
  
      CONFIG_BLK=y
      CONFIG_PARTITIONS=y
98dc26016   Heinrich Schuchardt   efi_loader: updat...
305
  ## TODOs as of U-Boot 2019.04
1914e5b5d   Heinrich Schuchardt   efi_loader: provi...
306
307
308
  
  * unimplemented or incompletely implemented boot services
    * Exit - call unload function, unload applications only
71cee4ce6   Heinrich Schuchardt   README.uefi: upda...
309
    * ProtocolRegisterNotify
1914e5b5d   Heinrich Schuchardt   efi_loader: provi...
310
    * UnloadImage
71cee4ce6   Heinrich Schuchardt   README.uefi: upda...
311
312
  * unimplemented or incompletely implemented runtime services
    * SetVariable() ignores attribute EFI_VARIABLE_APPEND_WRITE
71cee4ce6   Heinrich Schuchardt   README.uefi: upda...
313
    * QueryVariableInfo is not implemented
1914e5b5d   Heinrich Schuchardt   efi_loader: provi...
314
315
316
  * unimplemented events
    * EVT_RUNTIME
    * EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
1914e5b5d   Heinrich Schuchardt   efi_loader: provi...
317
318
  
  * data model
1914e5b5d   Heinrich Schuchardt   efi_loader: provi...
319
320
321
322
323
324
325
326
327
328
    * manage configuration tables in a linked list
  
  * UEFI drivers
    * support DisconnectController for UEFI block devices.
  
  * support for CONFIG_EFI_LOADER in the sandbox (CONFIG_SANDBOX=y)
  
  * UEFI variables
    * persistence
    * runtime support
17394f9a6   Heinrich Schuchardt   efi_loader: TODO ...
329
330
  * incompletely implemented protocols
    * support version 0x00020000 of the EFI file protocol
1914e5b5d   Heinrich Schuchardt   efi_loader: provi...
331
332
333
334
335
336
  ## Links
  
  * [1](http://uefi.org/specifications)
    http://uefi.org/specifications - UEFI specifications
  * [2](./driver-model/README.txt) doc/driver-model/README.txt - Driver model
  * [3](./README.iscsi) doc/README.iscsi - iSCSI booting with U-Boot and iPXE
9ba712dc8   Heinrich Schuchardt   efi_loader: defin...
337
338
  * [4](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