aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/boot
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 /arch/x86/boot
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()
Diffstat (limited to 'arch/x86/boot')
-rw-r--r--arch/x86/boot/compressed/eboot.c20
1 files changed, 17 insertions, 3 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;