[image] Use memmap_describe() to check loadable image segments

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2025-05-15 23:02:06 +01:00
parent a353e70800
commit 25ab8f4629

View File

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