diff options
| author | Michael Brown | 2025-05-16 00:02:06 +0200 |
|---|---|---|
| committer | Michael Brown | 2025-05-16 17:55:35 +0200 |
| commit | 25ab8f462978ee45abdf6b3a9bc0eee9872014ec (patch) | |
| tree | 35ee0a081b73c27e157776a0d9a7271353788e7f /src | |
| parent | [memmap] Use memmap_dump_all() to dump debug memory maps (diff) | |
| download | ipxe-25ab8f462978ee45abdf6b3a9bc0eee9872014ec.tar.gz ipxe-25ab8f462978ee45abdf6b3a9bc0eee9872014ec.tar.xz ipxe-25ab8f462978ee45abdf6b3a9bc0eee9872014ec.zip | |
[image] Use memmap_describe() to check loadable image segments
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src')
| -rw-r--r-- | src/image/segment.c | 53 |
1 files changed, 30 insertions, 23 deletions
diff --git a/src/image/segment.c b/src/image/segment.c index 52272170a..848831ace 100644 --- a/src/image/segment.c +++ b/src/image/segment.c @@ -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 ( ®ion, "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 ( ®ion, "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 ( ®ion, "SEGMENT [%#08lx,%#08lx,%#08lx) wraps " + "around\n", start, mid, end ); + return -EINVAL; + } + + /* Describe region containing this segment */ + memmap_describe ( start, 1, ®ion ); + memmap_dump ( ®ion ); + + /* Fail unless region is usable and sufficiently large */ + if ( ( ! memmap_is_usable ( ®ion ) ) || ( region.last < last ) ) { + DBGC ( ®ion, "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; } |
