]>
Commit | Line | Data |
---|---|---|
73d95c24 HS |
1 | .. SPDX-License-Identifier: GPL-2.0+ |
2 | .. Copyright (C) 2015 Google, Inc | |
f3b5056c HS |
3 | |
4 | U-Boot on EFI | |
5 | ============= | |
6 | This document provides information about U-Boot running on top of EFI, either | |
7 | as an application or just as a means of getting U-Boot onto a new platform. | |
8 | ||
9 | ||
f3b5056c HS |
10 | Motivation |
11 | ---------- | |
12 | Running 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 | |
73d95c24 HS |
15 | fully yet. You can boot into U-Boot from EFI and use that until U-Boot is |
16 | fully ported | |
f3b5056c HS |
17 | |
18 | - You need to use an EFI implementation (e.g. UEFI) because your vendor | |
73d95c24 | 19 | requires it in order to provide support |
f3b5056c HS |
20 | |
21 | - You plan to use coreboot to boot into U-Boot but coreboot support does | |
73d95c24 HS |
22 | 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 | |
f3b5056c HS |
24 | |
25 | - You use EFI but want to experiment with a simpler alternative like U-Boot | |
26 | ||
27 | ||
28 | Status | |
29 | ------ | |
30 | Only x86 is supported at present. If you are using EFI on another architecture | |
31 | you may want to reconsider. However, much of the code is generic so could be | |
32 | ported. | |
33 | ||
34 | U-Boot supports running as an EFI application for 32-bit EFI only. This is | |
35 | not very useful since only a serial port is provided. You can look around at | |
36 | memory and type 'help' but that is about it. | |
37 | ||
38 | More usefully, U-Boot supports building itself as a payload for either 32-bit | |
39 | or 64-bit EFI. U-Boot is packaged up and loaded in its entirety by EFI. Once | |
40 | started, U-Boot changes to 32-bit mode (currently) and takes over the | |
41 | machine. You can use devices, boot a kernel, etc. | |
42 | ||
43 | ||
44 | Build Instructions | |
45 | ------------------ | |
46 | First choose a board that has EFI support and obtain an EFI implementation | |
47 | for that board. It will be either 32-bit or 64-bit. Alternatively, you can | |
48 | opt for using QEMU [1] and the OVMF [2], as detailed below. | |
49 | ||
50 | To build U-Boot as an EFI application (32-bit EFI required), enable CONFIG_EFI | |
3ebd892f | 51 | and CONFIG_EFI_APP. The efi-x86_app config (efi-x86_app_defconfig) is set up |
73d95c24 | 52 | for this. Just build U-Boot as normal, e.g.:: |
f3b5056c | 53 | |
3ebd892f | 54 | make efi-x86_app_defconfig |
f3b5056c HS |
55 | make |
56 | ||
32151d40 BM |
57 | To build U-Boot as an EFI payload (32-bit or 64-bit EFI can be used), enable |
58 | CONFIG_EFI, CONFIG_EFI_STUB, and select either CONFIG_EFI_STUB_32BIT or | |
59 | CONFIG_EFI_STUB_64BIT. The efi-x86_payload configs (efi-x86_payload32_defconfig | |
60 | and efi-x86_payload32_defconfig) are set up for this. Then build U-Boot as | |
73d95c24 | 61 | normal, e.g.:: |
f3b5056c | 62 | |
32151d40 | 63 | make efi-x86_payload32_defconfig (or efi-x86_payload64_defconfig) |
f3b5056c HS |
64 | make |
65 | ||
66 | You will end up with one of these files depending on what you build for: | |
67 | ||
73d95c24 HS |
68 | * u-boot-app.efi - U-Boot EFI application |
69 | * u-boot-payload.efi - U-Boot EFI payload application | |
f3b5056c HS |
70 | |
71 | ||
72 | Trying it out | |
73 | ------------- | |
74 | QEMU is an emulator and it can emulate an x86 machine. Please make sure your | |
75 | QEMU version is 2.3.0 or above to test this. You can run the payload with | |
73d95c24 | 76 | something like this:: |
f3b5056c HS |
77 | |
78 | mkdir /tmp/efi | |
79 | cp /path/to/u-boot*.efi /tmp/efi | |
80 | qemu-system-x86_64 -bios bios.bin -hda fat:/tmp/efi/ | |
81 | ||
82 | Add -nographic if you want to use the terminal for output. Once it starts | |
83 | type 'fs0:u-boot-payload.efi' to run the payload or 'fs0:u-boot-app.efi' to | |
84 | run the application. 'bios.bin' is the EFI 'BIOS'. Check [2] to obtain a | |
85 | prebuilt EFI BIOS for QEMU or you can build one from source as well. | |
86 | ||
87 | To try it on real hardware, put u-boot-app.efi on a suitable boot medium, | |
73d95c24 | 88 | such as a USB stick. Then you can type something like this to start it:: |
f3b5056c HS |
89 | |
90 | fs0:u-boot-payload.efi | |
91 | ||
92 | (or fs0:u-boot-app.efi for the application) | |
93 | ||
94 | This will start the payload, copy U-Boot into RAM and start U-Boot. Note | |
95 | that EFI does not support booting a 64-bit application from a 32-bit | |
96 | EFI (or vice versa). Also it will often fail to print an error message if | |
97 | you get this wrong. | |
98 | ||
99 | ||
100 | Inner workings | |
73d95c24 | 101 | -------------- |
f3b5056c HS |
102 | Here follow a few implementation notes for those who want to fiddle with |
103 | this and perhaps contribute patches. | |
104 | ||
105 | The application and payload approaches sound similar but are in fact | |
106 | implemented completely differently. | |
107 | ||
108 | EFI Application | |
73d95c24 | 109 | ~~~~~~~~~~~~~~~ |
f3b5056c HS |
110 | For the application the whole of U-Boot is built as a shared library. The |
111 | efi_main() function is in lib/efi/efi_app.c. It sets up some basic EFI | |
112 | functions with efi_init(), sets up U-Boot global_data, allocates memory for | |
113 | U-Boot's malloc(), etc. and enters the normal init sequence (board_init_f() | |
114 | and board_init_r()). | |
115 | ||
116 | Since U-Boot limits its memory access to the allocated regions very little | |
117 | special code is needed. The CONFIG_EFI_APP option controls a few things | |
118 | that need to change so 'git grep CONFIG_EFI_APP' may be instructive. | |
119 | The CONFIG_EFI option controls more general EFI adjustments. | |
120 | ||
121 | The only available driver is the serial driver. This calls back into EFI | |
122 | 'boot services' to send and receive characters. Although it is implemented | |
123 | as a serial driver the console device is not necessarilly serial. If you | |
124 | boot EFI with video output then the 'serial' device will operate on your | |
125 | target devices's display instead and the device's USB keyboard will also | |
126 | work if connected. If you have both serial and video output, then both | |
127 | consoles will be active. Even though U-Boot does the same thing normally, | |
128 | These are features of EFI, not U-Boot. | |
129 | ||
130 | Very little code is involved in implementing the EFI application feature. | |
131 | U-Boot is highly portable. Most of the difficulty is in modifying the | |
132 | Makefile settings to pass the right build flags. In particular there is very | |
133 | little x86-specific code involved - you can find most of it in | |
134 | arch/x86/cpu. Porting to ARM (which can also use EFI if you are brave | |
135 | enough) should be straightforward. | |
136 | ||
137 | Use the 'reset' command to get back to EFI. | |
138 | ||
139 | EFI Payload | |
73d95c24 | 140 | ~~~~~~~~~~~ |
f3b5056c HS |
141 | The payload approach is a different kettle of fish. It works by building |
142 | U-Boot exactly as normal for your target board, then adding the entire | |
143 | image (including device tree) into a small EFI stub application responsible | |
144 | for booting it. The stub application is built as a normal EFI application | |
145 | except that it has a lot of data attached to it. | |
146 | ||
147 | The stub application is implemented in lib/efi/efi_stub.c. The efi_main() | |
148 | function is called by EFI. It is responsible for copying U-Boot from its | |
149 | original location into memory, disabling EFI boot services and starting | |
150 | U-Boot. U-Boot then starts as normal, relocates, starts all drivers, etc. | |
151 | ||
152 | The stub application is architecture-dependent. At present it has some | |
153 | x86-specific code and a comment at the top of efi_stub.c describes this. | |
154 | ||
155 | While the stub application does allocate some memory from EFI this is not | |
156 | used by U-Boot (the payload). In fact when U-Boot starts it has all of the | |
157 | memory available to it and can operate as it pleases (but see the next | |
158 | section). | |
159 | ||
160 | Tables | |
73d95c24 | 161 | ~~~~~~ |
f3b5056c HS |
162 | The payload can pass information to U-Boot in the form of EFI tables. At |
163 | present this feature is used to pass the EFI memory map, an inordinately | |
164 | large list of memory regions. You can use the 'efi mem all' command to | |
165 | display this list. U-Boot uses the list to work out where to relocate | |
166 | itself. | |
167 | ||
168 | Although U-Boot can use any memory it likes, EFI marks some memory as used | |
169 | by 'run-time services', code that hangs around while U-Boot is running and | |
170 | is even present when Linux is running. This is common on x86 and provides | |
171 | a way for Linux to call back into the firmware to control things like CPU | |
172 | fan speed. U-Boot uses only 'conventional' memory, in EFI terminology. It | |
173 | will relocate itself to the top of the largest block of memory it can find | |
174 | below 4GB. | |
175 | ||
176 | Interrupts | |
73d95c24 | 177 | ~~~~~~~~~~ |
f3b5056c HS |
178 | U-Boot drivers typically don't use interrupts. Since EFI enables interrupts |
179 | it is possible that an interrupt will fire that U-Boot cannot handle. This | |
180 | seems to cause problems. For this reason the U-Boot payload runs with | |
181 | interrupts disabled at present. | |
182 | ||
183 | 32/64-bit | |
73d95c24 | 184 | ~~~~~~~~~ |
f3b5056c HS |
185 | While the EFI application can in principle be built as either 32- or 64-bit, |
186 | only 32-bit is currently supported. This means that the application can only | |
187 | be used with 32-bit EFI. | |
188 | ||
189 | The payload stub can be build as either 32- or 64-bits. Only a small amount | |
190 | of code is built this way (see the extra- line in lib/efi/Makefile). | |
191 | Everything else is built as a normal U-Boot, so is always 32-bit on x86 at | |
192 | present. | |
193 | ||
194 | Future work | |
195 | ----------- | |
196 | This work could be extended in a number of ways: | |
197 | ||
f3b5056c HS |
198 | - Add ARM support |
199 | ||
200 | - Add 64-bit application support | |
201 | ||
202 | - Figure out how to solve the interrupt problem | |
203 | ||
204 | - Add more drivers to the application side (e.g. video, block devices, USB, | |
73d95c24 HS |
205 | environment access). This would mostly be an academic exercise as a strong |
206 | use case is not readily apparent, but it might be fun. | |
f3b5056c HS |
207 | |
208 | - Avoid turning off boot services in the stub. Instead allow U-Boot to make | |
73d95c24 HS |
209 | use of boot services in case it wants to. It is unclear what it might want |
210 | though. | |
f3b5056c HS |
211 | |
212 | Where is the code? | |
213 | ------------------ | |
214 | lib/efi | |
215 | payload stub, application, support code. Mostly arch-neutral | |
216 | ||
f3b5056c | 217 | arch/x86/cpu/efi |
4f1dacd4 | 218 | x86 support code for running as an EFI application and payload |
f3b5056c | 219 | |
3ebd892f | 220 | board/efi/efi-x86_app/efi.c |
f3b5056c HS |
221 | x86 board code for running as an EFI application |
222 | ||
32151d40 BM |
223 | board/efi/efi-x86_payload |
224 | generic x86 EFI payload board support code | |
225 | ||
f3b5056c HS |
226 | common/cmd_efi.c |
227 | the 'efi' command | |
228 | ||
229 | -- | |
230 | Ben Stoltz, Simon Glass | |
231 | Google, Inc | |
232 | July 2015 | |
233 | ||
73d95c24 HS |
234 | * [1] http://www.qemu.org |
235 | * [2] http://www.tianocore.org/ovmf/ |