
On Tue, Dec 22, 2015 at 02:57:53PM +0100, Alexander Graf wrote:
After booting has finished, EFI allows firmware to still interact with the OS using the "runtime services". These callbacks live in a separate address space, since they are available long after U-Boot has been overwritten by the OS.
However, since U-Boot has no notion of RTS, we just create an extremely minimal RTS stub that just declares all functions as unsupported. We could in the future map U-boot environment variables to EFI variables here.
Signed-off-by: Alexander Graf agraf@suse.de
arch/arm/cpu/armv8/u-boot.lds | 8 ++++++ arch/arm/cpu/u-boot.lds | 13 ++++++++++ arch/arm/lib/sections.c | 2 ++ include/efi_loader.h | 3 +++ lib/efi_loader/efi_runtime.c | 59 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+) create mode 100644 lib/efi_loader/efi_runtime.c
diff --git a/arch/arm/cpu/armv8/u-boot.lds b/arch/arm/cpu/armv8/u-boot.lds index 4c12222..7c5b032 100644 --- a/arch/arm/cpu/armv8/u-boot.lds +++ b/arch/arm/cpu/armv8/u-boot.lds @@ -42,6 +42,14 @@ SECTIONS
. = ALIGN(8);
- .efi_runtime : {
__efi_runtime_start = .;
*(efi_runtime)
__efi_runtime_stop = .;
- }
- . = ALIGN(8);
- .image_copy_end : { *(.__image_copy_end)
diff --git a/arch/arm/cpu/u-boot.lds b/arch/arm/cpu/u-boot.lds index d48a905..b5198d0 100644 --- a/arch/arm/cpu/u-boot.lds +++ b/arch/arm/cpu/u-boot.lds @@ -89,6 +89,19 @@ SECTIONS
. = ALIGN(4);
- .__efi_runtime_start : {
*(.__efi_runtime_start)
- }
- .efi_runtime : {
*(efi_runtime)
- }
- .__efi_runtime_stop : {
*(.__efi_runtime_stop)
- }
- . = ALIGN(4);
- .image_copy_end : { *(.__image_copy_end)
diff --git a/arch/arm/lib/sections.c b/arch/arm/lib/sections.c index a1205c3..21b3066 100644 --- a/arch/arm/lib/sections.c +++ b/arch/arm/lib/sections.c @@ -27,4 +27,6 @@ char __rel_dyn_start[0] __attribute__((section(".__rel_dyn_start"))); char __rel_dyn_end[0] __attribute__((section(".__rel_dyn_end"))); char __secure_start[0] __attribute__((section(".__secure_start"))); char __secure_end[0] __attribute__((section(".__secure_end"))); +char __efi_runtime_start[0] __attribute__((section(".__efi_runtime_start"))); +char __efi_runtime_stop[0] __attribute__((section(".__efi_runtime_stop"))); char _end[0] __attribute__((section(".__end"))); diff --git a/include/efi_loader.h b/include/efi_loader.h index 7fb2106..af1c88f 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -39,6 +39,7 @@
#define EFI_EXIT(ret) efi_exit_func(ret);
+extern const struct efi_runtime_services efi_runtime_services; extern struct efi_system_table systab;
extern const struct efi_simple_text_output_protocol efi_con_out; @@ -49,6 +50,8 @@ extern const efi_guid_t efi_guid_console_control; extern const efi_guid_t efi_guid_device_path; extern const efi_guid_t efi_guid_loaded_image;
+extern unsigned int __efi_runtime_start, __efi_runtime_stop;
struct efi_class_map { const efi_guid_t *guid; const void *interface; diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c new file mode 100644 index 0000000..214e1f5 --- /dev/null +++ b/lib/efi_loader/efi_runtime.c @@ -0,0 +1,59 @@ +/*
- EFI application runtime services
- Copyright (c) 2015 Alexander Graf
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- SPDX-License-Identifier: LGPL-2.1+
- */
+#include <common.h> +#include <efi_loader.h>
+/*
- EFI Runtime code is still alive when U-Boot is long overwritten. To isolate
- this code from the rest, we put it into a special section.
!!WARNING!!
- This means that we can not rely on any code outside of this file at runtime.
- Please keep it fully self-contained.
- */
+asm(".section efi_runtime,"a"");
+static efi_status_t efi_unimplemented(void) +{
- return EFI_UNSUPPORTED;
Again, EFI_UNSUPPORTED is not necessarily a valid return value for all runtime services.
+}
+const struct efi_runtime_services efi_runtime_services = {
- .hdr = {
.signature = EFI_RUNTIME_SERVICES_SIGNATURE,
.revision = EFI_RUNTIME_SERVICES_REVISION,
.headersize = sizeof(struct efi_table_hdr),
- },
- .get_time = (void *)&efi_unimplemented,
EFI_DEVICE_ERROR
- .set_time = (void *)&efi_unimplemented,
EFI_DEVICE_ERROR
- .get_wakeup_time = (void *)&efi_unimplemented,
- .set_wakeup_time = (void *)&efi_unimplemented,
Both of these are fine, and correct, to return EFI_UNSUPPORTED.
- .set_virtual_address_map = (void *)&efi_unimplemented,
- .convert_pointer = (void *)&efi_unimplemented,
There really isn't a way to gracefully decline these two functions. All valid error codes refer to invalid inputs.
- .get_variable = (void *)&efi_unimplemented,
EFI_DEVICE_ERROR would probably be the closest thing to a correct return code in this instance.
- .get_next_variable = (void *)&efi_unimplemented,
(get_next_variable_name?) Again, EFI_DEVICE_ERROR, is probably the least wrong return value.
- .set_variable = (void *)&efi_unimplemented,
EFI_DEVICE_ERROR
- .get_next_high_mono_count = (void *)&efi_unimplemented,
EFI_DEVICE_ERROR
- .reset_system = (void *)&efi_unimplemented,
"The ResetSystem() function does not return."
+};
2.1.4