aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/efi.h21
-rw-r--r--arch/x86/platform/efi/Makefile1
-rw-r--r--arch/x86/platform/efi/efi.c127
-rw-r--r--arch/x86/platform/efi/efi_64.c335
-rw-r--r--arch/x86/platform/efi/efi_stub_64.S1
-rw-r--r--arch/x86/platform/efi/efi_thunk_64.S65
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
155extern struct console early_efi_console; 155extern struct console early_efi_console;
156extern void parse_efi_setup(u64 phys_addr, u32 data_len); 156extern void parse_efi_setup(u64 phys_addr, u32 data_len);
157
158#ifdef CONFIG_EFI_MIXED
159extern void efi_thunk_runtime_setup(void);
160extern 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
167static inline void efi_thunk_runtime_setup(void) {}
168static 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 @@
1obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o 1obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o
2obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o 2obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
3obj-$(CONFIG_EARLY_PRINTK_EFI) += early_printk.o 3obj-$(CONFIG_EARLY_PRINTK_EFI) += early_printk.o
4obj-$(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
591static int __init efi_runtime_init(void) 591static 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
622static 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
653static 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
892static 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 */
845static void __init efi_merge_regions(void) 909static 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(