1
2
3
4
5
6
7
8#define LOG_CATEGORY LOGC_EFI
9
10#include <common.h>
11#include <bootm.h>
12#include <charset.h>
13#include <command.h>
14#include <dm.h>
15#include <efi_loader.h>
16#include <efi_selftest.h>
17#include <env.h>
18#include <errno.h>
19#include <image.h>
20#include <log.h>
21#include <malloc.h>
22#include <asm/global_data.h>
23#include <linux/libfdt.h>
24#include <linux/libfdt_env.h>
25#include <mapmem.h>
26#include <memalign.h>
27#include <asm-generic/sections.h>
28#include <linux/linkage.h>
29
30DECLARE_GLOBAL_DATA_PTR;
31
32static struct efi_device_path *bootefi_image_path;
33static struct efi_device_path *bootefi_device_path;
34static void *image_addr;
35static size_t image_size;
36
37
38
39
40static void efi_clear_bootdev(void)
41{
42 efi_free_pool(bootefi_device_path);
43 efi_free_pool(bootefi_image_path);
44 bootefi_device_path = NULL;
45 bootefi_image_path = NULL;
46 image_addr = NULL;
47 image_size = 0;
48}
49
50
51
52
53
54
55
56
57
58
59
60
61
62void efi_set_bootdev(const char *dev, const char *devnr, const char *path,
63 void *buffer, size_t buffer_size)
64{
65 struct efi_device_path *device, *image;
66 efi_status_t ret;
67
68
69 if (buffer + buffer_size >= image_addr &&
70 image_addr + image_size >= buffer)
71 efi_clear_bootdev();
72
73
74 if (efi_check_pe(buffer, buffer_size, NULL) != EFI_SUCCESS) {
75#ifdef CONFIG_FIT
76 if (fit_check_format(buffer, IMAGE_SIZE_INVAL))
77 return;
78
79
80
81
82 buffer = 0;
83 buffer_size = 0;
84#else
85 return;
86#endif
87 }
88
89
90 efi_clear_bootdev();
91
92 image_addr = buffer;
93 image_size = buffer_size;
94
95 ret = efi_dp_from_name(dev, devnr, path, &device, &image);
96 if (ret == EFI_SUCCESS) {
97 bootefi_device_path = device;
98 if (image) {
99
100 struct efi_device_path *image_tmp = image;
101
102 efi_dp_split_file_path(image, &device, &image);
103 efi_free_pool(image_tmp);
104 }
105 bootefi_image_path = image;
106 } else {
107 efi_clear_bootdev();
108 }
109}
110
111
112
113
114
115
116
117
118
119static efi_status_t efi_env_set_load_options(efi_handle_t handle,
120 const char *env_var,
121 u16 **load_options)
122{
123 const char *env = env_get(env_var);
124 size_t size;
125 u16 *pos;
126 efi_status_t ret;
127
128 *load_options = NULL;
129 if (!env)
130 return EFI_SUCCESS;
131 size = sizeof(u16) * (utf8_utf16_strlen(env) + 1);
132 pos = calloc(size, 1);
133 if (!pos)
134 return EFI_OUT_OF_RESOURCES;
135 *load_options = pos;
136 utf8_utf16_strcpy(&pos, env);
137 ret = efi_set_load_options(handle, size, *load_options);
138 if (ret != EFI_SUCCESS) {
139 free(*load_options);
140 *load_options = NULL;
141 }
142 return ret;
143}
144
145#if !CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
146
147
148
149
150
151
152
153
154
155
156
157
158
159static efi_status_t copy_fdt(void **fdtp)
160{
161 unsigned long fdt_ram_start = -1L, fdt_pages;
162 efi_status_t ret = 0;
163 void *fdt, *new_fdt;
164 u64 new_fdt_addr;
165 uint fdt_size;
166 int i;
167
168 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
169 u64 ram_start = gd->bd->bi_dram[i].start;
170 u64 ram_size = gd->bd->bi_dram[i].size;
171
172 if (!ram_size)
173 continue;
174
175 if (ram_start < fdt_ram_start)
176 fdt_ram_start = ram_start;
177 }
178
179
180
181
182
183 fdt = *fdtp;
184 fdt_pages = efi_size_in_pages(fdt_totalsize(fdt) + 0x3000);
185 fdt_size = fdt_pages << EFI_PAGE_SHIFT;
186
187
188
189
190
191 new_fdt_addr = (uintptr_t)map_sysmem(fdt_ram_start + 0x7f00000 +
192 fdt_size, 0);
193 ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
194 EFI_ACPI_RECLAIM_MEMORY, fdt_pages,
195 &new_fdt_addr);
196 if (ret != EFI_SUCCESS) {
197
198 new_fdt_addr = (ulong)memalign(EFI_PAGE_SIZE, fdt_size);
199 ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
200 EFI_ACPI_RECLAIM_MEMORY, fdt_pages,
201 &new_fdt_addr);
202 if (ret != EFI_SUCCESS) {
203 log_err("ERROR: Failed to reserve space for FDT\n");
204 goto done;
205 }
206 }
207 new_fdt = (void *)(uintptr_t)new_fdt_addr;
208 memcpy(new_fdt, fdt, fdt_totalsize(fdt));
209 fdt_set_totalsize(new_fdt, fdt_size);
210
211 *fdtp = (void *)(uintptr_t)new_fdt_addr;
212done:
213 return ret;
214}
215
216
217
218
219
220
221
222static void *get_config_table(const efi_guid_t *guid)
223{
224 size_t i;
225
226 for (i = 0; i < systab.nr_tables; i++) {
227 if (!guidcmp(guid, &systab.tables[i].guid))
228 return systab.tables[i].table;
229 }
230 return NULL;
231}
232
233#endif
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252efi_status_t efi_install_fdt(void *fdt)
253{
254
255
256
257
258#if CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
259 if (fdt) {
260 log_err("ERROR: can't have ACPI table and device tree.\n");
261 return EFI_LOAD_ERROR;
262 }
263#else
264 bootm_headers_t img = { 0 };
265 efi_status_t ret;
266
267 if (fdt == EFI_FDT_USE_INTERNAL) {
268 const char *fdt_opt;
269 uintptr_t fdt_addr;
270
271
272 if (get_config_table(&efi_guid_fdt))
273 return EFI_SUCCESS;
274
275 fdt_opt = env_get("fdt_addr");
276
277 if (!fdt_opt) {
278 fdt_opt = env_get("fdtcontroladdr");
279 if (!fdt_opt) {
280 log_err("ERROR: need device tree\n");
281 return EFI_NOT_FOUND;
282 }
283 }
284 fdt_addr = simple_strtoul(fdt_opt, NULL, 16);
285 if (!fdt_addr) {
286 log_err("ERROR: invalid $fdt_addr or $fdtcontroladdr\n");
287 return EFI_LOAD_ERROR;
288 }
289 fdt = map_sysmem(fdt_addr, 0);
290 }
291
292
293 if (fdt_check_header(fdt)) {
294 log_err("ERROR: invalid device tree\n");
295 return EFI_LOAD_ERROR;
296 }
297
298
299 ret = copy_fdt(&fdt);
300 if (ret) {
301 log_err("ERROR: out of memory\n");
302 return EFI_OUT_OF_RESOURCES;
303 }
304
305 if (image_setup_libfdt(&img, fdt, 0, NULL)) {
306 log_err("ERROR: failed to process device tree\n");
307 return EFI_LOAD_ERROR;
308 }
309
310
311 efi_carve_out_dt_rsv(fdt);
312
313
314 ret = efi_install_configuration_table(&efi_guid_fdt, fdt);
315 if (ret != EFI_SUCCESS) {
316 log_err("ERROR: failed to install device tree\n");
317 return ret;
318 }
319#endif
320
321 return EFI_SUCCESS;
322}
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337static efi_status_t do_bootefi_exec(efi_handle_t handle, void *load_options)
338{
339 efi_status_t ret;
340 efi_uintn_t exit_data_size = 0;
341 u16 *exit_data = NULL;
342
343
344 switch_to_non_secure_mode();
345
346
347 ret = EFI_CALL(efi_start_image(handle, &exit_data_size, &exit_data));
348 if (ret != EFI_SUCCESS) {
349 log_err("## Application failed, r = %lu\n",
350 ret & ~EFI_ERROR_MASK);
351 if (exit_data) {
352 log_err("## %ls\n", exit_data);
353 efi_free_pool(exit_data);
354 }
355 }
356
357 efi_restore_gd();
358
359 free(load_options);
360
361 if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD))
362 efi_initrd_deregister();
363
364 return ret;
365}
366
367
368
369
370
371
372static int do_efibootmgr(void)
373{
374 efi_handle_t handle;
375 efi_status_t ret;
376 void *load_options;
377
378 ret = efi_bootmgr_load(&handle, &load_options);
379 if (ret != EFI_SUCCESS) {
380 log_notice("EFI boot manager: Cannot load any image\n");
381 return CMD_RET_FAILURE;
382 }
383
384 ret = do_bootefi_exec(handle, load_options);
385
386 if (ret != EFI_SUCCESS)
387 return CMD_RET_FAILURE;
388
389 return CMD_RET_SUCCESS;
390}
391
392
393
394
395
396
397
398
399
400
401static int do_bootefi_image(const char *image_opt)
402{
403 void *image_buf;
404 unsigned long addr, size;
405 efi_status_t ret;
406
407#ifdef CONFIG_CMD_BOOTEFI_HELLO
408 if (!strcmp(image_opt, "hello")) {
409 image_buf = __efi_helloworld_begin;
410 size = __efi_helloworld_end - __efi_helloworld_begin;
411 efi_clear_bootdev();
412 } else
413#endif
414 {
415 addr = strtoul(image_opt, NULL, 16);
416
417 if (!addr)
418 return CMD_RET_USAGE;
419
420 image_buf = map_sysmem(addr, 0);
421
422 if (image_buf != image_addr) {
423 log_err("No UEFI binary known at %s\n", image_opt);
424 return CMD_RET_FAILURE;
425 }
426 size = image_size;
427 }
428 ret = efi_run_image(image_buf, size);
429
430 if (ret != EFI_SUCCESS)
431 return CMD_RET_FAILURE;
432
433 return CMD_RET_SUCCESS;
434}
435
436
437
438
439
440
441
442
443efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size)
444{
445 efi_handle_t mem_handle = NULL, handle;
446 struct efi_device_path *file_path = NULL;
447 struct efi_device_path *msg_path;
448 efi_status_t ret;
449 u16 *load_options;
450
451 if (!bootefi_device_path || !bootefi_image_path) {
452
453
454
455
456
457 file_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
458 (uintptr_t)source_buffer,
459 source_size);
460
461
462
463
464 ret = efi_create_handle(&mem_handle);
465 if (ret != EFI_SUCCESS)
466 goto out;
467
468 ret = efi_add_protocol(mem_handle, &efi_guid_device_path,
469 file_path);
470 if (ret != EFI_SUCCESS)
471 goto out;
472 msg_path = file_path;
473 } else {
474 file_path = efi_dp_append(bootefi_device_path,
475 bootefi_image_path);
476 msg_path = bootefi_image_path;
477 }
478
479 log_info("Booting %pD\n", msg_path);
480
481 ret = EFI_CALL(efi_load_image(false, efi_root, file_path, source_buffer,
482 source_size, &handle));
483 if (ret != EFI_SUCCESS) {
484 log_err("Loading image failed\n");
485 goto out;
486 }
487
488
489 ret = efi_env_set_load_options(handle, "bootargs", &load_options);
490 if (ret != EFI_SUCCESS)
491 goto out;
492
493 ret = do_bootefi_exec(handle, load_options);
494
495out:
496 efi_delete_handle(mem_handle);
497 efi_free_pool(file_path);
498 return ret;
499}
500
501#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
502static efi_status_t bootefi_run_prepare(const char *load_options_path,
503 struct efi_device_path *device_path,
504 struct efi_device_path *image_path,
505 struct efi_loaded_image_obj **image_objp,
506 struct efi_loaded_image **loaded_image_infop)
507{
508 efi_status_t ret;
509 u16 *load_options;
510
511 ret = efi_setup_loaded_image(device_path, image_path, image_objp,
512 loaded_image_infop);
513 if (ret != EFI_SUCCESS)
514 return ret;
515
516
517 return efi_env_set_load_options((efi_handle_t)*image_objp,
518 load_options_path,
519 &load_options);
520}
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535static efi_status_t bootefi_test_prepare
536 (struct efi_loaded_image_obj **image_objp,
537 struct efi_loaded_image **loaded_image_infop, const char *path,
538 const char *load_options_path)
539{
540 efi_status_t ret;
541
542
543 bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, 0, 0);
544 if (!bootefi_device_path)
545 return EFI_OUT_OF_RESOURCES;
546
547 bootefi_image_path = efi_dp_from_file(NULL, 0, path);
548 if (!bootefi_image_path) {
549 ret = EFI_OUT_OF_RESOURCES;
550 goto failure;
551 }
552
553 ret = bootefi_run_prepare(load_options_path, bootefi_device_path,
554 bootefi_image_path, image_objp,
555 loaded_image_infop);
556 if (ret == EFI_SUCCESS)
557 return ret;
558
559failure:
560 efi_clear_bootdev();
561 return ret;
562}
563
564
565
566
567
568
569
570static void bootefi_run_finish(struct efi_loaded_image_obj *image_obj,
571 struct efi_loaded_image *loaded_image_info)
572{
573 efi_restore_gd();
574 free(loaded_image_info->load_options);
575 efi_delete_handle(&image_obj->header);
576}
577
578
579
580
581
582
583static int do_efi_selftest(void)
584{
585 struct efi_loaded_image_obj *image_obj;
586 struct efi_loaded_image *loaded_image_info;
587 efi_status_t ret;
588
589 ret = bootefi_test_prepare(&image_obj, &loaded_image_info,
590 "\\selftest", "efi_selftest");
591 if (ret != EFI_SUCCESS)
592 return CMD_RET_FAILURE;
593
594
595 ret = EFI_CALL(efi_selftest(&image_obj->header, &systab));
596 bootefi_run_finish(image_obj, loaded_image_info);
597
598 return ret != EFI_SUCCESS;
599}
600#endif
601
602
603
604
605
606
607
608
609
610
611static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc,
612 char *const argv[])
613{
614 efi_status_t ret;
615 void *fdt;
616
617 if (argc < 2)
618 return CMD_RET_USAGE;
619
620
621 ret = efi_init_obj_list();
622 if (ret != EFI_SUCCESS) {
623 log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n",
624 ret & ~EFI_ERROR_MASK);
625 return CMD_RET_FAILURE;
626 }
627
628 if (argc > 2) {
629 uintptr_t fdt_addr;
630
631 fdt_addr = simple_strtoul(argv[2], NULL, 16);
632 fdt = map_sysmem(fdt_addr, 0);
633 } else {
634 fdt = EFI_FDT_USE_INTERNAL;
635 }
636 ret = efi_install_fdt(fdt);
637 if (ret == EFI_INVALID_PARAMETER)
638 return CMD_RET_USAGE;
639 else if (ret != EFI_SUCCESS)
640 return CMD_RET_FAILURE;
641
642 if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR)) {
643 if (!strcmp(argv[1], "bootmgr"))
644 return do_efibootmgr();
645 }
646#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
647 if (!strcmp(argv[1], "selftest"))
648 return do_efi_selftest();
649#endif
650
651 return do_bootefi_image(argv[1]);
652}
653
654#ifdef CONFIG_SYS_LONGHELP
655static char bootefi_help_text[] =
656 "<image address> [fdt address]\n"
657 " - boot EFI payload stored at address <image address>.\n"
658 " If specified, the device tree located at <fdt address> gets\n"
659 " exposed as EFI configuration table.\n"
660#ifdef CONFIG_CMD_BOOTEFI_HELLO
661 "bootefi hello\n"
662 " - boot a sample Hello World application stored within U-Boot\n"
663#endif
664#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
665 "bootefi selftest [fdt address]\n"
666 " - boot an EFI selftest application stored within U-Boot\n"
667 " Use environment variable efi_selftest to select a single test.\n"
668 " Use 'setenv efi_selftest list' to enumerate all tests.\n"
669#endif
670#ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
671 "bootefi bootmgr [fdt address]\n"
672 " - load and boot EFI payload based on BootOrder/BootXXXX variables.\n"
673 "\n"
674 " If specified, the device tree located at <fdt address> gets\n"
675 " exposed as EFI configuration table.\n"
676#endif
677 ;
678#endif
679
680U_BOOT_CMD(
681 bootefi, 3, 0, do_bootefi,
682 "Boots an EFI payload from memory",
683 bootefi_help_text
684);
685