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