aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-02 19:25:50 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-02 19:25:50 -0400
commit4d6f843a38fa26035598f1f35181aa5f328db897 (patch)
tree0a2fa0b492ae121dc937f08efd5ba6ef9d110db3
parent55a0d3ff603a69ea4ec7677effd457f838390afc (diff)
parentd3768d885c6ccbf8a137276843177d76c49033a7 (diff)
Merge branch 'x86-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 EFI changes from Ingo Molnar: "Two fixes that should in principle increase robustness of our interaction with the EFI firmware, and a cleanup" * 'x86-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86, efi: retry ExitBootServices() on failure efi: Convert runtime services function ptrs UEFI: Don't pass boot services regions to SetVirtualAddressMap()
-rw-r--r--arch/x86/boot/compressed/eboot.c20
-rw-r--r--arch/x86/include/asm/efi.h28
-rw-r--r--arch/x86/platform/efi/efi.c7
-rw-r--r--include/linux/efi.h28
4 files changed, 52 insertions, 31 deletions
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index c205035a6b96..d606463aa6d6 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -992,18 +992,20 @@ static efi_status_t exit_boot(struct boot_params *boot_params,
992 efi_memory_desc_t *mem_map; 992 efi_memory_desc_t *mem_map;
993 efi_status_t status; 993 efi_status_t status;
994 __u32 desc_version; 994 __u32 desc_version;
995 bool called_exit = false;
995 u8 nr_entries; 996 u8 nr_entries;
996 int i; 997 int i;
997 998
998 size = sizeof(*mem_map) * 32; 999 size = sizeof(*mem_map) * 32;
999 1000
1000again: 1001again:
1001 size += sizeof(*mem_map); 1002 size += sizeof(*mem_map) * 2;
1002 _size = size; 1003 _size = size;
1003 status = low_alloc(size, 1, (unsigned long *)&mem_map); 1004 status = low_alloc(size, 1, (unsigned long *)&mem_map);
1004 if (status != EFI_SUCCESS) 1005 if (status != EFI_SUCCESS)
1005 return status; 1006 return status;
1006 1007
1008get_map:
1007 status = efi_call_phys5(sys_table->boottime->get_memory_map, &size, 1009 status = efi_call_phys5(sys_table->boottime->get_memory_map, &size,
1008 mem_map, &key, &desc_size, &desc_version); 1010 mem_map, &key, &desc_size, &desc_version);
1009 if (status == EFI_BUFFER_TOO_SMALL) { 1011 if (status == EFI_BUFFER_TOO_SMALL) {
@@ -1029,8 +1031,20 @@ again:
1029 /* Might as well exit boot services now */ 1031 /* Might as well exit boot services now */
1030 status = efi_call_phys2(sys_table->boottime->exit_boot_services, 1032 status = efi_call_phys2(sys_table->boottime->exit_boot_services,
1031 handle, key); 1033 handle, key);
1032 if (status != EFI_SUCCESS) 1034 if (status != EFI_SUCCESS) {
1033 goto free_mem_map; 1035 /*
1036 * ExitBootServices() will fail if any of the event
1037 * handlers change the memory map. In which case, we
1038 * must be prepared to retry, but only once so that
1039 * we're guaranteed to exit on repeated failures instead
1040 * of spinning forever.
1041 */
1042 if (called_exit)
1043 goto free_mem_map;
1044
1045 called_exit = true;
1046 goto get_map;
1047 }
1034 1048
1035 /* Historic? */ 1049 /* Historic? */
1036 boot_params->alt_mem_k = 32 * 1024; 1050 boot_params->alt_mem_k = 32 * 1024;
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 60c89f30c727..0062a0125041 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -52,40 +52,40 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3,
52 u64 arg4, u64 arg5, u64 arg6); 52 u64 arg4, u64 arg5, u64 arg6);
53 53
54#define efi_call_phys0(f) \ 54#define efi_call_phys0(f) \
55 efi_call0((void *)(f)) 55 efi_call0((f))
56#define efi_call_phys1(f, a1) \ 56#define efi_call_phys1(f, a1) \
57 efi_call1((void *)(f), (u64)(a1)) 57 efi_call1((f), (u64)(a1))
58#define efi_call_phys2(f, a1, a2) \ 58#define efi_call_phys2(f, a1, a2) \
59 efi_call2((void *)(f), (u64)(a1), (u64)(a2)) 59 efi_call2((f), (u64)(a1), (u64)(a2))
60#define efi_call_phys3(f, a1, a2, a3) \ 60#define efi_call_phys3(f, a1, a2, a3) \
61 efi_call3((void *)(f), (u64)(a1), (u64)(a2), (u64)(a3)) 61 efi_call3((f), (u64)(a1), (u64)(a2), (u64)(a3))
62#define efi_call_phys4(f, a1, a2, a3, a4) \ 62#define efi_call_phys4(f, a1, a2, a3, a4) \
63 efi_call4((void *)(f), (u64)(a1), (u64)(a2), (u64)(a3), \ 63 efi_call4((f), (u64)(a1), (u64)(a2), (u64)(a3), \
64 (u64)(a4)) 64 (u64)(a4))
65#define efi_call_phys5(f, a1, a2, a3, a4, a5) \ 65#define efi_call_phys5(f, a1, a2, a3, a4, a5) \
66 efi_call5((void *)(f), (u64)(a1), (u64)(a2), (u64)(a3), \ 66 efi_call5((f), (u64)(a1), (u64)(a2), (u64)(a3), \
67 (u64)(a4), (u64)(a5)) 67 (u64)(a4), (u64)(a5))
68#define efi_call_phys6(f, a1, a2, a3, a4, a5, a6) \ 68#define efi_call_phys6(f, a1, a2, a3, a4, a5, a6) \
69 efi_call6((void *)(f), (u64)(a1), (u64)(a2), (u64)(a3), \ 69 efi_call6((f), (u64)(a1), (u64)(a2), (u64)(a3), \
70 (u64)(a4), (u64)(a5), (u64)(a6)) 70 (u64)(a4), (u64)(a5), (u64)(a6))
71 71
72#define efi_call_virt0(f) \ 72#define efi_call_virt0(f) \
73 efi_call0((void *)(efi.systab->runtime->f)) 73 efi_call0((efi.systab->runtime->f))
74#define efi_call_virt1(f, a1) \ 74#define efi_call_virt1(f, a1) \
75 efi_call1((void *)(efi.systab->runtime->f), (u64)(a1)) 75 efi_call1((efi.systab->runtime->f), (u64)(a1))
76#define efi_call_virt2(f, a1, a2) \ 76#define efi_call_virt2(f, a1, a2) \
77 efi_call2((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2)) 77 efi_call2((efi.systab->runtime->f), (u64)(a1), (u64)(a2))
78#define efi_call_virt3(f, a1, a2, a3) \ 78#define efi_call_virt3(f, a1, a2, a3) \
79 efi_call3((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ 79 efi_call3((efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
80 (u64)(a3)) 80 (u64)(a3))
81#define efi_call_virt4(f, a1, a2, a3, a4) \ 81#define efi_call_virt4(f, a1, a2, a3, a4) \
82 efi_call4((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ 82 efi_call4((efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
83 (u64)(a3), (u64)(a4)) 83 (u64)(a3), (u64)(a4))
84#define efi_call_virt5(f, a1, a2, a3, a4, a5) \ 84#define efi_call_virt5(f, a1, a2, a3, a4, a5) \
85 efi_call5((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ 85 efi_call5((efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
86 (u64)(a3), (u64)(a4), (u64)(a5)) 86 (u64)(a3), (u64)(a4), (u64)(a5))
87#define efi_call_virt6(f, a1, a2, a3, a4, a5, a6) \ 87#define efi_call_virt6(f, a1, a2, a3, a4, a5, a6) \
88 efi_call6((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ 88 efi_call6((efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
89 (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6)) 89 (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6))
90 90
91extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, 91extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index d2fbcedcf6ea..b410b71bdcf7 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -929,6 +929,13 @@ void __init efi_enter_virtual_mode(void)
929 va = efi_ioremap(md->phys_addr, size, 929 va = efi_ioremap(md->phys_addr, size,
930 md->type, md->attribute); 930 md->type, md->attribute);
931 931
932 if (!(md->attribute & EFI_MEMORY_RUNTIME)) {
933 if (!va)
934 pr_err("ioremap of 0x%llX failed!\n",
935 (unsigned long long)md->phys_addr);
936 continue;
937 }
938
932 md->virt_addr = (u64) (unsigned long) va; 939 md->virt_addr = (u64) (unsigned long) va;
933 940
934 if (!va) { 941 if (!va) {
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 2bc0ad78d058..21ae6b3c0359 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -287,20 +287,20 @@ typedef struct {
287 287
288typedef struct { 288typedef struct {
289 efi_table_hdr_t hdr; 289 efi_table_hdr_t hdr;
290 unsigned long get_time; 290 void *get_time;
291 unsigned long set_time; 291 void *set_time;
292 unsigned long get_wakeup_time; 292 void *get_wakeup_time;
293 unsigned long set_wakeup_time; 293 void *set_wakeup_time;
294 unsigned long set_virtual_address_map; 294 void *set_virtual_address_map;
295 unsigned long convert_pointer; 295 void *convert_pointer;
296 unsigned long get_variable; 296 void *get_variable;
297 unsigned long get_next_variable; 297 void *get_next_variable;
298 unsigned long set_variable; 298 void *set_variable;
299 unsigned long get_next_high_mono_count; 299 void *get_next_high_mono_count;
300 unsigned long reset_system; 300 void *reset_system;
301 unsigned long update_capsule; 301 void *update_capsule;
302 unsigned long query_capsule_caps; 302 void *query_capsule_caps;
303 unsigned long query_variable_info; 303 void *query_variable_info;
304} efi_runtime_services_t; 304} efi_runtime_services_t;
305 305
306typedef efi_status_t efi_get_time_t (efi_time_t *tm, efi_time_cap_t *tc); 306typedef efi_status_t efi_get_time_t (efi_time_t *tm, efi_time_cap_t *tc);