xref: /openbmc/u-boot/doc/README.u-boot_on_efi (revision f3b5056c4e726238f3cbcdb8e5c34f38ba197611)
1*f3b5056cSHeinrich Schuchardt#
2*f3b5056cSHeinrich Schuchardt# Copyright (C) 2015 Google, Inc
3*f3b5056cSHeinrich Schuchardt#
4*f3b5056cSHeinrich Schuchardt# SPDX-License-Identifier:	GPL-2.0+
5*f3b5056cSHeinrich Schuchardt#
6*f3b5056cSHeinrich Schuchardt
7*f3b5056cSHeinrich SchuchardtU-Boot on EFI
8*f3b5056cSHeinrich Schuchardt=============
9*f3b5056cSHeinrich SchuchardtThis document provides information about U-Boot running on top of EFI, either
10*f3b5056cSHeinrich Schuchardtas an application or just as a means of getting U-Boot onto a new platform.
11*f3b5056cSHeinrich Schuchardt
12*f3b5056cSHeinrich Schuchardt
13*f3b5056cSHeinrich Schuchardt=========== Table of Contents ===========
14*f3b5056cSHeinrich Schuchardt
15*f3b5056cSHeinrich SchuchardtMotivation
16*f3b5056cSHeinrich SchuchardtStatus
17*f3b5056cSHeinrich SchuchardtBuild Instructions
18*f3b5056cSHeinrich SchuchardtTrying it out
19*f3b5056cSHeinrich SchuchardtInner workings
20*f3b5056cSHeinrich SchuchardtEFI Application
21*f3b5056cSHeinrich SchuchardtEFI Payload
22*f3b5056cSHeinrich SchuchardtTables
23*f3b5056cSHeinrich SchuchardtInterrupts
24*f3b5056cSHeinrich Schuchardt32/64-bit
25*f3b5056cSHeinrich SchuchardtFuture work
26*f3b5056cSHeinrich SchuchardtWhere is the code?
27*f3b5056cSHeinrich Schuchardt
28*f3b5056cSHeinrich Schuchardt
29*f3b5056cSHeinrich SchuchardtMotivation
30*f3b5056cSHeinrich Schuchardt----------
31*f3b5056cSHeinrich SchuchardtRunning U-Boot on EFI is useful in several situations:
32*f3b5056cSHeinrich Schuchardt
33*f3b5056cSHeinrich Schuchardt- You have EFI running on a board but U-Boot does not natively support it
34*f3b5056cSHeinrich Schuchardtfully yet. You can boot into U-Boot from EFI and use that until U-Boot is
35*f3b5056cSHeinrich Schuchardtfully ported
36*f3b5056cSHeinrich Schuchardt
37*f3b5056cSHeinrich Schuchardt- You need to use an EFI implementation (e.g. UEFI) because your vendor
38*f3b5056cSHeinrich Schuchardtrequires it in order to provide support
39*f3b5056cSHeinrich Schuchardt
40*f3b5056cSHeinrich Schuchardt- You plan to use coreboot to boot into U-Boot but coreboot support does
41*f3b5056cSHeinrich Schuchardtnot currently exist for your platform. In the meantime you can use U-Boot
42*f3b5056cSHeinrich Schuchardton EFI and then move to U-Boot on coreboot when ready
43*f3b5056cSHeinrich Schuchardt
44*f3b5056cSHeinrich Schuchardt- You use EFI but want to experiment with a simpler alternative like U-Boot
45*f3b5056cSHeinrich Schuchardt
46*f3b5056cSHeinrich Schuchardt
47*f3b5056cSHeinrich SchuchardtStatus
48*f3b5056cSHeinrich Schuchardt------
49*f3b5056cSHeinrich SchuchardtOnly x86 is supported at present. If you are using EFI on another architecture
50*f3b5056cSHeinrich Schuchardtyou may want to reconsider. However, much of the code is generic so could be
51*f3b5056cSHeinrich Schuchardtported.
52*f3b5056cSHeinrich Schuchardt
53*f3b5056cSHeinrich SchuchardtU-Boot supports running as an EFI application for 32-bit EFI only. This is
54*f3b5056cSHeinrich Schuchardtnot very useful since only a serial port is provided. You can look around at
55*f3b5056cSHeinrich Schuchardtmemory and type 'help' but that is about it.
56*f3b5056cSHeinrich Schuchardt
57*f3b5056cSHeinrich SchuchardtMore usefully, U-Boot supports building itself as a payload for either 32-bit
58*f3b5056cSHeinrich Schuchardtor 64-bit EFI. U-Boot is packaged up and loaded in its entirety by EFI. Once
59*f3b5056cSHeinrich Schuchardtstarted, U-Boot changes to 32-bit mode (currently) and takes over the
60*f3b5056cSHeinrich Schuchardtmachine. You can use devices, boot a kernel, etc.
61*f3b5056cSHeinrich Schuchardt
62*f3b5056cSHeinrich Schuchardt
63*f3b5056cSHeinrich SchuchardtBuild Instructions
64*f3b5056cSHeinrich Schuchardt------------------
65*f3b5056cSHeinrich SchuchardtFirst choose a board that has EFI support and obtain an EFI implementation
66*f3b5056cSHeinrich Schuchardtfor that board. It will be either 32-bit or 64-bit. Alternatively, you can
67*f3b5056cSHeinrich Schuchardtopt for using QEMU [1] and the OVMF [2], as detailed below.
68*f3b5056cSHeinrich Schuchardt
69*f3b5056cSHeinrich SchuchardtTo build U-Boot as an EFI application (32-bit EFI required), enable CONFIG_EFI
70*f3b5056cSHeinrich Schuchardtand CONFIG_EFI_APP. The efi-x86 config (efi-x86_defconfig) is set up for this.
71*f3b5056cSHeinrich SchuchardtJust build U-Boot as normal, e.g.
72*f3b5056cSHeinrich Schuchardt
73*f3b5056cSHeinrich Schuchardt   make efi-x86_defconfig
74*f3b5056cSHeinrich Schuchardt   make
75*f3b5056cSHeinrich Schuchardt
76*f3b5056cSHeinrich SchuchardtTo build U-Boot as an EFI payload (32-bit or 64-bit EFI can be used), adjust an
77*f3b5056cSHeinrich Schuchardtexisting config (like qemu-x86_defconfig) to enable CONFIG_EFI, CONFIG_EFI_STUB
78*f3b5056cSHeinrich Schuchardtand either CONFIG_EFI_STUB_32BIT or CONFIG_EFI_STUB_64BIT. All of these are
79*f3b5056cSHeinrich Schuchardtboolean Kconfig options. Then build U-Boot as normal, e.g.
80*f3b5056cSHeinrich Schuchardt
81*f3b5056cSHeinrich Schuchardt   make qemu-x86_defconfig
82*f3b5056cSHeinrich Schuchardt   make
83*f3b5056cSHeinrich Schuchardt
84*f3b5056cSHeinrich SchuchardtYou will end up with one of these files depending on what you build for:
85*f3b5056cSHeinrich Schuchardt
86*f3b5056cSHeinrich Schuchardt   u-boot-app.efi      - U-Boot EFI application
87*f3b5056cSHeinrich Schuchardt   u-boot-payload.efi  - U-Boot EFI payload application
88*f3b5056cSHeinrich Schuchardt
89*f3b5056cSHeinrich Schuchardt
90*f3b5056cSHeinrich SchuchardtTrying it out
91*f3b5056cSHeinrich Schuchardt-------------
92*f3b5056cSHeinrich SchuchardtQEMU is an emulator and it can emulate an x86 machine. Please make sure your
93*f3b5056cSHeinrich SchuchardtQEMU version is 2.3.0 or above to test this. You can run the payload with
94*f3b5056cSHeinrich Schuchardtsomething like this:
95*f3b5056cSHeinrich Schuchardt
96*f3b5056cSHeinrich Schuchardt   mkdir /tmp/efi
97*f3b5056cSHeinrich Schuchardt   cp /path/to/u-boot*.efi /tmp/efi
98*f3b5056cSHeinrich Schuchardt   qemu-system-x86_64 -bios bios.bin -hda fat:/tmp/efi/
99*f3b5056cSHeinrich Schuchardt
100*f3b5056cSHeinrich SchuchardtAdd -nographic if you want to use the terminal for output. Once it starts
101*f3b5056cSHeinrich Schuchardttype 'fs0:u-boot-payload.efi' to run the payload or 'fs0:u-boot-app.efi' to
102*f3b5056cSHeinrich Schuchardtrun the application. 'bios.bin' is the EFI 'BIOS'. Check [2] to obtain a
103*f3b5056cSHeinrich Schuchardtprebuilt EFI BIOS for QEMU or you can build one from source as well.
104*f3b5056cSHeinrich Schuchardt
105*f3b5056cSHeinrich SchuchardtTo try it on real hardware, put u-boot-app.efi on a suitable boot medium,
106*f3b5056cSHeinrich Schuchardtsuch as a USB stick. Then you can type something like this to start it:
107*f3b5056cSHeinrich Schuchardt
108*f3b5056cSHeinrich Schuchardt   fs0:u-boot-payload.efi
109*f3b5056cSHeinrich Schuchardt
110*f3b5056cSHeinrich Schuchardt(or fs0:u-boot-app.efi for the application)
111*f3b5056cSHeinrich Schuchardt
112*f3b5056cSHeinrich SchuchardtThis will start the payload, copy U-Boot into RAM and start U-Boot. Note
113*f3b5056cSHeinrich Schuchardtthat EFI does not support booting a 64-bit application from a 32-bit
114*f3b5056cSHeinrich SchuchardtEFI (or vice versa). Also it will often fail to print an error message if
115*f3b5056cSHeinrich Schuchardtyou get this wrong.
116*f3b5056cSHeinrich Schuchardt
117*f3b5056cSHeinrich Schuchardt
118*f3b5056cSHeinrich SchuchardtInner workings
119*f3b5056cSHeinrich Schuchardt==============
120*f3b5056cSHeinrich SchuchardtHere follow a few implementation notes for those who want to fiddle with
121*f3b5056cSHeinrich Schuchardtthis and perhaps contribute patches.
122*f3b5056cSHeinrich Schuchardt
123*f3b5056cSHeinrich SchuchardtThe application and payload approaches sound similar but are in fact
124*f3b5056cSHeinrich Schuchardtimplemented completely differently.
125*f3b5056cSHeinrich Schuchardt
126*f3b5056cSHeinrich SchuchardtEFI Application
127*f3b5056cSHeinrich Schuchardt---------------
128*f3b5056cSHeinrich SchuchardtFor the application the whole of U-Boot is built as a shared library. The
129*f3b5056cSHeinrich Schuchardtefi_main() function is in lib/efi/efi_app.c. It sets up some basic EFI
130*f3b5056cSHeinrich Schuchardtfunctions with efi_init(), sets up U-Boot global_data, allocates memory for
131*f3b5056cSHeinrich SchuchardtU-Boot's malloc(), etc. and enters the normal init sequence (board_init_f()
132*f3b5056cSHeinrich Schuchardtand board_init_r()).
133*f3b5056cSHeinrich Schuchardt
134*f3b5056cSHeinrich SchuchardtSince U-Boot limits its memory access to the allocated regions very little
135*f3b5056cSHeinrich Schuchardtspecial code is needed. The CONFIG_EFI_APP option controls a few things
136*f3b5056cSHeinrich Schuchardtthat need to change so 'git grep CONFIG_EFI_APP' may be instructive.
137*f3b5056cSHeinrich SchuchardtThe CONFIG_EFI option controls more general EFI adjustments.
138*f3b5056cSHeinrich Schuchardt
139*f3b5056cSHeinrich SchuchardtThe only available driver is the serial driver. This calls back into EFI
140*f3b5056cSHeinrich Schuchardt'boot services' to send and receive characters. Although it is implemented
141*f3b5056cSHeinrich Schuchardtas a serial driver the console device is not necessarilly serial. If you
142*f3b5056cSHeinrich Schuchardtboot EFI with video output then the 'serial' device will operate on your
143*f3b5056cSHeinrich Schuchardttarget devices's display instead and the device's USB keyboard will also
144*f3b5056cSHeinrich Schuchardtwork if connected. If you have both serial and video output, then both
145*f3b5056cSHeinrich Schuchardtconsoles will be active. Even though U-Boot does the same thing normally,
146*f3b5056cSHeinrich SchuchardtThese are features of EFI, not U-Boot.
147*f3b5056cSHeinrich Schuchardt
148*f3b5056cSHeinrich SchuchardtVery little code is involved in implementing the EFI application feature.
149*f3b5056cSHeinrich SchuchardtU-Boot is highly portable. Most of the difficulty is in modifying the
150*f3b5056cSHeinrich SchuchardtMakefile settings to pass the right build flags. In particular there is very
151*f3b5056cSHeinrich Schuchardtlittle x86-specific code involved - you can find most of it in
152*f3b5056cSHeinrich Schuchardtarch/x86/cpu. Porting to ARM (which can also use EFI if you are brave
153*f3b5056cSHeinrich Schuchardtenough) should be straightforward.
154*f3b5056cSHeinrich Schuchardt
155*f3b5056cSHeinrich SchuchardtUse the 'reset' command to get back to EFI.
156*f3b5056cSHeinrich Schuchardt
157*f3b5056cSHeinrich SchuchardtEFI Payload
158*f3b5056cSHeinrich Schuchardt-----------
159*f3b5056cSHeinrich SchuchardtThe payload approach is a different kettle of fish. It works by building
160*f3b5056cSHeinrich SchuchardtU-Boot exactly as normal for your target board, then adding the entire
161*f3b5056cSHeinrich Schuchardtimage (including device tree) into a small EFI stub application responsible
162*f3b5056cSHeinrich Schuchardtfor booting it. The stub application is built as a normal EFI application
163*f3b5056cSHeinrich Schuchardtexcept that it has a lot of data attached to it.
164*f3b5056cSHeinrich Schuchardt
165*f3b5056cSHeinrich SchuchardtThe stub application is implemented in lib/efi/efi_stub.c. The efi_main()
166*f3b5056cSHeinrich Schuchardtfunction is called by EFI. It is responsible for copying U-Boot from its
167*f3b5056cSHeinrich Schuchardtoriginal location into memory, disabling EFI boot services and starting
168*f3b5056cSHeinrich SchuchardtU-Boot. U-Boot then starts as normal, relocates, starts all drivers, etc.
169*f3b5056cSHeinrich Schuchardt
170*f3b5056cSHeinrich SchuchardtThe stub application is architecture-dependent. At present it has some
171*f3b5056cSHeinrich Schuchardtx86-specific code and a comment at the top of efi_stub.c describes this.
172*f3b5056cSHeinrich Schuchardt
173*f3b5056cSHeinrich SchuchardtWhile the stub application does allocate some memory from EFI this is not
174*f3b5056cSHeinrich Schuchardtused by U-Boot (the payload). In fact when U-Boot starts it has all of the
175*f3b5056cSHeinrich Schuchardtmemory available to it and can operate as it pleases (but see the next
176*f3b5056cSHeinrich Schuchardtsection).
177*f3b5056cSHeinrich Schuchardt
178*f3b5056cSHeinrich SchuchardtTables
179*f3b5056cSHeinrich Schuchardt------
180*f3b5056cSHeinrich SchuchardtThe payload can pass information to U-Boot in the form of EFI tables. At
181*f3b5056cSHeinrich Schuchardtpresent this feature is used to pass the EFI memory map, an inordinately
182*f3b5056cSHeinrich Schuchardtlarge list of memory regions. You can use the 'efi mem all' command to
183*f3b5056cSHeinrich Schuchardtdisplay this list. U-Boot uses the list to work out where to relocate
184*f3b5056cSHeinrich Schuchardtitself.
185*f3b5056cSHeinrich Schuchardt
186*f3b5056cSHeinrich SchuchardtAlthough U-Boot can use any memory it likes, EFI marks some memory as used
187*f3b5056cSHeinrich Schuchardtby 'run-time services', code that hangs around while U-Boot is running and
188*f3b5056cSHeinrich Schuchardtis even present when Linux is running. This is common on x86 and provides
189*f3b5056cSHeinrich Schuchardta way for Linux to call back into the firmware to control things like CPU
190*f3b5056cSHeinrich Schuchardtfan speed. U-Boot uses only 'conventional' memory, in EFI terminology. It
191*f3b5056cSHeinrich Schuchardtwill relocate itself to the top of the largest block of memory it can find
192*f3b5056cSHeinrich Schuchardtbelow 4GB.
193*f3b5056cSHeinrich Schuchardt
194*f3b5056cSHeinrich SchuchardtInterrupts
195*f3b5056cSHeinrich Schuchardt----------
196*f3b5056cSHeinrich SchuchardtU-Boot drivers typically don't use interrupts. Since EFI enables interrupts
197*f3b5056cSHeinrich Schuchardtit is possible that an interrupt will fire that U-Boot cannot handle. This
198*f3b5056cSHeinrich Schuchardtseems to cause problems. For this reason the U-Boot payload runs with
199*f3b5056cSHeinrich Schuchardtinterrupts disabled at present.
200*f3b5056cSHeinrich Schuchardt
201*f3b5056cSHeinrich Schuchardt32/64-bit
202*f3b5056cSHeinrich Schuchardt---------
203*f3b5056cSHeinrich SchuchardtWhile the EFI application can in principle be built as either 32- or 64-bit,
204*f3b5056cSHeinrich Schuchardtonly 32-bit is currently supported. This means that the application can only
205*f3b5056cSHeinrich Schuchardtbe used with 32-bit EFI.
206*f3b5056cSHeinrich Schuchardt
207*f3b5056cSHeinrich SchuchardtThe payload stub can be build as either 32- or 64-bits. Only a small amount
208*f3b5056cSHeinrich Schuchardtof code is built this way (see the extra- line in lib/efi/Makefile).
209*f3b5056cSHeinrich SchuchardtEverything else is built as a normal U-Boot, so is always 32-bit on x86 at
210*f3b5056cSHeinrich Schuchardtpresent.
211*f3b5056cSHeinrich Schuchardt
212*f3b5056cSHeinrich SchuchardtFuture work
213*f3b5056cSHeinrich Schuchardt-----------
214*f3b5056cSHeinrich SchuchardtThis work could be extended in a number of ways:
215*f3b5056cSHeinrich Schuchardt
216*f3b5056cSHeinrich Schuchardt- Add a generic x86 EFI payload configuration. At present you need to modify
217*f3b5056cSHeinrich Schuchardtan existing one, but mostly the low-level x86 code is disabled when booting
218*f3b5056cSHeinrich Schuchardton EFI anyway, so a generic 'EFI' board could be created with a suitable set
219*f3b5056cSHeinrich Schuchardtof drivers enabled.
220*f3b5056cSHeinrich Schuchardt
221*f3b5056cSHeinrich Schuchardt- Add ARM support
222*f3b5056cSHeinrich Schuchardt
223*f3b5056cSHeinrich Schuchardt- Add 64-bit application support
224*f3b5056cSHeinrich Schuchardt
225*f3b5056cSHeinrich Schuchardt- Figure out how to solve the interrupt problem
226*f3b5056cSHeinrich Schuchardt
227*f3b5056cSHeinrich Schuchardt- Add more drivers to the application side (e.g. video, block devices, USB,
228*f3b5056cSHeinrich Schuchardtenvironment access). This would mostly be an academic exercise as a strong
229*f3b5056cSHeinrich Schuchardtuse case is not readily apparent, but it might be fun.
230*f3b5056cSHeinrich Schuchardt
231*f3b5056cSHeinrich Schuchardt- Avoid turning off boot services in the stub. Instead allow U-Boot to make
232*f3b5056cSHeinrich Schuchardtuse of boot services in case it wants to. It is unclear what it might want
233*f3b5056cSHeinrich Schuchardtthough.
234*f3b5056cSHeinrich Schuchardt
235*f3b5056cSHeinrich SchuchardtWhere is the code?
236*f3b5056cSHeinrich Schuchardt------------------
237*f3b5056cSHeinrich Schuchardtlib/efi
238*f3b5056cSHeinrich Schuchardt	payload stub, application, support code. Mostly arch-neutral
239*f3b5056cSHeinrich Schuchardt
240*f3b5056cSHeinrich Schuchardtarch/x86/lib/efi
241*f3b5056cSHeinrich Schuchardt	helper functions for the fake DRAM init, etc. These can be used by
242*f3b5056cSHeinrich Schuchardt	any board that runs as a payload.
243*f3b5056cSHeinrich Schuchardt
244*f3b5056cSHeinrich Schuchardtarch/x86/cpu/efi
245*f3b5056cSHeinrich Schuchardt	x86 support code for running as an EFI application
246*f3b5056cSHeinrich Schuchardt
247*f3b5056cSHeinrich Schuchardtboard/efi/efi-x86/efi.c
248*f3b5056cSHeinrich Schuchardt	x86 board code for running as an EFI application
249*f3b5056cSHeinrich Schuchardt
250*f3b5056cSHeinrich Schuchardtcommon/cmd_efi.c
251*f3b5056cSHeinrich Schuchardt	the 'efi' command
252*f3b5056cSHeinrich Schuchardt
253*f3b5056cSHeinrich Schuchardt--
254*f3b5056cSHeinrich SchuchardtBen Stoltz, Simon Glass
255*f3b5056cSHeinrich SchuchardtGoogle, Inc
256*f3b5056cSHeinrich SchuchardtJuly 2015
257*f3b5056cSHeinrich Schuchardt
258*f3b5056cSHeinrich Schuchardt[1] http://www.qemu.org
259*f3b5056cSHeinrich Schuchardt[2] http://www.tianocore.org/ovmf/
260