[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 <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;
}
/* No suitable memory region found */
DBG ( "Segment [%lx,%lx,%lx) does not fit into available memory\n",
start, mid, end );
return -ERANGE_SEGMENT;
/* 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;
}
/* Found valid region: zero bss and return */
memset ( ( segment + filesz ), 0, ( memsz - filesz ) );
return 0;
}