diff options
| -rw-r--r-- | arch/x86/include/asm/efi.h | 21 | ||||
| -rw-r--r-- | arch/x86/platform/efi/Makefile | 1 | ||||
| -rw-r--r-- | arch/x86/platform/efi/efi.c | 127 | ||||
| -rw-r--r-- | arch/x86/platform/efi/efi_64.c | 335 | ||||
| -rw-r--r-- | arch/x86/platform/efi/efi_stub_64.S | 1 | ||||
| -rw-r--r-- | arch/x86/platform/efi/efi_thunk_64.S | 65 |
6 files changed, 517 insertions, 33 deletions
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 85856868507b..85935e6f69f3 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h | |||
| @@ -154,6 +154,27 @@ static inline bool efi_is_native(void) | |||
| 154 | 154 | ||
| 155 | extern struct console early_efi_console; | 155 | extern struct console early_efi_console; |
| 156 | extern void parse_efi_setup(u64 phys_addr, u32 data_len); | 156 | extern void parse_efi_setup(u64 phys_addr, u32 data_len); |
| 157 | |||
| 158 | #ifdef CONFIG_EFI_MIXED | ||
| 159 | extern void efi_thunk_runtime_setup(void); | ||
| 160 | extern efi_status_t efi_thunk_set_virtual_address_map( | ||
| 161 | void *phys_set_virtual_address_map, | ||
| 162 | unsigned long memory_map_size, | ||
| 163 | unsigned long descriptor_size, | ||
| 164 | u32 descriptor_version, | ||
| 165 | efi_memory_desc_t *virtual_map); | ||
| 166 | #else | ||
| 167 | static inline void efi_thunk_runtime_setup(void) {} | ||
| 168 | static inline efi_status_t efi_thunk_set_virtual_address_map( | ||
| 169 | void *phys_set_virtual_address_map, | ||
| 170 | unsigned long memory_map_size, | ||
| 171 | unsigned long descriptor_size, | ||
| 172 | u32 descriptor_version, | ||
| 173 | efi_memory_desc_t *virtual_map) | ||
| 174 | { | ||
| 175 | return EFI_SUCCESS; | ||
| 176 | } | ||
| 177 | #endif /* CONFIG_EFI_MIXED */ | ||
| 157 | #else | 178 | #else |
| 158 | /* | 179 | /* |
| 159 | * IF EFI is not configured, have the EFI calls return -ENOSYS. | 180 | * IF EFI is not configured, have the EFI calls return -ENOSYS. |
diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile index b7b0b35c1981..d51045afcaaf 100644 --- a/arch/x86/platform/efi/Makefile +++ b/arch/x86/platform/efi/Makefile | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o | 1 | obj-$(CONFIG_EFI) += 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 | ||
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index b96ae7918a16..39f5b7bba695 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c | |||
| @@ -588,37 +588,85 @@ static int __init efi_systab_init(void *phys) | |||
| 588 | return 0; | 588 | return 0; |
| 589 | } | 589 | } |
| 590 | 590 | ||
| 591 | static int __init efi_runtime_init(void) | 591 | static int __init efi_runtime_init32(void) |
| 592 | { | 592 | { |
| 593 | efi_runtime_services_t *runtime; | 593 | efi_runtime_services_32_t *runtime; |
| 594 | |||
| 595 | runtime = early_ioremap((unsigned long)efi.systab->runtime, | ||
| 596 | sizeof(efi_runtime_services_32_t)); | ||
| 597 | if (!runtime) { | ||
| 598 | pr_err("Could not map the runtime service table!\n"); | ||
| 599 | return -ENOMEM; | ||
| 600 | } | ||
| 594 | 601 | ||
| 595 | /* | 602 | /* |
| 596 | * Check out the runtime services table. We need to map | 603 | * We will only need *early* access to the following two |
| 597 | * the runtime services table so that we can grab the physical | 604 | * EFI runtime services before set_virtual_address_map |
| 598 | * address of several of the EFI runtime functions, needed to | 605 | * is invoked. |
| 599 | * set the firmware into virtual mode. | ||
| 600 | */ | 606 | */ |
| 607 | efi_phys.get_time = (efi_get_time_t *) | ||
| 608 | (unsigned long)runtime->get_time; | ||
| 609 | efi_phys.set_virtual_address_map = | ||
| 610 | (efi_set_virtual_address_map_t *) | ||
| 611 | (unsigned long)runtime->set_virtual_address_map; | ||
| 612 | /* | ||
| 613 | * Make efi_get_time can be called before entering | ||
| 614 | * virtual mode. | ||
| 615 | */ | ||
| 616 | efi.get_time = phys_efi_get_time; | ||
| 617 | early_iounmap(runtime, sizeof(efi_runtime_services_32_t)); | ||
| 618 | |||
| 619 | return 0; | ||
| 620 | } | ||
| 621 | |||
| 622 | static int __init efi_runtime_init64(void) | ||
| 623 | { | ||
| 624 | efi_runtime_services_64_t *runtime; | ||
| 625 | |||
| 601 | runtime = early_ioremap((unsigned long)efi.systab->runtime, | 626 | runtime = early_ioremap((unsigned long)efi.systab->runtime, |
| 602 | sizeof(efi_runtime_services_t)); | 627 | sizeof(efi_runtime_services_64_t)); |
| 603 | if (!runtime) { | 628 | if (!runtime) { |
| 604 | pr_err("Could not map the runtime service table!\n"); | 629 | pr_err("Could not map the runtime service table!\n"); |
| 605 | return -ENOMEM; | 630 | return -ENOMEM; |
| 606 | } | 631 | } |
| 632 | |||
| 607 | /* | 633 | /* |
| 608 | * We will only need *early* access to the following | 634 | * We will only need *early* access to the following two |
| 609 | * two EFI runtime services before set_virtual_address_map | 635 | * EFI runtime services before set_virtual_address_map |
| 610 | * is invoked. | 636 | * is invoked. |
| 611 | */ | 637 | */ |
| 612 | efi_phys.get_time = (efi_get_time_t *)runtime->get_time; | 638 | efi_phys.get_time = (efi_get_time_t *) |
| 639 | (unsigned long)runtime->get_time; | ||
| 613 | efi_phys.set_virtual_address_map = | 640 | efi_phys.set_virtual_address_map = |
| 614 | (efi_set_virtual_address_map_t *) | 641 | (efi_set_virtual_address_map_t *) |
| 615 | runtime->set_virtual_address_map; | 642 | (unsigned long)runtime->set_virtual_address_map; |
| 616 | /* | 643 | /* |
| 617 | * Make efi_get_time can be called before entering | 644 | * Make efi_get_time can be called before entering |
| 618 | * virtual mode. | 645 | * virtual mode. |
| 619 | */ | 646 | */ |
| 620 | efi.get_time = phys_efi_get_time; | 647 | efi.get_time = phys_efi_get_time; |
| 621 | early_iounmap(runtime, sizeof(efi_runtime_services_t)); | 648 | early_iounmap(runtime, sizeof(efi_runtime_services_64_t)); |
| 649 | |||
| 650 | return 0; | ||
| 651 | } | ||
| 652 | |||
| 653 | static int __init efi_runtime_init(void) | ||
| 654 | { | ||
| 655 | int rv; | ||
| 656 | |||
| 657 | /* | ||
| 658 | * Check out the runtime services table. We need to map | ||
| 659 | * the runtime services table so that we can grab the physical | ||
| 660 | * address of several of the EFI runtime functions, needed to | ||
| 661 | * set the firmware into virtual mode. | ||
| 662 | */ | ||
| 663 | if (efi_enabled(EFI_64BIT)) | ||
| 664 | rv = efi_runtime_init64(); | ||
| 665 | else | ||
| 666 | rv = efi_runtime_init32(); | ||
| 667 | |||
| 668 | if (rv) | ||
| 669 | return rv; | ||
| 622 | 670 | ||
| 623 | return 0; | 671 | return 0; |
| 624 | } | 672 | } |
| @@ -841,6 +889,22 @@ void __init old_map_region(efi_memory_desc_t *md) | |||
| 841 | (unsigned long long)md->phys_addr); | 889 | (unsigned long long)md->phys_addr); |
| 842 | } | 890 | } |
| 843 | 891 | ||
| 892 | static void native_runtime_setup(void) | ||
| 893 | { | ||
| 894 | efi.get_time = virt_efi_get_time; | ||
| 895 | efi.set_time = virt_efi_set_time; | ||
| 896 | efi.get_wakeup_time = virt_efi_get_wakeup_time; | ||
| 897 | efi.set_wakeup_time = virt_efi_set_wakeup_time; | ||
| 898 | efi.get_variable = virt_efi_get_variable; | ||
| 899 | efi.get_next_variable = virt_efi_get_next_variable; | ||
| 900 | efi.set_variable = virt_efi_set_variable; | ||
| 901 | efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count; | ||
| 902 | efi.reset_system = virt_efi_reset_system; | ||
| 903 | efi.query_variable_info = virt_efi_query_variable_info; | ||
| 904 | efi.update_capsule = virt_efi_update_capsule; | ||
| 905 | efi.query_capsule_caps = virt_efi_query_capsule_caps; | ||
| 906 | } | ||
| 907 | |||
| 844 | /* Merge contiguous regions of the same type and attribute */ | 908 | /* Merge contiguous regions of the same type and attribute */ |
| 845 | static void __init efi_merge_regions(void) | 909 | static void __init efi_merge_regions(void) |
| 846 | { | 910 | { |
| @@ -1023,11 +1087,20 @@ void __init efi_enter_virtual_mode(void) | |||
| 1023 | efi_sync_low_kernel_mappings(); | 1087 | efi_sync_low_kernel_mappings(); |
| 1024 | 1088 | ||
| 1025 | if (!efi_setup) { | 1089 | if (!efi_setup) { |
| 1026 | status = phys_efi_set_virtual_address_map( | 1090 | if (efi_is_native()) { |
| 1027 | memmap.desc_size * count, | 1091 | status = phys_efi_set_virtual_address_map( |
| 1028 | memmap.desc_size, | 1092 | memmap.desc_size * count, |
| 1029 | memmap.desc_version, | 1093 | memmap.desc_size, |
| 1030 | (efi_memory_desc_t *)__pa(new_memmap)); | 1094 | memmap.desc_version, |
| 1095 | (efi_memory_desc_t *)__pa(new_memmap)); | ||
| 1096 | } else { | ||
| 1097 | status = efi_thunk_set_virtual_address_map( | ||
