[kernel: 67/85] add UEFI boot fixes from mfleming's 'urgent' branch (BKO #84241)
Adam Williamson
adamwill at fedoraproject.org
Wed Nov 26 20:54:22 UTC 2014
commit 189cc862893882b254316cb453cc8c0076f8815c
Author: Adam Williamson <awilliam at redhat.com>
Date: Sat Sep 13 11:27:40 2014 -0700
add UEFI boot fixes from mfleming's 'urgent' branch (BKO #84241)
kernel.spec | 7 +
x86-efi-fixup-got-in-all-boot-code-paths.patch | 227 ++++++++++++++++++++
...i-only-load-initrd-above-4g-on-second-try.patch | 79 +++++++
3 files changed, 313 insertions(+), 0 deletions(-)
---
diff --git a/kernel.spec b/kernel.spec
index f6a6023..264e429 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -634,6 +634,11 @@ Patch31010: 0001-ACPI-temporary-dep-solution-for-battery-support.patch
# Add SDIO ID for the V8P wireless adapter to ath6kl driver
Patch31200: support-Dell-OEM-chipset-found-in-Venue-8-Pro-SDIO-I.patch
+# UEFI boot fixes from Matt Fleming, fix
+# https://bugzilla.kernel.org/show_bug.cgi?id=84241
+Patch31201: x86-efi-only-load-initrd-above-4g-on-second-try.patch
+Patch21202: x86-efi-fixup-got-in-all-boot-code-paths.patch
+
# END OF AWB PATCH DEFINITIONS
# END OF PATCH DEFINITIONS
@@ -1376,6 +1381,8 @@ ApplyPatch kernel-arm64.patch -R
# AWB (BAYTRAIL) PATCH APPLICATIONS
ApplyPatch 0001-ACPI-temporary-dep-solution-for-battery-support.patch
ApplyPatch support-Dell-OEM-chipset-found-in-Venue-8-Pro-SDIO-I.patch
+ApplyPatch x86-efi-only-load-initrd-above-4g-on-second-try.patch
+ApplyPatch x86-efi-fixup-got-in-all-boot-code-paths.patch
# END OF AWB (BAYTRAIL) PATCH APPLICATIONS
diff --git a/x86-efi-fixup-got-in-all-boot-code-paths.patch b/x86-efi-fixup-got-in-all-boot-code-paths.patch
new file mode 100644
index 0000000..0c82266
--- /dev/null
+++ b/x86-efi-fixup-got-in-all-boot-code-paths.patch
@@ -0,0 +1,227 @@
+From 9cb0e394234d244fe5a97e743ec9dd7ddff7e64b Mon Sep 17 00:00:00 2001
+From: Matt Fleming <matt.fleming at intel.com>
+Date: Fri, 5 Sep 2014 14:52:26 +0100
+Subject: x86/efi: Fixup GOT in all boot code paths
+
+Maarten reported that his Macbook pro 8.2 stopped booting after commit
+f23cf8bd5c1f49 ("efi/x86: efistub: Move shared dependencies to
+<asm/efi.h>"), the main feature of which is changing the visibility of
+symbol 'efi_early' from local to global.
+
+By making 'efi_early' global we end up requiring an entry in the Global
+Offset Table. Unfortunately, while we do include code to fixup GOT
+entries in the early boot code, it's only called after we've executed
+the EFI boot stub.
+
+What this amounts to is that references to 'efi_early' in the EFI boot
+stub don't point to the correct place.
+
+Since we've got multiple boot entry points we need to be prepared to
+fixup the GOT in multiple places, while ensuring that we never do it
+more than once, otherwise the GOT entries will still point to the wrong
+place.
+
+Reported-by: Maarten Lankhorst <maarten.lankhorst at canonical.com>
+Tested-by: Maarten Lankhorst <maarten.lankhorst at canonical.com>
+Cc: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+Signed-off-by: Matt Fleming <matt.fleming at intel.com>
+
+diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
+index cbed140..d6b8aa4 100644
+--- a/arch/x86/boot/compressed/head_32.S
++++ b/arch/x86/boot/compressed/head_32.S
+@@ -30,6 +30,33 @@
+ #include <asm/boot.h>
+ #include <asm/asm-offsets.h>
+
++/*
++ * Adjust our own GOT
++ *
++ * The relocation base must be in %ebx
++ *
++ * It is safe to call this macro more than once, because in some of the
++ * code paths multiple invocations are inevitable, e.g. via the efi*
++ * entry points.
++ *
++ * Relocation is only performed the first time.
++ */
++.macro FIXUP_GOT
++ cmpb $1, got_fixed(%ebx)
++ je 2f
++
++ leal _got(%ebx), %edx
++ leal _egot(%ebx), %ecx
++1:
++ cmpl %ecx, %edx
++ jae 2f
++ addl %ebx, (%edx)
++ addl $4, %edx
++ jmp 1b
++2:
++ movb $1, got_fixed(%ebx)
++.endm
++
+ __HEAD
+ ENTRY(startup_32)
+ #ifdef CONFIG_EFI_STUB
+@@ -56,6 +83,9 @@ ENTRY(efi_pe_entry)
+ add %esi, 88(%eax)
+ pushl %eax
+
++ movl %esi, %ebx
++ FIXUP_GOT
++
+ call make_boot_params
+ cmpl $0, %eax
+ je fail
+@@ -81,6 +111,10 @@ ENTRY(efi32_stub_entry)
+ leal efi32_config(%esi), %eax
+ add %esi, 88(%eax)
+ pushl %eax
++
++ movl %esi, %ebx
++ FIXUP_GOT
++
+ 2:
+ call efi_main
+ cmpl $0, %eax
+@@ -190,19 +224,7 @@ relocated:
+ shrl $2, %ecx
+ rep stosl
+
+-/*
+- * Adjust our own GOT
+- */
+- leal _got(%ebx), %edx
+- leal _egot(%ebx), %ecx
+-1:
+- cmpl %ecx, %edx
+- jae 2f
+- addl %ebx, (%edx)
+- addl $4, %edx
+- jmp 1b
+-2:
+-
++ FIXUP_GOT
+ /*
+ * Do the decompression, and jump to the new kernel..
+ */
+@@ -225,8 +247,12 @@ relocated:
+ xorl %ebx, %ebx
+ jmp *%eax
+
+-#ifdef CONFIG_EFI_STUB
+ .data
++/* Have we relocated the GOT? */
++got_fixed:
++ .byte 0
++
++#ifdef CONFIG_EFI_STUB
+ efi32_config:
+ .fill 11,8,0
+ .long efi_call_phys
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index 2884e0c..50f69c7 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -32,6 +32,33 @@
+ #include <asm/processor-flags.h>
+ #include <asm/asm-offsets.h>
+
++/*
++ * Adjust our own GOT
++ *
++ * The relocation base must be in %rbx
++ *
++ * It is safe to call this macro more than once, because in some of the
++ * code paths multiple invocations are inevitable, e.g. via the efi*
++ * entry points.
++ *
++ * Relocation is only performed the first time.
++ */
++.macro FIXUP_GOT
++ cmpb $1, got_fixed(%rip)
++ je 2f
++
++ leaq _got(%rip), %rdx
++ leaq _egot(%rip), %rcx
++1:
++ cmpq %rcx, %rdx
++ jae 2f
++ addq %rbx, (%rdx)
++ addq $8, %rdx
++ jmp 1b
++2:
++ movb $1, got_fixed(%rip)
++.endm
++
+ __HEAD
+ .code32
+ ENTRY(startup_32)
+@@ -252,10 +279,13 @@ ENTRY(efi_pe_entry)
+ subq $1b, %rbp
+
+ /*
+- * Relocate efi_config->call().
++ * Relocate efi_config->call() and the GOT entries.
+ */
+ addq %rbp, efi64_config+88(%rip)
+
++ movq %rbp, %rbx
++ FIXUP_GOT
++
+ movq %rax, %rdi
+ call make_boot_params
+ cmpq $0,%rax
+@@ -271,10 +301,13 @@ handover_entry:
+ subq $1b, %rbp
+
+ /*
+- * Relocate efi_config->call().
++ * Relocate efi_config->call() and the GOT entries.
+ */
+ movq efi_config(%rip), %rax
+ addq %rbp, 88(%rax)
++
++ movq %rbp, %rbx
++ FIXUP_GOT
+ 2:
+ movq efi_config(%rip), %rdi
+ call efi_main
+@@ -385,19 +418,8 @@ relocated:
+ shrq $3, %rcx
+ rep stosq
+
+-/*
+- * Adjust our own GOT
+- */
+- leaq _got(%rip), %rdx
+- leaq _egot(%rip), %rcx
+-1:
+- cmpq %rcx, %rdx
+- jae 2f
+- addq %rbx, (%rdx)
+- addq $8, %rdx
+- jmp 1b
+-2:
+-
++ FIXUP_GOT
++
+ /*
+ * Do the decompression, and jump to the new kernel..
+ */
+@@ -437,6 +459,10 @@ gdt:
+ .quad 0x0000000000000000 /* TS continued */
+ gdt_end:
+
++/* Have we relocated the GOT? */
++got_fixed:
++ .byte 0
++
+ #ifdef CONFIG_EFI_STUB
+ efi_config:
+ .quad 0
+--
+cgit v0.10.1
+
+
diff --git a/x86-efi-only-load-initrd-above-4g-on-second-try.patch b/x86-efi-only-load-initrd-above-4g-on-second-try.patch
new file mode 100644
index 0000000..f977d8e
--- /dev/null
+++ b/x86-efi-only-load-initrd-above-4g-on-second-try.patch
@@ -0,0 +1,79 @@
+From 47226ad4f4cfd1e91ded7f2ec42f83ff1c624663 Mon Sep 17 00:00:00 2001
+From: Yinghai Lu <yinghai at kernel.org>
+Date: Wed, 3 Sep 2014 21:50:07 -0700
+Subject: x86/efi: Only load initrd above 4g on second try
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Mantas found that after commit 4bf7111f5016 ("x86/efi: Support initrd
+loaded above 4G"), the kernel freezes at the earliest possible moment
+when trying to boot via UEFI on Asus laptop.
+
+Revert to old way to load initrd under 4G on first try, second try will
+use above 4G buffer when initrd is too big and does not fit under 4G.
+
+[ The cause of the freeze appears to be a firmware bug when reading
+ file data into buffers above 4GB, though the exact reason is unknown.
+ Mantas reports that the hang can be avoid if the file size is a
+ multiple of 512 bytes, but I've seen some ASUS firmware simply
+ corrupting the file data rather than freezing.
+
+ Laszlo fixed an issue in the upstream EDK2 DiskIO code in Aug 2013
+ which may possibly be related, commit 4e39b75e ("MdeModulePkg/DiskIoDxe:
+ fix source/destination pointer of overrun transfer").
+
+ Whatever the cause, it's unlikely that a fix will be forthcoming
+ from the vendor, hence the workaround - Matt ]
+
+Cc: Laszlo Ersek <lersek at redhat.com>
+Reported-by: Mantas Mikulėnas <grawity at gmail.com>
+Reported-by: Harald Hoyer <harald at redhat.com>
+Tested-by: Anders Darander <anders at chargestorm.se>
+Tested-by: Calvin Walton <calvin.walton at kepstin.ca>
+Signed-off-by: Yinghai Lu <yinghai at kernel.org>
+Signed-off-by: Matt Fleming <matt.fleming at intel.com>
+
+diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
+index f277184..dca9842 100644
+--- a/arch/x86/boot/compressed/eboot.c
++++ b/arch/x86/boot/compressed/eboot.c
+@@ -1032,7 +1032,6 @@ struct boot_params *make_boot_params(struct efi_config *c)
+ int i;
+ unsigned long ramdisk_addr;
+ unsigned long ramdisk_size;
+- unsigned long initrd_addr_max;
+
+ efi_early = c;
+ sys_table = (efi_system_table_t *)(unsigned long)efi_early->table;
+@@ -1095,15 +1094,20 @@ struct boot_params *make_boot_params(struct efi_config *c)
+
+ memset(sdt, 0, sizeof(*sdt));
+
+- if (hdr->xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G)
+- initrd_addr_max = -1UL;
+- else
+- initrd_addr_max = hdr->initrd_addr_max;
+-
+ status = handle_cmdline_files(sys_table, image,
+ (char *)(unsigned long)hdr->cmd_line_ptr,
+- "initrd=", initrd_addr_max,
++ "initrd=", hdr->initrd_addr_max,
+ &ramdisk_addr, &ramdisk_size);
++
++ if (status != EFI_SUCCESS &&
++ hdr->xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G) {
++ efi_printk(sys_table, "Trying to load files to higher address\n");
++ status = handle_cmdline_files(sys_table, image,
++ (char *)(unsigned long)hdr->cmd_line_ptr,
++ "initrd=", -1UL,
++ &ramdisk_addr, &ramdisk_size);
++ }
++
+ if (status != EFI_SUCCESS)
+ goto fail2;
+ hdr->ramdisk_image = ramdisk_addr & 0xffffffff;
+--
+cgit v0.10.1
+
+
More information about the scm-commits
mailing list