You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
101 lines
2.9 KiB
101 lines
2.9 KiB
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> |
|
--- |
|
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 33e981e76e7..2f0336809e7 100644 |
|
--- a/grub-core/loader/i386/efi/linux.c |
|
+++ b/grub-core/loader/i386/efi/linux.c |
|
@@ -35,11 +35,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 |
|
@@ -73,6 +78,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[]) |
|
@@ -126,7 +169,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"), |
|
@@ -152,11 +195,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[])
|
|
|