[ipxe-devel] [PATCH 1/6] [image] add support for EFI in prep_segment()

Doug Goldstein cardoe at cardoe.com
Thu Jan 26 21:34:56 UTC 2017


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 <cardoe at 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



More information about the ipxe-devel mailing list