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
 
