summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS3
-rw-r--r--arch/arm/lib/crt0_aarch64_efi.S4
-rw-r--r--arch/arm/lib/crt0_arm_efi.S4
-rw-r--r--cmd/bootefi.c2
-rw-r--r--doc/README.efi275
-rw-r--r--doc/README.u-boot_on_efi259
-rw-r--r--include/asm-generic/pe.h21
-rw-r--r--include/efi_api.h37
-rw-r--r--include/efi_loader.h4
-rw-r--r--include/pe.h8
-rw-r--r--lib/efi_driver/efi_uclass.c6
-rw-r--r--lib/efi_loader/efi_boottime.c35
-rw-r--r--lib/efi_loader/efi_disk.c71
-rw-r--r--lib/efi_loader/efi_image_loader.c2
-rw-r--r--lib/efi_loader/efi_runtime.c29
-rw-r--r--lib/efi_selftest/Makefile6
16 files changed, 453 insertions, 313 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index be941c1e99..d2f8c513e0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -289,8 +289,11 @@ EFI PAYLOAD
M: Alexander Graf <agraf@suse.de>
S: Maintained
T: git git://github.com/agraf/u-boot.git
+F: doc/README.efi
F: doc/README.iscsi
F: include/efi*
+F: include/pe.h
+F: include/asm-generic/pe.h
F: lib/efi*/
F: test/py/tests/test_efi*
F: cmd/bootefi.c
diff --git a/arch/arm/lib/crt0_aarch64_efi.S b/arch/arm/lib/crt0_aarch64_efi.S
index 52056469be..9b0e894f8a 100644
--- a/arch/arm/lib/crt0_aarch64_efi.S
+++ b/arch/arm/lib/crt0_aarch64_efi.S
@@ -8,6 +8,8 @@
* This file is taken and modified from the gnu-efi project.
*/
+#include <asm-generic/pe.h>
+
.section .text.head
/*
@@ -62,7 +64,7 @@ extra_header_fields:
*/
.long _start - ImageBase /* SizeOfHeaders */
.long 0 /* CheckSum */
- .short EFI_SUBSYSTEM /* Subsystem */
+ .short IMAGE_SUBSYSTEM_EFI_APPLICATION /* Subsystem */
.short 0 /* DllCharacteristics */
.quad 0 /* SizeOfStackReserve */
.quad 0 /* SizeOfStackCommit */
diff --git a/arch/arm/lib/crt0_arm_efi.S b/arch/arm/lib/crt0_arm_efi.S
index 967c885982..af55bba4ba 100644
--- a/arch/arm/lib/crt0_arm_efi.S
+++ b/arch/arm/lib/crt0_arm_efi.S
@@ -8,6 +8,8 @@
* This file is taken and modified from the gnu-efi project.
*/
+#include <asm-generic/pe.h>
+
.section .text.head
/*
@@ -64,7 +66,7 @@ extra_header_fields:
*/
.long _start - image_base /* SizeOfHeaders */
.long 0 /* CheckSum */
- .short EFI_SUBSYSTEM /* Subsystem */
+ .short IMAGE_SUBSYSTEM_EFI_APPLICATION /* Subsystem */
.short 0 /* DllCharacteristics */
.long 0 /* SizeOfStackReserve */
.long 0 /* SizeOfStackCommit */
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 4233d36b72..2106ed9c8c 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -411,7 +411,7 @@ static char bootefi_help_text[] =
" Use environment variable efi_selftest to select a single test.\n"
" Use 'setenv efi_selftest list' to enumerate all tests.\n"
#endif
- "bootmgr [fdt addr]\n"
+ "bootefi bootmgr [fdt addr]\n"
" - load and boot EFI payload based on BootOrder/BootXXXX variables.\n"
"\n"
" If specified, the device tree located at <fdt address> gets\n"
diff --git a/doc/README.efi b/doc/README.efi
index 66259f3e26..956f5bfa0c 100644
--- a/doc/README.efi
+++ b/doc/README.efi
@@ -4,279 +4,24 @@
# SPDX-License-Identifier: GPL-2.0+
#
-=========== Table of Contents ===========
-
- 1 U-Boot on EFI
- 1.1 In God's Name, Why?
- 1.2 Status
- 1.3 Build Instructions
- 1.4 Trying it out
- 1.5 Inner workings
- 1.6 EFI Application
- 1.7 EFI Payload
- 1.8 Tables
- 1.9 Interrupts
- 1.10 32/64-bit
- 1.11 Future work
- 1.12 Where is the code?
-
- 2 EFI on U-Boot
- 2.1 In God's Name, Why?
- 2.2 How do I get it?
- 2.3 Status
- 2.4 Future work
-
-U-Boot on EFI
+EFI on U-Boot
=============
-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.
-
-
-In God's Name, Why?
--------------------
-This 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
+This document provides information about the implementation of the UEFI API [1]
+in U-Boot.
-- 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
+=========== Table of Contents ===========
+Motivation
+How do I get it?
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/
-
--------------------------------------------------------------------------------
-
-EFI on U-Boot
-=============
-
-In addition to support for running U-Boot as a UEFI application, U-Boot itself
-can also expose the UEFI interfaces and thus allow UEFI payloads to run under
-it.
-
-In God's Name, Why?
--------------------
+Motivation
+----------
-With this support in place, you can run any UEFI payload (such as the Linux
+With this API support in place, you can run any UEFI payload (such as the Linux
kernel, grub2 or gummiboot) on U-Boot. This dramatically simplifies boot loader
configuration, as U-Boot based systems now look and feel (almost) the same way
as TianoCore based systems.
@@ -337,3 +82,5 @@ have)
- Network device support
- Support for payload exit
- Payload Watchdog support
+
+[1] http://uefi.org/
diff --git a/doc/README.u-boot_on_efi b/doc/README.u-boot_on_efi
new file mode 100644
index 0000000000..298b94e342
--- /dev/null
+++ b/doc/README.u-boot_on_efi
@@ -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/
diff --git a/include/asm-generic/pe.h b/include/asm-generic/pe.h
new file mode 100644
index 0000000000..d1683f238a
--- /dev/null
+++ b/include/asm-generic/pe.h
@@ -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 */
diff --git a/include/efi_api.h b/include/efi_api.h
index 205f8f1f70..3ba650e57e 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -166,7 +166,14 @@ struct efi_boot_services {
void (EFIAPI *copy_mem)(void *destination, const void *source,
size_t length);
void (EFIAPI *set_mem)(void *buffer, size_t size, uint8_t value);
- void *create_event_ex;
+ efi_status_t (EFIAPI *create_event_ex)(
+ uint32_t type, efi_uintn_t notify_tpl,
+ void (EFIAPI *notify_function) (
+ struct efi_event *event,
+ void *context),
+ void *notify_context,
+ efi_guid_t *event_group,
+ struct efi_event **event);
};
/* Types and defines for EFI ResetSystem */
@@ -180,6 +187,17 @@ enum efi_reset_type {
#define EFI_RUNTIME_SERVICES_SIGNATURE 0x5652453544e5552ULL
#define EFI_RUNTIME_SERVICES_REVISION 0x00010000
+#define CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x00010000
+#define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000
+#define CAPSULE_FLAGS_INITIATE_RESET 0x00040000
+
+struct efi_capsule_header {
+ efi_guid_t *capsule_guid;
+ u32 header_size;
+ u32 flags;
+ u32 capsule_image_size;
+};
+
struct efi_runtime_services {
struct efi_table_hdr hdr;
efi_status_t (EFIAPI *get_time)(struct efi_time *time,
@@ -209,9 +227,20 @@ struct efi_runtime_services {
void (EFIAPI *reset_system)(enum efi_reset_type reset_type,
efi_status_t reset_status,
unsigned long data_size, void *reset_data);
- void *update_capsule;
- void *query_capsule_caps;
- void *query_variable_info;
+ efi_status_t (EFIAPI *update_capsule)(
+ struct efi_capsule_header **capsule_header_array,
+ efi_uintn_t capsule_count,
+ u64 scatter_gather_list);
+ efi_status_t (EFIAPI *query_capsule_caps)(
+ struct efi_capsule_header **capsule_header_array,
+ efi_uintn_t capsule_count,
+ u64 maximum_capsule_size,
+ u32 reset_type);
+ efi_status_t (EFIAPI *query_variable_info)(
+ u32 attributes,
+ u64 maximum_variable_storage_size,
+ u64 remaining_variable_storage_size,
+ u64 maximum_variable_size);
};
/* EFI Configuration Table and GUID definitions */
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 21c03c5c28..07730c3f39 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -173,7 +173,7 @@ extern struct list_head efi_obj_list;
/* Called by bootefi to make console interface available */
int efi_console_register(void);
/* Called by bootefi to make all disk storage accessible as EFI objects */
-int efi_disk_register(void);
+efi_status_t efi_disk_register(void);
/* Create handles and protocols for the partitions of a block device */
int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
const char *if_typename, int diskid,
@@ -272,7 +272,7 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size,
uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
bool overlap_only_ram);
/* Called by board init to initialize the EFI drivers */
-int efi_driver_init(void);
+efi_status_t efi_driver_init(void);
/* Called by board init to initialize the EFI memory map */
int efi_memory_init(void);
/* Adds new or overrides configuration table entry to the system table */
diff --git a/include/pe.h b/include/pe.h
index 4ef3e92efa..c3a19cef76 100644
--- a/include/pe.h
+++ b/include/pe.h
@@ -11,6 +11,8 @@
#ifndef _PE_H
#define _PE_H
+#include <asm-generic/pe.h>
+
typedef struct _IMAGE_DOS_HEADER {
uint16_t e_magic; /* 00: MZ Header signature */
uint16_t e_cblp; /* 02: Bytes on last page of file */
@@ -62,12 +64,6 @@ typedef struct _IMAGE_DATA_DIRECTORY {
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
-/* PE32+ Subsystem type for EFI images */
-#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10
-#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
-#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12
-#define IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13
-
typedef struct _IMAGE_OPTIONAL_HEADER64 {
uint16_t Magic; /* 0x20b */
uint8_t MajorLinkerVersion;
diff --git a/lib/efi_driver/efi_uclass.c b/lib/efi_driver/efi_uclass.c
index 90797f96d8..46b69b479c 100644
--- a/lib/efi_driver/efi_uclass.c
+++ b/lib/efi_driver/efi_uclass.c
@@ -287,10 +287,10 @@ out:
*
* @return 0 = success, any other value will stop further execution
*/
-int efi_driver_init(void)
+efi_status_t efi_driver_init(void)
{
struct driver *drv;
- int ret = 0;
+ efi_status_t ret = EFI_SUCCESS;
/* Save 'gd' pointer */
efi_save_gd();
@@ -300,7 +300,7 @@ int efi_driver_init(void)
drv < ll_entry_end(struct driver, driver); ++drv) {
if (drv->id == UCLASS_EFI) {
ret = efi_add_driver(drv);
- if (ret) {
+ if (ret != EFI_SUCCESS) {
printf("EFI: ERROR: failed to add driver %s\n",
drv->name);
break;
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index da93498b36..6eea2395c7 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -526,6 +526,38 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
}
/*
+ * Create an event in a group.
+ *
+ * This function implements the CreateEventEx service.
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ * TODO: Support event groups
+ *
+ * @type type of the event to create
+ * @notify_tpl task priority level of the event
+ * @notify_function notification function of the event
+ * @notify_context pointer passed to the notification function
+ * @event created event
+ * @event_group event group
+ * @return status code
+ */
+efi_status_t EFIAPI efi_create_event_ex(uint32_t type, efi_uintn_t notify_tpl,
+ void (EFIAPI *notify_function) (
+ struct efi_event *event,
+ void *context),
+ void *notify_context,
+ efi_guid_t *event_group,
+ struct efi_event **event)
+{
+ EFI_ENTRY("%d, 0x%zx, %p, %p, %pUl", type, notify_tpl, notify_function,
+ notify_context, event_group);
+ if (event_group)
+ return EFI_EXIT(EFI_UNSUPPORTED);
+ return EFI_EXIT(efi_create_event(type, notify_tpl, notify_function,
+ notify_context, event));
+}
+
+/*
* Create an event.
*
* This function implements the CreateEvent service.
@@ -2851,6 +2883,7 @@ static const struct efi_boot_services efi_boot_services = {
.calculate_crc32 = efi_calculate_crc32,
.copy_mem = efi_copy_mem,
.set_mem = efi_set_mem,
+ .create_event_ex = efi_create_event_ex,
};
@@ -2859,7 +2892,7 @@ static uint16_t __efi_runtime_data firmware_vendor[] = L"Das U-Boot";
struct efi_system_table __efi_runtime_data systab = {
.hdr = {
.signature = EFI_SYSTEM_TABLE_SIGNATURE,
- .revision = 0x20005, /* 2.5 */
+ .revision = 2 << 16 | 70, /* 2.7 */
.headersize = sizeof(struct efi_table_hdr),
},
.fw_vendor = (long)firmware_vendor,
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index ac39a65ee8..825a6d86de 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -226,25 +226,26 @@ efi_fs_from_path(struct efi_device_path *full_path)
* @offset offset into disk for simple partitions
* @return disk object
*/
-static struct efi_disk_obj *efi_disk_add_dev(
+static efi_status_t efi_disk_add_dev(
efi_handle_t parent,
struct efi_device_path *dp_parent,
const char *if_typename,
struct blk_desc *desc,
int dev_index,
lbaint_t offset,
- unsigned int part)
+ unsigned int part,
+ struct efi_disk_obj **disk)
{
struct efi_disk_obj *diskobj;
efi_status_t ret;
/* Don't add empty devices */
if (!desc->lba)
- return NULL;
+ return EFI_NOT_READY;
diskobj = calloc(1, sizeof(*diskobj));
if (!diskobj)
- goto out_of_memory;
+ return EFI_OUT_OF_RESOURCES;
/* Hook up to the device list */
efi_add_handle(&diskobj->parent);
@@ -262,11 +263,11 @@ static struct efi_disk_obj *efi_disk_add_dev(
ret = efi_add_protocol(diskobj->parent.handle, &efi_block_io_guid,
&diskobj->ops);
if (ret != EFI_SUCCESS)
- goto out_of_memory;
+ return ret;
ret = efi_add_protocol(diskobj->parent.handle, &efi_guid_device_path,
diskobj->dp);
if (ret != EFI_SUCCESS)
- goto out_of_memory;
+ return ret;
if (part >= 1) {
diskobj->volume = efi_simple_file_system(desc, part,
diskobj->dp);
@@ -274,7 +275,7 @@ static struct efi_disk_obj *efi_disk_add_dev(
&efi_simple_file_system_protocol_guid,
diskobj->volume);
if (ret != EFI_SUCCESS)
- goto out_of_memory;
+ return ret;
}
diskobj->ops = block_io_disk_template;
diskobj->ifname = if_typename;
@@ -291,10 +292,9 @@ static struct efi_disk_obj *efi_disk_add_dev(
if (part != 0)
diskobj->media.logical_partition = 1;
diskobj->ops.media = &diskobj->media;
- return diskobj;
-out_of_memory:
- printf("ERROR: Out of memory\n");
- return NULL;
+ if (disk)
+ *disk = diskobj;
+ return EFI_SUCCESS;
}
/*
@@ -330,8 +330,12 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
continue;
snprintf(devname, sizeof(devname), "%s:%d", pdevname,
part);
- efi_disk_add_dev(parent, dp, if_typename, desc, diskid,
- info.start, part);
+ ret = efi_disk_add_dev(parent, dp, if_typename, desc, diskid,
+ info.start, part, NULL);
+ if (ret != EFI_SUCCESS) {
+ printf("Adding partition %s failed\n", pdevname);
+ continue;
+ }
disks++;
}
@@ -349,26 +353,32 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
*
* This gets called from do_bootefi_exec().
*/
-int efi_disk_register(void)
+efi_status_t efi_disk_register(void)
{
struct efi_disk_obj *disk;
int disks = 0;
+ efi_status_t ret;
#ifdef CONFIG_BLK
struct udevice *dev;
- for (uclass_first_device_check(UCLASS_BLK, &dev);
- dev;
+ for (uclass_first_device_check(UCLASS_BLK, &dev); dev;
uclass_next_device_check(&dev)) {
struct blk_desc *desc = dev_get_uclass_platdata(dev);
const char *if_typename = blk_get_if_type_name(desc->if_type);
- printf("Scanning disk %s...\n", dev->name);
-
/* Add block device for the full device */
- disk = efi_disk_add_dev(NULL, NULL, if_typename,
- desc, desc->devnum, 0, 0);
- if (!disk)
- return -ENOMEM;
+ printf("Scanning disk %s...\n", dev->name);
+ ret = efi_disk_add_dev(NULL, NULL, if_typename,
+ desc, desc->devnum, 0, 0, &disk);
+ if (ret == EFI_NOT_READY) {
+ printf("Disk %s not ready\n", dev->name);
+ continue;
+ }
+ if (ret) {
+ printf("ERROR: failure to add disk device %s, r = %lu\n",
+ dev->name, ret & ~EFI_ERROR_MASK);
+ return ret;
+ }
disks++;
/* Partitions show up as block devices in EFI */
@@ -404,10 +414,17 @@ int efi_disk_register(void)
if_typename, i);
/* Add block device for the full device */
- disk = efi_disk_add_dev(NULL, NULL, if_typename, desc,
- i, 0, 0);
- if (!disk)
- return -ENOMEM;
+ ret = efi_disk_add_dev(NULL, NULL, if_typename, desc,
+ i, 0, 0, &disk);
+ if (ret == EFI_NOT_READY) {
+ printf("Disk %s not ready\n", devname);
+ continue;
+ }
+ if (ret) {
+ printf("ERROR: failure to add disk device %s, r = %lu\n",
+ devname, ret & ~EFI_ERROR_MASK);
+ return ret;
+ }
disks++;
/* Partitions show up as block devices in EFI */
@@ -419,5 +436,5 @@ int efi_disk_register(void)
#endif
printf("Found %d disks\n", disks);
- return 0;
+ return EFI_SUCCESS;
}
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index 9d2214b481..cac64ba9fe 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -94,7 +94,7 @@ static void efi_set_code_and_data_type(
loaded_image_info->image_data_type = EFI_BOOT_SERVICES_DATA;
break;
case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
- case IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:
+ case IMAGE_SUBSYSTEM_EFI_ROM:
loaded_image_info->image_code_type = EFI_RUNTIME_SERVICES_CODE;
loaded_image_info->image_data_type = EFI_RUNTIME_SERVICES_DATA;
break;
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
index 8104e08c46..ccb4fc6141 100644
--- a/lib/efi_loader/efi_runtime.c
+++ b/lib/efi_loader/efi_runtime.c
@@ -381,6 +381,32 @@ static efi_status_t __efi_runtime EFIAPI efi_invalid_parameter(void)
return EFI_INVALID_PARAMETER;
}
+efi_status_t __efi_runtime EFIAPI efi_update_capsule(
+ struct efi_capsule_header **capsule_header_array,
+ efi_uintn_t capsule_count,
+ u64 scatter_gather_list)
+{
+ return EFI_UNSUPPORTED;
+}
+
+efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps(
+ struct efi_capsule_header **capsule_header_array,
+ efi_uintn_t capsule_count,
+ u64 maximum_capsule_size,
+ u32 reset_type)
+{
+ return EFI_UNSUPPORTED;
+}
+
+efi_status_t __efi_runtime EFIAPI efi_query_variable_info(
+ u32 attributes,
+ u64 maximum_variable_storage_size,
+ u64 remaining_variable_storage_size,
+ u64 maximum_variable_size)
+{
+ return EFI_UNSUPPORTED;
+}
+
struct efi_runtime_services __efi_runtime_data efi_runtime_services = {
.hdr = {
.signature = EFI_RUNTIME_SERVICES_SIGNATURE,
@@ -398,4 +424,7 @@ struct efi_runtime_services __efi_runtime_data efi_runtime_services = {
.set_variable = efi_set_variable,
.get_next_high_mono_count = (void *)&efi_device_error,
.reset_system = &efi_reset_system_boottime,
+ .update_capsule = efi_update_capsule,
+ .query_capsule_caps = efi_query_capsule_caps,
+ .query_variable_info = efi_query_variable_info,
};
diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
index 90246f7827..c4bdbdf6c0 100644
--- a/lib/efi_selftest/Makefile
+++ b/lib/efi_selftest/Makefile
@@ -7,8 +7,10 @@
# This file only gets included with CONFIG_EFI_LOADER set, so all
# object inclusion implicitly depends on it
-CFLAGS_efi_selftest_miniapp.o := $(CFLAGS_EFI) -Os -ffreestanding
-CFLAGS_REMOVE_efi_selftest_miniapp.o := $(CFLAGS_NON_EFI) -Os
+CFLAGS_efi_selftest_miniapp_exit.o := $(CFLAGS_EFI) -Os -ffreestanding
+CFLAGS_REMOVE_efi_selftest_miniapp_exit.o := $(CFLAGS_NON_EFI) -Os
+CFLAGS_efi_selftest_miniapp_return.o := $(CFLAGS_EFI) -Os -ffreestanding
+CFLAGS_REMOVE_efi_selftest_miniapp_return.o := $(CFLAGS_NON_EFI) -Os
obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += \
efi_selftest.o \