1
2
3
4
5
6
7#include <common.h>
8#include <bootm.h>
9#include <bootstage.h>
10#include <cpu_func.h>
11#include <efi_loader.h>
12#include <env.h>
13#include <fdt_support.h>
14#include <image.h>
15#include <lmb.h>
16#include <log.h>
17#include <asm/global_data.h>
18#include <linux/libfdt.h>
19#include <malloc.h>
20#include <mapmem.h>
21#include <vxworks.h>
22#include <tee/optee.h>
23
24DECLARE_GLOBAL_DATA_PTR;
25
26static int do_bootm_standalone(int flag, int argc, char *const argv[],
27 bootm_headers_t *images)
28{
29 char *s;
30 int (*appl)(int, char *const[]);
31
32
33 s = env_get("autostart");
34 if ((s != NULL) && !strcmp(s, "no")) {
35 env_set_hex("filesize", images->os.image_len);
36 return 0;
37 }
38 appl = (int (*)(int, char * const []))images->ep;
39 appl(argc, argv);
40 return 0;
41}
42
43
44
45
46
47#if defined(CONFIG_BOOTM_NETBSD) || defined(CONFIG_BOOTM_PLAN9)
48static void copy_args(char *dest, int argc, char *const argv[], char delim)
49{
50 int i;
51
52 for (i = 0; i < argc; i++) {
53 if (i > 0)
54 *dest++ = delim;
55 strcpy(dest, argv[i]);
56 dest += strlen(argv[i]);
57 }
58}
59#endif
60
61static void __maybe_unused fit_unsupported_reset(const char *msg)
62{
63 if (CONFIG_IS_ENABLED(FIT_VERBOSE)) {
64 printf("! FIT images not supported for '%s' - must reset board to recover!\n",
65 msg);
66 }
67}
68
69#ifdef CONFIG_BOOTM_NETBSD
70static int do_bootm_netbsd(int flag, int argc, char *const argv[],
71 bootm_headers_t *images)
72{
73 void (*loader)(struct bd_info *, image_header_t *, char *, char *);
74 image_header_t *os_hdr, *hdr;
75 ulong kernel_data, kernel_len;
76 char *cmdline;
77
78 if (flag != BOOTM_STATE_OS_GO)
79 return 0;
80
81#if defined(CONFIG_FIT)
82 if (!images->legacy_hdr_valid) {
83 fit_unsupported_reset("NetBSD");
84 return 1;
85 }
86#endif
87 hdr = images->legacy_hdr_os;
88
89
90
91
92
93
94
95
96
97
98
99
100 os_hdr = NULL;
101 if (image_check_type(&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) {
102 image_multi_getimg(hdr, 1, &kernel_data, &kernel_len);
103 if (kernel_len)
104 os_hdr = hdr;
105 }
106
107 if (argc > 0) {
108 ulong len;
109 int i;
110
111 for (i = 0, len = 0; i < argc; i += 1)
112 len += strlen(argv[i]) + 1;
113 cmdline = malloc(len);
114 copy_args(cmdline, argc, argv, ' ');
115 } else {
116 cmdline = env_get("bootargs");
117 if (cmdline == NULL)
118 cmdline = "";
119 }
120
121 loader = (void (*)(struct bd_info *, image_header_t *, char *, char *))images->ep;
122
123 printf("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n",
124 (ulong)loader);
125
126 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
127
128
129
130
131
132
133
134
135 (*loader)(gd->bd, os_hdr, "", cmdline);
136
137 return 1;
138}
139#endif
140
141#ifdef CONFIG_BOOTM_RTEMS
142static int do_bootm_rtems(int flag, int argc, char *const argv[],
143 bootm_headers_t *images)
144{
145 void (*entry_point)(struct bd_info *);
146
147 if (flag != BOOTM_STATE_OS_GO)
148 return 0;
149
150#if defined(CONFIG_FIT)
151 if (!images->legacy_hdr_valid) {
152 fit_unsupported_reset("RTEMS");
153 return 1;
154 }
155#endif
156
157 entry_point = (void (*)(struct bd_info *))images->ep;
158
159 printf("## Transferring control to RTEMS (at address %08lx) ...\n",
160 (ulong)entry_point);
161
162 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
163
164
165
166
167
168 (*entry_point)(gd->bd);
169
170 return 1;
171}
172#endif
173
174#if defined(CONFIG_BOOTM_OSE)
175static int do_bootm_ose(int flag, int argc, char *const argv[],
176 bootm_headers_t *images)
177{
178 void (*entry_point)(void);
179
180 if (flag != BOOTM_STATE_OS_GO)
181 return 0;
182
183#if defined(CONFIG_FIT)
184 if (!images->legacy_hdr_valid) {
185 fit_unsupported_reset("OSE");
186 return 1;
187 }
188#endif
189
190 entry_point = (void (*)(void))images->ep;
191
192 printf("## Transferring control to OSE (at address %08lx) ...\n",
193 (ulong)entry_point);
194
195 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
196
197
198
199
200
201 (*entry_point)();
202
203 return 1;
204}
205#endif
206
207#if defined(CONFIG_BOOTM_PLAN9)
208static int do_bootm_plan9(int flag, int argc, char *const argv[],
209 bootm_headers_t *images)
210{
211 void (*entry_point)(void);
212 char *s;
213
214 if (flag != BOOTM_STATE_OS_GO)
215 return 0;
216
217#if defined(CONFIG_FIT)
218 if (!images->legacy_hdr_valid) {
219 fit_unsupported_reset("Plan 9");
220 return 1;
221 }
222#endif
223
224
225 s = env_get("confaddr");
226 if (s != NULL) {
227 char *confaddr = (char *)hextoul(s, NULL);
228
229 if (argc > 0) {
230 copy_args(confaddr, argc, argv, '\n');
231 } else {
232 s = env_get("bootargs");
233 if (s != NULL)
234 strcpy(confaddr, s);
235 }
236 }
237
238 entry_point = (void (*)(void))images->ep;
239
240 printf("## Transferring control to Plan 9 (at address %08lx) ...\n",
241 (ulong)entry_point);
242
243 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
244
245
246
247
248
249 (*entry_point)();
250
251 return 1;
252}
253#endif
254
255#if defined(CONFIG_BOOTM_VXWORKS) && \
256 (defined(CONFIG_PPC) || defined(CONFIG_ARM))
257
258static void do_bootvx_fdt(bootm_headers_t *images)
259{
260#if defined(CONFIG_OF_LIBFDT)
261 int ret;
262 char *bootline;
263 ulong of_size = images->ft_len;
264 char **of_flat_tree = &images->ft_addr;
265 struct lmb *lmb = &images->lmb;
266
267 if (*of_flat_tree) {
268 boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree);
269
270 ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size);
271 if (ret)
272 return;
273
274
275 fdt_fixup_ethernet(*of_flat_tree);
276
277 ret = fdt_add_subnode(*of_flat_tree, 0, "chosen");
278 if ((ret >= 0 || ret == -FDT_ERR_EXISTS)) {
279 bootline = env_get("bootargs");
280 if (bootline) {
281 ret = fdt_find_and_setprop(*of_flat_tree,
282 "/chosen", "bootargs",
283 bootline,
284 strlen(bootline) + 1, 1);
285 if (ret < 0) {
286 printf("## ERROR: %s : %s\n", __func__,
287 fdt_strerror(ret));
288 return;
289 }
290 }
291 } else {
292 printf("## ERROR: %s : %s\n", __func__,
293 fdt_strerror(ret));
294 return;
295 }
296 }
297#endif
298
299 boot_prep_vxworks(images);
300
301 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
302
303#if defined(CONFIG_OF_LIBFDT)
304 printf("## Starting vxWorks at 0x%08lx, device tree at 0x%08lx ...\n",
305 (ulong)images->ep, (ulong)*of_flat_tree);
306#else
307 printf("## Starting vxWorks at 0x%08lx\n", (ulong)images->ep);
308#endif
309
310 boot_jump_vxworks(images);
311
312 puts("## vxWorks terminated\n");
313}
314
315static int do_bootm_vxworks_legacy(int flag, int argc, char *const argv[],
316 bootm_headers_t *images)
317{
318 if (flag != BOOTM_STATE_OS_GO)
319 return 0;
320
321#if defined(CONFIG_FIT)
322 if (!images->legacy_hdr_valid) {
323 fit_unsupported_reset("VxWorks");
324 return 1;
325 }
326#endif
327
328 do_bootvx_fdt(images);
329
330 return 1;
331}
332
333int do_bootm_vxworks(int flag, int argc, char *const argv[],
334 bootm_headers_t *images)
335{
336 char *bootargs;
337 int pos;
338 unsigned long vxflags;
339 bool std_dtb = false;
340
341
342 bootargs = env_get("bootargs");
343
344 if (bootargs != NULL) {
345 for (pos = 0; pos < strlen(bootargs); pos++) {
346
347 if ((bootargs[pos] == '=') && (pos >= 1) &&
348 (bootargs[pos - 1] == 'f')) {
349 vxflags = hextoul(&bootargs[pos + 1], NULL);
350 if (vxflags & VXWORKS_SYSFLG_STD_DTB)
351 std_dtb = true;
352 }
353 }
354 }
355
356 if (std_dtb) {
357 if (flag & BOOTM_STATE_OS_PREP)
358 printf(" Using standard DTB\n");
359 return do_bootm_linux(flag, argc, argv, images);
360 } else {
361 if (flag & BOOTM_STATE_OS_PREP)
362 printf(" !!! WARNING !!! Using legacy DTB\n");
363 return do_bootm_vxworks_legacy(flag, argc, argv, images);
364 }
365}
366#endif
367
368#if defined(CONFIG_CMD_ELF)
369static int do_bootm_qnxelf(int flag, int argc, char *const argv[],
370 bootm_headers_t *images)
371{
372 char *local_args[2];
373 char str[16];
374 int dcache;
375
376 if (flag != BOOTM_STATE_OS_GO)
377 return 0;
378
379#if defined(CONFIG_FIT)
380 if (!images->legacy_hdr_valid) {
381 fit_unsupported_reset("QNX");
382 return 1;
383 }
384#endif
385
386 sprintf(str, "%lx", images->ep);
387 local_args[0] = argv[0];
388 local_args[1] = str;
389
390
391
392
393 dcache = dcache_status();
394 if (dcache)
395 dcache_disable();
396
397 do_bootelf(NULL, 0, 2, local_args);
398
399 if (dcache)
400 dcache_enable();
401
402 return 1;
403}
404#endif
405
406#ifdef CONFIG_INTEGRITY
407static int do_bootm_integrity(int flag, int argc, char *const argv[],
408 bootm_headers_t *images)
409{
410 void (*entry_point)(void);
411
412 if (flag != BOOTM_STATE_OS_GO)
413 return 0;
414
415#if defined(CONFIG_FIT)
416 if (!images->legacy_hdr_valid) {
417 fit_unsupported_reset("INTEGRITY");
418 return 1;
419 }
420#endif
421
422 entry_point = (void (*)(void))images->ep;
423
424 printf("## Transferring control to INTEGRITY (at address %08lx) ...\n",
425 (ulong)entry_point);
426
427 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
428
429
430
431
432
433 (*entry_point)();
434
435 return 1;
436}
437#endif
438
439#ifdef CONFIG_BOOTM_OPENRTOS
440static int do_bootm_openrtos(int flag, int argc, char *const argv[],
441 bootm_headers_t *images)
442{
443 void (*entry_point)(void);
444
445 if (flag != BOOTM_STATE_OS_GO)
446 return 0;
447
448 entry_point = (void (*)(void))images->ep;
449
450 printf("## Transferring control to OpenRTOS (at address %08lx) ...\n",
451 (ulong)entry_point);
452
453 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
454
455
456
457
458
459 (*entry_point)();
460
461 return 1;
462}
463#endif
464
465#ifdef CONFIG_BOOTM_OPTEE
466static int do_bootm_tee(int flag, int argc, char *const argv[],
467 bootm_headers_t *images)
468{
469 int ret;
470
471
472 if (images->os.os != IH_OS_TEE) {
473 return 1;
474 };
475
476
477 ret = optee_verify_bootm_image(images->os.image_start,
478 images->os.load,
479 images->os.image_len);
480 if (ret)
481 return ret;
482
483
484 ret = bootm_find_images(flag, argc, argv, 0, 0);
485 if (ret)
486 return ret;
487
488
489 return do_bootm_linux(flag, argc, argv, images);
490}
491#endif
492
493#ifdef CONFIG_BOOTM_EFI
494static int do_bootm_efi(int flag, int argc, char *const argv[],
495 bootm_headers_t *images)
496{
497 int ret;
498 efi_status_t efi_ret;
499 void *image_buf;
500
501 if (flag != BOOTM_STATE_OS_GO)
502 return 0;
503
504
505 ret = bootm_find_images(flag, argc, argv, 0, 0);
506 if (ret)
507 return ret;
508
509
510 efi_ret = efi_init_obj_list();
511 if (efi_ret != EFI_SUCCESS) {
512 printf("## Failed to initialize UEFI sub-system: r = %lu\n",
513 efi_ret & ~EFI_ERROR_MASK);
514 return 1;
515 }
516
517
518 efi_ret = efi_install_fdt(images->ft_len
519 ? images->ft_addr : EFI_FDT_USE_INTERNAL);
520 if (efi_ret != EFI_SUCCESS) {
521 printf("## Failed to install device tree: r = %lu\n",
522 efi_ret & ~EFI_ERROR_MASK);
523 return 1;
524 }
525
526
527 printf("## Transferring control to EFI (at address %08lx) ...\n",
528 images->ep);
529 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
530
531
532 images->os.type = IH_TYPE_STANDALONE;
533
534 image_buf = map_sysmem(images->ep, images->os.image_len);
535
536 efi_ret = efi_run_image(image_buf, images->os.image_len);
537 if (efi_ret != EFI_SUCCESS)
538 return 1;
539 return 0;
540}
541#endif
542
543static boot_os_fn *boot_os[] = {
544 [IH_OS_U_BOOT] = do_bootm_standalone,
545#ifdef CONFIG_BOOTM_LINUX
546 [IH_OS_LINUX] = do_bootm_linux,
547#endif
548#ifdef CONFIG_BOOTM_NETBSD
549 [IH_OS_NETBSD] = do_bootm_netbsd,
550#endif
551#ifdef CONFIG_BOOTM_RTEMS
552 [IH_OS_RTEMS] = do_bootm_rtems,
553#endif
554#if defined(CONFIG_BOOTM_OSE)
555 [IH_OS_OSE] = do_bootm_ose,
556#endif
557#if defined(CONFIG_BOOTM_PLAN9)
558 [IH_OS_PLAN9] = do_bootm_plan9,
559#endif
560#if defined(CONFIG_BOOTM_VXWORKS) && \
561 (defined(CONFIG_PPC) || defined(CONFIG_ARM) || defined(CONFIG_RISCV))
562 [IH_OS_VXWORKS] = do_bootm_vxworks,
563#endif
564#if defined(CONFIG_CMD_ELF)
565 [IH_OS_QNX] = do_bootm_qnxelf,
566#endif
567#ifdef CONFIG_INTEGRITY
568 [IH_OS_INTEGRITY] = do_bootm_integrity,
569#endif
570#ifdef CONFIG_BOOTM_OPENRTOS
571 [IH_OS_OPENRTOS] = do_bootm_openrtos,
572#endif
573#ifdef CONFIG_BOOTM_OPTEE
574 [IH_OS_TEE] = do_bootm_tee,
575#endif
576#ifdef CONFIG_BOOTM_EFI
577 [IH_OS_EFI] = do_bootm_efi,
578#endif
579};
580
581
582__weak void arch_preboot_os(void)
583{
584
585}
586
587
588__weak void board_preboot_os(void)
589{
590
591}
592
593int boot_selected_os(int argc, char *const argv[], int state,
594 bootm_headers_t *images, boot_os_fn *boot_fn)
595{
596 arch_preboot_os();
597 board_preboot_os();
598 boot_fn(state, argc, argv, images);
599
600
601 if (images->os.type == IH_TYPE_STANDALONE ||
602 IS_ENABLED(CONFIG_SANDBOX) ||
603 state == BOOTM_STATE_OS_FAKE_GO)
604 return 0;
605 bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED);
606 debug("\n## Control returned to monitor - resetting...\n");
607
608 return BOOTM_ERR_RESET;
609}
610
611boot_os_fn *bootm_os_get_boot_func(int os)
612{
613#ifdef CONFIG_NEEDS_MANUAL_RELOC
614 static bool relocated;
615
616 if (!relocated) {
617 int i;
618
619
620 for (i = 0; i < ARRAY_SIZE(boot_os); i++)
621 if (boot_os[i] != NULL)
622 boot_os[i] += gd->reloc_off;
623
624 relocated = true;
625 }
626#endif
627 return boot_os[os];
628}
629