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