Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 6 Mar 2017 09:34:32 +0000 (UTC)
From:      Dexuan Cui <dexuan@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r314770 - head/sys/boot/efi/loader
Message-ID:  <201703060934.v269YWab074543@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: dexuan
Date: Mon Mar  6 09:34:31 2017
New Revision: 314770
URL: https://svnweb.freebsd.org/changeset/base/314770

Log:
  loader.efi: fix recent UEFI-boot regression on physical machines
  
  This patch fixes my recent patch
  "loader.efi: reduce the size of the staging area if necessary", which
  causes EFI-boot failure on physical machines since Mar 2:
  on the host there is a 1MB LoaderData memory range, which splits
  the big Conventional Memory range into a small one (15MB) and a
  big one: the small one is too small to hold the staging area.
  
  We can actually use the LoaderData range safely, because when
  amd64_tramp -> efi_copy_finish() starts to run, we're almost at
  the very end of the efi loader code and we're going to "return"
  to the kernel entry, so we're pretty sure we won't access any loader
  data any more.
  
  For people who are interested in the details: please see
  https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=211746#c22
  
  PS, some people also reported the regression happened to FreeBSD VM
  running on Bhyve in EFI mode. This patch should resolve it too,
  though I don't have such a setup to test.
  
  Reviewed by:	sephe
  Approved by:	sephe (mentor)
  MFC after:	2 weeks
  Sponsored by:	Microsoft
  Differential Revision:	https://reviews.freebsd.org/D9904

Modified:
  head/sys/boot/efi/loader/copy.c

Modified: head/sys/boot/efi/loader/copy.c
==============================================================================
--- head/sys/boot/efi/loader/copy.c	Mon Mar  6 08:13:19 2017	(r314769)
+++ head/sys/boot/efi/loader/copy.c	Mon Mar  6 09:34:31 2017	(r314770)
@@ -53,7 +53,7 @@ efi_verify_staging_size(unsigned long *n
 	UINT32 dver;
 	EFI_STATUS status;
 	int i, ndesc;
-	unsigned long available_pages;
+	unsigned long available_pages = 0;
 
 	sz = 0;
 	status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
@@ -70,7 +70,6 @@ efi_verify_staging_size(unsigned long *n
 	}
 
 	ndesc = sz / dsz;
-
 	for (i = 0, p = map; i < ndesc;
 	     i++, p = NextMemoryDescriptor(p, dsz)) {
 		start = p->PhysicalStart;
@@ -81,20 +80,38 @@ efi_verify_staging_size(unsigned long *n
 			continue;
 
 		if (p->Type != EfiConventionalMemory)
-			continue;
+			printf("Warning: wrong EFI memory type: %d\n",
+			    p->Type);
 
 		available_pages = p->NumberOfPages -
 			((KERNEL_PHYSICAL_BASE - start) >> EFI_PAGE_SHIFT);
+		break;
+	}
+
+	if (available_pages == 0) {
+		printf("Can't find valid memory map for staging area!\n");
+		goto out;
+	}
 
-		if (*nr_pages > available_pages) {
-			printf("staging area size is reduced: %ld -> %ld!\n",
-			    *nr_pages, available_pages);
-			*nr_pages = available_pages;
-		}
+	for ( ; i < ndesc;
+	     i++, p = NextMemoryDescriptor(p, dsz)) {
+		if (p->Type != EfiConventionalMemory &&
+		    p->Type != EfiLoaderData)
+			break;
 
-		break;
+		if (p->PhysicalStart != end)
+			break;
+
+		end = p->PhysicalStart + p->NumberOfPages * EFI_PAGE_SIZE;
+
+		available_pages += p->NumberOfPages;
 	}
 
+	if (*nr_pages > available_pages) {
+		printf("Staging area's size is reduced: %ld -> %ld!\n",
+		    *nr_pages, available_pages);
+		*nr_pages = available_pages;
+	}
 out:
 	free(map);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703060934.v269YWab074543>