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