|
@@ -1037,18 +1037,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) {
|
|
@@ -1074,8 +1076,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;
|