la s6, _prefix
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 */
la t0, 1f
add t0, t0, s6
/* Store boot hart */
STOREN s0, boot_hart, t0
- /* Register copy of device tree as system device tree */
- la a0, sysfdt
- la a1, _end
- li a2, -1
- call fdt_parse
+ /* Copy and register system device tree */
+ phys_to_virt a0, s1
+ call fdtmem_register
/* Return to a virtual address in the relocated copy */
add ra, s2, s6
/** Start address of the iPXE image */
extern char _prefix[];
-/** Initialised-data size of the iPXE image (defined by linker) */
-extern size_t ABS_SYMBOL ( _filesz );
-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 );
+/** End address of the iPXE image */
+extern char _end[];
/** Relocation required alignment (defined by prefix or linker) */
extern physaddr_t ABS_SYMBOL ( _max_align );
static physaddr_t max_align = ABS_VALUE_INIT ( _max_align );
/** Colour for debug messages */
-#define colour &memsz
+#define colour &_prefix[0]
/** A memory region descriptor */
struct fdtmem_region {
physaddr_t old;
physaddr_t new;
physaddr_t try;
+ size_t memsz;
size_t len;
- void *dest;
int rc;
/* Sanity check */
}
/* Determine required length */
+ memsz = ( _end - _prefix );
assert ( memsz > 0 );
assert ( ( memsz % FDT_MAX_ALIGN ) == 0 );
len = ( memsz + fdt.len );
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",
old, new, ( ( physaddr_t ) ( new + len - 1 ) ) );
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;
+}