[U-Boot] [RFC 1/1] efi_loader: in situ relocation

Heinrich Schuchardt xypron.glpk at gmx.de
Sat Feb 16 19:50:44 UTC 2019


All code and data sections of PE images are already in the correct relative
location when loaded into memory. There is not need to copy them once
again.

Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
---
 lib/efi_loader/efi_image_loader.c | 64 ++++++-------------------------
 1 file changed, 11 insertions(+), 53 deletions(-)

diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index fe66e7b9ffe..6146acc6b6f 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -2,7 +2,7 @@
 /*
  *  EFI image loader
  *
- *  based partly on wine code
+ *  based partly on Wine code
  *
  *  Copyright (c) 2016 Alexander Graf
  */
@@ -219,16 +219,12 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
 {
 	IMAGE_NT_HEADERS32 *nt;
 	IMAGE_DOS_HEADER *dos;
-	IMAGE_SECTION_HEADER *sections;
-	int num_sections;
-	void *efi_reloc;
 	int i;
 	const IMAGE_BASE_RELOCATION *rel;
 	unsigned long rel_size;
 	int rel_idx = IMAGE_DIRECTORY_ENTRY_BASERELOC;
 	uint64_t image_base;
 	uint64_t image_size;
-	unsigned long virt_size = 0;
 	int supported = 0;
 
 	dos = efi;
@@ -255,85 +251,47 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
 		return EFI_LOAD_ERROR;
 	}
 
-	/* Calculate upper virtual address boundary */
-	num_sections = nt->FileHeader.NumberOfSections;
-	sections = (void *)&nt->OptionalHeader +
-			    nt->FileHeader.SizeOfOptionalHeader;
-
-	for (i = num_sections - 1; i >= 0; i--) {
-		IMAGE_SECTION_HEADER *sec = &sections[i];
-		virt_size = max_t(unsigned long, virt_size,
-				  sec->VirtualAddress + sec->Misc.VirtualSize);
-	}
-
 	/* Read 32/64bit specific header bits */
 	if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
 		IMAGE_NT_HEADERS64 *nt64 = (void *)nt;
 		IMAGE_OPTIONAL_HEADER64 *opt = &nt64->OptionalHeader;
+
 		image_base = opt->ImageBase;
 		image_size = opt->SizeOfImage;
 		efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
-		efi_reloc = efi_alloc(virt_size,
-				      loaded_image_info->image_code_type);
-		if (!efi_reloc) {
-			printf("%s: Could not allocate %lu bytes\n",
-			       __func__, virt_size);
-			return EFI_OUT_OF_RESOURCES;
-		}
-		handle->entry = efi_reloc + opt->AddressOfEntryPoint;
+		handle->entry = efi + opt->AddressOfEntryPoint;
 		rel_size = opt->DataDirectory[rel_idx].Size;
-		rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
-		virt_size = ALIGN(virt_size, opt->SectionAlignment);
+		rel = efi + opt->DataDirectory[rel_idx].VirtualAddress;
 	} else if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
 		IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader;
+
 		image_base = opt->ImageBase;
 		image_size = opt->SizeOfImage;
 		efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
-		efi_reloc = efi_alloc(virt_size,
-				      loaded_image_info->image_code_type);
-		if (!efi_reloc) {
-			printf("%s: Could not allocate %lu bytes\n",
-			       __func__, virt_size);
-			return EFI_OUT_OF_RESOURCES;
-		}
-		handle->entry = efi_reloc + opt->AddressOfEntryPoint;
+		handle->entry = efi + opt->AddressOfEntryPoint;
 		rel_size = opt->DataDirectory[rel_idx].Size;
-		rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
-		virt_size = ALIGN(virt_size, opt->SectionAlignment);
+		rel = efi + opt->DataDirectory[rel_idx].VirtualAddress;
 	} else {
 		printf("%s: Invalid optional header magic %x\n", __func__,
 		       nt->OptionalHeader.Magic);
 		return EFI_LOAD_ERROR;
 	}
 
-	/* Load sections into RAM */
-	for (i = num_sections - 1; i >= 0; i--) {
-		IMAGE_SECTION_HEADER *sec = &sections[i];
-		memset(efi_reloc + sec->VirtualAddress, 0,
-		       sec->Misc.VirtualSize);
-		memcpy(efi_reloc + sec->VirtualAddress,
-		       efi + sec->PointerToRawData,
-		       sec->SizeOfRawData);
-	}
-
 	/* Run through relocations */
-	if (efi_loader_relocate(rel, rel_size, efi_reloc,
+	if (efi_loader_relocate(rel, rel_size, efi,
 				(unsigned long)image_base) != EFI_SUCCESS) {
-		efi_free_pages((uintptr_t) efi_reloc,
-			       (virt_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT);
 		return EFI_LOAD_ERROR;
 	}
 
 	/* Flush cache */
-	flush_cache((ulong)efi_reloc,
-		    ALIGN(virt_size, EFI_CACHELINE_SIZE));
+	flush_cache((ulong)efi, ALIGN(image_size, EFI_CACHELINE_SIZE));
 	invalidate_icache_all();
 
 	/* Populate the loaded image interface bits */
 	loaded_image_info->image_base = efi;
 	loaded_image_info->image_size = image_size;
-	handle->reloc_base = efi_reloc;
-	handle->reloc_size = virt_size;
+	handle->reloc_base = efi;
+	handle->reloc_size = image_size;
 
 	return EFI_SUCCESS;
 }
-- 
2.20.1



More information about the U-Boot mailing list