diff options
author | Tom Rini | 2018-09-26 14:14:02 -0500 |
---|---|---|
committer | Tom Rini | 2018-09-26 16:02:46 -0500 |
commit | 0ae8dcfef7c890330c62bb34c724126ffc169bef (patch) | |
tree | aeeaa9a83efad66ca4db0b4aca2ee5cf3478728e /cmd | |
parent | d8d81d4a5d0e5aaef5a005a357d3b9ed2b7cc4b2 (diff) | |
parent | eaac4fb296b1899369e49d941f2c0d346c7f5c7a (diff) | |
download | u-boot-0ae8dcfef7c890330c62bb34c724126ffc169bef.tar.gz u-boot-0ae8dcfef7c890330c62bb34c724126ffc169bef.tar.xz u-boot-0ae8dcfef7c890330c62bb34c724126ffc169bef.zip |
Merge tag 'signed-efi-next' of git://github.com/agraf/u-boot
Patch queue for efi - 2018-09-26
A lot of goodness in this release. We're *very* close to running the
UEFI Shell and SCT natively. The only missing piece are HII protocols.
- FAT write support (needed for SCT)
- improved FAT directory support (needed for SCT)
- RTC support with QEMU -M virt
- Sandbox support (run UEFI binaries in Linux - yay)
- Proper UTF-16 support
- EFI_UNICODE_COLLATION_PROTOCOL support (for UEFI Shell)
- EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL support (for UEFI Shell)
- Fix window size determination
- Fix Tegra by explicitly unmapping RAM
- Clean up handle entanglement
- Lots of generic code cleanup
[trini: Fixup merge conflict in include/configs/qemu-arm.h]
Signed-off-by: Tom Rini <trini@konsulko.com>
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/bootefi.c | 187 | ||||
-rw-r--r-- | cmd/fat.c | 34 |
2 files changed, 151 insertions, 70 deletions
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index b60c151fb4..82d755ceb3 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c | |||
@@ -49,6 +49,11 @@ efi_status_t efi_init_obj_list(void) | |||
49 | if (ret != EFI_SUCCESS) | 49 | if (ret != EFI_SUCCESS) |
50 | goto out; | 50 | goto out; |
51 | 51 | ||
52 | /* Initialize root node */ | ||
53 | ret = efi_root_node_register(); | ||
54 | if (ret != EFI_SUCCESS) | ||
55 | goto out; | ||
56 | |||
52 | /* Initialize EFI driver uclass */ | 57 | /* Initialize EFI driver uclass */ |
53 | ret = efi_driver_init(); | 58 | ret = efi_driver_init(); |
54 | if (ret != EFI_SUCCESS) | 59 | if (ret != EFI_SUCCESS) |
@@ -116,32 +121,47 @@ static void set_load_options(struct efi_loaded_image *loaded_image_info, | |||
116 | { | 121 | { |
117 | size_t size; | 122 | size_t size; |
118 | const char *env = env_get(env_var); | 123 | const char *env = env_get(env_var); |
124 | u16 *pos; | ||
119 | 125 | ||
120 | loaded_image_info->load_options = NULL; | 126 | loaded_image_info->load_options = NULL; |
121 | loaded_image_info->load_options_size = 0; | 127 | loaded_image_info->load_options_size = 0; |
122 | if (!env) | 128 | if (!env) |
123 | return; | 129 | return; |
124 | size = strlen(env) + 1; | 130 | size = utf8_utf16_strlen(env) + 1; |
125 | loaded_image_info->load_options = calloc(size, sizeof(u16)); | 131 | loaded_image_info->load_options = calloc(size, sizeof(u16)); |
126 | if (!loaded_image_info->load_options) { | 132 | if (!loaded_image_info->load_options) { |
127 | printf("ERROR: Out of memory\n"); | 133 | printf("ERROR: Out of memory\n"); |
128 | return; | 134 | return; |
129 | } | 135 | } |
130 | utf8_to_utf16(loaded_image_info->load_options, (u8 *)env, size); | 136 | pos = loaded_image_info->load_options; |
137 | utf8_utf16_strcpy(&pos, env); | ||
131 | loaded_image_info->load_options_size = size * 2; | 138 | loaded_image_info->load_options_size = size * 2; |
132 | } | 139 | } |
133 | 140 | ||
134 | static void *copy_fdt(void *fdt) | 141 | /** |
142 | * copy_fdt() - Copy the device tree to a new location available to EFI | ||
143 | * | ||
144 | * The FDT is relocated into a suitable location within the EFI memory map. | ||
145 | * An additional 12KB is added to the space in case the device tree needs to be | ||
146 | * expanded later with fdt_open_into(). | ||
147 | * | ||
148 | * @fdt_addr: On entry, address of start of FDT. On exit, address of relocated | ||
149 | * FDT start | ||
150 | * @fdt_sizep: Returns new size of FDT, including | ||
151 | * @return new relocated address of FDT | ||
152 | */ | ||
153 | static efi_status_t copy_fdt(ulong *fdt_addrp, ulong *fdt_sizep) | ||
135 | { | 154 | { |
136 | u64 fdt_size = fdt_totalsize(fdt); | ||
137 | unsigned long fdt_ram_start = -1L, fdt_pages; | 155 | unsigned long fdt_ram_start = -1L, fdt_pages; |
156 | efi_status_t ret = 0; | ||
157 | void *fdt, *new_fdt; | ||
138 | u64 new_fdt_addr; | 158 | u64 new_fdt_addr; |
139 | void *new_fdt; | 159 | uint fdt_size; |
140 | int i; | 160 | int i; |
141 | 161 | ||
142 | for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { | 162 | for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { |
143 | u64 ram_start = gd->bd->bi_dram[i].start; | 163 | u64 ram_start = gd->bd->bi_dram[i].start; |
144 | u64 ram_size = gd->bd->bi_dram[i].size; | 164 | u64 ram_size = gd->bd->bi_dram[i].size; |
145 | 165 | ||
146 | if (!ram_size) | 166 | if (!ram_size) |
147 | continue; | 167 | continue; |
@@ -154,30 +174,37 @@ static void *copy_fdt(void *fdt) | |||
154 | * Give us at least 4KB of breathing room in case the device tree needs | 174 | * Give us at least 4KB of breathing room in case the device tree needs |
155 | * to be expanded later. Round up to the nearest EFI page boundary. | 175 | * to be expanded later. Round up to the nearest EFI page boundary. |
156 | */ | 176 | */ |
157 | fdt_size += 4096; | 177 | fdt = map_sysmem(*fdt_addrp, 0); |
178 | fdt_size = fdt_totalsize(fdt); | ||
179 | fdt_size += 4096 * 3; | ||
158 | fdt_size = ALIGN(fdt_size + EFI_PAGE_SIZE - 1, EFI_PAGE_SIZE); | 180 | fdt_size = ALIGN(fdt_size + EFI_PAGE_SIZE - 1, EFI_PAGE_SIZE); |
159 | fdt_pages = fdt_size >> EFI_PAGE_SHIFT; | 181 | fdt_pages = fdt_size >> EFI_PAGE_SHIFT; |
160 | 182 | ||
161 | /* Safe fdt location is at 128MB */ | 183 | /* Safe fdt location is at 127MB */ |
162 | new_fdt_addr = fdt_ram_start + (128 * 1024 * 1024) + fdt_size; | 184 | new_fdt_addr = fdt_ram_start + (127 * 1024 * 1024) + fdt_size; |
163 | if (efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, | 185 | ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, |
164 | EFI_RUNTIME_SERVICES_DATA, fdt_pages, | 186 | EFI_RUNTIME_SERVICES_DATA, fdt_pages, |
165 | &new_fdt_addr) != EFI_SUCCESS) { | 187 | &new_fdt_addr); |
188 | if (ret != EFI_SUCCESS) { | ||
166 | /* If we can't put it there, put it somewhere */ | 189 | /* If we can't put it there, put it somewhere */ |
167 | new_fdt_addr = (ulong)memalign(EFI_PAGE_SIZE, fdt_size); | 190 | new_fdt_addr = (ulong)memalign(EFI_PAGE_SIZE, fdt_size); |
168 | if (efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, | 191 | ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, |
169 | EFI_RUNTIME_SERVICES_DATA, fdt_pages, | 192 | EFI_RUNTIME_SERVICES_DATA, fdt_pages, |
170 | &new_fdt_addr) != EFI_SUCCESS) { | 193 | &new_fdt_addr); |
194 | if (ret != EFI_SUCCESS) { | ||
171 | printf("ERROR: Failed to reserve space for FDT\n"); | 195 | printf("ERROR: Failed to reserve space for FDT\n"); |
172 | return NULL; | 196 | goto done; |
173 | } | 197 | } |
174 | } | 198 | } |
175 | 199 | ||
176 | new_fdt = (void*)(ulong)new_fdt_addr; | 200 | new_fdt = map_sysmem(new_fdt_addr, fdt_size); |
177 | memcpy(new_fdt, fdt, fdt_totalsize(fdt)); | 201 | memcpy(new_fdt, fdt, fdt_totalsize(fdt)); |
178 | fdt_set_totalsize(new_fdt, fdt_size); | 202 | fdt_set_totalsize(new_fdt, fdt_size); |
179 | 203 | ||
180 | return new_fdt; | 204 | *fdt_addrp = new_fdt_addr; |
205 | *fdt_sizep = fdt_size; | ||
206 | done: | ||
207 | return ret; | ||
181 | } | 208 | } |
182 | 209 | ||
183 | static efi_status_t efi_do_enter( | 210 | static efi_status_t efi_do_enter( |
@@ -250,22 +277,27 @@ static void efi_carve_out_dt_rsv(void *fdt) | |||
250 | } | 277 | } |
251 | } | 278 | } |
252 | 279 | ||
253 | static efi_status_t efi_install_fdt(void *fdt) | 280 | static efi_status_t efi_install_fdt(ulong fdt_addr) |
254 | { | 281 | { |
255 | bootm_headers_t img = { 0 }; | 282 | bootm_headers_t img = { 0 }; |
256 | ulong fdt_pages, fdt_size, fdt_start, fdt_end; | 283 | ulong fdt_pages, fdt_size, fdt_start; |
257 | efi_status_t ret; | 284 | efi_status_t ret; |
285 | void *fdt; | ||
258 | 286 | ||
287 | fdt = map_sysmem(fdt_addr, 0); | ||
259 | if (fdt_check_header(fdt)) { | 288 | if (fdt_check_header(fdt)) { |
260 | printf("ERROR: invalid device tree\n"); | 289 | printf("ERROR: invalid device tree\n"); |
261 | return EFI_INVALID_PARAMETER; | 290 | return EFI_INVALID_PARAMETER; |
262 | } | 291 | } |
263 | 292 | ||
264 | /* Prepare fdt for payload */ | 293 | /* Prepare fdt for payload */ |
265 | fdt = copy_fdt(fdt); | 294 | ret = copy_fdt(&fdt_addr, &fdt_size); |
266 | if (!fdt) | 295 | if (ret) |
267 | return EFI_OUT_OF_RESOURCES; | 296 | return ret; |
268 | 297 | ||
298 | unmap_sysmem(fdt); | ||
299 | fdt = map_sysmem(fdt_addr, 0); | ||
300 | fdt_size = fdt_totalsize(fdt); | ||
269 | if (image_setup_libfdt(&img, fdt, 0, NULL)) { | 301 | if (image_setup_libfdt(&img, fdt, 0, NULL)) { |
270 | printf("ERROR: failed to process device tree\n"); | 302 | printf("ERROR: failed to process device tree\n"); |
271 | return EFI_LOAD_ERROR; | 303 | return EFI_LOAD_ERROR; |
@@ -279,30 +311,35 @@ static efi_status_t efi_install_fdt(void *fdt) | |||
279 | return EFI_OUT_OF_RESOURCES; | 311 | return EFI_OUT_OF_RESOURCES; |
280 | 312 | ||
281 | /* And reserve the space in the memory map */ | 313 | /* And reserve the space in the memory map */ |
282 | fdt_start = ((ulong)fdt) & ~EFI_PAGE_MASK; | 314 | fdt_start = fdt_addr; |
283 | fdt_end = ((ulong)fdt) + fdt_totalsize(fdt); | ||
284 | fdt_size = (fdt_end - fdt_start) + EFI_PAGE_MASK; | ||
285 | fdt_pages = fdt_size >> EFI_PAGE_SHIFT; | 315 | fdt_pages = fdt_size >> EFI_PAGE_SHIFT; |
286 | /* Give a bootloader the chance to modify the device tree */ | 316 | |
287 | fdt_pages += 2; | ||
288 | ret = efi_add_memory_map(fdt_start, fdt_pages, | 317 | ret = efi_add_memory_map(fdt_start, fdt_pages, |
289 | EFI_BOOT_SERVICES_DATA, true); | 318 | EFI_BOOT_SERVICES_DATA, true); |
319 | |||
290 | return ret; | 320 | return ret; |
291 | } | 321 | } |
292 | 322 | ||
293 | /* | 323 | /** |
294 | * Load an EFI payload into a newly allocated piece of memory, register all | 324 | * do_bootefi_exec() - execute EFI binary |
295 | * EFI objects it would want to access and jump to it. | 325 | * |
326 | * @efi: address of the binary | ||
327 | * @device_path: path of the device from which the binary was loaded | ||
328 | * @image_path: device path of the binary | ||
329 | * Return: status code | ||
330 | * | ||
331 | * Load the EFI binary into a newly assigned memory unwinding the relocation | ||
332 | * information, install the loaded image protocol, and call the binary. | ||
296 | */ | 333 | */ |
297 | static efi_status_t do_bootefi_exec(void *efi, | 334 | static efi_status_t do_bootefi_exec(void *efi, |
298 | struct efi_device_path *device_path, | 335 | struct efi_device_path *device_path, |
299 | struct efi_device_path *image_path) | 336 | struct efi_device_path *image_path) |
300 | { | 337 | { |
301 | struct efi_loaded_image loaded_image_info = {}; | 338 | efi_handle_t mem_handle = NULL; |
302 | struct efi_object loaded_image_info_obj = {}; | ||
303 | struct efi_object mem_obj = {}; | ||
304 | struct efi_device_path *memdp = NULL; | 339 | struct efi_device_path *memdp = NULL; |
305 | efi_status_t ret; | 340 | efi_status_t ret; |
341 | struct efi_loaded_image_obj *image_handle = NULL; | ||
342 | struct efi_loaded_image *loaded_image_info = NULL; | ||
306 | 343 | ||
307 | EFIAPI efi_status_t (*entry)(efi_handle_t image_handle, | 344 | EFIAPI efi_status_t (*entry)(efi_handle_t image_handle, |
308 | struct efi_system_table *st); | 345 | struct efi_system_table *st); |
@@ -310,16 +347,21 @@ static efi_status_t do_bootefi_exec(void *efi, | |||
310 | /* | 347 | /* |
311 | * Special case for efi payload not loaded from disk, such as | 348 | * Special case for efi payload not loaded from disk, such as |
312 | * 'bootefi hello' or for example payload loaded directly into | 349 | * 'bootefi hello' or for example payload loaded directly into |
313 | * memory via jtag/etc: | 350 | * memory via jtag, etc: |
314 | */ | 351 | */ |
315 | if (!device_path && !image_path) { | 352 | if (!device_path && !image_path) { |
316 | printf("WARNING: using memory device/image path, this may confuse some payloads!\n"); | 353 | printf("WARNING: using memory device/image path, this may confuse some payloads!\n"); |
317 | /* actual addresses filled in after efi_load_pe() */ | 354 | /* actual addresses filled in after efi_load_pe() */ |
318 | memdp = efi_dp_from_mem(0, 0, 0); | 355 | memdp = efi_dp_from_mem(0, 0, 0); |
319 | device_path = image_path = memdp; | 356 | device_path = image_path = memdp; |
320 | efi_add_handle(&mem_obj); | 357 | /* |
321 | 358 | * Grub expects that the device path of the loaded image is | |
322 | ret = efi_add_protocol(mem_obj.handle, &efi_guid_device_path, | 359 | * installed on a handle. |
360 | */ | ||
361 | ret = efi_create_handle(&mem_handle); | ||
362 | if (ret != EFI_SUCCESS) | ||
363 | goto exit; | ||
364 | ret = efi_add_protocol(mem_handle, &efi_guid_device_path, | ||
323 | device_path); | 365 | device_path); |
324 | if (ret != EFI_SUCCESS) | 366 | if (ret != EFI_SUCCESS) |
325 | goto exit; | 367 | goto exit; |
@@ -327,8 +369,10 @@ static efi_status_t do_bootefi_exec(void *efi, | |||
327 | assert(device_path && image_path); | 369 | assert(device_path && image_path); |
328 | } | 370 | } |
329 | 371 | ||
330 | efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj, | 372 | ret = efi_setup_loaded_image(device_path, image_path, &image_handle, |
331 | device_path, image_path); | 373 | &loaded_image_info); |
374 | if (ret != EFI_SUCCESS) | ||
375 | goto exit; | ||
332 | 376 | ||
333 | /* | 377 | /* |
334 | * gd lives in a fixed register which may get clobbered while we execute | 378 | * gd lives in a fixed register which may get clobbered while we execute |
@@ -337,9 +381,9 @@ static efi_status_t do_bootefi_exec(void *efi, | |||
337 | efi_save_gd(); | 381 | efi_save_gd(); |
338 | 382 | ||
339 | /* Transfer environment variable bootargs as load options */ | 383 | /* Transfer environment variable bootargs as load options */ |
340 | set_load_options(&loaded_image_info, "bootargs"); | 384 | set_load_options(loaded_image_info, "bootargs"); |
341 | /* Load the EFI payload */ | 385 | /* Load the EFI payload */ |
342 | entry = efi_load_pe(efi, &loaded_image_info); | 386 | entry = efi_load_pe(image_handle, efi, loaded_image_info); |
343 | if (!entry) { | 387 | if (!entry) { |
344 | ret = EFI_LOAD_ERROR; | 388 | ret = EFI_LOAD_ERROR; |
345 | goto exit; | 389 | goto exit; |
@@ -347,10 +391,10 @@ static efi_status_t do_bootefi_exec(void *efi, | |||
347 | 391 | ||
348 | if (memdp) { | 392 | if (memdp) { |
349 | struct efi_device_path_memory *mdp = (void *)memdp; | 393 | struct efi_device_path_memory *mdp = (void *)memdp; |
350 | mdp->memory_type = loaded_image_info.image_code_type; | 394 | mdp->memory_type = loaded_image_info->image_code_type; |
351 | mdp->start_address = (uintptr_t)loaded_image_info.image_base; | 395 | mdp->start_address = (uintptr_t)loaded_image_info->image_base; |
352 | mdp->end_address = mdp->start_address + | 396 | mdp->end_address = mdp->start_address + |
353 | loaded_image_info.image_size; | 397 | loaded_image_info->image_size; |
354 | } | 398 | } |
355 | 399 | ||
356 | /* we don't support much: */ | 400 | /* we don't support much: */ |
@@ -360,8 +404,8 @@ static efi_status_t do_bootefi_exec(void *efi, | |||
360 | /* Call our payload! */ | 404 | /* Call our payload! */ |
361 | debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry); | 405 | debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry); |
362 | 406 | ||
363 | if (setjmp(&loaded_image_info.exit_jmp)) { | 407 | if (setjmp(&image_handle->exit_jmp)) { |
364 | ret = loaded_image_info.exit_status; | 408 | ret = image_handle->exit_status; |
365 | goto exit; | 409 | goto exit; |
366 | } | 410 | } |
367 | 411 | ||
@@ -373,7 +417,7 @@ static efi_status_t do_bootefi_exec(void *efi, | |||
373 | 417 | ||
374 | /* Move into EL2 and keep running there */ | 418 | /* Move into EL2 and keep running there */ |
375 | armv8_switch_to_el2((ulong)entry, | 419 | armv8_switch_to_el2((ulong)entry, |
376 | (ulong)&loaded_image_info_obj.handle, | 420 | (ulong)image_handle, |
377 | (ulong)&systab, 0, (ulong)efi_run_in_el2, | 421 | (ulong)&systab, 0, (ulong)efi_run_in_el2, |
378 | ES_TO_AARCH64); | 422 | ES_TO_AARCH64); |
379 | 423 | ||
@@ -390,7 +434,7 @@ static efi_status_t do_bootefi_exec(void *efi, | |||
390 | secure_ram_addr(_do_nonsec_entry)( | 434 | secure_ram_addr(_do_nonsec_entry)( |
391 | efi_run_in_hyp, | 435 | efi_run_in_hyp, |
392 | (uintptr_t)entry, | 436 | (uintptr_t)entry, |
393 | (uintptr_t)loaded_image_info_obj.handle, | 437 | (uintptr_t)image_handle, |
394 | (uintptr_t)&systab); | 438 | (uintptr_t)&systab); |
395 | 439 | ||
396 | /* Should never reach here, efi exits with longjmp */ | 440 | /* Should never reach here, efi exits with longjmp */ |
@@ -398,13 +442,14 @@ static efi_status_t do_bootefi_exec(void *efi, | |||
398 | } | 442 | } |
399 | #endif | 443 | #endif |
400 | 444 | ||
401 | ret = efi_do_enter(loaded_image_info_obj.handle, &systab, entry); | 445 | ret = efi_do_enter(image_handle, &systab, entry); |
402 | 446 | ||
403 | exit: | 447 | exit: |
404 | /* image has returned, loaded-image obj goes *poof*: */ | 448 | /* image has returned, loaded-image obj goes *poof*: */ |
405 | list_del(&loaded_image_info_obj.link); | 449 | if (image_handle) |
406 | if (mem_obj.handle) | 450 | efi_delete_handle(&image_handle->parent); |
407 | list_del(&mem_obj.link); | 451 | if (mem_handle) |
452 | efi_delete_handle(mem_handle); | ||
408 | 453 | ||
409 | return ret; | 454 | return ret; |
410 | } | 455 | } |
@@ -443,7 +488,6 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | |||
443 | char *saddr; | 488 | char *saddr; |
444 | efi_status_t r; | 489 | efi_status_t r; |
445 | unsigned long fdt_addr; | 490 | unsigned long fdt_addr; |
446 | void *fdt; | ||
447 | 491 | ||
448 | /* Allow unaligned memory access */ | 492 | /* Allow unaligned memory access */ |
449 | allow_unaligned(); | 493 | allow_unaligned(); |
@@ -464,8 +508,7 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | |||
464 | if (!fdt_addr && *argv[2] != '0') | 508 | if (!fdt_addr && *argv[2] != '0') |
465 | return CMD_RET_USAGE; | 509 | return CMD_RET_USAGE; |
466 | /* Install device tree */ | 510 | /* Install device tree */ |
467 | fdt = map_sysmem(fdt_addr, 0); | 511 | r = efi_install_fdt(fdt_addr); |
468 | r = efi_install_fdt(fdt); | ||
469 | if (r != EFI_SUCCESS) { | 512 | if (r != EFI_SUCCESS) { |
470 | printf("ERROR: failed to install device tree\n"); | 513 | printf("ERROR: failed to install device tree\n"); |
471 | return CMD_RET_FAILURE; | 514 | return CMD_RET_FAILURE; |
@@ -489,8 +532,8 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | |||
489 | #endif | 532 | #endif |
490 | #ifdef CONFIG_CMD_BOOTEFI_SELFTEST | 533 | #ifdef CONFIG_CMD_BOOTEFI_SELFTEST |
491 | if (!strcmp(argv[1], "selftest")) { | 534 | if (!strcmp(argv[1], "selftest")) { |
492 | struct efi_loaded_image loaded_image_info = {}; | 535 | struct efi_loaded_image_obj *image_handle; |
493 | struct efi_object loaded_image_info_obj = {}; | 536 | struct efi_loaded_image *loaded_image_info; |
494 | 537 | ||
495 | /* Construct a dummy device path. */ | 538 | /* Construct a dummy device path. */ |
496 | bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, | 539 | bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, |
@@ -498,9 +541,12 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | |||
498 | (uintptr_t)&efi_selftest); | 541 | (uintptr_t)&efi_selftest); |
499 | bootefi_image_path = efi_dp_from_file(NULL, 0, "\\selftest"); | 542 | bootefi_image_path = efi_dp_from_file(NULL, 0, "\\selftest"); |
500 | 543 | ||
501 | efi_setup_loaded_image(&loaded_image_info, | 544 | r = efi_setup_loaded_image(bootefi_device_path, |
502 | &loaded_image_info_obj, | 545 | bootefi_image_path, &image_handle, |
503 | bootefi_device_path, bootefi_image_path); | 546 | &loaded_image_info); |
547 | if (r != EFI_SUCCESS) | ||
548 | return CMD_RET_FAILURE; | ||
549 | |||
504 | /* | 550 | /* |
505 | * gd lives in a fixed register which may get clobbered while we | 551 | * gd lives in a fixed register which may get clobbered while we |
506 | * execute the payload. So save it here and restore it on every | 552 | * execute the payload. So save it here and restore it on every |
@@ -508,12 +554,12 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | |||
508 | */ | 554 | */ |
509 | efi_save_gd(); | 555 | efi_save_gd(); |
510 | /* Transfer environment variable efi_selftest as load options */ | 556 | /* Transfer environment variable efi_selftest as load options */ |
511 | set_load_options(&loaded_image_info, "efi_selftest"); | 557 | set_load_options(loaded_image_info, "efi_selftest"); |
512 | /* Execute the test */ | 558 | /* Execute the test */ |
513 | r = efi_selftest(loaded_image_info_obj.handle, &systab); | 559 | r = efi_selftest(image_handle, &systab); |
514 | efi_restore_gd(); | 560 | efi_restore_gd(); |
515 | free(loaded_image_info.load_options); | 561 | free(loaded_image_info->load_options); |
516 | list_del(&loaded_image_info_obj.link); | 562 | efi_delete_handle(&image_handle->parent); |
517 | return r != EFI_SUCCESS; | 563 | return r != EFI_SUCCESS; |
518 | } else | 564 | } else |
519 | #endif | 565 | #endif |
@@ -575,6 +621,13 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path) | |||
575 | char filename[32] = { 0 }; /* dp->str is u16[32] long */ | 621 | char filename[32] = { 0 }; /* dp->str is u16[32] long */ |
576 | char *s; | 622 | char *s; |
577 | 623 | ||
624 | /* efi_set_bootdev is typically called repeatedly, recover memory */ | ||
625 | efi_free_pool(bootefi_device_path); | ||
626 | efi_free_pool(bootefi_image_path); | ||
627 | /* If blk_get_device_part_str fails, avoid duplicate free. */ | ||
628 | bootefi_device_path = NULL; | ||
629 | bootefi_image_path = NULL; | ||
630 | |||
578 | if (strcmp(dev, "Net")) { | 631 | if (strcmp(dev, "Net")) { |
579 | struct blk_desc *desc; | 632 | struct blk_desc *desc; |
580 | disk_partition_t fs_partition; | 633 | disk_partition_t fs_partition; |
@@ -104,6 +104,7 @@ static int do_fat_fswrite(cmd_tbl_t *cmdtp, int flag, | |||
104 | int ret; | 104 | int ret; |
105 | unsigned long addr; | 105 | unsigned long addr; |
106 | unsigned long count; | 106 | unsigned long count; |
107 | long offset; | ||
107 | struct blk_desc *dev_desc = NULL; | 108 | struct blk_desc *dev_desc = NULL; |
108 | disk_partition_t info; | 109 | disk_partition_t info; |
109 | int dev = 0; | 110 | int dev = 0; |
@@ -126,9 +127,11 @@ static int do_fat_fswrite(cmd_tbl_t *cmdtp, int flag, | |||
126 | } | 127 | } |
127 | addr = simple_strtoul(argv[3], NULL, 16); | 128 | addr = simple_strtoul(argv[3], NULL, 16); |
128 | count = (argc <= 5) ? 0 : simple_strtoul(argv[5], NULL, 16); | 129 | count = (argc <= 5) ? 0 : simple_strtoul(argv[5], NULL, 16); |
130 | /* offset should be a hex, but "-1" is allowed */ | ||
131 | offset = (argc <= 6) ? 0 : simple_strtol(argv[6], NULL, 16); | ||
129 | 132 | ||
130 | buf = map_sysmem(addr, count); | 133 | buf = map_sysmem(addr, count); |
131 | ret = file_fat_write(argv[4], buf, 0, count, &size); | 134 | ret = file_fat_write(argv[4], buf, offset, count, &size); |
132 | unmap_sysmem(buf); | 135 | unmap_sysmem(buf); |
133 | if (ret < 0) { | 136 | if (ret < 0) { |
134 | printf("\n** Unable to write \"%s\" from %s %d:%d **\n", | 137 | printf("\n** Unable to write \"%s\" from %s %d:%d **\n", |
@@ -142,10 +145,35 @@ static int do_fat_fswrite(cmd_tbl_t *cmdtp, int flag, | |||
142 | } | 145 | } |
143 | 146 | ||
144 | U_BOOT_CMD( | 147 | U_BOOT_CMD( |
145 | fatwrite, 6, 0, do_fat_fswrite, | 148 | fatwrite, 7, 0, do_fat_fswrite, |
146 | "write file into a dos filesystem", | 149 | "write file into a dos filesystem", |
147 | "<interface> <dev[:part]> <addr> <filename> [<bytes>]\n" | 150 | "<interface> <dev[:part]> <addr> <filename> [<bytes> [<offset>]]\n" |
148 | " - write file 'filename' from the address 'addr' in RAM\n" | 151 | " - write file 'filename' from the address 'addr' in RAM\n" |
149 | " to 'dev' on 'interface'" | 152 | " to 'dev' on 'interface'" |
150 | ); | 153 | ); |
154 | |||
155 | static int do_fat_rm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | ||
156 | { | ||
157 | return do_rm(cmdtp, flag, argc, argv, FS_TYPE_FAT); | ||
158 | } | ||
159 | |||
160 | U_BOOT_CMD( | ||
161 | fatrm, 4, 1, do_fat_rm, | ||
162 | "delete a file", | ||
163 | "<interface> [<dev[:part]>] <filename>\n" | ||
164 | " - delete a file from 'dev' on 'interface'" | ||
165 | ); | ||
166 | |||
167 | static int do_fat_mkdir(cmd_tbl_t *cmdtp, int flag, int argc, | ||
168 | char * const argv[]) | ||
169 | { | ||
170 | return do_mkdir(cmdtp, flag, argc, argv, FS_TYPE_FAT); | ||
171 | } | ||
172 | |||
173 | U_BOOT_CMD( | ||
174 | fatmkdir, 4, 1, do_fat_mkdir, | ||
175 | "create a directory", | ||
176 | "<interface> [<dev[:part]>] <directory>\n" | ||
177 | " - create a directory in 'dev' on 'interface'" | ||
178 | ); | ||
151 | #endif | 179 | #endif |