[Concept,09/15] riscv: Add EFI app linker script and build CRT objects

Message ID 20260212001410.1919749-10-sjg@u-boot.org
State New
Headers
Series riscv: Add EFI-application support |

Commit Message

Simon Glass Feb. 12, 2026, 12:14 a.m. UTC
  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
  

Patch

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