Merge branch 'c8-beta' into a8-beta

This commit is contained in:
eabdullin 2022-10-07 10:29:45 +03:00
commit f416e63f99
68 changed files with 6950 additions and 38 deletions

View File

@ -1,4 +1,4 @@
From fe8b1f619fafcd2438e3d86fb07c6a5e9280423c Mon Sep 17 00:00:00 2001
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ian Page Hands <iphands@gmail.com>
Date: Tue, 8 Jun 2021 13:48:56 -0400
Subject: [PATCH] efinet: Add DHCP proxy support
@ -51,6 +51,3 @@ index df7760ad2..25809050b 100644
1, device, path);
grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path);
}
--
2.34.1

View File

@ -1,7 +1,8 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Renaud=20M=C3=A9trich?= <rmetrich@redhat.com>
Date: Tue, 8 Feb 2022 08:39:10 +0100
Subject: [PATCH] search: fixed bug stopping iteration when --no-floppy is used
Subject: [PATCH] commands/search: Fix bug stopping iteration when --no-floppy
is used
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@ -10,8 +11,11 @@ When using --no-floppy and a floppy was encountered, iterate_device()
was returning 1, causing the iteration to stop instead of continuing.
Signed-off-by: Renaud Métrich <rmetrich@redhat.com>
(cherry picked from commit e784b4b3367341b0468dd2a83b265d49383f48ae)
(cherry picked from commit 8f4688fd61dcf35de3d7ebbc2b237cfa2f202930)
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit 68ba54c2298604146be83cae144dafd1cfd1fe2d)
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
(cherry picked from commit 7ada55e3fcd16e00773d3918955b2b945b7f063a)
(cherry picked from commit 44a58e304fd06155a56b650927728af01bbc647d)
---
grub-core/commands/search.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

View File

@ -17,8 +17,10 @@ effective EFI device behind.
This commit also refactors handling of --no-floppy option.
Signed-off-by: Renaud Métrich <rmetrich@redhat.com>
(cherry picked from commit aedb45f32106dd2a64f906b0db6a76ee09f1b930)
(cherry picked from commit 4fef28d5405f7f986dba6e503e48d6a408588382)
[rharwood: apply rmetrich's flags initialization fix]
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
(cherry picked from commit fdd8396f4fa750bbbabd4298f2593942f2b84710)
(cherry picked from commit bea473b58726705bb83a3db88f52d46fdcc6150e)
---
grub-core/commands/search.c | 27 +++++++++++++++++++++++----
grub-core/commands/search_wrap.c | 18 ++++++++++++------
@ -86,7 +88,7 @@ index d3180bf66..2036a756b 100644
.nhints = nhints,
.count = 0,
diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c
index 47fc8eb99..464e6ebb1 100644
index 47fc8eb99..0b62acf85 100644
--- a/grub-core/commands/search_wrap.c
+++ b/grub-core/commands/search_wrap.c
@@ -40,6 +40,7 @@ static const struct grub_arg_option options[] =
@ -109,7 +111,7 @@ index 47fc8eb99..464e6ebb1 100644
const char *id = 0;
int i = 0, j = 0, nhints = 0;
char **hints = NULL;
+ enum search_flags flags;
+ enum search_flags flags = 0;
if (state[SEARCH_HINT].set)
for (i = 0; state[SEARCH_HINT].args[i]; i++)

View File

@ -50,10 +50,10 @@ The code is easily extensible to handle other arguments in the future if
needed.
Signed-off-by: Renaud Métrich <rmetrich@redhat.com>
(cherry picked from commit 73e183ce1e42bd97ae91a9254f8d4acd4d0b1cbc)
(cherry picked from commit 174c3efcf17b1f5ad466f9c5fb83cd9554edb5f9)
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
(cherry picked from commit cc972c27314c841f80ab0fe8318fae06f078c680)
(cherry picked from commit 84b0c3f965a3918be64ca850139bea7c32d23ae9)
---
NEWS | 2 +-
grub-core/Makefile.core.def | 6 ++
grub-core/commands/efi/connectefi.c | 205 ++++++++++++++++++++++++++++++++++++
grub-core/commands/efi/lsefi.c | 1 +
@ -61,22 +61,10 @@ Signed-off-by: Renaud Métrich <rmetrich@redhat.com>
grub-core/kern/efi/efi.c | 13 +++
include/grub/efi/disk.h | 2 +
include/grub/efi/efi.h | 5 +
NEWS | 2 +-
8 files changed, 246 insertions(+), 1 deletion(-)
create mode 100644 grub-core/commands/efi/connectefi.c
diff --git a/NEWS b/NEWS
index 2ebd54e78..b04041507 100644
--- a/NEWS
+++ b/NEWS
@@ -66,7 +66,7 @@ New in 2.02:
* Prefer pmtimer for TSC calibration.
* New/improved platform support:
- * New `efifwsetup' and `lsefi' commands on EFI platforms.
+ * New `efifwsetup', `lsefi' and `connectefi` commands on EFI platforms.
* New `cmosdump' and `cmosset' commands on platforms with CMOS support.
* New command `pcidump' for PCI platforms.
* Improve opcode parsing in ACPI halt implementation.
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 612df2e9c..ef06f8c95 100644
--- a/grub-core/Makefile.core.def
@ -394,3 +382,16 @@ index 570a69361..4411ffa16 100644
void *EXPORT_FUNC(grub_efi_open_protocol) (grub_efi_handle_t handle,
grub_efi_guid_t *protocol,
grub_efi_uint32_t attributes);
diff --git a/NEWS b/NEWS
index 2ebd54e78..b04041507 100644
--- a/NEWS
+++ b/NEWS
@@ -66,7 +66,7 @@ New in 2.02:
* Prefer pmtimer for TSC calibration.
* New/improved platform support:
- * New `efifwsetup' and `lsefi' commands on EFI platforms.
+ * New `efifwsetup', `lsefi' and `connectefi` commands on EFI platforms.
* New `cmosdump' and `cmosset' commands on platforms with CMOS support.
* New command `pcidump' for PCI platforms.
* Improve opcode parsing in ACPI halt implementation.

View File

@ -0,0 +1,203 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 11 Jul 2019 17:17:02 +0200
Subject: [PATCH] Try to pick better locations for kernel and initrd
- Don't limit allocations on 64-bit platforms to < 0x[37f]fffffff if
we're using the "large" code model ; use __UINTPTR_MAX__.
- Get the comparison right to check the address we've allocated.
- Fix the allocation for the command line as well.
*But*, when we did this some systems started failing badly; coudln't
parse partition tables, etc. What's going on here is the disk controller
is silently failing DMAs to addresses above 4GB, so we're trying to parse
uninitialized (or HW zeroed) ram when looking for the partition table,
etc.
So to limit this, we make grub_malloc() pick addresses below 4GB on
x86_64, but the direct EFI page allocation functions can get addresses
above that.
Additionally, we now try to locate kernel+initrd+cmdline+etc below
0x7fffffff, and if they're too big to fit any memory window there, then
we try a higher address.
Signed-off-by: Peter Jones <pjones@redhat.com>
(cherry picked from commit 9035d4f9ea2f26a9d4412a0918d597ceb5365442)
Conflicts:
grub-core/loader/i386/efi/linux.c
Context diffs in includes.
Signed-off-by: Lenny Szubowicz <lszubowi@redhat.com>
---
grub-core/kern/efi/mm.c | 8 ++++----
grub-core/loader/i386/efi/linux.c | 24 +++++++++++++++++-------
include/grub/arm/efi/memory.h | 1 +
include/grub/arm64/efi/memory.h | 1 +
include/grub/i386/efi/memory.h | 1 +
include/grub/ia64/efi/memory.h | 1 +
include/grub/x86_64/efi/memory.h | 4 +++-
7 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index 2d9c9032b..9e76f23e5 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -122,7 +122,7 @@ grub_efi_allocate_pages_max (grub_efi_physical_address_t max,
grub_efi_boot_services_t *b;
grub_efi_physical_address_t address = max;
- if (max > 0xffffffff)
+ if (max > GRUB_EFI_MAX_USABLE_ADDRESS)
return 0;
b = grub_efi_system_table->boot_services;
@@ -472,7 +472,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
{
if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
#if 1
- && desc->physical_start <= GRUB_EFI_MAX_USABLE_ADDRESS
+ && desc->physical_start <= GRUB_EFI_MAX_ALLOCATION_ADDRESS
#endif
&& desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000
&& desc->num_pages != 0)
@@ -490,9 +490,9 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
#if 1
if (BYTES_TO_PAGES (filtered_desc->physical_start)
+ filtered_desc->num_pages
- > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS))
+ > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_ALLOCATION_ADDRESS))
filtered_desc->num_pages
- = (BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS)
+ = (BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_ALLOCATION_ADDRESS)
- BYTES_TO_PAGES (filtered_desc->physical_start));
#endif
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index 576f8c07e..c5fdf522b 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -27,6 +27,7 @@
#include <grub/lib/cmdline.h>
#include <grub/efi/efi.h>
#include <grub/efi/linux.h>
+#include <grub/cpu/efi/memory.h>
#include <grub/tpm.h>
#include <grub/safemath.h>
@@ -113,7 +114,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
}
}
- initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
+ initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, BYTES_TO_PAGES(size));
+ if (!initrd_mem)
+ initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, BYTES_TO_PAGES(size));
if (!initrd_mem)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
@@ -217,8 +220,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
}
}
- params = grub_efi_allocate_pages_max (0x3fffffff,
+ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS,
BYTES_TO_PAGES(sizeof(*params)));
+ if (!params)
+ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS,
+ BYTES_TO_PAGES(sizeof(*params)));
if (! params)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
@@ -288,8 +294,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
#endif
grub_dprintf ("linux", "setting up cmdline\n");
- linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff,
- BYTES_TO_PAGES(lh->cmdline_size + 1));
+ linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
+ BYTES_TO_PAGES(lh->cmdline_size + 1));
+ if (!linux_cmdline)
+ linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS,
+ BYTES_TO_PAGES(lh->cmdline_size + 1));
if (!linux_cmdline)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
@@ -316,11 +325,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
kernel_mem = grub_efi_allocate_pages_max(lh->pref_address,
BYTES_TO_PAGES(lh->init_size));
-
if (!kernel_mem)
- kernel_mem = grub_efi_allocate_pages_max(0x3fffffff,
+ kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
+ BYTES_TO_PAGES(lh->init_size));
+ if (!kernel_mem)
+ kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS,
BYTES_TO_PAGES(lh->init_size));
-
if (!kernel_mem)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
diff --git a/include/grub/arm/efi/memory.h b/include/grub/arm/efi/memory.h
index 2c64918e3..a4c2ec835 100644
--- a/include/grub/arm/efi/memory.h
+++ b/include/grub/arm/efi/memory.h
@@ -2,5 +2,6 @@
#include <grub/efi/memory.h>
#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
#endif /* ! GRUB_MEMORY_CPU_HEADER */
diff --git a/include/grub/arm64/efi/memory.h b/include/grub/arm64/efi/memory.h
index c6cb32417..acb61dca4 100644
--- a/include/grub/arm64/efi/memory.h
+++ b/include/grub/arm64/efi/memory.h
@@ -2,5 +2,6 @@
#include <grub/efi/memory.h>
#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffffffffULL
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
#endif /* ! GRUB_MEMORY_CPU_HEADER */
diff --git a/include/grub/i386/efi/memory.h b/include/grub/i386/efi/memory.h
index 2c64918e3..a4c2ec835 100644
--- a/include/grub/i386/efi/memory.h
+++ b/include/grub/i386/efi/memory.h
@@ -2,5 +2,6 @@
#include <grub/efi/memory.h>
#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
#endif /* ! GRUB_MEMORY_CPU_HEADER */
diff --git a/include/grub/ia64/efi/memory.h b/include/grub/ia64/efi/memory.h
index 2c64918e3..a4c2ec835 100644
--- a/include/grub/ia64/efi/memory.h
+++ b/include/grub/ia64/efi/memory.h
@@ -2,5 +2,6 @@
#include <grub/efi/memory.h>
#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
#endif /* ! GRUB_MEMORY_CPU_HEADER */
diff --git a/include/grub/x86_64/efi/memory.h b/include/grub/x86_64/efi/memory.h
index 46e9145a3..e81cfb322 100644
--- a/include/grub/x86_64/efi/memory.h
+++ b/include/grub/x86_64/efi/memory.h
@@ -2,9 +2,11 @@
#include <grub/efi/memory.h>
#if defined (__code_model_large__)
-#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
+#define GRUB_EFI_MAX_USABLE_ADDRESS __UINTPTR_MAX__
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS 0x7fffffff
#else
#define GRUB_EFI_MAX_USABLE_ADDRESS 0x7fffffff
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
#endif
#endif /* ! GRUB_MEMORY_CPU_HEADER */

View File

@ -0,0 +1,109 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Fri, 12 Jul 2019 09:53:32 +0200
Subject: [PATCH] x86-efi: Use bounce buffers for reading to addresses > 4GB
Lots of machines apparently can't DMA correctly above 4GB during UEFI,
so use bounce buffers for the initramfs read.
Signed-off-by: Peter Jones <pjones@redhat.com>
(cherry picked from commit 7765a790dee00f2e0d414cf3a3d016c493cf0d9b)
Conflicts:
grub-core/loader/i386/efi/linux.c
git cherry-pick thought delete of prior def of MIN was a
conflict.
Signed-off-by: Lenny Szubowicz <lszubowi@redhat.com>
---
grub-core/loader/i386/efi/linux.c | 52 +++++++++++++++++++++++++++++++++------
1 file changed, 45 insertions(+), 7 deletions(-)
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index c5fdf522b..73cd838e9 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -37,11 +37,16 @@ static grub_dl_t my_mod;
static int loaded;
static void *kernel_mem;
static grub_uint64_t kernel_size;
-static grub_uint8_t *initrd_mem;
+static void *initrd_mem;
static grub_uint32_t handover_offset;
struct linux_kernel_params *params;
static char *linux_cmdline;
+#define MIN(a, b) \
+ ({ typeof (a) _a = (a); \
+ typeof (b) _b = (b); \
+ _a < _b ? _a : _b; })
+
#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12)
static grub_err_t
@@ -75,6 +80,44 @@ grub_linuxefi_unload (void)
return GRUB_ERR_NONE;
}
+#define BOUNCE_BUFFER_MAX 0x10000000ull
+
+static grub_ssize_t
+read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len)
+{
+ grub_ssize_t bufpos = 0;
+ static grub_size_t bbufsz = 0;
+ static char *bbuf = NULL;
+
+ if (bbufsz == 0)
+ bbufsz = MIN(BOUNCE_BUFFER_MAX, len);
+
+ while (!bbuf && bbufsz)
+ {
+ bbuf = grub_malloc(bbufsz);
+ if (!bbuf)
+ bbufsz >>= 1;
+ }
+ if (!bbuf)
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate bounce buffer"));
+
+ while (bufpos < (long long)len)
+ {
+ grub_ssize_t sz;
+
+ sz = grub_file_read (file, bbuf, MIN(bbufsz, len - bufpos));
+ if (sz < 0)
+ return sz;
+ if (sz == 0)
+ break;
+
+ grub_memcpy(bufp + bufpos, bbuf, sz);
+ bufpos += sz;
+ }
+
+ return bufpos;
+}
+
static grub_err_t
grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
@@ -133,7 +176,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
for (i = 0; i < nfiles; i++)
{
grub_ssize_t cursize = grub_file_size (files[i]);
- if (grub_file_read (files[i], ptr, cursize) != cursize)
+ if (read (files[i], ptr, cursize) != cursize)
{
if (!grub_errno)
grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
@@ -161,11 +204,6 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
return grub_errno;
}
-#define MIN(a, b) \
- ({ typeof (a) _a = (a); \
- typeof (b) _b = (b); \
- _a < _b ? _a : _b; })
-
static grub_err_t
grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])

View File

@ -0,0 +1,134 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 13 Sep 2018 14:42:34 -0400
Subject: [PATCH] x86-efi: Re-arrange grub_cmd_linux() a little bit.
This just helps the next patch be easier to read.
Signed-off-by: Peter Jones <pjones@redhat.com>
(cherry picked from commit 486cdd48889b30b03143c393e59a75ea040b5c40)
---
grub-core/loader/i386/efi/linux.c | 75 +++++++++++++++++++++------------------
1 file changed, 41 insertions(+), 34 deletions(-)
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index 73cd838e9..c9650561f 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -258,32 +258,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
}
}
- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS,
- BYTES_TO_PAGES(sizeof(*params)));
- if (!params)
- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS,
- BYTES_TO_PAGES(sizeof(*params)));
- if (! params)
- {
- grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
- goto fail;
- }
+ lh = (struct linux_i386_kernel_header *)kernel;
+ grub_dprintf ("linux", "original lh is at %p\n", kernel);
- grub_dprintf ("linux", "params = %p\n", params);
-
- grub_memset (params, 0, sizeof(*params));
-
- setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201);
- grub_dprintf ("linux", "copying %lu bytes from %p to %p\n",
- MIN((grub_size_t)0x202+setup_header_end_offset,
- sizeof (*params)) - 0x1f1,
- (grub_uint8_t *)kernel + 0x1f1,
- (grub_uint8_t *)params + 0x1f1);
- grub_memcpy ((grub_uint8_t *)params + 0x1f1,
- (grub_uint8_t *)kernel + 0x1f1,
- MIN((grub_size_t)0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1);
- lh = (struct linux_i386_kernel_header *)params;
- grub_dprintf ("linux", "lh is at %p\n", lh);
grub_dprintf ("linux", "checking lh->boot_flag\n");
if (lh->boot_flag != grub_cpu_to_le16 (0xaa55))
{
@@ -331,6 +308,34 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
}
#endif
+ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS,
+ BYTES_TO_PAGES(sizeof(*params)));
+ if (!params)
+ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS,
+ BYTES_TO_PAGES(sizeof(*params)));
+ if (! params)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
+ goto fail;
+ }
+
+ grub_dprintf ("linux", "params = %p\n", params);
+
+ grub_memset (params, 0, sizeof(*params));
+
+ setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201);
+ grub_dprintf ("linux", "copying %lu bytes from %p to %p\n",
+ MIN((grub_size_t)0x202+setup_header_end_offset,
+ sizeof (*params)) - 0x1f1,
+ (grub_uint8_t *)kernel + 0x1f1,
+ (grub_uint8_t *)params + 0x1f1);
+ grub_memcpy ((grub_uint8_t *)params + 0x1f1,
+ (grub_uint8_t *)kernel + 0x1f1,
+ MIN((grub_size_t)0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1);
+
+ lh = (struct linux_i386_kernel_header *)params;
+ grub_dprintf ("linux", "new lh is at %p\n", lh);
+
grub_dprintf ("linux", "setting up cmdline\n");
linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
BYTES_TO_PAGES(lh->cmdline_size + 1));
@@ -356,8 +361,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_dprintf ("linux", "setting lh->cmd_line_ptr\n");
lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
- grub_dprintf ("linux", "computing handover offset\n");
handover_offset = lh->handover_offset;
+ grub_dprintf("linux", "handover_offset: %08x\n", handover_offset);
start = (lh->setup_sects + 1) * 512;
@@ -374,26 +379,28 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
goto fail;
}
-
- grub_dprintf ("linux", "kernel_mem = %lx\n", (unsigned long) kernel_mem);
+ grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem);
grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
- loaded=1;
+
+ loaded = 1;
+
grub_dprintf ("linux", "setting lh->code32_start to %p\n", kernel_mem);
lh->code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
grub_memcpy (kernel_mem, (char *)kernel + start, filelen - start);
- grub_dprintf ("linux", "setting lh->type_of_loader\n");
lh->type_of_loader = 0x6;
+ grub_dprintf ("linux", "setting lh->type_of_loader = 0x%02x\n",
+ lh->type_of_loader);
- grub_dprintf ("linux", "setting lh->ext_loader_{type,ver}\n");
params->ext_loader_type = 0;
params->ext_loader_ver = 2;
- grub_dprintf("linux", "kernel_mem: %p handover_offset: %08x\n",
- kernel_mem, handover_offset);
+ grub_dprintf ("linux",
+ "setting lh->ext_loader_{type,ver} = {0x%02x,0x%02x}\n",
+ params->ext_loader_type, params->ext_loader_ver);
- fail:
+fail:
if (file)
grub_file_close (file);

View File

@ -0,0 +1,259 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 12 Sep 2018 16:03:55 -0400
Subject: [PATCH] x86-efi: Make our own allocator for kernel stuff
This helps enable allocations above 4GB.
Signed-off-by: Peter Jones <pjones@redhat.com>
(cherry picked from commit cfea4ae780f8860d472cd2d5a9765ec2fe2adc83)
---
grub-core/loader/i386/efi/linux.c | 167 +++++++++++++++++++++-----------------
1 file changed, 94 insertions(+), 73 deletions(-)
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index c9650561f..5eed2014c 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -49,6 +49,65 @@ static char *linux_cmdline;
#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12)
+struct allocation_choice {
+ grub_efi_physical_address_t addr;
+ grub_efi_allocate_type_t alloc_type;
+};
+
+static struct allocation_choice max_addresses[] =
+ {
+ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+ { 0, 0 }
+ };
+
+static inline void
+kernel_free(void *addr, grub_efi_uintn_t size)
+{
+ if (addr && size)
+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)addr,
+ BYTES_TO_PAGES(size));
+}
+
+static void *
+kernel_alloc(grub_efi_uintn_t size, const char * const errmsg)
+{
+ void *addr = 0;
+ unsigned int i;
+ grub_efi_physical_address_t prev_max = 0;
+
+ for (i = 0; max_addresses[i].addr != 0 && addr == 0; i++)
+ {
+ grub_uint64_t max = max_addresses[i].addr;
+ grub_efi_uintn_t pages;
+
+ if (max == prev_max)
+ continue;
+
+ pages = BYTES_TO_PAGES(size);
+ grub_dprintf ("linux", "Trying to allocate %lu pages from %p\n",
+ pages, (void *)max);
+
+ prev_max = max;
+ addr = grub_efi_allocate_pages_real (max, pages,
+ max_addresses[i].alloc_type,
+ GRUB_EFI_LOADER_DATA);
+ if (addr)
+ grub_dprintf ("linux", "Allocated at %p\n", addr);
+ }
+
+ while (grub_error_pop ())
+ {
+ ;
+ }
+
+ if (addr == NULL)
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "%s", errmsg);
+
+ return addr;
+}
+
static grub_err_t
grub_linuxefi_boot (void)
{
@@ -64,19 +123,12 @@ grub_linuxefi_unload (void)
{
grub_dl_unref (my_mod);
loaded = 0;
- if (initrd_mem)
- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem,
- BYTES_TO_PAGES(params->ramdisk_size));
- if (linux_cmdline)
- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)
- linux_cmdline,
- BYTES_TO_PAGES(params->cmdline_size + 1));
- if (kernel_mem)
- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)kernel_mem,
- BYTES_TO_PAGES(kernel_size));
- if (params)
- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)params,
- BYTES_TO_PAGES(16384));
+
+ kernel_free(initrd_mem, params->ramdisk_size);
+ kernel_free(linux_cmdline, params->cmdline_size + 1);
+ kernel_free(kernel_mem, kernel_size);
+ kernel_free(params, sizeof(*params));
+
return GRUB_ERR_NONE;
}
@@ -157,19 +209,13 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
}
}
- initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, BYTES_TO_PAGES(size));
- if (!initrd_mem)
- initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, BYTES_TO_PAGES(size));
- if (!initrd_mem)
- {
- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
- goto fail;
- }
-
- grub_dprintf ("linux", "initrd_mem = %lx\n", (unsigned long) initrd_mem);
+ initrd_mem = kernel_alloc(size, N_("can't allocate initrd"));
+ if (initrd_mem == NULL)
+ goto fail;
+ grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem);
params->ramdisk_size = size;
- params->ramdisk_image = (grub_uint32_t)(grub_addr_t) initrd_mem;
+ params->ramdisk_image = initrd_mem;
ptr = initrd_mem;
@@ -230,7 +276,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
filelen = grub_file_size (file);
kernel = grub_malloc(filelen);
-
if (!kernel)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
@@ -289,7 +334,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
-#if defined(__x86_64__) || defined(__aarch64__)
+#if defined(__x86_64__)
grub_dprintf ("linux", "checking lh->xloadflags\n");
if (!(lh->xloadflags & LINUX_XLF_KERNEL_64))
{
@@ -308,17 +353,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
}
#endif
- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS,
- BYTES_TO_PAGES(sizeof(*params)));
+ params = kernel_alloc (sizeof(*params), "cannot allocate kernel parameters");
if (!params)
- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS,
- BYTES_TO_PAGES(sizeof(*params)));
- if (! params)
- {
- grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
- goto fail;
- }
-
+ goto fail;
grub_dprintf ("linux", "params = %p\n", params);
grub_memset (params, 0, sizeof(*params));
@@ -337,19 +374,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_dprintf ("linux", "new lh is at %p\n", lh);
grub_dprintf ("linux", "setting up cmdline\n");
- linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
- BYTES_TO_PAGES(lh->cmdline_size + 1));
+ linux_cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline"));
if (!linux_cmdline)
- linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS,
- BYTES_TO_PAGES(lh->cmdline_size + 1));
- if (!linux_cmdline)
- {
- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
- goto fail;
- }
-
- grub_dprintf ("linux", "linux_cmdline = %lx\n",
- (unsigned long)linux_cmdline);
+ goto fail;
+ grub_dprintf ("linux", "linux_cmdline = %p\n", linux_cmdline);
grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
grub_create_loader_cmdline (argc, argv,
@@ -358,27 +386,24 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
GRUB_VERIFY_KERNEL_CMDLINE);
grub_dprintf ("linux", "cmdline:%s\n", linux_cmdline);
- grub_dprintf ("linux", "setting lh->cmd_line_ptr\n");
- lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
+ grub_dprintf ("linux", "setting lh->cmd_line_ptr to 0x%08x\n",
+ linux_cmdline);
+ lh->cmd_line_ptr = linux_cmdline;
handover_offset = lh->handover_offset;
- grub_dprintf("linux", "handover_offset: %08x\n", handover_offset);
+ grub_dprintf("linux", "handover_offset: 0x%08x\n", handover_offset);
start = (lh->setup_sects + 1) * 512;
- kernel_mem = grub_efi_allocate_pages_max(lh->pref_address,
- BYTES_TO_PAGES(lh->init_size));
- if (!kernel_mem)
- kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
- BYTES_TO_PAGES(lh->init_size));
- if (!kernel_mem)
- kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS,
- BYTES_TO_PAGES(lh->init_size));
- if (!kernel_mem)
+ grub_dprintf ("linux", "lh->pref_address: %p\n", (void *)(grub_addr_t)lh->pref_address);
+ if (lh->pref_address < (grub_uint64_t)GRUB_EFI_MAX_ALLOCATION_ADDRESS)
{
- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
- goto fail;
+ max_addresses[0].addr = lh->pref_address;
+ max_addresses[0].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS;
}
+ kernel_mem = kernel_alloc (lh->init_size, N_("can't allocate kernel"));
+ if (!kernel_mem)
+ goto fail;
grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem);
grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
@@ -413,18 +438,14 @@ fail:
loaded = 0;
}
- if (linux_cmdline && lh && !loaded)
- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)
- linux_cmdline,
- BYTES_TO_PAGES(lh->cmdline_size + 1));
+ if (!loaded)
+ {
+ if (lh)
+ kernel_free (linux_cmdline, lh->cmdline_size + 1);
- if (kernel_mem && !loaded)
- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)kernel_mem,
- BYTES_TO_PAGES(kernel_size));
-
- if (params && !loaded)
- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)params,
- BYTES_TO_PAGES(16384));
+ kernel_free (kernel_mem, kernel_size);
+ kernel_free (params, sizeof(*params));
+ }
return grub_errno;
}

View File

@ -0,0 +1,172 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 12 Sep 2018 16:12:27 -0400
Subject: [PATCH] x86-efi: Allow initrd+params+cmdline allocations above 4GB.
This enables everything except the kernel itself to be above 4GB.
Putting the kernel up there still doesn't work, because of the way
params->code32_start is used.
Signed-off-by: Peter Jones <pjones@redhat.com>
(cherry picked from commit 2b636967018431b046b625ad4753c8de51f7f6b2)
---
grub-core/loader/i386/efi/linux.c | 67 +++++++++++++++++++++++++++++++++++----
include/grub/i386/linux.h | 6 +++-
2 files changed, 65 insertions(+), 8 deletions(-)
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index 5eed2014c..e9d2c85b3 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -54,13 +54,22 @@ struct allocation_choice {
grub_efi_allocate_type_t alloc_type;
};
-static struct allocation_choice max_addresses[] =
+static struct allocation_choice max_addresses[4] =
{
+ /* the kernel overrides this one with pref_address and
+ * GRUB_EFI_ALLOCATE_ADDRESS */
{ GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+ /* this one is always below 4GB, which we still *prefer* even if the flag
+ * is set. */
{ GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+ /* If the flag in params is set, this one gets changed to be above 4GB. */
{ GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
{ 0, 0 }
};
+static struct allocation_choice saved_addresses[4];
+
+#define save_addresses() grub_memcpy(saved_addresses, max_addresses, sizeof(max_addresses))
+#define restore_addresses() grub_memcpy(max_addresses, saved_addresses, sizeof(max_addresses))
static inline void
kernel_free(void *addr, grub_efi_uintn_t size)
@@ -82,6 +91,11 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg)
grub_uint64_t max = max_addresses[i].addr;
grub_efi_uintn_t pages;
+ /*
+ * When we're *not* loading the kernel, or >4GB allocations aren't
+ * supported, these entries are basically all the same, so don't re-try
+ * the same parameters.
+ */
if (max == prev_max)
continue;
@@ -170,6 +184,9 @@ read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len)
return bufpos;
}
+#define LOW_U32(val) ((grub_uint32_t)(((grub_addr_t)(val)) & 0xffffffffull))
+#define HIGH_U32(val) ((grub_uint32_t)(((grub_addr_t)(val) >> 32) & 0xffffffffull))
+
static grub_err_t
grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
@@ -214,8 +231,12 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
goto fail;
grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem);
- params->ramdisk_size = size;
- params->ramdisk_image = initrd_mem;
+ params->ramdisk_size = LOW_U32(size);
+ params->ramdisk_image = LOW_U32(initrd_mem);
+#if defined(__x86_64__)
+ params->ext_ramdisk_size = HIGH_U32(size);
+ params->ext_ramdisk_image = HIGH_U32(initrd_mem);
+#endif
ptr = initrd_mem;
@@ -353,6 +374,18 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
}
#endif
+#if defined(__x86_64__)
+ if (lh->xloadflags & LINUX_XLF_CAN_BE_LOADED_ABOVE_4G)
+ {
+ grub_dprintf ("linux", "Loading kernel above 4GB is supported; enabling.\n");
+ max_addresses[2].addr = GRUB_EFI_MAX_USABLE_ADDRESS;
+ }
+ else
+ {
+ grub_dprintf ("linux", "Loading kernel above 4GB is not supported\n");
+ }
+#endif
+
params = kernel_alloc (sizeof(*params), "cannot allocate kernel parameters");
if (!params)
goto fail;
@@ -387,21 +420,40 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_dprintf ("linux", "cmdline:%s\n", linux_cmdline);
grub_dprintf ("linux", "setting lh->cmd_line_ptr to 0x%08x\n",
- linux_cmdline);
- lh->cmd_line_ptr = linux_cmdline;
+ LOW_U32(linux_cmdline));
+ lh->cmd_line_ptr = LOW_U32(linux_cmdline);
+#if defined(__x86_64__)
+ if ((grub_efi_uintn_t)linux_cmdline > 0xffffffffull)
+ {
+ grub_dprintf ("linux", "setting params->ext_cmd_line_ptr to 0x%08x\n",
+ HIGH_U32(linux_cmdline));
+ params->ext_cmd_line_ptr = HIGH_U32(linux_cmdline);
+ }
+#endif
handover_offset = lh->handover_offset;
grub_dprintf("linux", "handover_offset: 0x%08x\n", handover_offset);
start = (lh->setup_sects + 1) * 512;
+ /*
+ * AFAICS >4GB for kernel *cannot* work because of params->code32_start being
+ * 32-bit and getting called unconditionally in head_64.S from either entry
+ * point.
+ *
+ * so nerf that out here...
+ */
+ save_addresses();
grub_dprintf ("linux", "lh->pref_address: %p\n", (void *)(grub_addr_t)lh->pref_address);
if (lh->pref_address < (grub_uint64_t)GRUB_EFI_MAX_ALLOCATION_ADDRESS)
{
max_addresses[0].addr = lh->pref_address;
max_addresses[0].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS;
}
+ max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
+ max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
kernel_mem = kernel_alloc (lh->init_size, N_("can't allocate kernel"));
+ restore_addresses();
if (!kernel_mem)
goto fail;
grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem);
@@ -410,8 +462,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
loaded = 1;
- grub_dprintf ("linux", "setting lh->code32_start to %p\n", kernel_mem);
- lh->code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
+ grub_dprintf ("linux", "setting lh->code32_start to 0x%08x\n",
+ LOW_U32(kernel_mem));
+ lh->code32_start = LOW_U32(kernel_mem);
grub_memcpy (kernel_mem, (char *)kernel + start, filelen - start);
diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h
index 8474a857e..a4b37dcce 100644
--- a/include/grub/i386/linux.h
+++ b/include/grub/i386/linux.h
@@ -230,7 +230,11 @@ struct linux_kernel_params
grub_uint32_t ofw_cif_handler; /* b8 */
grub_uint32_t ofw_idt; /* bc */
- grub_uint8_t padding7[0x1b8 - 0xc0];
+ grub_uint32_t ext_ramdisk_image; /* 0xc0 */
+ grub_uint32_t ext_ramdisk_size; /* 0xc4 */
+ grub_uint32_t ext_cmd_line_ptr; /* 0xc8 */
+
+ grub_uint8_t padding7[0x1b8 - 0xcc];
union
{

View File

@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Tue, 26 May 2020 16:59:28 +0200
Subject: [PATCH] x86-efi: Reduce maximum bounce buffer size to 16 MiB
The EFI linux loader allocates a bounce buffer to copy the initrd since in
some machines doing DMA on addresses above 4GB is not possible during EFI.
But the verifiers framework also allocates a buffer to copy the initrd in
its grub_file_open() handler. It does this since the data to verify has to
be passed as a single chunk to modules that use the verifiers framework.
If the initrd image size is big there may not be enough memory in the heap
to allocate two buffers of that size. This causes an allocation failure in
the verifiers framework and leads to the initrd not being read.
To prevent these allocation failures, let's reduce the maximum size of the
bounce buffer used in the EFI loader. Since the data read can be copied to
the actual initrd address in multilple chunks.
Resolves: rhbz#1838633
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
(cherry picked from commit 1c0d2ebdddf69962395f0fa4578446654512f3c4)
---
grub-core/loader/i386/efi/linux.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index e9d2c85b3..a043df891 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -146,7 +146,7 @@ grub_linuxefi_unload (void)
return GRUB_ERR_NONE;
}
-#define BOUNCE_BUFFER_MAX 0x10000000ull
+#define BOUNCE_BUFFER_MAX 0x1000000ull
static grub_ssize_t
read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len)

View File

@ -0,0 +1,221 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@linux.ibm.com>
Date: Sun, 15 Mar 2020 12:37:10 -0400
Subject: [PATCH] ibmvtpm: Add support for trusted boot using a vTPM 2.0
Add support for trusted boot using a vTPM 2.0 on the IBM IEEE1275
PowerPC platform. With this patch grub now measures text and binary data
into the TPM's PCRs 8 and 9 in the same way as the x86_64 platform
does.
This patch requires Daniel Axtens's patches for claiming more memory.
For vTPM support to work on PowerVM, system driver levels 1010.30
or 1020.00 are required.
Note: Previous versions of firmware levels with the 2hash-ext-log
API call have a bug that, once this API call is invoked, has the
effect of disabling the vTPM driver under Linux causing an error
message to be displayed in the Linux kernel log. Those users will
have to update their machines to the firmware levels mentioned
above.
Cc: Eric Snowberg <eric.snowberg@oracle.com>
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
grub-core/Makefile.core.def | 7 ++
grub-core/commands/ieee1275/ibmvtpm.c | 152 ++++++++++++++++++++++++++++++++++
include/grub/ieee1275/ieee1275.h | 3 +
3 files changed, 162 insertions(+)
create mode 100644 grub-core/commands/ieee1275/ibmvtpm.c
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index ef06f8c95a..b11f74e6b2 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1104,6 +1104,13 @@ module = {
enable = powerpc_ieee1275;
};
+module = {
+ name = tpm;
+ common = commands/tpm.c;
+ ieee1275 = commands/ieee1275/ibmvtpm.c;
+ enable = powerpc_ieee1275;
+};
+
module = {
name = terminal;
common = commands/terminal.c;
diff --git a/grub-core/commands/ieee1275/ibmvtpm.c b/grub-core/commands/ieee1275/ibmvtpm.c
new file mode 100644
index 0000000000..e68b8448bc
--- /dev/null
+++ b/grub-core/commands/ieee1275/ibmvtpm.c
@@ -0,0 +1,152 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2021 Free Software Foundation, Inc.
+ * Copyright (C) 2021 IBM Corporation
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * IBM vTPM support code.
+ */
+
+#include <grub/err.h>
+#include <grub/types.h>
+#include <grub/tpm.h>
+#include <grub/ieee1275/ieee1275.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+
+static grub_ieee1275_ihandle_t tpm_ihandle;
+static grub_uint8_t tpm_version;
+
+#define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_ihandle_t)0)
+
+static void
+tpm_get_tpm_version (void)
+{
+ grub_ieee1275_phandle_t vtpm;
+ char buffer[20];
+
+ if (!grub_ieee1275_finddevice ("/vdevice/vtpm", &vtpm) &&
+ !grub_ieee1275_get_property (vtpm, "compatible", buffer,
+ sizeof (buffer), NULL) &&
+ !grub_strcmp (buffer, "IBM,vtpm20"))
+ tpm_version = 2;
+}
+
+static grub_err_t
+tpm_init (void)
+{
+ static int init_success = 0;
+
+ if (!init_success)
+ {
+ if (grub_ieee1275_open ("/vdevice/vtpm", &tpm_ihandle) < 0) {
+ tpm_ihandle = IEEE1275_IHANDLE_INVALID;
+ return GRUB_ERR_UNKNOWN_DEVICE;
+ }
+
+ init_success = 1;
+
+ tpm_get_tpm_version ();
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static int
+ibmvtpm_2hash_ext_log (grub_uint8_t pcrindex,
+ grub_uint32_t eventtype,
+ const char *description,
+ grub_size_t description_size,
+ void *buf, grub_size_t size)
+{
+ struct tpm_2hash_ext_log
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t method;
+ grub_ieee1275_cell_t ihandle;
+ grub_ieee1275_cell_t size;
+ grub_ieee1275_cell_t buf;
+ grub_ieee1275_cell_t description_size;
+ grub_ieee1275_cell_t description;
+ grub_ieee1275_cell_t eventtype;
+ grub_ieee1275_cell_t pcrindex;
+ grub_ieee1275_cell_t catch_result;
+ grub_ieee1275_cell_t rc;
+ }
+ args;
+
+ INIT_IEEE1275_COMMON (&args.common, "call-method", 8, 2);
+ args.method = (grub_ieee1275_cell_t) "2hash-ext-log";
+ args.ihandle = tpm_ihandle;
+ args.pcrindex = pcrindex;
+ args.eventtype = eventtype;
+ args.description = (grub_ieee1275_cell_t) description;
+ args.description_size = description_size;
+ args.buf = (grub_ieee1275_cell_t) buf;
+ args.size = (grub_ieee1275_cell_t) size;
+
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+ return -1;
+
+ /*
+ * catch_result is set if firmware does not support 2hash-ext-log
+ * rc is GRUB_IEEE1275_CELL_FALSE (0) on failure
+ */
+ if ((args.catch_result) || args.rc == GRUB_IEEE1275_CELL_FALSE)
+ return -1;
+
+ return 0;
+}
+
+static grub_err_t
+tpm2_log_event (unsigned char *buf,
+ grub_size_t size, grub_uint8_t pcr,
+ const char *description)
+{
+ static int error_displayed = 0;
+ int err;
+
+ err = ibmvtpm_2hash_ext_log (pcr, EV_IPL,
+ description,
+ grub_strlen(description) + 1,
+ buf, size);
+ if (err && !error_displayed)
+ {
+ error_displayed++;
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ "2HASH-EXT-LOG failed: Firmware is likely too old.\n");
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
+ const char *description)
+{
+ grub_err_t err = tpm_init();
+
+ /* Absence of a TPM isn't a failure. */
+ if (err != GRUB_ERR_NONE)
+ return GRUB_ERR_NONE;
+
+ grub_dprintf ("tpm", "log_event, pcr = %d, size = 0x%" PRIxGRUB_SIZE ", %s\n",
+ pcr, size, description);
+
+ if (tpm_version == 2)
+ return tpm2_log_event (buf, size, pcr, description);
+
+ return GRUB_ERR_NONE;
+}
diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
index 131808d619..87b9f95d34 100644
--- a/include/grub/ieee1275/ieee1275.h
+++ b/include/grub/ieee1275/ieee1275.h
@@ -24,6 +24,9 @@
#include <grub/types.h>
#include <grub/machine/ieee1275.h>
+#define GRUB_IEEE1275_CELL_FALSE ((grub_ieee1275_cell_t) 0)
+#define GRUB_IEEE1275_CELL_TRUE ((grub_ieee1275_cell_t) -1)
+
struct grub_ieee1275_mem_region
{
unsigned int start;

View File

@ -0,0 +1,94 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@linux.vnet.ibm.com>
Date: Fri, 11 Feb 2022 16:34:23 -0500
Subject: [PATCH] ibmvtpm: Backport ibmvtpm support to grub 2.02
Backport ibmvtpm support to grub 2.02 by making as few changes to the
source as possible and building it into the core.
Since ibmvtpm support is built into grub 2.02 do not print the error
message we would typically print if it was a module and the user had
a choice to not use vTPM support if there was no vTPM by avoiding
to use the module.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
grub-core/Makefile.core.def | 8 +-------
grub-core/commands/ieee1275/ibmvtpm.c | 13 ++++++++++---
include/grub/tpm.h | 2 +-
3 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index b11f74e6b2..637d7203e3 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -298,6 +298,7 @@ kernel = {
powerpc_ieee1275 = kern/powerpc/cache.S;
powerpc_ieee1275 = kern/powerpc/dl.c;
powerpc_ieee1275 = kern/powerpc/compiler-rt.S;
+ powerpc_ieee1275 = commands/ieee1275/ibmvtpm.c;
sparc64_ieee1275 = kern/sparc64/cache.S;
sparc64_ieee1275 = kern/sparc64/dl.c;
@@ -1104,13 +1105,6 @@ module = {
enable = powerpc_ieee1275;
};
-module = {
- name = tpm;
- common = commands/tpm.c;
- ieee1275 = commands/ieee1275/ibmvtpm.c;
- enable = powerpc_ieee1275;
-};
-
module = {
name = terminal;
common = commands/terminal.c;
diff --git a/grub-core/commands/ieee1275/ibmvtpm.c b/grub-core/commands/ieee1275/ibmvtpm.c
index e68b8448bc..728b2cbdcd 100644
--- a/grub-core/commands/ieee1275/ibmvtpm.c
+++ b/grub-core/commands/ieee1275/ibmvtpm.c
@@ -115,7 +115,8 @@ tpm2_log_event (unsigned char *buf,
grub_size_t size, grub_uint8_t pcr,
const char *description)
{
- static int error_displayed = 0;
+ /* Do not print error since vTPM support is built-in */
+ static int error_displayed = 1;
int err;
err = ibmvtpm_2hash_ext_log (pcr, EV_IPL,
@@ -132,8 +133,8 @@ tpm2_log_event (unsigned char *buf,
return GRUB_ERR_NONE;
}
-grub_err_t
-grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
+static grub_err_t
+_grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
const char *description)
{
grub_err_t err = tpm_init();
@@ -150,3 +151,9 @@ grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
return GRUB_ERR_NONE;
}
+
+grub_err_t grub_tpm_log_event(unsigned char *buf, grub_size_t size,
+ grub_uint8_t pcr, const char *description)
+{
+ return _grub_tpm_measure(buf, size, pcr, description);
+}
diff --git a/include/grub/tpm.h b/include/grub/tpm.h
index ce52be4ff7..52af2b8448 100644
--- a/include/grub/tpm.h
+++ b/include/grub/tpm.h
@@ -69,7 +69,7 @@ typedef struct {
grub_err_t EXPORT_FUNC(grub_tpm_measure) (unsigned char *buf, grub_size_t size,
grub_uint8_t pcr, const char *kind,
const char *description);
-#if defined (GRUB_MACHINE_EFI)
+#if defined (GRUB_MACHINE_EFI) || defined (GRUB_MACHINE_IEEE1275)
grub_err_t grub_tpm_execute(PassThroughToTPM_InputParamBlock *inbuf,
PassThroughToTPM_OutputParamBlock *outbuf);
grub_err_t grub_tpm_log_event(unsigned char *buf, grub_size_t size,

View File

@ -0,0 +1,112 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Fri, 8 Apr 2022 12:35:28 +1000
Subject: [PATCH] powerpc: do CAS in a more compatible way
I wrongly assumed that the most compatible way to perform CAS
negotiation was to only set the minimum number of vectors required
to ask for more memory. It turns out that this messes up booting
if the minimum VP capacity would be less than the default 10% in
vector 4.
Linux configures the minimum capacity to be 1%, so copy it for that
and for vector 3 which we now need to specify as well.
Signed-off-by: Daniel Axtens <dja@axtens.net>
(cherry picked from commit e6f02ad4e75cd995a8ee2954d28949c415b6cbfe)
(cherry picked from commit 9f825ebc319c56ca503741e6dc1a0f27ff36fe2d)
---
grub-core/kern/ieee1275/init.c | 54 ++++++++++++++++++++++++------------------
1 file changed, 31 insertions(+), 23 deletions(-)
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index adf4bd5a88..1414695cc6 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -294,33 +294,37 @@ grub_ieee1275_total_mem (grub_uint64_t *total)
/* Based on linux - arch/powerpc/kernel/prom_init.c */
struct option_vector2 {
- grub_uint8_t byte1;
- grub_uint16_t reserved;
- grub_uint32_t real_base;
- grub_uint32_t real_size;
- grub_uint32_t virt_base;
- grub_uint32_t virt_size;
- grub_uint32_t load_base;
- grub_uint32_t min_rma;
- grub_uint32_t min_load;
- grub_uint8_t min_rma_percent;
- grub_uint8_t max_pft_size;
+ grub_uint8_t byte1;
+ grub_uint16_t reserved;
+ grub_uint32_t real_base;
+ grub_uint32_t real_size;
+ grub_uint32_t virt_base;
+ grub_uint32_t virt_size;
+ grub_uint32_t load_base;
+ grub_uint32_t min_rma;
+ grub_uint32_t min_load;
+ grub_uint8_t min_rma_percent;
+ grub_uint8_t max_pft_size;
} __attribute__((packed));
struct pvr_entry {
- grub_uint32_t mask;
- grub_uint32_t entry;
+ grub_uint32_t mask;
+ grub_uint32_t entry;
};
struct cas_vector {
- struct {
- struct pvr_entry terminal;
- } pvr_list;
- grub_uint8_t num_vecs;
- grub_uint8_t vec1_size;
- grub_uint8_t vec1;
- grub_uint8_t vec2_size;
- struct option_vector2 vec2;
+ struct {
+ struct pvr_entry terminal;
+ } pvr_list;
+ grub_uint8_t num_vecs;
+ grub_uint8_t vec1_size;
+ grub_uint8_t vec1;
+ grub_uint8_t vec2_size;
+ struct option_vector2 vec2;
+ grub_uint8_t vec3_size;
+ grub_uint16_t vec3;
+ grub_uint8_t vec4_size;
+ grub_uint16_t vec4;
} __attribute__((packed));
/* Call ibm,client-architecture-support to try to get more RMA.
@@ -341,13 +345,17 @@ grub_ieee1275_ibm_cas (void)
} args;
struct cas_vector vector = {
.pvr_list = { { 0x00000000, 0xffffffff } }, /* any processor */
- .num_vecs = 2 - 1,
+ .num_vecs = 4 - 1,
.vec1_size = 0,
.vec1 = 0x80, /* ignore */
.vec2_size = 1 + sizeof(struct option_vector2) - 2,
.vec2 = {
0, 0, -1, -1, -1, -1, -1, 512, -1, 0, 48
},
+ .vec3_size = 2 - 1,
+ .vec3 = 0x00e0, // ask for FP + VMX + DFP but don't halt if unsatisfied
+ .vec4_size = 2 - 1,
+ .vec4 = 0x0001, // set required minimum capacity % to the lowest value
};
INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2);
@@ -360,7 +368,7 @@ grub_ieee1275_ibm_cas (void)
args.ihandle = root;
args.cas_addr = (grub_ieee1275_cell_t)&vector;
- grub_printf("Calling ibm,client-architecture-support...");
+ grub_printf("Calling ibm,client-architecture-support from grub...");
IEEE1275_CALL_ENTRY_FN (&args);
grub_printf("done\n");

View File

@ -0,0 +1,73 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Thu, 24 Mar 2022 14:34:32 +1100
Subject: [PATCH] powerpc: prefix detection: support device names with commas
Frustratingly, the device name itself can contain an embedded comma:
e.g /pci@800000020000015/pci1014,034A@0/sas/disk@5000c50098a0ee8b
So my previous approach was wrong: we cannot rely upon the presence
of a comma to say that a partition has been specified!
It turns out for prefixes like (,gpt2)/grub2 we really want to make
up a full (device,partition)/patch prefix, because root discovery code
in 10_linux will reset the root variable and use search to fill it again.
If you have run grub-install, you probably don't have search built in,
and if you don't have prefix containing (device,partition), grub will
construct ($root)$prefix/powerpc-ieee1275/search.mod - but because $root
has just been changed, this will no longer work, and the boot will fail!
Retain the gist of the logic, but instead of looking for a comma, look for
a leading '('. This matches the earlier code better anyway.
There's certainly a better fix to be had. But any time you chose to build
with a bare prefix like '/grub2', you're almost certainly going to build in
search anyway, so this will do.
Signed-off-by: Daniel Axtens <dja@axtens.net>
(cherry picked from commit 80b6eb5e55e6d1a4c9896361e61de31c29e6939d)
(cherry picked from commit f3df9f1c2335df22d020e80583d932e254594f0e)
---
grub-core/kern/main.c | 27 +++++++++++++++++++++------
1 file changed, 21 insertions(+), 6 deletions(-)
diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
index 40a709117f..abbf8af9e6 100644
--- a/grub-core/kern/main.c
+++ b/grub-core/kern/main.c
@@ -241,14 +241,29 @@ grub_set_prefix_and_root (void)
what sorts of paths represent disks with partition tables and those
without partition tables.
- So we act unless there is a comma in the device, which would indicate
- a partition has already been specified.
+ - Frustratingly, the device name itself can contain an embedded comma:
+ /pci@800000020000015/pci1014,034A@0/sas/disk@5000c50098a0ee8b
+ So we cannot even rely upon the presence of a comma to say that a
+ partition has been specified!
- (If we only have a path, the code in normal to discover config files
- will try both without partitions and then with any partitions so we
- will cover both CDs and HDs.)
+ If we only have a path in $prefix, the code in normal to discover
+ config files will try all disks, both without partitions and then with
+ any partitions so we will cover both CDs and HDs.
+
+ However, it doesn't then set the prefix to be something like
+ (discovered partition)/path, and so it is fragile against runtime
+ changes to $root. For example some of the stuff done in 10_linux to
+ reload $root sets root differently and then uses search to find it
+ again. If the search module is not built in, when we change root, grub
+ will look in (new root)/path/powerpc-ieee1275, that won't work, and we
+ will not be able to load the search module and the boot will fail.
+
+ This is particularly likely to hit us in the grub-install
+ (,msdos2)/grub2 case, so we act unless the supplied prefix starts with
+ '(', which would likely indicate a partition has already been
+ specified.
*/
- if (grub_strchr (device, ',') == NULL)
+ if (prefix && prefix[0] != '(')
grub_env_set ("prefix", path);
else
#endif

View File

@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegdo@br.ibm.com>
Date: Thu, 24 Mar 2022 13:14:42 -0400
Subject: [PATCH] make ofdisk_retries optional
The feature Retry on Fail added to GRUB can cause a LPM to take
longer if the SAN is slow.
When a LPM to external site occur, the path of the disk can change
and thus the disk search function on grub can take some time since
it is used as a hint. This can cause the Retry on Fail feature to
try to access the disk 20x times (since this is hardcoded number)
and, if the SAN is slow, the boot time can increase a lot.
In some situations not acceptable.
The following patch enables a configuration at user space of the
maximum number of retries we want for this feature.
The variable ofdisk_retries should be set using grub2-editenv
and will be checked by retry function. If the variable is not set,
so the default number of retries will be used instead.
---
include/grub/ieee1275/ofdisk.h | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/include/grub/ieee1275/ofdisk.h b/include/grub/ieee1275/ofdisk.h
index 7d2d540930..0074d55eee 100644
--- a/include/grub/ieee1275/ofdisk.h
+++ b/include/grub/ieee1275/ofdisk.h
@@ -25,7 +25,12 @@ extern void grub_ofdisk_fini (void);
#define MAX_RETRIES 20
-#define RETRY_IEEE1275_OFDISK_OPEN(device, last_ihandle) unsigned retry_i=0;for(retry_i=0; retry_i < MAX_RETRIES; retry_i++){ \
+#define RETRY_IEEE1275_OFDISK_OPEN(device, last_ihandle) \
+ unsigned max_retries = MAX_RETRIES; \
+ if(grub_env_get("ofdisk_retries") != NULL) \
+ max_retries = grub_strtoul(grub_env_get("ofdisk_retries"), 0, 10)+1; \
+ grub_dprintf("ofdisk","MAX_RETRIES set to %u\n",max_retries); \
+ unsigned retry_i=0;for(retry_i=0; retry_i < max_retries; retry_i++){ \
if(!grub_ieee1275_open(device, last_ihandle)) \
break; \
grub_dprintf("ofdisk","Opening disk %s failed. Retrying...\n",device); }

View File

@ -0,0 +1,71 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Chris Coulson <chris.coulson@canonical.com>
Date: Thu, 28 Apr 2022 21:53:36 +0100
Subject: [PATCH] loader/efi/chainloader: grub_load_and_start_image doesn't
load and start
grub_load_and_start_image only loads an image - it still requires the
caller to start it. This renames it to grub_load_image.
It's called from 2 places:
- grub_cmd_chainloader when not using the shim protocol.
- grub_secureboot_chainloader_boot if handle_image returns an error.
In this case, the image is loaded and then nothing else happens which
seems strange. I assume the intention is that it falls back to LoadImage
and StartImage if handle_image fails, so I've made it do that.
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
(cherry picked from commit b4d70820a65c00561045856b7b8355461a9545f6)
(cherry picked from commit 05b16a6be50b1910609740a66b561276fa490538)
(cherry picked from commit 16486a34f3aa41a94e334e86db1a1e21e9b0a45f)
---
grub-core/loader/efi/chainloader.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
index 29663f7180..d75d345003 100644
--- a/grub-core/loader/efi/chainloader.c
+++ b/grub-core/loader/efi/chainloader.c
@@ -835,7 +835,7 @@ grub_secureboot_chainloader_unload (void)
}
static grub_err_t
-grub_load_and_start_image(void *boot_image)
+grub_load_image(void *boot_image)
{
grub_efi_boot_services_t *b;
grub_efi_status_t status;
@@ -877,13 +877,23 @@ grub_load_and_start_image(void *boot_image)
static grub_err_t
grub_secureboot_chainloader_boot (void)
{
+ grub_efi_boot_services_t *b;
int rc;
+
rc = handle_image ((void *)(unsigned long)address, fsize);
if (rc == 0)
{
- grub_load_and_start_image((void *)(unsigned long)address);
+ /* We weren't able to attempt to execute the image, so fall back
+ * to LoadImage / StartImage.
+ */
+ rc = grub_load_image((void *)(unsigned long)address);
+ if (rc == 0)
+ grub_chainloader_boot ();
}
+ b = grub_efi_system_table->boot_services;
+ efi_call_1 (b->unload_image, image_handle);
+
grub_loader_unset ();
return grub_errno;
}
@@ -1072,7 +1082,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
}
else if (rc == 0)
{
- grub_load_and_start_image(boot_image);
+ grub_load_image(boot_image);
grub_file_close (file);
grub_device_close (dev);
grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);

View File

@ -0,0 +1,334 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Chris Coulson <chris.coulson@canonical.com>
Date: Fri, 29 Apr 2022 21:13:08 +0100
Subject: [PATCH] loader/efi/chainloader: simplify the loader state
When not using the shim lock protocol, the chainloader command retains
the source buffer and device path passed to LoadImage, requiring the
unload hook passed to grub_loader_set to free them. It isn't required
to retain this state though - they aren't required by StartImage or
anything else in the boot hook, so clean them up before