c2f7a5
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
c2f7a5
From: Peter Jones <pjones@redhat.com>
98536e
Date: Mon, 27 Aug 2018 14:31:37 -0400
c2f7a5
Subject: [PATCH] Try to pick better locations for kernel and initrd
c2f7a5
98536e
- Don't limit allocations on 64-bit platforms to < 0x[37f]fffffff if
98536e
  we're using the "large" code model ; use __UINTPTR_MAX__.
98536e
- Get the comparison right to check the address we've allocated.
98536e
- Fix the allocation for the command line as well.
98536e
98536e
*But*, when we did this some systems started failing badly; coudln't
98536e
parse partition tables, etc.  What's going on here is the disk controller
98536e
is silently failing DMAs to addresses above 4GB, so we're trying to parse
98536e
uninitialized (or HW zeroed) ram when looking for the partition table,
98536e
etc.
98536e
98536e
So to limit this, we make grub_malloc() pick addresses below 4GB on
98536e
x86_64, but the direct EFI page allocation functions can get addresses
98536e
above that.
98536e
98536e
Additionally, we now try to locate kernel+initrd+cmdline+etc below
98536e
0x7fffffff, and if they're too big to fit any memory window there, then
98536e
we try a higher address.
c2f7a5
c2f7a5
Signed-off-by: Peter Jones <pjones@redhat.com>
c2f7a5
---
98536e
 grub-core/kern/efi/mm.c           |  8 ++++----
98536e
 grub-core/loader/i386/efi/linux.c | 24 +++++++++++++++++-------
98536e
 include/grub/arm/efi/memory.h     |  1 +
98536e
 include/grub/arm64/efi/memory.h   |  1 +
98536e
 include/grub/i386/efi/memory.h    |  1 +
98536e
 include/grub/ia64/efi/memory.h    |  1 +
98536e
 include/grub/x86_64/efi/memory.h  |  4 +++-
98536e
 7 files changed, 28 insertions(+), 12 deletions(-)
c2f7a5
c2f7a5
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
753122
index 2c41a528f27..cac775fc935 100644
c2f7a5
--- a/grub-core/kern/efi/mm.c
c2f7a5
+++ b/grub-core/kern/efi/mm.c
c2f7a5
@@ -122,7 +122,7 @@ grub_efi_allocate_pages_max (grub_efi_physical_address_t max,
c2f7a5
   grub_efi_boot_services_t *b;
c2f7a5
   grub_efi_physical_address_t address = max;
c2f7a5
 
c2f7a5
-  if (max > 0xffffffff)
98536e
+  if (max > GRUB_EFI_MAX_USABLE_ADDRESS)
c2f7a5
     return 0;
c2f7a5
 
c2f7a5
   b = grub_efi_system_table->boot_services;
753122
@@ -466,7 +466,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
98536e
     {
98536e
       if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
98536e
 #if 1
98536e
-	  && desc->physical_start <= GRUB_EFI_MAX_USABLE_ADDRESS
98536e
+	  && desc->physical_start <= GRUB_EFI_MAX_ALLOCATION_ADDRESS
98536e
 #endif
98536e
 	  && desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000
98536e
 	  && desc->num_pages != 0)
753122
@@ -484,9 +484,9 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
98536e
 #if 1
98536e
 	  if (BYTES_TO_PAGES (filtered_desc->physical_start)
98536e
 	      + filtered_desc->num_pages
98536e
-	      > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS))
98536e
+	      > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_ALLOCATION_ADDRESS))
98536e
 	    filtered_desc->num_pages
98536e
-	      = (BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS)
98536e
+	      = (BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_ALLOCATION_ADDRESS)
98536e
 		 - BYTES_TO_PAGES (filtered_desc->physical_start));
98536e
 #endif
98536e
 
c2f7a5
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
98536e
index ea9f5134e67..851bce77f12 100644
c2f7a5
--- a/grub-core/loader/i386/efi/linux.c
c2f7a5
+++ b/grub-core/loader/i386/efi/linux.c
c2f7a5
@@ -28,6 +28,7 @@
c2f7a5
 #include <grub efi="" efi.h="">
c2f7a5
 #include <grub efi="" linux.h="">
c2f7a5
 #include <grub tpm.h="">
c2f7a5
+#include <grub cpu="" efi="" memory.h="">
c2f7a5
 
c2f7a5
 GRUB_MOD_LICENSE ("GPLv3+");
c2f7a5
 
98536e
@@ -108,7 +109,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
c2f7a5
       size += ALIGN_UP (grub_file_size (files[i]), 4);
c2f7a5
     }
c2f7a5
 
c2f7a5
-  initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
98536e
+  initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, BYTES_TO_PAGES(size));
98536e
+  if (!initrd_mem)
98536e
+    initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, BYTES_TO_PAGES(size));
c2f7a5
   if (!initrd_mem)
c2f7a5
     {
c2f7a5
       grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
98536e
@@ -209,8 +212,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
c2f7a5
       goto fail;
c2f7a5
     }
c2f7a5
 
c2f7a5
-  params = grub_efi_allocate_pages_max (0x3fffffff,
98536e
+  params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS,
c2f7a5
 					BYTES_TO_PAGES(sizeof(*params)));
98536e
+  if (!params)
98536e
+    params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS,
98536e
+					  BYTES_TO_PAGES(sizeof(*params)));
c2f7a5
   if (! params)
c2f7a5
     {
98536e
       grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
98536e
@@ -280,8 +286,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
98536e
 #endif
98536e
 
98536e
   grub_dprintf ("linux", "setting up cmdline\n");
98536e
-  linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff,
98536e
-					 BYTES_TO_PAGES(lh->cmdline_size + 1));
98536e
+  linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
98536e
+					      BYTES_TO_PAGES(lh->cmdline_size + 1));
98536e
+  if (!linux_cmdline)
98536e
+    linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS,
98536e
+						BYTES_TO_PAGES(lh->cmdline_size + 1));
98536e
   if (!linux_cmdline)
98536e
     {
98536e
       grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
98536e
@@ -307,11 +316,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
c2f7a5
 
98536e
   kernel_mem = grub_efi_allocate_pages_max(lh->pref_address,
98536e
 					   BYTES_TO_PAGES(lh->init_size));
98536e
-
c2f7a5
   if (!kernel_mem)
c2f7a5
-    kernel_mem = grub_efi_allocate_pages_max(0x3fffffff,
98536e
+    kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
98536e
+					     BYTES_TO_PAGES(lh->init_size));
98536e
+  if (!kernel_mem)
c2f7a5
+    kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS,
c2f7a5
 					     BYTES_TO_PAGES(lh->init_size));
98536e
-
c2f7a5
   if (!kernel_mem)
98536e
     {
98536e
       grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
98536e
diff --git a/include/grub/arm/efi/memory.h b/include/grub/arm/efi/memory.h
98536e
index 2c64918e3f7..a4c2ec83502 100644
98536e
--- a/include/grub/arm/efi/memory.h
98536e
+++ b/include/grub/arm/efi/memory.h
98536e
@@ -2,5 +2,6 @@
98536e
 #include <grub efi="" memory.h="">
98536e
 
98536e
 #define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
98536e
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
98536e
 
98536e
 #endif /* ! GRUB_MEMORY_CPU_HEADER */
c2f7a5
diff --git a/include/grub/arm64/efi/memory.h b/include/grub/arm64/efi/memory.h
98536e
index c6cb3241714..acb61dca44b 100644
c2f7a5
--- a/include/grub/arm64/efi/memory.h
c2f7a5
+++ b/include/grub/arm64/efi/memory.h
98536e
@@ -2,5 +2,6 @@
c2f7a5
 #include <grub efi="" memory.h="">
c2f7a5
 
98536e
 #define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffffffffULL
98536e
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
98536e
 
98536e
 #endif /* ! GRUB_MEMORY_CPU_HEADER */
98536e
diff --git a/include/grub/i386/efi/memory.h b/include/grub/i386/efi/memory.h
98536e
index 2c64918e3f7..a4c2ec83502 100644
98536e
--- a/include/grub/i386/efi/memory.h
98536e
+++ b/include/grub/i386/efi/memory.h
98536e
@@ -2,5 +2,6 @@
98536e
 #include <grub efi="" memory.h="">
98536e
 
98536e
 #define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
98536e
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
98536e
 
98536e
 #endif /* ! GRUB_MEMORY_CPU_HEADER */
98536e
diff --git a/include/grub/ia64/efi/memory.h b/include/grub/ia64/efi/memory.h
98536e
index 2c64918e3f7..a4c2ec83502 100644
98536e
--- a/include/grub/ia64/efi/memory.h
98536e
+++ b/include/grub/ia64/efi/memory.h
98536e
@@ -2,5 +2,6 @@
98536e
 #include <grub efi="" memory.h="">
98536e
 
98536e
 #define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
98536e
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
c2f7a5
 
c2f7a5
 #endif /* ! GRUB_MEMORY_CPU_HEADER */
c2f7a5
diff --git a/include/grub/x86_64/efi/memory.h b/include/grub/x86_64/efi/memory.h
98536e
index 46e9145a308..e81cfb32213 100644
c2f7a5
--- a/include/grub/x86_64/efi/memory.h
c2f7a5
+++ b/include/grub/x86_64/efi/memory.h
98536e
@@ -2,9 +2,11 @@
c2f7a5
 #include <grub efi="" memory.h="">
c2f7a5
 
c2f7a5
 #if defined (__code_model_large__)
98536e
-#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
c2f7a5
+#define GRUB_EFI_MAX_USABLE_ADDRESS __UINTPTR_MAX__
98536e
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS 0x7fffffff
c2f7a5
 #else
98536e
 #define GRUB_EFI_MAX_USABLE_ADDRESS 0x7fffffff
98536e
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
c2f7a5
 #endif
c2f7a5
 
c2f7a5
 #endif /* ! GRUB_MEMORY_CPU_HEADER */