diff mbox series

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

Message ID 20240517-mips-efi-v1-2-79096e3ca3b3@flygoat.com
State New
Delegated to: Heinrich Schuchardt
Headers show
Series MIPS: Enable EFI support | expand

Commit Message

Jiaxun Yang May 17, 2024, 4:32 p.m. UTC
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.

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.

Signed-off-by: Jiaxun Yang <jiaxun.yang@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(-)

Comments

Heinrich Schuchardt May 17, 2024, 6:45 p.m. UTC | #1
Am 17. Mai 2024 18:32:53 MESZ schrieb Jiaxun Yang <jiaxun.yang@flygoat.com>:
>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.
>
>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.
>
>Signed-off-by: Jiaxun Yang <jiaxun.yang@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

The sandbox should build on all architectures with EFI support. So for the sandbox I guess you should consider the host architecture.

>+	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@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
> 
>
Ilias Apalodimas May 21, 2024, 1:58 p.m. UTC | #2
Hi Jiaxun,

On Fri, 17 May 2024 at 19:33, Jiaxun Yang <jiaxun.yang@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@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@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
>
Jiaxun Yang May 21, 2024, 2:42 p.m. UTC | #3
在2024年5月21日五月 下午2:58,Ilias Apalodimas写道:
> Hi Jiaxun,
>
> On Fri, 17 May 2024 at 19:33, Jiaxun Yang <jiaxun.yang@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?
Hi Ilias,

It's guarantee by all the existing implementations, ventoy,
linux etc.

It's nearly impossible to run MIPS OS in virtual (or paged)
segment. All MIPS OS and bootloaders are running in KSEG/XKPHYS
segment, which directly mapping lower bits of virtual address
into physical address. So I suppose set_virtual_address_map
is unnecessary on MIPS because the mapping for U-Boot is
always here and can't be disabled in hardware.

>
>>
>> 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?

MIPS is odd here, we are not compiling U-Boot with -fPIC, instead
we use our own tools to generate relocation records and embedded
them into U-Boot.

Adding relocation support requires modifications to that tool
"tools/mips-relocs.c" and also processing our own record format
here.

Given that set_virtual_address_map have no practice use on MIPS,
I think the best way to handle it is to leave set_virtual_address_map
alone.

Thanks
>
> Thanks
> /Ilias
>>
[...]
Ilias Apalodimas May 21, 2024, 5:32 p.m. UTC | #4
On Tue, 21 May 2024 at 17:42, Jiaxun Yang <jiaxun.yang@flygoat.com> wrote:
>
>
>
> 在2024年5月21日五月 下午2:58,Ilias Apalodimas写道:
> > Hi Jiaxun,
> >
> > On Fri, 17 May 2024 at 19:33, Jiaxun Yang <jiaxun.yang@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?
> Hi Ilias,
>
> It's guarantee by all the existing implementations, ventoy,
> linux etc.
>

What's ventoy? Googling it seems to be a tool for writing images?

> It's nearly impossible to run MIPS OS in virtual (or paged)
> segment. All MIPS OS and bootloaders are running in KSEG/XKPHYS
> segment, which directly mapping lower bits of virtual address
> into physical address. So I suppose set_virtual_address_map
> is unnecessary on MIPS because the mapping for U-Boot is
> always here and can't be disabled in hardware.
>

Fair enough, I am not too happy with the restriction but I think it's
ok to start with

> >
> >>
> >> 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?
>
> MIPS is odd here, we are not compiling U-Boot with -fPIC, instead
> we use our own tools to generate relocation records and embedded
> them into U-Boot.
>
> Adding relocation support requires modifications to that tool
> "tools/mips-relocs.c" and also processing our own record format
> here.
>
> Given that set_virtual_address_map have no practice use on MIPS,
> I think the best way to handle it is to leave set_virtual_address_map
> alone.

hrrm any idea why? Was that a pre-existing state in mips? Perhaps we
can fix it in the future.

That being said, I was away on a conference, I'll have a look at the
mips patches, but probably next week

Cheers
/Ilias
>
> Thanks
> >
> > Thanks
> > /Ilias
> >>
> [...]
> --
> - Jiaxun
Jiaxun Yang May 22, 2024, 6:12 a.m. UTC | #5
在2024年5月21日五月 下午6:32,Ilias Apalodimas写道:
[...]
> What's ventoy? Googling it seems to be a tool for writing images?

It's a sophisticated EFI application designed for network booting,
more file system support etc...

>
>> It's nearly impossible to run MIPS OS in virtual (or paged)
>> segment. All MIPS OS and bootloaders are running in KSEG/XKPHYS
>> segment, which directly mapping lower bits of virtual address
>> into physical address. So I suppose set_virtual_address_map
>> is unnecessary on MIPS because the mapping for U-Boot is
>> always here and can't be disabled in hardware.
>>
>
> Fair enough, I am not too happy with the restriction but I think it's
> ok to start with
>
[...]
>
> hrrm any idea why? Was that a pre-existing state in mips? Perhaps we
> can fix it in the future.

Yes, I think that's because on some MIPS ISA reversion we don't have
PC-Relative addressing instruction, which makes MIPS's PIC ABI really
awkward. That's why Kernel choose to use such relocation mechanism.

At U-Boot we are just following kernel for now. It might be possible
to switch to standard -fPIC relocation. But I'd prefer just leave it
at this point.

>
> That being said, I was away on a conference, I'll have a look at the
> mips patches, but probably next week

Much appreciated!

Thanks
>
> Cheers
> /Ilias
>>
>> Thanks
>> >
>> > Thanks
>> > /Ilias
>> >>
>> [...]
>> --
>> - Jiaxun
Maciej W. Rozycki June 1, 2024, 4:37 p.m. UTC | #6
On Tue, 21 May 2024, Jiaxun Yang wrote:

> It's nearly impossible to run MIPS OS in virtual (or paged)
> segment. All MIPS OS and bootloaders are running in KSEG/XKPHYS
> segment, which directly mapping lower bits of virtual address
> into physical address. So I suppose set_virtual_address_map
> is unnecessary on MIPS because the mapping for U-Boot is
> always here and can't be disabled in hardware.

 Surely it's possible to run a MIPS OS kernel mapped via page tables, it 
is what KSEG2 and XKSEG segments can be used for with 32-bit and 64-bit 
configurations respectively.  Both CP0.Context and CP0.XContext registers 
support placing page tables in virtual memory too, KSEG2 and XKSEG 
segments respectively, and a nested TLB refill exception is supported.  
Only the TLB exception handlers themselves obviously have to be unmapped.

 These features have hardly ever been used (original MIPSCO OS reportedly 
was an example, perhaps unsurprisingly), but they are there and it cannot 
be stated that it is nearly impossible to make use of them.  It is not.

 Note that the MIPS architecture does not have a real mode, but its 
purpose is served by the unmapped segments, which are also convenient to 
use for various reasons by OSes that otherwise do virtual addressing.

 Also for the record there are SGI IP27 Linux configurations that run from 
XKSEG rather than XKPHYS (running from KSEG2 used to be supported too, but 
has been since dropped), via a wired page mapping.

 I guess none of this really matters for U-Boot, but let's get the facts 
straight so that people who are not MIPS experts are not led into false 
understanding.

  Maciej
Jiaxun Yang June 4, 2024, 10:45 a.m. UTC | #7
在2024年6月1日六月 下午5:37,Maciej W. Rozycki写道:
> On Tue, 21 May 2024, Jiaxun Yang wrote:
>
>> It's nearly impossible to run MIPS OS in virtual (or paged)
>> segment. All MIPS OS and bootloaders are running in KSEG/XKPHYS
>> segment, which directly mapping lower bits of virtual address
>> into physical address. So I suppose set_virtual_address_map
>> is unnecessary on MIPS because the mapping for U-Boot is
>> always here and can't be disabled in hardware.
>
>  Surely it's possible to run a MIPS OS kernel mapped via page tables, it 
> is what KSEG2 and XKSEG segments can be used for with 32-bit and 64-bit 
> configurations respectively.  Both CP0.Context and CP0.XContext registers 
> support placing page tables in virtual memory too, KSEG2 and XKSEG 
> segments respectively, and a nested TLB refill exception is supported.  
> Only the TLB exception handlers themselves obviously have to be unmapped.
>
>  These features have hardly ever been used (original MIPSCO OS reportedly 
> was an example, perhaps unsurprisingly), but they are there and it cannot 
> be stated that it is nearly impossible to make use of them.  It is not.
>
>  Note that the MIPS architecture does not have a real mode, but its 
> purpose is served by the unmapped segments, which are also convenient to 
> use for various reasons by OSes that otherwise do virtual addressing.
>
>  Also for the record there are SGI IP27 Linux configurations that run from 
> XKSEG rather than XKPHYS (running from KSEG2 used to be supported too, but 
> has been since dropped), via a wired page mapping.
>
>  I guess none of this really matters for U-Boot, but let's get the facts 
> straight so that people who are not MIPS experts are not led into false 
> understanding.
Hi Maciej,

Thanks for your insights!

I was trying to implement a mapped kernel on MIPS M5150 and faced many
many issues like wired entry + FTLB is not big enough to hold page table,
thus I came out with this conclusion.

Thanks for letting me know it's possible!

For U-Boot this is irrelevant as the main concern is whether KSEG0
is working after hand over control to OS. Disabling KSEG0 is impossible
without SegCtl.

Anyway, nice to have you here.

Thanks
>
>   Maciej
diff mbox series

Patch

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@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