Blob Blame History Raw
From: Ard Biesheuvel <ardb@kernel.org>
Date: Mon, 10 Feb 2020 17:02:45 +0100
Subject: efi/libstub: Take soft and hard memory limits into account for initrd
 loading
Patch-mainline: v5.7-rc1
Git-commit: 31f5e546655b502d508e160e6cab20462089e34d
References: jsc#SLE-16407

On x86, the preferred load address of the initrd is still below 4 GB,
even though in some cases, we can cope with an initrd that is loaded
above that.

To simplify the code, and to make it more straightforward to introduce
other ways to load the initrd, pass the soft and hard memory limits at
the same time, and let the code handling the initrd= command line option
deal with this.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Acked-by: Lee, Chun-Yi <jlee@suse.com>
---
 drivers/firmware/efi/libstub/arm-stub.c |    2 +-
 drivers/firmware/efi/libstub/efistub.h  |    3 ++-
 drivers/firmware/efi/libstub/file.c     |   21 +++++++++++++++------
 drivers/firmware/efi/libstub/x86-stub.c |   11 ++---------
 4 files changed, 20 insertions(+), 17 deletions(-)

--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -267,7 +267,7 @@ efi_status_t efi_entry(efi_handle_t hand
 	if (!fdt_addr)
 		pr_efi("Generating empty DTB\n");
 
-	status = efi_load_initrd(image, &initrd_addr, &initrd_size,
+	status = efi_load_initrd(image, &initrd_addr, &initrd_size, ULONG_MAX,
 				 efi_get_max_initrd_addr(dram_base, image_addr));
 	if (status != EFI_SUCCESS)
 		pr_efi_err("Failed initrd from command line!\n");
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -619,6 +619,7 @@ efi_status_t efi_load_dtb(efi_loaded_ima
 efi_status_t efi_load_initrd(efi_loaded_image_t *image,
 			     unsigned long *load_addr,
 			     unsigned long *load_size,
-			     unsigned long max_addr);
+			     unsigned long soft_limit,
+			     unsigned long hard_limit);
 
 #endif
--- a/drivers/firmware/efi/libstub/file.c
+++ b/drivers/firmware/efi/libstub/file.c
@@ -123,7 +123,8 @@ static int find_file_option(const efi_ch
 static efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
 					 const efi_char16_t *optstr,
 					 int optstr_size,
-					 unsigned long max_addr,
+					 unsigned long soft_limit,
+					 unsigned long hard_limit,
 					 unsigned long *load_addr,
 					 unsigned long *load_size)
 {
@@ -179,8 +180,15 @@ static efi_status_t handle_cmdline_files
 		    round_up(alloc_size, EFI_ALLOC_ALIGN)) {
 			unsigned long old_addr = alloc_addr;
 
-			status = efi_allocate_pages(alloc_size + size, &alloc_addr,
-						    max_addr);
+			status = EFI_OUT_OF_RESOURCES;
+			if (soft_limit < hard_limit)
+				status = efi_allocate_pages(alloc_size + size,
+							    &alloc_addr,
+							    soft_limit);
+			if (status == EFI_OUT_OF_RESOURCES)
+				status = efi_allocate_pages(alloc_size + size,
+							    &alloc_addr,
+							    hard_limit);
 			if (status != EFI_SUCCESS) {
 				pr_efi_err("Failed to reallocate memory for files\n");
 				goto err_close_file;
@@ -236,14 +244,15 @@ efi_status_t efi_load_dtb(efi_loaded_ima
 			  unsigned long *load_size)
 {
 	return handle_cmdline_files(image, L"dtb=", sizeof(L"dtb=") - 2,
-				    ULONG_MAX, load_addr, load_size);
+				    ULONG_MAX, ULONG_MAX, load_addr, load_size);
 }
 
 efi_status_t efi_load_initrd(efi_loaded_image_t *image,
 			     unsigned long *load_addr,
 			     unsigned long *load_size,
-			     unsigned long max_addr)
+			     unsigned long soft_limit,
+			     unsigned long hard_limit)
 {
 	return handle_cmdline_files(image, L"initrd=", sizeof(L"initrd=") - 2,
-				    max_addr, load_addr, load_size);
+				    soft_limit, hard_limit, load_addr, load_size);
 }
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -422,15 +422,8 @@ efi_status_t __efiapi efi_pe_entry(efi_h
 		goto fail2;
 
 	status = efi_load_initrd(image, &ramdisk_addr, &ramdisk_size,
-				 hdr->initrd_addr_max);
-
-	if (status != EFI_SUCCESS &&
-	    hdr->xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G) {
-		efi_printk("Trying to load files to higher address\n");
-		status = efi_load_initrd(image, &ramdisk_addr, &ramdisk_size,
-					 ULONG_MAX);
-	}
-
+				 hdr->initrd_addr_max,
+				 above4g ? ULONG_MAX : hdr->initrd_addr_max);
 	if (status != EFI_SUCCESS)
 		goto fail2;
 	hdr->ramdisk_image = ramdisk_addr & 0xffffffff;