efi/libstub: Use efi_exit_boot_services() in FDT
The FDT code directly calls ExitBootServices. This is inadvisable as the UEFI spec details a complex set of errors, race conditions, and API interactions that the caller of ExitBootServices must get correct. The FDT code does not handle EFI_INVALID_PARAMETER as required by the spec, which causes intermittent boot failures on the Qualcomm Technologies QDF2432. Call the efi_exit_boot_services() helper intead, which handles the EFI_INVALID_PARAMETER scenario properly. Signed-off-by: Jeffrey Hugo <jhugo@codeaurora.org> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Leif Lindholm <leif.lindholm@linaro.org> Cc: Ingo Molnar <mingo@kernel.org> Cc: <stable@vger.kernel.org> Signed-off-by: Matt Fleming <matt@codeblueprint.co.uk>
This commit is contained in:
parent
fc07716ba8
commit
ed9cc156c4
@ -152,6 +152,27 @@ fdt_set_fail:
|
|||||||
#define EFI_FDT_ALIGN EFI_PAGE_SIZE
|
#define EFI_FDT_ALIGN EFI_PAGE_SIZE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct exit_boot_struct {
|
||||||
|
efi_memory_desc_t *runtime_map;
|
||||||
|
int *runtime_entry_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
|
||||||
|
struct efi_boot_memmap *map,
|
||||||
|
void *priv)
|
||||||
|
{
|
||||||
|
struct exit_boot_struct *p = priv;
|
||||||
|
/*
|
||||||
|
* Update the memory map with virtual addresses. The function will also
|
||||||
|
* populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME
|
||||||
|
* entries so that we can pass it straight to SetVirtualAddressMap()
|
||||||
|
*/
|
||||||
|
efi_get_virtmap(*map->map, *map->map_size, *map->desc_size,
|
||||||
|
p->runtime_map, p->runtime_entry_count);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate memory for a new FDT, then add EFI, commandline, and
|
* Allocate memory for a new FDT, then add EFI, commandline, and
|
||||||
* initrd related fields to the FDT. This routine increases the
|
* initrd related fields to the FDT. This routine increases the
|
||||||
@ -183,6 +204,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
|||||||
efi_status_t status;
|
efi_status_t status;
|
||||||
int runtime_entry_count = 0;
|
int runtime_entry_count = 0;
|
||||||
struct efi_boot_memmap map;
|
struct efi_boot_memmap map;
|
||||||
|
struct exit_boot_struct priv;
|
||||||
|
|
||||||
map.map = &runtime_map;
|
map.map = &runtime_map;
|
||||||
map.map_size = &map_size;
|
map.map_size = &map_size;
|
||||||
@ -257,16 +279,11 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
sys_table->boottime->free_pool(memory_map);
|
||||||
* Update the memory map with virtual addresses. The function will also
|
priv.runtime_map = runtime_map;
|
||||||
* populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME
|
priv.runtime_entry_count = &runtime_entry_count;
|
||||||
* entries so that we can pass it straight into SetVirtualAddressMap()
|
status = efi_exit_boot_services(sys_table, handle, &map, &priv,
|
||||||
*/
|
exit_boot_func);
|
||||||
efi_get_virtmap(memory_map, map_size, desc_size, runtime_map,
|
|
||||||
&runtime_entry_count);
|
|
||||||
|
|
||||||
/* Now we are ready to exit_boot_services.*/
|
|
||||||
status = sys_table->boottime->exit_boot_services(handle, mmap_key);
|
|
||||||
|
|
||||||
if (status == EFI_SUCCESS) {
|
if (status == EFI_SUCCESS) {
|
||||||
efi_set_virtual_address_map_t *svam;
|
efi_set_virtual_address_map_t *svam;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user