]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[riscv] Avoid potentially overwriting the scratch area during relocation
authorMichael Brown <mcb30@ipxe.org>
Tue, 13 May 2025 12:46:35 +0000 (13:46 +0100)
committerMichael Brown <mcb30@ipxe.org>
Tue, 13 May 2025 13:00:34 +0000 (14:00 +0100)
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>
src/arch/riscv/prefix/libprefix.S
src/core/fdtmem.c
src/include/ipxe/fdtmem.h

index e47bab98102f45adc795bf3c9876637057b40c3f..69b9f9ba27e7284cb2abe73105b5ed35b037afe9 100644 (file)
@@ -1023,6 +1023,21 @@ install:
        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
@@ -1042,11 +1057,9 @@ install:
        /* 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
index a41604eb5399c8f955699b0d318f773c5419400d..9e8ab2406fe6b952fe7de1cecc7d200e5d7b3c20 100644 (file)
@@ -41,20 +41,15 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 /** 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 {
@@ -278,8 +273,8 @@ physaddr_t fdtmem_relocate ( struct fdt_header *hdr, size_t limit ) {
        physaddr_t old;
        physaddr_t new;
        physaddr_t try;
+       size_t memsz;
        size_t len;
-       void *dest;
        int rc;
 
        /* Sanity check */
@@ -297,6 +292,7 @@ physaddr_t fdtmem_relocate ( struct fdt_header *hdr, size_t limit ) {
        }
 
        /* Determine required length */
+       memsz = ( _end - _prefix );
        assert ( memsz > 0 );
        assert ( ( memsz % FDT_MAX_ALIGN ) == 0 );
        len = ( memsz + fdt.len );
@@ -355,15 +351,39 @@ physaddr_t fdtmem_relocate ( struct fdt_header *hdr, size_t limit ) {
                        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;
+}
index 98395b8e9f79350822655adc557905b281246e00..a5777f6a21a194f6838c3fdef0dcdee2ba954b8a 100644 (file)
@@ -13,5 +13,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <ipxe/fdt.h>
 
 extern physaddr_t fdtmem_relocate ( struct fdt_header *hdr, size_t limit );
+extern int fdtmem_register ( struct fdt_header *hdr );
 
 #endif /* _IPXE_FDTMEM_H */