aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/platform/efi/efi.c
diff options
context:
space:
mode:
authorMatt Fleming <matt.fleming@intel.com>2014-01-10 13:48:30 -0500
committerMatt Fleming <matt.fleming@intel.com>2014-03-04 16:43:14 -0500
commit4f9dbcfc40299ddaa780fe8c1cd74998c1be3af5 (patch)
treef6d2f85b23fae5ee8d9da79f30c47351aa890d5b /arch/x86/platform/efi/efi.c
parentb8ff87a6158886771677e6dc8139bac6e3cba717 (diff)
x86/efi: Add mixed runtime services support
Setup the runtime services based on whether we're booting in EFI native mode or not. For non-native mode we need to thunk from 64-bit into 32-bit mode before invoking the EFI runtime services. Using the runtime services after SetVirtualAddressMap() is slightly more complicated because we need to ensure that all the addresses we pass to the firmware are below the 4GB boundary so that they can be addressed with 32-bit pointers, see efi_setup_page_tables(). Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Diffstat (limited to 'arch/x86/platform/efi/efi.c')
-rw-r--r--arch/x86/platform/efi/efi.c127
1 files changed, 97 insertions, 30 deletions
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(
1098 efi_phys.set_virtual_address_map,
1099 memmap.desc_size * count,
1100 memmap.desc_size,
1101 memmap.desc_version,
1102 (efi_memory_desc_t *)__pa(new_memmap));
1103 }
1031 1104
1032 if (status != EFI_SUCCESS) { 1105 if (status != EFI_SUCCESS) {
1033 pr_alert("Unable to switch EFI into virtual mode (status=%lx)!\n", 1106 pr_alert("Unable to switch EFI into virtual mode (status=%lx)!\n",
@@ -1043,19 +1116,13 @@ void __init efi_enter_virtual_mode(void)
1043 * Call EFI services through wrapper functions. 1116 * Call EFI services through wrapper functions.
1044 */ 1117 */
1045 efi.runtime_version = efi_systab.hdr.revision; 1118 efi.runtime_version = efi_systab.hdr.revision;
1046 efi.get_time = virt_efi_get_time; 1119
1047 efi.set_time = virt_efi_set_time; 1120 if (efi_is_native())
1048 efi.get_wakeup_time = virt_efi_get_wakeup_time; 1121 native_runtime_setup();
1049 efi.set_wakeup_time = virt_efi_set_wakeup_time; 1122 else
1050 efi.get_variable = virt_efi_get_variable; 1123 efi_thunk_runtime_setup();
1051 efi.get_next_variable = virt_efi_get_next_variable; 1124
1052 efi.set_variable = virt_efi_set_variable;
1053 efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
1054 efi.reset_system = virt_efi_reset_system;
1055 efi.set_virtual_address_map = NULL; 1125 efi.set_virtual_address_map = NULL;
1056 efi.query_variable_info = virt_efi_query_variable_info;
1057 efi.update_capsule = virt_efi_update_capsule;
1058 efi.query_capsule_caps = virt_efi_query_capsule_caps;
1059 1126
1060 efi_runtime_mkexec(); 1127 efi_runtime_mkexec();
1061 1128