mirror of
https://github.com/ipxe/ipxe
synced 2025-12-30 04:28:12 +03:00
[image] Use memmap_describe() to check loadable image segments
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -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 ( ®ion, "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 ( ®ion, "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 ( ®ion, "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, ®ion );
|
||||||
start, mid, end );
|
memmap_dump ( ®ion );
|
||||||
return -ERANGE_SEGMENT;
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Found valid region: zero bss and return */
|
||||||
|
memset ( ( segment + filesz ), 0, ( memsz - filesz ) );
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user