[PATCH 2/7] efi: Allow runtime relocate to be disabled

Ilias Apalodimas ilias.apalodimas at linaro.org
Tue May 21 15:58:48 CEST 2024


Hi Jiaxun,

On Fri, 17 May 2024 at 19:33, Jiaxun Yang <jiaxun.yang at flygoat.com> wrote:
>
> Allow runtime relocate to be disabled because on MIPS we
> never do that. It's guaranteed that OS won't call
> set_virtual_address_map and convert_pointer as well.

Who guarantees that? Is it only for Linux?

>
> On MIPS KSEG0 is always mapped to memory and there is no
> way to disable it for kernel mode. Both EFI runtime and
> kernel lays in this segment, so relocation is totally
> unnecessary.
>
> Also U-Boot does not use traditional .dyn.rel to perform
> relocation on MIPS, that makes implementation of runtime
> relocation pretty hard.

It already works on other architectures so I suppose it's only a
matter of adding it?

Thanks
/Ilias
>
> Signed-off-by: Jiaxun Yang <jiaxun.yang at flygoat.com>
> ---
>  include/efi_loader.h              | 26 ++++++++++++++++++--------
>  lib/efi_loader/Kconfig            | 10 ++++++++++
>  lib/efi_loader/efi_image_loader.c |  1 +
>  lib/efi_loader/efi_memory.c       | 14 +++++++++++---
>  lib/efi_loader/efi_runtime.c      | 11 ++++++++++-
>  lib/efi_loader/efi_var_mem.c      |  6 +++++-
>  lib/efi_selftest/Makefile         |  2 +-
>  7 files changed, 56 insertions(+), 14 deletions(-)
>
> diff --git a/include/efi_loader.h b/include/efi_loader.h
> index 9600941aa327..1ae62906e099 100644
> --- a/include/efi_loader.h
> +++ b/include/efi_loader.h
> @@ -31,7 +31,7 @@ static inline void *guidcpy(void *dst, const void *src)
>         return memcpy(dst, src, sizeof(efi_guid_t));
>  }
>
> -#if CONFIG_IS_ENABLED(EFI_LOADER)
> +#if CONFIG_IS_ENABLED(EFI_LOADER) && CONFIG_IS_ENABLED(EFI_RUNTIME_RELOCATE)
>
>  /**
>   * __efi_runtime_data - declares a non-const variable for EFI runtime section
> @@ -79,6 +79,23 @@ static inline void *guidcpy(void *dst, const void *src)
>   */
>  #define __efi_runtime __section(".text.efi_runtime")
>
> +/* Call this to relocate the runtime section to an address space */
> +void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map);
> +
> +#else /* CONFIG_IS_ENABLED(EFI_LOADER) && CONFIG_IS_ENABLED(EFI_RUNTIME_RELOCATE) */
> +
> +/* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */
> +#define __efi_runtime_data
> +#define __efi_runtime_rodata
> +#define __efi_runtime
> +
> +static inline void efi_runtime_relocate(ulong offset,
> +                                       struct efi_mem_desc *map) {};
> +
> +#endif /* CONFIG_IS_ENABLED(EFI_LOADER) && CONFIG_IS_ENABLED(EFI_RUNTIME_RELOCATE) */
> +
> +#if CONFIG_IS_ENABLED(EFI_LOADER)
> +
>  /*
>   * Call this with mmio_ptr as the _pointer_ to a pointer to an MMIO region
>   * to make it available at runtime
> @@ -101,10 +118,6 @@ efi_status_t efi_launch_capsules(void);
>
>  #else /* CONFIG_IS_ENABLED(EFI_LOADER) */
>
> -/* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */
> -#define __efi_runtime_data
> -#define __efi_runtime_rodata
> -#define __efi_runtime
>  static inline efi_status_t efi_add_runtime_mmio(void *mmio_ptr, u64 len)
>  {
>         return EFI_SUCCESS;
> @@ -118,7 +131,6 @@ static inline efi_status_t efi_launch_capsules(void)
>  {
>         return EFI_SUCCESS;
>  }
> -
>  #endif /* CONFIG_IS_ENABLED(EFI_LOADER) */
>
>  #if CONFIG_IS_ENABLED(EFI_BINARY_EXEC)
> @@ -641,8 +653,6 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle,
>                          struct efi_loaded_image *loaded_image_info);
>  /* Called once to store the pristine gd pointer */
>  void efi_save_gd(void);
> -/* Call this to relocate the runtime section to an address space */
> -void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map);
>  /* Call this to get image parameters */
>  void efi_get_image_parameters(void **img_addr, size_t *img_size);
>  /* Add a new object to the object list. */
> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> index 430bb7f0f7dc..bc5ae9086ea2 100644
> --- a/lib/efi_loader/Kconfig
> +++ b/lib/efi_loader/Kconfig
> @@ -359,6 +359,16 @@ config EFI_UNICODE_CAPITALIZATION
>
>  endif
>
> +config EFI_RUNTIME_RELOCATE
> +       bool "Support relocation for EFI runtime service"
> +       depends on ARM || X86 || RISCV || SANDBOX
> +       default y
> +       help
> +         Select this option to enable relocation for EFI runtime service. It
> +         enables set_virtual_address_map and convert_pointer runtime service.
> +         It is required for OS on most architectures to make use of EFI runtime
> +         services.
> +
>  config EFI_LOADER_BOUNCE_BUFFER
>         bool "EFI Applications use bounce buffers for DMA operations"
>         depends on ARM64
> diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
> index 604243603289..cedc4d822fe7 100644
> --- a/lib/efi_loader/efi_image_loader.c
> +++ b/lib/efi_loader/efi_image_loader.c
> @@ -50,6 +50,7 @@ static int machines[] = {
>  #if defined(__riscv) && (__riscv_xlen == 64)
>         IMAGE_FILE_MACHINE_RISCV64,
>  #endif
> +
>         0 };
>
>  /**
> diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
> index 12cf23fa3fa8..7a1959d2409a 100644
> --- a/lib/efi_loader/efi_memory.c
> +++ b/lib/efi_loader/efi_memory.c
> @@ -908,8 +908,8 @@ __weak void efi_add_known_memory(void)
>   */
>  static void add_u_boot_and_runtime(void)
>  {
> -       unsigned long runtime_start, runtime_end, runtime_pages;
> -       unsigned long runtime_mask = EFI_PAGE_MASK;
> +       __maybe_unused unsigned long runtime_start, runtime_end, runtime_pages;
> +       __maybe_unused unsigned long runtime_mask = EFI_PAGE_MASK;
>         unsigned long uboot_start, uboot_pages;
>         unsigned long uboot_stack_size = CONFIG_STACK_SIZE;
>
> @@ -918,7 +918,13 @@ static void add_u_boot_and_runtime(void)
>                        uboot_stack_size) & ~EFI_PAGE_MASK;
>         uboot_pages = ((uintptr_t)map_sysmem(gd->ram_top - 1, 0) -
>                        uboot_start + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
> -       efi_add_memory_map_pg(uboot_start, uboot_pages, EFI_BOOT_SERVICES_CODE,
> +       /*
> +        * In case runtime relocate is not enabled just mark whole U-Boot
> +        * as EFI_RUNTIME_SERVICES_CODE because all are required at runtime.
> +        */
> +       efi_add_memory_map_pg(uboot_start, uboot_pages,
> +                             CONFIG_IS_ENABLED(EFI_RUNTIME_RELOCATE) ?
> +                             EFI_BOOT_SERVICES_CODE : EFI_RUNTIME_SERVICES_CODE,
>                               false);
>
>  #if defined(__aarch64__)
> @@ -930,6 +936,7 @@ static void add_u_boot_and_runtime(void)
>         runtime_mask = SZ_64K - 1;
>  #endif
>
> +#if CONFIG_IS_ENABLED(EFI_RUNTIME_RELOCATE)
>         /*
>          * Add Runtime Services. We mark surrounding boottime code as runtime as
>          * well to fulfill the runtime alignment constraints but avoid padding.
> @@ -940,6 +947,7 @@ static void add_u_boot_and_runtime(void)
>         runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT;
>         efi_add_memory_map_pg(runtime_start, runtime_pages,
>                               EFI_RUNTIME_SERVICES_CODE, false);
> +#endif
>  }
>
>  int efi_memory_init(void)
> diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
> index 011bcd04836d..9a6a131e5695 100644
> --- a/lib/efi_loader/efi_runtime.c
> +++ b/lib/efi_loader/efi_runtime.c
> @@ -37,6 +37,7 @@ static LIST_HEAD(efi_runtime_mmio);
>
>  static efi_status_t __efi_runtime EFIAPI efi_unimplemented(void);
>
> +#if (CONFIG_IS_ENABLED(EFI_RUNTIME_RELOCATE))
>  /*
>   * TODO(sjg at chromium.org): These defines and structures should come from the ELF
>   * header for each architecture (or a generic header) rather than being repeated
> @@ -94,6 +95,7 @@ struct elf_rela {
>  static __efi_runtime_data struct efi_mem_desc *efi_virtmap;
>  static __efi_runtime_data efi_uintn_t efi_descriptor_count;
>  static __efi_runtime_data efi_uintn_t efi_descriptor_size;
> +#endif
>
>  /*
>   * EFI runtime code lives in two stages. In the first stage, U-Boot and an EFI
> @@ -546,7 +548,7 @@ static efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps_unsupported(
>   * Return:     true if the pointer points to a service function pointer in the
>   *             runtime table
>   */
> -static bool efi_is_runtime_service_pointer(void *p)
> +static bool __maybe_unused efi_is_runtime_service_pointer(void *p)
>  {
>         return (p >= (void *)&efi_runtime_services.get_time &&
>                 p <= (void *)&efi_runtime_services.query_variable_info) ||
> @@ -574,6 +576,7 @@ void efi_runtime_detach(void)
>         efi_update_table_header_crc32(&efi_runtime_services.hdr);
>  }
>
> +#if (CONFIG_IS_ENABLED(EFI_RUNTIME_RELOCATE))
>  /**
>   * efi_set_virtual_address_map_runtime() - change from physical to virtual
>   *                                        mapping
> @@ -910,6 +913,7 @@ static efi_status_t EFIAPI efi_set_virtual_address_map(
>  out:
>         return EFI_EXIT(ret);
>  }
> +#endif
>
>  /**
>   * efi_add_runtime_mmio() - add memory-mapped IO region
> @@ -987,8 +991,13 @@ struct efi_runtime_services __efi_runtime_data efi_runtime_services = {
>         .set_time = &efi_set_time_boottime,
>         .get_wakeup_time = (void *)&efi_unimplemented,
>         .set_wakeup_time = (void *)&efi_unimplemented,
> +#if (CONFIG_IS_ENABLED(EFI_RUNTIME_RELOCATE))
>         .set_virtual_address_map = &efi_set_virtual_address_map,
>         .convert_pointer = efi_convert_pointer,
> +#else
> +       .set_virtual_address_map = (void *)&efi_unimplemented,
> +       .convert_pointer = (void *)&efi_unimplemented,
> +#endif
>         .get_variable = efi_get_variable,
>         .get_next_variable_name = efi_get_next_variable_name,
>         .set_variable = efi_set_variable,
> diff --git a/lib/efi_loader/efi_var_mem.c b/lib/efi_loader/efi_var_mem.c
> index 139e16aad7c6..7afad47b9e12 100644
> --- a/lib/efi_loader/efi_var_mem.c
> +++ b/lib/efi_loader/efi_var_mem.c
> @@ -201,6 +201,7 @@ u64 __efi_runtime efi_var_mem_free(void)
>                sizeof(struct efi_var_entry);
>  }
>
> +#if CONFIG_IS_ENABLED(EFI_RUNTIME_RELOCATE)
>  /**
>   * efi_var_mem_notify_exit_boot_services() - SetVirtualMemoryMap callback
>   *
> @@ -213,12 +214,13 @@ efi_var_mem_notify_virtual_address_map(struct efi_event *event, void *context)
>         efi_convert_pointer(0, (void **)&efi_var_buf);
>         efi_current_var = NULL;
>  }
> +#endif
>
>  efi_status_t efi_var_mem_init(void)
>  {
>         u64 memory;
>         efi_status_t ret;
> -       struct efi_event *event;
> +       struct efi_event *event __maybe_unused;
>
>         ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
>                                  EFI_RUNTIME_SERVICES_DATA,
> @@ -232,11 +234,13 @@ efi_status_t efi_var_mem_init(void)
>         efi_var_buf->length = (uintptr_t)efi_var_buf->var -
>                               (uintptr_t)efi_var_buf;
>
> +#if CONFIG_IS_ENABLED(EFI_RUNTIME_RELOCATE)
>         ret = efi_create_event(EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, TPL_CALLBACK,
>                                efi_var_mem_notify_virtual_address_map, NULL,
>                                NULL, &event);
>         if (ret != EFI_SUCCESS)
>                 return ret;
> +#endif
>         return ret;
>  }
>
> diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
> index 414701893f65..d707d921bc8e 100644
> --- a/lib/efi_selftest/Makefile
> +++ b/lib/efi_selftest/Makefile
> @@ -37,7 +37,6 @@ efi_selftest_memory.o \
>  efi_selftest_open_protocol.o \
>  efi_selftest_register_notify.o \
>  efi_selftest_reset.o \
> -efi_selftest_set_virtual_address_map.o \
>  efi_selftest_startimage_exit.o \
>  efi_selftest_startimage_return.o \
>  efi_selftest_textinput.o \
> @@ -50,6 +49,7 @@ efi_selftest_variables.o \
>  efi_selftest_variables_runtime.o \
>  efi_selftest_watchdog.o
>
> +obj-$(CONFIG_EFI_RUNTIME_RELOCATE) += efi_selftest_set_virtual_address_map.o
>  obj-$(CONFIG_EFI_ECPT) += efi_selftest_ecpt.o
>  obj-$(CONFIG_NETDEVICES) += efi_selftest_snp.o
>
>
> --
> 2.34.1
>


More information about the U-Boot mailing list