diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-04 20:13:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-04 20:13:50 -0400 |
commit | 76f09aa464a1913efd596dd0edbf88f932fde08c (patch) | |
tree | ce9aadc9a1c30597b9d61c7aac86bfb2e6caf961 | |
parent | e9c9eecabaa898ff3fedd98813ee4ac1a00d006a (diff) | |
parent | 99a5603e2a1f146ac0c6414d8a3669aa749ccff8 (diff) |
Merge branch 'x86-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull EFI changes from Ingo Molnar:
"Main changes in this cycle are:
- arm64 efi stub fixes, preservation of FP/SIMD registers across
firmware calls, and conversion of the EFI stub code into a static
library - Ard Biesheuvel
- Xen EFI support - Daniel Kiper
- Support for autoloading the efivars driver - Lee, Chun-Yi
- Use the PE/COFF headers in the x86 EFI boot stub to request that
the stub be loaded with CONFIG_PHYSICAL_ALIGN alignment - Michael
Brown
- Consolidate all the x86 EFI quirks into one file - Saurabh Tangri
- Additional error logging in x86 EFI boot stub - Ulf Winkelvos
- Support loading initrd above 4G in EFI boot stub - Yinghai Lu
- EFI reboot patches for ACPI hardware reduced platforms"
* 'x86-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (31 commits)
efi/arm64: Handle missing virtual mapping for UEFI System Table
arch/x86/xen: Silence compiler warnings
xen: Silence compiler warnings
x86/efi: Request desired alignment via the PE/COFF headers
x86/efi: Add better error logging to EFI boot stub
efi: Autoload efivars
efi: Update stale locking comment for struct efivars
arch/x86: Remove efi_set_rtc_mmss()
arch/x86: Replace plain strings with constants
xen: Put EFI machinery in place
xen: Define EFI related stuff
arch/x86: Remove redundant set_bit(EFI_MEMMAP) call
arch/x86: Remove redundant set_bit(EFI_SYSTEM_TABLES) call
efi: Introduce EFI_PARAVIRT flag
arch/x86: Do not access EFI memory map if it is not available
efi: Use early_mem*() instead of early_io*()
arch/ia64: Define early_memunmap()
x86/reboot: Add EFI reboot quirk for ACPI Hardware Reduced flag
efi/reboot: Allow powering off machines using EFI
efi/reboot: Add generic wrapper around EfiResetSystem()
...
40 files changed, 1508 insertions, 622 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index f3b584be76d7..b0f9c9db9590 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig | |||
@@ -347,12 +347,18 @@ config CMDLINE_FORCE | |||
347 | This is useful if you cannot or don't want to change the | 347 | This is useful if you cannot or don't want to change the |
348 | command-line options your boot loader passes to the kernel. | 348 | command-line options your boot loader passes to the kernel. |
349 | 349 | ||
350 | config EFI_STUB | ||
351 | bool | ||
352 | |||
350 | config EFI | 353 | config EFI |
351 | bool "UEFI runtime support" | 354 | bool "UEFI runtime support" |
352 | depends on OF && !CPU_BIG_ENDIAN | 355 | depends on OF && !CPU_BIG_ENDIAN |
353 | select LIBFDT | 356 | select LIBFDT |
354 | select UCS2_STRING | 357 | select UCS2_STRING |
355 | select EFI_PARAMS_FROM_FDT | 358 | select EFI_PARAMS_FROM_FDT |
359 | select EFI_RUNTIME_WRAPPERS | ||
360 | select EFI_STUB | ||
361 | select EFI_ARMSTUB | ||
356 | default y | 362 | default y |
357 | help | 363 | help |
358 | This option provides support for runtime services provided | 364 | This option provides support for runtime services provided |
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index e8d025c1459e..57833546bf00 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile | |||
@@ -52,6 +52,7 @@ core-$(CONFIG_XEN) += arch/arm64/xen/ | |||
52 | core-$(CONFIG_CRYPTO) += arch/arm64/crypto/ | 52 | core-$(CONFIG_CRYPTO) += arch/arm64/crypto/ |
53 | libs-y := arch/arm64/lib/ $(libs-y) | 53 | libs-y := arch/arm64/lib/ $(libs-y) |
54 | libs-y += $(LIBGCC) | 54 | libs-y += $(LIBGCC) |
55 | libs-$(CONFIG_EFI_STUB) += drivers/firmware/efi/libstub/ | ||
55 | 56 | ||
56 | # Default target when executing plain make | 57 | # Default target when executing plain make |
57 | KBUILD_IMAGE := Image.gz | 58 | KBUILD_IMAGE := Image.gz |
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index 5a46c4e7f539..a34fd3b12e2b 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define _ASM_EFI_H | 2 | #define _ASM_EFI_H |
3 | 3 | ||
4 | #include <asm/io.h> | 4 | #include <asm/io.h> |
5 | #include <asm/neon.h> | ||
5 | 6 | ||
6 | #ifdef CONFIG_EFI | 7 | #ifdef CONFIG_EFI |
7 | extern void efi_init(void); | 8 | extern void efi_init(void); |
@@ -11,4 +12,36 @@ extern void efi_idmap_init(void); | |||
11 | #define efi_idmap_init() | 12 | #define efi_idmap_init() |
12 | #endif | 13 | #endif |
13 | 14 | ||
15 | #define efi_call_virt(f, ...) \ | ||
16 | ({ \ | ||
17 | efi_##f##_t *__f = efi.systab->runtime->f; \ | ||
18 | efi_status_t __s; \ | ||
19 | \ | ||
20 | kernel_neon_begin(); \ | ||
21 | __s = __f(__VA_ARGS__); \ | ||
22 | kernel_neon_end(); \ | ||
23 | __s; \ | ||
24 | }) | ||
25 | |||
26 | #define __efi_call_virt(f, ...) \ | ||
27 | ({ \ | ||
28 | efi_##f##_t *__f = efi.systab->runtime->f; \ | ||
29 | \ | ||
30 | kernel_neon_begin(); \ | ||
31 | __f(__VA_ARGS__); \ | ||
32 | kernel_neon_end(); \ | ||
33 | }) | ||
34 | |||
35 | /* arch specific definitions used by the stub code */ | ||
36 | |||
37 | /* | ||
38 | * AArch64 requires the DTB to be 8-byte aligned in the first 512MiB from | ||
39 | * start of kernel and may not cross a 2MiB boundary. We set alignment to | ||
40 | * 2MiB so we know it won't cross a 2MiB boundary. | ||
41 | */ | ||
42 | #define EFI_FDT_ALIGN SZ_2M /* used by allocate_new_fdt_and_exit_boot() */ | ||
43 | #define MAX_FDT_OFFSET SZ_512M | ||
44 | |||
45 | #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) | ||
46 | |||
14 | #endif /* _ASM_EFI_H */ | 47 | #endif /* _ASM_EFI_H */ |
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 27c72ef4fd7a..df7ef8768fc2 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile | |||
@@ -4,8 +4,7 @@ | |||
4 | 4 | ||
5 | CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET) | 5 | CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET) |
6 | AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET) | 6 | AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET) |
7 | CFLAGS_efi-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) \ | 7 | CFLAGS_efi-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) |
8 | -I$(src)/../../../scripts/dtc/libfdt | ||
9 | 8 | ||
10 | CFLAGS_REMOVE_ftrace.o = -pg | 9 | CFLAGS_REMOVE_ftrace.o = -pg |
11 | CFLAGS_REMOVE_insn.o = -pg | 10 | CFLAGS_REMOVE_insn.o = -pg |
diff --git a/arch/arm64/kernel/efi-stub.c b/arch/arm64/kernel/efi-stub.c index e786e6cdc400..1317fef8dde9 100644 --- a/arch/arm64/kernel/efi-stub.c +++ b/arch/arm64/kernel/efi-stub.c | |||
@@ -10,46 +10,16 @@ | |||
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | #include <linux/efi.h> | 12 | #include <linux/efi.h> |
13 | #include <linux/libfdt.h> | 13 | #include <asm/efi.h> |
14 | #include <asm/sections.h> | 14 | #include <asm/sections.h> |
15 | 15 | ||
16 | /* | 16 | efi_status_t handle_kernel_image(efi_system_table_t *sys_table, |
17 | * AArch64 requires the DTB to be 8-byte aligned in the first 512MiB from | 17 | unsigned long *image_addr, |
18 | * start of kernel and may not cross a 2MiB boundary. We set alignment to | 18 | unsigned long *image_size, |
19 | * 2MiB so we know it won't cross a 2MiB boundary. | 19 | unsigned long *reserve_addr, |
20 | */ | 20 | unsigned long *reserve_size, |
21 | #define EFI_FDT_ALIGN SZ_2M /* used by allocate_new_fdt_and_exit_boot() */ | 21 | unsigned long dram_base, |
22 | #define MAX_FDT_OFFSET SZ_512M | 22 | efi_loaded_image_t *image) |
23 | |||
24 | #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) | ||
25 | |||
26 | static void efi_char16_printk(efi_system_table_t *sys_table_arg, | ||
27 | efi_char16_t *str); | ||
28 | |||
29 | static efi_status_t efi_open_volume(efi_system_table_t *sys_table, | ||
30 | void *__image, void **__fh); | ||
31 | static efi_status_t efi_file_close(void *handle); | ||
32 | |||
33 | static efi_status_t | ||
34 | efi_file_read(void *handle, unsigned long *size, void *addr); | ||
35 | |||
36 | static efi_status_t | ||
37 | efi_file_size(efi_system_table_t *sys_table, void *__fh, | ||
38 | efi_char16_t *filename_16, void **handle, u64 *file_sz); | ||
39 | |||
40 | /* Include shared EFI stub code */ | ||
41 | #include "../../../drivers/firmware/efi/efi-stub-helper.c" | ||
42 | #include "../../../drivers/firmware/efi/fdt.c" | ||
43 | #include "../../../drivers/firmware/efi/arm-stub.c" | ||
44 | |||
45 | |||
46 | static efi_status_t handle_kernel_image(efi_system_table_t *sys_table, | ||
47 | unsigned long *image_addr, | ||
48 | unsigned long *image_size, | ||
49 | unsigned long *reserve_addr, | ||
50 | unsigned long *reserve_size, | ||
51 | unsigned long dram_base, | ||
52 | efi_loaded_image_t *image) | ||
53 | { | 23 | { |
54 | efi_status_t status; | 24 | efi_status_t status; |
55 | unsigned long kernel_size, kernel_memsize = 0; | 25 | unsigned long kernel_size, kernel_memsize = 0; |
@@ -69,7 +39,7 @@ static efi_status_t handle_kernel_image(efi_system_table_t *sys_table, | |||
69 | if (*image_addr != (dram_base + TEXT_OFFSET)) { | 39 | if (*image_addr != (dram_base + TEXT_OFFSET)) { |
70 | pr_efi_err(sys_table, "Failed to alloc kernel memory\n"); | 40 | pr_efi_err(sys_table, "Failed to alloc kernel memory\n"); |
71 | efi_free(sys_table, kernel_memsize, *image_addr); | 41 | efi_free(sys_table, kernel_memsize, *image_addr); |
72 | return EFI_ERROR; | 42 | return EFI_LOAD_ERROR; |
73 | } | 43 | } |
74 | *image_size = kernel_memsize; | 44 | *image_size = kernel_memsize; |
75 | } | 45 | } |
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 14db1f6e8d7f..e72f3100958f 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c | |||
@@ -414,13 +414,24 @@ static int __init arm64_enter_virtual_mode(void) | |||
414 | for_each_efi_memory_desc(&memmap, md) { | 414 | for_each_efi_memory_desc(&memmap, md) { |
415 | if (!(md->attribute & EFI_MEMORY_RUNTIME)) | 415 | if (!(md->attribute & EFI_MEMORY_RUNTIME)) |
416 | continue; | 416 | continue; |
417 | if (remap_region(md, &virt_md)) | 417 | if (!remap_region(md, &virt_md)) |
418 | ++count; | 418 | goto err_unmap; |
419 | ++count; | ||
419 | } | 420 | } |
420 | 421 | ||
421 | efi.systab = (__force void *)efi_lookup_mapped_addr(efi_system_table); | 422 | efi.systab = (__force void *)efi_lookup_mapped_addr(efi_system_table); |
422 | if (efi.systab) | 423 | if (!efi.systab) { |
423 | set_bit(EFI_SYSTEM_TABLES, &efi.flags); | 424 | /* |
425 | * If we have no virtual mapping for the System Table at this | ||
426 | * point, the memory map doesn't cover the physical offset where | ||
427 | * it resides. This means the System Table will be inaccessible | ||
428 | * to Runtime Services themselves once the virtual mapping is | ||
429 | * installed. | ||
430 | */ | ||
431 | pr_err("Failed to remap EFI System Table -- buggy firmware?\n"); | ||
432 | goto err_unmap; | ||
433 | } | ||
434 | set_bit(EFI_SYSTEM_TABLES, &efi.flags); | ||
424 | 435 | ||
425 | local_irq_save(flags); | 436 | local_irq_save(flags); |
426 | cpu_switch_mm(idmap_pg_dir, &init_mm); | 437 | cpu_switch_mm(idmap_pg_dir, &init_mm); |
@@ -449,21 +460,18 @@ static int __init arm64_enter_virtual_mode(void) | |||
449 | 460 | ||
450 | /* Set up runtime services function pointers */ | 461 | /* Set up runtime services function pointers */ |
451 | runtime = efi.systab->runtime; | 462 | runtime = efi.systab->runtime; |
452 | efi.get_time = runtime->get_time; | 463 | efi_native_runtime_setup(); |
453 | efi.set_time = runtime->set_time; | ||
454 | efi.get_wakeup_time = runtime->get_wakeup_time; | ||
455 | efi.set_wakeup_time = runtime->set_wakeup_time; | ||
456 | efi.get_variable = runtime->get_variable; | ||
457 | efi.get_next_variable = runtime->get_next_variable; | ||
458 | efi.set_variable = runtime->set_variable; | ||
459 | efi.query_variable_info = runtime->query_variable_info; | ||
460 | efi.update_capsule = runtime->update_capsule; | ||
461 | efi.query_capsule_caps = runtime->query_capsule_caps; | ||
462 | efi.get_next_high_mono_count = runtime->get_next_high_mono_count; | ||
463 | efi.reset_system = runtime->reset_system; | ||
464 | |||
465 | set_bit(EFI_RUNTIME_SERVICES, &efi.flags); | 464 | set_bit(EFI_RUNTIME_SERVICES, &efi.flags); |
466 | 465 | ||
467 | return 0; | 466 | return 0; |
467 | |||
468 | err_unmap: | ||
469 | /* unmap all mappings that succeeded: there are 'count' of those */ | ||
470 | for (virt_md = virtmap; count--; virt_md += memmap.desc_size) { | ||
471 | md = virt_md; | ||
472 | iounmap((__force void __iomem *)md->virt_addr); | ||
473 | } | ||
474 | kfree(virtmap); | ||
475 | return -1; | ||
468 | } | 476 | } |
469 | early_initcall(arm64_enter_virtual_mode); | 477 | early_initcall(arm64_enter_virtual_mode); |
diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h index 0d2bcb37ec35..bee0acd52f7e 100644 --- a/arch/ia64/include/asm/io.h +++ b/arch/ia64/include/asm/io.h | |||
@@ -426,6 +426,7 @@ extern void iounmap (volatile void __iomem *addr); | |||
426 | extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size); | 426 | extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size); |
427 | #define early_memremap(phys_addr, size) early_ioremap(phys_addr, size) | 427 | #define early_memremap(phys_addr, size) early_ioremap(phys_addr, size) |
428 | extern void early_iounmap (volatile void __iomem *addr, unsigned long size); | 428 | extern void early_iounmap (volatile void __iomem *addr, unsigned long size); |
429 | #define early_memunmap(addr, size) early_iounmap(addr, size) | ||
429 | static inline void __iomem * ioremap_cache (unsigned long phys_addr, unsigned long size) | 430 | static inline void __iomem * ioremap_cache (unsigned long phys_addr, unsigned long size) |
430 | { | 431 | { |
431 | return ioremap(phys_addr, size); | 432 | return ioremap(phys_addr, size); |
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 55d4ba47a907..deed6fa96bb0 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c | |||
@@ -662,7 +662,7 @@ void | |||
662 | machine_restart (char *restart_cmd) | 662 | machine_restart (char *restart_cmd) |
663 | { | 663 | { |
664 | (void) notify_die(DIE_MACHINE_RESTART, restart_cmd, NULL, 0, 0, 0); | 664 | (void) notify_die(DIE_MACHINE_RESTART, restart_cmd, NULL, 0, 0, 0); |
665 | (*efi.reset_system)(EFI_RESET_WARM, 0, 0, NULL); | 665 | efi_reboot(REBOOT_WARM, NULL); |
666 | } | 666 | } |
667 | 667 | ||
668 | void | 668 | void |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 2840c27d4479..3fc7d724d0a3 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -1522,6 +1522,7 @@ config EFI | |||
1522 | bool "EFI runtime service support" | 1522 | bool "EFI runtime service support" |
1523 | depends on ACPI | 1523 | depends on ACPI |
1524 | select UCS2_STRING | 1524 | select UCS2_STRING |
1525 | select EFI_RUNTIME_WRAPPERS | ||
1525 | ---help--- | 1526 | ---help--- |
1526 | This enables the kernel to use EFI runtime services that are | 1527 | This enables the kernel to use EFI runtime services that are |
1527 | available (such as the EFI variable services). | 1528 | available (such as the EFI variable services). |
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 0fcd9133790c..7a801a310e37 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile | |||
@@ -33,7 +33,8 @@ VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \ | |||
33 | $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone | 33 | $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone |
34 | 34 | ||
35 | ifeq ($(CONFIG_EFI_STUB), y) | 35 | ifeq ($(CONFIG_EFI_STUB), y) |
36 | VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o | 36 | VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o \ |
37 | $(objtree)/drivers/firmware/efi/libstub/lib.a | ||
37 | endif | 38 | endif |
38 | 39 | ||
39 | $(obj)/vmlinux: $(VMLINUX_OBJS) FORCE | 40 | $(obj)/vmlinux: $(VMLINUX_OBJS) FORCE |
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index 0331d765c2bb..f277184e2ac1 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c | |||
@@ -19,10 +19,7 @@ | |||
19 | 19 | ||
20 | static efi_system_table_t *sys_table; | 20 | static efi_system_table_t *sys_table; |
21 | 21 | ||
22 | static struct efi_config *efi_early; | 22 | struct efi_config *efi_early; |
23 | |||
24 | #define efi_call_early(f, ...) \ | ||
25 | efi_early->call(efi_early->f, __VA_ARGS__); | ||
26 | 23 | ||
27 | #define BOOT_SERVICES(bits) \ | 24 | #define BOOT_SERVICES(bits) \ |
28 | static void setup_boot_services##bits(struct efi_config *c) \ | 25 | static void setup_boot_services##bits(struct efi_config *c) \ |
@@ -48,8 +45,7 @@ static void setup_boot_services##bits(struct efi_config *c) \ | |||
48 | BOOT_SERVICES(32); | 45 | BOOT_SERVICES(32); |
49 | BOOT_SERVICES(64); | 46 | BOOT_SERVICES(64); |
50 | 47 | ||
51 | static void efi_printk(efi_system_table_t *, char *); | 48 | void efi_char16_printk(efi_system_table_t *, efi_char16_t *); |
52 | static void efi_char16_printk(efi_system_table_t *, efi_char16_t *); | ||
53 | 49 | ||
54 | static efi_status_t | 50 | static efi_status_t |
55 | __file_size32(void *__fh, efi_char16_t *filename_16, | 51 | __file_size32(void *__fh, efi_char16_t *filename_16, |
@@ -156,7 +152,7 @@ grow: | |||
156 | 152 | ||
157 | return status; | 153 | return status; |
158 | } | 154 | } |
159 | static efi_status_t | 155 | efi_status_t |
160 | efi_file_size(efi_system_table_t *sys_table, void *__fh, | 156 | efi_file_size(efi_system_table_t *sys_table, void *__fh, |
161 | efi_char16_t *filename_16, void **handle, u64 *file_sz) | 157 | efi_char16_t *filename_16, void **handle, u64 *file_sz) |
162 | { | 158 | { |
@@ -166,7 +162,7 @@ efi_file_size(efi_system_table_t *sys_table, void *__fh, | |||
166 | return __file_size32(__fh, filename_16, handle, file_sz); | 162 | return __file_size32(__fh, filename_16, handle, file_sz); |
167 | } | 163 | } |
168 | 164 | ||
169 | static inline efi_status_t | 165 | efi_status_t |
170 | efi_file_read(void *handle, unsigned long *size, void *addr) | 166 | efi_file_read(void *handle, unsigned long *size, void *addr) |
171 | { | 167 | { |
172 | unsigned long func; | 168 | unsigned long func; |
@@ -184,7 +180,7 @@ efi_file_read(void *handle, unsigned long *size, void *addr) | |||
184 | } | 180 | } |
185 | } | 181 | } |
186 | 182 | ||
187 | static inline efi_status_t efi_file_close(void *handle) | 183 | efi_status_t efi_file_close(void *handle) |
188 | { | 184 | { |
189 | if (efi_early->is64) { | 185 | if (efi_early->is64) { |
190 | efi_file_handle_64_t *fh = handle; | 186 | efi_file_handle_64_t *fh = handle; |
@@ -249,7 +245,7 @@ static inline efi_status_t __open_volume64(void *__image, void **__fh) | |||
249 | return status; | 245 | return status; |
250 | } | 246 | } |
251 | 247 | ||
252 | static inline efi_status_t | 248 | efi_status_t |
253 | efi_open_volume(efi_system_table_t *sys_table, void *__image, void **__fh) | 249 | efi_open_volume(efi_system_table_t *sys_table, void *__image, void **__fh) |
254 | { | 250 | { |
255 | if (efi_early->is64) | 251 | if (efi_early->is64) |
@@ -258,7 +254,7 @@ efi_open_volume(efi_system_table_t *sys_table, void *__image, void **__fh) | |||
258 | return __open_volume32(__image, __fh); | 254 | return __open_volume32(__image, __fh); |
259 | } | 255 | } |
260 | 256 | ||
261 | static void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str) | 257 | void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str) |
262 | { | 258 | { |
263 | unsigned long output_string; | 259 | unsigned long output_string; |
264 | size_t offset; | 260 | size_t offset; |
@@ -284,8 +280,6 @@ static void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str) | |||
284 | } | 280 | } |
285 | } | 281 | } |
286 | 282 | ||
287 | #include "../../../../drivers/firmware/efi/efi-stub-helper.c" | ||
288 | |||
289 | static void find_bits(unsigned long mask, u8 *pos, u8 *size) | 283 | static void find_bits(unsigned long mask, u8 *pos, u8 *size) |
290 | { | 284 | { |
291 | u8 first, len; | 285 | u8 first, len; |
@@ -1038,6 +1032,7 @@ struct boot_params *make_boot_params(struct efi_config *c) | |||
1038 | int i; | 1032 | int i; |
1039 | unsigned long ramdisk_addr; | 1033 | unsigned long ramdisk_addr; |
1040 | unsigned long ramdisk_size; | 1034 | unsigned long ramdisk_size; |
1035 | unsigned long initrd_addr_max; | ||
1041 | 1036 | ||
1042 | efi_early = c; | 1037 | efi_early = c; |
1043 | sys_table = (efi_system_table_t *)(unsigned long)efi_early->table; | 1038 | sys_table = (efi_system_table_t *)(unsigned long)efi_early->table; |
@@ -1100,14 +1095,21 @@ struct boot_params *make_boot_params(struct efi_config *c) | |||
1100 | 1095 | ||
1101 | memset(sdt, 0, sizeof(*sdt)); | 1096 | memset(sdt, 0, sizeof(*sdt)); |
1102 | 1097 | ||
1098 | if (hdr->xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G) | ||
1099 | initrd_addr_max = -1UL; | ||
1100 | else | ||
1101 | initrd_addr_max = hdr->initrd_addr_max; | ||
1102 | |||
1103 | status = handle_cmdline_files(sys_table, image, | 1103 | status = handle_cmdline_files(sys_table, image, |
1104 | (char *)(unsigned long)hdr->cmd_line_ptr, | 1104 | (char *)(unsigned long)hdr->cmd_line_ptr, |
1105 | "initrd=", hdr->initrd_addr_max, | 1105 | "initrd=", initrd_addr_max, |
1106 | &ramdisk_addr, &ramdisk_size); | 1106 | &ramdisk_addr, &ramdisk_size); |
1107 | if (status != EFI_SUCCESS) | 1107 | if (status != EFI_SUCCESS) |
1108 | goto fail2; | 1108 | goto fail2; |
1109 | hdr->ramdisk_image = ramdisk_addr; | 1109 | hdr->ramdisk_image = ramdisk_addr & 0xffffffff; |
1110 | hdr->ramdisk_size = ramdisk_size; | 1110 | hdr->ramdisk_size = ramdisk_size & 0xffffffff; |
1111 | boot_params->ext_ramdisk_image = (u64)ramdisk_addr >> 32; | ||
1112 | boot_params->ext_ramdisk_size = (u64)ramdisk_size >> 32; | ||
1111 | 1113 | ||
1112 | return boot_params; | 1114 | return boot_params; |
1113 | fail2: | 1115 | fail2: |
@@ -1374,7 +1376,10 @@ struct boot_params *efi_main(struct efi_config *c, | |||
1374 | 1376 | ||
1375 | setup_graphics(boot_params); | 1377 | setup_graphics(boot_params); |
1376 | 1378 | ||
1377 | setup_efi_pci(boot_params); | 1379 | status = setup_efi_pci(boot_params); |
1380 | if (status != EFI_SUCCESS) { | ||
1381 | efi_printk(sys_table, "setup_efi_pci() failed!\n"); | ||
1382 | } | ||
1378 | 1383 | ||
1379 | status = efi_call_early(allocate_pool, EFI_LOADER_DATA, | 1384 | status = efi_call_early(allocate_pool, EFI_LOADER_DATA, |
1380 | sizeof(*gdt), (void **)&gdt); | 1385 | sizeof(*gdt), (void **)&gdt); |
@@ -1401,16 +1406,20 @@ struct boot_params *efi_main(struct efi_config *c, | |||
1401 | hdr->init_size, hdr->init_size, | 1406 | hdr->init_size, hdr->init_size, |
1402 | hdr->pref_address, | 1407 | hdr->pref_address, |
1403 | hdr->kernel_alignment); | 1408 | hdr->kernel_alignment); |
1404 | if (status != EFI_SUCCESS) | 1409 | if (status != EFI_SUCCESS) { |
1410 | efi_printk(sys_table, "efi_relocate_kernel() failed!\n"); | ||
1405 | goto fail; | 1411 | goto fail; |
1412 | } | ||
1406 | 1413 | ||
1407 | hdr->pref_address = hdr->code32_start; | 1414 | hdr->pref_address = hdr->code32_start; |
1408 | hdr->code32_start = bzimage_addr; | 1415 | hdr->code32_start = bzimage_addr; |
1409 | } | 1416 | } |
1410 | 1417 | ||
1411 | status = exit_boot(boot_params, handle, is64); | 1418 | status = exit_boot(boot_params, handle, is64); |
1412 | if (status != EFI_SUCCESS) | 1419 | if (status != EFI_SUCCESS) { |
1420 | efi_printk(sys_table, "exit_boot() failed!\n"); | ||
1413 | goto fail; | 1421 | goto fail; |
1422 | } | ||
1414 | 1423 | ||
1415 | memset((char *)gdt->address, 0x0, gdt->size); | 1424 | memset((char *)gdt->address, 0x0, gdt->size); |
1416 | desc = (struct desc_struct *)gdt->address; | 1425 | desc = (struct desc_struct *)gdt->address; |
@@ -1470,5 +1479,6 @@ struct boot_params *efi_main(struct efi_config *c, | |||
1470 | 1479 | ||
1471 | return boot_params; | 1480 | return boot_params; |
1472 | fail: | 1481 | fail: |
1482 | efi_printk(sys_table, "efi_main() failed!\n"); | ||
1473 | return NULL; | 1483 | return NULL; |
1474 | } | 1484 | } |
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 { | |||
103 | void *blt; | 103 | void *blt; |
104 | }; | 104 | }; |
105 | 105 | ||
106 | struct efi_config { | ||
107 | u64 image_handle; | ||
108 | u64 table; | ||
109 | u64 allocate_pool; | ||
110 | u64 allocate_pages; | ||
111 | u64 get_memory_map; | ||
112 | u64 free_pool; | ||
113 | u64 free_pages; | ||
114 | u64 locate_handle; | ||
115 | u64 handle_protocol; | ||
116 | u64 exit_boot_services; | ||
117 | u64 text_output; | ||
118 | efi_status_t (*call)(unsigned long, ...); | ||
119 | bool is64; | ||
120 | } __packed; | ||
121 | |||
122 | #endif /* BOOT_COMPRESSED_EBOOT_H */ | 106 | #endif /* BOOT_COMPRESSED_EBOOT_H */ |
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 7a6d43a554d7..16ef02596db2 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S | |||
@@ -154,7 +154,7 @@ extra_header_fields: | |||
154 | #else | 154 | #else |
155 | .quad 0 # ImageBase | 155 | .quad 0 # ImageBase |
156 | #endif | 156 | #endif |
157 | .long 0x20 # SectionAlignment | 157 | .long CONFIG_PHYSICAL_ALIGN # SectionAlignment |
158 | .long 0x20 # FileAlignment | 158 | .long 0x20 # FileAlignment |
159 | .word 0 # MajorOperatingSystemVersion | 159 | .word 0 # MajorOperatingSystemVersion |
160 | .word 0 # MinorOperatingSystemVersion | 160 | .word 0 # MinorOperatingSystemVersion |
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 1eb5f6433ad8..044a2fd3c5fe 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); | |||
104 | extern void __init efi_runtime_mkexec(void); | 104 | extern void __init efi_runtime_mkexec(void); |
105 | extern void __init efi_dump_pagetable(void); | 105 | extern void __init efi_dump_pagetable(void); |
106 | extern void __init efi_apply_memmap_quirks(void); | 106 | extern void __init efi_apply_memmap_quirks(void); |
107 | extern int __init efi_reuse_config(u64 tables, int nr_tables); | ||
108 | extern void efi_delete_dummy_variable(void); | ||
107 | 109 | ||
108 | struct efi_setup_data { | 110 | struct efi_setup_data { |
109 | u64 fw_vendor; | 111 | u64 fw_vendor; |
@@ -156,6 +158,33 @@ static inline efi_status_t efi_thunk_set_virtual_address_map( | |||
156 | return EFI_SUCCESS; | 158 | return EFI_SUCCESS; |
157 | } | 159 | } |
158 | #endif /* CONFIG_EFI_MIXED */ | 160 | #endif /* CONFIG_EFI_MIXED */ |
161 | |||
162 | |||
163 | /* arch specific definitions used by the stub code */ | ||
164 | |||
165 | struct efi_config { | ||
166 | u64 image_handle; | ||
167 | u64 table; | ||
168 | u64 allocate_pool; | ||
169 | u64 allocate_pages; | ||
170 | u64 get_memory_map; | ||
171 | u64 free_pool; | ||
172 | u64 free_pages; | ||
173 | u64 locate_handle; | ||
174 | u64 handle_protocol; | ||
175 | u64 exit_boot_services; | ||
176 | u64 text_output; | ||
177 | efi_status_t (*call)(unsigned long, ...); | ||
178 | bool is64; | ||
179 | } __packed; | ||
180 | |||
181 | extern struct efi_config *efi_early; | ||
182 | |||
183 | #define efi_call_early(f, ...) \ | ||
184 | efi_early->call(efi_early->f, __VA_ARGS__); | ||
185 | |||
186 | extern bool efi_reboot_required(void); | ||
187 | |||
159 | #else | 188 | #else |
160 | /* | 189 | /* |
161 | * IF EFI is not configured, have the EFI calls return -ENOSYS. | 190 | * IF EFI is not configured, have the EFI calls return -ENOSYS. |
@@ -168,6 +197,10 @@ static inline efi_status_t efi_thunk_set_virtual_address_map( | |||
168 | #define efi_call5(_f, _a1, _a2, _a3, _a4, _a5) (-ENOSYS) | 197 | #define efi_call5(_f, _a1, _a2, _a3, _a4, _a5) (-ENOSYS) |
169 | #define efi_call6(_f, _a1, _a2, _a3, _a4, _a5, _a6) (-ENOSYS) | 198 | #define efi_call6(_f, _a1, _a2, _a3, _a4, _a5, _a6) (-ENOSYS) |
170 | static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {} | 199 | static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {} |
200 | static inline bool efi_reboot_required(void) | ||
201 | { | ||
202 | return false; | ||
203 | } | ||
171 | #endif /* CONFIG_EFI */ | 204 | #endif /* CONFIG_EFI */ |
172 | 205 | ||
173 | #endif /* _ASM_X86_EFI_H */ | 206 | #endif /* _ASM_X86_EFI_H */ |
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 52b1157c53eb..17962e667a91 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/mc146818rtc.h> | 28 | #include <linux/mc146818rtc.h> |
29 | #include <asm/realmode.h> | 29 | #include <asm/realmode.h> |
30 | #include <asm/x86_init.h> | 30 | #include <asm/x86_init.h> |
31 | #include <asm/efi.h> | ||
31 | 32 | ||
32 | /* | 33 | /* |
33 | * Power off function, if any | 34 | * Power off function, if any |
@@ -401,12 +402,25 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { | |||
401 | 402 | ||
402 | static int __init reboot_init(void) | 403 | static int __init reboot_init(void) |
403 | { | 404 | { |
405 | int rv; | ||
406 | |||
404 | /* | 407 | /* |
405 | * Only do the DMI check if reboot_type hasn't been overridden | 408 | * Only do the DMI check if reboot_type hasn't been overridden |
406 | * on the command line | 409 | * on the command line |
407 | */ | 410 | */ |
408 | if (reboot_default) | 411 | if (!reboot_default) |
409 | dmi_check_system(reboot_dmi_table); | 412 | return 0; |
413 | |||
414 | /* | ||
415 | * The DMI quirks table takes precedence. If no quirks entry | ||
416 | * matches and the ACPI Hardware Reduced bit is set, force EFI | ||
417 | * reboot. | ||
418 | */ | ||
419 | rv = dmi_check_system(reboot_dmi_table); | ||
420 | |||
421 | if (!rv && efi_reboot_required()) | ||
422 | reboot_type = BOOT_EFI; | ||
423 | |||
410 | return 0; | 424 | return 0; |
411 | } | 425 | } |
412 | core_initcall(reboot_init); | 426 | core_initcall(reboot_init); |
@@ -528,11 +542,7 @@ static void native_machine_emergency_restart(void) | |||
528 | break; | 542 | break; |
529 | 543 | ||
530 | case BOOT_EFI: | 544 | case BOOT_EFI: |
531 | if (efi_enabled(EFI_RUNTIME_SERVICES)) | 545 | efi_reboot(reboot_mode, NULL); |
532 | efi.reset_system(reboot_mode == REBOOT_WARM ? | ||
533 | EFI_RESET_WARM : | ||
534 | EFI_RESET_COLD, | ||
535 | EFI_SUCCESS, 0, NULL); | ||
536 | reboot_type = BOOT_BIOS; | 546 | reboot_type = BOOT_BIOS; |
537 | break; | 547 | break; |
538 | 548 | ||
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 78a0e6298922..41ead8d3bc0b 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -924,10 +924,10 @@ void __init setup_arch(char **cmdline_p) | |||
924 | #endif | 924 | #endif |
925 | #ifdef CONFIG_EFI | 925 | #ifdef CONFIG_EFI |
926 | if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, | 926 | if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, |
927 | "EL32", 4)) { | 927 | EFI32_LOADER_SIGNATURE, 4)) { |
928 | set_bit(EFI_BOOT, &efi.flags); | 928 | set_bit(EFI_BOOT, &efi.flags); |
929 | } else if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, | 929 | } else if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, |
930 | "EL64", 4)) { | 930 | EFI64_LOADER_SIGNATURE, 4)) { |
931 | set_bit(EFI_BOOT, &efi.flags); | 931 | set_bit(EFI_BOOT, &efi.flags); |
932 | set_bit(EFI_64BIT, &efi.flags); | 932 | set_bit(EFI_64BIT, &efi.flags); |
933 | } | 933 | } |
diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile index d51045afcaaf..2846aaab5103 100644 --- a/arch/x86/platform/efi/Makefile +++ b/arch/x86/platform/efi/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o | 1 | obj-$(CONFIG_EFI) += quirks.o efi.o efi_$(BITS).o efi_stub_$(BITS).o |
2 | obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o | 2 | obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o |
3 | obj-$(CONFIG_EARLY_PRINTK_EFI) += early_printk.o | 3 | obj-$(CONFIG_EARLY_PRINTK_EFI) += early_printk.o |
4 | obj-$(CONFIG_EFI_MIXED) += efi_thunk_$(BITS).o | 4 | obj-$(CONFIG_EFI_MIXED) += efi_thunk_$(BITS).o |
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 87fc96bcc13c..850da94fef30 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c | |||
@@ -56,13 +56,6 @@ | |||
56 | 56 | ||
57 | #define EFI_DEBUG | 57 | #define EFI_DEBUG |
58 | 58 | ||
59 | #define EFI_MIN_RESERVE 5120 | ||
60 | |||
61 | #define EFI_DUMMY_GUID \ | ||
62 | EFI_GUID(0x4424ac57, 0xbe4b, 0x47dd, 0x9e, 0x97, 0xed, 0x50, 0xf0, 0x9f, 0x92, 0xa9) | ||
63 | |||
64 | static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 }; | ||
65 | |||
66 | struct efi_memory_map memmap; | 59 | struct efi_memory_map memmap; |
67 | 60 | ||
68 | static struct efi efi_phys __initdata; | 61 | static struct efi efi_phys __initdata; |
@@ -95,139 +88,6 @@ static int __init setup_add_efi_memmap(char *arg) | |||
95 | } | 88 | } |
96 | early_param("add_efi_memmap", setup_add_efi_memmap); | 89 | early_param("add_efi_memmap", setup_add_efi_memmap); |
97 | 90 | ||
98 | static bool efi_no_storage_paranoia; | ||
99 | |||
100 | static int __init setup_storage_paranoia(char *arg) | ||
101 | { | ||
102 | efi_no_storage_paranoia = true; | ||
103 | return 0; | ||
104 | } | ||
105 | early_param("efi_no_storage_paranoia", setup_storage_paranoia); | ||
106 | |||
107 | static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) | ||
108 | { | ||
109 | unsigned long flags; | ||
110 | efi_status_t status; | ||
111 | |||
112 | spin_lock_irqsave(&rtc_lock, flags); | ||
113 | status = efi_call_virt(get_time, tm, tc); | ||
114 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
115 | return status; | ||
116 | } | ||
117 | |||
118 | static efi_status_t virt_efi_set_time(efi_time_t *tm) | ||
119 | { | ||
120 | unsigned long flags; | ||
121 | efi_status_t status; | ||
122 | |||
123 | spin_lock_irqsave(&rtc_lock, flags); | ||
124 | status = efi_call_virt(set_time, tm); | ||
125 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
126 | return status; | ||
127 | } | ||
128 | |||
129 | static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled, | ||
130 | efi_bool_t *pending, | ||
131 | efi_time_t *tm) | ||
132 | { | ||
133 | unsigned long flags; | ||
134 | efi_status_t status; | ||
135 | |||
136 | spin_lock_irqsave(&rtc_lock, flags); | ||
137 | status = efi_call_virt(get_wakeup_time, enabled, pending, tm); | ||
138 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
139 | return status; | ||
140 | } | ||
141 | |||
142 | static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) | ||
143 | { | ||
144 | unsigned long flags; | ||
145 | efi_status_t status; | ||
146 | |||
147 | spin_lock_irqsave(&rtc_lock, flags); | ||
148 | status = efi_call_virt(set_wakeup_time, enabled, tm); | ||
149 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
150 | return status; | ||
151 | } | ||
152 | |||
153 | static efi_status_t virt_efi_get_variable(efi_char16_t *name, | ||
154 | efi_guid_t *vendor, | ||
155 | u32 *attr, | ||
156 | unsigned long *data_size, | ||
157 | void *data) | ||
158 | { | ||
159 | return efi_call_virt(get_variable, | ||
160 | name, vendor, attr, | ||
161 | data_size, data); | ||
162 | } | ||
163 | |||
164 | static efi_status_t virt_efi_get_next_variable(unsigned long *name_size, | ||
165 | efi_char16_t *name, | ||
166 | efi_guid_t *vendor) | ||
167 | { | ||
168 | return efi_call_virt(get_next_variable, | ||
169 | name_size, name, vendor); | ||
170 | } | ||
171 | |||
172 | static efi_status_t virt_efi_set_variable(efi_char16_t *name, | ||
173 | efi_guid_t *vendor, | ||
174 | u32 attr, | ||
175 | unsigned long data_size, | ||
176 | void *data) | ||
177 | { | ||
178 | return efi_call_virt(set_variable, | ||
179 | name, vendor, attr, | ||
180 | data_size, data); | ||
181 | } | ||
182 | |||
183 | static efi_status_t virt_efi_query_variable_info(u32 attr, | ||
184 | u64 *storage_space, | ||
185 | u64 *remaining_space, | ||
186 | u64 *max_variable_size) | ||
187 | { | ||
188 | if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) | ||
189 | return EFI_UNSUPPORTED; | ||
190 | |||
191 | return efi_call_virt(query_variable_info, attr, storage_space, | ||
192 | remaining_space, max_variable_size); | ||
193 | } | ||
194 | |||
195 | static efi_status_t virt_efi_get_next_high_mono_count(u32 *count) | ||
196 | { | ||
197 | return efi_call_virt(get_next_high_mono_count, count); | ||
198 | } | ||
199 | |||
200 | static void virt_efi_reset_system(int reset_type, | ||
201 | efi_status_t status, | ||
202 | unsigned long data_size, | ||
203 | efi_char16_t *data) | ||
204 | { | ||
205 | __efi_call_virt(reset_system, reset_type, status, | ||
206 | data_size, data); | ||
207 | } | ||
208 | |||
209 | static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules, | ||
210 | unsigned long count, | ||
211 | unsigned long sg_list) | ||
212 | { | ||
213 | if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) | ||
214 | return EFI_UNSUPPORTED; | ||
215 | |||
216 | return efi_call_virt(update_capsule, capsules, count, sg_list); | ||
217 | } | ||
218 | |||
219 | static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules, | ||
220 | unsigned long count, | ||
221 | u64 *max_size, | ||
222 | int *reset_type) | ||
223 | { | ||
224 | if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) | ||
225 | return EFI_UNSUPPORTED; | ||
226 | |||
227 | return efi_call_virt(query_capsule_caps, capsules, count, max_size, | ||
228 | reset_type); | ||
229 | } | ||
230 | |||
231 | static efi_status_t __init phys_efi_set_virtual_address_map( | 91 | static efi_status_t __init phys_efi_set_virtual_address_map( |
232 | unsigned long memory_map_size, | 92 | unsigned long memory_map_size, |
233 | unsigned long descriptor_size, | 93 | unsigned long descriptor_size, |
@@ -244,42 +104,6 @@ static efi_status_t __init phys_efi_set_virtual_address_map( | |||
244 | return status; | 104 | return status; |
245 | } | 105 | } |
246 | 106 | ||
247 | int efi_set_rtc_mmss(const struct timespec *now) | ||
248 | { | ||
249 | unsigned long nowtime = now->tv_sec; | ||
250 | efi_status_t status; | ||
251 | efi_time_t eft; | ||
252 | efi_time_cap_t cap; | ||
253 | struct rtc_time tm; | ||
254 | |||
255 | status = efi.get_time(&eft, &cap); | ||
256 | if (status != EFI_SUCCESS) { | ||
257 | pr_err("Oops: efitime: can't read time!\n"); | ||
258 | return -1; | ||
259 | } | ||
260 | |||
261 | rtc_time_to_tm(nowtime, &tm); | ||
262 | if (!rtc_valid_tm(&tm)) { | ||
263 | eft.year = tm.tm_year + 1900; | ||
264 | eft.month = tm.tm_mon + 1; | ||
265 | eft.day = tm.tm_mday; | ||
266 | eft.minute = tm.tm_min; | ||
267 | eft.second = tm.tm_sec; | ||
268 | eft.nanosecond = 0; | ||
269 | } else { | ||
270 | pr_err("%s: Invalid EFI RTC value: write of %lx to EFI RTC failed\n", | ||
271 | __func__, nowtime); | ||
272 | return -1; | ||
273 | } | ||
274 | |||
275 | status = efi.set_time(&eft); | ||
276 | if (status != EFI_SUCCESS) { | ||
277 | pr_err("Oops: efitime: can't write time!\n"); | ||
278 | return -1; | ||
279 | } | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | void efi_get_time(struct timespec *now) | 107 | void efi_get_time(struct timespec *now) |
284 | { | 108 | { |
285 | efi_status_t status; | 109 | efi_status_t status; |
@@ -350,6 +174,9 @@ int __init efi_memblock_x86_reserve_range(void) | |||
350 | struct efi_info *e = &boot_params.efi_info; | 174 | struct efi_info *e = &boot_params.efi_info; |
351 | unsigned long pmap; | 175 | unsigned long pmap; |
352 | 176 | ||
177 | if (efi_enabled(EFI_PARAVIRT)) | ||
178 | return 0; | ||
179 | |||
353 | #ifdef CONFIG_X86_32 | 180 | #ifdef CONFIG_X86_32 |
354 | /* Can't handle data above 4GB at this time */ | 181 | /* Can't handle data above 4GB at this time */ |
355 | if (e->efi_memmap_hi) { | 182 | if (e->efi_memmap_hi) { |
@@ -392,69 +219,15 @@ static void __init print_efi_memmap(void) | |||
392 | #endif /* EFI_DEBUG */ | 219 | #endif /* EFI_DEBUG */ |
393 | } | 220 | } |
394 | 221 | ||
395 | void __init efi_reserve_boot_services(void) | ||
396 | { | ||
397 | void *p; | ||
398 | |||
399 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | ||
400 | efi_memory_desc_t *md = p; | ||
401 | u64 start = md->phys_addr; | ||
402 | u64 size = md->num_pages << EFI_PAGE_SHIFT; | ||
403 | |||
404 | if (md->type != EFI_BOOT_SERVICES_CODE && | ||
405 | md->type != EFI_BOOT_SERVICES_DATA) | ||
406 | continue; | ||
407 | /* Only reserve where possible: | ||
408 | * - Not within any already allocated areas | ||
409 | * - Not over any memory area (really needed, if above?) | ||
410 | * - Not within any part of the kernel | ||
411 | * - Not the bios reserved area | ||
412 | */ | ||
413 | if ((start + size > __pa_symbol(_text) | ||
414 | && start <= __pa_symbol(_end)) || | ||
415 | !e820_all_mapped(start, start+size, E820_RAM) || | ||
416 | memblock_is_region_reserved(start, size)) { | ||
417 | /* Could not reserve, skip it */ | ||
418 | md->num_pages = 0; | ||
419 | memblock_dbg("Could not reserve boot range [0x%010llx-0x%010llx]\n", | ||
420 | start, start+size-1); | ||
421 | } else | ||
422 | memblock_reserve(start, size); | ||
423 | } | ||
424 | } | ||
425 | |||
426 | void __init efi_unmap_memmap(void) | 222 | void __init efi_unmap_memmap(void) |
427 | { | 223 | { |
428 | clear_bit(EFI_MEMMAP, &efi.flags); | 224 | clear_bit(EFI_MEMMAP, &efi.flags); |
429 | if (memmap.map) { | 225 | if (memmap.map) { |
430 | early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); | 226 | early_memunmap(memmap.map, memmap.nr_map * memmap.desc_size); |
431 | memmap.map = NULL; | 227 | memmap.map = NULL; |
432 | } | 228 | } |
433 | } | 229 | } |
434 | 230 | ||
435 | void __init efi_free_boot_services(void) | ||
436 | { | ||
437 | void *p; | ||
438 | |||
439 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | ||
440 | efi_memory_desc_t *md = p; | ||
441 | unsigned long long start = md->phys_addr; | ||
442 | unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; | ||
443 | |||
444 | if (md->type != EFI_BOOT_SERVICES_CODE && | ||
445 | md->type != EFI_BOOT_SERVICES_DATA) | ||
446 | continue; | ||
447 | |||
448 | /* Could not reserve boot area */ | ||
449 | if (!size) | ||
450 | continue; | ||
451 | |||
452 | free_bootmem_late(start, size); | ||
453 | } | ||
454 | |||
455 | efi_unmap_memmap(); | ||
456 | } | ||
457 | |||
458 | static int __init efi_systab_init(void *phys) | 231 | static int __init efi_systab_init(void *phys) |
459 | { | 232 | { |
460 | if (efi_enabled(EFI_64BIT)) { | 233 | if (efi_enabled(EFI_64BIT)) { |
@@ -467,12 +240,12 @@ static int __init efi_systab_init(void *phys) | |||
467 | if (!data) | 240 | if (!data) |
468 | return -ENOMEM; | 241 | return -ENOMEM; |
469 | } | 242 | } |
470 | systab64 = early_ioremap((unsigned long)phys, | 243 | systab64 = early_memremap((unsigned long)phys, |
471 | sizeof(*systab64)); | 244 | sizeof(*systab64)); |
472 | if (systab64 == NULL) { | 245 | if (systab64 == NULL) { |
473 | pr_err("Couldn't map the system table!\n"); | 246 | pr_err("Couldn't map the system table!\n"); |
474 | if (data) | 247 | if (data) |
475 | early_iounmap(data, sizeof(*data)); | 248 | early_memunmap(data, sizeof(*data)); |
476 | return -ENOMEM; | 249 | return -ENOMEM; |
477 | } | 250 | } |
478 | 251 | ||
@@ -504,9 +277,9 @@ static int __init efi_systab_init(void *phys) | |||
504 | systab64->tables; | 277 | systab64->tables; |
505 | tmp |= data ? data->tables : systab64->tables; | 278 | tmp |= data ? data->tables : systab64->tables; |
506 | 279 | ||
507 | early_iounmap(systab64, sizeof(*systab64)); | 280 | early_memunmap(systab64, sizeof(*systab64)); |
508 | if (data) | 281 | if (data) |
509 | early_iounmap(data, sizeof(*data)); | 282 | early_memunmap(data, sizeof(*data)); |
510 | #ifdef CONFIG_X86_32 | 283 | #ifdef CONFIG_X86_32 |
511 | if (tmp >> 32) { | 284 | if (tmp >> 32) { |
512 | pr_err("EFI data located above 4GB, disabling EFI.\n"); | 285 | pr_err("EFI data located above 4GB, disabling EFI.\n"); |
@@ -516,7 +289,7 @@ static int __init efi_systab_init(void *phys) | |||
516 | } else { | 289 | } else { |
517 | efi_system_table_32_t *systab32; | 290 | efi_system_table_32_t *systab32; |
518 | 291 | ||
519 | systab32 = early_ioremap((unsigned long)phys, | 292 | systab32 = early_memremap((unsigned long)phys, |
520 | sizeof(*systab32)); | 293 | sizeof(*systab32)); |
521 | if (systab32 == NULL) { | 294 | if (systab32 == NULL) { |
522 | pr_err("Couldn't map the system table!\n"); | 295 | pr_err("Couldn't map the system table!\n"); |
@@ -537,7 +310,7 @@ static int __init efi_systab_init(void *phys) | |||
537 | efi_systab.nr_tables = systab32->nr_tables; | 310 | efi_systab.nr_tables = systab32->nr_tables; |
538 | efi_systab.tables = systab32->tables; | 311 | efi_systab.tables = systab32->tables; |
539 | 312 | ||
540 | early_iounmap(systab32, sizeof(*systab32)); | 313 | early_memunmap(systab32, sizeof(*systab32)); |
541 | } | 314 | } |
542 | 315 | ||
543 | efi.systab = &efi_systab; | 316 | efi.systab = &efi_systab; |
@@ -563,7 +336,7 @@ static int __init efi_runtime_init32(void) | |||
563 | { | 336 | { |
564 | efi_runtime_services_32_t *runtime; | 337 | efi_runtime_services_32_t *runtime; |
565 | 338 | ||
566 | runtime = early_ioremap((unsigned long)efi.systab->runtime, | 339 | runtime = early_memremap((unsigned long)efi.systab->runtime, |
567 | sizeof(efi_runtime_services_32_t)); | 340 | sizeof(efi_runtime_services_32_t)); |
568 | if (!runtime) { | 341 | if (!runtime) { |
569 | pr_err("Could not map the runtime service table!\n"); | 342 | pr_err("Could not map the runtime service table!\n"); |
@@ -578,7 +351,7 @@ static int __init efi_runtime_init32(void) | |||
578 | efi_phys.set_virtual_address_map = | 351 | efi_phys.set_virtual_address_map = |
579 | (efi_set_virtual_address_map_t *) | 352 | (efi_set_virtual_address_map_t *) |
580 | (unsigned long)runtime->set_virtual_address_map; | 353 | (unsigned long)runtime->set_virtual_address_map; |
581 | early_iounmap(runtime, sizeof(efi_runtime_services_32_t)); | 354 | early_memunmap(runtime, sizeof(efi_runtime_services_32_t)); |
582 | 355 | ||
583 | return 0; | 356 | return 0; |
584 | } | 357 | } |
@@ -587,7 +360,7 @@ static int __init efi_runtime_init64(void) | |||
587 | { | 360 | { |
588 | efi_runtime_services_64_t *runtime; | 361 | efi_runtime_services_64_t *runtime; |
589 | 362 | ||
590 | runtime = early_ioremap((unsigned long)efi.systab->runtime, | 363 | runtime = early_memremap((unsigned long)efi.systab->runtime, |
591 | sizeof(efi_runtime_services_64_t)); | 364 | sizeof(efi_runtime_services_64_t)); |
592 | if (!runtime) { | 365 | if (!runtime) { |
593 | pr_err("Could not map the runtime service table!\n"); | 366 | pr_err("Could not map the runtime service table!\n"); |
@@ -602,7 +375,7 @@ static int __init efi_runtime_init64(void) | |||
602 | efi_phys.set_virtual_address_map = | 375 | efi_phys.set_virtual_address_map = |
603 | (efi_set_virtual_address_map_t *) | 376 | (efi_set_virtual_address_map_t *) |
604 | (unsigned long)runtime->set_virtual_address_map; | 377 | (unsigned long)runtime->set_virtual_address_map; |
605 | early_iounmap(runtime, sizeof(efi_runtime_services_64_t)); | 378 | early_memunmap(runtime, sizeof(efi_runtime_services_64_t)); |
606 | 379 | ||
607 | return 0; | 380 | return 0; |
608 | } | 381 | } |
@@ -616,14 +389,24 @@ static int __init efi_runtime_init(void) | |||
616 | * the runtime services table so that we can grab the physical | 389 | * the runtime services table so that we can grab the physical |
617 | * address of several of the EFI runtime functions, needed to | 390 | * address of several of the EFI runtime functions, needed to |
618 | * set the firmware into virtual mode. | 391 | * set the firmware into virtual mode. |
392 | * | ||
393 | * When EFI_PARAVIRT is in force then we could not map runtime | ||
394 | * service memory region because we do not have direct access to it. | ||
395 | * However, runtime services are available through proxy functions | ||
396 | * (e.g. in case of Xen dom0 EFI implementation they call special | ||
397 | * hypercall which executes relevant EFI functions) and that is why | ||
398 | * they are always enabled. | ||
619 | */ | 399 | */ |
620 | if (efi_enabled(EFI_64BIT)) | ||
621 | rv = efi_runtime_init64(); | ||
622 | else | ||
623 | rv = efi_runtime_init32(); | ||
624 | 400 | ||
625 | if (rv) | 401 | if (!efi_enabled(EFI_PARAVIRT)) { |
626 | return rv; | 402 | if (efi_enabled(EFI_64BIT)) |
403 | rv = efi_runtime_init64(); | ||
404 | else | ||
405 | rv = efi_runtime_init32(); | ||
406 | |||
407 | if (rv) | ||
408 | return rv; | ||
409 | } | ||
627 | 410 | ||
628 | set_bit(EFI_RUNTIME_SERVICES, &efi.flags); | 411 | set_bit(EFI_RUNTIME_SERVICES, &efi.flags); |
629 | 412 | ||
@@ -632,8 +415,11 @@ static int __init efi_runtime_init(void) | |||
632 | 415 | ||
633 | static int __init efi_memmap_init(void) | 416 | static int __init efi_memmap_init(void) |
634 | { | 417 | { |
418 | if (efi_enabled(EFI_PARAVIRT)) | ||
419 | return 0; | ||
420 | |||
635 | /* Map the EFI memory map */ | 421 | /* Map the EFI memory map */ |
636 | memmap.map = early_ioremap((unsigned long)memmap.phys_map, | 422 | memmap.map = early_memremap((unsigned long)memmap.phys_map, |
637 | memmap.nr_map * memmap.desc_size); | 423 | memmap.nr_map * memmap.desc_size); |
638 | if (memmap.map == NULL) { | 424 | if (memmap.map == NULL) { |
639 | pr_err("Could not map the memory map!\n"); | 425 | pr_err("Could not map the memory map!\n"); |
@@ -649,62 +435,6 @@ static int __init efi_memmap_init(void) | |||
649 | return 0; | 435 | return 0; |
650 | } | 436 | } |
651 | 437 | ||
652 | /* | ||
653 | * A number of config table entries get remapped to virtual addresses | ||
654 | * after entering EFI virtual mode. However, the kexec kernel requires | ||
655 | * their physical addresses therefore we pass them via setup_data and | ||
656 | * correct those entries to their respective physical addresses here. | ||
657 | * | ||
658 | * Currently only handles smbios which is necessary for some firmware | ||
659 | * implementation. | ||
660 | */ | ||
661 | static int __init efi_reuse_config(u64 tables, int nr_tables) | ||
662 | { | ||
663 | int i, sz, ret = 0; | ||
664 | void *p, *tablep; | ||
665 | struct efi_setup_data *data; | ||
666 | |||
667 | if (!efi_setup) | ||
668 | return 0; | ||
669 | |||
670 | if (!efi_enabled(EFI_64BIT)) | ||
671 | return 0; | ||
672 | |||
673 | data = early_memremap(efi_setup, sizeof(*data)); | ||
674 | if (!data) { | ||
675 | ret = -ENOMEM; | ||
676 | goto out; | ||
677 | } | ||
678 | |||
679 | if (!data->smbios) | ||
680 | goto out_memremap; | ||
681 | |||
682 | sz = sizeof(efi_config_table_64_t); | ||
683 | |||
684 | p = tablep = early_memremap(tables, nr_tables * sz); | ||
685 | if (!p) { | ||
686 | pr_err("Could not map Configuration table!\n"); | ||
687 | ret = -ENOMEM; | ||
688 | goto out_memremap; | ||
689 | } | ||
690 | |||
691 | for (i = 0; i < efi.systab->nr_tables; i++) { | ||
692 | efi_guid_t guid; | ||
693 | |||
694 | guid = ((efi_config_table_64_t *)p)->guid; | ||
695 | |||
696 | if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID)) | ||
697 | ((efi_config_table_64_t *)p)->table = data->smbios; | ||
698 | p += sz; | ||
699 | } | ||
700 | early_iounmap(tablep, nr_tables * sz); | ||
701 | |||
702 | out_memremap: | ||
703 | early_iounmap(data, sizeof(*data)); | ||
704 | out: | ||
705 | return ret; | ||
706 | } | ||
707 | |||
708 | void __init efi_init(void) | 438 | void __init efi_init(void) |
709 | { | 439 | { |
710 | efi_char16_t *c16; | 440 | efi_char16_t *c16; |
@@ -728,8 +458,6 @@ void __init efi_init(void) | |||
728 | if (efi_systab_init(efi_phys.systab)) | 458 | if (efi_systab_init(efi_phys.systab)) |
729 | return; | 459 | return; |
730 | 460 | ||
731 | set_bit(EFI_SYSTEM_TABLES, &efi.flags); | ||
732 | |||
733 | efi.config_table = (unsigned long)efi.systab->tables; | 461 | efi.config_table = (unsigned long)efi.systab->tables; |
734 | efi.fw_vendor = (unsigned long)efi.systab->fw_vendor; | 462 | efi.fw_vendor = (unsigned long)efi.systab->fw_vendor; |
735 | efi.runtime = (unsigned long)efi.systab->runtime; | 463 | efi.runtime = (unsigned long)efi.systab->runtime; |
@@ -737,14 +465,14 @@ void __init efi_init(void) | |||
737 | /* | 465 | /* |
738 | * Show what we know for posterity | 466 | * Show what we know for posterity |
739 | */ | 467 | */ |
740 | c16 = tmp = early_ioremap(efi.systab->fw_vendor, 2); | 468 | c16 = tmp = early_memremap(efi.systab->fw_vendor, 2); |
741 | if (c16) { | 469 | if (c16) { |
742 | for (i = 0; i < sizeof(vendor) - 1 && *c16; ++i) | 470 | for (i = 0; i < sizeof(vendor) - 1 && *c16; ++i) |
743 | vendor[i] = *c16++; | 471 | vendor[i] = *c16++; |
744 | vendor[i] = '\0'; | 472 | vendor[i] = '\0'; |
745 | } else | 473 | } else |
746 | pr_err("Could not map the firmware vendor!\n"); | 474 | pr_err("Could not map the firmware vendor!\n"); |
747 | early_iounmap(tmp, 2); | 475 | early_memunmap(tmp, 2); |
748 | 476 | ||
749 | pr_info("EFI v%u.%.02u by %s\n", | 477 | pr_info("EFI v%u.%.02u by %s\n", |
750 | efi.systab->hdr.revision >> 16, | 478 | efi.systab->hdr.revision >> 16, |
@@ -770,8 +498,6 @@ void __init efi_init(void) | |||
770 | if (efi_memmap_init()) | 498 | if (efi_memmap_init()) |
771 | return; | 499 | return; |
772 | 500 | ||
773 | set_bit(EFI_MEMMAP, &efi.flags); | ||
774 | |||
775 | print_efi_memmap(); | 501 | print_efi_memmap(); |
776 | } | 502 | } |
777 | 503 | ||
@@ -847,22 +573,6 @@ void __init old_map_region(efi_memory_desc_t *md) | |||
847 | (unsigned long long)md->phys_addr); | 573 | (unsigned long long)md->phys_addr); |
848 | } | 574 | } |
849 | 575 | ||
850 | static void native_runtime_setup(void) | ||
851 | { | ||
852 | efi.get_time = virt_efi_get_time; | ||
853 | efi.set_time = virt_efi_set_time; | ||
854 | efi.get_wakeup_time = virt_efi_get_wakeup_time; | ||
855 | efi.set_wakeup_time = virt_efi_set_wakeup_time; | ||
856 | efi.get_variable = virt_efi_get_variable; | ||
857 | efi.get_next_variable = virt_efi_get_next_variable; | ||
858 | efi.set_variable = virt_efi_set_variable; | ||
859 | efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count; | ||
860 | efi.reset_system = virt_efi_reset_system; | ||
861 | efi.query_variable_info = virt_efi_query_variable_info; | ||
862 | efi.update_capsule = virt_efi_update_capsule; | ||
863 | efi.query_capsule_caps = virt_efi_query_capsule_caps; | ||
864 | } | ||
865 | |||
866 | /* Merge contiguous regions of the same type and attribute */ | 576 | /* Merge contiguous regions of the same type and attribute */ |
867 | static void __init efi_merge_regions(void) | 577 | static void __init efi_merge_regions(void) |
868 | { | 578 | { |
@@ -1049,7 +759,7 @@ static void __init kexec_enter_virtual_mode(void) | |||
1049 | */ | 759 | */ |
1050 | efi.runtime_version = efi_systab.hdr.revision; | 760 | efi.runtime_version = efi_systab.hdr.revision; |
1051 | 761 | ||
1052 | native_runtime_setup(); | 762 | efi_native_runtime_setup(); |
1053 | 763 | ||
1054 | efi.set_virtual_address_map = NULL; | 764 | efi.set_virtual_address_map = NULL; |
1055 | 765 | ||
@@ -1057,11 +767,7 @@ static void __init kexec_enter_virtual_mode(void) | |||
1057 | runtime_code_page_mkexec(); | 767 | runtime_code_page_mkexec(); |
1058 | 768 | ||
1059 | /* clean DUMMY object */ | 769 | /* clean DUMMY object */ |
1060 | efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID, | 770 | efi_delete_dummy_variable(); |
1061 | EFI_VARIABLE_NON_VOLATILE | | ||
1062 | EFI_VARIABLE_BOOTSERVICE_ACCESS | | ||
1063 | EFI_VARIABLE_RUNTIME_ACCESS, | ||
1064 | 0, NULL); | ||
1065 | #endif | 771 | #endif |
1066 | } | 772 | } |
1067 | 773 | ||
@@ -1142,7 +848,7 @@ static void __init __efi_enter_virtual_mode(void) | |||
1142 | efi.runtime_version = efi_systab.hdr.revision; | 848 | efi.runtime_version = efi_systab.hdr.revision; |
1143 | 849 | ||
1144 | if (efi_is_native()) | 850 | if (efi_is_native()) |
1145 | native_runtime_setup(); | 851 | efi_native_runtime_setup(); |
1146 | else | 852 | else |
1147 | efi_thunk_runtime_setup(); | 853 | efi_thunk_runtime_setup(); |
1148 | 854 | ||
@@ -1179,15 +885,14 @@ static void __init __efi_enter_virtual_mode(void) | |||
1179 | free_pages((unsigned long)new_memmap, pg_shift); | 885 | free_pages((unsigned long)new_memmap, pg_shift); |
1180 | 886 | ||
1181 | /* clean DUMMY object */ | 887 | /* clean DUMMY object */ |
1182 | efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID, | 888 | efi_delete_dummy_variable(); |
1183 | EFI_VARIABLE_NON_VOLATILE | | ||
1184 | EFI_VARIABLE_BOOTSERVICE_ACCESS | | ||
1185 | EFI_VARIABLE_RUNTIME_ACCESS, | ||
1186 | 0, NULL); | ||
1187 | } | 889 | } |
1188 | 890 | ||
1189 | void __init efi_enter_virtual_mode(void) | 891 | void __init efi_enter_virtual_mode(void) |
1190 | { | 892 | { |
893 | if (efi_enabled(EFI_PARAVIRT)) | ||
894 | return; | ||
895 | |||
1191 | if (efi_setup) | 896 | if (efi_setup) |
1192 | kexec_enter_virtual_mode(); | 897 | kexec_enter_virtual_mode(); |
1193 | else | 898 | else |
@@ -1220,6 +925,9 @@ u64 efi_mem_attributes(unsigned long phys_addr) | |||
1220 | efi_memory_desc_t *md; | 925 | efi_memory_desc_t *md; |
1221 | void *p; | 926 | void *p; |
1222 | 927 | ||
928 | if (!efi_enabled(EFI_MEMMAP)) | ||
929 | return 0; | ||
930 | |||
1223 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 931 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
1224 | md = p; | 932 | md = p; |
1225 | if ((md->phys_addr <= phys_addr) && | 933 | if ((md->phys_addr <= phys_addr) && |
@@ -1230,86 +938,6 @@ u64 efi_mem_attributes(unsigned long phys_addr) | |||
1230 | return 0; | 938 | return 0; |
1231 | } | 939 | } |
1232 | 940 | ||
1233 | /* | ||
1234 | * Some firmware implementations refuse to boot if there's insufficient space | ||
1235 | * in the variable store. Ensure that we never use more than a safe limit. | ||
1236 | * | ||
1237 | * Return EFI_SUCCESS if it is safe to write 'size' bytes to the variable | ||
1238 | * store. | ||
1239 | */ | ||
1240 | efi_status_t efi_query_variable_store(u32 attributes, unsigned long size) | ||
1241 | { | ||
1242 | efi_status_t status; | ||
1243 | u64 storage_size, remaining_size, max_size; | ||
1244 | |||
1245 | if (!(attributes & EFI_VARIABLE_NON_VOLATILE)) | ||
1246 | return 0; | ||
1247 | |||
1248 | status = efi.query_variable_info(attributes, &storage_size, | ||
1249 | &remaining_size, &max_size); | ||
1250 | if (status != EFI_SUCCESS) | ||
1251 | return status; | ||
1252 | |||
1253 | /* | ||
1254 | * We account for that by refusing the write if permitting it would | ||
1255 | * reduce the available space to under 5KB. This figure was provided by | ||
1256 | * Samsung, so should be safe. | ||
1257 | */ | ||
1258 | if ((remaining_size - size < EFI_MIN_RESERVE) && | ||
1259 | !efi_no_storage_paranoia) { | ||
1260 | |||
1261 | /* | ||
1262 | * Triggering garbage collection may require that the firmware | ||
1263 | * generate a real EFI_OUT_OF_RESOURCES error. We can force | ||
1264 | * that by attempting to use more space than is available. | ||
1265 | */ | ||
1266 | unsigned long dummy_size = remaining_size + 1024; | ||
1267 | void *dummy = kzalloc(dummy_size, GFP_ATOMIC); | ||
1268 | |||
1269 | if (!dummy) | ||
1270 | return EFI_OUT_OF_RESOURCES; | ||
1271 | |||
1272 | status = efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID, | ||
1273 | EFI_VARIABLE_NON_VOLATILE | | ||
1274 | EFI_VARIABLE_BOOTSERVICE_ACCESS | | ||
1275 | EFI_VARIABLE_RUNTIME_ACCESS, | ||
1276 | dummy_size, dummy); | ||
1277 | |||
1278 | if (status == EFI_SUCCESS) { | ||
1279 | /* | ||
1280 | * This should have failed, so if it didn't make sure | ||
1281 | * that we delete it... | ||
1282 | */ | ||
1283 | efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID, | ||
1284 | EFI_VARIABLE_NON_VOLATILE | | ||
1285 | EFI_VARIABLE_BOOTSERVICE_ACCESS | | ||
1286 | EFI_VARIABLE_RUNTIME_ACCESS, | ||
1287 | 0, dummy); | ||
1288 | } | ||
1289 | |||
1290 | kfree(dummy); | ||
1291 | |||
1292 | /* | ||
1293 | * The runtime code may now have triggered a garbage collection | ||
1294 | * run, so check the variable info again | ||
1295 | */ | ||
1296 | status = efi.query_variable_info(attributes, &storage_size, | ||
1297 | &remaining_size, &max_size); | ||
1298 | |||
1299 | if (status != EFI_SUCCESS) | ||
1300 | return status; | ||
1301 | |||
1302 | /* | ||
1303 | * There still isn't enough room, so return an error | ||
1304 | */ | ||
1305 | if (remaining_size - size < EFI_MIN_RESERVE) | ||
1306 | return EFI_OUT_OF_RESOURCES; | ||
1307 | } | ||
1308 | |||
1309 | return EFI_SUCCESS; | ||
1310 | } | ||
1311 | EXPORT_SYMBOL_GPL(efi_query_variable_store); | ||
1312 | |||
1313 | static int __init parse_efi_cmdline(char *str) | 941 | static int __init parse_efi_cmdline(char *str) |
1314 | { | 942 | { |
1315 | if (*str == '=') | 943 | if (*str == '=') |
@@ -1321,22 +949,3 @@ static int __init parse_efi_cmdline(char *str) | |||
1321 | return 0; | 949 | return 0; |
1322 | } | 950 | } |
1323 | early_param("efi", parse_efi_cmdline); | 951 | early_param("efi", parse_efi_cmdline); |
1324 | |||
1325 | void __init efi_apply_memmap_quirks(void) | ||
1326 | { | ||
1327 | /* | ||
1328 | * Once setup is done earlier, unmap the EFI memory map on mismatched | ||
1329 | * firmware/kernel architectures since there is no support for runtime | ||
1330 | * services. | ||
1331 | */ | ||
1332 | if (!efi_runtime_supported()) { | ||
1333 | pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n"); | ||
1334 | efi_unmap_memmap(); | ||
1335 | } | ||
1336 | |||
1337 | /* | ||
1338 | * UV doesn't support the new EFI pagetable mapping yet. | ||
1339 | */ | ||
1340 | if (is_uv_system()) | ||
1341 | set_bit(EFI_OLD_MEMMAP, &efi.flags); | ||
1342 | } | ||
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c new file mode 100644 index 000000000000..1c7380da65ff --- /dev/null +++ b/arch/x86/platform/efi/quirks.c | |||
@@ -0,0 +1,290 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/kernel.h> | ||
3 | #include <linux/string.h> | ||
4 | #include <linux/time.h> | ||
5 | #include <linux/types.h> | ||
6 | #include <linux/efi.h> | ||
7 | #include <linux/slab.h> | ||
8 | #include <linux/memblock.h> | ||
9 | #include <linux/bootmem.h> | ||
10 | #include <linux/acpi.h> | ||
11 | #include <asm/efi.h> | ||
12 | #include <asm/uv/uv.h> | ||
13 | |||
14 | #define EFI_MIN_RESERVE 5120 | ||
15 | |||
16 | #define EFI_DUMMY_GUID \ | ||
17 | EFI_GUID(0x4424ac57, 0xbe4b, 0x47dd, 0x9e, 0x97, 0xed, 0x50, 0xf0, 0x9f, 0x92, 0xa9) | ||
18 | |||
19 | static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 }; | ||
20 | |||
21 | static bool efi_no_storage_paranoia; | ||
22 | |||
23 | /* | ||
24 | * Some firmware implementations refuse to boot if there's insufficient | ||
25 | * space in the variable store. The implementation of garbage collection | ||
26 | * in some FW versions causes stale (deleted) variables to take up space | ||
27 | * longer than intended and space is only freed once the store becomes | ||
28 | * almost completely full. | ||
29 | * | ||
30 | * Enabling this option disables the space checks in | ||
31 | * efi_query_variable_store() and forces garbage collection. | ||
32 | * | ||
33 | * Only enable this option if deleting EFI variables does not free up | ||
34 | * space in your variable store, e.g. if despite deleting variables | ||
35 | * you're unable to create new ones. | ||
36 | */ | ||
37 | static int __init setup_storage_paranoia(char *arg) | ||
38 | { | ||
39 | efi_no_storage_paranoia = true; | ||
40 | return 0; | ||
41 | } | ||
42 | early_param("efi_no_storage_paranoia", setup_storage_paranoia); | ||
43 | |||
44 | /* | ||
45 | * Deleting the dummy variable which kicks off garbage collection | ||
46 | */ | ||
47 | void efi_delete_dummy_variable(void) | ||
48 | { | ||
49 | efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID, | ||
50 | EFI_VARIABLE_NON_VOLATILE | | ||
51 | EFI_VARIABLE_BOOTSERVICE_ACCESS | | ||
52 | EFI_VARIABLE_RUNTIME_ACCESS, | ||
53 | 0, NULL); | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * Some firmware implementations refuse to boot if there's insufficient space | ||
58 | * in the variable store. Ensure that we never use more than a safe limit. | ||
59 | * | ||
60 | * Return EFI_SUCCESS if it is safe to write 'size' bytes to the variable | ||
61 | * store. | ||
62 | */ | ||
63 | efi_status_t efi_query_variable_store(u32 attributes, unsigned long size) | ||
64 | { | ||
65 | efi_status_t status; | ||
66 | u64 storage_size, remaining_size, max_size; | ||
67 | |||
68 | if (!(attributes & EFI_VARIABLE_NON_VOLATILE)) | ||
69 | return 0; | ||
70 | |||
71 | status = efi.query_variable_info(attributes, &storage_size, | ||
72 | &remaining_size, &max_size); | ||
73 | if (status != EFI_SUCCESS) | ||
74 | return status; | ||
75 | |||
76 | /* | ||
77 | * We account for that by refusing the write if permitting it would | ||
78 | * reduce the available space to under 5KB. This figure was provided by | ||
79 | * Samsung, so should be safe. | ||
80 | */ | ||
81 | if ((remaining_size - size < EFI_MIN_RESERVE) && | ||
82 | !efi_no_storage_paranoia) { | ||
83 | |||
84 | /* | ||
85 | * Triggering garbage collection may require that the firmware | ||
86 | * generate a real EFI_OUT_OF_RESOURCES error. We can force | ||
87 | * that by attempting to use more space than is available. | ||
88 | */ | ||
89 | unsigned long dummy_size = remaining_size + 1024; | ||
90 | void *dummy = kzalloc(dummy_size, GFP_ATOMIC); | ||
91 | |||
92 | if (!dummy) | ||
93 | return EFI_OUT_OF_RESOURCES; | ||
94 | |||
95 | status = efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID, | ||
96 | EFI_VARIABLE_NON_VOLATILE | | ||
97 | EFI_VARIABLE_BOOTSERVICE_ACCESS | | ||
98 | EFI_VARIABLE_RUNTIME_ACCESS, | ||
99 | dummy_size, dummy); | ||
100 | |||
101 | if (status == EFI_SUCCESS) { | ||
102 | /* | ||
103 | * This should have failed, so if it didn't make sure | ||
104 | * that we delete it... | ||
105 | */ | ||
106 | efi_delete_dummy_variable(); | ||
107 | } | ||
108 | |||
109 | kfree(dummy); | ||
110 | |||
111 | /* | ||
112 | * The runtime code may now have triggered a garbage collection | ||
113 | * run, so check the variable info again | ||
114 | */ | ||
115 | status = efi.query_variable_info(attributes, &storage_size, | ||
116 | &remaining_size, &max_size); | ||
117 | |||
118 | if (status != EFI_SUCCESS) | ||
119 | return status; | ||
120 | |||
121 | /* | ||
122 | * There still isn't enough room, so return an error | ||
123 | */ | ||
124 | if (remaining_size - size < EFI_MIN_RESERVE) | ||
125 | return EFI_OUT_OF_RESOURCES; | ||
126 | } | ||
127 | |||
128 | return EFI_SUCCESS; | ||
129 | } | ||
130 | EXPORT_SYMBOL_GPL(efi_query_variable_store); | ||
131 | |||
132 | /* | ||
133 | * The UEFI specification makes it clear that the operating system is free to do | ||
134 | * whatever it wants with boot services code after ExitBootServices() has been | ||
135 | * called. Ignoring this recommendation a significant bunch of EFI implementations | ||
136 | * continue calling into boot services code (SetVirtualAddressMap). In order to | ||
137 | * work around such buggy implementations we reserve boot services region during | ||
138 | * EFI init and make sure it stays executable. Then, after SetVirtualAddressMap(), it | ||
139 | * is discarded. | ||
140 | */ | ||
141 | void __init efi_reserve_boot_services(void) | ||
142 | { | ||
143 | void *p; | ||
144 | |||
145 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | ||
146 | efi_memory_desc_t *md = p; | ||
147 | u64 start = md->phys_addr; | ||
148 | u64 size = md->num_pages << EFI_PAGE_SHIFT; | ||
149 | |||
150 | if (md->type != EFI_BOOT_SERVICES_CODE && | ||
151 | md->type != EFI_BOOT_SERVICES_DATA) | ||
152 | continue; | ||
153 | /* Only reserve where possible: | ||
154 | * - Not within any already allocated areas | ||
155 | * - Not over any memory area (really needed, if above?) | ||
156 | * - Not within any part of the kernel | ||
157 | * - Not the bios reserved area | ||
158 | */ | ||
159 | if ((start + size > __pa_symbol(_text) | ||
160 | && start <= __pa_symbol(_end)) || | ||
161 | !e820_all_mapped(start, start+size, E820_RAM) || | ||
162 | memblock_is_region_reserved(start, size)) { | ||
163 | /* Could not reserve, skip it */ | ||
164 | md->num_pages = 0; | ||
165 | memblock_dbg("Could not reserve boot range [0x%010llx-0x%010llx]\n", | ||
166 | start, start+size-1); | ||
167 | } else | ||
168 | memblock_reserve(start, size); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | void __init efi_free_boot_services(void) | ||
173 | { | ||
174 | void *p; | ||
175 | |||
176 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | ||
177 | efi_memory_desc_t *md = p; | ||
178 | unsigned long long start = md->phys_addr; | ||
179 | unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; | ||
180 | |||
181 | if (md->type != EFI_BOOT_SERVICES_CODE && | ||
182 | md->type != EFI_BOOT_SERVICES_DATA) | ||
183 | continue; | ||
184 | |||
185 | /* Could not reserve boot area */ | ||
186 | if (!size) | ||
187 | continue; | ||
188 | |||
189 | free_bootmem_late(start, size); | ||
190 | } | ||
191 | |||
192 | efi_unmap_memmap(); | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * A number of config table entries get remapped to virtual addresses | ||
197 | * after entering EFI virtual mode. However, the kexec kernel requires | ||
198 | * their physical addresses therefore we pass them via setup_data and | ||
199 | * correct those entries to their respective physical addresses here. | ||
200 | * | ||
201 | * Currently only handles smbios which is necessary for some firmware | ||
202 | * implementation. | ||
203 | */ | ||
204 | int __init efi_reuse_config(u64 tables, int nr_tables) | ||
205 | { | ||
206 | int i, sz, ret = 0; | ||
207 | void *p, *tablep; | ||
208 | struct efi_setup_data *data; | ||
209 | |||
210 | if (!efi_setup) | ||
211 | return 0; | ||
212 | |||
213 | if (!efi_enabled(EFI_64BIT)) | ||
214 | return 0; | ||
215 | |||
216 | data = early_memremap(efi_setup, sizeof(*data)); | ||
217 | if (!data) { | ||
218 | ret = -ENOMEM; | ||
219 | goto out; | ||
220 | } | ||
221 | |||
222 | if (!data->smbios) | ||
223 | goto out_memremap; | ||
224 | |||
225 | sz = sizeof(efi_config_table_64_t); | ||
226 | |||
227 | p = tablep = early_memremap(tables, nr_tables * sz); | ||
228 | if (!p) { | ||
229 | pr_err("Could not map Configuration table!\n"); | ||
230 | ret = -ENOMEM; | ||
231 | goto out_memremap; | ||
232 | } | ||
233 | |||
234 | for (i = 0; i < efi.systab->nr_tables; i++) { | ||
235 | efi_guid_t guid; | ||
236 | |||
237 | guid = ((efi_config_table_64_t *)p)->guid; | ||
238 | |||
239 | if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID)) | ||
240 | ((efi_config_table_64_t *)p)->table = data->smbios; | ||
241 | p += sz; | ||
242 | } | ||
243 | early_memunmap(tablep, nr_tables * sz); | ||
244 | |||
245 | out_memremap: | ||
246 | early_memunmap(data, sizeof(*data)); | ||
247 | out: | ||
248 | return ret; | ||
249 | } | ||
250 | |||
251 | void __init efi_apply_memmap_quirks(void) | ||
252 | { | ||
253 | /* | ||
254 | * Once setup is done earlier, unmap the EFI memory map on mismatched | ||
255 | * firmware/kernel architectures since there is no support for runtime | ||
256 | * services. | ||
257 | */ | ||
258 | if (!efi_runtime_supported()) { | ||
259 | pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n"); | ||
260 | efi_unmap_memmap(); | ||
261 | } | ||
262 | |||
263 | /* | ||
264 | * UV doesn't support the new EFI pagetable mapping yet. | ||
265 | */ | ||
266 | if (is_uv_system()) | ||
267 | set_bit(EFI_OLD_MEMMAP, &efi.flags); | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | * For most modern platforms the preferred method of powering off is via | ||
272 | * ACPI. However, there are some that are known to require the use of | ||
273 | * EFI runtime services and for which ACPI does not work at all. | ||
274 | * | ||
275 | * Using EFI is a last resort, to be used only if no other option | ||
276 | * exists. | ||
277 | */ | ||
278 | bool efi_reboot_required(void) | ||
279 | { | ||
280 | if (!acpi_gbl_reduced_hardware) | ||
281 | return false; | ||
282 | |||
283 | efi_reboot_quirk_mode = EFI_RESET_WARM; | ||
284 | return true; | ||
285 | } | ||
286 | |||
287 | bool efi_poweroff_required(void) | ||
288 | { | ||
289 | return !!acpi_gbl_reduced_hardware; | ||
290 | } | ||
diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile index 96ab2c09cb68..7322755f337a 100644 --- a/arch/x86/xen/Makefile +++ b/arch/x86/xen/Makefile | |||
@@ -22,3 +22,4 @@ obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o | |||
22 | obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o | 22 | obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o |
23 | obj-$(CONFIG_XEN_DOM0) += apic.o vga.o | 23 | obj-$(CONFIG_XEN_DOM0) += apic.o vga.o |
24 | obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o | 24 | obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o |
25 | obj-$(CONFIG_XEN_EFI) += efi.o | ||
diff --git a/arch/x86/xen/efi.c b/arch/x86/xen/efi.c new file mode 100644 index 000000000000..a02e09e18f57 --- /dev/null +++ b/arch/x86/xen/efi.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 Oracle Co., Daniel Kiper | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along | ||
15 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | ||
17 | |||
18 | #include <linux/efi.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/string.h> | ||
21 | |||
22 | #include <xen/xen-ops.h> | ||
23 | |||
24 | #include <asm/setup.h> | ||
25 | |||
26 | void __init xen_efi_init(void) | ||
27 | { | ||
28 | efi_system_table_t *efi_systab_xen; | ||
29 | |||
30 | efi_systab_xen = xen_efi_probe(); | ||
31 | |||
32 | if (efi_systab_xen == NULL) | ||
33 | return; | ||
34 | |||
35 | strncpy((char *)&boot_params.efi_info.efi_loader_signature, "Xen", | ||
36 | sizeof(boot_params.efi_info.efi_loader_signature)); | ||
37 | boot_params.efi_info.efi_systab = (__u32)__pa(efi_systab_xen); | ||
38 | boot_params.efi_info.efi_systab_hi = (__u32)(__pa(efi_systab_xen) >> 32); | ||
39 | |||
40 | set_bit(EFI_BOOT, &efi.flags); | ||
41 | set_bit(EFI_PARAVIRT, &efi.flags); | ||
42 | set_bit(EFI_64BIT, &efi.flags); | ||
43 | } | ||
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index ffb101e45731..94813515fdd6 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -1718,6 +1718,8 @@ asmlinkage __visible void __init xen_start_kernel(void) | |||
1718 | 1718 | ||
1719 | xen_setup_runstate_info(0); | 1719 | xen_setup_runstate_info(0); |
1720 | 1720 | ||
1721 | xen_efi_init(); | ||
1722 | |||
1721 | /* Start the world */ | 1723 | /* Start the world */ |
1722 | #ifdef CONFIG_X86_32 | 1724 | #ifdef CONFIG_X86_32 |
1723 | i386_start_kernel(); | 1725 | i386_start_kernel(); |
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 97d87659f779..28c7e0be56e4 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h | |||
@@ -105,6 +105,14 @@ static inline void __init xen_init_apic(void) | |||
105 | } | 105 | } |
106 | #endif | 106 | #endif |
107 | 107 | ||
108 | #ifdef CONFIG_XEN_EFI | ||
109 | extern void xen_efi_init(void); | ||
110 | #else | ||
111 | static inline void __init xen_efi_init(void) | ||
112 | { | ||
113 | } | ||
114 | #endif | ||
115 | |||
108 | /* Declare an asm function, along with symbols needed to make it | 116 | /* Declare an asm function, along with symbols needed to make it |
109 | inlineable */ | 117 | inlineable */ |
110 | #define DECL_ASM(ret, name, ...) \ | 118 | #define DECL_ASM(ret, name, ...) \ |
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index d420ae2d3413..f712d47f30d8 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig | |||
@@ -54,6 +54,12 @@ config EFI_PARAMS_FROM_FDT | |||
54 | the EFI runtime support gets system table address, memory | 54 | the EFI runtime support gets system table address, memory |
55 | map address, and other parameters from the device tree. | 55 | map address, and other parameters from the device tree. |
56 | 56 | ||
57 | config EFI_RUNTIME_WRAPPERS | ||
58 | bool | ||
59 | |||
60 | config EFI_ARMSTUB | ||
61 | bool | ||
62 | |||
57 | endmenu | 63 | endmenu |
58 | 64 | ||
59 | config UEFI_CPER | 65 | config UEFI_CPER |
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index 9553496b0f43..d8be608a9f3b 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile | |||
@@ -1,8 +1,10 @@ | |||
1 | # | 1 | # |
2 | # Makefile for linux kernel | 2 | # Makefile for linux kernel |
3 | # | 3 | # |
4 | obj-$(CONFIG_EFI) += efi.o vars.o | 4 | obj-$(CONFIG_EFI) += efi.o vars.o reboot.o |
5 | obj-$(CONFIG_EFI_VARS) += efivars.o | 5 | obj-$(CONFIG_EFI_VARS) += efivars.o |
6 | obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o | 6 | obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o |
7 | obj-$(CONFIG_UEFI_CPER) += cper.o | 7 | obj-$(CONFIG_UEFI_CPER) += cper.o |
8 | obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o | 8 | obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o |
9 | obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o | ||
10 | obj-$(CONFIG_EFI_STUB) += libstub/ | ||
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index dc79346689e6..64ecbb501c50 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/of.h> | 23 | #include <linux/of.h> |
24 | #include <linux/of_fdt.h> | 24 | #include <linux/of_fdt.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/platform_device.h> | ||
26 | 27 | ||
27 | struct efi __read_mostly efi = { | 28 | struct efi __read_mostly efi = { |
28 | .mps = EFI_INVALID_TABLE_ADDR, | 29 | .mps = EFI_INVALID_TABLE_ADDR, |
@@ -104,16 +105,19 @@ static struct attribute *efi_subsys_attrs[] = { | |||
104 | static umode_t efi_attr_is_visible(struct kobject *kobj, | 105 | static umode_t efi_attr_is_visible(struct kobject *kobj, |
105 | struct attribute *attr, int n) | 106 | struct attribute *attr, int n) |
106 | { | 107 | { |
107 | umode_t mode = attr->mode; | 108 | if (attr == &efi_attr_fw_vendor.attr) { |
108 | 109 | if (efi_enabled(EFI_PARAVIRT) || | |
109 | if (attr == &efi_attr_fw_vendor.attr) | 110 | efi.fw_vendor == EFI_INVALID_TABLE_ADDR) |
110 | return (efi.fw_vendor == EFI_INVALID_TABLE_ADDR) ? 0 : mode; | 111 | return 0; |
111 | else if (attr == &efi_attr_runtime.attr) | 112 | } else if (attr == &efi_attr_runtime.attr) { |
112 | return (efi.runtime == EFI_INVALID_TABLE_ADDR) ? 0 : mode; | 113 | if (efi.runtime == EFI_INVALID_TABLE_ADDR) |
113 | else if (attr == &efi_attr_config_table.attr) | 114 | return 0; |
114 | return (efi.config_table == EFI_INVALID_TABLE_ADDR) ? 0 : mode; | 115 | } else if (attr == &efi_attr_config_table.attr) { |
116 | if (efi.config_table == EFI_INVALID_TABLE_ADDR) | ||
117 | return 0; | ||
118 | } | ||
115 | 119 | ||
116 | return mode; | 120 | return attr->mode; |
117 | } | 121 | } |
118 | 122 | ||
119 | static struct attribute_group efi_subsys_attr_group = { | 123 | static struct attribute_group efi_subsys_attr_group = { |
@@ -298,7 +302,7 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables) | |||
298 | if (table64 >> 32) { | 302 | if (table64 >> 32) { |
299 | pr_cont("\n"); | 303 | pr_cont("\n"); |
300 | pr_err("Table located above 4GB, disabling EFI.\n"); | 304 | pr_err("Table located above 4GB, disabling EFI.\n"); |
301 | early_iounmap(config_tables, | 305 | early_memunmap(config_tables, |
302 | efi.systab->nr_tables * sz); | 306 | efi.systab->nr_tables * sz); |
303 | return -EINVAL; | 307 | return -EINVAL; |
304 | } | 308 | } |
@@ -314,13 +318,27 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables) | |||
314 | tablep += sz; | 318 | tablep += sz; |
315 | } | 319 | } |
316 | pr_cont("\n"); | 320 | pr_cont("\n"); |
317 | early_iounmap(config_tables, efi.systab->nr_tables * sz); | 321 | early_memunmap(config_tables, efi.systab->nr_tables * sz); |
318 | 322 | ||
319 | set_bit(EFI_CONFIG_TABLES, &efi.flags); | 323 | set_bit(EFI_CONFIG_TABLES, &efi.flags); |
320 | 324 | ||
321 | return 0; | 325 | return 0; |
322 | } | 326 | } |
323 | 327 | ||
328 | #ifdef CONFIG_EFI_VARS_MODULE | ||
329 | static int __init efi_load_efivars(void) | ||
330 | { | ||
331 | struct platform_device *pdev; | ||
332 | |||
333 | if (!efi_enabled(EFI_RUNTIME_SERVICES)) | ||
334 | return 0; | ||
335 | |||
336 | pdev = platform_device_register_simple("efivars", 0, NULL, 0); | ||
337 | return IS_ERR(pdev) ? PTR_ERR(pdev) : 0; | ||
338 | } | ||
339 | device_initcall(efi_load_efivars); | ||
340 | #endif | ||
341 | |||
324 | #ifdef CONFIG_EFI_PARAMS_FROM_FDT | 342 | #ifdef CONFIG_EFI_PARAMS_FROM_FDT |
325 | 343 | ||
326 | #define UEFI_PARAM(name, prop, field) \ | 344 | #define UEFI_PARAM(name, prop, field) \ |
diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c index 463c56545ae8..f256ecd8a176 100644 --- a/drivers/firmware/efi/efivars.c +++ b/drivers/firmware/efi/efivars.c | |||
@@ -78,6 +78,7 @@ MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>"); | |||
78 | MODULE_DESCRIPTION("sysfs interface to EFI Variables"); | 78 | MODULE_DESCRIPTION("sysfs interface to EFI Variables"); |
79 | MODULE_LICENSE("GPL"); | 79 | MODULE_LICENSE("GPL"); |
80 | MODULE_VERSION(EFIVARS_VERSION); | 80 | MODULE_VERSION(EFIVARS_VERSION); |
81 | MODULE_ALIAS("platform:efivars"); | ||
81 | 82 | ||
82 | LIST_HEAD(efivar_sysfs_list); | 83 | LIST_HEAD(efivar_sysfs_list); |
83 | EXPORT_SYMBOL_GPL(efivar_sysfs_list); | 84 | EXPORT_SYMBOL_GPL(efivar_sysfs_list); |
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile new file mode 100644 index 000000000000..b14bc2b9fb4d --- /dev/null +++ b/drivers/firmware/efi/libstub/Makefile | |||
@@ -0,0 +1,26 @@ | |||
1 | # | ||
2 | # The stub may be linked into the kernel proper or into a separate boot binary, | ||
3 | # but in either case, it executes before the kernel does (with MMU disabled) so | ||
4 | # things like ftrace and stack-protector are likely to cause trouble if left | ||
5 | # enabled, even if doing so doesn't break the build. | ||
6 | # | ||
7 | cflags-$(CONFIG_X86_32) := -march=i386 | ||
8 | cflags-$(CONFIG_X86_64) := -mcmodel=small | ||
9 | cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 \ | ||
10 | -fPIC -fno-strict-aliasing -mno-red-zone \ | ||
11 | -mno-mmx -mno-sse -DDISABLE_BRANCH_PROFILING | ||
12 | |||
13 | cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS)) | ||
14 | cflags-$(CONFIG_ARM) := $(subst -pg,,$(KBUILD_CFLAGS)) \ | ||
15 | -fno-builtin -fpic -mno-single-pic-base | ||
16 | |||
17 | KBUILD_CFLAGS := $(cflags-y) \ | ||
18 | $(call cc-option,-ffreestanding) \ | ||
19 | $(call cc-option,-fno-stack-protector) | ||
20 | |||
21 | GCOV_PROFILE := n | ||
22 | |||
23 | lib-y := efi-stub-helper.o | ||
24 | lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o | ||
25 | |||
26 | CFLAGS_fdt.o += -I$(srctree)/scripts/dtc/libfdt/ | ||
diff --git a/drivers/firmware/efi/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 41114ce03b01..480339b6b110 100644 --- a/drivers/firmware/efi/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c | |||
@@ -12,6 +12,11 @@ | |||
12 | * | 12 | * |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/efi.h> | ||
16 | #include <asm/efi.h> | ||
17 | |||
18 | #include "efistub.h" | ||
19 | |||
15 | static int __init efi_secureboot_enabled(efi_system_table_t *sys_table_arg) | 20 | static int __init efi_secureboot_enabled(efi_system_table_t *sys_table_arg) |
16 | { | 21 | { |
17 | static efi_guid_t const var_guid __initconst = EFI_GLOBAL_VARIABLE_GUID; | 22 | static efi_guid_t const var_guid __initconst = EFI_GLOBAL_VARIABLE_GUID; |
@@ -36,8 +41,8 @@ static int __init efi_secureboot_enabled(efi_system_table_t *sys_table_arg) | |||
36 | } | 41 | } |
37 | } | 42 | } |
38 | 43 | ||
39 | static efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, | 44 | efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, |
40 | void *__image, void **__fh) | 45 | void *__image, void **__fh) |
41 | { | 46 | { |
42 | efi_file_io_interface_t *io; | 47 | efi_file_io_interface_t *io; |
43 | efi_loaded_image_t *image = __image; | 48 | efi_loaded_image_t *image = __image; |
@@ -60,14 +65,15 @@ static efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, | |||
60 | *__fh = fh; | 65 | *__fh = fh; |
61 | return status; | 66 | return status; |
62 | } | 67 | } |
63 | static efi_status_t efi_file_close(void *handle) | 68 | |
69 | efi_status_t efi_file_close(void *handle) | ||
64 | { | 70 | { |
65 | efi_file_handle_t *fh = handle; | 71 | efi_file_handle_t *fh = handle; |
66 | 72 | ||
67 | return fh->close(handle); | 73 | return fh->close(handle); |
68 | } | 74 | } |
69 | 75 | ||
70 | static efi_status_t | 76 | efi_status_t |
71 | efi_file_read(void *handle, unsigned long *size, void *addr) | 77 | efi_file_read(void *handle, unsigned long *size, void *addr) |
72 | { | 78 | { |
73 | efi_file_handle_t *fh = handle; | 79 | efi_file_handle_t *fh = handle; |
@@ -76,7 +82,7 @@ efi_file_read(void *handle, unsigned long *size, void *addr) | |||
76 | } | 82 | } |
77 | 83 | ||
78 | 84 | ||
79 | static efi_status_t | 85 | efi_status_t |
80 | efi_file_size(efi_system_table_t *sys_table_arg, void *__fh, | 86 | efi_file_size(efi_system_table_t *sys_table_arg, void *__fh, |
81 | efi_char16_t *filename_16, void **handle, u64 *file_sz) | 87 | efi_char16_t *filename_16, void **handle, u64 *file_sz) |
82 | { | 88 | { |
@@ -129,7 +135,7 @@ grow: | |||
129 | 135 | ||
130 | 136 | ||
131 | 137 | ||
132 | static void efi_char16_printk(efi_system_table_t *sys_table_arg, | 138 | void efi_char16_printk(efi_system_table_t *sys_table_arg, |
133 | efi_char16_t *str) | 139 | efi_char16_t *str) |
134 | { | 140 | { |
135 | struct efi_simple_text_output_protocol *out; | 141 | struct efi_simple_text_output_protocol *out; |
@@ -145,13 +151,13 @@ static void efi_char16_printk(efi_system_table_t *sys_table_arg, | |||
145 | * must be reserved. On failure it is required to free all | 151 | * must be reserved. On failure it is required to free all |
146 | * all allocations it has made. | 152 | * all allocations it has made. |
147 | */ | 153 | */ |
148 | static efi_status_t handle_kernel_image(efi_system_table_t *sys_table, | 154 | efi_status_t handle_kernel_image(efi_system_table_t *sys_table, |
149 | unsigned long *image_addr, | 155 | unsigned long *image_addr, |
150 | unsigned long *image_size, | 156 | unsigned long *image_size, |
151 | unsigned long *reserve_addr, | 157 | unsigned long *reserve_addr, |
152 | unsigned long *reserve_size, | 158 | unsigned long *reserve_size, |
153 | unsigned long dram_base, | 159 | unsigned long dram_base, |
154 | efi_loaded_image_t *image); | 160 | efi_loaded_image_t *image); |
155 | /* | 161 | /* |
156 | * EFI entry point for the arm/arm64 EFI stubs. This is the entrypoint | 162 | * EFI entry point for the arm/arm64 EFI stubs. This is the entrypoint |
157 | * that is described in the PE/COFF header. Most of the code is the same | 163 | * that is described in the PE/COFF header. Most of the code is the same |
diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index eb6d4be9e722..32d5cca30f49 100644 --- a/drivers/firmware/efi/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c | |||
@@ -9,18 +9,20 @@ | |||
9 | * under the terms of the GNU General Public License version 2. | 9 | * under the terms of the GNU General Public License version 2. |
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | #define EFI_READ_CHUNK_SIZE (1024 * 1024) | ||
13 | 12 | ||
14 | /* error code which can't be mistaken for valid address */ | 13 | #include <linux/efi.h> |
15 | #define EFI_ERROR (~0UL) | 14 | #include <asm/efi.h> |
15 | |||
16 | #include "efistub.h" | ||
16 | 17 | ||
18 | #define EFI_READ_CHUNK_SIZE (1024 * 1024) | ||
17 | 19 | ||
18 | struct file_info { | 20 | struct file_info { |
19 | efi_file_handle_t *handle; | 21 | efi_file_handle_t *handle; |
20 | u64 size; | 22 | u64 size; |
21 | }; | 23 | }; |
22 | 24 | ||
23 | static void efi_printk(efi_system_table_t *sys_table_arg, char *str) | 25 | void efi_printk(efi_system_table_t *sys_table_arg, char *str) |
24 | { | 26 | { |
25 | char *s8; | 27 | char *s8; |
26 | 28 | ||
@@ -37,16 +39,12 @@ static void efi_printk(efi_system_table_t *sys_table_arg, char *str) | |||
37 | } | 39 | } |
38 | } | 40 | } |
39 | 41 | ||
40 | #define pr_efi(sys_table, msg) efi_printk(sys_table, "EFI stub: "msg) | 42 | efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg, |
41 | #define pr_efi_err(sys_table, msg) efi_printk(sys_table, "EFI stub: ERROR: "msg) | 43 | efi_memory_desc_t **map, |
42 | 44 | unsigned long *map_size, | |
43 | 45 | unsigned long *desc_size, | |
44 | static efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg, | 46 | u32 *desc_ver, |
45 | efi_memory_desc_t **map, | 47 | unsigned long *key_ptr) |
46 | unsigned long *map_size, | ||
47 | unsigned long *desc_size, | ||
48 | u32 *desc_ver, | ||
49 | unsigned long *key_ptr) | ||
50 | { | 48 | { |
51 | efi_memory_desc_t *m = NULL; | 49 | efi_memory_desc_t *m = NULL; |
52 | efi_status_t status; | 50 | efi_status_t status; |
@@ -88,7 +86,7 @@ fail: | |||
88 | } | 86 | } |
89 | 87 | ||
90 | 88 | ||
91 | static unsigned long __init get_dram_base(efi_system_table_t *sys_table_arg) | 89 | unsigned long __init get_dram_base(efi_system_table_t *sys_table_arg) |
92 | { | 90 | { |
93 | efi_status_t status; | 91 | efi_status_t status; |
94 | unsigned long map_size; | 92 | unsigned long map_size; |
@@ -116,9 +114,9 @@ static unsigned long __init get_dram_base(efi_system_table_t *sys_table_arg) | |||
116 | /* | 114 | /* |
117 | * Allocate at the highest possible address that is not above 'max'. | 115 | * Allocate at the highest possible address that is not above 'max'. |
118 | */ | 116 | */ |
119 | static efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg, | 117 | efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg, |
120 | unsigned long size, unsigned long align, | 118 | unsigned long size, unsigned long align, |
121 | unsigned long *addr, unsigned long max) | 119 | unsigned long *addr, unsigned long max) |
122 | { | 120 | { |
123 | unsigned long map_size, desc_size; | 121 | unsigned long map_size, desc_size; |
124 | efi_memory_desc_t *map; | 122 | efi_memory_desc_t *map; |
@@ -202,9 +200,9 @@ fail: | |||
202 | /* | 200 | /* |
203 | * Allocate at the lowest possible address. | 201 | * Allocate at the lowest possible address. |
204 | */ | 202 | */ |
205 | static efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg, | 203 | efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg, |
206 | unsigned long size, unsigned long align, | 204 | unsigned long size, unsigned long align, |
207 | unsigned long *addr) | 205 | unsigned long *addr) |
208 | { | 206 | { |
209 | unsigned long map_size, desc_size; | 207 | unsigned long map_size, desc_size; |
210 | efi_memory_desc_t *map; | 208 | efi_memory_desc_t *map; |
@@ -271,8 +269,8 @@ fail: | |||
271 | return status; | 269 | return status; |
272 | } | 270 | } |
273 | 271 | ||
274 | static void efi_free(efi_system_table_t *sys_table_arg, unsigned long size, | 272 | void efi_free(efi_system_table_t *sys_table_arg, unsigned long size, |
275 | unsigned long addr) | 273 | unsigned long addr) |
276 | { | 274 | { |
277 | unsigned long nr_pages; | 275 | unsigned long nr_pages; |
278 | 276 | ||
@@ -290,12 +288,12 @@ static void efi_free(efi_system_table_t *sys_table_arg, unsigned long size, | |||
290 | * We only support loading a file from the same filesystem as | 288 | * We only support loading a file from the same filesystem as |
291 | * the kernel image. | 289 | * the kernel image. |
292 | */ | 290 | */ |
293 | static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, | 291 | efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, |
294 | efi_loaded_image_t *image, | 292 | efi_loaded_image_t *image, |
295 | char *cmd_line, char *option_string, | 293 | char *cmd_line, char *option_string, |
296 | unsigned long max_addr, | 294 | unsigned long max_addr, |
297 | unsigned long *load_addr, | 295 | unsigned long *load_addr, |
298 | unsigned long *load_size) | 296 | unsigned long *load_size) |
299 | { | 297 | { |
300 | struct file_info *files; | 298 | struct file_info *files; |
301 | unsigned long file_addr; | 299 | unsigned long file_addr; |
@@ -477,12 +475,12 @@ fail: | |||
477 | * address is not available the lowest available address will | 475 | * address is not available the lowest available address will |
478 | * be used. | 476 | * be used. |
479 | */ | 477 | */ |
480 | static efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg, | 478 | efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg, |
481 | unsigned long *image_addr, | 479 | unsigned long *image_addr, |
482 | unsigned long image_size, | 480 | unsigned long image_size, |
483 | unsigned long alloc_size, | 481 | unsigned long alloc_size, |
484 | unsigned long preferred_addr, | 482 | unsigned long preferred_addr, |
485 | unsigned long alignment) | 483 | unsigned long alignment) |
486 | { | 484 | { |
487 | unsigned long cur_image_addr; | 485 | unsigned long cur_image_addr; |
488 | unsigned long new_addr = 0; | 486 | unsigned long new_addr = 0; |
@@ -589,9 +587,9 @@ static u8 *efi_utf16_to_utf8(u8 *dst, const u16 *src, int n) | |||
589 | * Size of memory allocated return in *cmd_line_len. | 587 | * Size of memory allocated return in *cmd_line_len. |
590 | * Returns NULL on error. | 588 | * Returns NULL on error. |
591 | */ | 589 | */ |
592 | static char *efi_convert_cmdline(efi_system_table_t *sys_table_arg, | 590 | char *efi_convert_cmdline(efi_system_table_t *sys_table_arg, |
593 | efi_loaded_image_t *image, | 591 | efi_loaded_image_t *image, |
594 | int *cmd_line_len) | 592 | int *cmd_line_len) |
595 | { | 593 | { |
596 | const u16 *s2; | 594 | const u16 *s2; |
597 | u8 *s1 = NULL; | 595 | u8 *s1 = NULL; |
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h new file mode 100644 index 000000000000..304ab295ca1a --- /dev/null +++ b/drivers/firmware/efi/libstub/efistub.h | |||
@@ -0,0 +1,42 @@ | |||
1 | |||
2 | #ifndef _DRIVERS_FIRMWARE_EFI_EFISTUB_H | ||
3 | #define _DRIVERS_FIRMWARE_EFI_EFISTUB_H | ||
4 | |||
5 | /* error code which can't be mistaken for valid address */ | ||
6 | #define EFI_ERROR (~0UL) | ||
7 | |||
8 | void efi_char16_printk(efi_system_table_t *, efi_char16_t *); | ||
9 | |||
10 | efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image, | ||
11 | void **__fh); | ||
12 | |||
13 | efi_status_t efi_file_size(efi_system_table_t *sys_table_arg, void *__fh, | ||
14 | efi_char16_t *filename_16, void **handle, | ||
15 | u64 *file_sz); | ||
16 | |||
17 | efi_status_t efi_file_read(void *handle, unsigned long *size, void *addr); | ||
18 | |||
19 | efi_status_t efi_file_close(void *handle); | ||
20 | |||
21 | unsigned long get_dram_base(efi_system_table_t *sys_table_arg); | ||
22 | |||
23 | efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, | ||
24 | unsigned long orig_fdt_size, | ||
25 | void *fdt, int new_fdt_size, char *cmdline_ptr, | ||
26 | u64 initrd_addr, u64 initrd_size, | ||
27 | efi_memory_desc_t *memory_map, | ||
28 | unsigned long map_size, unsigned long desc_size, | ||
29 | u32 desc_ver); | ||
30 | |||
31 | efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, | ||
32 | void *handle, | ||
33 | unsigned long *new_fdt_addr, | ||
34 | unsigned long max_addr, | ||
35 | u64 initrd_addr, u64 initrd_size, | ||
36 | char *cmdline_ptr, | ||
37 | unsigned long fdt_addr, | ||
38 | unsigned long fdt_size); | ||
39 | |||
40 | void *get_fdt(efi_system_table_t *sys_table); | ||
41 | |||
42 | #endif | ||
diff --git a/drivers/firmware/efi/fdt.c b/drivers/firmware/efi/libstub/fdt.c index 507a3df46a5d..a56bb3528755 100644 --- a/drivers/firmware/efi/fdt.c +++ b/drivers/firmware/efi/libstub/fdt.c | |||
@@ -10,13 +10,17 @@ | |||
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | 12 | ||
13 | static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, | 13 | #include <linux/efi.h> |
14 | unsigned long orig_fdt_size, | 14 | #include <linux/libfdt.h> |
15 | void *fdt, int new_fdt_size, char *cmdline_ptr, | 15 | #include <asm/efi.h> |
16 | u64 initrd_addr, u64 initrd_size, | 16 | |
17 | efi_memory_desc_t *memory_map, | 17 | efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, |
18 | unsigned long map_size, unsigned long desc_size, | 18 | unsigned long orig_fdt_size, |
19 | u32 desc_ver) | 19 | void *fdt, int new_fdt_size, char *cmdline_ptr, |
20 | u64 initrd_addr, u64 initrd_size, | ||
21 | efi_memory_desc_t *memory_map, | ||
22 | unsigned long map_size, unsigned long desc_size, | ||
23 | u32 desc_ver) | ||
20 | { | 24 | { |
21 | int node, prev; | 25 | int node, prev; |
22 | int status; | 26 | int status; |
@@ -255,7 +259,7 @@ fail: | |||
255 | return EFI_LOAD_ERROR; | 259 | return EFI_LOAD_ERROR; |
256 | } | 260 | } |
257 | 261 | ||
258 | static void *get_fdt(efi_system_table_t *sys_table) | 262 | void *get_fdt(efi_system_table_t *sys_table) |
259 | { | 263 | { |
260 | efi_guid_t fdt_guid = DEVICE_TREE_GUID; | 264 | efi_guid_t fdt_guid = DEVICE_TREE_GUID; |
261 | efi_config_table_t *tables; | 265 | efi_config_table_t *tables; |
diff --git a/drivers/firmware/efi/reboot.c b/drivers/firmware/efi/reboot.c new file mode 100644 index 000000000000..9c59d1c795d1 --- /dev/null +++ b/drivers/firmware/efi/reboot.c | |||
@@ -0,0 +1,56 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Intel Corporation; author Matt Fleming | ||
3 | * Copyright (c) 2014 Red Hat, Inc., Mark Salter <msalter@redhat.com> | ||
4 | */ | ||
5 | #include <linux/efi.h> | ||
6 | #include <linux/reboot.h> | ||
7 | |||
8 | int efi_reboot_quirk_mode = -1; | ||
9 | |||
10 | void efi_reboot(enum reboot_mode reboot_mode, const char *__unused) | ||
11 | { | ||
12 | int efi_mode; | ||
13 | |||
14 | if (!efi_enabled(EFI_RUNTIME_SERVICES)) | ||
15 | return; | ||
16 | |||
17 | switch (reboot_mode) { | ||
18 | case REBOOT_WARM: | ||
19 | case REBOOT_SOFT: | ||
20 | efi_mode = EFI_RESET_WARM; | ||
21 | break; | ||
22 | default: | ||
23 | efi_mode = EFI_RESET_COLD; | ||
24 | break; | ||
25 | } | ||
26 | |||
27 | /* | ||
28 | * If a quirk forced an EFI reset mode, always use that. | ||
29 | */ | ||
30 | if (efi_reboot_quirk_mode != -1) | ||
31 | efi_mode = efi_reboot_quirk_mode; | ||
32 | |||
33 | efi.reset_system(efi_mode, EFI_SUCCESS, 0, NULL); | ||
34 | } | ||
35 | |||
36 | bool __weak efi_poweroff_required(void) | ||
37 | { | ||
38 | return false; | ||
39 | } | ||
40 | |||
41 | static void efi_power_off(void) | ||
42 | { | ||
43 | efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL); | ||
44 | } | ||
45 | |||
46 | static int __init efi_shutdown_init(void) | ||
47 | { | ||
48 | if (!efi_enabled(EFI_RUNTIME_SERVICES)) | ||
49 | return -ENODEV; | ||
50 | |||
51 | if (efi_poweroff_required()) | ||
52 | pm_power_off = efi_power_off; | ||
53 | |||
54 | return 0; | ||
55 | } | ||
56 | late_initcall(efi_shutdown_init); | ||
diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c new file mode 100644 index 000000000000..10daa4bbb258 --- /dev/null +++ b/drivers/firmware/efi/runtime-wrappers.c | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | * runtime-wrappers.c - Runtime Services function call wrappers | ||
3 | * | ||
4 | * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org> | ||
5 | * | ||
6 | * Split off from arch/x86/platform/efi/efi.c | ||
7 | * | ||
8 | * Copyright (C) 1999 VA Linux Systems | ||
9 | * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> | ||
10 | * Copyright (C) 1999-2002 Hewlett-Packard Co. | ||
11 | * Copyright (C) 2005-2008 Intel Co. | ||
12 | * Copyright (C) 2013 SuSE Labs | ||
13 | * | ||
14 | * This file is released under the GPLv2. | ||
15 | */ | ||
16 | |||
17 | #include <linux/efi.h> | ||
18 | #include <linux/spinlock.h> /* spinlock_t */ | ||
19 | #include <asm/efi.h> | ||
20 | |||
21 | /* | ||
22 | * As per commit ef68c8f87ed1 ("x86: Serialize EFI time accesses on rtc_lock"), | ||
23 | * the EFI specification requires that callers of the time related runtime | ||
24 | * functions serialize with other CMOS accesses in the kernel, as the EFI time | ||
25 | * functions may choose to also use the legacy CMOS RTC. | ||
26 | */ | ||
27 | __weak DEFINE_SPINLOCK(rtc_lock); | ||
28 | |||
29 | static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) | ||
30 | { | ||
31 | unsigned long flags; | ||
32 | efi_status_t status; | ||
33 | |||
34 | spin_lock_irqsave(&rtc_lock, flags); | ||
35 | status = efi_call_virt(get_time, tm, tc); | ||
36 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
37 | return status; | ||
38 | } | ||
39 | |||
40 | static efi_status_t virt_efi_set_time(efi_time_t *tm) | ||
41 | { | ||
42 | unsigned long flags; | ||
43 | efi_status_t status; | ||
44 | |||
45 | spin_lock_irqsave(&rtc_lock, flags); | ||
46 | status = efi_call_virt(set_time, tm); | ||
47 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
48 | return status; | ||
49 | } | ||
50 | |||
51 | static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled, | ||
52 | efi_bool_t *pending, | ||
53 | efi_time_t *tm) | ||
54 | { | ||
55 | unsigned long flags; | ||
56 | efi_status_t status; | ||
57 | |||
58 | spin_lock_irqsave(&rtc_lock, flags); | ||
59 | status = efi_call_virt(get_wakeup_time, enabled, pending, tm); | ||
60 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
61 | return status; | ||
62 | } | ||
63 | |||
64 | static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) | ||
65 | { | ||
66 | unsigned long flags; | ||
67 | efi_status_t status; | ||
68 | |||
69 | spin_lock_irqsave(&rtc_lock, flags); | ||
70 | status = efi_call_virt(set_wakeup_time, enabled, tm); | ||
71 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
72 | return status; | ||
73 | } | ||
74 | |||
75 | static efi_status_t virt_efi_get_variable(efi_char16_t *name, | ||
76 | efi_guid_t *vendor, | ||
77 | u32 *attr, | ||
78 | unsigned long *data_size, | ||
79 | void *data) | ||
80 | { | ||
81 | return efi_call_virt(get_variable, name, vendor, attr, data_size, data); | ||
82 | } | ||
83 | |||
84 | static efi_status_t virt_efi_get_next_variable(unsigned long *name_size, | ||
85 | efi_char16_t *name, | ||
86 | efi_guid_t *vendor) | ||
87 | { | ||
88 | return efi_call_virt(get_next_variable, name_size, name, vendor); | ||
89 | } | ||
90 | |||
91 | static efi_status_t virt_efi_set_variable(efi_char16_t *name, | ||
92 | efi_guid_t *vendor, | ||
93 | u32 attr, | ||
94 | unsigned long data_size, | ||
95 | void *data) | ||
96 | { | ||
97 | return efi_call_virt(set_variable, name, vendor, attr, data_size, data); | ||
98 | } | ||
99 | |||
100 | static efi_status_t virt_efi_query_variable_info(u32 attr, | ||
101 | u64 *storage_space, | ||
102 | u64 *remaining_space, | ||
103 | u64 *max_variable_size) | ||
104 | { | ||
105 | if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) | ||
106 | return EFI_UNSUPPORTED; | ||
107 | |||
108 | return efi_call_virt(query_variable_info, attr, storage_space, | ||
109 | remaining_space, max_variable_size); | ||
110 | } | ||
111 | |||
112 | static efi_status_t virt_efi_get_next_high_mono_count(u32 *count) | ||
113 | { | ||
114 | return efi_call_virt(get_next_high_mono_count, count); | ||
115 | } | ||
116 | |||
117 | static void virt_efi_reset_system(int reset_type, | ||
118 | efi_status_t status, | ||
119 | unsigned long data_size, | ||
120 | efi_char16_t *data) | ||
121 | { | ||
122 | __efi_call_virt(reset_system, reset_type, status, data_size, data); | ||
123 | } | ||
124 | |||
125 | static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules, | ||
126 | unsigned long count, | ||
127 | unsigned long sg_list) | ||
128 | { | ||
129 | if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) | ||
130 | return EFI_UNSUPPORTED; | ||
131 | |||
132 | return efi_call_virt(update_capsule, capsules, count, sg_list); | ||
133 | } | ||
134 | |||
135 | static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules, | ||
136 | unsigned long count, | ||
137 | u64 *max_size, | ||
138 | int *reset_type) | ||
139 | { | ||
140 | if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) | ||
141 | return EFI_UNSUPPORTED; | ||
142 | |||
143 | return efi_call_virt(query_capsule_caps, capsules, count, max_size, | ||
144 | reset_type); | ||
145 | } | ||
146 | |||
147 | void efi_native_runtime_setup(void) | ||
148 | { | ||
149 | efi.get_time = virt_efi_get_time; | ||
150 | efi.set_time = virt_efi_set_time; | ||
151 | efi.get_wakeup_time = virt_efi_get_wakeup_time; | ||
152 | efi.set_wakeup_time = virt_efi_set_wakeup_time; | ||
153 | efi.get_variable = virt_efi_get_variable; | ||
154 | efi.get_next_variable = virt_efi_get_next_variable; | ||
155 | efi.set_variable = virt_efi_set_variable; | ||
156 | efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count; | ||
157 | efi.reset_system = virt_efi_reset_system; | ||
158 | efi.query_variable_info = virt_efi_query_variable_info; | ||
159 | efi.update_capsule = virt_efi_update_capsule; | ||
160 | efi.query_capsule_caps = virt_efi_query_capsule_caps; | ||
161 | } | ||
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 38fb36e1c592..8bc01838daf9 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig | |||
@@ -240,4 +240,8 @@ config XEN_MCE_LOG | |||
240 | config XEN_HAVE_PVMMU | 240 | config XEN_HAVE_PVMMU |
241 | bool | 241 | bool |
242 | 242 | ||
243 | config XEN_EFI | ||
244 | def_bool y | ||
245 | depends on X86_64 && EFI | ||
246 | |||
243 | endmenu | 247 | endmenu |
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 45e00afa7f2d..84044b554e33 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile | |||
@@ -9,6 +9,8 @@ obj-y += xenbus/ | |||
9 | nostackp := $(call cc-option, -fno-stack-protector) | 9 | nostackp := $(call cc-option, -fno-stack-protector) |
10 | CFLAGS_features.o := $(nostackp) | 10 | CFLAGS_features.o := $(nostackp) |
11 | 11 | ||
12 | CFLAGS_efi.o += -fshort-wchar | ||
13 | |||
12 | dom0-$(CONFIG_PCI) += pci.o | 14 | dom0-$(CONFIG_PCI) += pci.o |
13 | dom0-$(CONFIG_USB_SUPPORT) += dbgp.o | 15 | dom0-$(CONFIG_USB_SUPPORT) += dbgp.o |
14 | dom0-$(CONFIG_ACPI) += acpi.o $(xen-pad-y) | 16 | dom0-$(CONFIG_ACPI) += acpi.o $(xen-pad-y) |
@@ -33,6 +35,7 @@ obj-$(CONFIG_XEN_STUB) += xen-stub.o | |||
33 | obj-$(CONFIG_XEN_ACPI_HOTPLUG_MEMORY) += xen-acpi-memhotplug.o | 35 | obj-$(CONFIG_XEN_ACPI_HOTPLUG_MEMORY) += xen-acpi-memhotplug.o |
34 | obj-$(CONFIG_XEN_ACPI_HOTPLUG_CPU) += xen-acpi-cpuhotplug.o | 36 | obj-$(CONFIG_XEN_ACPI_HOTPLUG_CPU) += xen-acpi-cpuhotplug.o |
35 | obj-$(CONFIG_XEN_ACPI_PROCESSOR) += xen-acpi-processor.o | 37 | obj-$(CONFIG_XEN_ACPI_PROCESSOR) += xen-acpi-processor.o |
38 | obj-$(CONFIG_XEN_EFI) += efi.o | ||
36 | xen-evtchn-y := evtchn.o | 39 | xen-evtchn-y := evtchn.o |
37 | xen-gntdev-y := gntdev.o | 40 | xen-gntdev-y := gntdev.o |
38 | xen-gntalloc-y := gntalloc.o | 41 | xen-gntalloc-y := gntalloc.o |
diff --git a/drivers/xen/efi.c b/drivers/xen/efi.c new file mode 100644 index 000000000000..31f618a49661 --- /dev/null +++ b/drivers/xen/efi.c | |||
@@ -0,0 +1,368 @@ | |||
1 | /* | ||
2 | * EFI support for Xen. | ||
3 | * | ||
4 | * Copyright (C) 1999 VA Linux Systems | ||
5 | * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> | ||
6 | * Copyright (C) 1999-2002 Hewlett-Packard Co. | ||
7 | * David Mosberger-Tang <davidm@hpl.hp.com> | ||
8 | * Stephane Eranian <eranian@hpl.hp.com> | ||
9 | * Copyright (C) 2005-2008 Intel Co. | ||
10 | * Fenghua Yu <fenghua.yu@intel.com> | ||
11 | * Bibo Mao <bibo.mao@intel.com> | ||
12 | * Chandramouli Narayanan <mouli@linux.intel.com> | ||
13 | * Huang Ying <ying.huang@intel.com> | ||
14 | * Copyright (C) 2011 Novell Co. | ||
15 | * Jan Beulich <JBeulich@suse.com> | ||
16 | * Copyright (C) 2011-2012 Oracle Co. | ||
17 | * Liang Tang <liang.tang@oracle.com> | ||
18 | * Copyright (c) 2014 Oracle Co., Daniel Kiper | ||
19 | */ | ||
20 | |||
21 | #include <linux/bug.h> | ||
22 | #include <linux/efi.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/string.h> | ||
25 | |||
26 | #include <xen/interface/xen.h> | ||
27 | #include <xen/interface/platform.h> | ||
28 | #include <xen/xen.h> | ||
29 | |||
30 | #include <asm/xen/hypercall.h> | ||
31 | |||
32 | #define INIT_EFI_OP(name) \ | ||
33 | {.cmd = XENPF_efi_runtime_call, \ | ||
34 | .u.efi_runtime_call.function = XEN_EFI_##name, \ | ||
35 | .u.efi_runtime_call.misc = 0} | ||
36 | |||
37 | #define efi_data(op) (op.u.efi_runtime_call) | ||
38 | |||
39 | static efi_status_t xen_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) | ||
40 | { | ||
41 | struct xen_platform_op op = INIT_EFI_OP(get_time); | ||
42 | |||
43 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
44 | return EFI_UNSUPPORTED; | ||
45 | |||
46 | if (tm) { | ||
47 | BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.get_time.time)); | ||
48 | memcpy(tm, &efi_data(op).u.get_time.time, sizeof(*tm)); | ||
49 | } | ||
50 | |||
51 | if (tc) { | ||
52 | tc->resolution = efi_data(op).u.get_time.resolution; | ||
53 | tc->accuracy = efi_data(op).u.get_time.accuracy; | ||
54 | tc->sets_to_zero = !!(efi_data(op).misc & | ||
55 | XEN_EFI_GET_TIME_SET_CLEARS_NS); | ||
56 | } | ||
57 | |||
58 | return efi_data(op).status; | ||
59 | } | ||
60 | |||
61 | static efi_status_t xen_efi_set_time(efi_time_t *tm) | ||
62 | { | ||
63 | struct xen_platform_op op = INIT_EFI_OP(set_time); | ||
64 | |||
65 | BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.set_time)); | ||
66 | memcpy(&efi_data(op).u.set_time, tm, sizeof(*tm)); | ||
67 | |||
68 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
69 | return EFI_UNSUPPORTED; | ||
70 | |||
71 | return efi_data(op).status; | ||
72 | } | ||
73 | |||
74 | static efi_status_t xen_efi_get_wakeup_time(efi_bool_t *enabled, | ||
75 | efi_bool_t *pending, | ||
76 | efi_time_t *tm) | ||
77 | { | ||
78 | struct xen_platform_op op = INIT_EFI_OP(get_wakeup_time); | ||
79 | |||
80 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
81 | return EFI_UNSUPPORTED; | ||
82 | |||
83 | if (tm) { | ||
84 | BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.get_wakeup_time)); | ||
85 | memcpy(tm, &efi_data(op).u.get_wakeup_time, sizeof(*tm)); | ||
86 | } | ||
87 | |||
88 | if (enabled) | ||
89 | *enabled = !!(efi_data(op).misc & XEN_EFI_GET_WAKEUP_TIME_ENABLED); | ||
90 | |||
91 | if (pending) | ||
92 | *pending = !!(efi_data(op).misc & XEN_EFI_GET_WAKEUP_TIME_PENDING); | ||
93 | |||
94 | return efi_data(op).status; | ||
95 | } | ||
96 | |||
97 | static efi_status_t xen_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) | ||
98 | { | ||
99 | struct xen_platform_op op = INIT_EFI_OP(set_wakeup_time); | ||
100 | |||
101 | BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.set_wakeup_time)); | ||
102 | if (enabled) | ||
103 | efi_data(op).misc = XEN_EFI_SET_WAKEUP_TIME_ENABLE; | ||
104 | if (tm) | ||
105 | memcpy(&efi_data(op).u.set_wakeup_time, tm, sizeof(*tm)); | ||
106 | else | ||
107 | efi_data(op).misc |= XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY; | ||
108 | |||
109 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
110 | return EFI_UNSUPPORTED; | ||
111 | |||
112 | return efi_data(op).status; | ||
113 | } | ||
114 | |||
115 | static efi_status_t xen_efi_get_variable(efi_char16_t *name, | ||
116 | efi_guid_t *vendor, | ||
117 | u32 *attr, | ||
118 | unsigned long *data_size, | ||
119 | void *data) | ||
120 | { | ||
121 | struct xen_platform_op op = INIT_EFI_OP(get_variable); | ||
122 | |||
123 | set_xen_guest_handle(efi_data(op).u.get_variable.name, name); | ||
124 | BUILD_BUG_ON(sizeof(*vendor) != | ||
125 | sizeof(efi_data(op).u.get_variable.vendor_guid)); | ||
126 | memcpy(&efi_data(op).u.get_variable.vendor_guid, vendor, sizeof(*vendor)); | ||
127 | efi_data(op).u.get_variable.size = *data_size; | ||
128 | set_xen_guest_handle(efi_data(op).u.get_variable.data, data); | ||
129 | |||
130 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
131 | return EFI_UNSUPPORTED; | ||
132 | |||
133 | *data_size = efi_data(op).u.get_variable.size; | ||
134 | if (attr) | ||
135 | *attr = efi_data(op).misc; | ||
136 | |||
137 | return efi_data(op).status; | ||
138 | } | ||
139 | |||
140 | static efi_status_t xen_efi_get_next_variable(unsigned long *name_size, | ||
141 | efi_char16_t *name, | ||
142 | efi_guid_t *vendor) | ||
143 | { | ||
144 | struct xen_platform_op op = INIT_EFI_OP(get_next_variable_name); | ||
145 | |||
146 | efi_data(op).u.get_next_variable_name.size = *name_size; | ||
147 | set_xen_guest_handle(efi_data(op).u.get_next_variable_name.name, name); | ||
148 | BUILD_BUG_ON(sizeof(*vendor) != | ||
149 | sizeof(efi_data(op).u.get_next_variable_name.vendor_guid)); | ||
150 | memcpy(&efi_data(op).u.get_next_variable_name.vendor_guid, vendor, | ||
151 | sizeof(*vendor)); | ||
152 | |||
153 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
154 | return EFI_UNSUPPORTED; | ||
155 | |||
156 | *name_size = efi_data(op).u.get_next_variable_name.size; | ||
157 | memcpy(vendor, &efi_data(op).u.get_next_variable_name.vendor_guid, | ||
158 | sizeof(*vendor)); | ||
159 | |||
160 | return efi_data(op).status; | ||
161 | } | ||
162 | |||
163 | static efi_status_t xen_efi_set_variable(efi_char16_t *name, | ||
164 | efi_guid_t *vendor, | ||
165 | u32 attr, | ||
166 | unsigned long data_size, | ||
167 | void *data) | ||
168 | { | ||
169 | struct xen_platform_op op = INIT_EFI_OP(set_variable); | ||
170 | |||
171 | set_xen_guest_handle(efi_data(op).u.set_variable.name, name); | ||
172 | efi_data(op).misc = attr; | ||
173 | BUILD_BUG_ON(sizeof(*vendor) != | ||
174 | sizeof(efi_data(op).u.set_variable.vendor_guid)); | ||
175 | memcpy(&efi_data(op).u.set_variable.vendor_guid, vendor, sizeof(*vendor)); | ||
176 | efi_data(op).u.set_variable.size = data_size; | ||
177 | set_xen_guest_handle(efi_data(op).u.set_variable.data, data); | ||
178 | |||
179 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
180 | return EFI_UNSUPPORTED; | ||
181 | |||
182 | return efi_data(op).status; | ||
183 | } | ||
184 | |||
185 | static efi_status_t xen_efi_query_variable_info(u32 attr, | ||
186 | u64 *storage_space, | ||
187 | u64 *remaining_space, | ||
188 | u64 *max_variable_size) | ||
189 | { | ||
190 | struct xen_platform_op op = INIT_EFI_OP(query_variable_info); | ||
191 | |||
192 | if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) | ||
193 | return EFI_UNSUPPORTED; | ||
194 | |||
195 | efi_data(op).u.query_variable_info.attr = attr; | ||
196 | |||
197 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
198 | return EFI_UNSUPPORTED; | ||
199 | |||
200 | *storage_space = efi_data(op).u.query_variable_info.max_store_size; | ||
201 | *remaining_space = efi_data(op).u.query_variable_info.remain_store_size; | ||
202 | *max_variable_size = efi_data(op).u.query_variable_info.max_size; | ||
203 | |||
204 | return efi_data(op).status; | ||
205 | } | ||
206 | |||
207 | static efi_status_t xen_efi_get_next_high_mono_count(u32 *count) | ||
208 | { | ||
209 | struct xen_platform_op op = INIT_EFI_OP(get_next_high_monotonic_count); | ||
210 | |||
211 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
212 | return EFI_UNSUPPORTED; | ||
213 | |||
214 | *count = efi_data(op).misc; | ||
215 | |||
216 | return efi_data(op).status; | ||
217 | } | ||
218 | |||
219 | static efi_status_t xen_efi_update_capsule(efi_capsule_header_t **capsules, | ||
220 | unsigned long count, | ||
221 | unsigned long sg_list) | ||
222 | { | ||
223 | struct xen_platform_op op = INIT_EFI_OP(update_capsule); | ||
224 | |||
225 | if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) | ||
226 | return EFI_UNSUPPORTED; | ||
227 | |||
228 | set_xen_guest_handle(efi_data(op).u.update_capsule.capsule_header_array, | ||
229 | capsules); | ||
230 | efi_data(op).u.update_capsule.capsule_count = count; | ||
231 | efi_data(op).u.update_capsule.sg_list = sg_list; | ||
232 | |||
233 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
234 | return EFI_UNSUPPORTED; | ||
235 | |||
236 | return efi_data(op).status; | ||
237 | } | ||
238 | |||
239 | static efi_status_t xen_efi_query_capsule_caps(efi_capsule_header_t **capsules, | ||
240 | unsigned long count, | ||
241 | u64 *max_size, | ||
242 | int *reset_type) | ||
243 | { | ||
244 | struct xen_platform_op op = INIT_EFI_OP(query_capsule_capabilities); | ||
245 | |||
246 | if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) | ||
247 | return EFI_UNSUPPORTED; | ||
248 | |||
249 | set_xen_guest_handle(efi_data(op).u.query_capsule_capabilities.capsule_header_array, | ||
250 | capsules); | ||
251 | efi_data(op).u.query_capsule_capabilities.capsule_count = count; | ||
252 | |||
253 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
254 | return EFI_UNSUPPORTED; | ||
255 | |||
256 | *max_size = efi_data(op).u.query_capsule_capabilities.max_capsule_size; | ||
257 | *reset_type = efi_data(op).u.query_capsule_capabilities.reset_type; | ||
258 | |||
259 | return efi_data(op).status; | ||
260 | } | ||
261 | |||
262 | static efi_char16_t vendor[100] __initdata; | ||
263 | |||
264 | static efi_system_table_t efi_systab_xen __initdata = { | ||
265 | .hdr = { | ||
266 | .signature = EFI_SYSTEM_TABLE_SIGNATURE, | ||
267 | .revision = 0, /* Initialized later. */ | ||
268 | .headersize = 0, /* Ignored by Linux Kernel. */ | ||
269 | .crc32 = 0, /* Ignored by Linux Kernel. */ | ||
270 | .reserved = 0 | ||
271 | }, | ||
272 | .fw_vendor = EFI_INVALID_TABLE_ADDR, /* Initialized later. */ | ||
273 | .fw_revision = 0, /* Initialized later. */ | ||
274 | .con_in_handle = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ | ||
275 | .con_in = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ | ||
276 | .con_out_handle = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ | ||
277 | .con_out = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ | ||
278 | .stderr_handle = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ | ||
279 | .stderr = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ | ||
280 | .runtime = (efi_runtime_services_t *)EFI_INVALID_TABLE_ADDR, | ||
281 | /* Not used under Xen. */ | ||
282 | .boottime = (efi_boot_services_t *)EFI_INVALID_TABLE_ADDR, | ||
283 | /* Not used under Xen. */ | ||
284 | .nr_tables = 0, /* Initialized later. */ | ||
285 | .tables = EFI_INVALID_TABLE_ADDR /* Initialized later. */ | ||
286 | }; | ||
287 | |||
288 | static const struct efi efi_xen __initconst = { | ||
289 | .systab = NULL, /* Initialized later. */ | ||
290 | .runtime_version = 0, /* Initialized later. */ | ||
291 | .mps = EFI_INVALID_TABLE_ADDR, | ||
292 | .acpi = EFI_INVALID_TABLE_ADDR, | ||
293 | .acpi20 = EFI_INVALID_TABLE_ADDR, | ||
294 | .smbios = EFI_INVALID_TABLE_ADDR, | ||
295 | .sal_systab = EFI_INVALID_TABLE_ADDR, | ||
296 | .boot_info = EFI_INVALID_TABLE_ADDR, | ||
297 | .hcdp = EFI_INVALID_TABLE_ADDR, | ||
298 | .uga = EFI_INVALID_TABLE_ADDR, | ||
299 | .uv_systab = EFI_INVALID_TABLE_ADDR, | ||
300 | .fw_vendor = EFI_INVALID_TABLE_ADDR, | ||
301 | .runtime = EFI_INVALID_TABLE_ADDR, | ||
302 | .config_table = EFI_INVALID_TABLE_ADDR, | ||
303 | .get_time = xen_efi_get_time, | ||
304 | .set_time = xen_efi_set_time, | ||
305 | .get_wakeup_time = xen_efi_get_wakeup_time, | ||
306 | .set_wakeup_time = xen_efi_set_wakeup_time, | ||
307 | .get_variable = xen_efi_get_variable, | ||
308 | .get_next_variable = xen_efi_get_next_variable, | ||
309 | .set_variable = xen_efi_set_variable, | ||
310 | .query_variable_info = xen_efi_query_variable_info, | ||
311 | .update_capsule = xen_efi_update_capsule, | ||
312 | .query_capsule_caps = xen_efi_query_capsule_caps, | ||
313 | .get_next_high_mono_count = xen_efi_get_next_high_mono_count, | ||
314 | .reset_system = NULL, /* Functionality provided by Xen. */ | ||
315 | .set_virtual_address_map = NULL, /* Not used under Xen. */ | ||
316 | .memmap = NULL, /* Not used under Xen. */ | ||
317 | .flags = 0 /* Initialized later. */ | ||
318 | }; | ||
319 | |||
320 | efi_system_table_t __init *xen_efi_probe(void) | ||
321 | { | ||
322 | struct xen_platform_op op = { | ||
323 | .cmd = XENPF_firmware_info, | ||
324 | .u.firmware_info = { | ||
325 | .type = XEN_FW_EFI_INFO, | ||
326 | .index = XEN_FW_EFI_CONFIG_TABLE | ||
327 | } | ||
328 | }; | ||
329 | union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info; | ||
330 | |||
331 | if (!xen_initial_domain() || HYPERVISOR_dom0_op(&op) < 0) | ||
332 | return NULL; | ||
333 | |||
334 | /* Here we know that Xen runs on EFI platform. */ | ||
335 | |||
336 | efi = efi_xen; | ||
337 | |||
338 | efi_systab_xen.tables = info->cfg.addr; | ||
339 | efi_systab_xen.nr_tables = info->cfg.nent; | ||
340 | |||
341 | op.cmd = XENPF_firmware_info; | ||
342 | op.u.firmware_info.type = XEN_FW_EFI_INFO; | ||
343 | op.u.firmware_info.index = XEN_FW_EFI_VENDOR; | ||
344 | info->vendor.bufsz = sizeof(vendor); | ||
345 | set_xen_guest_handle(info->vendor.name, vendor); | ||
346 | |||
347 | if (HYPERVISOR_dom0_op(&op) == 0) { | ||
348 | efi_systab_xen.fw_vendor = __pa_symbol(vendor); | ||
349 | efi_systab_xen.fw_revision = info->vendor.revision; | ||
350 | } else | ||
351 | efi_systab_xen.fw_vendor = __pa_symbol(L"UNKNOWN"); | ||
352 | |||
353 | op.cmd = XENPF_firmware_info; | ||
354 | op.u.firmware_info.type = XEN_FW_EFI_INFO; | ||
355 | op.u.firmware_info.index = XEN_FW_EFI_VERSION; | ||
356 | |||
357 | if (HYPERVISOR_dom0_op(&op) == 0) | ||
358 | efi_systab_xen.hdr.revision = info->version; | ||
359 | |||
360 | op.cmd = XENPF_firmware_info; | ||
361 | op.u.firmware_info.type = XEN_FW_EFI_INFO; | ||
362 | op.u.firmware_info.index = XEN_FW_EFI_RT_VERSION; | ||
363 | |||
364 | if (HYPERVISOR_dom0_op(&op) == 0) | ||
365 | efi.runtime_version = info->version; | ||
366 | |||
367 | return &efi_systab_xen; | ||
368 | } | ||
diff --git a/include/linux/efi.h b/include/linux/efi.h index 41bbf8ba4ba8..efc681fd5895 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/ioport.h> | 20 | #include <linux/ioport.h> |
21 | #include <linux/pfn.h> | 21 | #include <linux/pfn.h> |
22 | #include <linux/pstore.h> | 22 | #include <linux/pstore.h> |
23 | #include <linux/reboot.h> | ||
23 | 24 | ||
24 | #include <asm/page.h> | 25 | #include <asm/page.h> |
25 | 26 | ||
@@ -521,6 +522,8 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, | |||
521 | int *reset_type); | 522 | int *reset_type); |
522 | typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long size); | 523 | typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long size); |
523 | 524 | ||
525 | void efi_native_runtime_setup(void); | ||
526 | |||
524 | /* | 527 | /* |
525 | * EFI Configuration Table and GUID definitions | 528 | * EFI Configuration Table and GUID definitions |
526 | */ | 529 | */ |
@@ -870,11 +873,13 @@ extern int __init efi_uart_console_only (void); | |||
870 | extern void efi_initialize_iomem_resources(struct resource *code_resource, | 873 | extern void efi_initialize_iomem_resources(struct resource *code_resource, |
871 | struct resource *data_resource, struct resource *bss_resource); | 874 | struct resource *data_resource, struct resource *bss_resource); |
872 | extern void efi_get_time(struct timespec *now); | 875 | extern void efi_get_time(struct timespec *now); |
873 | extern int efi_set_rtc_mmss(const struct timespec *now); | ||
874 | extern void efi_reserve_boot_services(void); | 876 | extern void efi_reserve_boot_services(void); |
875 | extern int efi_get_fdt_params(struct efi_fdt_params *params, int verbose); | 877 | extern int efi_get_fdt_params(struct efi_fdt_params *params, int verbose); |
876 | extern struct efi_memory_map memmap; | 878 | extern struct efi_memory_map memmap; |
877 | 879 | ||
880 | extern int efi_reboot_quirk_mode; | ||
881 | extern bool efi_poweroff_required(void); | ||
882 | |||
878 | /* Iterate through an efi_memory_map */ | 883 | /* Iterate through an efi_memory_map */ |
879 | #define for_each_efi_memory_desc(m, md) \ | 884 | #define for_each_efi_memory_desc(m, md) \ |
880 | for ((md) = (m)->map; \ | 885 | for ((md) = (m)->map; \ |
@@ -916,7 +921,8 @@ extern int __init efi_setup_pcdp_console(char *); | |||
916 | #define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */ | 921 | #define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */ |
917 | #define EFI_MEMMAP 4 /* Can we use EFI memory map? */ | 922 | #define EFI_MEMMAP 4 /* Can we use EFI memory map? */ |
918 | #define EFI_64BIT 5 /* Is the firmware 64-bit? */ | 923 | #define EFI_64BIT 5 /* Is the firmware 64-bit? */ |
919 | #define EFI_ARCH_1 6 /* First arch-specific bit */ | 924 | #define EFI_PARAVIRT 6 /* Access is via a paravirt interface */ |
925 | #define EFI_ARCH_1 7 /* First arch-specific bit */ | ||
920 | 926 | ||
921 | #ifdef CONFIG_EFI | 927 | #ifdef CONFIG_EFI |
922 | /* | 928 | /* |
@@ -926,11 +932,14 @@ static inline bool efi_enabled(int feature) | |||
926 | { | 932 | { |
927 | return test_bit(feature, &efi.flags) != 0; | 933 | return test_bit(feature, &efi.flags) != 0; |
928 | } | 934 | } |
935 | extern void efi_reboot(enum reboot_mode reboot_mode, const char *__unused); | ||
929 | #else | 936 | #else |
930 | static inline bool efi_enabled(int feature) | 937 | static inline bool efi_enabled(int feature) |
931 | { | 938 | { |
932 | return false; | 939 | return false; |
933 | } | 940 | } |
941 | static inline void | ||
942 | efi_reboot(enum reboot_mode reboot_mode, const char *__unused) {} | ||
934 | #endif | 943 | #endif |
935 | 944 | ||
936 | /* | 945 | /* |
@@ -1031,12 +1040,8 @@ struct efivar_operations { | |||
1031 | struct efivars { | 1040 | struct efivars { |
1032 | /* | 1041 | /* |
1033 | * ->lock protects two things: | 1042 | * ->lock protects two things: |
1034 | * 1) ->list - adds, removals, reads, writes | 1043 | * 1) efivarfs_list and efivars_sysfs_list |
1035 | * 2) ops.[gs]et_variable() calls. | 1044 | * 2) ->ops calls |
1036 | * It must not be held when creating sysfs entries or calling kmalloc. | ||
1037 | * ops.get_next_variable() is only called from register_efivars() | ||
1038 | * or efivar_update_sysfs_entries(), | ||
1039 | * which is protected by the BKL, so that path is safe. | ||
1040 | */ | 1045 | */ |
1041 | spinlock_t lock; | 1046 | spinlock_t lock; |
1042 | struct kset *kset; | 1047 | struct kset *kset; |
@@ -1161,4 +1166,46 @@ static inline void | |||
1161 | efi_runtime_map_setup(void *map, int nr_entries, u32 desc_size) {} | 1166 | efi_runtime_map_setup(void *map, int nr_entries, u32 desc_size) {} |
1162 | #endif | 1167 | #endif |
1163 | 1168 | ||
1169 | /* prototypes shared between arch specific and generic stub code */ | ||
1170 | |||
1171 | #define pr_efi(sys_table, msg) efi_printk(sys_table, "EFI stub: "msg) | ||
1172 | #define pr_efi_err(sys_table, msg) efi_printk(sys_table, "EFI stub: ERROR: "msg) | ||
1173 | |||
1174 | void efi_printk(efi_system_table_t *sys_table_arg, char *str); | ||
1175 | |||
1176 | void efi_free(efi_system_table_t *sys_table_arg, unsigned long size, | ||
1177 | unsigned long addr); | ||
1178 | |||
1179 | char *efi_convert_cmdline(efi_system_table_t *sys_table_arg, | ||
1180 | efi_loaded_image_t *image, int *cmd_line_len); | ||
1181 | |||
1182 | efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg, | ||
1183 | efi_memory_desc_t **map, | ||
1184 | unsigned long *map_size, | ||
1185 | unsigned long *desc_size, | ||
1186 | u32 *desc_ver, | ||
1187 | unsigned long *key_ptr); | ||
1188 | |||
1189 | efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg, | ||
1190 | unsigned long size, unsigned long align, | ||
1191 | unsigned long *addr); | ||
1192 | |||
1193 | efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg, | ||
1194 | unsigned long size, unsigned long align, | ||
1195 | unsigned long *addr, unsigned long max); | ||
1196 | |||
1197 | efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg, | ||
1198 | unsigned long *image_addr, | ||
1199 | unsigned long image_size, | ||
1200 | unsigned long alloc_size, | ||
1201 | unsigned long preferred_addr, | ||
1202 | unsigned long alignment); | ||
1203 | |||
1204 | efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, | ||
1205 | efi_loaded_image_t *image, | ||
1206 | char *cmd_line, char *option_string, | ||
1207 | unsigned long max_addr, | ||
1208 | unsigned long *load_addr, | ||
1209 | unsigned long *load_size); | ||
1210 | |||
1164 | #endif /* _LINUX_EFI_H */ | 1211 | #endif /* _LINUX_EFI_H */ |
diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h index f1331e3e7271..5cc49ea8d840 100644 --- a/include/xen/interface/platform.h +++ b/include/xen/interface/platform.h | |||
@@ -108,11 +108,113 @@ struct xenpf_platform_quirk { | |||
108 | }; | 108 | }; |
109 | DEFINE_GUEST_HANDLE_STRUCT(xenpf_platform_quirk_t); | 109 | DEFINE_GUEST_HANDLE_STRUCT(xenpf_platform_quirk_t); |
110 | 110 | ||
111 | #define XENPF_efi_runtime_call 49 | ||
112 | #define XEN_EFI_get_time 1 | ||
113 | #define XEN_EFI_set_time 2 | ||
114 | #define XEN_EFI_get_wakeup_time 3 | ||
115 | #define XEN_EFI_set_wakeup_time 4 | ||
116 | #define XEN_EFI_get_next_high_monotonic_count 5 | ||
117 | #define XEN_EFI_get_variable 6 | ||
118 | #define XEN_EFI_set_variable 7 | ||
119 | #define XEN_EFI_get_next_variable_name 8 | ||
120 | #define XEN_EFI_query_variable_info 9 | ||
121 | #define XEN_EFI_query_capsule_capabilities 10 | ||
122 | #define XEN_EFI_update_capsule 11 | ||
123 | |||
124 | struct xenpf_efi_runtime_call { | ||
125 | uint32_t function; | ||
126 | /* | ||
127 | * This field is generally used for per sub-function flags (defined | ||
128 | * below), except for the XEN_EFI_get_next_high_monotonic_count case, | ||
129 | * where it holds the single returned value. | ||
130 | */ | ||
131 | uint32_t misc; | ||
132 | xen_ulong_t status; | ||
133 | union { | ||
134 | #define XEN_EFI_GET_TIME_SET_CLEARS_NS 0x00000001 | ||
135 | struct { | ||
136 | struct xenpf_efi_time { | ||
137 | uint16_t year; | ||
138 | uint8_t month; | ||
139 | uint8_t day; | ||
140 | uint8_t hour; | ||
141 | uint8_t min; | ||
142 | uint8_t sec; | ||
143 | uint32_t ns; | ||
144 | int16_t tz; | ||
145 | uint8_t daylight; | ||
146 | } time; | ||
147 | uint32_t resolution; | ||
148 | uint32_t accuracy; | ||
149 | } get_time; | ||
150 | |||
151 | struct xenpf_efi_time set_time; | ||
152 | |||
153 | #define XEN_EFI_GET_WAKEUP_TIME_ENABLED 0x00000001 | ||
154 | #define XEN_EFI_GET_WAKEUP_TIME_PENDING 0x00000002 | ||
155 | struct xenpf_efi_time get_wakeup_time; | ||
156 | |||
157 | #define XEN_EFI_SET_WAKEUP_TIME_ENABLE 0x00000001 | ||
158 | #define XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY 0x00000002 | ||
159 | struct xenpf_efi_time set_wakeup_time; | ||
160 | |||
161 | #define XEN_EFI_VARIABLE_NON_VOLATILE 0x00000001 | ||
162 | #define XEN_EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 | ||
163 | #define XEN_EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 | ||
164 | struct { | ||
165 | GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */ | ||
166 | xen_ulong_t size; | ||
167 | GUEST_HANDLE(void) data; | ||
168 | struct xenpf_efi_guid { | ||
169 | uint32_t data1; | ||
170 | uint16_t data2; | ||
171 | uint16_t data3; | ||
172 | uint8_t data4[8]; | ||
173 | } vendor_guid; | ||
174 | } get_variable, set_variable; | ||
175 | |||
176 | struct { | ||
177 | xen_ulong_t size; | ||
178 | GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */ | ||
179 | struct xenpf_efi_guid vendor_guid; | ||
180 | } get_next_variable_name; | ||
181 | |||
182 | struct { | ||
183 | uint32_t attr; | ||
184 | uint64_t max_store_size; | ||
185 | uint64_t remain_store_size; | ||
186 | uint64_t max_size; | ||
187 | } query_variable_info; | ||
188 | |||
189 | struct { | ||
190 | GUEST_HANDLE(void) capsule_header_array; | ||
191 | xen_ulong_t capsule_count; | ||
192 | uint64_t max_capsule_size; | ||
193 | uint32_t reset_type; | ||
194 | } query_capsule_capabilities; | ||
195 | |||
196 | struct { | ||
197 | GUEST_HANDLE(void) capsule_header_array; | ||
198 | xen_ulong_t capsule_count; | ||
199 | uint64_t sg_list; /* machine address */ | ||
200 | } update_capsule; | ||
201 | } u; | ||
202 | }; | ||
203 | DEFINE_GUEST_HANDLE_STRUCT(xenpf_efi_runtime_call); | ||
204 | |||
205 | #define XEN_FW_EFI_VERSION 0 | ||
206 | #define XEN_FW_EFI_CONFIG_TABLE 1 | ||
207 | #define XEN_FW_EFI_VENDOR 2 | ||
208 | #define XEN_FW_EFI_MEM_INFO 3 | ||
209 | #define XEN_FW_EFI_RT_VERSION 4 | ||
210 | |||
111 | #define XENPF_firmware_info 50 | 211 | #define XENPF_firmware_info 50 |
112 | #define XEN_FW_DISK_INFO 1 /* from int 13 AH=08/41/48 */ | 212 | #define XEN_FW_DISK_INFO 1 /* from int 13 AH=08/41/48 */ |
113 | #define XEN_FW_DISK_MBR_SIGNATURE 2 /* from MBR offset 0x1b8 */ | 213 | #define XEN_FW_DISK_MBR_SIGNATURE 2 /* from MBR offset 0x1b8 */ |
114 | #define XEN_FW_VBEDDC_INFO 3 /* from int 10 AX=4f15 */ | 214 | #define XEN_FW_VBEDDC_INFO 3 /* from int 10 AX=4f15 */ |
215 | #define XEN_FW_EFI_INFO 4 /* from EFI */ | ||
115 | #define XEN_FW_KBD_SHIFT_FLAGS 5 /* Int16, Fn02: Get keyboard shift flags. */ | 216 | #define XEN_FW_KBD_SHIFT_FLAGS 5 /* Int16, Fn02: Get keyboard shift flags. */ |
217 | |||
116 | struct xenpf_firmware_info { | 218 | struct xenpf_firmware_info { |
117 | /* IN variables. */ | 219 | /* IN variables. */ |
118 | uint32_t type; | 220 | uint32_t type; |
@@ -144,6 +246,26 @@ struct xenpf_firmware_info { | |||
144 | GUEST_HANDLE(uchar) edid; | 246 | GUEST_HANDLE(uchar) edid; |
145 | } vbeddc_info; /* XEN_FW_VBEDDC_INFO */ | 247 | } vbeddc_info; /* XEN_FW_VBEDDC_INFO */ |
146 | 248 | ||
249 | union xenpf_efi_info { | ||
250 | uint32_t version; | ||
251 | struct { | ||
252 | uint64_t addr; /* EFI_CONFIGURATION_TABLE */ | ||
253 | uint32_t nent; | ||
254 | } cfg; | ||
255 | struct { | ||
256 | uint32_t revision; | ||
257 | uint32_t bufsz; /* input, in bytes */ | ||
258 | GUEST_HANDLE(void) name; | ||
259 | /* UCS-2/UTF-16 string */ | ||
260 | } vendor; | ||
261 | struct { | ||
262 | uint64_t addr; | ||
263 | uint64_t size; | ||
264 | uint64_t attr; | ||
265 | uint32_t type; | ||
266 | } mem; | ||
267 | } efi_info; /* XEN_FW_EFI_INFO */ | ||
268 | |||
147 | uint8_t kbd_shift_flags; /* XEN_FW_KBD_SHIFT_FLAGS */ | 269 | uint8_t kbd_shift_flags; /* XEN_FW_KBD_SHIFT_FLAGS */ |
148 | } u; | 270 | } u; |
149 | }; | 271 | }; |
@@ -362,6 +484,7 @@ struct xen_platform_op { | |||
362 | struct xenpf_read_memtype read_memtype; | 484 | struct xenpf_read_memtype read_memtype; |
363 | struct xenpf_microcode_update microcode; | 485 | struct xenpf_microcode_update microcode; |
364 | struct xenpf_platform_quirk platform_quirk; | 486 | struct xenpf_platform_quirk platform_quirk; |
487 | struct xenpf_efi_runtime_call efi_runtime_call; | ||
365 | struct xenpf_firmware_info firmware_info; | 488 | struct xenpf_firmware_info firmware_info; |
366 | struct xenpf_enter_acpi_sleep enter_acpi_sleep; | 489 | struct xenpf_enter_acpi_sleep enter_acpi_sleep; |
367 | struct xenpf_change_freq change_freq; | 490 | struct xenpf_change_freq change_freq; |
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h index 0b3149ed7eaa..7491ee5d8164 100644 --- a/include/xen/xen-ops.h +++ b/include/xen/xen-ops.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <linux/percpu.h> | 4 | #include <linux/percpu.h> |
5 | #include <linux/notifier.h> | 5 | #include <linux/notifier.h> |
6 | #include <linux/efi.h> | ||
6 | #include <asm/xen/interface.h> | 7 | #include <asm/xen/interface.h> |
7 | 8 | ||
8 | DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu); | 9 | DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu); |
@@ -35,4 +36,14 @@ int xen_unmap_domain_mfn_range(struct vm_area_struct *vma, | |||
35 | int numpgs, struct page **pages); | 36 | int numpgs, struct page **pages); |
36 | 37 | ||
37 | bool xen_running_on_version_or_later(unsigned int major, unsigned int minor); | 38 | bool xen_running_on_version_or_later(unsigned int major, unsigned int minor); |
39 | |||
40 | #ifdef CONFIG_XEN_EFI | ||
41 | extern efi_system_table_t *xen_efi_probe(void); | ||
42 | #else | ||
43 | static inline efi_system_table_t __init *xen_efi_probe(void) | ||
44 | { | ||
45 | return NULL; | ||
46 | } | ||
47 | #endif | ||
48 | |||
38 | #endif /* INCLUDE_XEN_OPS_H */ | 49 | #endif /* INCLUDE_XEN_OPS_H */ |