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