]> Git Repo - J-u-boot.git/blame - common/bootm_os.c
Fix some checkpatch warnings in calls to debug()
[J-u-boot.git] / common / bootm_os.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
b6396403
SG
2/*
3 * (C) Copyright 2000-2009
4 * Wolfgang Denk, DENX Software Engineering, [email protected].
b6396403
SG
5 */
6
7#include <common.h>
8#include <bootm.h>
52f24238 9#include <bootstage.h>
9edefc27 10#include <cpu_func.h>
ecc7fdaa 11#include <efi_loader.h>
c7694dd4 12#include <env.h>
b6396403 13#include <fdt_support.h>
4d72caa5
SG
14#include <image.h>
15#include <lmb.h>
b08c8c48 16#include <linux/libfdt.h>
b6396403 17#include <malloc.h>
ecc7fdaa 18#include <mapmem.h>
b6396403 19#include <vxworks.h>
c225e7cf 20#include <tee/optee.h>
b6396403
SG
21
22DECLARE_GLOBAL_DATA_PTR;
23
09140113 24static int do_bootm_standalone(int flag, int argc, char *const argv[],
b6396403
SG
25 bootm_headers_t *images)
26{
27 char *s;
28 int (*appl)(int, char *const[]);
29
30 /* Don't start if "autostart" is set to "no" */
00caae6d 31 s = env_get("autostart");
b6396403 32 if ((s != NULL) && !strcmp(s, "no")) {
018f5303 33 env_set_hex("filesize", images->os.image_len);
b6396403
SG
34 return 0;
35 }
36 appl = (int (*)(int, char * const []))images->ep;
37 appl(argc, argv);
38 return 0;
39}
40
41/*******************************************************************/
42/* OS booting routines */
43/*******************************************************************/
44
45#if defined(CONFIG_BOOTM_NETBSD) || defined(CONFIG_BOOTM_PLAN9)
09140113 46static void copy_args(char *dest, int argc, char *const argv[], char delim)
b6396403
SG
47{
48 int i;
49
50 for (i = 0; i < argc; i++) {
51 if (i > 0)
52 *dest++ = delim;
53 strcpy(dest, argv[i]);
54 dest += strlen(argv[i]);
55 }
56}
57#endif
58
59#ifdef CONFIG_BOOTM_NETBSD
09140113
SG
60static int do_bootm_netbsd(int flag, int argc, char *const argv[],
61 bootm_headers_t *images)
b6396403
SG
62{
63 void (*loader)(bd_t *, image_header_t *, char *, char *);
64 image_header_t *os_hdr, *hdr;
65 ulong kernel_data, kernel_len;
b6396403
SG
66 char *cmdline;
67
68 if (flag != BOOTM_STATE_OS_GO)
69 return 0;
70
71#if defined(CONFIG_FIT)
72 if (!images->legacy_hdr_valid) {
73 fit_unsupported_reset("NetBSD");
74 return 1;
75 }
76#endif
77 hdr = images->legacy_hdr_os;
78
79 /*
80 * Booting a (NetBSD) kernel image
81 *
82 * This process is pretty similar to a standalone application:
83 * The (first part of an multi-) image must be a stage-2 loader,
84 * which in turn is responsible for loading & invoking the actual
85 * kernel. The only differences are the parameters being passed:
86 * besides the board info strucure, the loader expects a command
87 * line, the name of the console device, and (optionally) the
88 * address of the original image header.
89 */
90 os_hdr = NULL;
91 if (image_check_type(&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) {
92 image_multi_getimg(hdr, 1, &kernel_data, &kernel_len);
93 if (kernel_len)
94 os_hdr = hdr;
95 }
96
b6396403
SG
97 if (argc > 0) {
98 ulong len;
99 int i;
100
101 for (i = 0, len = 0; i < argc; i += 1)
102 len += strlen(argv[i]) + 1;
103 cmdline = malloc(len);
104 copy_args(cmdline, argc, argv, ' ');
105 } else {
00caae6d 106 cmdline = env_get("bootargs");
b6396403
SG
107 if (cmdline == NULL)
108 cmdline = "";
109 }
110
111 loader = (void (*)(bd_t *, image_header_t *, char *, char *))images->ep;
112
113 printf("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n",
114 (ulong)loader);
115
116 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
117
118 /*
119 * NetBSD Stage-2 Loader Parameters:
120 * arg[0]: pointer to board info data
121 * arg[1]: image load address
122 * arg[2]: char pointer to the console device to use
123 * arg[3]: char pointer to the boot arguments
124 */
5b8e76c3 125 (*loader)(gd->bd, os_hdr, "", cmdline);
b6396403
SG
126
127 return 1;
128}
129#endif /* CONFIG_BOOTM_NETBSD*/
130
131#ifdef CONFIG_LYNXKDI
09140113
SG
132static int do_bootm_lynxkdi(int flag, int argc, char *const argv[],
133 bootm_headers_t *images)
b6396403
SG
134{
135 image_header_t *hdr = &images->legacy_hdr_os_copy;
136
137 if (flag != BOOTM_STATE_OS_GO)
138 return 0;
139
140#if defined(CONFIG_FIT)
141 if (!images->legacy_hdr_valid) {
142 fit_unsupported_reset("Lynx");
143 return 1;
144 }
145#endif
146
147 lynxkdi_boot((image_header_t *)hdr);
148
149 return 1;
150}
151#endif /* CONFIG_LYNXKDI */
152
153#ifdef CONFIG_BOOTM_RTEMS
09140113
SG
154static int do_bootm_rtems(int flag, int argc, char *const argv[],
155 bootm_headers_t *images)
b6396403
SG
156{
157 void (*entry_point)(bd_t *);
158
159 if (flag != BOOTM_STATE_OS_GO)
160 return 0;
161
162#if defined(CONFIG_FIT)
163 if (!images->legacy_hdr_valid) {
164 fit_unsupported_reset("RTEMS");
165 return 1;
166 }
167#endif
168
169 entry_point = (void (*)(bd_t *))images->ep;
170
171 printf("## Transferring control to RTEMS (at address %08lx) ...\n",
172 (ulong)entry_point);
173
174 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
175
176 /*
177 * RTEMS Parameters:
178 * r3: ptr to board info data
179 */
180 (*entry_point)(gd->bd);
181
182 return 1;
183}
184#endif /* CONFIG_BOOTM_RTEMS */
185
186#if defined(CONFIG_BOOTM_OSE)
09140113
SG
187static int do_bootm_ose(int flag, int argc, char *const argv[],
188 bootm_headers_t *images)
b6396403
SG
189{
190 void (*entry_point)(void);
191
192 if (flag != BOOTM_STATE_OS_GO)
193 return 0;
194
195#if defined(CONFIG_FIT)
196 if (!images->legacy_hdr_valid) {
197 fit_unsupported_reset("OSE");
198 return 1;
199 }
200#endif
201
202 entry_point = (void (*)(void))images->ep;
203
204 printf("## Transferring control to OSE (at address %08lx) ...\n",
205 (ulong)entry_point);
206
207 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
208
209 /*
210 * OSE Parameters:
211 * None
212 */
213 (*entry_point)();
214
215 return 1;
216}
217#endif /* CONFIG_BOOTM_OSE */
218
219#if defined(CONFIG_BOOTM_PLAN9)
09140113
SG
220static int do_bootm_plan9(int flag, int argc, char *const argv[],
221 bootm_headers_t *images)
b6396403
SG
222{
223 void (*entry_point)(void);
224 char *s;
225
226 if (flag != BOOTM_STATE_OS_GO)
227 return 0;
228
229#if defined(CONFIG_FIT)
230 if (!images->legacy_hdr_valid) {
231 fit_unsupported_reset("Plan 9");
232 return 1;
233 }
234#endif
235
236 /* See README.plan9 */
00caae6d 237 s = env_get("confaddr");
b6396403
SG
238 if (s != NULL) {
239 char *confaddr = (char *)simple_strtoul(s, NULL, 16);
240
241 if (argc > 0) {
242 copy_args(confaddr, argc, argv, '\n');
243 } else {
00caae6d 244 s = env_get("bootargs");
b6396403
SG
245 if (s != NULL)
246 strcpy(confaddr, s);
247 }
248 }
249
250 entry_point = (void (*)(void))images->ep;
251
252 printf("## Transferring control to Plan 9 (at address %08lx) ...\n",
253 (ulong)entry_point);
254
255 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
256
257 /*
258 * Plan 9 Parameters:
259 * None
260 */
261 (*entry_point)();
262
263 return 1;
264}
265#endif /* CONFIG_BOOTM_PLAN9 */
266
267#if defined(CONFIG_BOOTM_VXWORKS) && \
268 (defined(CONFIG_PPC) || defined(CONFIG_ARM))
269
7ebfb378 270static void do_bootvx_fdt(bootm_headers_t *images)
b6396403
SG
271{
272#if defined(CONFIG_OF_LIBFDT)
273 int ret;
274 char *bootline;
275 ulong of_size = images->ft_len;
276 char **of_flat_tree = &images->ft_addr;
277 struct lmb *lmb = &images->lmb;
278
279 if (*of_flat_tree) {
280 boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree);
281
282 ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size);
283 if (ret)
284 return;
285
a223e2bc
HS
286 /* Update ethernet nodes */
287 fdt_fixup_ethernet(*of_flat_tree);
288
b6396403
SG
289 ret = fdt_add_subnode(*of_flat_tree, 0, "chosen");
290 if ((ret >= 0 || ret == -FDT_ERR_EXISTS)) {
00caae6d 291 bootline = env_get("bootargs");
b6396403
SG
292 if (bootline) {
293 ret = fdt_find_and_setprop(*of_flat_tree,
294 "/chosen", "bootargs",
295 bootline,
296 strlen(bootline) + 1, 1);
297 if (ret < 0) {
298 printf("## ERROR: %s : %s\n", __func__,
299 fdt_strerror(ret));
300 return;
301 }
302 }
303 } else {
304 printf("## ERROR: %s : %s\n", __func__,
305 fdt_strerror(ret));
306 return;
307 }
308 }
309#endif
310
311 boot_prep_vxworks(images);
312
313 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
314
315#if defined(CONFIG_OF_LIBFDT)
316 printf("## Starting vxWorks at 0x%08lx, device tree at 0x%08lx ...\n",
317 (ulong)images->ep, (ulong)*of_flat_tree);
318#else
319 printf("## Starting vxWorks at 0x%08lx\n", (ulong)images->ep);
320#endif
321
322 boot_jump_vxworks(images);
323
324 puts("## vxWorks terminated\n");
325}
326
09140113 327static int do_bootm_vxworks_legacy(int flag, int argc, char *const argv[],
1e26f648 328 bootm_headers_t *images)
b6396403
SG
329{
330 if (flag != BOOTM_STATE_OS_GO)
331 return 0;
332
333#if defined(CONFIG_FIT)
334 if (!images->legacy_hdr_valid) {
335 fit_unsupported_reset("VxWorks");
336 return 1;
337 }
338#endif
339
340 do_bootvx_fdt(images);
341
342 return 1;
343}
1e26f648 344
09140113 345int do_bootm_vxworks(int flag, int argc, char *const argv[],
1e26f648
LZ
346 bootm_headers_t *images)
347{
348 char *bootargs;
349 int pos;
350 unsigned long vxflags;
351 bool std_dtb = false;
352
353 /* get bootargs env */
354 bootargs = env_get("bootargs");
355
356 if (bootargs != NULL) {
357 for (pos = 0; pos < strlen(bootargs); pos++) {
358 /* find f=0xnumber flag */
359 if ((bootargs[pos] == '=') && (pos >= 1) &&
360 (bootargs[pos - 1] == 'f')) {
361 vxflags = simple_strtoul(&bootargs[pos + 1],
362 NULL, 16);
363 if (vxflags & VXWORKS_SYSFLG_STD_DTB)
364 std_dtb = true;
365 }
366 }
367 }
368
369 if (std_dtb) {
370 if (flag & BOOTM_STATE_OS_PREP)
371 printf(" Using standard DTB\n");
372 return do_bootm_linux(flag, argc, argv, images);
373 } else {
374 if (flag & BOOTM_STATE_OS_PREP)
375 printf(" !!! WARNING !!! Using legacy DTB\n");
376 return do_bootm_vxworks_legacy(flag, argc, argv, images);
377 }
378}
b6396403
SG
379#endif
380
381#if defined(CONFIG_CMD_ELF)
09140113
SG
382static int do_bootm_qnxelf(int flag, int argc, char *const argv[],
383 bootm_headers_t *images)
b6396403
SG
384{
385 char *local_args[2];
386 char str[16];
995eab8b 387 int dcache;
b6396403
SG
388
389 if (flag != BOOTM_STATE_OS_GO)
390 return 0;
391
392#if defined(CONFIG_FIT)
393 if (!images->legacy_hdr_valid) {
394 fit_unsupported_reset("QNX");
395 return 1;
396 }
397#endif
398
399 sprintf(str, "%lx", images->ep); /* write entry-point into string */
400 local_args[0] = argv[0];
401 local_args[1] = str; /* and provide it via the arguments */
995eab8b
EV
402
403 /*
404 * QNX images require the data cache is disabled.
405 */
406 dcache = dcache_status();
407 if (dcache)
408 dcache_disable();
409
b6396403
SG
410 do_bootelf(NULL, 0, 2, local_args);
411
995eab8b
EV
412 if (dcache)
413 dcache_enable();
414
b6396403
SG
415 return 1;
416}
417#endif
418
419#ifdef CONFIG_INTEGRITY
09140113
SG
420static int do_bootm_integrity(int flag, int argc, char *const argv[],
421 bootm_headers_t *images)
b6396403
SG
422{
423 void (*entry_point)(void);
424
425 if (flag != BOOTM_STATE_OS_GO)
426 return 0;
427
428#if defined(CONFIG_FIT)
429 if (!images->legacy_hdr_valid) {
430 fit_unsupported_reset("INTEGRITY");
431 return 1;
432 }
433#endif
434
435 entry_point = (void (*)(void))images->ep;
436
437 printf("## Transferring control to INTEGRITY (at address %08lx) ...\n",
438 (ulong)entry_point);
439
440 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
441
442 /*
443 * INTEGRITY Parameters:
444 * None
445 */
446 (*entry_point)();
447
448 return 1;
449}
450#endif
451
67ddd955 452#ifdef CONFIG_BOOTM_OPENRTOS
09140113
SG
453static int do_bootm_openrtos(int flag, int argc, char *const argv[],
454 bootm_headers_t *images)
67ddd955
MV
455{
456 void (*entry_point)(void);
457
458 if (flag != BOOTM_STATE_OS_GO)
459 return 0;
460
461 entry_point = (void (*)(void))images->ep;
462
463 printf("## Transferring control to OpenRTOS (at address %08lx) ...\n",
464 (ulong)entry_point);
465
466 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
467
468 /*
469 * OpenRTOS Parameters:
470 * None
471 */
472 (*entry_point)();
473
474 return 1;
475}
476#endif
477
c225e7cf 478#ifdef CONFIG_BOOTM_OPTEE
09140113 479static int do_bootm_tee(int flag, int argc, char *const argv[],
c225e7cf
BD
480 bootm_headers_t *images)
481{
482 int ret;
483
484 /* Verify OS type */
485 if (images->os.os != IH_OS_TEE) {
486 return 1;
487 };
488
489 /* Validate OPTEE header */
490 ret = optee_verify_bootm_image(images->os.image_start,
491 images->os.load,
492 images->os.image_len);
493 if (ret)
494 return ret;
495
496 /* Locate FDT etc */
497 ret = bootm_find_images(flag, argc, argv);
498 if (ret)
499 return ret;
500
501 /* From here we can run the regular linux boot path */
502 return do_bootm_linux(flag, argc, argv, images);
503}
504#endif
505
ecc7fdaa 506#ifdef CONFIG_BOOTM_EFI
09140113 507static int do_bootm_efi(int flag, int argc, char *const argv[],
ecc7fdaa
CC
508 bootm_headers_t *images)
509{
510 int ret;
511 efi_status_t efi_ret;
512 void *image_buf;
513
514 if (flag != BOOTM_STATE_OS_GO)
515 return 0;
516
517 /* Locate FDT, if provided */
518 ret = bootm_find_images(flag, argc, argv);
519 if (ret)
520 return ret;
521
522 /* Initialize EFI drivers */
523 efi_ret = efi_init_obj_list();
524 if (efi_ret != EFI_SUCCESS) {
525 printf("## Failed to initialize UEFI sub-system: r = %lu\n",
526 efi_ret & ~EFI_ERROR_MASK);
527 return 1;
528 }
529
530 /* Install device tree */
531 efi_ret = efi_install_fdt(images->ft_len
532 ? images->ft_addr : EFI_FDT_USE_INTERNAL);
533 if (efi_ret != EFI_SUCCESS) {
534 printf("## Failed to install device tree: r = %lu\n",
535 efi_ret & ~EFI_ERROR_MASK);
536 return 1;
537 }
538
539 /* Run EFI image */
540 printf("## Transferring control to EFI (at address %08lx) ...\n",
541 images->ep);
542 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
543
544 image_buf = map_sysmem(images->ep, images->os.image_len);
545
546 efi_ret = efi_run_image(image_buf, images->os.image_len);
547 if (efi_ret != EFI_SUCCESS) {
548 printf("## Failed to run EFI image: r = %lu\n",
549 efi_ret & ~EFI_ERROR_MASK);
550 return 1;
551 }
552
553 return 0;
554}
555#endif
556
b6396403
SG
557static boot_os_fn *boot_os[] = {
558 [IH_OS_U_BOOT] = do_bootm_standalone,
559#ifdef CONFIG_BOOTM_LINUX
560 [IH_OS_LINUX] = do_bootm_linux,
561#endif
562#ifdef CONFIG_BOOTM_NETBSD
563 [IH_OS_NETBSD] = do_bootm_netbsd,
564#endif
565#ifdef CONFIG_LYNXKDI
566 [IH_OS_LYNXOS] = do_bootm_lynxkdi,
567#endif
568#ifdef CONFIG_BOOTM_RTEMS
569 [IH_OS_RTEMS] = do_bootm_rtems,
570#endif
571#if defined(CONFIG_BOOTM_OSE)
572 [IH_OS_OSE] = do_bootm_ose,
573#endif
574#if defined(CONFIG_BOOTM_PLAN9)
575 [IH_OS_PLAN9] = do_bootm_plan9,
576#endif
577#if defined(CONFIG_BOOTM_VXWORKS) && \
08337cd6 578 (defined(CONFIG_PPC) || defined(CONFIG_ARM) || defined(CONFIG_RISCV))
b6396403
SG
579 [IH_OS_VXWORKS] = do_bootm_vxworks,
580#endif
581#if defined(CONFIG_CMD_ELF)
582 [IH_OS_QNX] = do_bootm_qnxelf,
583#endif
584#ifdef CONFIG_INTEGRITY
585 [IH_OS_INTEGRITY] = do_bootm_integrity,
586#endif
67ddd955
MV
587#ifdef CONFIG_BOOTM_OPENRTOS
588 [IH_OS_OPENRTOS] = do_bootm_openrtos,
589#endif
c225e7cf
BD
590#ifdef CONFIG_BOOTM_OPTEE
591 [IH_OS_TEE] = do_bootm_tee,
592#endif
ecc7fdaa
CC
593#ifdef CONFIG_BOOTM_EFI
594 [IH_OS_EFI] = do_bootm_efi,
595#endif
b6396403
SG
596};
597
598/* Allow for arch specific config before we boot */
82c3a4c4 599__weak void arch_preboot_os(void)
b6396403
SG
600{
601 /* please define platform specific arch_preboot_os() */
602}
b6396403 603
fd3d1212
MV
604/* Allow for board specific config before we boot */
605__weak void board_preboot_os(void)
606{
607 /* please define board specific board_preboot_os() */
608}
609
09140113 610int boot_selected_os(int argc, char *const argv[], int state,
b6396403
SG
611 bootm_headers_t *images, boot_os_fn *boot_fn)
612{
613 arch_preboot_os();
fd3d1212 614 board_preboot_os();
b6396403
SG
615 boot_fn(state, argc, argv, images);
616
617 /* Stand-alone may return when 'autostart' is 'no' */
618 if (images->os.type == IH_TYPE_STANDALONE ||
b9c771b0 619 IS_ENABLED(CONFIG_SANDBOX) ||
b6396403
SG
620 state == BOOTM_STATE_OS_FAKE_GO) /* We expect to return */
621 return 0;
622 bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED);
851bda81
LM
623 debug("\n## Control returned to monitor - resetting...\n");
624
b6396403
SG
625 return BOOTM_ERR_RESET;
626}
627
628boot_os_fn *bootm_os_get_boot_func(int os)
629{
630#ifdef CONFIG_NEEDS_MANUAL_RELOC
631 static bool relocated;
632
633 if (!relocated) {
634 int i;
635
636 /* relocate boot function table */
637 for (i = 0; i < ARRAY_SIZE(boot_os); i++)
638 if (boot_os[i] != NULL)
639 boot_os[i] += gd->reloc_off;
640
641 relocated = true;
642 }
643#endif
644 return boot_os[os];
645}
This page took 0.381404 seconds and 4 git commands to generate.