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 /* 8 * Boot support 9 */ 10 #include <common.h> 11 #include <bootm.h> 12 #include <command.h> 13 #include <environment.h> 14 #include <errno.h> 15 #include <image.h> 16 #include <malloc.h> 17 #include <nand.h> 18 #include <asm/byteorder.h> 19 #include <linux/ctype.h> 20 #include <linux/err.h> 21 #include <u-boot/zlib.h> 22 23 DECLARE_GLOBAL_DATA_PTR; 24 25 #if defined(CONFIG_CMD_IMI) 26 static int image_info(unsigned long addr); 27 #endif 28 29 #if defined(CONFIG_CMD_IMLS) 30 #include <flash.h> 31 #include <mtd/cfi_flash.h> 32 extern flash_info_t flash_info[]; /* info for FLASH chips */ 33 #endif 34 35 #if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND) 36 static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); 37 #endif 38 39 /* we overload the cmd field with our state machine info instead of a 40 * function pointer */ 41 static cmd_tbl_t cmd_bootm_sub[] = { 42 U_BOOT_CMD_MKENT(start, 0, 1, (void *)BOOTM_STATE_START, "", ""), 43 U_BOOT_CMD_MKENT(loados, 0, 1, (void *)BOOTM_STATE_LOADOS, "", ""), 44 #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH 45 U_BOOT_CMD_MKENT(ramdisk, 0, 1, (void *)BOOTM_STATE_RAMDISK, "", ""), 46 #endif 47 #ifdef CONFIG_OF_LIBFDT 48 U_BOOT_CMD_MKENT(fdt, 0, 1, (void *)BOOTM_STATE_FDT, "", ""), 49 #endif 50 U_BOOT_CMD_MKENT(cmdline, 0, 1, (void *)BOOTM_STATE_OS_CMDLINE, "", ""), 51 U_BOOT_CMD_MKENT(bdt, 0, 1, (void *)BOOTM_STATE_OS_BD_T, "", ""), 52 U_BOOT_CMD_MKENT(prep, 0, 1, (void *)BOOTM_STATE_OS_PREP, "", ""), 53 U_BOOT_CMD_MKENT(fake, 0, 1, (void *)BOOTM_STATE_OS_FAKE_GO, "", ""), 54 U_BOOT_CMD_MKENT(go, 0, 1, (void *)BOOTM_STATE_OS_GO, "", ""), 55 }; 56 57 static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc, 58 char * const argv[]) 59 { 60 int ret = 0; 61 long state; 62 cmd_tbl_t *c; 63 64 c = find_cmd_tbl(argv[0], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub)); 65 argc--; argv++; 66 67 if (c) { 68 state = (long)c->cmd; 69 if (state == BOOTM_STATE_START) 70 state |= BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER; 71 } else { 72 /* Unrecognized command */ 73 return CMD_RET_USAGE; 74 } 75 76 if (((state & BOOTM_STATE_START) != BOOTM_STATE_START) && 77 images.state >= state) { 78 printf("Trying to execute a command out of order\n"); 79 return CMD_RET_USAGE; 80 } 81 82 ret = do_bootm_states(cmdtp, flag, argc, argv, state, &images, 0); 83 84 return ret; 85 } 86 87 /*******************************************************************/ 88 /* bootm - boot application image from image in memory */ 89 /*******************************************************************/ 90 91 int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 92 { 93 #ifdef CONFIG_NEEDS_MANUAL_RELOC 94 static int relocated = 0; 95 96 if (!relocated) { 97 int i; 98 99 /* relocate names of sub-command table */ 100 for (i = 0; i < ARRAY_SIZE(cmd_bootm_sub); i++) 101 cmd_bootm_sub[i].name += gd->reloc_off; 102 103 relocated = 1; 104 } 105 #endif 106 107 /* determine if we have a sub command */ 108 argc--; argv++; 109 if (argc > 0) { 110 char *endp; 111 112 simple_strtoul(argv[0], &endp, 16); 113 /* endp pointing to NULL means that argv[0] was just a 114 * valid number, pass it along to the normal bootm processing 115 * 116 * If endp is ':' or '#' assume a FIT identifier so pass 117 * along for normal processing. 118 * 119 * Right now we assume the first arg should never be '-' 120 */ 121 if ((*endp != 0) && (*endp != ':') && (*endp != '#')) 122 return do_bootm_subcommand(cmdtp, flag, argc, argv); 123 } 124 125 return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START | 126 BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER | 127 BOOTM_STATE_LOADOS | 128 #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH 129 BOOTM_STATE_RAMDISK | 130 #endif 131 #if defined(CONFIG_PPC) || defined(CONFIG_MIPS) 132 BOOTM_STATE_OS_CMDLINE | 133 #endif 134 BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO | 135 BOOTM_STATE_OS_GO, &images, 1); 136 } 137 138 int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd) 139 { 140 const char *ep = env_get("autostart"); 141 142 if (ep && !strcmp(ep, "yes")) { 143 char *local_args[2]; 144 local_args[0] = (char *)cmd; 145 local_args[1] = NULL; 146 printf("Automatic boot of image at addr 0x%08lX ...\n", load_addr); 147 return do_bootm(cmdtp, 0, 1, local_args); 148 } 149 150 return 0; 151 } 152 153 #ifdef CONFIG_SYS_LONGHELP 154 static char bootm_help_text[] = 155 "[addr [arg ...]]\n - boot application image stored in memory\n" 156 "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n" 157 "\t'arg' can be the address of an initrd image\n" 158 #if defined(CONFIG_OF_LIBFDT) 159 "\tWhen booting a Linux kernel which requires a flat device-tree\n" 160 "\ta third argument is required which is the address of the\n" 161 "\tdevice-tree blob. To boot that kernel without an initrd image,\n" 162 "\tuse a '-' for the second argument. If you do not pass a third\n" 163 "\ta bd_info struct will be passed instead\n" 164 #endif 165 #if defined(CONFIG_FIT) 166 "\t\nFor the new multi component uImage format (FIT) addresses\n" 167 "\tmust be extended to include component or configuration unit name:\n" 168 "\taddr:<subimg_uname> - direct component image specification\n" 169 "\taddr#<conf_uname> - configuration specification\n" 170 "\tUse iminfo command to get the list of existing component\n" 171 "\timages and configurations.\n" 172 #endif 173 "\nSub-commands to do part of the bootm sequence. The sub-commands " 174 "must be\n" 175 "issued in the order below (it's ok to not issue all sub-commands):\n" 176 "\tstart [addr [arg ...]]\n" 177 "\tloados - load OS image\n" 178 #if defined(CONFIG_SYS_BOOT_RAMDISK_HIGH) 179 "\tramdisk - relocate initrd, set env initrd_start/initrd_end\n" 180 #endif 181 #if defined(CONFIG_OF_LIBFDT) 182 "\tfdt - relocate flat device tree\n" 183 #endif 184 "\tcmdline - OS specific command line processing/setup\n" 185 "\tbdt - OS specific bd_t processing\n" 186 "\tprep - OS specific prep before relocation or go\n" 187 #if defined(CONFIG_TRACE) 188 "\tfake - OS specific fake start without go\n" 189 #endif 190 "\tgo - start OS"; 191 #endif 192 193 U_BOOT_CMD( 194 bootm, CONFIG_SYS_MAXARGS, 1, do_bootm, 195 "boot application image from memory", bootm_help_text 196 ); 197 198 /*******************************************************************/ 199 /* bootd - boot default image */ 200 /*******************************************************************/ 201 #if defined(CONFIG_CMD_BOOTD) 202 int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 203 { 204 return run_command(env_get("bootcmd"), flag); 205 } 206 207 U_BOOT_CMD( 208 boot, 1, 1, do_bootd, 209 "boot default, i.e., run 'bootcmd'", 210 "" 211 ); 212 213 /* keep old command name "bootd" for backward compatibility */ 214 U_BOOT_CMD( 215 bootd, 1, 1, do_bootd, 216 "boot default, i.e., run 'bootcmd'", 217 "" 218 ); 219 220 #endif 221 222 223 /*******************************************************************/ 224 /* iminfo - print header info for a requested image */ 225 /*******************************************************************/ 226 #if defined(CONFIG_CMD_IMI) 227 static int do_iminfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 228 { 229 int arg; 230 ulong addr; 231 int rcode = 0; 232 233 if (argc < 2) { 234 return image_info(load_addr); 235 } 236 237 for (arg = 1; arg < argc; ++arg) { 238 addr = simple_strtoul(argv[arg], NULL, 16); 239 if (image_info(addr) != 0) 240 rcode = 1; 241 } 242 return rcode; 243 } 244 245 static int image_info(ulong addr) 246 { 247 void *hdr = (void *)addr; 248 249 printf("\n## Checking Image at %08lx ...\n", addr); 250 251 switch (genimg_get_format(hdr)) { 252 #if defined(CONFIG_IMAGE_FORMAT_LEGACY) 253 case IMAGE_FORMAT_LEGACY: 254 puts(" Legacy image found\n"); 255 if (!image_check_magic(hdr)) { 256 puts(" Bad Magic Number\n"); 257 return 1; 258 } 259 260 if (!image_check_hcrc(hdr)) { 261 puts(" Bad Header Checksum\n"); 262 return 1; 263 } 264 265 image_print_contents(hdr); 266 267 puts(" Verifying Checksum ... "); 268 if (!image_check_dcrc(hdr)) { 269 puts(" Bad Data CRC\n"); 270 return 1; 271 } 272 puts("OK\n"); 273 return 0; 274 #endif 275 #if defined(CONFIG_ANDROID_BOOT_IMAGE) 276 case IMAGE_FORMAT_ANDROID: 277 puts(" Android image found\n"); 278 android_print_contents(hdr); 279 return 0; 280 #endif 281 #if defined(CONFIG_FIT) 282 case IMAGE_FORMAT_FIT: 283 puts(" FIT image found\n"); 284 285 if (!fit_check_format(hdr)) { 286 puts("Bad FIT image format!\n"); 287 return 1; 288 } 289 290 fit_print_contents(hdr); 291 292 if (!fit_all_image_verify(hdr)) { 293 puts("Bad hash in FIT image!\n"); 294 return 1; 295 } 296 297 return 0; 298 #endif 299 default: 300 puts("Unknown image format!\n"); 301 break; 302 } 303 304 return 1; 305 } 306 307 U_BOOT_CMD( 308 iminfo, CONFIG_SYS_MAXARGS, 1, do_iminfo, 309 "print header information for application image", 310 "addr [addr ...]\n" 311 " - print header information for application image starting at\n" 312 " address 'addr' in memory; this includes verification of the\n" 313 " image contents (magic number, header and payload checksums)" 314 ); 315 #endif 316 317 318 /*******************************************************************/ 319 /* imls - list all images found in flash */ 320 /*******************************************************************/ 321 #if defined(CONFIG_CMD_IMLS) 322 static int do_imls_nor(void) 323 { 324 flash_info_t *info; 325 int i, j; 326 void *hdr; 327 328 for (i = 0, info = &flash_info[0]; 329 i < CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) { 330 331 if (info->flash_id == FLASH_UNKNOWN) 332 goto next_bank; 333 for (j = 0; j < info->sector_count; ++j) { 334 335 hdr = (void *)info->start[j]; 336 if (!hdr) 337 goto next_sector; 338 339 switch (genimg_get_format(hdr)) { 340 #if defined(CONFIG_IMAGE_FORMAT_LEGACY) 341 case IMAGE_FORMAT_LEGACY: 342 if (!image_check_hcrc(hdr)) 343 goto next_sector; 344 345 printf("Legacy Image at %08lX:\n", (ulong)hdr); 346 image_print_contents(hdr); 347 348 puts(" Verifying Checksum ... "); 349 if (!image_check_dcrc(hdr)) { 350 puts("Bad Data CRC\n"); 351 } else { 352 puts("OK\n"); 353 } 354 break; 355 #endif 356 #if defined(CONFIG_FIT) 357 case IMAGE_FORMAT_FIT: 358 if (!fit_check_format(hdr)) 359 goto next_sector; 360 361 printf("FIT Image at %08lX:\n", (ulong)hdr); 362 fit_print_contents(hdr); 363 break; 364 #endif 365 default: 366 goto next_sector; 367 } 368 369 next_sector: ; 370 } 371 next_bank: ; 372 } 373 return 0; 374 } 375 #endif 376 377 #if defined(CONFIG_CMD_IMLS_NAND) 378 static int nand_imls_legacyimage(struct mtd_info *mtd, int nand_dev, 379 loff_t off, size_t len) 380 { 381 void *imgdata; 382 int ret; 383 384 imgdata = malloc(len); 385 if (!imgdata) { 386 printf("May be a Legacy Image at NAND device %d offset %08llX:\n", 387 nand_dev, off); 388 printf(" Low memory(cannot allocate memory for image)\n"); 389 return -ENOMEM; 390 } 391 392 ret = nand_read_skip_bad(mtd, off, &len, NULL, mtd->size, imgdata); 393 if (ret < 0 && ret != -EUCLEAN) { 394 free(imgdata); 395 return ret; 396 } 397 398 if (!image_check_hcrc(imgdata)) { 399 free(imgdata); 400 return 0; 401 } 402 403 printf("Legacy Image at NAND device %d offset %08llX:\n", 404 nand_dev, off); 405 image_print_contents(imgdata); 406 407 puts(" Verifying Checksum ... "); 408 if (!image_check_dcrc(imgdata)) 409 puts("Bad Data CRC\n"); 410 else 411 puts("OK\n"); 412 413 free(imgdata); 414 415 return 0; 416 } 417 418 static int nand_imls_fitimage(struct mtd_info *mtd, int nand_dev, loff_t off, 419 size_t len) 420 { 421 void *imgdata; 422 int ret; 423 424 imgdata = malloc(len); 425 if (!imgdata) { 426 printf("May be a FIT Image at NAND device %d offset %08llX:\n", 427 nand_dev, off); 428 printf(" Low memory(cannot allocate memory for image)\n"); 429 return -ENOMEM; 430 } 431 432 ret = nand_read_skip_bad(mtd, off, &len, NULL, mtd->size, imgdata); 433 if (ret < 0 && ret != -EUCLEAN) { 434 free(imgdata); 435 return ret; 436 } 437 438 if (!fit_check_format(imgdata)) { 439 free(imgdata); 440 return 0; 441 } 442 443 printf("FIT Image at NAND device %d offset %08llX:\n", nand_dev, off); 444 445 fit_print_contents(imgdata); 446 free(imgdata); 447 448 return 0; 449 } 450 451 static int do_imls_nand(void) 452 { 453 struct mtd_info *mtd; 454 int nand_dev = nand_curr_device; 455 size_t len; 456 loff_t off; 457 u32 buffer[16]; 458 459 if (nand_dev < 0 || nand_dev >= CONFIG_SYS_MAX_NAND_DEVICE) { 460 puts("\nNo NAND devices available\n"); 461 return -ENODEV; 462 } 463 464 printf("\n"); 465 466 for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) { 467 mtd = get_nand_dev_by_index(nand_dev); 468 if (!mtd->name || !mtd->size) 469 continue; 470 471 for (off = 0; off < mtd->size; off += mtd->erasesize) { 472 const image_header_t *header; 473 int ret; 474 475 if (nand_block_isbad(mtd, off)) 476 continue; 477 478 len = sizeof(buffer); 479 480 ret = nand_read(mtd, off, &len, (u8 *)buffer); 481 if (ret < 0 && ret != -EUCLEAN) { 482 printf("NAND read error %d at offset %08llX\n", 483 ret, off); 484 continue; 485 } 486 487 switch (genimg_get_format(buffer)) { 488 #if defined(CONFIG_IMAGE_FORMAT_LEGACY) 489 case IMAGE_FORMAT_LEGACY: 490 header = (const image_header_t *)buffer; 491 492 len = image_get_image_size(header); 493 nand_imls_legacyimage(mtd, nand_dev, off, len); 494 break; 495 #endif 496 #if defined(CONFIG_FIT) 497 case IMAGE_FORMAT_FIT: 498 len = fit_get_size(buffer); 499 nand_imls_fitimage(mtd, nand_dev, off, len); 500 break; 501 #endif 502 } 503 } 504 } 505 506 return 0; 507 } 508 #endif 509 510 #if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND) 511 static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 512 { 513 int ret_nor = 0, ret_nand = 0; 514 515 #if defined(CONFIG_CMD_IMLS) 516 ret_nor = do_imls_nor(); 517 #endif 518 519 #if defined(CONFIG_CMD_IMLS_NAND) 520 ret_nand = do_imls_nand(); 521 #endif 522 523 if (ret_nor) 524 return ret_nor; 525 526 if (ret_nand) 527 return ret_nand; 528 529 return (0); 530 } 531 532 U_BOOT_CMD( 533 imls, 1, 1, do_imls, 534 "list all images found in flash", 535 "\n" 536 " - Prints information about all images found at sector/block\n" 537 " boundaries in nor/nand flash." 538 ); 539 #endif 540