This time we have a few important bug fixes. Most noticable are: - Fix OpenBSD loader with CONFIG_BLK=n - Fix builds on various circumstances - Add missing stubs so callers don't call NULL - Bump UEFI revision to 2.7 -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABAgAGBQJafi5RAAoJECszeR4D/txgEgoQAK++XDqaPdSbQeU6vUawLDvi wSbAR0ei+WS0leH0ui4w0mjuB8sDs8kAJzbRrSV0Jbj11MYa1FuckDGldXCxegN/ TyxaUyGnlwd4cXqxIc5lmOc+Q0/rpH+q35a3ymAQvGqqgAVq1JbLmWYyOy9WMBRS 2QDV5Z4640fngEapQPlq83hWa4BG0bfUKjxAAj1JwF8I2MNnjJF7w5PYnvvr2KSD l7puS1nuVVy6NZ0AjrK4rZTmebEHfVQfhpIAWqcEPVr89KO3kfTYARLOmaMKUYAt UUJZFROcYc0hSXNHAekAHE2jON49aB0noXmGmAMzUD6BWxDxCBoCL1kTu01TZy3O NbbaU5m+VQaa+1tyPa6tJYq4teNcjLa1i6dBrtUIiF4YKqOPxV12RniLJUqEUE8P nSdZ8BcAhhXM7VqEHxie6AcQ98LNDgcmxHWrSyPa5iuURGqKO3+TLyDBPluO8tTy 6BxMCT0kpBuKOeDfm6DRAv0lTVFR7qV3Mx8QZjw7hIYxn2Mc8UjtCerJ0Xo+CC12 Nte7Qbnd2Md7kPGitralk6JlxeXqo41bQHQ6T5KMTAe2IYxoqu3fl5Y+bgrjrOGB P/NdtJHvqdqj6nDC2Ofub1BlnZfaQbh9obcv/7bJL8sX6QgPPYfWGbqx38Tl11Fa TVL/yhGE+hcF2YYI8ksM =JsQz -----END PGP SIGNATURE----- Merge tag 'signed-efi-v2018.03' of git://github.com/agraf/u-boot Patch queue for efi in 2018.03 - 2018-02-10 This time we have a few important bug fixes. Most noticable are: - Fix OpenBSD loader with CONFIG_BLK=n - Fix builds on various circumstances - Add missing stubs so callers don't call NULL - Bump UEFI revision to 2.7master
commit
f59ab6c659
@ -0,0 +1,259 @@ |
||||
# |
||||
# Copyright (C) 2015 Google, Inc |
||||
# |
||||
# SPDX-License-Identifier: GPL-2.0+ |
||||
# |
||||
|
||||
U-Boot on EFI |
||||
============= |
||||
This document provides information about U-Boot running on top of EFI, either |
||||
as an application or just as a means of getting U-Boot onto a new platform. |
||||
|
||||
|
||||
=========== Table of Contents =========== |
||||
|
||||
Motivation |
||||
Status |
||||
Build Instructions |
||||
Trying it out |
||||
Inner workings |
||||
EFI Application |
||||
EFI Payload |
||||
Tables |
||||
Interrupts |
||||
32/64-bit |
||||
Future work |
||||
Where is the code? |
||||
|
||||
|
||||
Motivation |
||||
---------- |
||||
Running U-Boot on EFI is useful in several situations: |
||||
|
||||
- You have EFI running on a board but U-Boot does not natively support it |
||||
fully yet. You can boot into U-Boot from EFI and use that until U-Boot is |
||||
fully ported |
||||
|
||||
- You need to use an EFI implementation (e.g. UEFI) because your vendor |
||||
requires it in order to provide support |
||||
|
||||
- You plan to use coreboot to boot into U-Boot but coreboot support does |
||||
not currently exist for your platform. In the meantime you can use U-Boot |
||||
on EFI and then move to U-Boot on coreboot when ready |
||||
|
||||
- You use EFI but want to experiment with a simpler alternative like U-Boot |
||||
|
||||
|
||||
Status |
||||
------ |
||||
Only x86 is supported at present. If you are using EFI on another architecture |
||||
you may want to reconsider. However, much of the code is generic so could be |
||||
ported. |
||||
|
||||
U-Boot supports running as an EFI application for 32-bit EFI only. This is |
||||
not very useful since only a serial port is provided. You can look around at |
||||
memory and type 'help' but that is about it. |
||||
|
||||
More usefully, U-Boot supports building itself as a payload for either 32-bit |
||||
or 64-bit EFI. U-Boot is packaged up and loaded in its entirety by EFI. Once |
||||
started, U-Boot changes to 32-bit mode (currently) and takes over the |
||||
machine. You can use devices, boot a kernel, etc. |
||||
|
||||
|
||||
Build Instructions |
||||
------------------ |
||||
First choose a board that has EFI support and obtain an EFI implementation |
||||
for that board. It will be either 32-bit or 64-bit. Alternatively, you can |
||||
opt for using QEMU [1] and the OVMF [2], as detailed below. |
||||
|
||||
To build U-Boot as an EFI application (32-bit EFI required), enable CONFIG_EFI |
||||
and CONFIG_EFI_APP. The efi-x86 config (efi-x86_defconfig) is set up for this. |
||||
Just build U-Boot as normal, e.g. |
||||
|
||||
make efi-x86_defconfig |
||||
make |
||||
|
||||
To build U-Boot as an EFI payload (32-bit or 64-bit EFI can be used), adjust an |
||||
existing config (like qemu-x86_defconfig) to enable CONFIG_EFI, CONFIG_EFI_STUB |
||||
and either CONFIG_EFI_STUB_32BIT or CONFIG_EFI_STUB_64BIT. All of these are |
||||
boolean Kconfig options. Then build U-Boot as normal, e.g. |
||||
|
||||
make qemu-x86_defconfig |
||||
make |
||||
|
||||
You will end up with one of these files depending on what you build for: |
||||
|
||||
u-boot-app.efi - U-Boot EFI application |
||||
u-boot-payload.efi - U-Boot EFI payload application |
||||
|
||||
|
||||
Trying it out |
||||
------------- |
||||
QEMU is an emulator and it can emulate an x86 machine. Please make sure your |
||||
QEMU version is 2.3.0 or above to test this. You can run the payload with |
||||
something like this: |
||||
|
||||
mkdir /tmp/efi |
||||
cp /path/to/u-boot*.efi /tmp/efi |
||||
qemu-system-x86_64 -bios bios.bin -hda fat:/tmp/efi/ |
||||
|
||||
Add -nographic if you want to use the terminal for output. Once it starts |
||||
type 'fs0:u-boot-payload.efi' to run the payload or 'fs0:u-boot-app.efi' to |
||||
run the application. 'bios.bin' is the EFI 'BIOS'. Check [2] to obtain a |
||||
prebuilt EFI BIOS for QEMU or you can build one from source as well. |
||||
|
||||
To try it on real hardware, put u-boot-app.efi on a suitable boot medium, |
||||
such as a USB stick. Then you can type something like this to start it: |
||||
|
||||
fs0:u-boot-payload.efi |
||||
|
||||
(or fs0:u-boot-app.efi for the application) |
||||
|
||||
This will start the payload, copy U-Boot into RAM and start U-Boot. Note |
||||
that EFI does not support booting a 64-bit application from a 32-bit |
||||
EFI (or vice versa). Also it will often fail to print an error message if |
||||
you get this wrong. |
||||
|
||||
|
||||
Inner workings |
||||
============== |
||||
Here follow a few implementation notes for those who want to fiddle with |
||||
this and perhaps contribute patches. |
||||
|
||||
The application and payload approaches sound similar but are in fact |
||||
implemented completely differently. |
||||
|
||||
EFI Application |
||||
--------------- |
||||
For the application the whole of U-Boot is built as a shared library. The |
||||
efi_main() function is in lib/efi/efi_app.c. It sets up some basic EFI |
||||
functions with efi_init(), sets up U-Boot global_data, allocates memory for |
||||
U-Boot's malloc(), etc. and enters the normal init sequence (board_init_f() |
||||
and board_init_r()). |
||||
|
||||
Since U-Boot limits its memory access to the allocated regions very little |
||||
special code is needed. The CONFIG_EFI_APP option controls a few things |
||||
that need to change so 'git grep CONFIG_EFI_APP' may be instructive. |
||||
The CONFIG_EFI option controls more general EFI adjustments. |
||||
|
||||
The only available driver is the serial driver. This calls back into EFI |
||||
'boot services' to send and receive characters. Although it is implemented |
||||
as a serial driver the console device is not necessarilly serial. If you |
||||
boot EFI with video output then the 'serial' device will operate on your |
||||
target devices's display instead and the device's USB keyboard will also |
||||
work if connected. If you have both serial and video output, then both |
||||
consoles will be active. Even though U-Boot does the same thing normally, |
||||
These are features of EFI, not U-Boot. |
||||
|
||||
Very little code is involved in implementing the EFI application feature. |
||||
U-Boot is highly portable. Most of the difficulty is in modifying the |
||||
Makefile settings to pass the right build flags. In particular there is very |
||||
little x86-specific code involved - you can find most of it in |
||||
arch/x86/cpu. Porting to ARM (which can also use EFI if you are brave |
||||
enough) should be straightforward. |
||||
|
||||
Use the 'reset' command to get back to EFI. |
||||
|
||||
EFI Payload |
||||
----------- |
||||
The payload approach is a different kettle of fish. It works by building |
||||
U-Boot exactly as normal for your target board, then adding the entire |
||||
image (including device tree) into a small EFI stub application responsible |
||||
for booting it. The stub application is built as a normal EFI application |
||||
except that it has a lot of data attached to it. |
||||
|
||||
The stub application is implemented in lib/efi/efi_stub.c. The efi_main() |
||||
function is called by EFI. It is responsible for copying U-Boot from its |
||||
original location into memory, disabling EFI boot services and starting |
||||
U-Boot. U-Boot then starts as normal, relocates, starts all drivers, etc. |
||||
|
||||
The stub application is architecture-dependent. At present it has some |
||||
x86-specific code and a comment at the top of efi_stub.c describes this. |
||||
|
||||
While the stub application does allocate some memory from EFI this is not |
||||
used by U-Boot (the payload). In fact when U-Boot starts it has all of the |
||||
memory available to it and can operate as it pleases (but see the next |
||||
section). |
||||
|
||||
Tables |
||||
------ |
||||
The payload can pass information to U-Boot in the form of EFI tables. At |
||||
present this feature is used to pass the EFI memory map, an inordinately |
||||
large list of memory regions. You can use the 'efi mem all' command to |
||||
display this list. U-Boot uses the list to work out where to relocate |
||||
itself. |
||||
|
||||
Although U-Boot can use any memory it likes, EFI marks some memory as used |
||||
by 'run-time services', code that hangs around while U-Boot is running and |
||||
is even present when Linux is running. This is common on x86 and provides |
||||
a way for Linux to call back into the firmware to control things like CPU |
||||
fan speed. U-Boot uses only 'conventional' memory, in EFI terminology. It |
||||
will relocate itself to the top of the largest block of memory it can find |
||||
below 4GB. |
||||
|
||||
Interrupts |
||||
---------- |
||||
U-Boot drivers typically don't use interrupts. Since EFI enables interrupts |
||||
it is possible that an interrupt will fire that U-Boot cannot handle. This |
||||
seems to cause problems. For this reason the U-Boot payload runs with |
||||
interrupts disabled at present. |
||||
|
||||
32/64-bit |
||||
--------- |
||||
While the EFI application can in principle be built as either 32- or 64-bit, |
||||
only 32-bit is currently supported. This means that the application can only |
||||
be used with 32-bit EFI. |
||||
|
||||
The payload stub can be build as either 32- or 64-bits. Only a small amount |
||||
of code is built this way (see the extra- line in lib/efi/Makefile). |
||||
Everything else is built as a normal U-Boot, so is always 32-bit on x86 at |
||||
present. |
||||
|
||||
Future work |
||||
----------- |
||||
This work could be extended in a number of ways: |
||||
|
||||
- Add a generic x86 EFI payload configuration. At present you need to modify |
||||
an existing one, but mostly the low-level x86 code is disabled when booting |
||||
on EFI anyway, so a generic 'EFI' board could be created with a suitable set |
||||
of drivers enabled. |
||||
|
||||
- Add ARM support |
||||
|
||||
- Add 64-bit application support |
||||
|
||||
- Figure out how to solve the interrupt problem |
||||
|
||||
- Add more drivers to the application side (e.g. video, block devices, USB, |
||||
environment access). This would mostly be an academic exercise as a strong |
||||
use case is not readily apparent, but it might be fun. |
||||
|
||||
- Avoid turning off boot services in the stub. Instead allow U-Boot to make |
||||
use of boot services in case it wants to. It is unclear what it might want |
||||
though. |
||||
|
||||
Where is the code? |
||||
------------------ |
||||
lib/efi |
||||
payload stub, application, support code. Mostly arch-neutral |
||||
|
||||
arch/x86/lib/efi |
||||
helper functions for the fake DRAM init, etc. These can be used by |
||||
any board that runs as a payload. |
||||
|
||||
arch/x86/cpu/efi |
||||
x86 support code for running as an EFI application |
||||
|
||||
board/efi/efi-x86/efi.c |
||||
x86 board code for running as an EFI application |
||||
|
||||
common/cmd_efi.c |
||||
the 'efi' command |
||||
|
||||
-- |
||||
Ben Stoltz, Simon Glass |
||||
Google, Inc |
||||
July 2015 |
||||
|
||||
[1] http://www.qemu.org |
||||
[2] http://www.tianocore.org/ovmf/ |
@ -0,0 +1,21 @@ |
||||
/*
|
||||
* Portable Executable and Common Object Constants |
||||
* |
||||
* Copyright (c) 2018 Heinrich Schuchardt |
||||
* |
||||
* based on the "Microsoft Portable Executable and Common Object File Format |
||||
* Specification", revision 11, 2017-01-23 |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0+ |
||||
*/ |
||||
|
||||
#ifndef _ASM_PE_H |
||||
#define _ASM_PE_H |
||||
|
||||
/* Subsystem type */ |
||||
#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 |
||||
#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 |
||||
#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 |
||||
#define IMAGE_SUBSYSTEM_EFI_ROM 13 |
||||
|
||||
#endif /* _ASM_PE_H */ |
Loading…
Reference in new issue