[PATCH 0/7] MIPS: Enable EFI support

Hi all,
This series enabled EFI support to MIPS platform.
Although MIPS is not defined by UEFI specification, there are quite a few firmware implementations available, including MIPS-EFI[1] for Loongson-2F, Lemote's proprietary EDK2 implementation on Loongson-3[2], Kunlun firmware for Loongson-3[3], efiffy[4] for MIPS Creator CI20 and another mystery EDK implementation shipped with some Creator CI20 board.
Available applications including gnu-efi, Loongson's GRUB fork[5], Ventoy[6].
My implementation in U-Boot is aiming to follow conventions made by other implementations for architecture stuff and remain compliance with spec for general aspects.
bootefi hello and selftest passed on both 32 and 64 bit system, gnu-efi, grub and ventoy are tested on mips64el with my pending platform works. mips32el efi executable from efiffy is tested as well.
Please review. Thanks
[1]: https://github.com/kontais/EFI-MIPS [2]: https://github.com/loongson-community/firmware-nonfree [3]: http://www.kunluntech.com.cn/klbiosxl [4]: https://sourceforge.net/projects/efify/ [5]: https://github.com/loongson-community/grub [6]: https://www.ventoy.net/en/index.html
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- Jiaxun Yang (7): MIPS: Implement setjmp efi: Allow runtime relocate to be disabled Makefile.lib: Preserve .rodata section for EFI file Makefile.lib: Enforce EFI CFLAGS/AFLAGS MIPS: Add smbios_start to arch_global_data MIPS: Define MIPS EFI related bits everywhere MIPS: Implement EFI supporting stuff
Makefile | 3 + arch/mips/config.mk | 9 + arch/mips/include/asm/global_data.h | 3 + arch/mips/include/asm/setjmp.h | 36 ++++ arch/mips/lib/Makefile | 15 ++ arch/mips/lib/crt0_mips_efi.S | 239 ++++++++++++++++++++++ arch/mips/lib/elf_mips_efi.lds | 113 ++++++++++ arch/mips/lib/reloc_mips_efi.c | 99 +++++++++ arch/mips/lib/setjmp32.S | 51 +++++ arch/mips/lib/setjmp64.S | 56 +++++ include/asm-generic/pe.h | 5 + include/config_distro_bootcmd.h | 6 + include/efi_default_filename.h | 8 + include/efi_loader.h | 26 ++- include/elf.h | 8 + lib/efi_loader/Kconfig | 12 +- lib/efi_loader/efi_image_loader.c | 18 ++ 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 +- lib/efi_selftest/efi_selftest_miniapp_exception.c | 2 + scripts/Makefile.lib | 10 +- 23 files changed, 734 insertions(+), 18 deletions(-) --- base-commit: ad7dce5abd49ef3b5c93da5303e15449c8c162b4 change-id: 20240517-mips-efi-c9a1ad819c2d
Best regards,

Implement setjmp with o32/n64 ABI's standard stack frame. Note that those two ABIs slightly disagreed on placement of registers so they are being implemented in two different files.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- arch/mips/include/asm/setjmp.h | 36 +++++++++++++++++++++++++++ arch/mips/lib/Makefile | 2 ++ arch/mips/lib/setjmp32.S | 51 ++++++++++++++++++++++++++++++++++++++ arch/mips/lib/setjmp64.S | 56 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+)
diff --git a/arch/mips/include/asm/setjmp.h b/arch/mips/include/asm/setjmp.h new file mode 100644 index 000000000000..afa2ffb007e6 --- /dev/null +++ b/arch/mips/include/asm/setjmp.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2024 Jiaxun Yang jiaxun.yang@flygoat.com + */ + +#ifndef _SETJMP_H_ +#define _SETJMP_H_ 1 + +/* + * This really should be opaque, but the EFI implementation wrongly + * assumes that a 'struct jmp_buf_data' is defined. + */ +#if __mips == 64 +struct jmp_buf_data { + unsigned long ra; + unsigned long sp; + unsigned long fp; + unsigned long gp; + unsigned long s_regs[8]; /* s0 - s7 */ +}; +#else +struct jmp_buf_data { + unsigned long ra; + unsigned long sp; + unsigned long s_regs[8]; /* s0 - s7 */ + unsigned long fp; + unsigned long gp; +}; +#endif + +typedef struct jmp_buf_data jmp_buf[1]; + +int setjmp(jmp_buf jmp); +void longjmp(jmp_buf jmp, int ret); + +#endif /* _SETJMP_H_ */ diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index 1621cc9a1ff9..e36dfd0547b5 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -10,6 +10,8 @@ obj-y += reloc.o obj-y += stack.o obj-y += traps.o
+obj-$(CONFIG_32BIT) += setjmp32.o +obj-$(CONFIG_64BIT) += setjmp64.o obj-$(CONFIG_CMD_BOOTM) += bootm.o obj-$(CONFIG_CMD_GO) += boot.o obj-$(CONFIG_SPL_BUILD) += spl.o diff --git a/arch/mips/lib/setjmp32.S b/arch/mips/lib/setjmp32.S new file mode 100644 index 000000000000..4a2661d29249 --- /dev/null +++ b/arch/mips/lib/setjmp32.S @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2024 Jiaxun Yang jiaxun.yang@flygoat.com + */ + +#include <linux/linkage.h> +#include <asm/regdef.h> + +.pushsection .text.setjmp, "ax" +ENTRY(setjmp) + sw ra, 0(a0) + sw sp, 4(a0) + sw s0, 8(a0) + sw s1, 12(a0) + sw s2, 16(a0) + sw s3, 20(a0) + sw s4, 24(a0) + sw s5, 28(a0) + sw s6, 32(a0) + sw s7, 36(a0) + sw fp, 40(a0) + sw gp, 44(a0) + + move v0, zero + jr ra +ENDPROC(setjmp) +.popsection + +.pushsection .text.longjmp, "ax" +ENTRY(longjmp) + lw ra, 0(a0) + lw sp, 4(a0) + lw s0, 8(a0) + lw s1, 12(a0) + lw s2, 16(a0) + lw s3, 20(a0) + lw s4, 24(a0) + lw s5, 28(a0) + lw s6, 32(a0) + lw s7, 36(a0) + lw fp, 40(a0) + lw gp, 44(a0) + + beqz a1, 1f + move v0, a1 + jr ra +1: + li v0, 1 + jr ra +ENDPROC(longjmp) +.popsection diff --git a/arch/mips/lib/setjmp64.S b/arch/mips/lib/setjmp64.S new file mode 100644 index 000000000000..6f615bb10014 --- /dev/null +++ b/arch/mips/lib/setjmp64.S @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved. + * Copyright (c) 2017 Lemote Co.Ltd + * Author: Heiher r@hev.cc + * Copyright (c) 2024 Jiaxun Yang jiaxun.yang@flygoat.com + */ + +#include <linux/linkage.h> +#include <asm/regdef.h> + +.pushsection .text.setjmp, "ax" +ENTRY(setjmp) + sd ra, 0x00(a0) + sd sp, 0x08(a0) + sd fp, 0x10(a0) + sd gp, 0x18(a0) + + sd s0, 0x20(a0) + sd s1, 0x28(a0) + sd s2, 0x30(a0) + sd s3, 0x38(a0) + sd s4, 0x40(a0) + sd s5, 0x48(a0) + sd s6, 0x50(a0) + sd s7, 0x58(a0) + + move v0, zero + jr ra +ENDPROC(setjmp) +.popsection + +.pushsection .text.longjmp, "ax" +ENTRY(longjmp) + ld ra, 0x00(a0) + ld sp, 0x08(a0) + ld fp, 0x10(a0) + ld gp, 0x18(a0) + + ld s0, 0x20(a0) + ld s1, 0x28(a0) + ld s2, 0x30(a0) + ld s3, 0x38(a0) + ld s4, 0x40(a0) + ld s5, 0x48(a0) + ld s6, 0x50(a0) + ld s7, 0x58(a0) + + beqz a1, 1f + move v0, a1 + jr ra +1: + li v0, 1 + jr ra +ENDPROC(longjmp) +.popsection

Am 17. Mai 2024 18:32:52 MESZ schrieb Jiaxun Yang jiaxun.yang@flygoat.com:
Implement setjmp with o32/n64 ABI's standard stack frame. Note that those two ABIs slightly disagreed on placement of registers so they are being implemented in two different files.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
arch/mips/include/asm/setjmp.h | 36 +++++++++++++++++++++++++++ arch/mips/lib/Makefile | 2 ++ arch/mips/lib/setjmp32.S | 51 ++++++++++++++++++++++++++++++++++++++ arch/mips/lib/setjmp64.S | 56 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+)
diff --git a/arch/mips/include/asm/setjmp.h b/arch/mips/include/asm/setjmp.h new file mode 100644 index 000000000000..afa2ffb007e6 --- /dev/null +++ b/arch/mips/include/asm/setjmp.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (c) 2024 Jiaxun Yang jiaxun.yang@flygoat.com
- */
+#ifndef _SETJMP_H_ +#define _SETJMP_H_ 1
+/*
- This really should be opaque, but the EFI implementation wrongly
- assumes that a 'struct jmp_buf_data' is defined.
- */
+#if __mips == 64 +struct jmp_buf_data {
- unsigned long ra;
- unsigned long sp;
- unsigned long fp;
- unsigned long gp;
- unsigned long s_regs[8]; /* s0 - s7 */
+}; +#else +struct jmp_buf_data {
- unsigned long ra;
- unsigned long sp;
- unsigned long s_regs[8]; /* s0 - s7 */
- unsigned long fp;
- unsigned long gp;
+};
As the jumpbuffer is only used inside U-Boot we should be able to use the same register sequence independant of the bitness.
Best regards
Heinrich
+#endif
+typedef struct jmp_buf_data jmp_buf[1];
+int setjmp(jmp_buf jmp); +void longjmp(jmp_buf jmp, int ret);
+#endif /* _SETJMP_H_ */ diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index 1621cc9a1ff9..e36dfd0547b5 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -10,6 +10,8 @@ obj-y += reloc.o obj-y += stack.o obj-y += traps.o
+obj-$(CONFIG_32BIT) += setjmp32.o +obj-$(CONFIG_64BIT) += setjmp64.o obj-$(CONFIG_CMD_BOOTM) += bootm.o obj-$(CONFIG_CMD_GO) += boot.o obj-$(CONFIG_SPL_BUILD) += spl.o diff --git a/arch/mips/lib/setjmp32.S b/arch/mips/lib/setjmp32.S new file mode 100644 index 000000000000..4a2661d29249 --- /dev/null +++ b/arch/mips/lib/setjmp32.S @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (c) 2024 Jiaxun Yang jiaxun.yang@flygoat.com
- */
+#include <linux/linkage.h> +#include <asm/regdef.h>
+.pushsection .text.setjmp, "ax" +ENTRY(setjmp)
- sw ra, 0(a0)
- sw sp, 4(a0)
- sw s0, 8(a0)
- sw s1, 12(a0)
- sw s2, 16(a0)
- sw s3, 20(a0)
- sw s4, 24(a0)
- sw s5, 28(a0)
- sw s6, 32(a0)
- sw s7, 36(a0)
- sw fp, 40(a0)
- sw gp, 44(a0)
- move v0, zero
- jr ra
+ENDPROC(setjmp) +.popsection
+.pushsection .text.longjmp, "ax" +ENTRY(longjmp)
- lw ra, 0(a0)
- lw sp, 4(a0)
- lw s0, 8(a0)
- lw s1, 12(a0)
- lw s2, 16(a0)
- lw s3, 20(a0)
- lw s4, 24(a0)
- lw s5, 28(a0)
- lw s6, 32(a0)
- lw s7, 36(a0)
- lw fp, 40(a0)
- lw gp, 44(a0)
- beqz a1, 1f
- move v0, a1
- jr ra
+1:
- li v0, 1
- jr ra
+ENDPROC(longjmp) +.popsection diff --git a/arch/mips/lib/setjmp64.S b/arch/mips/lib/setjmp64.S new file mode 100644 index 000000000000..6f615bb10014 --- /dev/null +++ b/arch/mips/lib/setjmp64.S @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
- Copyright (c) 2017 Lemote Co.Ltd
- Author: Heiher r@hev.cc
- Copyright (c) 2024 Jiaxun Yang jiaxun.yang@flygoat.com
- */
+#include <linux/linkage.h> +#include <asm/regdef.h>
+.pushsection .text.setjmp, "ax" +ENTRY(setjmp)
- sd ra, 0x00(a0)
- sd sp, 0x08(a0)
- sd fp, 0x10(a0)
- sd gp, 0x18(a0)
- sd s0, 0x20(a0)
- sd s1, 0x28(a0)
- sd s2, 0x30(a0)
- sd s3, 0x38(a0)
- sd s4, 0x40(a0)
- sd s5, 0x48(a0)
- sd s6, 0x50(a0)
- sd s7, 0x58(a0)
- move v0, zero
- jr ra
+ENDPROC(setjmp) +.popsection
+.pushsection .text.longjmp, "ax" +ENTRY(longjmp)
- ld ra, 0x00(a0)
- ld sp, 0x08(a0)
- ld fp, 0x10(a0)
- ld gp, 0x18(a0)
- ld s0, 0x20(a0)
- ld s1, 0x28(a0)
- ld s2, 0x30(a0)
- ld s3, 0x38(a0)
- ld s4, 0x40(a0)
- ld s5, 0x48(a0)
- ld s6, 0x50(a0)
- ld s7, 0x58(a0)
- beqz a1, 1f
- move v0, a1
- jr ra
+1:
- li v0, 1
- jr ra
+ENDPROC(longjmp) +.popsection

在2024年5月17日五月 下午10:11,Heinrich Schuchardt写道: [...]
As the jumpbuffer is only used inside U-Boot we should be able to use the same register sequence independant of the bitness.
Hi Heinrich,
I chose to use ABI's stack frame because GDB requires it to perform proper unwinding and it helped debugging a lot.
But I'm fine with unifying them if you think it's necessary, what's your opinion?
Thanks - Jiaxun
Best regards
Heinrich

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

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

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

在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
[...]

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

在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

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

在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

This is required in performing objcopy to MIPS EFI files.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- scripts/Makefile.lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 62f87517c09c..52aed7a65d47 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -469,7 +469,7 @@ $(obj)/%_efi.S: $(obj)/%.efi
quiet_cmd_efi_objcopy = OBJCOPY $@ cmd_efi_objcopy = $(OBJCOPY) -j .header -j .text -j .sdata -j .data -j \ - .dynamic -j .dynsym -j .rel* -j .rela* -j .reloc \ + .dynamic -j .dynsym -j .rel* -j .rela* -j .reloc -j .rodata \ $(if $(EFI_TARGET),$(EFI_TARGET),-O binary) $^ $@
$(obj)/%.efi: $(obj)/%_efi.so

Hi Jiaxun
On Fri, 17 May 2024 at 19:33, Jiaxun Yang jiaxun.yang@flygoat.com wrote:
This is required in performing objcopy to MIPS EFI files.
This seems not mips specific. What was missing for your case?
Thanks /Ilias
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
scripts/Makefile.lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 62f87517c09c..52aed7a65d47 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -469,7 +469,7 @@ $(obj)/%_efi.S: $(obj)/%.efi
quiet_cmd_efi_objcopy = OBJCOPY $@ cmd_efi_objcopy = $(OBJCOPY) -j .header -j .text -j .sdata -j .data -j \
.dynamic -j .dynsym -j .rel* -j .rela* -j .reloc \
.dynamic -j .dynsym -j .rel* -j .rela* -j .reloc -j .rodata \ $(if $(EFI_TARGET),$(EFI_TARGET),-O binary) $^ $@
$(obj)/%.efi: $(obj)/%_efi.so
-- 2.34.1

在2024年6月11日六月 下午2:49,Ilias Apalodimas写道:
Hi Jiaxun
On Fri, 17 May 2024 at 19:33, Jiaxun Yang jiaxun.yang@flygoat.com wrote:
This is required in performing objcopy to MIPS EFI files.
This seems not mips specific. What was missing for your case?
So MIPS EFI file would come with .rodata section. If we don't preserve it here, the whole section would be stripped away.
.rodata is always necessary in binary if it's in ELF as it contains valid program data.
Other architectures won't generate .rodata section in their ELF file so it's harmless. Besides GNU-EFI's universal strip commands also have -j .rodata argument.
Thanks - Jiaxun
Thanks /Ilias
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
scripts/Makefile.lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 62f87517c09c..52aed7a65d47 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -469,7 +469,7 @@ $(obj)/%_efi.S: $(obj)/%.efi
quiet_cmd_efi_objcopy = OBJCOPY $@ cmd_efi_objcopy = $(OBJCOPY) -j .header -j .text -j .sdata -j .data -j \
.dynamic -j .dynsym -j .rel* -j .rela* -j .reloc \
.dynamic -j .dynsym -j .rel* -j .rela* -j .reloc -j .rodata \ $(if $(EFI_TARGET),$(EFI_TARGET),-O binary) $^ $@
$(obj)/%.efi: $(obj)/%_efi.so
-- 2.34.1

On 11.06.24 16:06, Jiaxun Yang wrote:
在2024年6月11日六月 下午2:49,Ilias Apalodimas写道:
Hi Jiaxun
On Fri, 17 May 2024 at 19:33, Jiaxun Yang jiaxun.yang@flygoat.com wrote:
This is required in performing objcopy to MIPS EFI files.
This seems not mips specific. What was missing for your case?
So MIPS EFI file would come with .rodata section. If we don't preserve it here, the whole section would be stripped away.
.rodata is always necessary in binary if it's in ELF as it contains valid program data.
Other architectures won't generate .rodata section in their ELF file so it's harmless. Besides GNU-EFI's universal strip commands also have -j .rodata argument.
Thanks
- Jiaxun
Thanks /Ilias
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
scripts/Makefile.lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 62f87517c09c..52aed7a65d47 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -469,7 +469,7 @@ $(obj)/%_efi.S: $(obj)/%.efi
quiet_cmd_efi_objcopy = OBJCOPY $@ cmd_efi_objcopy = $(OBJCOPY) -j .header -j .text -j .sdata -j .data -j \
.dynamic -j .dynsym -j .rel* -j .rela* -j .reloc \
.dynamic -j .dynsym -j .rel* -j .rela* -j .reloc -j .rodata \ $(if $(EFI_TARGET),$(EFI_TARGET),-O binary) $^ $@
$(obj)/%.efi: $(obj)/%_efi.so
-- 2.34.1
We have:
arch/arm/lib/elf_aarch64_efi.lds:26: *(.rodata*) arch/arm/lib/elf_arm_efi.lds:26: *(.rodata*) arch/riscv/lib/elf_riscv32_efi.lds:26: *(.rodata*) arch/riscv/lib/elf_riscv64_efi.lds:26: *(.rodata*) arch/x86/lib/elf_ia32_efi.lds:35: *(.rodata*) arch/x86/lib/elf_x86_64_efi.lds:37: *(.rodata*)
Not considering .rodata in objcopy looks inconsistent.
As we use -fdata-sections wouldn't we expect a .rodata* section per function with constants on LoongArch? Shouldn't we use:
+ .dynamic -j .dynsym -j .rel* -j .rela* -j .reloc -j .rodata* \
Best regards
Heinrich

在2024年6月11日六月 下午3:28,Heinrich Schuchardt写道: [...]
We have:
arch/arm/lib/elf_aarch64_efi.lds:26: *(.rodata*) arch/arm/lib/elf_arm_efi.lds:26: *(.rodata*) arch/riscv/lib/elf_riscv32_efi.lds:26: *(.rodata*) arch/riscv/lib/elf_riscv64_efi.lds:26: *(.rodata*) arch/x86/lib/elf_ia32_efi.lds:35: *(.rodata*) arch/x86/lib/elf_x86_64_efi.lds:37: *(.rodata*)
Not considering .rodata in objcopy looks inconsistent.
As we use -fdata-sections wouldn't we expect a .rodata* section per function with constants on LoongArch? Shouldn't we use:
- .dynamic -j .dynsym -j .rel* -j .rela* -j .reloc -j .rodata* \
That makes sense, will take in next version.
Thanks
Best regards
Heinrich

On Tue, 11 Jun 2024 at 17:07, Jiaxun Yang jiaxun.yang@flygoat.com wrote:
在2024年6月11日六月 下午2:49,Ilias Apalodimas写道:
Hi Jiaxun
On Fri, 17 May 2024 at 19:33, Jiaxun Yang jiaxun.yang@flygoat.com wrote:
This is required in performing objcopy to MIPS EFI files.
This seems not mips specific. What was missing for your case?
So MIPS EFI file would come with .rodata section. If we don't preserve it here, the whole section would be stripped away.
.rodata is always necessary in binary if it's in ELF as it contains valid program data.
Other architectures won't generate .rodata section in their ELF file so it's harmless. Besides GNU-EFI's universal strip commands also have -j .rodata argument.
Yea I am not arguing that this is useless or dangerous, I was just wondering if more architectures need .rodata so we could make the commit message a bit more generic
Cheers /Ilias
Thanks
- Jiaxun
Thanks /Ilias
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
scripts/Makefile.lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 62f87517c09c..52aed7a65d47 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -469,7 +469,7 @@ $(obj)/%_efi.S: $(obj)/%.efi
quiet_cmd_efi_objcopy = OBJCOPY $@ cmd_efi_objcopy = $(OBJCOPY) -j .header -j .text -j .sdata -j .data -j \
.dynamic -j .dynsym -j .rel* -j .rela* -j .reloc \
.dynamic -j .dynsym -j .rel* -j .rela* -j .reloc -j .rodata \ $(if $(EFI_TARGET),$(EFI_TARGET),-O binary) $^ $@
$(obj)/%.efi: $(obj)/%_efi.so
-- 2.34.1
--
- Jiaxun

EFI AFLAGS/CFLAGS should be enforced for those runtime supporting files as well, otherwise EFI applications will fail to compile on MIPS.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- Makefile | 3 +++ scripts/Makefile.lib | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile index 44deb339af19..6c9098f5823f 100644 --- a/Makefile +++ b/Makefile @@ -652,6 +652,8 @@ export EFI_CRT0 # Filename of EFI CRT0 in arch/$(ARCH)/lib export EFI_RELOC # Filename of EFU relocation code in arch/$(ARCH)/lib export CFLAGS_EFI # Compiler flags to add when building EFI app export CFLAGS_NON_EFI # Compiler flags to remove when building EFI app +export AFLAGS_EFI # Assembler flags to add when building EFI app +export AFLAGS_NON_EFI # Assembler flags to remove when building EFI app export EFI_TARGET # binutils target if EFI is natively supported
export LTO_ENABLE @@ -926,6 +928,7 @@ export PLATFORM_LIBGCC LDPPFLAGS += \ -include $(srctree)/include/u-boot/u-boot.lds.h \ -DCPUDIR=$(CPUDIR) \ + -DARCHDIR=arch/$(ARCH) \ $(shell $(LD) --version | \ sed -ne 's/GNU ld version ([0-9][0-9]*).([0-9][0-9]*).*/-DLD_MAJOR=\1 -DLD_MINOR=\2/p')
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 52aed7a65d47..5aacab32cb38 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -495,8 +495,12 @@ $(obj)/%_efi.so: $(obj)/%.o $(obj)/efi_crt0.o $(obj)/efi_reloc.o $(obj)/efi_free
targets += $(obj)/efi_crt0.o $(obj)/efi_reloc.o $(obj)/efi_freestanding.o
-CFLAGS_REMOVE_efi_reloc.o := $(LTO_CFLAGS) -CFLAGS_REMOVE_efi_freestanding.o := $(LTO_CFLAGS) +AFLAGS_efi_crt0.o := $(AFLAGS_EFI) +CFLAGS_efi_reloc.o := $(CFLAGS_EFI) +CFLAGS_efi_freestanding.o := $(CFLAGS_EFI) +AFLAGS_REMOVE_efi_crt0.o := $(AFLAGS_NON_EFI) +CFLAGS_REMOVE_efi_reloc.o := $(CFLAGS_NON_EFI) $(LTO_CFLAGS) +CFLAGS_REMOVE_efi_freestanding.o := $(CFLAGS_NON_EFI) $(LTO_CFLAGS)
# ACPI # ---------------------------------------------------------------------------

Am 17. Mai 2024 18:32:55 MESZ schrieb Jiaxun Yang jiaxun.yang@flygoat.com:
EFI AFLAGS/CFLAGS should be enforced for those runtime supporting files as well, otherwise EFI applications will fail to compile on MIPS.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
Makefile | 3 +++ scripts/Makefile.lib | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile index 44deb339af19..6c9098f5823f 100644 --- a/Makefile +++ b/Makefile @@ -652,6 +652,8 @@ export EFI_CRT0 # Filename of EFI CRT0 in arch/$(ARCH)/lib export EFI_RELOC # Filename of EFU relocation code in arch/$(ARCH)/lib export CFLAGS_EFI # Compiler flags to add when building EFI app export CFLAGS_NON_EFI # Compiler flags to remove when building EFI app +export AFLAGS_EFI # Assembler flags to add when building EFI app +export AFLAGS_NON_EFI # Assembler flags to remove when building EFI app export EFI_TARGET # binutils target if EFI is natively supported
export LTO_ENABLE @@ -926,6 +928,7 @@ export PLATFORM_LIBGCC LDPPFLAGS += \ -include $(srctree)/include/u-boot/u-boot.lds.h \ -DCPUDIR=$(CPUDIR) \
- -DARCHDIR=arch/$(ARCH) \
This change seems to be unrelated.
$(shell $(LD) --version | \ sed -ne 's/GNU ld version ([0-9][0-9]*).([0-9][0-9]*).*/-DLD_MAJOR=\1 -DLD_MINOR=\2/p')
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 52aed7a65d47..5aacab32cb38 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -495,8 +495,12 @@ $(obj)/%_efi.so: $(obj)/%.o $(obj)/efi_crt0.o $(obj)/efi_reloc.o $(obj)/efi_free
targets += $(obj)/efi_crt0.o $(obj)/efi_reloc.o $(obj)/efi_freestanding.o
-CFLAGS_REMOVE_efi_reloc.o := $(LTO_CFLAGS) -CFLAGS_REMOVE_efi_freestanding.o := $(LTO_CFLAGS) +AFLAGS_efi_crt0.o := $(AFLAGS_EFI) +CFLAGS_efi_reloc.o := $(CFLAGS_EFI) +CFLAGS_efi_freestanding.o := $(CFLAGS_EFI) +AFLAGS_REMOVE_efi_crt0.o := $(AFLAGS_NON_EFI) +CFLAGS_REMOVE_efi_reloc.o := $(CFLAGS_NON_EFI) $(LTO_CFLAGS) +CFLAGS_REMOVE_efi_freestanding.o := $(CFLAGS_NON_EFI) $(LTO_CFLAGS)
# ACPI # ---------------------------------------------------------------------------

This is necessary for SMBIOS to build on MIPS.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- arch/mips/include/asm/global_data.h | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h index 147a95ecea8b..740bbcdb84e9 100644 --- a/arch/mips/include/asm/global_data.h +++ b/arch/mips/include/asm/global_data.h @@ -40,6 +40,9 @@ struct arch_global_data { #ifdef CONFIG_ARCH_OCTEON struct octeon_eeprom_mac_addr mac_desc; #endif +#ifdef CONFIG_SMBIOS + ulong smbios_start; /* Start address of SMBIOS table */ +#endif };
#include <asm-generic/global_data.h>

On Fri, 17 May 2024 at 19:33, Jiaxun Yang jiaxun.yang@flygoat.com wrote:
This is necessary for SMBIOS to build on MIPS.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
arch/mips/include/asm/global_data.h | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h index 147a95ecea8b..740bbcdb84e9 100644 --- a/arch/mips/include/asm/global_data.h +++ b/arch/mips/include/asm/global_data.h @@ -40,6 +40,9 @@ struct arch_global_data { #ifdef CONFIG_ARCH_OCTEON struct octeon_eeprom_mac_addr mac_desc; #endif +#ifdef CONFIG_SMBIOS
ulong smbios_start; /* Start address of SMBIOS table */
+#endif };
#include <asm-generic/global_data.h>
-- 2.34.1
Acked-by: Ilias Apalodimas ilias.apalodimas@linaro.org

Various file names, instruction defines, magic numbers related to MIPS's EFI implementation.
PE magic numbers are from winnt.h, DHCP numbers are from IANA page, boot file names are from other implementations.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- include/asm-generic/pe.h | 5 +++++ include/config_distro_bootcmd.h | 6 ++++++ include/efi_default_filename.h | 8 ++++++++ include/elf.h | 8 ++++++++ lib/efi_loader/efi_image_loader.c | 17 +++++++++++++++++ lib/efi_selftest/efi_selftest_miniapp_exception.c | 2 ++ 6 files changed, 46 insertions(+)
diff --git a/include/asm-generic/pe.h b/include/asm-generic/pe.h index cd5b6ad62bf0..42c4cbedbc95 100644 --- a/include/asm-generic/pe.h +++ b/include/asm-generic/pe.h @@ -31,6 +31,11 @@
/* Machine types */ #define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_R3000_BE 0x0160 +#define IMAGE_FILE_MACHINE_R3000 0x0162 +#define IMAGE_FILE_MACHINE_R4000_BE 0x0164 +#define IMAGE_FILE_MACHINE_R4000 0x0166 +#define IMAGE_FILE_MACHINE_R10000 0x0168 #define IMAGE_FILE_MACHINE_ARM 0x01c0 #define IMAGE_FILE_MACHINE_THUMB 0x01c2 #define IMAGE_FILE_MACHINE_ARMNT 0x01c4 diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h index 2a136b96a6d9..9e03d10acec5 100644 --- a/include/config_distro_bootcmd.h +++ b/include/config_distro_bootcmd.h @@ -366,6 +366,12 @@ #elif defined(CONFIG_ARCH_RV64I) || ((defined(__riscv) && __riscv_xlen == 64)) #define BOOTENV_EFI_PXE_ARCH "0x1b" #define BOOTENV_EFI_PXE_VCI "PXEClient:Arch:00027:UNDI:003000" +#elif defined(CONFIG_CPU_MIPS32) || ((defined(__mips) && __mips == 32)) +#define BOOTENV_EFI_PXE_ARCH "0x21" +#define BOOTENV_EFI_PXE_VCI "PXEClient:Arch:00033:UNDI:003000" +#elif defined(CONFIG_CPU_MIPS64) || ((defined(__mips) && __mips == 64)) +#define BOOTENV_EFI_PXE_ARCH "0x22" +#define BOOTENV_EFI_PXE_VCI "PXEClient:Arch:00034:UNDI:003000" #elif defined(CONFIG_SANDBOX) # error "sandbox EFI support is only supported on ARM and x86" #else diff --git a/include/efi_default_filename.h b/include/efi_default_filename.h index 77932984b557..eb94a54514bc 100644 --- a/include/efi_default_filename.h +++ b/include/efi_default_filename.h @@ -47,6 +47,14 @@ #define BOOTEFI_NAME "BOOTRISCV32.EFI" #elif defined(CONFIG_ARCH_RV64I) #define BOOTEFI_NAME "BOOTRISCV64.EFI" +#elif defined(CONFIG_CPU_MIPS32) && defined(CONFIG_SYS_BIG_ENDIAN) +#define BOOTEFI_NAME "BOOTMIPS.EFI" +#elif defined(CONFIG_CPU_MIPS32) && defined(CONFIG_SYS_LITTLE_ENDIAN) +#define BOOTEFI_NAME "BOOTMIPSEL.EFI" +#elif defined(CONFIG_CPU_MIPS64) && defined(CONFIG_SYS_BIG_ENDIAN) +#define BOOTEFI_NAME "BOOTMIPS64.EFI" +#elif defined(CONFIG_CPU_MIPS64) && defined(CONFIG_SYS_LITTLE_ENDIAN) +#define BOOTEFI_NAME "BOOTMIPS64EL.EFI" #else #error Unsupported UEFI architecture #endif diff --git a/include/elf.h b/include/elf.h index a4ba74d8abeb..95de6ffbce31 100644 --- a/include/elf.h +++ b/include/elf.h @@ -545,6 +545,9 @@ typedef struct { #define DT_LOPROC 0x70000000 /* reserved range for processor */ #define DT_HIPROC 0x7fffffff /* specific dynamic array tags */
+/* MIPS */ +#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local got entries */ + /* Dynamic Tag Flags - d_un.d_val */ #define DF_ORIGIN 0x01 /* Object may use DF_ORIGIN */ #define DF_SYMBOLIC 0x02 /* Symbol resolutions starts here */ @@ -699,6 +702,11 @@ unsigned long elf_hash(const unsigned char *name); #define R_RISCV_64 2 #define R_RISCV_RELATIVE 3
+/* MIPS Relocations */ +#define R_MIPS_NONE 0 +#define R_MIPS_REL32 3 +#define R_MIPS_64 18 + #ifndef __ASSEMBLY__ int valid_elf_image(unsigned long addr); unsigned long load_elf64_image_phdr(unsigned long addr); diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index cedc4d822fe7..8df469851851 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -51,6 +51,23 @@ static int machines[] = { IMAGE_FILE_MACHINE_RISCV64, #endif
+#if defined(__mips__) && (__mips == 32) && defined(__BIG_ENDIAN) + IMAGE_FILE_MACHINE_R3000_BE, +#endif + +#if defined(__mips__) && (__mips == 32) && defined(__LITTLE_ENDIAN) + IMAGE_FILE_MACHINE_R3000, +#endif + +#if defined(__mips__) && (__mips == 64) && defined(__BIG_ENDIAN) + IMAGE_FILE_MACHINE_R4000_BE, +#endif + +#if defined(__mips__) && (__mips == 64) && defined(__LITTLE_ENDIAN) + IMAGE_FILE_MACHINE_R4000, + IMAGE_FILE_MACHINE_R10000, +#endif + 0 };
/** diff --git a/lib/efi_selftest/efi_selftest_miniapp_exception.c b/lib/efi_selftest/efi_selftest_miniapp_exception.c index f668cdac4ab2..f3b4ee926f8f 100644 --- a/lib/efi_selftest/efi_selftest_miniapp_exception.c +++ b/lib/efi_selftest/efi_selftest_miniapp_exception.c @@ -33,6 +33,8 @@ efi_status_t EFIAPI efi_main(efi_handle_t handle, asm volatile (".word 0xe7f7defb\n"); #elif defined(CONFIG_RISCV) asm volatile (".word 0xffffffff\n"); +#elif defined(CONFIG_MIPS) + asm volatile ("break 0xf\n"); #elif defined(CONFIG_X86) asm volatile (".word 0xffff\n"); #elif defined(CONFIG_SANDBOX)

On Fri, 17 May 2024 at 19:33, Jiaxun Yang jiaxun.yang@flygoat.com wrote:
Various file names, instruction defines, magic numbers related to MIPS's EFI implementation.
PE magic numbers are from winnt.h, DHCP numbers are from IANA page, boot file names are from other implementations.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
include/asm-generic/pe.h | 5 +++++ include/config_distro_bootcmd.h | 6 ++++++ include/efi_default_filename.h | 8 ++++++++ include/elf.h | 8 ++++++++ lib/efi_loader/efi_image_loader.c | 17 +++++++++++++++++ lib/efi_selftest/efi_selftest_miniapp_exception.c | 2 ++ 6 files changed, 46 insertions(+)
diff --git a/include/asm-generic/pe.h b/include/asm-generic/pe.h index cd5b6ad62bf0..42c4cbedbc95 100644 --- a/include/asm-generic/pe.h +++ b/include/asm-generic/pe.h @@ -31,6 +31,11 @@
/* Machine types */ #define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_R3000_BE 0x0160 +#define IMAGE_FILE_MACHINE_R3000 0x0162 +#define IMAGE_FILE_MACHINE_R4000_BE 0x0164 +#define IMAGE_FILE_MACHINE_R4000 0x0166 +#define IMAGE_FILE_MACHINE_R10000 0x0168 #define IMAGE_FILE_MACHINE_ARM 0x01c0 #define IMAGE_FILE_MACHINE_THUMB 0x01c2 #define IMAGE_FILE_MACHINE_ARMNT 0x01c4 diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h index 2a136b96a6d9..9e03d10acec5 100644 --- a/include/config_distro_bootcmd.h +++ b/include/config_distro_bootcmd.h @@ -366,6 +366,12 @@ #elif defined(CONFIG_ARCH_RV64I) || ((defined(__riscv) && __riscv_xlen == 64)) #define BOOTENV_EFI_PXE_ARCH "0x1b" #define BOOTENV_EFI_PXE_VCI "PXEClient:Arch:00027:UNDI:003000" +#elif defined(CONFIG_CPU_MIPS32) || ((defined(__mips) && __mips == 32)) +#define BOOTENV_EFI_PXE_ARCH "0x21" +#define BOOTENV_EFI_PXE_VCI "PXEClient:Arch:00033:UNDI:003000" +#elif defined(CONFIG_CPU_MIPS64) || ((defined(__mips) && __mips == 64)) +#define BOOTENV_EFI_PXE_ARCH "0x22" +#define BOOTENV_EFI_PXE_VCI "PXEClient:Arch:00034:UNDI:003000" #elif defined(CONFIG_SANDBOX) # error "sandbox EFI support is only supported on ARM and x86" #else diff --git a/include/efi_default_filename.h b/include/efi_default_filename.h index 77932984b557..eb94a54514bc 100644 --- a/include/efi_default_filename.h +++ b/include/efi_default_filename.h @@ -47,6 +47,14 @@ #define BOOTEFI_NAME "BOOTRISCV32.EFI" #elif defined(CONFIG_ARCH_RV64I) #define BOOTEFI_NAME "BOOTRISCV64.EFI" +#elif defined(CONFIG_CPU_MIPS32) && defined(CONFIG_SYS_BIG_ENDIAN) +#define BOOTEFI_NAME "BOOTMIPS.EFI" +#elif defined(CONFIG_CPU_MIPS32) && defined(CONFIG_SYS_LITTLE_ENDIAN) +#define BOOTEFI_NAME "BOOTMIPSEL.EFI" +#elif defined(CONFIG_CPU_MIPS64) && defined(CONFIG_SYS_BIG_ENDIAN) +#define BOOTEFI_NAME "BOOTMIPS64.EFI" +#elif defined(CONFIG_CPU_MIPS64) && defined(CONFIG_SYS_LITTLE_ENDIAN) +#define BOOTEFI_NAME "BOOTMIPS64EL.EFI" #else #error Unsupported UEFI architecture #endif diff --git a/include/elf.h b/include/elf.h index a4ba74d8abeb..95de6ffbce31 100644 --- a/include/elf.h +++ b/include/elf.h @@ -545,6 +545,9 @@ typedef struct { #define DT_LOPROC 0x70000000 /* reserved range for processor */ #define DT_HIPROC 0x7fffffff /* specific dynamic array tags */
+/* MIPS */ +#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local got entries */
/* Dynamic Tag Flags - d_un.d_val */ #define DF_ORIGIN 0x01 /* Object may use DF_ORIGIN */ #define DF_SYMBOLIC 0x02 /* Symbol resolutions starts here */ @@ -699,6 +702,11 @@ unsigned long elf_hash(const unsigned char *name); #define R_RISCV_64 2 #define R_RISCV_RELATIVE 3
+/* MIPS Relocations */ +#define R_MIPS_NONE 0 +#define R_MIPS_REL32 3 +#define R_MIPS_64 18
#ifndef __ASSEMBLY__ int valid_elf_image(unsigned long addr); unsigned long load_elf64_image_phdr(unsigned long addr); diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index cedc4d822fe7..8df469851851 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -51,6 +51,23 @@ static int machines[] = { IMAGE_FILE_MACHINE_RISCV64, #endif
+#if defined(__mips__) && (__mips == 32) && defined(__BIG_ENDIAN)
IMAGE_FILE_MACHINE_R3000_BE,
+#endif
+#if defined(__mips__) && (__mips == 32) && defined(__LITTLE_ENDIAN)
IMAGE_FILE_MACHINE_R3000,
+#endif
+#if defined(__mips__) && (__mips == 64) && defined(__BIG_ENDIAN)
IMAGE_FILE_MACHINE_R4000_BE,
+#endif
+#if defined(__mips__) && (__mips == 64) && defined(__LITTLE_ENDIAN)
IMAGE_FILE_MACHINE_R4000,
IMAGE_FILE_MACHINE_R10000,
+#endif
0 };
/** diff --git a/lib/efi_selftest/efi_selftest_miniapp_exception.c b/lib/efi_selftest/efi_selftest_miniapp_exception.c index f668cdac4ab2..f3b4ee926f8f 100644 --- a/lib/efi_selftest/efi_selftest_miniapp_exception.c +++ b/lib/efi_selftest/efi_selftest_miniapp_exception.c @@ -33,6 +33,8 @@ efi_status_t EFIAPI efi_main(efi_handle_t handle, asm volatile (".word 0xe7f7defb\n"); #elif defined(CONFIG_RISCV) asm volatile (".word 0xffffffff\n"); +#elif defined(CONFIG_MIPS)
asm volatile ("break 0xf\n");
#elif defined(CONFIG_X86) asm volatile (".word 0xffff\n"); #elif defined(CONFIG_SANDBOX)
-- 2.34.1
Acked-by: Ilias Apalodimas ilias.apalodimas@linaro.org

Implemented crt, ELF and EFI linking, ELF relocation handling and other necessary bits for MIPS EFI.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- arch/mips/config.mk | 9 ++ arch/mips/lib/Makefile | 13 +++ arch/mips/lib/crt0_mips_efi.S | 239 +++++++++++++++++++++++++++++++++++++++++ arch/mips/lib/elf_mips_efi.lds | 113 +++++++++++++++++++ arch/mips/lib/reloc_mips_efi.c | 99 +++++++++++++++++ lib/efi_loader/Kconfig | 2 +- 6 files changed, 474 insertions(+), 1 deletion(-)
diff --git a/arch/mips/config.mk b/arch/mips/config.mk index 745f03190e98..e970858c1e59 100644 --- a/arch/mips/config.mk +++ b/arch/mips/config.mk @@ -36,6 +36,10 @@ endif PLATFORM_CPPFLAGS += -D__MIPS__ PLATFORM_ELFFLAGS += -B mips $(OBJCOPYFLAGS)
+EFI_LDS := elf_mips_efi.lds +EFI_CRT0 := crt0_mips_efi.o +EFI_RELOC := reloc_mips_efi.o + # # From Linux arch/mips/Makefile # @@ -66,3 +70,8 @@ LDFLAGS_FINAL += --gc-sections OBJCOPYFLAGS += -j .text -j .rodata -j .data -j __u_boot_list
LDFLAGS_STANDALONE += --gc-sections + +CFLAGS_EFI := -fPIE -mabicalls +AFLAGS_EFI := -fPIE -mabicalls +CFLAGS_NON_EFI := -mno-abicalls -fno-pic -fno-PIE +AFLAGS_NON_EFI := -mno-abicalls -fno-pic -fno-PIE diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index e36dfd0547b5..eef663febe47 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -17,3 +17,16 @@ obj-$(CONFIG_CMD_GO) += boot.o obj-$(CONFIG_SPL_BUILD) += spl.o
lib-$(CONFIG_USE_PRIVATE_LIBGCC) += ashldi3.o ashrdi3.o lshrdi3.o udivdi3.o + +# For building EFI apps +CFLAGS_$(EFI_CRT0) := $(CFLAGS_EFI) +CFLAGS_REMOVE_$(EFI_CRT0) := $(CFLAGS_NON_EFI) +AFLAGS_$(EFI_CRT0) := $(CFLAGS_EFI) +AFLAGS_REMOVE_$(EFI_CRT0) := $(CFLAGS_NON_EFI) + +CFLAGS_$(EFI_RELOC) := $(CFLAGS_EFI) +CFLAGS_REMOVE_$(EFI_RELOC) := $(CFLAGS_NON_EFI) + +extra-$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE) += $(EFI_CRT0) $(EFI_RELOC) +extra-$(CONFIG_CMD_BOOTEFI_SELFTEST) += $(EFI_CRT0) $(EFI_RELOC) +extra-$(CONFIG_EFI) += $(EFI_CRT0) $(EFI_RELOC) diff --git a/arch/mips/lib/crt0_mips_efi.S b/arch/mips/lib/crt0_mips_efi.S new file mode 100644 index 000000000000..84acee620d14 --- /dev/null +++ b/arch/mips/lib/crt0_mips_efi.S @@ -0,0 +1,239 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * crt0-efi-mips64el.S - PE/COFF header for MIPS64 EFI applications + * + * Copright (C) 2014 Linaro Ltd. ard.biesheuvel@linaro.org + * Copright (C) 2017 Heiher r@hev.cc + * Copright (C) 2024 Jiaxun Yang jiaxun.yang@flygoat.com + */ + +#include <asm/asm.h> +#include <asm-generic/pe.h> + +#if __mips == 64 +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define PE_MACHINE IMAGE_FILE_MACHINE_R4000 +#else +#define PE_MACHINE IMAGE_FILE_MACHINE_R4000_BE +#endif +#define PE_MAGIC IMAGE_NT_OPTIONAL_HDR64_MAGIC +#define IMG_CHARACTERISTICS \ + (IMAGE_FILE_EXECUTABLE_IMAGE | \ + IMAGE_FILE_LINE_NUMS_STRIPPED | \ + IMAGE_FILE_LOCAL_SYMS_STRIPPED | \ + IMAGE_FILE_LARGE_ADDRESS_AWARE | \ + IMAGE_FILE_DEBUG_STRIPPED) +#else +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define PE_MACHINE IMAGE_FILE_MACHINE_R3000 +#else +#define PE_MACHINE IMAGE_FILE_MACHINE_R3000_BE +#endif +#define PE_MAGIC IMAGE_NT_OPTIONAL_HDR32_MAGIC +#define IMG_CHARACTERISTICS \ + (IMAGE_FILE_EXECUTABLE_IMAGE | \ + IMAGE_FILE_LINE_NUMS_STRIPPED | \ + IMAGE_FILE_LOCAL_SYMS_STRIPPED | \ + IMAGE_FILE_DEBUG_STRIPPED) +#endif + + + .section .text.head + + /* + * Magic "MZ" signature for PE/COFF + */ + .globl ImageBase +ImageBase: + .2byte IMAGE_DOS_SIGNATURE /* 'MZ' */ + .skip 58 /* 'MZ' + pad + offset == 64 */ + .4byte pe_header - ImageBase /* Offset to the PE header */ +pe_header: + .4byte IMAGE_NT_SIGNATURE /* 'PE' */ +coff_header: + .2byte PE_MACHINE /* Machine Magic */ + .2byte 3 /* nr_sections */ + .4byte 0 /* TimeDateStamp */ + .4byte 0 /* PointerToSymbolTable */ + .4byte 0 /* NumberOfSymbols */ + .2byte section_table - optional_header /* SizeOfOptionalHeader */ + .2byte IMG_CHARACTERISTICS /* Characteristics */ + +optional_header: + .2byte PE_MAGIC /* PE32(+) format */ + .byte 0x02 /* MajorLinkerVersion */ + .byte 0x14 /* MinorLinkerVersion */ + .4byte _edata - _start /* SizeOfCode */ + .4byte 0 /* SizeOfInitializedData */ + .4byte 0 /* SizeOfUninitializedData */ + .4byte _start - ImageBase /* AddressOfEntryPoint */ + .4byte _start - ImageBase /* BaseOfCode */ +#if __mips != 64 + .4byte 0 /* BaseOfData */ +#endif + +extra_header_fields: +#if __mips == 64 + .8byte 0 /* ImageBase */ +#else + .4byte 0 /* ImageBase */ +#endif + .4byte 0x20 /* SectionAlignment */ + .4byte 0x8 /* FileAlignment */ + .2byte 0 /* MajorOperatingSystemVersion */ + .2byte 0 /* MinorOperatingSystemVersion */ + .2byte 1 /* MajorImageVersion */ + .2byte 0 /* MinorImageVersion */ + .2byte 0 /* MajorSubsystemVersion */ + .2byte 0 /* MinorSubsystemVersion */ + .4byte 0 /* Win32VersionValue */ + + .4byte _edata - ImageBase /* SizeOfImage */ + + /* + * Everything before the kernel image is considered part of the header + */ + .4byte _start - ImageBase /* SizeOfHeaders */ + .4byte 0 /* CheckSum */ + .short IMAGE_SUBSYSTEM_EFI_APPLICATION /* Subsystem */ +#if CONFIG_VENDOR_EFI + .short 0 /* DllCharacteristics */ +#else + .short IMAGE_DLLCHARACTERISTICS_NX_COMPAT +#endif +#if __mips == 64 + .8byte 0 /* SizeOfStackReserve */ + .8byte 0 /* SizeOfStackCommit */ + .8byte 0 /* SizeOfHeapReserve */ + .8byte 0 /* SizeOfHeapCommit */ +#else + .4byte 0 /* SizeOfStackReserve */ + .4byte 0 /* SizeOfStackCommit */ + .4byte 0 /* SizeOfHeapReserve */ + .4byte 0 /* SizeOfHeapCommit */ +#endif + .4byte 0 /* LoaderFlags */ + .4byte 0x6 /* LoaderFlags */ + + .4byte 0 /* ExportTable */ + .4byte 0 /* ImportTable */ + .4byte 0 /* ResourceTable */ + .4byte 0 /* ExceptionTable */ + .4byte 0 /* CertificationTable */ + .4byte 0 /* BaseRelocationTable */ + + // Section table +section_table: + + /* + * The EFI application loader requires a relocation section + * because EFI applications must be relocatable. This is a + * dummy section as far as we are concerned. + */ + .ascii ".reloc" + .byte 0 + .byte 0 /* end of 0 padding of section name */ + .4byte 0 + .4byte 0 + .4byte 0 /* SizeOfRawData */ + .4byte 0 /* PointerToRawData */ + .4byte 0 /* PointerToRelocations */ + .4byte 0 /* PointerToLineNumbers */ + .short 0 /* NumberOfRelocations */ + .short 0 /* NumberOfLineNumbers */ + .4byte 0x42100040 /* Characteristics (section flags) */ + + .ascii ".text" + .byte 0 + .byte 0 + .byte 0 /* end of 0 padding of section name */ + .4byte _etext - _start /* VirtualSize */ + .4byte _start - ImageBase /* VirtualAddress */ + .4byte _etext - _start /* SizeOfRawData */ + .4byte _start - ImageBase /* PointerToRawData */ + + .4byte 0 /* PointerToRelocations (0 for executables) */ + .4byte 0 /* PointerToLineNumbers (0 for executables) */ + .2byte 0 /* NumberOfRelocations (0 for executables) */ + .2byte 0 /* NumberOfLineNumbers (0 for executables) */ + /* Characteristics (section flags) */ + .4byte (IMAGE_SCN_MEM_READ | \ + IMAGE_SCN_MEM_EXECUTE | \ + IMAGE_SCN_CNT_CODE) + + .ascii ".data" + .byte 0 + .byte 0 + .byte 0 /* end of 0 padding of section name */ + .4byte _data_size /* VirtualSize */ + .4byte _etext - ImageBase /* VirtualAddress */ + .4byte _data_size /* SizeOfRawData */ + .4byte _etext - ImageBase /* PointerToRawData */ + .4byte 0 /* PointerToRelocations */ + .4byte 0 /* PointerToLineNumbers */ + .2byte 0 /* NumberOfRelocations */ + .2byte 0 /* NumberOfLineNumbers */ + /* Characteristics (section flags) */ + .4byte (IMAGE_SCN_MEM_WRITE | \ + IMAGE_SCN_MEM_READ | \ + IMAGE_SCN_CNT_INITIALIZED_DATA) + + .align 4 + + .globl _start + .ent _start + .type _start, @function +_start: + LONG_ADDIU $sp, -(LONGSIZE * 4) + LONG_S $ra, ($sp) + + // Get pc & gp + .set push + .set noreorder + .align LONGLOG + bal 1f + LONG_S $gp, (1 * LONGSIZE)($sp) /* Delay slot */ +_pc: + PTR _gp + PTR _DYNAMIC + PTR _relocate +1: + .set pop + // pc in ra + PTR_L $gp, ($ra) + PTR_LI $t0, _pc + PTR_SUBU $gp, $t0 + PTR_ADDU $gp, $ra + + LONG_S $a0, (2 * LONGSIZE)($sp) + LONG_S $a1, (3 * LONGSIZE)($sp) + + /* a0: ImageBase */ + PTR_LI $t1, ImageBase - _pc + PTR_ADDU $a0, $ra, $t1 + /* a1: DynamicSection */ + PTR_L $t1, (1 * PTRSIZE)($ra) + PTR_SUBU $t1, $t0 + PTR_ADDU $a1, $ra, $t1 + /* call _relocate */ + PTR_L $t1, (2 * PTRSIZE)($ra) + PTR_SUBU $t1, $t0 + PTR_ADDU $t9, $ra, $t1 + jalr $t9 + /* Return early */ + bnez $v0, 1b + + /* a0: ImageHandle */ + LONG_L $a0, (2 * LONGSIZE)($sp) + /* a1: SystemTable */ + LONG_L $a1, (3 * LONGSIZE)($sp) + /* Load the entry point */ + PTR_LA $t9, efi_main + jalr $t9 + +1: + LONG_L $gp, (1 * LONGSIZE)($sp) + LONG_L $ra, ($sp) + LONG_ADDIU $sp, (LONGSIZE * 4) + jr $ra +.end _start diff --git a/arch/mips/lib/elf_mips_efi.lds b/arch/mips/lib/elf_mips_efi.lds new file mode 100644 index 000000000000..31039c3d4843 --- /dev/null +++ b/arch/mips/lib/elf_mips_efi.lds @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * U-Boot MIPS EFI linker script + * + * Modified from elf_mips64el_efi.lds in gnu-efi + */ + +OUTPUT_ARCH(mips) +ENTRY(_start) + +SECTIONS +{ + .text 0x0 : { + _text = .; + *(.text.head) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.plt) + . = ALIGN(16); + } + _etext = .; + _text_size = _etext - _text; + . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + .dynamic : { *(.dynamic) } + . = ALIGN(4096); + .data : + { + _data = .; + *(.sdata) + *(.data) + *(.data1) + *(.data.*) + *(.got.plt) + HIDDEN (_gp = ALIGN (16) + 0x7ff0); + *(.got) + + /* + * Note that these aren't the using the GNU "CONSTRUCTOR" output section + * command, so they don't start with a size. Because of p2align and the + * end/END definitions, and the fact that they're mergeable, they can also + * have NULLs which aren't guaranteed to be at the end. + */ + . = ALIGN(16); + __init_array_start = .; + *(SORT(.init_array.*)) + *(.init_array) + __init_array_end = .; + . = ALIGN(16); + __CTOR_LIST__ = .; + *(SORT(.ctors.*)) + *(.ctors) + __CTOR_END__ = .; + . = ALIGN(16); + __DTOR_LIST__ = .; + *(SORT(.dtors.*)) + *(.dtors) + __DTOR_END__ = .; + . = ALIGN(16); + __fini_array_start = .; + *(SORT(.fini_array.*)) + *(.fini_array) + __fini_array_end = .; + + /* the EFI loader doesn't seem to like a .bss section, so we stick + it all into .data: */ + . = ALIGN(16); + _bss = .; + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss*) + *(COMMON) + . = ALIGN(16); + _bss_end = .; + } + + . = ALIGN(4096); + .rel : + { + *(.rel.text*) + *(.rel.data*) + *(.rel.got) + *(.rel.dyn) + *(.rel.stab) + *(.rel.init_array*) + *(.rel.fini_array*) + *(.rel.ctors*) + *(.rel.dtors*) + } + . = ALIGN(4096); + .rel.plt : { *(.rel.plt) } + . = ALIGN(4096); + .rodata : { *(.rodata*) } + _edata = .; + _data_size = _edata - _etext; + + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .note.gnu.build-id : { *(.note.gnu.build-id) } + . = DATA_SEGMENT_END (.); + /DISCARD/ : + { + *(.rel.reloc) + *(.eh_frame) + *(.MIPS.abiflags) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} diff --git a/arch/mips/lib/reloc_mips_efi.c b/arch/mips/lib/reloc_mips_efi.c new file mode 100644 index 000000000000..ee4f95d9e783 --- /dev/null +++ b/arch/mips/lib/reloc_mips_efi.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * reloc_mips64el.c - position independent MIPS64 ELF shared object relocator + * + * Copyright (C) 2014 Linaro Ltd. ard.biesheuvel@linaro.org + * Copyright (C) 1999 Hewlett-Packard Co. + * Contributed by David Mosberger davidm@hpl.hp.com. + * Copyright (C) 2017 Lemote Co. + * Contributed by Heiher r@hev.cc + * Copyright (C) 2024 Jiaxun Yang jiaxun.yang@flygoat.com + */ + +#include <efi.h> +#include <elf.h> + +#include <asm/byteorder.h> + +#if __mips == 64 +#define Elf_Dyn Elf64_Dyn +#define Elf_Rel Elf64_Rel +#define ELF_R_TYPE ELF64_R_TYPE +#define R_MIPS_RELATIVE ((R_MIPS_64 << 8) | R_MIPS_REL32) +#define swabl(x) swab64(x) +#else +#define Elf_Dyn Elf32_Dyn +#define Elf_Rel Elf32_Rel +#define ELF_R_TYPE ELF32_R_TYPE +#define R_MIPS_RELATIVE R_MIPS_REL32 +#define swabl(x) swab32(x) +#endif + +efi_status_t EFIAPI _relocate(long ldbase, Elf_Dyn *dyn) +{ + long relsz = 0, relent = 0, gotsz = 0; + Elf_Rel *rel = 0; + unsigned long *addr = 0; + int i; + + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { + switch (dyn[i].d_tag) { + case DT_REL: + rel = (Elf_Rel *) + ((unsigned long)dyn[i].d_un.d_ptr + + ldbase); + break; + + case DT_RELSZ: + relsz = dyn[i].d_un.d_val; + break; + + case DT_RELENT: + relent = dyn[i].d_un.d_val; + break; + + case DT_PLTGOT: + addr = (unsigned long *) + ((unsigned long)dyn[i].d_un.d_ptr + + ldbase); + break; + + case DT_MIPS_LOCAL_GOTNO: + gotsz = dyn[i].d_un.d_val; + break; + + default: + break; + } + } + + if ((!rel && relent == 0) && (!addr && gotsz == 0)) + return EFI_SUCCESS; + + if ((!rel && relent != 0) || (!addr && gotsz != 0)) + return EFI_LOAD_ERROR; + + while (gotsz > 0) { + *addr += ldbase; + addr += 1; + gotsz--; + } + + while (relsz > 0) { + /* apply the relocs */ + switch (ELF_R_TYPE(swabl(rel->r_info))) { + case R_MIPS_NONE: + break; + case R_MIPS_RELATIVE: + addr = (unsigned long *)(ldbase + rel->r_offset); + *addr += ldbase; + break; + default: + break; + } + rel = (Elf_Rel *)((char *) rel + relent); + relsz -= relent; + } + + return EFI_SUCCESS; +} diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index bc5ae9086ea2..a9b006fa6d24 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -5,7 +5,7 @@ config EFI_LOADER SYS_CPU = arm1176 || \ SYS_CPU = armv7 || \ SYS_CPU = armv8) || \ - X86 || RISCV || SANDBOX) + X86 || RISCV || MIPS || SANDBOX) # We need EFI_STUB_64BIT to be set on x86_64 with EFI_STUB depends on !EFI_STUB || !X86_64 || EFI_STUB_64BIT # We need EFI_STUB_32BIT to be set on x86_32 with EFI_STUB

Am 17. Mai 2024 18:32:51 MESZ schrieb Jiaxun Yang jiaxun.yang@flygoat.com:
Hi all,
This series enabled EFI support to MIPS platform.
Although MIPS is not defined by UEFI specification, there are quite a few firmware implementations available, including MIPS-EFI[1] for Loongson-2F, Lemote's proprietary EDK2 implementation on Loongson-3[2], Kunlun firmware for Loongson-3[3], efiffy[4] for MIPS Creator CI20 and another mystery EDK implementation shipped with some Creator CI20 board.
Available applications including gnu-efi, Loongson's GRUB fork[5], Ventoy[6].
My implementation in U-Boot is aiming to follow conventions made by other implementations for architecture stuff and remain compliance with spec for general aspects.
bootefi hello and selftest passed on both 32 and 64 bit system, gnu-efi, grub and ventoy are tested on mips64el with my pending platform works. mips32el efi executable from efiffy is tested as well.
Please review. Thanks
Implementing the Loongarch architecture defined in https://uefi.org/specs/UEFI/2.10/02_Overview.html#loongarch-platforms would make sense to me.
Supporting an architecture that does not have published UEFI standards is less convincing.
Is any of the mentioned boards being produced anymore?
Best regards
Heinrich
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
Jiaxun Yang (7): MIPS: Implement setjmp efi: Allow runtime relocate to be disabled Makefile.lib: Preserve .rodata section for EFI file Makefile.lib: Enforce EFI CFLAGS/AFLAGS MIPS: Add smbios_start to arch_global_data MIPS: Define MIPS EFI related bits everywhere MIPS: Implement EFI supporting stuff
Makefile | 3 + arch/mips/config.mk | 9 + arch/mips/include/asm/global_data.h | 3 + arch/mips/include/asm/setjmp.h | 36 ++++ arch/mips/lib/Makefile | 15 ++ arch/mips/lib/crt0_mips_efi.S | 239 ++++++++++++++++++++++ arch/mips/lib/elf_mips_efi.lds | 113 ++++++++++ arch/mips/lib/reloc_mips_efi.c | 99 +++++++++ arch/mips/lib/setjmp32.S | 51 +++++ arch/mips/lib/setjmp64.S | 56 +++++ include/asm-generic/pe.h | 5 + include/config_distro_bootcmd.h | 6 + include/efi_default_filename.h | 8 + include/efi_loader.h | 26 ++- include/elf.h | 8 + lib/efi_loader/Kconfig | 12 +- lib/efi_loader/efi_image_loader.c | 18 ++ 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 +- lib/efi_selftest/efi_selftest_miniapp_exception.c | 2 + scripts/Makefile.lib | 10 +- 23 files changed, 734 insertions(+), 18 deletions(-)
base-commit: ad7dce5abd49ef3b5c93da5303e15449c8c162b4 change-id: 20240517-mips-efi-c9a1ad819c2d
Best regards,

在2024年5月17日五月 下午6:12,Heinrich Schuchardt写道: [...]
as well.
Please review. Thanks
Implementing the Loongarch architecture defined in https://uefi.org/specs/UEFI/2.10/02_Overview.html#loongarch-platforms would make sense to me.
Supporting an architecture that does not have published UEFI standards is less convincing.
Is any of the mentioned boards being produced anymore?
Hi Heinrich,
Yes, MIPS/Loongson boards are still producing for many existing applications. There will be some future MIPS product from CIP United [1], and I think get EBBR like booting stuff implemented can save a lot of hassle.
I also intended to use UEFI as loongson3-virt firmware, supporting actual Loongson hardware is out of my scope.
I'm a hobbyist (and contractor) on MIPS stuff, so I don't really know details on LoongArch UEFI.
Thanks
[1]: http://www.cipunited.com/
Best regards
Heinrich
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
Jiaxun Yang (7): MIPS: Implement setjmp efi: Allow runtime relocate to be disabled Makefile.lib: Preserve .rodata section for EFI file Makefile.lib: Enforce EFI CFLAGS/AFLAGS MIPS: Add smbios_start to arch_global_data MIPS: Define MIPS EFI related bits everywhere MIPS: Implement EFI supporting stuff
Makefile | 3 + arch/mips/config.mk | 9 + arch/mips/include/asm/global_data.h | 3 + arch/mips/include/asm/setjmp.h | 36 ++++ arch/mips/lib/Makefile | 15 ++ arch/mips/lib/crt0_mips_efi.S | 239 ++++++++++++++++++++++ arch/mips/lib/elf_mips_efi.lds | 113 ++++++++++ arch/mips/lib/reloc_mips_efi.c | 99 +++++++++ arch/mips/lib/setjmp32.S | 51 +++++ arch/mips/lib/setjmp64.S | 56 +++++ include/asm-generic/pe.h | 5 + include/config_distro_bootcmd.h | 6 + include/efi_default_filename.h | 8 + include/efi_loader.h | 26 ++- include/elf.h | 8 + lib/efi_loader/Kconfig | 12 +- lib/efi_loader/efi_image_loader.c | 18 ++ 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 +- lib/efi_selftest/efi_selftest_miniapp_exception.c | 2 + scripts/Makefile.lib | 10 +- 23 files changed, 734 insertions(+), 18 deletions(-)
base-commit: ad7dce5abd49ef3b5c93da5303e15449c8c162b4 change-id: 20240517-mips-efi-c9a1ad819c2d
Best regards,

On 17.05.24 18:32, Jiaxun Yang wrote:
Hi all,
This series enabled EFI support to MIPS platform.
Although MIPS is not defined by UEFI specification, there are quite a few firmware implementations available, including MIPS-EFI[1] for Loongson-2F, Lemote's proprietary EDK2 implementation on Loongson-3[2], Kunlun firmware for Loongson-3[3], efiffy[4] for MIPS Creator CI20 and another mystery EDK implementation shipped with some Creator CI20 board.
Available applications including gnu-efi, Loongson's GRUB fork[5], Ventoy[6].
My implementation in U-Boot is aiming to follow conventions made by other implementations for architecture stuff and remain compliance with spec for general aspects.
bootefi hello and selftest passed on both 32 and 64 bit system, gnu-efi, grub and ventoy are tested on mips64el with my pending platform works. mips32el efi executable from efiffy is tested as well.
Please review. Thanks
Last commit 8 years ago.
Last commit 4 years ago.
Last commit 2018.
Last commit 5 year ago.
This looks like riding a dead horse.
Best regards
Heinrich
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
Jiaxun Yang (7): MIPS: Implement setjmp efi: Allow runtime relocate to be disabled Makefile.lib: Preserve .rodata section for EFI file Makefile.lib: Enforce EFI CFLAGS/AFLAGS MIPS: Add smbios_start to arch_global_data MIPS: Define MIPS EFI related bits everywhere MIPS: Implement EFI supporting stuff
Makefile | 3 + arch/mips/config.mk | 9 + arch/mips/include/asm/global_data.h | 3 + arch/mips/include/asm/setjmp.h | 36 ++++ arch/mips/lib/Makefile | 15 ++ arch/mips/lib/crt0_mips_efi.S | 239 ++++++++++++++++++++++ arch/mips/lib/elf_mips_efi.lds | 113 ++++++++++ arch/mips/lib/reloc_mips_efi.c | 99 +++++++++ arch/mips/lib/setjmp32.S | 51 +++++ arch/mips/lib/setjmp64.S | 56 +++++ include/asm-generic/pe.h | 5 + include/config_distro_bootcmd.h | 6 + include/efi_default_filename.h | 8 + include/efi_loader.h | 26 ++- include/elf.h | 8 + lib/efi_loader/Kconfig | 12 +- lib/efi_loader/efi_image_loader.c | 18 ++ 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 +- lib/efi_selftest/efi_selftest_miniapp_exception.c | 2 + scripts/Makefile.lib | 10 +- 23 files changed, 734 insertions(+), 18 deletions(-)
base-commit: ad7dce5abd49ef3b5c93da5303e15449c8c162b4 change-id: 20240517-mips-efi-c9a1ad819c2d
Best regards,
participants (4)
-
Heinrich Schuchardt
-
Ilias Apalodimas
-
Jiaxun Yang
-
Maciej W. Rozycki