summaryrefslogtreecommitdiffstats
path: root/src/image
diff options
context:
space:
mode:
authorMichael Brown2025-05-16 00:02:06 +0200
committerMichael Brown2025-05-16 17:55:35 +0200
commit25ab8f462978ee45abdf6b3a9bc0eee9872014ec (patch)
tree35ee0a081b73c27e157776a0d9a7271353788e7f /src/image
parent[memmap] Use memmap_dump_all() to dump debug memory maps (diff)
downloadipxe-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/image')
-rw-r--r--src/image/segment.c53
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 ( &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;
}