[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 <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2025-05-01 14:04:27 +01:00
parent 1534b0a6e9
commit a4b5dd63c5
3 changed files with 113 additions and 28 deletions

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2025 Michael Brown <mbrown@fensystems.co.uk>.
*
* 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

View File

@@ -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 */

View File

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