summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2014-09-09 16:56:12 +0200
committerIngo Molnar <mingo@kernel.org>2014-09-09 16:56:12 +0200
commit5ac385d83525fb8924ef87c18a4dc49998366394 (patch)
tree68748bd20b197309abeeea2698cd0ccffcd15717
parentcc99535eb4049c730cac421d403d079593cb31ae (diff)
parent0ceac9e094b065fe3fec19669740f338d3480498 (diff)
Merge tag 'efi-urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi into x86/urgent
Pull EFI fixes from Matt Fleming: * Fix early boot regression affecting x86 EFI boot stub when loading initrds above 4GB - Yinghai Lu * Relocate GOT entries in the x86 EFI boot stub now that we have symbols with global visibility - Matt Fleming * fdt memory reservation fix for arm64 - Mark Salter Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/arm64/mm/init.c3
-rw-r--r--arch/x86/boot/compressed/eboot.c18
-rw-r--r--arch/x86/boot/compressed/head_32.S54
-rw-r--r--arch/x86/boot/compressed/head_64.S56
-rw-r--r--drivers/firmware/efi/libstub/fdt.c10
5 files changed, 102 insertions, 39 deletions
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 5472c2401876..a83061f37e43 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -149,8 +149,7 @@ void __init arm64_memblock_init(void)
memblock_reserve(__virt_to_phys(initrd_start), initrd_end - initrd_start);
#endif
- if (!efi_enabled(EFI_MEMMAP))
- early_init_fdt_scan_reserved_mem();
+ early_init_fdt_scan_reserved_mem();
/* 4GB maximum for 32-bit only capable devices */
if (IS_ENABLED(CONFIG_ZONE_DMA))
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index f277184e2ac1..dca9842d8f91 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;
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index cbed1407a5cd..d6b8aa4c986c 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 2884e0c3e8a5..50f69c7eaaf4 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
diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
index a56bb3528755..c846a9608cbd 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -22,7 +22,7 @@ efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
unsigned long map_size, unsigned long desc_size,
u32 desc_ver)
{
- int node, prev;
+ int node, prev, num_rsv;
int status;
u32 fdt_val32;
u64 fdt_val64;
@@ -73,6 +73,14 @@ efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
prev = node;
}
+ /*
+ * Delete all memory reserve map entries. When booting via UEFI,
+ * kernel will use the UEFI memory map to find reserved regions.
+ */
+ num_rsv = fdt_num_mem_rsv(fdt);
+ while (num_rsv-- > 0)
+ fdt_del_mem_rsv(fdt, num_rsv);
+
node = fdt_subnode_offset(fdt, 0, "chosen");
if (node < 0) {
node = fdt_add_subnode(fdt, 0, "chosen");