1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2000-2009 4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 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, struct bootm_info *bmi) 27{ 28 struct bootm_headers *images = bmi->images; 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(bmi->argc, bmi->argv); 37 return 0; 38} 39 40/*******************************************************************/ 41/* OS booting routines */ 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, struct bootm_info *bmi) 68{ 69 struct bootm_headers *images = bmi->images; 70 void (*loader)(struct bd_info *bd, struct legacy_img_hdr *hdr, 71 char *console, char *cmdline); 72 struct legacy_img_hdr *os_hdr, *hdr; 73 ulong kernel_data, kernel_len; 74 char *cmdline; 75 76 if (flag != BOOTM_STATE_OS_GO) 77 return 0; 78 79#if defined(CONFIG_FIT) 80 if (!images->legacy_hdr_valid) { 81 fit_unsupported_reset("NetBSD"); 82 return 1; 83 } 84#endif 85 hdr = images->legacy_hdr_os; 86 87 /* 88 * Booting a (NetBSD) kernel image 89 * 90 * This process is pretty similar to a standalone application: 91 * The (first part of an multi-) image must be a stage-2 loader, 92 * which in turn is responsible for loading & invoking the actual 93 * kernel. The only differences are the parameters being passed: 94 * besides the board info strucure, the loader expects a command 95 * line, the name of the console device, and (optionally) the 96 * address of the original image header. 97 */ 98 os_hdr = NULL; 99 if (image_check_type(&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) { 100 image_multi_getimg(hdr, 1, &kernel_data, &kernel_len); 101 if (kernel_len) 102 os_hdr = hdr; 103 } 104 105 if (bmi->argc > 0) { 106 ulong len; 107 int i; 108 109 for (i = 0, len = 0; i < bmi->argc; i += 1) 110 len += strlen(bmi->argv[i]) + 1; 111 cmdline = malloc(len); 112 copy_args(cmdline, bmi->argc, bmi->argv, ' '); 113 } else { 114 cmdline = env_get("bootargs"); 115 if (cmdline == NULL) 116 cmdline = ""; 117 } 118 119 loader = (void (*)(struct bd_info *, struct legacy_img_hdr *, char *, char *))images->ep; 120 121 printf("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n", 122 (ulong)loader); 123 124 bootstage_mark(BOOTSTAGE_ID_RUN_OS); 125 126 /* 127 * NetBSD Stage-2 Loader Parameters: 128 * arg[0]: pointer to board info data 129 * arg[1]: image load address 130 * arg[2]: char pointer to the console device to use 131 * arg[3]: char pointer to the boot arguments 132 */ 133 (*loader)(gd->bd, os_hdr, "", cmdline); 134 135 return 1; 136} 137#endif /* CONFIG_BOOTM_NETBSD*/ 138 139#ifdef CONFIG_BOOTM_RTEMS 140static int do_bootm_rtems(int flag, struct bootm_info *bmi) 141{ 142 struct bootm_headers *images = bmi->images; 143 void (*entry_point)(struct bd_info *); 144 145 if (flag != BOOTM_STATE_OS_GO) 146 return 0; 147 148#if defined(CONFIG_FIT) 149 if (!images->legacy_hdr_valid) { 150 fit_unsupported_reset("RTEMS"); 151 return 1; 152 } 153#endif 154 155 entry_point = (void (*)(struct bd_info *))images->ep; 156 157 printf("## Transferring control to RTEMS (at address %08lx) ...\n", 158 (ulong)entry_point); 159 160 bootstage_mark(BOOTSTAGE_ID_RUN_OS); 161 162 /* 163 * RTEMS Parameters: 164 * r3: ptr to board info data 165 */ 166 (*entry_point)(gd->bd); 167 168 return 1; 169} 170#endif /* CONFIG_BOOTM_RTEMS */ 171 172#if defined(CONFIG_BOOTM_OSE) 173static int do_bootm_ose(int flag, struct bootm_info *bmi) 174{ 175 struct bootm_headers *images = bmi->images; 176 void (*entry_point)(void); 177 178 if (flag != BOOTM_STATE_OS_GO) 179 return 0; 180 181#if defined(CONFIG_FIT) 182 if (!images->legacy_hdr_valid) { 183 fit_unsupported_reset("OSE"); 184 return 1; 185 } 186#endif 187 188 entry_point = (void (*)(void))images->ep; 189 190 printf("## Transferring control to OSE (at address %08lx) ...\n", 191 (ulong)entry_point); 192 193 bootstage_mark(BOOTSTAGE_ID_RUN_OS); 194 195 /* 196 * OSE Parameters: 197 * None 198 */ 199 (*entry_point)(); 200 201 return 1; 202} 203#endif /* CONFIG_BOOTM_OSE */ 204 205#if defined(CONFIG_BOOTM_PLAN9) 206static int do_bootm_plan9(int flag, struct bootm_info *bmi) 207{ 208 struct bootm_headers *images = bmi->images; 209 void (*entry_point)(void); 210 char *s; 211 212 if (flag != BOOTM_STATE_OS_GO) 213 return 0; 214 215#if defined(CONFIG_FIT) 216 if (!images->legacy_hdr_valid) { 217 fit_unsupported_reset("Plan 9"); 218 return 1; 219 } 220#endif 221 222 /* See README.plan9 */ 223 s = env_get("confaddr"); 224 if (s != NULL) { 225 char *confaddr = (char *)hextoul(s, NULL); 226 227 if (bmi->argc) { 228 copy_args(confaddr, bmi->argc, bmi->argv, '\n'); 229 } else { 230 s = env_get("bootargs"); 231 if (s != NULL) 232 strcpy(confaddr, s); 233 } 234 } 235 236 entry_point = (void (*)(void))images->ep; 237 238 printf("## Transferring control to Plan 9 (at address %08lx) ...\n", 239 (ulong)entry_point); 240 241 bootstage_mark(BOOTSTAGE_ID_RUN_OS); 242 243 /* 244 * Plan 9 Parameters: 245 * None 246 */ 247 (*entry_point)(); 248 249 return 1; 250} 251#endif /* CONFIG_BOOTM_PLAN9 */ 252 253#if defined(CONFIG_BOOTM_VXWORKS) && \ 254 (defined(CONFIG_PPC) || defined(CONFIG_ARM)) 255 256static void do_bootvx_fdt(struct bootm_headers *images) 257{ 258#if defined(CONFIG_OF_LIBFDT) 259 int ret; 260 char *bootline; 261 ulong of_size = images->ft_len; 262 char **of_flat_tree = &images->ft_addr; 263 struct lmb *lmb = &images->lmb; 264 265 if (*of_flat_tree) { 266 boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree); 267 268 ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size); 269 if (ret) 270 return; 271 272 /* Update ethernet nodes */ 273 fdt_fixup_ethernet(*of_flat_tree); 274 275 ret = fdt_add_subnode(*of_flat_tree, 0, "chosen"); 276 if ((ret >= 0 || ret == -FDT_ERR_EXISTS)) { 277 bootline = env_get("bootargs"); 278 if (bootline) { 279 ret = fdt_find_and_setprop(*of_flat_tree, 280 "/chosen", "bootargs", 281 bootline, 282 strlen(bootline) + 1, 1); 283 if (ret < 0) { 284 printf("## ERROR: %s : %s\n", __func__, 285 fdt_strerror(ret)); 286 return; 287 } 288 } 289 } else { 290 printf("## ERROR: %s : %s\n", __func__, 291 fdt_strerror(ret)); 292 return; 293 } 294 } 295#endif 296 297 boot_prep_vxworks(images); 298 299 bootstage_mark(BOOTSTAGE_ID_RUN_OS); 300 301#if defined(CONFIG_OF_LIBFDT) 302 printf("## Starting vxWorks at 0x%08lx, device tree at 0x%08lx ...\n", 303 (ulong)images->ep, (ulong)*of_flat_tree); 304#else 305 printf("## Starting vxWorks at 0x%08lx\n", (ulong)images->ep); 306#endif 307 flush(); 308 309 boot_jump_vxworks(images); 310 311 puts("## vxWorks terminated\n"); 312} 313 314static int do_bootm_vxworks_legacy(int flag, struct bootm_info *bmi) 315{ 316 struct bootm_headers *images = bmi->images; 317 318 if (flag != BOOTM_STATE_OS_GO) 319 return 0; 320 321 do_bootvx_fdt(images); 322 323 return 1; 324} 325 326int do_bootm_vxworks(int flag, struct bootm_info *bmi) 327{ 328 char *bootargs; 329 int pos; 330 unsigned long vxflags; 331 bool std_dtb = false; 332 333 /* get bootargs env */ 334 bootargs = env_get("bootargs"); 335 336 if (bootargs != NULL) { 337 for (pos = 0; pos < strlen(bootargs); pos++) { 338 /* find f=0xnumber flag */ 339 if ((bootargs[pos] == '=') && (pos >= 1) && 340 (bootargs[pos - 1] == 'f')) { 341 vxflags = hextoul(&bootargs[pos + 1], NULL); 342 if (vxflags & VXWORKS_SYSFLG_STD_DTB) 343 std_dtb = true; 344 } 345 } 346 } 347 348 if (std_dtb) { 349 if (flag & BOOTM_STATE_OS_PREP) 350 printf(" Using standard DTB\n"); 351 return do_bootm_linux(flag, bmi); 352 } else { 353 if (flag & BOOTM_STATE_OS_PREP) 354 printf(" !!! WARNING !!! Using legacy DTB\n"); 355 return do_bootm_vxworks_legacy(flag, bmi); 356 } 357} 358#endif 359 360#if defined(CONFIG_CMD_ELF) 361static int do_bootm_qnxelf(int flag, struct bootm_info *bmi) 362{ 363 struct bootm_headers *images = bmi->images; 364 char *local_args[2]; 365 char str[16]; 366 int dcache; 367 368 if (flag != BOOTM_STATE_OS_GO) 369 return 0; 370 371#if defined(CONFIG_FIT) 372 if (!images->legacy_hdr_valid) { 373 fit_unsupported_reset("QNX"); 374 return 1; 375 } 376#endif 377 378 sprintf(str, "%lx", images->ep); /* write entry-point into string */ 379 local_args[0] = bmi->argv[0]; 380 local_args[1] = str; /* and provide it via the arguments */ 381 382 /* 383 * QNX images require the data cache is disabled. 384 */ 385 dcache = dcache_status(); 386 if (dcache) 387 dcache_disable(); 388 389 do_bootelf(NULL, 0, 2, local_args); 390 391 if (dcache) 392 dcache_enable(); 393 394 return 1; 395} 396#endif 397 398#ifdef CONFIG_INTEGRITY 399static int do_bootm_integrity(int flag, struct bootm_info *bmi) 400{ 401 struct bootm_headers *images = bmi->images; 402 void (*entry_point)(void); 403 404 if (flag != BOOTM_STATE_OS_GO) 405 return 0; 406 407#if defined(CONFIG_FIT) 408 if (!images->legacy_hdr_valid) { 409 fit_unsupported_reset("INTEGRITY"); 410 return 1; 411 } 412#endif 413 414 entry_point = (void (*)(void))images->ep; 415 416 printf("## Transferring control to INTEGRITY (at address %08lx) ...\n", 417 (ulong)entry_point); 418 419 bootstage_mark(BOOTSTAGE_ID_RUN_OS); 420 421 /* 422 * INTEGRITY Parameters: 423 * None 424 */ 425 (*entry_point)(); 426 427 return 1; 428} 429#endif 430 431#ifdef CONFIG_BOOTM_OPENRTOS 432static int do_bootm_openrtos(int flag, struct bootm_info *bmi) 433{ 434 struct bootm_headers *images = bmi->images; 435 void (*entry_point)(void); 436 437 if (flag != BOOTM_STATE_OS_GO) 438 return 0; 439 440 entry_point = (void (*)(void))images->ep; 441 442 printf("## Transferring control to OpenRTOS (at address %08lx) ...\n", 443 (ulong)entry_point); 444 445 bootstage_mark(BOOTSTAGE_ID_RUN_OS); 446 447 /* 448 * OpenRTOS Parameters: 449 * None 450 */ 451 (*entry_point)(); 452 453 return 1; 454} 455#endif 456 457#ifdef CONFIG_BOOTM_OPTEE 458static int do_bootm_tee(int flag, struct bootm_info *bmi) 459{ 460 struct bootm_headers *images = bmi->images; 461 int ret; 462 463 /* Validate OPTEE header */ 464 ret = optee_verify_bootm_image(images->os.image_start, 465 images->os.load, 466 images->os.image_len); 467 if (ret) 468 return ret; 469 470 /* From here we can run the regular linux boot path */ 471 return do_bootm_linux(flag, bmi); 472} 473#endif 474 475#ifdef CONFIG_BOOTM_EFI 476static int do_bootm_efi(int flag, struct bootm_info *bmi) 477{ 478 struct bootm_headers *images = bmi->images; 479 int ret; 480 void *image_buf; 481 482 if (flag != BOOTM_STATE_OS_GO) 483 return 0; 484 485 /* We expect to return */ 486 images->os.type = IH_TYPE_STANDALONE; 487 488 image_buf = map_sysmem(images->ep, images->os.image_len); 489 490 /* Run EFI image */ 491 printf("## Transferring control to EFI (at address %08lx) ...\n", 492 images->ep); 493 bootstage_mark(BOOTSTAGE_ID_RUN_OS); 494 495 ret = efi_binary_run(image_buf, images->os.image_len, 496 images->ft_len 497 ? images->ft_addr : EFI_FDT_USE_INTERNAL); 498 499 return ret; 500} 501#endif 502 503static boot_os_fn *boot_os[] = { 504 [IH_OS_U_BOOT] = do_bootm_standalone, 505#ifdef CONFIG_BOOTM_LINUX 506 [IH_OS_LINUX] = do_bootm_linux, 507#endif 508#ifdef CONFIG_BOOTM_NETBSD 509 [IH_OS_NETBSD] = do_bootm_netbsd, 510#endif 511#ifdef CONFIG_BOOTM_RTEMS 512 [IH_OS_RTEMS] = do_bootm_rtems, 513#endif 514#if defined(CONFIG_BOOTM_OSE) 515 [IH_OS_OSE] = do_bootm_ose, 516#endif 517#if defined(CONFIG_BOOTM_PLAN9) 518 [IH_OS_PLAN9] = do_bootm_plan9, 519#endif 520#if defined(CONFIG_BOOTM_VXWORKS) && \ 521 (defined(CONFIG_PPC) || defined(CONFIG_ARM) || defined(CONFIG_RISCV)) 522 [IH_OS_VXWORKS] = do_bootm_vxworks, 523#endif 524#if defined(CONFIG_CMD_ELF) 525 [IH_OS_QNX] = do_bootm_qnxelf, 526#endif 527#ifdef CONFIG_INTEGRITY 528 [IH_OS_INTEGRITY] = do_bootm_integrity, 529#endif 530#ifdef CONFIG_BOOTM_OPENRTOS 531 [IH_OS_OPENRTOS] = do_bootm_openrtos, 532#endif 533#ifdef CONFIG_BOOTM_OPTEE 534 [IH_OS_TEE] = do_bootm_tee, 535#endif 536#ifdef CONFIG_BOOTM_EFI 537 [IH_OS_EFI] = do_bootm_efi, 538#endif 539}; 540 541/* Allow for arch specific config before we boot */ 542__weak void arch_preboot_os(void) 543{ 544 /* please define platform specific arch_preboot_os() */ 545} 546 547/* Allow for board specific config before we boot */ 548__weak void board_preboot_os(void) 549{ 550 /* please define board specific board_preboot_os() */ 551} 552 553int boot_selected_os(int state, struct bootm_info *bmi, boot_os_fn *boot_fn) 554{ 555 arch_preboot_os(); 556 board_preboot_os(); 557 558 boot_fn(state, bmi); 559 560 /* Stand-alone may return when 'autostart' is 'no' */ 561 if (bmi->images->os.type == IH_TYPE_STANDALONE || 562 IS_ENABLED(CONFIG_SANDBOX) || 563 state == BOOTM_STATE_OS_FAKE_GO) /* We expect to return */ 564 return 0; 565 bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED); 566 debug("\n## Control returned to monitor - resetting...\n"); 567 568 return BOOTM_ERR_RESET; 569} 570 571boot_os_fn *bootm_os_get_boot_func(int os) 572{ 573 return boot_os[os]; 574} 575