From mboxrd@z Thu Jan 1 00:00:00 1970 From: Alexander Graf Date: Tue, 2 Feb 2016 00:57:07 +0100 Subject: [U-Boot] [PATCH 06/14] efi_loader: Add runtime services In-Reply-To: References: <1452834380-164453-1-git-send-email-agraf@suse.de> <1452834380-164453-7-git-send-email-agraf@suse.de> Message-ID: <56AFF0D3.7000906@suse.de> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de On 01/31/2016 04:20 PM, Simon Glass wrote: > Hi Alexander, > > On 14 January 2016 at 22:06, 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. >> >> This patch adds enough framework for arbitrary code inside of U-Boot to become >> a runtime service with the right section attributes set. For now, we don't make >> use of it yet though. >> >> We could maybe in the future map U-boot environment variables to EFI variables >> here. >> >> Signed-off-by: Alexander Graf >> >> --- >> >> v1 -> v2: >> >> - Fix runtime service sections >> - Add runtime detach >> - Enable runtime relocations >> - Add get_time >> - Fix relocation >> - Fix 32bit >> - Add am335x support >> - Move section definition to header >> - Add systab to runtime section >> - Add self-relocation hook table >> - Fix self-relocation >> - Relocate efi_runtime section early during bootup >> - Fix return values for a number of callbacks to be more UEFI compliant >> - Move to GPLv2+ >> --- >> arch/arm/config.mk | 4 + >> arch/arm/cpu/armv8/u-boot.lds | 16 +++ >> arch/arm/cpu/u-boot.lds | 30 +++++ >> arch/arm/lib/sections.c | 4 + >> board/ti/am335x/u-boot.lds | 30 +++++ >> common/board_r.c | 4 + >> include/efi_loader.h | 10 ++ >> lib/efi_loader/efi_boottime.c | 6 +- >> lib/efi_loader/efi_runtime.c | 300 ++++++++++++++++++++++++++++++++++++++++++ >> 9 files changed, 401 insertions(+), 3 deletions(-) >> create mode 100644 lib/efi_loader/efi_runtime.c > Reviewed-by: Simon Glass > > A few nits. > >> diff --git a/arch/arm/config.mk b/arch/arm/config.mk >> index 0550225..ecb956d 100644 >> --- a/arch/arm/config.mk >> +++ b/arch/arm/config.mk >> @@ -120,6 +120,10 @@ ifdef CONFIG_OF_EMBED >> OBJCOPYFLAGS += -j .dtb.init.rodata >> endif >> >> +ifdef CONFIG_EFI_LOADER >> +OBJCOPYFLAGS += -j .efi_runtime -j .efi_runtime_rel >> +endif >> + >> ifneq ($(CONFIG_IMX_CONFIG),) >> ifdef CONFIG_SPL >> ifndef CONFIG_SPL_BUILD >> diff --git a/arch/arm/cpu/armv8/u-boot.lds b/arch/arm/cpu/armv8/u-boot.lds >> index 4c12222..fd15ad5 100644 >> --- a/arch/arm/cpu/armv8/u-boot.lds >> +++ b/arch/arm/cpu/armv8/u-boot.lds >> @@ -42,6 +42,22 @@ SECTIONS >> >> . = ALIGN(8); >> >> + .efi_runtime : { >> + __efi_runtime_start = .; >> + *(efi_runtime_text) >> + *(efi_runtime_data) >> + __efi_runtime_stop = .; >> + } >> + >> + .efi_runtime_rel : { >> + __efi_runtime_rel_start = .; >> + *(.relaefi_runtime_text) >> + *(.relaefi_runtime_data) >> + __efi_runtime_rel_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..596a17d 100644 >> --- a/arch/arm/cpu/u-boot.lds >> +++ b/arch/arm/cpu/u-boot.lds >> @@ -89,6 +89,36 @@ SECTIONS >> >> . = ALIGN(4); >> >> + .__efi_runtime_start : { >> + *(.__efi_runtime_start) >> + } >> + >> + .efi_runtime : { >> + *(efi_runtime_text) >> + *(efi_runtime_data) >> + } >> + >> + .__efi_runtime_stop : { >> + *(.__efi_runtime_stop) >> + } >> + >> + .efi_runtime_rel_start : >> + { >> + *(.__efi_runtime_rel_start) >> + } >> + >> + .efi_runtime_rel : { >> + *(.relefi_runtime_text) >> + *(.relefi_runtime_data) >> + } >> + >> + .efi_runtime_rel_stop : >> + { >> + *(.__efi_runtime_rel_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..6a94522 100644 >> --- a/arch/arm/lib/sections.c >> +++ b/arch/arm/lib/sections.c >> @@ -27,4 +27,8 @@ 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 __efi_runtime_rel_start[0] __attribute__((section(".__efi_runtime_rel_start"))); >> +char __efi_runtime_rel_stop[0] __attribute__((section(".__efi_runtime_rel_stop"))); >> char _end[0] __attribute__((section(".__end"))); >> diff --git a/board/ti/am335x/u-boot.lds b/board/ti/am335x/u-boot.lds >> index 78f294a..a56cc82 100644 >> --- a/board/ti/am335x/u-boot.lds >> +++ b/board/ti/am335x/u-boot.lds >> @@ -59,6 +59,36 @@ SECTIONS >> >> . = ALIGN(4); >> >> + .__efi_runtime_start : { >> + *(.__efi_runtime_start) >> + } >> + >> + .efi_runtime : { >> + *(efi_runtime_text) >> + *(efi_runtime_data) >> + } >> + >> + .__efi_runtime_stop : { >> + *(.__efi_runtime_stop) >> + } >> + >> + .efi_runtime_rel_start : >> + { >> + *(.__efi_runtime_rel_start) >> + } >> + >> + .efi_runtime_rel : { >> + *(.relefi_runtime_text) >> + *(.relefi_runtime_data) >> + } >> + >> + .efi_runtime_rel_stop : >> + { >> + *(.__efi_runtime_rel_stop) >> + } >> + >> + . = ALIGN(4); >> + >> .image_copy_end : >> { >> *(.__image_copy_end) >> diff --git a/common/board_r.c b/common/board_r.c >> index 75ee43e..420e2c8 100644 >> --- a/common/board_r.c >> +++ b/common/board_r.c >> @@ -64,6 +64,7 @@ >> #ifdef CONFIG_AVR32 >> #include >> #endif >> +#include >> >> DECLARE_GLOBAL_DATA_PTR; >> >> @@ -176,6 +177,9 @@ static int initr_reloc_global_data(void) >> */ >> gd->fdt_blob += gd->reloc_off; >> #endif >> +#ifdef CONFIG_EFI_LOADER >> + efi_runtime_relocate(gd->relocaddr, NULL); >> +#endif >> >> return 0; >> } >> diff --git a/include/efi_loader.h b/include/efi_loader.h >> index d314002..0f821ff 100644 >> --- a/include/efi_loader.h >> +++ b/include/efi_loader.h >> @@ -29,6 +29,7 @@ >> >> #define EFI_EXIT(ret) efi_exit_func(ret); >> >> +extern struct efi_runtime_services efi_runtime_services; >> extern struct efi_system_table systab; >> >> extern const struct efi_simple_text_output_protocol efi_con_out; >> @@ -39,6 +40,9 @@ 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; >> +extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop; >> + >> struct efi_class_map { >> const efi_guid_t *guid; >> const void *interface; >> @@ -68,12 +72,18 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info); >> void efi_save_gd(void); >> void efi_restore_gd(void); >> efi_status_t efi_exit_func(efi_status_t ret); >> +void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map); > Function comment please. > >> #define EFI_LOADER_POOL_SIZE (128 * 1024 * 1024) >> void *efi_loader_alloc(uint64_t len); >> >> +#define EFI_RUNTIME_DATA __attribute__ ((section ("efi_runtime_data"))) >> +#define EFI_RUNTIME_TEXT __attribute__ ((section ("efi_runtime_text"))) >> + >> #else /* defined(EFI_LOADER) */ >> >> +#define EFI_RUNTIME_DATA >> +#define EFI_RUNTIME_TEXT >> static inline void efi_restore_gd(void) { } >> >> #endif >> diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c >> index 5756c9c..45217ef 100644 >> --- a/lib/efi_loader/efi_boottime.c >> +++ b/lib/efi_loader/efi_boottime.c >> @@ -36,7 +36,7 @@ static bool efi_is_direct_boot = true; >> * In most cases we want to pass an FDT to the payload, so reserve one slot of >> * config table space for it. The pointer gets populated by do_bootefi_exec(). >> */ >> -static struct efi_configuration_table efi_conf_table[] = { >> +static struct efi_configuration_table EFI_RUNTIME_DATA efi_conf_table[] = { >> { >> .guid = EFI_FDT_GUID, >> }, >> @@ -741,10 +741,10 @@ static const struct efi_boot_services efi_boot_services = { >> }; >> >> >> -static uint16_t firmware_vendor[] = >> +static uint16_t EFI_RUNTIME_DATA firmware_vendor[] = >> { 'D','a','s',' ','U','-','b','o','o','t',0 }; >> >> -struct efi_system_table systab = { >> +struct efi_system_table EFI_RUNTIME_DATA systab = { >> .hdr = { >> .signature = EFI_SYSTEM_TABLE_SIGNATURE, >> .revision = 0x20005, /* 2.5 */ >> diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c >> new file mode 100644 >> index 0000000..b7aa1e9 >> --- /dev/null >> +++ b/lib/efi_loader/efi_runtime.c >> @@ -0,0 +1,300 @@ >> +/* >> + * EFI application runtime services >> + * >> + * Copyright (c) 2016 Alexander Graf >> + * >> + * SPDX-License-Identifier: GPL-2.0+ >> + */ >> + >> +#include > You use driver model so need too. > >> +#include >> +#include >> +#include >> +#include >> + >> +/* For manual relocation support */ >> +DECLARE_GLOBAL_DATA_PTR; >> + >> +static efi_status_t EFI_RUNTIME_TEXT efi_unimplemented(void); >> +static efi_status_t EFI_RUNTIME_TEXT efi_device_error(void); >> +static efi_status_t EFI_RUNTIME_TEXT efi_invalid_parameter(void); >> + >> +#if defined(CONFIG_ARM64) >> +#define R_RELATIVE 1027 >> +#define R_MASK 0xffffffffULL >> +#define IS_RELA 1 >> +#elif defined(CONFIG_ARM) >> +#define R_RELATIVE 23 >> +#define R_MASK 0xffULL >> +#else >> +#error Need to add relocation awareness >> +#endif >> + >> +struct elf_rel { >> + ulong *offset; >> + ulong info; >> +}; >> + >> +struct elf_rela { >> + ulong *offset; >> + ulong info; >> + long addend; >> +}; > Can you use elf.h? I could, but elf.h has a hard distinction between 32bit and 64bit binaries while I really just want the one the binary is actually using at this specific moment. So I could add #ifdefs on 32bit vs 64bit and then use the elf.h defines instead, but I'm not sure the code would look any more readable than it is now after that ;). > >> + >> +/* >> + * EFI Runtime code lives in 2 stages. In the first stage, U-Boot and an EFI >> + * payload are running concurrently at the same time. In this mode, we can >> + * handle a good number of runtime callbacks >> + */ >> + >> +static void efi_reset_system(enum efi_reset_type reset_type, >> + efi_status_t reset_status, unsigned long data_size, >> + void *reset_data) >> +{ >> + EFI_ENTRY("%d %lx %lx %p", reset_type, reset_status, data_size, reset_data); >> + >> + switch (reset_type) { >> + case EFI_RESET_COLD: >> + case EFI_RESET_WARM: >> + do_reset(NULL, 0, 0, NULL); >> + break; >> + case EFI_RESET_SHUTDOWN: >> + /* We don't have anything to map this to */ >> + break; >> + } >> + >> + EFI_EXIT(EFI_SUCCESS); >> +} >> + >> +static efi_status_t efi_get_time(struct efi_time *time, >> + struct efi_time_cap *capabilities) >> +{ >> +#ifdef CONFIG_CMD_DATE >> + >> + struct rtc_time tm; >> + int r; >> +#ifdef CONFIG_DM_RTC > Since this is a new service I don't think you need to support the old RTC API. ok Alex