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