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
do_bootm_subcommand(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])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
do_bootm(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])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
bootm_maybe_autostart(cmd_tbl_t * cmdtp,const char * cmd)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)
do_bootd(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])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)
do_iminfo(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])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
image_info(ulong addr)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)
do_imls_nor(void)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)
nand_imls_legacyimage(struct mtd_info * mtd,int nand_dev,loff_t off,size_t len)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
nand_imls_fitimage(struct mtd_info * mtd,int nand_dev,loff_t off,size_t len)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
do_imls_nand(void)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)
do_imls(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])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