From eeb9db09f738993c63ecb5aedf950a1e4fe4bd3f Mon Sep 17 00:00:00 2001 From: Saurabh Tangri Date: Mon, 2 Jun 2014 05:18:35 -0700 Subject: x86/efi: Move all workarounds to a separate file quirks.c Currently, it's difficult to find all the workarounds that are applied when running on EFI, because they're littered throughout various code paths. This change moves all of them into a separate file with the hope that it will be come the single location for all our well documented quirks. Signed-off-by: Saurabh Tangri Signed-off-by: Matt Fleming --- arch/x86/include/asm/efi.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/x86/include/asm/efi.h') diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 1eb5f6433ad8..3dbf56eb540d 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -104,6 +104,8 @@ extern void __init runtime_code_page_mkexec(void); extern void __init efi_runtime_mkexec(void); extern void __init efi_dump_pagetable(void); extern void __init efi_apply_memmap_quirks(void); +extern int __init efi_reuse_config(u64 tables, int nr_tables); +extern void efi_delete_dummy_variable(void); struct efi_setup_data { u64 fw_vendor; -- cgit v1.2.3 From f23cf8bd5c1f49fb12459797d88b8407af93383d Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 2 Jul 2014 14:54:40 +0200 Subject: efi/x86: efistub: Move shared dependencies to This moves definitions depended upon both by code under arch/x86/boot and under drivers/firmware/efi to . This is in preparation of turning the stub code under drivers/firmware/efi into a static library. Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming --- arch/x86/boot/compressed/eboot.c | 5 +---- arch/x86/boot/compressed/eboot.h | 16 ---------------- arch/x86/include/asm/efi.h | 25 +++++++++++++++++++++++++ 3 files changed, 26 insertions(+), 20 deletions(-) (limited to 'arch/x86/include/asm/efi.h') diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index 385f42c200bc..c066bc4e3051 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -19,10 +19,7 @@ static efi_system_table_t *sys_table; -static struct efi_config *efi_early; - -#define efi_call_early(f, ...) \ - efi_early->call(efi_early->f, __VA_ARGS__); +struct efi_config *efi_early; #define BOOT_SERVICES(bits) \ static void setup_boot_services##bits(struct efi_config *c) \ diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h index c88c31ecad12..d487e727f1ec 100644 --- a/arch/x86/boot/compressed/eboot.h +++ b/arch/x86/boot/compressed/eboot.h @@ -103,20 +103,4 @@ struct efi_uga_draw_protocol { void *blt; }; -struct efi_config { - u64 image_handle; - u64 table; - u64 allocate_pool; - u64 allocate_pages; - u64 get_memory_map; - u64 free_pool; - u64 free_pages; - u64 locate_handle; - u64 handle_protocol; - u64 exit_boot_services; - u64 text_output; - efi_status_t (*call)(unsigned long, ...); - bool is64; -} __packed; - #endif /* BOOT_COMPRESSED_EBOOT_H */ diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 3dbf56eb540d..9043f365ebf5 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -158,6 +158,31 @@ static inline efi_status_t efi_thunk_set_virtual_address_map( return EFI_SUCCESS; } #endif /* CONFIG_EFI_MIXED */ + + +/* arch specific definitions used by the stub code */ + +struct efi_config { + u64 image_handle; + u64 table; + u64 allocate_pool; + u64 allocate_pages; + u64 get_memory_map; + u64 free_pool; + u64 free_pages; + u64 locate_handle; + u64 handle_protocol; + u64 exit_boot_services; + u64 text_output; + efi_status_t (*call)(unsigned long, ...); + bool is64; +} __packed; + +extern struct efi_config *efi_early; + +#define efi_call_early(f, ...) \ + efi_early->call(efi_early->f, __VA_ARGS__); + #else /* * IF EFI is not configured, have the EFI calls return -ENOSYS. -- cgit v1.2.3 From 44be28e9dd9880dca3e2cbf7a844f2114e67f2cb Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Fri, 13 Jun 2014 12:39:55 +0100 Subject: x86/reboot: Add EFI reboot quirk for ACPI Hardware Reduced flag It appears that the BayTrail-T class of hardware requires EFI in order to powerdown and reboot and no other reliable method exists. This quirk is generally applicable to all hardware that has the ACPI Hardware Reduced bit set, since usually ACPI would be the preferred method. Cc: Len Brown Cc: Mark Salter Cc: "Rafael J. Wysocki" Signed-off-by: Matt Fleming --- arch/x86/include/asm/efi.h | 6 ++++++ arch/x86/kernel/reboot.c | 18 ++++++++++++++++-- arch/x86/platform/efi/quirks.c | 23 +++++++++++++++++++++++ drivers/firmware/efi/reboot.c | 8 ++++++++ include/linux/efi.h | 1 + 5 files changed, 54 insertions(+), 2 deletions(-) (limited to 'arch/x86/include/asm/efi.h') diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 9043f365ebf5..044a2fd3c5fe 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -183,6 +183,8 @@ extern struct efi_config *efi_early; #define efi_call_early(f, ...) \ efi_early->call(efi_early->f, __VA_ARGS__); +extern bool efi_reboot_required(void); + #else /* * IF EFI is not configured, have the EFI calls return -ENOSYS. @@ -195,6 +197,10 @@ extern struct efi_config *efi_early; #define efi_call5(_f, _a1, _a2, _a3, _a4, _a5) (-ENOSYS) #define efi_call6(_f, _a1, _a2, _a3, _a4, _a5, _a6) (-ENOSYS) static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {} +static inline bool efi_reboot_required(void) +{ + return false; +} #endif /* CONFIG_EFI */ #endif /* _ASM_X86_EFI_H */ diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 09e709fd1830..17962e667a91 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -28,6 +28,7 @@ #include #include #include +#include /* * Power off function, if any @@ -401,12 +402,25 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { static int __init reboot_init(void) { + int rv; + /* * Only do the DMI check if reboot_type hasn't been overridden * on the command line */ - if (reboot_default) - dmi_check_system(reboot_dmi_table); + if (!reboot_default) + return 0; + + /* + * The DMI quirks table takes precedence. If no quirks entry + * matches and the ACPI Hardware Reduced bit is set, force EFI + * reboot. + */ + rv = dmi_check_system(reboot_dmi_table); + + if (!rv && efi_reboot_required()) + reboot_type = BOOT_EFI; + return 0; } core_initcall(reboot_init); diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c index b4cb9182f155..1c7380da65ff 100644 --- a/arch/x86/platform/efi/quirks.c +++ b/arch/x86/platform/efi/quirks.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -265,3 +266,25 @@ void __init efi_apply_memmap_quirks(void) if (is_uv_system()) set_bit(EFI_OLD_MEMMAP, &efi.flags); } + +/* + * For most modern platforms the preferred method of powering off is via + * ACPI. However, there are some that are known to require the use of + * EFI runtime services and for which ACPI does not work at all. + * + * Using EFI is a last resort, to be used only if no other option + * exists. + */ +bool efi_reboot_required(void) +{ + if (!acpi_gbl_reduced_hardware) + return false; + + efi_reboot_quirk_mode = EFI_RESET_WARM; + return true; +} + +bool efi_poweroff_required(void) +{ + return !!acpi_gbl_reduced_hardware; +} diff --git a/drivers/firmware/efi/reboot.c b/drivers/firmware/efi/reboot.c index e9eeeb3c6345..9c59d1c795d1 100644 --- a/drivers/firmware/efi/reboot.c +++ b/drivers/firmware/efi/reboot.c @@ -5,6 +5,8 @@ #include #include +int efi_reboot_quirk_mode = -1; + void efi_reboot(enum reboot_mode reboot_mode, const char *__unused) { int efi_mode; @@ -22,6 +24,12 @@ void efi_reboot(enum reboot_mode reboot_mode, const char *__unused) break; } + /* + * If a quirk forced an EFI reset mode, always use that. + */ + if (efi_reboot_quirk_mode != -1) + efi_mode = efi_reboot_quirk_mode; + efi.reset_system(efi_mode, EFI_SUCCESS, 0, NULL); } diff --git a/include/linux/efi.h b/include/linux/efi.h index 9917f58ee83e..bac0f93dc473 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -878,6 +878,7 @@ extern void efi_reserve_boot_services(void); extern int efi_get_fdt_params(struct efi_fdt_params *params, int verbose); extern struct efi_memory_map memmap; +extern int efi_reboot_quirk_mode; extern bool efi_poweroff_required(void); /* Iterate through an efi_memory_map */ -- cgit v1.2.3 From 84be880560fbbd0b6a6ef973bee85dbd4ca52198 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Tue, 23 Sep 2014 10:37:43 +0100 Subject: Revert "efi/x86: efistub: Move shared dependencies to " This reverts commit f23cf8bd5c1f ("efi/x86: efistub: Move shared dependencies to ") as well as the x86 parts of commit f4f75ad5741f ("efi: efistub: Convert into static library"). The road leading to these two reverts is long and winding. The above two commits were merged during the v3.17 merge window and turned the common EFI boot stub code into a static library. This necessitated making some symbols global in the x86 boot stub which introduced new entries into the early boot GOT. The problem was that we weren't fixing up the newly created GOT entries before invoking the EFI boot stub, which sometimes resulted in hangs or resets. This failure was reported by Maarten on his Macbook pro. The proposed fix was commit 9cb0e394234d ("x86/efi: Fixup GOT in all boot code paths"). However, that caused issues for Linus when booting his Sony Vaio Pro 11. It was subsequently reverted in commit f3670394c29f. So that leaves us back with Maarten's Macbook pro not booting. At this stage in the release cycle the least risky option is to revert the x86 EFI boot stub to the pre-merge window code structure where we explicitly #include efi-stub-helper.c instead of linking with the static library. The arm64 code remains unaffected. We can take another swing at the x86 parts for v3.18. Conflicts: arch/x86/include/asm/efi.h Tested-by: Josh Boyer Tested-by: Maarten Lankhorst Tested-by: Leif Lindholm [arm64] Tested-by: Linus Torvalds Cc: H. Peter Anvin Cc: Ard Biesheuvel , Cc: Ingo Molnar Signed-off-by: Matt Fleming --- arch/x86/boot/compressed/Makefile | 3 +-- arch/x86/boot/compressed/eboot.c | 7 ++++++- arch/x86/boot/compressed/eboot.h | 16 ++++++++++++++++ arch/x86/include/asm/efi.h | 24 ------------------------ drivers/firmware/efi/Makefile | 2 +- 5 files changed, 24 insertions(+), 28 deletions(-) (limited to 'arch/x86/include/asm/efi.h') diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 7a801a310e37..0fcd9133790c 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -33,8 +33,7 @@ VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \ $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone ifeq ($(CONFIG_EFI_STUB), y) - VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o \ - $(objtree)/drivers/firmware/efi/libstub/lib.a + VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o endif $(obj)/vmlinux: $(VMLINUX_OBJS) FORCE diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index dca9842d8f91..b04f1e0e3fab 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -19,7 +19,10 @@ static efi_system_table_t *sys_table; -struct efi_config *efi_early; +static struct efi_config *efi_early; + +#define efi_call_early(f, ...) \ + efi_early->call(efi_early->f, __VA_ARGS__); #define BOOT_SERVICES(bits) \ static void setup_boot_services##bits(struct efi_config *c) \ @@ -280,6 +283,8 @@ void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str) } } +#include "../../../../drivers/firmware/efi/libstub/efi-stub-helper.c" + static void find_bits(unsigned long mask, u8 *pos, u8 *size) { u8 first, len; diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h index d487e727f1ec..c88c31ecad12 100644 --- a/arch/x86/boot/compressed/eboot.h +++ b/arch/x86/boot/compressed/eboot.h @@ -103,4 +103,20 @@ struct efi_uga_draw_protocol { void *blt; }; +struct efi_config { + u64 image_handle; + u64 table; + u64 allocate_pool; + u64 allocate_pages; + u64 get_memory_map; + u64 free_pool; + u64 free_pages; + u64 locate_handle; + u64 handle_protocol; + u64 exit_boot_services; + u64 text_output; + efi_status_t (*call)(unsigned long, ...); + bool is64; +} __packed; + #endif /* BOOT_COMPRESSED_EBOOT_H */ diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 044a2fd3c5fe..0ec241ede5a2 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -159,30 +159,6 @@ static inline efi_status_t efi_thunk_set_virtual_address_map( } #endif /* CONFIG_EFI_MIXED */ - -/* arch specific definitions used by the stub code */ - -struct efi_config { - u64 image_handle; - u64 table; - u64 allocate_pool; - u64 allocate_pages; - u64 get_memory_map; - u64 free_pool; - u64 free_pages; - u64 locate_handle; - u64 handle_protocol; - u64 exit_boot_services; - u64 text_output; - efi_status_t (*call)(unsigned long, ...); - bool is64; -} __packed; - -extern struct efi_config *efi_early; - -#define efi_call_early(f, ...) \ - efi_early->call(efi_early->f, __VA_ARGS__); - extern bool efi_reboot_required(void); #else diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index d8be608a9f3b..aef6a95adef5 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile @@ -7,4 +7,4 @@ obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o obj-$(CONFIG_UEFI_CPER) += cper.o obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o -obj-$(CONFIG_EFI_STUB) += libstub/ +obj-$(CONFIG_EFI_ARM_STUB) += libstub/ -- cgit v1.2.3