NOTE: I need some feedback here on how to implement this within the style of iPXE. I've noticed that there's interfaces but those didn't seem to line up with moving prep_segment into there nor did any of the arch directories.
The prep_segment function is called by the elf_load() function and its job is to ensure that the segment that is about to be loaded can be at the address it wants to be without trampling existing memory and then clears BSS. It uses the get_memmap() function which has been disabled on EFI so this provides an alternative that uses EFI's allocation functions to ensure that chunk of memory that the segment wants to be loaded at is available and clears BSS. Signed-off-by: Doug Goldstein <car...@cardoe.com> --- src/image/segment.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+) diff --git a/src/image/segment.c b/src/image/segment.c index 2d0f2f0..875379c 100644 --- a/src/image/segment.c +++ b/src/image/segment.c @@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * */ +#include <assert.h> #include <errno.h> #include <ipxe/uaccess.h> #include <ipxe/io.h> @@ -49,6 +50,53 @@ struct errortab segment_errors[] __errortab = { __einfo_errortab ( EINFO_ERANGE_SEGMENT ), }; +#ifdef EFIAPI +/** + * Prepare segment for loading + * + * @v segment Segment start + * @v filesz Size of the "allocated bytes" portion of the segment + * @v memsz Size of the segment + * @ret rc Return status code + */ +int prep_segment ( userptr_t segment, size_t filesz, size_t memsz ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + unsigned int pages; + EFI_PHYSICAL_ADDRESS phys_addr; + physaddr_t start = user_to_phys ( segment, 0 ); + physaddr_t mid = user_to_phys ( segment, filesz ); + physaddr_t end = user_to_phys ( segment, memsz ); + + DBG ( "Preparing segment [%lx,%lx,%lx)\n", start, mid, end ); + + /* Sanity check */ + if ( filesz > memsz ) { + DBG ( "Insane segment [%lx,%lx,%lx)\n", start, mid, end ); + return -EINVAL; + } + + /* Start address of the segment so that we know where to allocate from */ + phys_addr = start; + /* Size of the segment in pages */ + pages = EFI_SIZE_TO_PAGES ( memsz ); + /* Allocate the memory via EFI to ensure its reserved */ + if ( bs->AllocatePages ( AllocateAddress, + EfiLoaderData, + pages, + &phys_addr ) != 0 ) { + /* No suitable memory region found */ + DBG ( "Segment [%lx,%lx,%lx) does not fit into available memory\n", + start, mid, end ); + return -ERANGE_SEGMENT; + } + + assert ( phys_to_user ( phys_addr ) == segment ); + + /* Found valid region: zero bss and return */ + memset_user ( segment, filesz, 0, ( memsz - filesz ) ); + return 0; +} +#else /** * Prepare segment for loading * @@ -93,3 +141,4 @@ int prep_segment ( userptr_t segment, size_t filesz, size_t memsz ) { start, mid, end ); return -ERANGE_SEGMENT; } +#endif /* EFIAPI */ -- git-series 0.9.1 _______________________________________________ ipxe-devel mailing list ipxe-devel@lists.ipxe.org https://lists.ipxe.org/mailman/listinfo.cgi/ipxe-devel