[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