efi_loader: ARM: don't attempt to enter non-secure mode twice
[platform/kernel/u-boot.git] / cmd / bootefi.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  *  EFI application loader
4  *
5  *  Copyright (c) 2016 Alexander Graf
6  */
7
8 #include <charset.h>
9 #include <common.h>
10 #include <command.h>
11 #include <dm.h>
12 #include <efi_loader.h>
13 #include <efi_selftest.h>
14 #include <errno.h>
15 #include <linux/libfdt.h>
16 #include <linux/libfdt_env.h>
17 #include <memalign.h>
18 #include <asm/global_data.h>
19 #include <asm-generic/sections.h>
20 #include <asm-generic/unaligned.h>
21 #include <linux/linkage.h>
22
23 #ifdef CONFIG_ARMV7_NONSEC
24 #include <asm/armv7.h>
25 #include <asm/secure.h>
26 #endif
27
28 DECLARE_GLOBAL_DATA_PTR;
29
30 #define OBJ_LIST_NOT_INITIALIZED 1
31
32 static efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED;
33
34 static struct efi_device_path *bootefi_image_path;
35 static struct efi_device_path *bootefi_device_path;
36
37 /* Initialize and populate EFI object list */
38 efi_status_t efi_init_obj_list(void)
39 {
40         efi_status_t ret = EFI_SUCCESS;
41
42         /* Initialize once only */
43         if (efi_obj_list_initialized != OBJ_LIST_NOT_INITIALIZED)
44                 return efi_obj_list_initialized;
45
46         /* Initialize EFI driver uclass */
47         ret = efi_driver_init();
48         if (ret != EFI_SUCCESS)
49                 goto out;
50
51         ret = efi_console_register();
52         if (ret != EFI_SUCCESS)
53                 goto out;
54 #ifdef CONFIG_PARTITIONS
55         ret = efi_disk_register();
56         if (ret != EFI_SUCCESS)
57                 goto out;
58 #endif
59 #if defined(CONFIG_LCD) || defined(CONFIG_DM_VIDEO)
60         ret = efi_gop_register();
61         if (ret != EFI_SUCCESS)
62                 goto out;
63 #endif
64 #ifdef CONFIG_NET
65         ret = efi_net_register();
66         if (ret != EFI_SUCCESS)
67                 goto out;
68 #endif
69 #ifdef CONFIG_GENERATE_ACPI_TABLE
70         ret = efi_acpi_register();
71         if (ret != EFI_SUCCESS)
72                 goto out;
73 #endif
74 #ifdef CONFIG_GENERATE_SMBIOS_TABLE
75         ret = efi_smbios_register();
76         if (ret != EFI_SUCCESS)
77                 goto out;
78 #endif
79         ret = efi_watchdog_register();
80         if (ret != EFI_SUCCESS)
81                 goto out;
82
83         /* Initialize EFI runtime services */
84         ret = efi_reset_system_init();
85         if (ret != EFI_SUCCESS)
86                 goto out;
87         ret = efi_get_time_init();
88         if (ret != EFI_SUCCESS)
89                 goto out;
90
91 out:
92         efi_obj_list_initialized = ret;
93         return ret;
94 }
95
96 /*
97  * Allow unaligned memory access.
98  *
99  * This routine is overridden by architectures providing this feature.
100  */
101 void __weak allow_unaligned(void)
102 {
103 }
104
105 /*
106  * Set the load options of an image from an environment variable.
107  *
108  * @loaded_image_info:  the image
109  * @env_var:            name of the environment variable
110  */
111 static void set_load_options(struct efi_loaded_image *loaded_image_info,
112                              const char *env_var)
113 {
114         size_t size;
115         const char *env = env_get(env_var);
116
117         loaded_image_info->load_options = NULL;
118         loaded_image_info->load_options_size = 0;
119         if (!env)
120                 return;
121         size = strlen(env) + 1;
122         loaded_image_info->load_options = calloc(size, sizeof(u16));
123         if (!loaded_image_info->load_options) {
124                 printf("ERROR: Out of memory\n");
125                 return;
126         }
127         utf8_to_utf16(loaded_image_info->load_options, (u8 *)env, size);
128         loaded_image_info->load_options_size = size * 2;
129 }
130
131 static void *copy_fdt(void *fdt)
132 {
133         u64 fdt_size = fdt_totalsize(fdt);
134         unsigned long fdt_ram_start = -1L, fdt_pages;
135         u64 new_fdt_addr;
136         void *new_fdt;
137         int i;
138
139         for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
140                 u64 ram_start = gd->bd->bi_dram[i].start;
141                 u64 ram_size = gd->bd->bi_dram[i].size;
142
143                 if (!ram_size)
144                         continue;
145
146                 if (ram_start < fdt_ram_start)
147                         fdt_ram_start = ram_start;
148         }
149
150         /* Give us at least 4kb breathing room */
151         fdt_size = ALIGN(fdt_size + 4096, EFI_PAGE_SIZE);
152         fdt_pages = fdt_size >> EFI_PAGE_SHIFT;
153
154         /* Safe fdt location is at 128MB */
155         new_fdt_addr = fdt_ram_start + (128 * 1024 * 1024) + fdt_size;
156         if (efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
157                                EFI_RUNTIME_SERVICES_DATA, fdt_pages,
158                                &new_fdt_addr) != EFI_SUCCESS) {
159                 /* If we can't put it there, put it somewhere */
160                 new_fdt_addr = (ulong)memalign(EFI_PAGE_SIZE, fdt_size);
161                 if (efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
162                                        EFI_RUNTIME_SERVICES_DATA, fdt_pages,
163                                        &new_fdt_addr) != EFI_SUCCESS) {
164                         printf("ERROR: Failed to reserve space for FDT\n");
165                         return NULL;
166                 }
167         }
168
169         new_fdt = (void*)(ulong)new_fdt_addr;
170         memcpy(new_fdt, fdt, fdt_totalsize(fdt));
171         fdt_set_totalsize(new_fdt, fdt_size);
172
173         return new_fdt;
174 }
175
176 static efi_status_t efi_do_enter(
177                         efi_handle_t image_handle, struct efi_system_table *st,
178                         EFIAPI efi_status_t (*entry)(
179                                 efi_handle_t image_handle,
180                                 struct efi_system_table *st))
181 {
182         efi_status_t ret = EFI_LOAD_ERROR;
183
184         if (entry)
185                 ret = entry(image_handle, st);
186         st->boottime->exit(image_handle, ret, 0, NULL);
187         return ret;
188 }
189
190 #ifdef CONFIG_ARM64
191 static efi_status_t efi_run_in_el2(EFIAPI efi_status_t (*entry)(
192                         efi_handle_t image_handle, struct efi_system_table *st),
193                         efi_handle_t image_handle, struct efi_system_table *st)
194 {
195         /* Enable caches again */
196         dcache_enable();
197
198         return efi_do_enter(image_handle, st, entry);
199 }
200 #endif
201
202 #ifdef CONFIG_ARMV7_NONSEC
203 static bool is_nonsec;
204
205 static efi_status_t efi_run_in_hyp(EFIAPI efi_status_t (*entry)(
206                         efi_handle_t image_handle, struct efi_system_table *st),
207                         efi_handle_t image_handle, struct efi_system_table *st)
208 {
209         /* Enable caches again */
210         dcache_enable();
211
212         is_nonsec = true;
213
214         return efi_do_enter(image_handle, st, entry);
215 }
216 #endif
217
218 /* Carve out DT reserved memory ranges */
219 static efi_status_t efi_carve_out_dt_rsv(void *fdt)
220 {
221         int nr_rsv, i;
222         uint64_t addr, size, pages;
223
224         nr_rsv = fdt_num_mem_rsv(fdt);
225
226         /* Look for an existing entry and add it to the efi mem map. */
227         for (i = 0; i < nr_rsv; i++) {
228                 if (fdt_get_mem_rsv(fdt, i, &addr, &size) != 0)
229                         continue;
230
231                 pages = ALIGN(size, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT;
232                 efi_add_memory_map(addr, pages, EFI_RESERVED_MEMORY_TYPE,
233                                    false);
234         }
235
236         return EFI_SUCCESS;
237 }
238
239 static efi_status_t efi_install_fdt(void *fdt)
240 {
241         bootm_headers_t img = { 0 };
242         ulong fdt_pages, fdt_size, fdt_start, fdt_end;
243         efi_status_t ret;
244
245         if (fdt_check_header(fdt)) {
246                 printf("ERROR: invalid device tree\n");
247                 return EFI_INVALID_PARAMETER;
248         }
249
250         /* Prepare fdt for payload */
251         fdt = copy_fdt(fdt);
252         if (!fdt)
253                 return EFI_OUT_OF_RESOURCES;
254
255         if (image_setup_libfdt(&img, fdt, 0, NULL)) {
256                 printf("ERROR: failed to process device tree\n");
257                 return EFI_LOAD_ERROR;
258         }
259
260         if (efi_carve_out_dt_rsv(fdt) != EFI_SUCCESS) {
261                 printf("ERROR: failed to carve out memory\n");
262                 return EFI_LOAD_ERROR;
263         }
264
265         /* Link to it in the efi tables */
266         ret = efi_install_configuration_table(&efi_guid_fdt, fdt);
267         if (ret != EFI_SUCCESS)
268                 return EFI_OUT_OF_RESOURCES;
269
270         /* And reserve the space in the memory map */
271         fdt_start = ((ulong)fdt) & ~EFI_PAGE_MASK;
272         fdt_end = ((ulong)fdt) + fdt_totalsize(fdt);
273         fdt_size = (fdt_end - fdt_start) + EFI_PAGE_MASK;
274         fdt_pages = fdt_size >> EFI_PAGE_SHIFT;
275         /* Give a bootloader the chance to modify the device tree */
276         fdt_pages += 2;
277         ret = efi_add_memory_map(fdt_start, fdt_pages,
278                                  EFI_BOOT_SERVICES_DATA, true);
279         return ret;
280 }
281
282 /*
283  * Load an EFI payload into a newly allocated piece of memory, register all
284  * EFI objects it would want to access and jump to it.
285  */
286 static efi_status_t do_bootefi_exec(void *efi,
287                                     struct efi_device_path *device_path,
288                                     struct efi_device_path *image_path)
289 {
290         struct efi_loaded_image loaded_image_info = {};
291         struct efi_object loaded_image_info_obj = {};
292         struct efi_object mem_obj = {};
293         struct efi_device_path *memdp = NULL;
294         efi_status_t ret;
295
296         EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
297                                      struct efi_system_table *st);
298
299         /*
300          * Special case for efi payload not loaded from disk, such as
301          * 'bootefi hello' or for example payload loaded directly into
302          * memory via jtag/etc:
303          */
304         if (!device_path && !image_path) {
305                 printf("WARNING: using memory device/image path, this may confuse some payloads!\n");
306                 /* actual addresses filled in after efi_load_pe() */
307                 memdp = efi_dp_from_mem(0, 0, 0);
308                 device_path = image_path = memdp;
309                 efi_add_handle(&mem_obj);
310
311                 ret = efi_add_protocol(mem_obj.handle, &efi_guid_device_path,
312                                        device_path);
313                 if (ret != EFI_SUCCESS)
314                         goto exit;
315         } else {
316                 assert(device_path && image_path);
317         }
318
319         efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj,
320                                device_path, image_path);
321
322         /*
323          * gd lives in a fixed register which may get clobbered while we execute
324          * the payload. So save it here and restore it on every callback entry
325          */
326         efi_save_gd();
327
328         /* Transfer environment variable bootargs as load options */
329         set_load_options(&loaded_image_info, "bootargs");
330         /* Load the EFI payload */
331         entry = efi_load_pe(efi, &loaded_image_info);
332         if (!entry) {
333                 ret = EFI_LOAD_ERROR;
334                 goto exit;
335         }
336
337         if (memdp) {
338                 struct efi_device_path_memory *mdp = (void *)memdp;
339                 mdp->memory_type = loaded_image_info.image_code_type;
340                 mdp->start_address = (uintptr_t)loaded_image_info.image_base;
341                 mdp->end_address = mdp->start_address +
342                                 loaded_image_info.image_size;
343         }
344
345         /* we don't support much: */
346         env_set("efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported",
347                 "{ro,boot}(blob)0000000000000000");
348
349         /* Call our payload! */
350         debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry);
351
352         if (setjmp(&loaded_image_info.exit_jmp)) {
353                 ret = loaded_image_info.exit_status;
354                 goto exit;
355         }
356
357 #ifdef CONFIG_ARM64
358         /* On AArch64 we need to make sure we call our payload in < EL3 */
359         if (current_el() == 3) {
360                 smp_kick_all_cpus();
361                 dcache_disable();       /* flush cache before switch to EL2 */
362
363                 /* Move into EL2 and keep running there */
364                 armv8_switch_to_el2((ulong)entry,
365                                     (ulong)&loaded_image_info_obj.handle,
366                                     (ulong)&systab, 0, (ulong)efi_run_in_el2,
367                                     ES_TO_AARCH64);
368
369                 /* Should never reach here, efi exits with longjmp */
370                 while (1) { }
371         }
372 #endif
373
374 #ifdef CONFIG_ARMV7_NONSEC
375         if (armv7_boot_nonsec() && !is_nonsec) {
376                 dcache_disable();       /* flush cache before switch to HYP */
377
378                 armv7_init_nonsec();
379                 secure_ram_addr(_do_nonsec_entry)(
380                                         efi_run_in_hyp,
381                                         (uintptr_t)entry,
382                                         (uintptr_t)loaded_image_info_obj.handle,
383                                         (uintptr_t)&systab);
384
385                 /* Should never reach here, efi exits with longjmp */
386                 while (1) { }
387         }
388 #endif
389
390         ret = efi_do_enter(loaded_image_info_obj.handle, &systab, entry);
391
392 exit:
393         /* image has returned, loaded-image obj goes *poof*: */
394         list_del(&loaded_image_info_obj.link);
395         if (mem_obj.handle)
396                 list_del(&mem_obj.link);
397
398         return ret;
399 }
400
401 static int do_bootefi_bootmgr_exec(void)
402 {
403         struct efi_device_path *device_path, *file_path;
404         void *addr;
405         efi_status_t r;
406
407         /*
408          * gd lives in a fixed register which may get clobbered while we execute
409          * the payload. So save it here and restore it on every callback entry
410          */
411         efi_save_gd();
412
413         addr = efi_bootmgr_load(&device_path, &file_path);
414         if (!addr)
415                 return 1;
416
417         printf("## Starting EFI application at %p ...\n", addr);
418         r = do_bootefi_exec(addr, device_path, file_path);
419         printf("## Application terminated, r = %lu\n",
420                r & ~EFI_ERROR_MASK);
421
422         if (r != EFI_SUCCESS)
423                 return 1;
424
425         return 0;
426 }
427
428 /* Interpreter command to boot an arbitrary EFI image from memory */
429 static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
430 {
431         unsigned long addr;
432         char *saddr;
433         efi_status_t r;
434         void *fdt_addr;
435
436         /* Allow unaligned memory access */
437         allow_unaligned();
438
439         /* Initialize EFI drivers */
440         r = efi_init_obj_list();
441         if (r != EFI_SUCCESS) {
442                 printf("Error: Cannot set up EFI drivers, r = %lu\n",
443                        r & ~EFI_ERROR_MASK);
444                 return CMD_RET_FAILURE;
445         }
446
447         if (argc < 2)
448                 return CMD_RET_USAGE;
449
450         if (argc > 2) {
451                 fdt_addr = (void *)simple_strtoul(argv[2], NULL, 16);
452                 if (!fdt_addr && *argv[2] != '0')
453                         return CMD_RET_USAGE;
454                 /* Install device tree */
455                 r = efi_install_fdt(fdt_addr);
456                 if (r != EFI_SUCCESS) {
457                         printf("ERROR: failed to install device tree\n");
458                         return CMD_RET_FAILURE;
459                 }
460         } else {
461                 /* Remove device tree. EFI_NOT_FOUND can be ignored here */
462                 efi_install_configuration_table(&efi_guid_fdt, NULL);
463                 printf("WARNING: booting without device tree\n");
464         }
465 #ifdef CONFIG_CMD_BOOTEFI_HELLO
466         if (!strcmp(argv[1], "hello")) {
467                 ulong size = __efi_helloworld_end - __efi_helloworld_begin;
468
469                 saddr = env_get("loadaddr");
470                 if (saddr)
471                         addr = simple_strtoul(saddr, NULL, 16);
472                 else
473                         addr = CONFIG_SYS_LOAD_ADDR;
474                 memcpy((char *)addr, __efi_helloworld_begin, size);
475         } else
476 #endif
477 #ifdef CONFIG_CMD_BOOTEFI_SELFTEST
478         if (!strcmp(argv[1], "selftest")) {
479                 struct efi_loaded_image loaded_image_info = {};
480                 struct efi_object loaded_image_info_obj = {};
481
482                 /* Construct a dummy device path. */
483                 bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
484                                                       (uintptr_t)&efi_selftest,
485                                                       (uintptr_t)&efi_selftest);
486                 bootefi_image_path = efi_dp_from_file(NULL, 0, "\\selftest");
487
488                 efi_setup_loaded_image(&loaded_image_info,
489                                        &loaded_image_info_obj,
490                                        bootefi_device_path, bootefi_image_path);
491                 /*
492                  * gd lives in a fixed register which may get clobbered while we
493                  * execute the payload. So save it here and restore it on every
494                  * callback entry
495                  */
496                 efi_save_gd();
497                 /* Transfer environment variable efi_selftest as load options */
498                 set_load_options(&loaded_image_info, "efi_selftest");
499                 /* Execute the test */
500                 r = efi_selftest(loaded_image_info_obj.handle, &systab);
501                 efi_restore_gd();
502                 free(loaded_image_info.load_options);
503                 list_del(&loaded_image_info_obj.link);
504                 return r != EFI_SUCCESS;
505         } else
506 #endif
507         if (!strcmp(argv[1], "bootmgr")) {
508                 return do_bootefi_bootmgr_exec();
509         } else {
510                 saddr = argv[1];
511
512                 addr = simple_strtoul(saddr, NULL, 16);
513                 /* Check that a numeric value was passed */
514                 if (!addr && *saddr != '0')
515                         return CMD_RET_USAGE;
516
517         }
518
519         printf("## Starting EFI application at %08lx ...\n", addr);
520         r = do_bootefi_exec((void *)addr, bootefi_device_path,
521                             bootefi_image_path);
522         printf("## Application terminated, r = %lu\n",
523                r & ~EFI_ERROR_MASK);
524
525         if (r != EFI_SUCCESS)
526                 return 1;
527         else
528                 return 0;
529 }
530
531 #ifdef CONFIG_SYS_LONGHELP
532 static char bootefi_help_text[] =
533         "<image address> [fdt address]\n"
534         "  - boot EFI payload stored at address <image address>.\n"
535         "    If specified, the device tree located at <fdt address> gets\n"
536         "    exposed as EFI configuration table.\n"
537 #ifdef CONFIG_CMD_BOOTEFI_HELLO
538         "bootefi hello\n"
539         "  - boot a sample Hello World application stored within U-Boot\n"
540 #endif
541 #ifdef CONFIG_CMD_BOOTEFI_SELFTEST
542         "bootefi selftest [fdt address]\n"
543         "  - boot an EFI selftest application stored within U-Boot\n"
544         "    Use environment variable efi_selftest to select a single test.\n"
545         "    Use 'setenv efi_selftest list' to enumerate all tests.\n"
546 #endif
547         "bootefi bootmgr [fdt addr]\n"
548         "  - load and boot EFI payload based on BootOrder/BootXXXX variables.\n"
549         "\n"
550         "    If specified, the device tree located at <fdt address> gets\n"
551         "    exposed as EFI configuration table.\n";
552 #endif
553
554 U_BOOT_CMD(
555         bootefi, 3, 0, do_bootefi,
556         "Boots an EFI payload from memory",
557         bootefi_help_text
558 );
559
560 void efi_set_bootdev(const char *dev, const char *devnr, const char *path)
561 {
562         char filename[32] = { 0 }; /* dp->str is u16[32] long */
563         char *s;
564
565         if (strcmp(dev, "Net")) {
566                 struct blk_desc *desc;
567                 disk_partition_t fs_partition;
568                 int part;
569
570                 part = blk_get_device_part_str(dev, devnr, &desc, &fs_partition,
571                                                1);
572                 if (part < 0)
573                         return;
574
575                 bootefi_device_path = efi_dp_from_part(desc, part);
576         } else {
577 #ifdef CONFIG_NET
578                 bootefi_device_path = efi_dp_from_eth();
579 #endif
580         }
581
582         if (!path)
583                 return;
584
585         if (strcmp(dev, "Net")) {
586                 /* Add leading / to fs paths, because they're absolute */
587                 snprintf(filename, sizeof(filename), "/%s", path);
588         } else {
589                 snprintf(filename, sizeof(filename), "%s", path);
590         }
591         /* DOS style file path: */
592         s = filename;
593         while ((s = strchr(s, '/')))
594                 *s++ = '\\';
595         bootefi_image_path = efi_dp_from_file(NULL, 0, filename);
596 }