More EFI memory allocator work.
Signed-off-by: Peter Jones <pjones@redhat.com>
This commit is contained in:
parent
c4e6bf30f6
commit
e30274adfa
101
0243-x86-efi-Use-bounce-buffers-for-reading-to-addresses-.patch
Normal file
101
0243-x86-efi-Use-bounce-buffers-for-reading-to-addresses-.patch
Normal file
@ -0,0 +1,101 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Fri, 14 Sep 2018 13:34:55 -0400
|
||||
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>
|
||||
---
|
||||
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 851bce77f12..06d19b9fc0e 100644
|
||||
--- a/grub-core/loader/i386/efi/linux.c
|
||||
+++ b/grub-core/loader/i386/efi/linux.c
|
||||
@@ -36,11 +36,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
|
||||
@@ -74,6 +79,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[])
|
||||
@@ -128,7 +171,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"),
|
||||
@@ -156,11 +199,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[])
|
133
0244-x86-efi-Re-arrange-grub_cmd_linux-a-little-bit.patch
Normal file
133
0244-x86-efi-Re-arrange-grub_cmd_linux-a-little-bit.patch
Normal file
@ -0,0 +1,133 @@
|
||||
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>
|
||||
---
|
||||
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 06d19b9fc0e..de5f839ff0f 100644
|
||||
--- a/grub-core/loader/i386/efi/linux.c
|
||||
+++ b/grub-core/loader/i386/efi/linux.c
|
||||
@@ -250,32 +250,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
||||
goto fail;
|
||||
}
|
||||
|
||||
- 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))
|
||||
{
|
||||
@@ -323,6 +300,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));
|
||||
@@ -347,8 +352,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;
|
||||
|
||||
@@ -365,26 +370,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);
|
||||
|
253
0245-x86-efi-Make-our-own-allocator-for-kernel-stuff.patch
Normal file
253
0245-x86-efi-Make-our-own-allocator-for-kernel-stuff.patch
Normal file
@ -0,0 +1,253 @@
|
||||
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>
|
||||
---
|
||||
grub-core/loader/i386/efi/linux.c | 162 +++++++++++++++++++++-----------------
|
||||
1 file changed, 89 insertions(+), 73 deletions(-)
|
||||
|
||||
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
|
||||
index de5f839ff0f..36b3c989c39 100644
|
||||
--- a/grub-core/loader/i386/efi/linux.c
|
||||
+++ b/grub-core/loader/i386/efi/linux.c
|
||||
@@ -48,6 +48,60 @@ 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);
|
||||
+ }
|
||||
+
|
||||
+ if (addr == NULL)
|
||||
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, errmsg);
|
||||
+
|
||||
+ return addr;
|
||||
+}
|
||||
+
|
||||
static grub_err_t
|
||||
grub_linuxefi_boot (void)
|
||||
{
|
||||
@@ -63,19 +117,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;
|
||||
}
|
||||
|
||||
@@ -152,19 +199,13 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
|
||||
size += ALIGN_UP (grub_file_size (files[i]), 4);
|
||||
}
|
||||
|
||||
- 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;
|
||||
|
||||
@@ -225,7 +266,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"));
|
||||
@@ -281,7 +321,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))
|
||||
{
|
||||
@@ -300,17 +340,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));
|
||||
@@ -329,19 +361,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,
|
||||
@@ -349,27 +372,24 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
||||
lh->cmdline_size - (sizeof (LINUX_IMAGE) - 1));
|
||||
|
||||
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);
|
||||
@@ -404,18 +424,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;
|
||||
}
|
171
0246-x86-efi-Allow-initrd-params-cmdline-allocations-abov.patch
Normal file
171
0246-x86-efi-Allow-initrd-params-cmdline-allocations-abov.patch
Normal file
@ -0,0 +1,171 @@
|
||||
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>
|
||||
---
|
||||
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 36b3c989c39..09908b62644 100644
|
||||
--- a/grub-core/loader/i386/efi/linux.c
|
||||
+++ b/grub-core/loader/i386/efi/linux.c
|
||||
@@ -53,13 +53,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)
|
||||
@@ -81,6 +90,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;
|
||||
|
||||
@@ -164,6 +178,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[])
|
||||
@@ -204,8 +221,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;
|
||||
|
||||
@@ -340,6 +361,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;
|
||||
@@ -373,21 +406,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);
|
||||
@@ -396,8 +448,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 %p\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 8474a857ed2..a4b37dcced5 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
|
||||
{
|
@ -240,3 +240,7 @@ Patch0239: 0239-Try-to-pick-better-locations-for-kernel-and-initrd.patch
|
||||
Patch0240: 0240-Attempt-to-fix-up-all-the-places-Wsign-compare-error.patch
|
||||
Patch0241: 0241-Don-t-use-Wno-sign-compare-Wno-conversion-Wno-error-.patch
|
||||
Patch0242: 0242-grub-boot-success.timer-Add-a-few-Conditions-for-run.patch
|
||||
Patch0243: 0243-x86-efi-Use-bounce-buffers-for-reading-to-addresses-.patch
|
||||
Patch0244: 0244-x86-efi-Re-arrange-grub_cmd_linux-a-little-bit.patch
|
||||
Patch0245: 0245-x86-efi-Make-our-own-allocator-for-kernel-stuff.patch
|
||||
Patch0246: 0246-x86-efi-Allow-initrd-params-cmdline-allocations-abov.patch
|
||||
|
@ -498,6 +498,10 @@ fi
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Tue Sep 25 2018 Peter Jones <pjones@redhat.com>
|
||||
- Use bounce buffers for addresses above 4GB
|
||||
- Allow initramfs, cmdline, and params >4GB, but not kernel
|
||||
|
||||
* Wed Sep 12 2018 Peter Jones <pjones@redhat.com> - 2.02-58
|
||||
- Add 2 conditions to boot-success timer and service:
|
||||
- Don't run it for system users
|
||||
|
Loading…
Reference in New Issue
Block a user