From: Simon Glass <simon.glass@canonical.com> Add a linker script for building U-Boot as a RISC-V EFI application. This defines the PE/COFF .text and .data sections, the .reloc section for PE base relocations and the .embedded_dtb section (16-byte aligned) for the devicetree blob. Also add the EFI CRT0 and relocation objects to the build for EFI_APP so they are linked into the final binary. Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- arch/riscv/lib/Makefile | 2 + arch/riscv/lib/elf_riscv64_efi_app.lds | 136 +++++++++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 arch/riscv/lib/elf_riscv64_efi_app.lds diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile index 36712cbb5c9..b0b1cabf903 100644 --- a/arch/riscv/lib/Makefile +++ b/arch/riscv/lib/Makefile @@ -38,6 +38,8 @@ CFLAGS_REMOVE_$(EFI_CRT0) := $(CFLAGS_NON_EFI) CFLAGS_$(EFI_RELOC) := $(CFLAGS_EFI) CFLAGS_REMOVE_$(EFI_RELOC) := $(CFLAGS_NON_EFI) +obj-$(CONFIG_EFI_APP) += $(EFI_CRT0) $(EFI_RELOC) + obj-$(CONFIG_$(PHASE_)USE_ARCH_MEMSET) += memset.o obj-$(CONFIG_$(PHASE_)USE_ARCH_MEMMOVE) += memmove.o obj-$(CONFIG_$(PHASE_)USE_ARCH_MEMCPY) += memcpy.o diff --git a/arch/riscv/lib/elf_riscv64_efi_app.lds b/arch/riscv/lib/elf_riscv64_efi_app.lds new file mode 100644 index 00000000000..6374433cdb3 --- /dev/null +++ b/arch/riscv/lib/elf_riscv64_efi_app.lds @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * U-Boot riscv64 EFI application linker script + * + * Modified from lib/efi_loader/elf_efi.ldsi and + * arch/arm/lib/elf_aarch64_efi.lds + */ + +OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", "elf64-littleriscv") +OUTPUT_ARCH(riscv) +ENTRY(_start) +SECTIONS +{ + /* + * The .text section must come first at VMA 0 so that the PE/COFF + * header in .text.head is at the start of the binary. The CRT0 + * defines image_base at the very beginning of .text.head. + */ + .text 0x0 : { + _text = .; + *(.text.head) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.srodata) + *(.rodata*) + . = ALIGN(16); + *(.dynamic); + . = ALIGN(512); + } + . = ALIGN(4096); + _etext = .; + _text_size = . - _text; + + /* + * .hash and .gnu.hash are needed in the ELF for dynamic linking + * during the link step, but are not extracted into the PE binary. + */ + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .eh_frame : { *(.eh_frame) } + + . = ALIGN(65536); + .reloc : { + KEEP (*(.reloc)) + } + + /* + * Everything from _data to _edata makes up the PE .data section. + * The CRT0 PE header uses _edata for both VirtualSize and + * SizeOfRawData, so BSS must be included (as zero-filled file + * data) rather than in a separate section. + */ + . = ALIGN(4096); + _data = .; + + /* + * Dynamic relocations in .rela.dyn so the linker sets DT_RELA + * to point here. All relocation input sections are gathered + * into this single output section. + */ + .rela.dyn : { + *(.rela.dyn) + *(.rela.text*) + *(.rela.data*) + *(.rela.got) + *(.rela.stab) + *(.rela.init_array*) + *(.rela.fini_array*) + *(.rela.ctors*) + *(.rela.dtors*) + *(.rela__u_boot_list*) + } + + /* Dynamic symbol table and strings */ + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + + /* Embedded device tree (must be separate for embeddtb command) */ + . = ALIGN(16); + .embedded_dtb : { + *(.embedded_dtb) + } + + /* + * Regular data and BSS live together in one output section. + * Mixing PROGBITS (.data) and NOBITS (.bss) input sections in + * the same output section forces the linker to emit file content + * for the entire section, so BSS gets zero-filled in the file. + * This avoids a VMA gap that would bloat the PE binary. + */ + .data : { + *(.sdata) + *(.data) + *(.data1) + *(.data.*) + *(.got.plt) + *(.got) + + /* U-Boot lists */ + . = ALIGN(8); + KEEP(*(SORT(__u_boot_list*))); + . = ALIGN(8); + + /* BSS merged into data to get file content */ + . = ALIGN(16); + _bss = .; + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(512); + _bss_end = .; + _edata = .; + _end = .; + } + _data_size = _edata - _data; + + /* + * PLT relocations are placed after _edata so they do not fall + * within the DT_RELA range. _relocate() only handles + * R_RISCV_RELATIVE and would panic on R_RISCV_JUMP_SLOT entries. + */ + .rela.plt : { *(.rela.plt) } + + . = ALIGN(4096); + .note.gnu.build-id : { *(.note.gnu.build-id) } + /DISCARD/ : { + *(.rel.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} -- 2.43.0