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