aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/efi.h12
-rw-r--r--arch/x86/include/uapi/asm/bootparam.h1
-rw-r--r--arch/x86/kernel/setup.c3
-rw-r--r--arch/x86/platform/efi/efi.c158
-rw-r--r--arch/x86/platform/efi/efi_32.c1
-rw-r--r--arch/x86/platform/efi/efi_64.c6
6 files changed, 156 insertions, 25 deletions
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 9fbaeb239bde..4d1ba80b6ff1 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -133,6 +133,18 @@ extern void efi_sync_low_kernel_mappings(void);
133extern void efi_setup_page_tables(void); 133extern void efi_setup_page_tables(void);
134extern void __init old_map_region(efi_memory_desc_t *md); 134extern void __init old_map_region(efi_memory_desc_t *md);
135 135
136struct efi_setup_data {
137 u64 fw_vendor;
138 u64 runtime;
139 u64 tables;
140 u64 smbios;
141 u64 reserved[8];
142};
143
144extern u64 efi_setup;
145extern u32 efi_data_len;
146extern void parse_efi_setup(u64 phys_addr, u32 data_len);
147
136#ifdef CONFIG_EFI 148#ifdef CONFIG_EFI
137 149
138static inline bool efi_is_native(void) 150static inline bool efi_is_native(void)
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
index 9c3733c5f8f7..64fe421aab65 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -6,6 +6,7 @@
6#define SETUP_E820_EXT 1 6#define SETUP_E820_EXT 1
7#define SETUP_DTB 2 7#define SETUP_DTB 2
8#define SETUP_PCI 3 8#define SETUP_PCI 3
9#define SETUP_EFI 4
9 10
10/* ram_size flags */ 11/* ram_size flags */
11#define RAMDISK_IMAGE_START_MASK 0x07FF 12#define RAMDISK_IMAGE_START_MASK 0x07FF
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index cb233bc9dee3..24536f7a0ae6 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -447,6 +447,9 @@ static void __init parse_setup_data(void)
447 case SETUP_DTB: 447 case SETUP_DTB:
448 add_dtb(pa_data); 448 add_dtb(pa_data);
449 break; 449 break;
450 case SETUP_EFI:
451 parse_efi_setup(pa_data, data_len);
452 break;
450 default: 453 default:
451 break; 454 break;
452 } 455 }
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 74fe7a719508..9965ff403c6e 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -78,6 +78,8 @@ static __initdata efi_config_table_type_t arch_tables[] = {
78 78
79static void *efi_runtime_map; 79static void *efi_runtime_map;
80static int nr_efi_runtime_map; 80static int nr_efi_runtime_map;
81u64 efi_setup; /* efi setup_data physical address */
82u32 efi_data_len; /* efi setup_data payload length */
81 83
82/* 84/*
83 * Returns 1 if 'facility' is enabled, 0 otherwise. 85 * Returns 1 if 'facility' is enabled, 0 otherwise.
@@ -115,7 +117,6 @@ static int __init setup_storage_paranoia(char *arg)
115} 117}
116early_param("efi_no_storage_paranoia", setup_storage_paranoia); 118early_param("efi_no_storage_paranoia", setup_storage_paranoia);
117 119
118
119static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) 120static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
120{ 121{
121 unsigned long flags; 122 unsigned long flags;
@@ -494,18 +495,27 @@ static int __init efi_systab_init(void *phys)
494{ 495{
495 if (efi_enabled(EFI_64BIT)) { 496 if (efi_enabled(EFI_64BIT)) {
496 efi_system_table_64_t *systab64; 497 efi_system_table_64_t *systab64;
498 struct efi_setup_data *data = NULL;
497 u64 tmp = 0; 499 u64 tmp = 0;
498 500
501 if (efi_setup) {
502 data = early_memremap(efi_setup, sizeof(*data));
503 if (!data)
504 return -ENOMEM;
505 }
499 systab64 = early_ioremap((unsigned long)phys, 506 systab64 = early_ioremap((unsigned long)phys,
500 sizeof(*systab64)); 507 sizeof(*systab64));
501 if (systab64 == NULL) { 508 if (systab64 == NULL) {
502 pr_err("Couldn't map the system table!\n"); 509 pr_err("Couldn't map the system table!\n");
510 if (data)
511 early_iounmap(data, sizeof(*data));
503 return -ENOMEM; 512 return -ENOMEM;
504 } 513 }
505 514
506 efi_systab.hdr = systab64->hdr; 515 efi_systab.hdr = systab64->hdr;
507 efi_systab.fw_vendor = systab64->fw_vendor; 516 efi_systab.fw_vendor = data ? (unsigned long)data->fw_vendor :
508 tmp |= systab64->fw_vendor; 517 systab64->fw_vendor;
518 tmp |= data ? data->fw_vendor : systab64->fw_vendor;
509 efi_systab.fw_revision = systab64->fw_revision; 519 efi_systab.fw_revision = systab64->fw_revision;
510 efi_systab.con_in_handle = systab64->con_in_handle; 520 efi_systab.con_in_handle = systab64->con_in_handle;
511 tmp |= systab64->con_in_handle; 521 tmp |= systab64->con_in_handle;
@@ -519,15 +529,20 @@ static int __init efi_systab_init(void *phys)
519 tmp |= systab64->stderr_handle; 529 tmp |= systab64->stderr_handle;
520 efi_systab.stderr = systab64->stderr; 530 efi_systab.stderr = systab64->stderr;
521 tmp |= systab64->stderr; 531 tmp |= systab64->stderr;
522 efi_systab.runtime = (void *)(unsigned long)systab64->runtime; 532 efi_systab.runtime = data ?
523 tmp |= systab64->runtime; 533 (void *)(unsigned long)data->runtime :
534 (void *)(unsigned long)systab64->runtime;
535 tmp |= data ? data->runtime : systab64->runtime;
524 efi_systab.boottime = (void *)(unsigned long)systab64->boottime; 536 efi_systab.boottime = (void *)(unsigned long)systab64->boottime;
525 tmp |= systab64->boottime; 537 tmp |= systab64->boottime;
526 efi_systab.nr_tables = systab64->nr_tables; 538 efi_systab.nr_tables = systab64->nr_tables;
527 efi_systab.tables = systab64->tables; 539 efi_systab.tables = data ? (unsigned long)data->tables :
528 tmp |= systab64->tables; 540 systab64->tables;
541 tmp |= data ? data->tables : systab64->tables;
529 542
530 early_iounmap(systab64, sizeof(*systab64)); 543 early_iounmap(systab64, sizeof(*systab64));
544 if (data)
545 early_iounmap(data, sizeof(*data));
531#ifdef CONFIG_X86_32 546#ifdef CONFIG_X86_32
532 if (tmp >> 32) { 547 if (tmp >> 32) {
533 pr_err("EFI data located above 4GB, disabling EFI.\n"); 548 pr_err("EFI data located above 4GB, disabling EFI.\n");
@@ -631,6 +646,71 @@ static int __init efi_memmap_init(void)
631 return 0; 646 return 0;
632} 647}
633 648
649/*
650 * A number of config table entries get remapped to virtual addresses
651 * after entering EFI virtual mode. However, the kexec kernel requires
652 * their physical addresses therefore we pass them via setup_data and
653 * correct those entries to their respective physical addresses here.
654 *
655 * Currently only handles smbios which is necessary for some firmware
656 * implementation.
657 */
658static int __init efi_reuse_config(u64 tables, int nr_tables)
659{
660 int i, sz, ret = 0;
661 void *p, *tablep;
662 struct efi_setup_data *data;
663
664 if (!efi_setup)
665 return 0;
666
667 if (!efi_enabled(EFI_64BIT))
668 return 0;
669
670 data = early_memremap(efi_setup, sizeof(*data));
671 if (!data) {
672 ret = -ENOMEM;
673 goto out;
674 }
675
676 if (!data->smbios)
677 goto out_memremap;
678
679 sz = sizeof(efi_config_table_64_t);
680
681 p = tablep = early_memremap(tables, nr_tables * sz);
682 if (!p) {
683 pr_err("Could not map Configuration table!\n");
684 ret = -ENOMEM;
685 goto out_memremap;
686 }
687
688 for (i = 0; i < efi.systab->nr_tables; i++) {
689 efi_guid_t guid;
690
691 guid = ((efi_config_table_64_t *)p)->guid;
692
693 if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID))
694 ((efi_config_table_64_t *)p)->table = data->smbios;
695 p += sz;
696 }
697 early_iounmap(tablep, nr_tables * sz);
698
699out_memremap:
700 early_iounmap(data, sizeof(*data));
701out:
702 return ret;
703}
704
705static void get_nr_runtime_map(void)
706{
707 if (!efi_setup)
708 return;
709
710 nr_efi_runtime_map = (efi_data_len - sizeof(struct efi_setup_data)) /
711 sizeof(efi_memory_desc_t);
712}
713
634void __init efi_init(void) 714void __init efi_init(void)
635{ 715{
636 efi_char16_t *c16; 716 efi_char16_t *c16;
@@ -638,6 +718,7 @@ void __init efi_init(void)
638 int i = 0; 718 int i = 0;
639 void *tmp; 719 void *tmp;
640 720
721 get_nr_runtime_map();
641#ifdef CONFIG_X86_32 722#ifdef CONFIG_X86_32
642 if (boot_params.efi_info.efi_systab_hi || 723 if (boot_params.efi_info.efi_systab_hi ||
643 boot_params.efi_info.efi_memmap_hi) { 724 boot_params.efi_info.efi_memmap_hi) {
@@ -676,6 +757,9 @@ void __init efi_init(void)
676 efi.systab->hdr.revision >> 16, 757 efi.systab->hdr.revision >> 16,
677 efi.systab->hdr.revision & 0xffff, vendor); 758 efi.systab->hdr.revision & 0xffff, vendor);
678 759
760 if (efi_reuse_config(efi.systab->tables, efi.systab->nr_tables))
761 return;
762
679 if (efi_config_init(arch_tables)) 763 if (efi_config_init(arch_tables))
680 return; 764 return;
681 765
@@ -861,6 +945,23 @@ out:
861} 945}
862 946
863/* 947/*
948 * Map efi regions which were passed via setup_data. The virt_addr is a fixed
949 * addr which was used in first kernel of a kexec boot.
950 */
951static void __init efi_map_regions_fixed(void)
952{
953 void *p;
954 efi_memory_desc_t *md;
955
956 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
957 md = p;
958 efi_map_region_fixed(md); /* FIXME: add error handling */
959 get_systab_virt_addr(md);
960 }
961
962}
963
964/*
864 * Map efi memory ranges for runtime serivce and update new_memmap with virtual 965 * Map efi memory ranges for runtime serivce and update new_memmap with virtual
865 * addresses. 966 * addresses.
866 */ 967 */
@@ -914,6 +1015,10 @@ out:
914 * so that we're in a different address space when calling a runtime 1015 * so that we're in a different address space when calling a runtime
915 * function. For function arguments passing we do copy the PGDs of the 1016 * function. For function arguments passing we do copy the PGDs of the
916 * kernel page table into ->trampoline_pgd prior to each call. 1017 * kernel page table into ->trampoline_pgd prior to each call.
1018 *
1019 * Specially for kexec boot, efi runtime maps in previous kernel should
1020 * be passed in via setup_data. In that case runtime ranges will be mapped
1021 * to the same virtual addresses as the first kernel.
917 */ 1022 */
918void __init efi_enter_virtual_mode(void) 1023void __init efi_enter_virtual_mode(void)
919{ 1024{
@@ -932,12 +1037,15 @@ void __init efi_enter_virtual_mode(void)
932 return; 1037 return;
933 } 1038 }
934 1039
935 efi_merge_regions(); 1040 if (efi_setup) {
936 1041 efi_map_regions_fixed();
937 new_memmap = efi_map_regions(&count); 1042 } else {
938 if (!new_memmap) { 1043 efi_merge_regions();
939 pr_err("Error reallocating memory, EFI runtime non-functional!\n"); 1044 new_memmap = efi_map_regions(&count);
940 return; 1045 if (!new_memmap) {
1046 pr_err("Error reallocating memory, EFI runtime non-functional!\n");
1047 return;
1048 }
941 } 1049 }
942 1050
943 err = save_runtime_map(); 1051 err = save_runtime_map();
@@ -949,16 +1057,18 @@ void __init efi_enter_virtual_mode(void)
949 efi_setup_page_tables(); 1057 efi_setup_page_tables();
950 efi_sync_low_kernel_mappings(); 1058 efi_sync_low_kernel_mappings();
951 1059
952 status = phys_efi_set_virtual_address_map( 1060 if (!efi_setup) {
953 memmap.desc_size * count, 1061 status = phys_efi_set_virtual_address_map(
954 memmap.desc_size, 1062 memmap.desc_size * count,
955 memmap.desc_version, 1063 memmap.desc_size,
956 (efi_memory_desc_t *)__pa(new_memmap)); 1064 memmap.desc_version,
957 1065 (efi_memory_desc_t *)__pa(new_memmap));
958 if (status != EFI_SUCCESS) { 1066
959 pr_alert("Unable to switch EFI into virtual mode " 1067 if (status != EFI_SUCCESS) {
960 "(status=%lx)!\n", status); 1068 pr_alert("Unable to switch EFI into virtual mode (status=%lx)!\n",
961 panic("EFI call to SetVirtualAddressMap() failed!"); 1069 status);
1070 panic("EFI call to SetVirtualAddressMap() failed!");
1071 }
962 } 1072 }
963 1073
964 /* 1074 /*
@@ -993,8 +1103,6 @@ void __init efi_enter_virtual_mode(void)
993 EFI_VARIABLE_BOOTSERVICE_ACCESS | 1103 EFI_VARIABLE_BOOTSERVICE_ACCESS |
994 EFI_VARIABLE_RUNTIME_ACCESS, 1104 EFI_VARIABLE_RUNTIME_ACCESS,
995 0, NULL); 1105 0, NULL);
996
997 return;
998} 1106}
999 1107
1000/* 1108/*
diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c
index 7b3ec6ed99af..249b183cf417 100644
--- a/arch/x86/platform/efi/efi_32.c
+++ b/arch/x86/platform/efi/efi_32.c
@@ -48,6 +48,7 @@ void __init efi_map_region(efi_memory_desc_t *md)
48} 48}
49 49
50void __init efi_map_region_fixed(efi_memory_desc_t *md) {} 50void __init efi_map_region_fixed(efi_memory_desc_t *md) {}
51void __init parse_efi_setup(u64 phys_addr, u32 data_len) {}
51 52
52void efi_call_phys_prelog(void) 53void efi_call_phys_prelog(void)
53{ 54{
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index ff08cb19630b..324b65103851 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -228,3 +228,9 @@ void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,
228 228
229 return (void __iomem *)__va(phys_addr); 229 return (void __iomem *)__va(phys_addr);
230} 230}
231
232void __init parse_efi_setup(u64 phys_addr, u32 data_len)
233{
234 efi_setup = phys_addr + sizeof(struct setup_data);
235 efi_data_len = data_len - sizeof(struct setup_data);
236}