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