svn commit: r292338 - in head/sys/boot/efi/loader: . arch/amd64 arch/arm arch/arm64

Ed Maste emaste at FreeBSD.org
Wed Dec 16 16:19:20 UTC 2015


Author: emaste
Date: Wed Dec 16 16:19:18 2015
New Revision: 292338
URL: https://svnweb.freebsd.org/changeset/base/292338

Log:
  UEFI: combine GetMemoryMap and ExitBootServices and retry on error
  
  The EFI memory map may change before or during the first
  ExitBootServices call. In that case ExitBootServices returns an error,
  and GetMemoryMap and ExitBootServices must be retried.
  
  Glue together calls to GetMemoryMap(), ExitBootServices() and storage of
  (now up-to-date) MODINFOMD_EFI_MAP metadata within a single function.
  
  That new function - bi_add_efi_data_and_exit() - uses space previously
  allocated in bi_load_efi_data() to store the memory map (it will fail if
  that space is too short). It handles re-calling GetMemoryMap() once to
  update the map key if necessary. Finally, if ExitBootServices() is
  successful, it stores the memory map and its header as MODINFOMD_EFI_MAP
  metadata.
  
  ExitBootServices() calls are now done earlier, from within arch-
  independent bi_load() code.
  
  PR:		202455
  Submitted by:	Ganael LAPLANCHE
  Reviewed by:	kib
  MFC after:	2 weeks
  Relnotes:	Yes
  Differential Revision:	https://reviews.freebsd.org/D4296

Modified:
  head/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c
  head/sys/boot/efi/loader/arch/arm/exec.c
  head/sys/boot/efi/loader/arch/arm64/exec.c
  head/sys/boot/efi/loader/bootinfo.c
  head/sys/boot/efi/loader/loader_efi.h

Modified: head/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c
==============================================================================
--- head/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c	Wed Dec 16 15:26:31 2015	(r292337)
+++ head/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c	Wed Dec 16 16:19:18 2015	(r292338)
@@ -174,13 +174,6 @@ elf64_exec(struct preloaded_file *fp)
 	if (err != 0)
 		return(err);
 
-	status = BS->ExitBootServices(IH, efi_mapkey);
-	if (EFI_ERROR(status)) {
-		printf("%s: ExitBootServices() returned 0x%lx\n", __func__,
-		    (long)status);
-		return (EINVAL);
-	}
-
 	dev_cleanup();
 
 	trampoline(trampstack, efi_copy_finish, kernend, modulep, PT4,

Modified: head/sys/boot/efi/loader/arch/arm/exec.c
==============================================================================
--- head/sys/boot/efi/loader/arch/arm/exec.c	Wed Dec 16 15:26:31 2015	(r292337)
+++ head/sys/boot/efi/loader/arch/arm/exec.c	Wed Dec 16 16:19:18 2015	(r292338)
@@ -82,13 +82,6 @@ __elfN(arm_exec)(struct preloaded_file *
 	printf("modulep: %#x\n", modulep);
 	printf("relocation_offset %llx\n", __elfN(relocation_offset));
 
-	status = BS->ExitBootServices(IH, efi_mapkey);
-	if (EFI_ERROR(status)) {
-		printf("%s: ExitBootServices() returned 0x%lx\n", __func__,
-		    (long)status);
-		return (EINVAL);
-	}
-
 	dev_cleanup();
 
 	(*entry)((void *)modulep);

Modified: head/sys/boot/efi/loader/arch/arm64/exec.c
==============================================================================
--- head/sys/boot/efi/loader/arch/arm64/exec.c	Wed Dec 16 15:26:31 2015	(r292337)
+++ head/sys/boot/efi/loader/arch/arm64/exec.c	Wed Dec 16 16:19:18 2015	(r292338)
@@ -118,13 +118,6 @@ elf64_exec(struct preloaded_file *fp)
 	if (err != 0)
 		return (err);
 
-	status = BS->ExitBootServices(IH, efi_mapkey);
-        if (EFI_ERROR(status)) {
-		printf("%s: ExitBootServices() returned 0x%lx\n", __func__,
-		    (long)status);
-		return (EINVAL);
-	}
-
 	/* Clean D-cache under kernel area and invalidate whole I-cache */
 	clean_addr = efi_translate(fp->f_addr);
 	clean_size = efi_translate(kernendp) - clean_addr;

Modified: head/sys/boot/efi/loader/bootinfo.c
==============================================================================
--- head/sys/boot/efi/loader/bootinfo.c	Wed Dec 16 15:26:31 2015	(r292337)
+++ head/sys/boot/efi/loader/bootinfo.c	Wed Dec 16 16:19:18 2015	(r292338)
@@ -55,8 +55,6 @@ __FBSDID("$FreeBSD$");
 #include <fdt_platform.h>
 #endif
 
-UINTN efi_mapkey;
-
 static const char howto_switches[] = "aCdrgDmphsv";
 static int howto_masks[] = {
 	RB_ASKNAME, RB_CDROM, RB_KDB, RB_DFLTROOT, RB_GDB, RB_MULTIPLE,
@@ -234,12 +232,50 @@ bi_copymodules(vm_offset_t addr)
 }
 
 static int
+bi_add_efi_data_and_exit(struct preloaded_file *kfp,
+    struct efi_map_header *efihdr, size_t efisz, EFI_MEMORY_DESCRIPTOR *mm,
+    UINTN sz)
+{
+	UINTN efi_mapkey;
+	UINTN mmsz;
+	UINT32 mmver;
+	EFI_STATUS status;
+	UINTN retry;
+
+	/*
+	 * It is possible that the first call to ExitBootServices may change
+	 * the map key. Fetch a new map key and retry ExitBootServices in that
+	 * case.
+	 */
+	for (retry = 2; retry > 0; retry--) {
+		status = BS->GetMemoryMap(&sz, mm, &efi_mapkey, &mmsz, &mmver);
+		if (EFI_ERROR(status)) {
+			printf("%s: GetMemoryMap() returned 0x%lx\n", __func__,
+			    (long)status);
+			return (EINVAL);
+		}
+		status = BS->ExitBootServices(IH, efi_mapkey);
+		if (EFI_ERROR(status) == 0) {
+			efihdr->memory_size = sz;
+			efihdr->descriptor_size = mmsz;
+			efihdr->descriptor_version = mmver;
+			file_addmetadata(kfp, MODINFOMD_EFI_MAP, efisz + sz,
+			    efihdr);
+			return (0);
+		}
+	}
+	printf("ExitBootServices() returned 0x%lx\n", (long)status);
+	return (EINVAL);
+}
+
+static int
 bi_load_efi_data(struct preloaded_file *kfp)
 {
 	EFI_MEMORY_DESCRIPTOR *mm;
 	EFI_PHYSICAL_ADDRESS addr;
 	EFI_STATUS status;
 	size_t efisz;
+	UINTN efi_mapkey;
 	UINTN mmsz, pages, sz;
 	UINT32 mmver;
 	struct efi_map_header *efihdr;
@@ -294,20 +330,8 @@ bi_load_efi_data(struct preloaded_file *
 	efihdr = (struct efi_map_header *)addr;
 	mm = (void *)((uint8_t *)efihdr + efisz);
 	sz = (EFI_PAGE_SIZE * pages) - efisz;
-	status = BS->GetMemoryMap(&sz, mm, &efi_mapkey, &mmsz, &mmver);
-	if (EFI_ERROR(status)) {
-		printf("%s: GetMemoryMap() returned 0x%lx\n", __func__,
-		    (long)status);
-		return (EINVAL);
-	}
-
-	efihdr->memory_size = sz;
-	efihdr->descriptor_size = mmsz;
-	efihdr->descriptor_version = mmver;
 
-	file_addmetadata(kfp, MODINFOMD_EFI_MAP, efisz + sz, efihdr);
-
-	return (0);
+	return (bi_add_efi_data_and_exit(kfp, efihdr, efisz, mm, sz));
 }
 
 /*

Modified: head/sys/boot/efi/loader/loader_efi.h
==============================================================================
--- head/sys/boot/efi/loader/loader_efi.h	Wed Dec 16 15:26:31 2015	(r292337)
+++ head/sys/boot/efi/loader/loader_efi.h	Wed Dec 16 16:19:18 2015	(r292338)
@@ -44,8 +44,6 @@ ssize_t	efi_copyout(const vm_offset_t sr
 ssize_t	efi_readin(const int fd, vm_offset_t dest, const size_t len);
 void * efi_translate(vm_offset_t ptr);
 
-extern UINTN efi_mapkey;
-
 void	efi_copy_finish(void);
 
 #endif	/* _LOADER_EFI_COPY_H_ */


More information about the svn-src-head mailing list