From: Michael Brown Date: Thu, 1 May 2025 13:04:27 +0000 (+0100) Subject: [riscv] Split out runtime relocator to libprefix.S X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a4b5dd63c5a99df3cfa2c4dd3cd0fd9019635b92;p=thirdparty%2Fipxe.git [riscv] Split out runtime relocator to libprefix.S Split out the runtime relocation logic from sbiprefix.S to a new library libprefix.S. Since this logically decouples the process of runtime relocation from the _sbi_start symbol (currently used to determine the base address for applying relocations), provide an alternative mechanism for the relocator to determine the base address. Signed-off-by: Michael Brown --- diff --git a/src/arch/riscv/prefix/libprefix.S b/src/arch/riscv/prefix/libprefix.S new file mode 100644 index 000000000..7f4d57000 --- /dev/null +++ b/src/arch/riscv/prefix/libprefix.S @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2025 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + + FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ) + +/** @file + * + * RISC-V prefix library + * + */ + + .section ".note.GNU-stack", "", @progbits + .text + +/***************************************************************************** + * + * Apply relocation records + * + ***************************************************************************** + * + * Apply relocation records from .rel.dyn to fix up iPXE to run at its + * current address. + * + * This function must run before .bss is zeroed (since the relocation + * records are overlaid with .bss). It does not require a valid stack + * pointer. + * + * Parameters: none (address is implicit in the program counter) + * + * Returns: none + * + */ + +/* Relative relocation type */ +#define R_RISCV_RELATIVE 3 + + /* Layout of a relocation record */ + .struct 0 +rela_offset: .space ( __riscv_xlen / 8 ) +rela_type: .space ( __riscv_xlen / 8 ) +rela_addend: .space ( __riscv_xlen / 8 ) +rela_len: + .previous + + .section ".prefix.apply_relocs", "ax", @progbits + .globl apply_relocs +apply_relocs: + + /* Get relocation records */ + la t0, _reloc + la t1, _ereloc + + /* Determine current location */ + la t2, reloc_base + LOADN t2, (t2) + sub t2, t0, t2 + +1: /* Read relocation record */ + LOADN t3, rela_offset(t0) + LOADN t4, rela_type(t0) + LOADN t5, rela_addend(t0) + + /* Check relocation type */ + addi t4, t4, -R_RISCV_RELATIVE + bnez t4, 2f + + /* Apply relocation */ + add t3, t3, t2 + add t5, t5, t2 + STOREN t5, (t3) +2: + /* Loop until done */ + addi t0, t0, rela_len + blt t0, t1, 1b + + /* Return to caller */ + ret + .size apply_relocs, . - apply_relocs + + /* Link-time address of _reloc */ + .section ".rodata", "a", @progbits +reloc_base: + .dword _reloc_base + .size reloc_base, . - reloc_base diff --git a/src/arch/riscv/prefix/sbiprefix.S b/src/arch/riscv/prefix/sbiprefix.S index e8ef40b6d..ccf8b0743 100644 --- a/src/arch/riscv/prefix/sbiprefix.S +++ b/src/arch/riscv/prefix/sbiprefix.S @@ -41,17 +41,6 @@ #define SBI_SRST_SYSTEM_RESET 0x00 #define SBI_RESET_COLD 0x00000001 -/* Relative relocation type */ -#define R_RISCV_RELATIVE 3 - - /* Layout of a relocation record */ - .struct 0 -rela_offset: .space ( __riscv_xlen / 8 ) -rela_type: .space ( __riscv_xlen / 8 ) -rela_addend: .space ( __riscv_xlen / 8 ) -rela_len: - .previous - /* * Display progress message via debug console */ @@ -85,23 +74,7 @@ _sbi_start: progress "\nSBI->iPXE" /* Apply dynamic relocations */ - la t0, _reloc - la t1, _ereloc - la t2, _sbi_start -1: /* Read relocation record */ - LOADN t3, rela_offset(t0) - LOADN t4, rela_type(t0) - LOADN t5, rela_addend(t0) - /* Check relocation type */ - addi t4, t4, -R_RISCV_RELATIVE - bnez t4, 2f - /* Apply relocation */ - add t3, t3, t2 - add t5, t5, t2 - STOREN t5, (t3) -2: /* Loop */ - addi t0, t0, rela_len - blt t0, t1, 1b + call apply_relocs progress " .reloc" /* Zero the bss */ diff --git a/src/arch/riscv/scripts/sbi.lds b/src/arch/riscv/scripts/sbi.lds index a65b27181..afb1902e1 100644 --- a/src/arch/riscv/scripts/sbi.lds +++ b/src/arch/riscv/scripts/sbi.lds @@ -87,6 +87,14 @@ SECTIONS { } } + /* Absolute link-time address of _reloc + * + * The runtime relocator needs to know the link-time addresses. + * Since RISC-V uses .rela (rather than .rel), the only way to + * expose this to the relocator is via an absolute symbol. + */ + _reloc_base = ABSOLUTE ( _reloc ); + /* Calculate end of relocations * * This cannot be done by placing "_ereloc = .;" inside the