Home | History | Annotate | Download | only in cmd
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * (C) Copyright 2000-2009
      4  * Wolfgang Denk, DENX Software Engineering, wd (at) 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