aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
authorJeffrey Hugo <jhugo@codeaurora.org>2016-08-29 16:38:53 -0400
committerMatt Fleming <matt@codeblueprint.co.uk>2016-09-05 07:32:36 -0400
commited9cc156c42ff0c0bf9b1d09df48a12bf0873473 (patch)
treec1fb0debfe329e10e5eef595a67775bc94c86542 /drivers/firmware
parentfc07716ba803483be91bc4b2344f9c84985e6f07 (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.c37
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
155struct exit_boot_struct {
156 efi_memory_desc_t *runtime_map;
157 int *runtime_entry_count;
158};
159
160static 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;