blob: 245b4af1fa3540fbbe9beb0a2e2a91396f8df170 [file] [log] [blame]
Heinrich Schuchardtfd0b53f2019-07-26 06:46:08 +02001.. SPDX-License-Identifier: GPL-2.0+
2.. Copyright (C) 2015 Google, Inc
Heinrich Schuchardt32409242018-01-30 20:03:02 +01003
4U-Boot on EFI
5=============
6This document provides information about U-Boot running on top of EFI, either
7as an application or just as a means of getting U-Boot onto a new platform.
8
9
Heinrich Schuchardt32409242018-01-30 20:03:02 +010010Motivation
11----------
12Running U-Boot on EFI is useful in several situations:
13
14- You have EFI running on a board but U-Boot does not natively support it
Heinrich Schuchardtfd0b53f2019-07-26 06:46:08 +020015 fully yet. You can boot into U-Boot from EFI and use that until U-Boot is
16 fully ported
Heinrich Schuchardt32409242018-01-30 20:03:02 +010017
18- You need to use an EFI implementation (e.g. UEFI) because your vendor
Heinrich Schuchardtfd0b53f2019-07-26 06:46:08 +020019 requires it in order to provide support
Heinrich Schuchardt32409242018-01-30 20:03:02 +010020
21- You plan to use coreboot to boot into U-Boot but coreboot support does
Heinrich Schuchardtfd0b53f2019-07-26 06:46:08 +020022 not currently exist for your platform. In the meantime you can use U-Boot
23 on EFI and then move to U-Boot on coreboot when ready
Heinrich Schuchardt32409242018-01-30 20:03:02 +010024
25- You use EFI but want to experiment with a simpler alternative like U-Boot
26
27
28Status
29------
30Only x86 is supported at present. If you are using EFI on another architecture
31you may want to reconsider. However, much of the code is generic so could be
32ported.
33
Simon Glassd38bbb52023-09-03 09:15:51 -060034U-Boot supports running as an EFI application for both 32- and 64-bit EFI.
Heinrich Schuchardt32409242018-01-30 20:03:02 +010035
Simon Glassd38bbb52023-09-03 09:15:51 -060036U-Boot supports building itself as a payload for either 32-bit or 64-bit EFI.
37U-Boot is packaged up and loaded in its entirety by EFI. Once started, U-Boot
38changes to 32-bit mode (currently) and takes over the machine. You can use
39devices, boot a kernel, etc.
Heinrich Schuchardt32409242018-01-30 20:03:02 +010040
41
42Build Instructions
43------------------
44First choose a board that has EFI support and obtain an EFI implementation
45for that board. It will be either 32-bit or 64-bit. Alternatively, you can
46opt for using QEMU [1] and the OVMF [2], as detailed below.
47
Simon Glassd38bbb52023-09-03 09:15:51 -060048To build U-Boot as an EFI application, enable CONFIG_EFI and CONFIG_EFI_APP.
49The efi-x86_app32 and efi-x86_app64 configs are set up for this. Just build
50U-Boot as normal, e.g.::
Heinrich Schuchardt32409242018-01-30 20:03:02 +010051
Simon Glass49a643b2021-11-03 21:09:07 -060052 make efi-x86_app32_defconfig
Heinrich Schuchardt32409242018-01-30 20:03:02 +010053 make
54
Bin Meng858429b2018-06-12 08:36:18 -070055To build U-Boot as an EFI payload (32-bit or 64-bit EFI can be used), enable
56CONFIG_EFI, CONFIG_EFI_STUB, and select either CONFIG_EFI_STUB_32BIT or
57CONFIG_EFI_STUB_64BIT. The efi-x86_payload configs (efi-x86_payload32_defconfig
58and efi-x86_payload32_defconfig) are set up for this. Then build U-Boot as
Heinrich Schuchardtfd0b53f2019-07-26 06:46:08 +020059normal, e.g.::
Heinrich Schuchardt32409242018-01-30 20:03:02 +010060
Bin Meng858429b2018-06-12 08:36:18 -070061 make efi-x86_payload32_defconfig (or efi-x86_payload64_defconfig)
Heinrich Schuchardt32409242018-01-30 20:03:02 +010062 make
63
64You will end up with one of these files depending on what you build for:
65
Heinrich Schuchardtfd0b53f2019-07-26 06:46:08 +020066* u-boot-app.efi - U-Boot EFI application
67* u-boot-payload.efi - U-Boot EFI payload application
Heinrich Schuchardt32409242018-01-30 20:03:02 +010068
69
70Trying it out
71-------------
72QEMU is an emulator and it can emulate an x86 machine. Please make sure your
Bin Meng74efc6e2021-06-21 10:12:32 +080073QEMU version is 6.0.0 or above to test this. You can run the payload with
Heinrich Schuchardtfd0b53f2019-07-26 06:46:08 +020074something like this::
Heinrich Schuchardt32409242018-01-30 20:03:02 +010075
76 mkdir /tmp/efi
77 cp /path/to/u-boot*.efi /tmp/efi
Bin Meng74efc6e2021-06-21 10:12:32 +080078 qemu-system-x86_64 -pflash edk2-x86_64-code.fd -hda fat:rw:/tmp/efi/
Heinrich Schuchardt32409242018-01-30 20:03:02 +010079
80Add -nographic if you want to use the terminal for output. Once it starts
81type 'fs0:u-boot-payload.efi' to run the payload or 'fs0:u-boot-app.efi' to
Bin Meng74efc6e2021-06-21 10:12:32 +080082run the application. 'edk2-x86_64-code.fd' is the EFI 'BIOS'. QEMU already
83ships both 32-bit and 64-bit EFI BIOS images. For 32-bit EFI 'BIOS' image,
84use 'edk2-i386-code.fd'.
85
Heinrich Schuchardt32409242018-01-30 20:03:02 +010086
87To try it on real hardware, put u-boot-app.efi on a suitable boot medium,
Heinrich Schuchardtfd0b53f2019-07-26 06:46:08 +020088such as a USB stick. Then you can type something like this to start it::
Heinrich Schuchardt32409242018-01-30 20:03:02 +010089
90 fs0:u-boot-payload.efi
91
92(or fs0:u-boot-app.efi for the application)
93
94This will start the payload, copy U-Boot into RAM and start U-Boot. Note
95that EFI does not support booting a 64-bit application from a 32-bit
96EFI (or vice versa). Also it will often fail to print an error message if
97you get this wrong.
98
Simon Glassdaa53a22021-11-03 21:09:03 -060099You may find the script `scripts/build-efi.sh` helpful for building and testing
100U-Boot on UEFI on QEMU. It also includes links to UEFI binaries dating from
1012021.
102
103See `Example run`_ for an example run.
Heinrich Schuchardt32409242018-01-30 20:03:02 +0100104
105Inner workings
Heinrich Schuchardtfd0b53f2019-07-26 06:46:08 +0200106--------------
Heinrich Schuchardt32409242018-01-30 20:03:02 +0100107Here follow a few implementation notes for those who want to fiddle with
108this and perhaps contribute patches.
109
110The application and payload approaches sound similar but are in fact
111implemented completely differently.
112
113EFI Application
Heinrich Schuchardtfd0b53f2019-07-26 06:46:08 +0200114~~~~~~~~~~~~~~~
Heinrich Schuchardt32409242018-01-30 20:03:02 +0100115For the application the whole of U-Boot is built as a shared library. The
116efi_main() function is in lib/efi/efi_app.c. It sets up some basic EFI
117functions with efi_init(), sets up U-Boot global_data, allocates memory for
118U-Boot's malloc(), etc. and enters the normal init sequence (board_init_f()
119and board_init_r()).
120
121Since U-Boot limits its memory access to the allocated regions very little
122special code is needed. The CONFIG_EFI_APP option controls a few things
123that need to change so 'git grep CONFIG_EFI_APP' may be instructive.
124The CONFIG_EFI option controls more general EFI adjustments.
125
126The only available driver is the serial driver. This calls back into EFI
127'boot services' to send and receive characters. Although it is implemented
128as a serial driver the console device is not necessarilly serial. If you
129boot EFI with video output then the 'serial' device will operate on your
130target devices's display instead and the device's USB keyboard will also
131work if connected. If you have both serial and video output, then both
132consoles will be active. Even though U-Boot does the same thing normally,
133These are features of EFI, not U-Boot.
134
135Very little code is involved in implementing the EFI application feature.
136U-Boot is highly portable. Most of the difficulty is in modifying the
137Makefile settings to pass the right build flags. In particular there is very
138little x86-specific code involved - you can find most of it in
139arch/x86/cpu. Porting to ARM (which can also use EFI if you are brave
140enough) should be straightforward.
141
142Use the 'reset' command to get back to EFI.
143
144EFI Payload
Heinrich Schuchardtfd0b53f2019-07-26 06:46:08 +0200145~~~~~~~~~~~
Heinrich Schuchardt32409242018-01-30 20:03:02 +0100146The payload approach is a different kettle of fish. It works by building
147U-Boot exactly as normal for your target board, then adding the entire
148image (including device tree) into a small EFI stub application responsible
149for booting it. The stub application is built as a normal EFI application
150except that it has a lot of data attached to it.
151
152The stub application is implemented in lib/efi/efi_stub.c. The efi_main()
153function is called by EFI. It is responsible for copying U-Boot from its
154original location into memory, disabling EFI boot services and starting
155U-Boot. U-Boot then starts as normal, relocates, starts all drivers, etc.
156
157The stub application is architecture-dependent. At present it has some
158x86-specific code and a comment at the top of efi_stub.c describes this.
159
160While the stub application does allocate some memory from EFI this is not
161used by U-Boot (the payload). In fact when U-Boot starts it has all of the
162memory available to it and can operate as it pleases (but see the next
163section).
164
165Tables
Heinrich Schuchardtfd0b53f2019-07-26 06:46:08 +0200166~~~~~~
Heinrich Schuchardt32409242018-01-30 20:03:02 +0100167The payload can pass information to U-Boot in the form of EFI tables. At
168present this feature is used to pass the EFI memory map, an inordinately
169large list of memory regions. You can use the 'efi mem all' command to
170display this list. U-Boot uses the list to work out where to relocate
171itself.
172
173Although U-Boot can use any memory it likes, EFI marks some memory as used
174by 'run-time services', code that hangs around while U-Boot is running and
175is even present when Linux is running. This is common on x86 and provides
176a way for Linux to call back into the firmware to control things like CPU
177fan speed. U-Boot uses only 'conventional' memory, in EFI terminology. It
178will relocate itself to the top of the largest block of memory it can find
179below 4GB.
180
181Interrupts
Heinrich Schuchardtfd0b53f2019-07-26 06:46:08 +0200182~~~~~~~~~~
Heinrich Schuchardt32409242018-01-30 20:03:02 +0100183U-Boot drivers typically don't use interrupts. Since EFI enables interrupts
184it is possible that an interrupt will fire that U-Boot cannot handle. This
185seems to cause problems. For this reason the U-Boot payload runs with
186interrupts disabled at present.
187
18832/64-bit
Heinrich Schuchardtfd0b53f2019-07-26 06:46:08 +0200189~~~~~~~~~
Simon Glassd38bbb52023-09-03 09:15:51 -0600190While the EFI application can be built as either 32- or 64-bit, you need to be
191careful to build the correct one so that your UEFI firmware can start it. Most
192UEFI images are 64-bit at present.
Heinrich Schuchardt32409242018-01-30 20:03:02 +0100193
194The payload stub can be build as either 32- or 64-bits. Only a small amount
195of code is built this way (see the extra- line in lib/efi/Makefile).
196Everything else is built as a normal U-Boot, so is always 32-bit on x86 at
197present.
198
Simon Glassdaa53a22021-11-03 21:09:03 -0600199Example run
200-----------
201
202This shows running with serial enabled (see `include/configs/efi-x86_app.h`)::
203
204 $ scripts/build-efi.sh -wsPr
205 Packaging efi-x86_app32
206 Running qemu-system-i386
207
208 BdsDxe: failed to load Boot0001 "UEFI QEMU HARDDISK QM00005 " from PciRoot(0x0)/Pci(0x3,0x0)/Sata(0x0,0xFFFF,0x0): Not Found
209 BdsDxe: loading Boot0002 "EFI Internal Shell" from Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1)
210 BdsDxe: starting Boot0002 "EFI Internal Shell" from Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1)
211
212 UEFI Interactive Shell v2.2
213 EDK II
214 UEFI v2.70 (EDK II, 0x00010000)
215 Mapping table
216 FS0: Alias(s):HD0a65535a1:;BLK1:
217 PciRoot(0x0)/Pci(0x3,0x0)/Sata(0x0,0xFFFF,0x0)/HD(1,GPT,0FFD5E61-3B0C-4326-8049-BDCDC910AF72,0x800,0xB000)
218 BLK0: Alias(s):
219 PciRoot(0x0)/Pci(0x3,0x0)/Sata(0x0,0xFFFF,0x0)
220
221 Press ESC in 5 seconds to skip startup.nsh or any other key to continue.
222 Shell> fs0:u-boot-app.efi
223 U-Boot EFI App (using allocated RAM address 47d4000) key=8d4, image=06a6f610
224 starting
225
226
227 U-Boot 2022.01-rc4 (Sep 19 2021 - 14:03:20 -0600)
228
229 CPU: x86, vendor Intel, device 663h
230 DRAM: 32 MiB
231 0: efi_media_0 PciRoot(0x0)/Pci(0x3,0x0)/Sata(0x0,0xFFFF,0x0)
232 1: <partition> PciRoot(0x0)/Pci(0x3,0x0)/Sata(0x0,0xFFFF,0x0)/HD(1,GPT,0FFD5E61-3B0C-4326-8049-BDCDC910AF72,0x800,0xB000)
233 Loading Environment from nowhere... OK
234 Model: EFI x86 Application
235 Hit any key to stop autoboot: 0
236
237 Partition Map for EFI device 0 -- Partition Type: EFI
238
239 Part Start LBA End LBA Name
240 Attributes
241 Type GUID
242 Partition GUID
243 1 0x00000800 0x0000b7ff "boot"
244 attrs: 0x0000000000000000
245 type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
246 guid: 0ffd5e61-3b0c-4326-8049-bdcdc910af72
247 19 startup.nsh
248 528384 u-boot-app.efi
249 10181 NvVars
250
251 3 file(s), 0 dir(s)
252
253 => QEMU: Terminated
254
Thomas Mittelstaedtfb4ef742023-08-22 13:49:02 +0000255Run on VirtualBox (x86_64)
256--------------------------
257
258Enable EFI
259~~~~~~~~~~
260At settings for virtual machine the flag at **System->Motherboard->Enable EFI
261(special OSes only)** has to be enabled.
262
263Installation
264~~~~~~~~~~~~
265Provide the preinstalled Linux system as a Virtual Disk Image (VDI) and assign
266it to a SATA controller (type AHCI) using the settings for the virtual machine
267at menu item **System->Storage->Controller:SATA**.
268
269For the following description three GPT partitions are assumed:
270
271- Partition 1: formatted as FAT file-system and marked as EFI system partition
272 (partition type 0xEF00) used for the U-Boot EFI binary. (If VirtualBox is UEFI
273 compliant, it should recognize the ESP as the boot partition.)
274
275- Partition 2: formatted as **ext4**, used for root file system
276
277Create an extlinux.conf or a boot script
278~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
279
280Following files are assumed to be located at system for boot configuration::
281
282 Partition File Comment
283 1 EFI/BOOT/BOOTX64.efi # renamed U-Boot EFI image
284 1 Image # Linux image
285 1 Initrd # Initramfs of Linux
286
287**EFI/BOOT/BOOTX64.efi** is a renamed build result **u-boot-payload.efi**, built with
288**efi-x86_payload64_defconfig** configuration.
289
290Boot script
291~~~~~~~~~~~
292
293The boot script **boot.scr** is assumed to be located at::
294
295 Partition File Comment
296 1 boot.scr # Boot script, generated with mkimage from template
297
298Content of **boot.scr**:
299
300.. code-block:: bash
301
302 ext4load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} ${prefix}Image
303 setenv kernel_size ${filesize}
304 ext4load ${devtype} ${devnum}:${distro_bootpart} ${ramdisk_addr_r} ${prefix}Initrd
305 setenv initrd_size ${filesize}
306 zboot ${kernel_addr_r} ${kernel_size} ${ramdisk_addr_r} ${initrd_size}
307
308Extlinux configuration
309~~~~~~~~~~~~~~~~~~~~~~
310
311Alternatively a configuration **extlinux.conf** can be used. **extlinux.conf**
312is assumed to be located at::
313
314 Partition File Comment
315 1 extlinux/extlinux.conf # Extlinux boot configuration
316
317Content of **extlinux.conf**:
318
319.. code-block:: bash
320
321 default l0
322 menu title U-Boot menu
323 prompt 0
324 timeout 50
325
326 label l0
327 menu label Linux
328 linux /Image
329 initrd /Initrd
330
331
332Additionally something like (sda is assumed as disk device):
333
334.. code-block:: bash
335
336 append root=/dev/sda2 console=tty0 console=ttyS0,115200n8 rootwait rw
337
338
Simon Glassdaa53a22021-11-03 21:09:03 -0600339
Heinrich Schuchardt32409242018-01-30 20:03:02 +0100340Future work
341-----------
342This work could be extended in a number of ways:
343
Heinrich Schuchardt32409242018-01-30 20:03:02 +0100344- Add ARM support
345
Heinrich Schuchardt32409242018-01-30 20:03:02 +0100346- Figure out how to solve the interrupt problem
347
Simon Glass2d4b33e2021-12-29 11:57:36 -0700348- Add more drivers to the application side (e.g.USB, environment access).
Heinrich Schuchardt32409242018-01-30 20:03:02 +0100349
350- Avoid turning off boot services in the stub. Instead allow U-Boot to make
Heinrich Schuchardtfd0b53f2019-07-26 06:46:08 +0200351 use of boot services in case it wants to. It is unclear what it might want
Simon Glass5c267a02021-12-29 11:57:38 -0700352 though. It is better to use the app.
Heinrich Schuchardt32409242018-01-30 20:03:02 +0100353
354Where is the code?
355------------------
356lib/efi
357 payload stub, application, support code. Mostly arch-neutral
358
Heinrich Schuchardt32409242018-01-30 20:03:02 +0100359arch/x86/cpu/efi
Bin Meng525c8612018-06-12 08:36:16 -0700360 x86 support code for running as an EFI application and payload
Heinrich Schuchardt32409242018-01-30 20:03:02 +0100361
Bin Meng65820742018-06-12 08:36:24 -0700362board/efi/efi-x86_app/efi.c
Heinrich Schuchardt32409242018-01-30 20:03:02 +0100363 x86 board code for running as an EFI application
364
Bin Meng858429b2018-06-12 08:36:18 -0700365board/efi/efi-x86_payload
366 generic x86 EFI payload board support code
367
Heinrich Schuchardt32409242018-01-30 20:03:02 +0100368common/cmd_efi.c
369 the 'efi' command
370
371--
372Ben Stoltz, Simon Glass
373Google, Inc
374July 2015
375
Heinrich Schuchardtfd0b53f2019-07-26 06:46:08 +0200376* [1] http://www.qemu.org
Bin Meng74efc6e2021-06-21 10:12:32 +0800377* [2] https://github.com/tianocore/tianocore.github.io/wiki/OVMF