]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[image] Use memmap_describe() to check loadable image segments
authorMichael Brown <mcb30@ipxe.org>
Thu, 15 May 2025 22:02:06 +0000 (23:02 +0100)
committerMichael Brown <mcb30@ipxe.org>
Fri, 16 May 2025 15:55:35 +0000 (16:55 +0100)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/image/segment.c

index 52272170a44938bb07d39d62bc96b21693f2166f..848831acea9401af6b9a073c8a885d59c44d0637 100644 (file)
@@ -33,7 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <string.h>
 #include <errno.h>
 #include <ipxe/uaccess.h>
-#include <ipxe/io.h>
+#include <ipxe/memmap.h>
 #include <ipxe/errortab.h>
 #include <ipxe/segment.h>
 
@@ -59,38 +59,45 @@ struct errortab segment_errors[] __errortab = {
  * @ret rc             Return status code
  */
 int prep_segment ( void *segment, size_t filesz, size_t memsz ) {
-       struct memory_map memmap;
+       struct memmap_region region;
        physaddr_t start = virt_to_phys ( segment );
        physaddr_t mid = ( start + filesz );
        physaddr_t end = ( start + memsz );
-       unsigned int i;
+       physaddr_t last;
 
-       DBG ( "Preparing segment [%lx,%lx,%lx)\n", start, mid, end );
+       DBGC ( &region, "SEGMENT [%#08lx,%#08lx,%#08lx)\n", start, mid, end );
 
-       /* Sanity check */
+       /* Check for malformed lengths */
        if ( filesz > memsz ) {
-               DBG ( "Insane segment [%lx,%lx,%lx)\n", start, mid, end );
+               DBGC ( &region, "SEGMENT [%#08lx,%#08lx,%#08lx) is "
+                      "malformed\n", start, mid, end );
                return -EINVAL;
        }
 
-       /* Get a fresh memory map.  This allows us to automatically
-        * avoid treading on any regions that Etherboot is currently
-        * editing out of the memory map.
-        */
-       get_memmap ( &memmap );
+       /* Zero-length segments do not need a memory region */
+       if ( memsz == 0 )
+               return 0;
+       last = ( end - 1 );
 
-       /* Look for a suitable memory region */
-       for ( i = 0 ; i < memmap.count ; i++ ) {
-               if ( ( start >= memmap.regions[i].start ) &&
-                    ( end <= memmap.regions[i].end ) ) {
-                       /* Found valid region: zero bss and return */
-                       memset ( ( segment + filesz ), 0, ( memsz - filesz ) );
-                       return 0;
-               }
+       /* Check for address space overflow */
+       if ( last < start ) {
+               DBGC ( &region, "SEGMENT [%#08lx,%#08lx,%#08lx) wraps "
+                      "around\n", start, mid, end );
+               return -EINVAL;
+       }
+
+       /* Describe region containing this segment */
+       memmap_describe ( start, 1, &region );
+       memmap_dump ( &region );
+
+       /* Fail unless region is usable and sufficiently large */
+       if ( ( ! memmap_is_usable ( &region ) ) || ( region.last < last ) ) {
+               DBGC ( &region, "SEGMENT [%#08lx,%#08lx,%#08lx) does not fit "
+                      "into available memory\n", start, mid, end );
+               return -ERANGE_SEGMENT;
        }
 
-       /* No suitable memory region found */
-       DBG ( "Segment [%lx,%lx,%lx) does not fit into available memory\n",
-             start, mid, end );
-       return -ERANGE_SEGMENT;
+       /* Found valid region: zero bss and return */
+       memset ( ( segment + filesz ), 0, ( memsz - filesz ) );
+       return 0;
 }