mirror of
https://github.com/ipxe/ipxe
synced 2026-03-16 03:02:07 +03:00
[riscv] Avoid potentially overwriting the scratch area during relocation
We do not currently describe the temporary page table or the temporary stack as areas to be avoided during relocation of the iPXE image to a new physical address. Perform the copy of the iPXE image and zeroing of the .bss within libprefix.S, after we have no futher use for the temporary page table or the temporary initial stack. Perform the copy and registration of the system device tree in C code after relocation is complete and the new stack (within .bss) has been set up. This provides a clean separation of responsibilities between the RISC-V libprefix.S and the architecture-independent fdtmem.c. The prefix is responsible only for relocating iPXE to the new physical address returned from fdtmem_relocate(), and doesn't need to know or care where fdtmem.c is planning to place the copy of the device tree. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -1023,6 +1023,21 @@ install:
|
|||||||
la s6, _prefix
|
la s6, _prefix
|
||||||
sub s6, s5, s6
|
sub s6, s5, s6
|
||||||
|
|
||||||
|
/* Copy iPXE image to new location and zero .bss */
|
||||||
|
mv t0, s5
|
||||||
|
la t1, _prefix
|
||||||
|
la t2, _edata
|
||||||
|
1: LOADN t3, (t1)
|
||||||
|
STOREN t3, (t0)
|
||||||
|
addi t0, t0, ( __riscv_xlen / 8 )
|
||||||
|
addi t1, t1, ( __riscv_xlen / 8 )
|
||||||
|
blt t1, t2, 1b
|
||||||
|
la t1, _ebss
|
||||||
|
add t1, t1, s6
|
||||||
|
2: STOREN zero, (t0)
|
||||||
|
addi t0, t0, ( __riscv_xlen / 8 )
|
||||||
|
blt t0, t1, 2b
|
||||||
|
|
||||||
/* Jump to relocated copy */
|
/* Jump to relocated copy */
|
||||||
la t0, 1f
|
la t0, 1f
|
||||||
add t0, t0, s6
|
add t0, t0, s6
|
||||||
@@ -1042,11 +1057,9 @@ install:
|
|||||||
/* Store boot hart */
|
/* Store boot hart */
|
||||||
STOREN s0, boot_hart, t0
|
STOREN s0, boot_hart, t0
|
||||||
|
|
||||||
/* Register copy of device tree as system device tree */
|
/* Copy and register system device tree */
|
||||||
la a0, sysfdt
|
phys_to_virt a0, s1
|
||||||
la a1, _end
|
call fdtmem_register
|
||||||
li a2, -1
|
|
||||||
call fdt_parse
|
|
||||||
|
|
||||||
/* Return to a virtual address in the relocated copy */
|
/* Return to a virtual address in the relocated copy */
|
||||||
add ra, s2, s6
|
add ra, s2, s6
|
||||||
|
|||||||
@@ -41,20 +41,15 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
/** Start address of the iPXE image */
|
/** Start address of the iPXE image */
|
||||||
extern char _prefix[];
|
extern char _prefix[];
|
||||||
|
|
||||||
/** Initialised-data size of the iPXE image (defined by linker) */
|
/** End address of the iPXE image */
|
||||||
extern size_t ABS_SYMBOL ( _filesz );
|
extern char _end[];
|
||||||
static size_t filesz = ABS_VALUE_INIT ( _filesz );
|
|
||||||
|
|
||||||
/** In-memory size of the iPXE image (defined by linker) */
|
|
||||||
extern size_t ABS_SYMBOL ( _memsz );
|
|
||||||
static size_t memsz = ABS_VALUE_INIT ( _memsz );
|
|
||||||
|
|
||||||
/** Relocation required alignment (defined by prefix or linker) */
|
/** Relocation required alignment (defined by prefix or linker) */
|
||||||
extern physaddr_t ABS_SYMBOL ( _max_align );
|
extern physaddr_t ABS_SYMBOL ( _max_align );
|
||||||
static physaddr_t max_align = ABS_VALUE_INIT ( _max_align );
|
static physaddr_t max_align = ABS_VALUE_INIT ( _max_align );
|
||||||
|
|
||||||
/** Colour for debug messages */
|
/** Colour for debug messages */
|
||||||
#define colour &memsz
|
#define colour &_prefix[0]
|
||||||
|
|
||||||
/** A memory region descriptor */
|
/** A memory region descriptor */
|
||||||
struct fdtmem_region {
|
struct fdtmem_region {
|
||||||
@@ -278,8 +273,8 @@ physaddr_t fdtmem_relocate ( struct fdt_header *hdr, size_t limit ) {
|
|||||||
physaddr_t old;
|
physaddr_t old;
|
||||||
physaddr_t new;
|
physaddr_t new;
|
||||||
physaddr_t try;
|
physaddr_t try;
|
||||||
|
size_t memsz;
|
||||||
size_t len;
|
size_t len;
|
||||||
void *dest;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
@@ -297,6 +292,7 @@ physaddr_t fdtmem_relocate ( struct fdt_header *hdr, size_t limit ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Determine required length */
|
/* Determine required length */
|
||||||
|
memsz = ( _end - _prefix );
|
||||||
assert ( memsz > 0 );
|
assert ( memsz > 0 );
|
||||||
assert ( ( memsz % FDT_MAX_ALIGN ) == 0 );
|
assert ( ( memsz % FDT_MAX_ALIGN ) == 0 );
|
||||||
len = ( memsz + fdt.len );
|
len = ( memsz + fdt.len );
|
||||||
@@ -355,15 +351,39 @@ physaddr_t fdtmem_relocate ( struct fdt_header *hdr, size_t limit ) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy iPXE and device tree to new location */
|
|
||||||
if ( new != old ) {
|
|
||||||
dest = phys_to_virt ( new );
|
|
||||||
memset ( dest, 0, len );
|
|
||||||
memcpy ( dest, _prefix, filesz );
|
|
||||||
memcpy ( ( dest + memsz ), hdr, fdt.len );
|
|
||||||
}
|
|
||||||
|
|
||||||
DBGC ( colour, "FDTMEM relocating %#08lx => [%#08lx,%#08lx]\n",
|
DBGC ( colour, "FDTMEM relocating %#08lx => [%#08lx,%#08lx]\n",
|
||||||
old, new, ( ( physaddr_t ) ( new + len - 1 ) ) );
|
old, new, ( ( physaddr_t ) ( new + len - 1 ) ) );
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy and register system device tree
|
||||||
|
*
|
||||||
|
* @v hdr FDT header
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
int fdtmem_register ( struct fdt_header *hdr ) {
|
||||||
|
struct fdt_header *copy;
|
||||||
|
struct fdt fdt;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Parse FDT to obtain length */
|
||||||
|
if ( ( rc = fdt_parse ( &fdt, hdr, -1UL ) ) != 0 ) {
|
||||||
|
DBGC ( colour, "FDTMEM could not parse FDT: %s\n",
|
||||||
|
strerror ( rc ) );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy device tree to end of iPXE image */
|
||||||
|
copy = ( ( void * ) _end );
|
||||||
|
memcpy ( copy, hdr, fdt.len );
|
||||||
|
|
||||||
|
/* Register copy as system device tree */
|
||||||
|
if ( ( rc = fdt_parse ( &sysfdt, copy, -1UL ) ) != 0 ) {
|
||||||
|
DBGC ( colour, "FDTMEM could not register FDT: %s\n",
|
||||||
|
strerror ( rc ) );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,5 +13,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
#include <ipxe/fdt.h>
|
#include <ipxe/fdt.h>
|
||||||
|
|
||||||
extern physaddr_t fdtmem_relocate ( struct fdt_header *hdr, size_t limit );
|
extern physaddr_t fdtmem_relocate ( struct fdt_header *hdr, size_t limit );
|
||||||
|
extern int fdtmem_register ( struct fdt_header *hdr );
|
||||||
|
|
||||||
#endif /* _IPXE_FDTMEM_H */
|
#endif /* _IPXE_FDTMEM_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user