diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-02 16:25:50 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-02 16:25:50 -0700 |
commit | 4d6f843a38fa26035598f1f35181aa5f328db897 (patch) | |
tree | 0a2fa0b492ae121dc937f08efd5ba6ef9d110db3 /arch/x86/boot/compressed/eboot.c | |
parent | 55a0d3ff603a69ea4ec7677effd457f838390afc (diff) | |
parent | d3768d885c6ccbf8a137276843177d76c49033a7 (diff) | |
download | op-kernel-dev-4d6f843a38fa26035598f1f35181aa5f328db897.zip op-kernel-dev-4d6f843a38fa26035598f1f35181aa5f328db897.tar.gz |
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/compressed/eboot.c')
-rw-r--r-- | arch/x86/boot/compressed/eboot.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index c205035..d606463 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, efi_memory_desc_t *mem_map; efi_status_t status; __u32 desc_version; + bool called_exit = false; u8 nr_entries; int i; size = sizeof(*mem_map) * 32; again: - size += sizeof(*mem_map); + size += sizeof(*mem_map) * 2; _size = size; status = low_alloc(size, 1, (unsigned long *)&mem_map); if (status != EFI_SUCCESS) return status; +get_map: status = efi_call_phys5(sys_table->boottime->get_memory_map, &size, mem_map, &key, &desc_size, &desc_version); if (status == EFI_BUFFER_TOO_SMALL) { @@ -1029,8 +1031,20 @@ again: /* Might as well exit boot services now */ status = efi_call_phys2(sys_table->boottime->exit_boot_services, handle, key); - if (status != EFI_SUCCESS) - goto free_mem_map; + if (status != EFI_SUCCESS) { + /* + * ExitBootServices() will fail if any of the event + * handlers change the memory map. In which case, we + * must be prepared to retry, but only once so that + * we're guaranteed to exit on repeated failures instead + * of spinning forever. + */ + if (called_exit) + goto free_mem_map; + + called_exit = true; + goto get_map; + } /* Historic? */ boot_params->alt_mem_k = 32 * 1024; |