diff options
author | Jeffrey Hugo <jhugo@codeaurora.org> | 2016-08-29 16:38:53 -0400 |
---|---|---|
committer | Matt Fleming <matt@codeblueprint.co.uk> | 2016-09-05 07:32:36 -0400 |
commit | ed9cc156c42ff0c0bf9b1d09df48a12bf0873473 (patch) | |
tree | c1fb0debfe329e10e5eef595a67775bc94c86542 /drivers/firmware | |
parent | fc07716ba803483be91bc4b2344f9c84985e6f07 (diff) |
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>
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/efi/libstub/fdt.c | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c index bec0fa8d8746..a6a93116a8f0 100644 --- a/drivers/firmware/efi/libstub/fdt.c +++ b/drivers/firmware/efi/libstub/fdt.c | |||
@@ -152,6 +152,27 @@ fdt_set_fail: | |||
152 | #define EFI_FDT_ALIGN EFI_PAGE_SIZE | 152 | #define EFI_FDT_ALIGN EFI_PAGE_SIZE |
153 | #endif | 153 | #endif |
154 | 154 | ||
155 | struct exit_boot_struct { | ||
156 | efi_memory_desc_t *runtime_map; | ||
157 | int *runtime_entry_count; | ||
158 | }; | ||
159 | |||
160 | static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg, | ||
161 | struct efi_boot_memmap *map, | ||
162 | void *priv) | ||
163 | { | ||
164 | struct exit_boot_struct *p = priv; | ||
165 | /* | ||
166 | * Update the memory map with virtual addresses. The function will also | ||
167 | * populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME | ||
168 | * entries so that we can pass it straight to SetVirtualAddressMap() | ||
169 | */ | ||
170 | efi_get_virtmap(*map->map, *map->map_size, *map->desc_size, | ||
171 | p->runtime_map, p->runtime_entry_count); | ||
172 | |||
173 | return EFI_SUCCESS; | ||
174 | } | ||
175 | |||
155 | /* | 176 | /* |
156 | * Allocate memory for a new FDT, then add EFI, commandline, and | 177 | * Allocate memory for a new FDT, then add EFI, commandline, and |
157 | * initrd related fields to the FDT. This routine increases the | 178 | * 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, | |||
183 | efi_status_t status; | 204 | efi_status_t status; |
184 | int runtime_entry_count = 0; | 205 | int runtime_entry_count = 0; |
185 | struct efi_boot_memmap map; | 206 | struct efi_boot_memmap map; |
207 | struct exit_boot_struct priv; | ||
186 | 208 | ||
187 | map.map = &runtime_map; | 209 | map.map = &runtime_map; |
188 | map.map_size = &map_size; | 210 | map.map_size = &map_size; |
@@ -257,16 +279,11 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, | |||
257 | } | 279 | } |
258 | } | 280 | } |
259 | 281 | ||
260 | /* | 282 | sys_table->boottime->free_pool(memory_map); |
261 | * Update the memory map with virtual addresses. The function will also | 283 | priv.runtime_map = runtime_map; |
262 | * populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME | 284 | priv.runtime_entry_count = &runtime_entry_count; |
263 | * entries so that we can pass it straight into SetVirtualAddressMap() | 285 | status = efi_exit_boot_services(sys_table, handle, &map, &priv, |
264 | */ | 286 | exit_boot_func); |
265 | efi_get_virtmap(memory_map, map_size, desc_size, runtime_map, | ||
266 | &runtime_entry_count); | ||
267 | |||
268 | /* Now we are ready to exit_boot_services.*/ | ||
269 | status = sys_table->boottime->exit_boot_services(handle, mmap_key); | ||
270 | 287 | ||
271 | if (status == EFI_SUCCESS) { | 288 | if (status == EFI_SUCCESS) { |
272 | efi_set_virtual_address_map_t *svam; | 289 | efi_set_virtual_address_map_t *svam; |