]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/cmd_bootm.c
Merge branch 'master' of git://git.denx.de/u-boot-imx
[karo-tx-uboot.git] / common / cmd_bootm.c
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 <lmb.h>
18 #include <malloc.h>
19 #include <nand.h>
20 #include <asm/byteorder.h>
21 #include <linux/compiler.h>
22 #include <linux/ctype.h>
23 #include <linux/err.h>
24 #include <u-boot/zlib.h>
25
26 DECLARE_GLOBAL_DATA_PTR;
27
28 #if defined(CONFIG_CMD_IMI)
29 static int image_info(unsigned long addr);
30 #endif
31
32 #if defined(CONFIG_CMD_IMLS)
33 #include <flash.h>
34 #include <mtd/cfi_flash.h>
35 extern flash_info_t flash_info[]; /* info for FLASH chips */
36 #endif
37
38 #if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
39 static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
40 #endif
41
42 bootm_headers_t images;         /* pointers to os/initrd/fdt images */
43
44 /* we overload the cmd field with our state machine info instead of a
45  * function pointer */
46 static cmd_tbl_t cmd_bootm_sub[] = {
47         U_BOOT_CMD_MKENT(start, 0, 1, (void *)BOOTM_STATE_START, "", ""),
48         U_BOOT_CMD_MKENT(loados, 0, 1, (void *)BOOTM_STATE_LOADOS, "", ""),
49 #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
50         U_BOOT_CMD_MKENT(ramdisk, 0, 1, (void *)BOOTM_STATE_RAMDISK, "", ""),
51 #endif
52 #ifdef CONFIG_OF_LIBFDT
53         U_BOOT_CMD_MKENT(fdt, 0, 1, (void *)BOOTM_STATE_FDT, "", ""),
54 #endif
55         U_BOOT_CMD_MKENT(cmdline, 0, 1, (void *)BOOTM_STATE_OS_CMDLINE, "", ""),
56         U_BOOT_CMD_MKENT(bdt, 0, 1, (void *)BOOTM_STATE_OS_BD_T, "", ""),
57         U_BOOT_CMD_MKENT(prep, 0, 1, (void *)BOOTM_STATE_OS_PREP, "", ""),
58         U_BOOT_CMD_MKENT(fake, 0, 1, (void *)BOOTM_STATE_OS_FAKE_GO, "", ""),
59         U_BOOT_CMD_MKENT(go, 0, 1, (void *)BOOTM_STATE_OS_GO, "", ""),
60 };
61
62 static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
63                         char * const argv[])
64 {
65         int ret = 0;
66         long state;
67         cmd_tbl_t *c;
68
69         c = find_cmd_tbl(argv[0], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));
70         argc--; argv++;
71
72         if (c) {
73                 state = (long)c->cmd;
74                 if (state == BOOTM_STATE_START)
75                         state |= BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER;
76         } else {
77                 /* Unrecognized command */
78                 return CMD_RET_USAGE;
79         }
80
81         if (state != BOOTM_STATE_START && images.state >= state) {
82                 printf("Trying to execute a command out of order\n");
83                 return CMD_RET_USAGE;
84         }
85
86         ret = do_bootm_states(cmdtp, flag, argc, argv, state, &images, 0);
87
88         return ret;
89 }
90
91 /*******************************************************************/
92 /* bootm - boot application image from image in memory */
93 /*******************************************************************/
94
95 int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
96 {
97 #ifdef CONFIG_NEEDS_MANUAL_RELOC
98         static int relocated = 0;
99
100         if (!relocated) {
101                 int i;
102
103                 /* relocate names of sub-command table */
104                 for (i = 0; i < ARRAY_SIZE(cmd_bootm_sub); i++)
105                         cmd_bootm_sub[i].name += gd->reloc_off;
106
107                 relocated = 1;
108         }
109 #endif
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 #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 extened 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         "\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_FIT)
274         case IMAGE_FORMAT_FIT:
275                 puts("   FIT image found\n");
276
277                 if (!fit_check_format(hdr)) {
278                         puts("Bad FIT image format!\n");
279                         return 1;
280                 }
281
282                 fit_print_contents(hdr);
283
284                 if (!fit_all_image_verify(hdr)) {
285                         puts("Bad hash in FIT image!\n");
286                         return 1;
287                 }
288
289                 return 0;
290 #endif
291         default:
292                 puts("Unknown image format!\n");
293                 break;
294         }
295
296         return 1;
297 }
298
299 U_BOOT_CMD(
300         iminfo, CONFIG_SYS_MAXARGS,     1,      do_iminfo,
301         "print header information for application image",
302         "addr [addr ...]\n"
303         "    - print header information for application image starting at\n"
304         "      address 'addr' in memory; this includes verification of the\n"
305         "      image contents (magic number, header and payload checksums)"
306 );
307 #endif
308
309
310 /*******************************************************************/
311 /* imls - list all images found in flash */
312 /*******************************************************************/
313 #if defined(CONFIG_CMD_IMLS)
314 static int do_imls_nor(void)
315 {
316         flash_info_t *info;
317         int i, j;
318         void *hdr;
319
320         for (i = 0, info = &flash_info[0];
321                 i < CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) {
322
323                 if (info->flash_id == FLASH_UNKNOWN)
324                         goto next_bank;
325                 for (j = 0; j < info->sector_count; ++j) {
326
327                         hdr = (void *)info->start[j];
328                         if (!hdr)
329                                 goto next_sector;
330
331                         switch (genimg_get_format(hdr)) {
332 #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
333                         case IMAGE_FORMAT_LEGACY:
334                                 if (!image_check_hcrc(hdr))
335                                         goto next_sector;
336
337                                 printf("Legacy Image at %08lX:\n", (ulong)hdr);
338                                 image_print_contents(hdr);
339
340                                 puts("   Verifying Checksum ... ");
341                                 if (!image_check_dcrc(hdr)) {
342                                         puts("Bad Data CRC\n");
343                                 } else {
344                                         puts("OK\n");
345                                 }
346                                 break;
347 #endif
348 #if defined(CONFIG_FIT)
349                         case IMAGE_FORMAT_FIT:
350                                 if (!fit_check_format(hdr))
351                                         goto next_sector;
352
353                                 printf("FIT Image at %08lX:\n", (ulong)hdr);
354                                 fit_print_contents(hdr);
355                                 break;
356 #endif
357                         default:
358                                 goto next_sector;
359                         }
360
361 next_sector:            ;
362                 }
363 next_bank:      ;
364         }
365         return 0;
366 }
367 #endif
368
369 #if defined(CONFIG_CMD_IMLS_NAND)
370 static int nand_imls_legacyimage(nand_info_t *nand, int nand_dev, loff_t off,
371                 size_t len)
372 {
373         void *imgdata;
374         int ret;
375
376         imgdata = malloc(len);
377         if (!imgdata) {
378                 printf("May be a Legacy Image at NAND device %d offset %08llX:\n",
379                                 nand_dev, off);
380                 printf("   Low memory(cannot allocate memory for image)\n");
381                 return -ENOMEM;
382         }
383
384         ret = nand_read_skip_bad(nand, off, &len,
385                         imgdata);
386         if (ret < 0 && ret != -EUCLEAN) {
387                 free(imgdata);
388                 return ret;
389         }
390
391         if (!image_check_hcrc(imgdata)) {
392                 free(imgdata);
393                 return 0;
394         }
395
396         printf("Legacy Image at NAND device %d offset %08llX:\n",
397                         nand_dev, off);
398         image_print_contents(imgdata);
399
400         puts("   Verifying Checksum ... ");
401         if (!image_check_dcrc(imgdata))
402                 puts("Bad Data CRC\n");
403         else
404                 puts("OK\n");
405
406         free(imgdata);
407
408         return 0;
409 }
410
411 static int nand_imls_fitimage(nand_info_t *nand, int nand_dev, loff_t off,
412                 size_t len)
413 {
414         void *imgdata;
415         int ret;
416
417         imgdata = malloc(len);
418         if (!imgdata) {
419                 printf("May be a FIT Image at NAND device %d offset %08llX:\n",
420                                 nand_dev, off);
421                 printf("   Low memory(cannot allocate memory for image)\n");
422                 return -ENOMEM;
423         }
424
425         ret = nand_read_skip_bad(nand, off, &len,
426                         imgdata);
427         if (ret < 0 && ret != -EUCLEAN) {
428                 free(imgdata);
429                 return ret;
430         }
431
432         if (!fit_check_format(imgdata)) {
433                 free(imgdata);
434                 return 0;
435         }
436
437         printf("FIT Image at NAND device %d offset %08llX:\n", nand_dev, off);
438
439         fit_print_contents(imgdata);
440         free(imgdata);
441
442         return 0;
443 }
444
445 static int do_imls_nand(void)
446 {
447         nand_info_t *nand;
448         int nand_dev = nand_curr_device;
449         size_t len;
450         loff_t off;
451         u32 buffer[16];
452
453         if (nand_dev < 0 || nand_dev >= CONFIG_SYS_MAX_NAND_DEVICE) {
454                 puts("\nNo NAND devices available\n");
455                 return -ENODEV;
456         }
457
458         printf("\n");
459
460         for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) {
461                 nand = &nand_info[nand_dev];
462                 if (!nand->name || !nand->size)
463                         continue;
464
465                 for (off = 0; off < nand->size; off += nand->erasesize) {
466                         const image_header_t *header;
467                         int ret;
468
469                         if (nand_block_isbad(nand, off))
470                                 continue;
471
472                         len = sizeof(buffer);
473
474                         ret = nand_read(nand, off, &len, (u8 *)buffer);
475                         if (ret < 0 && ret != -EUCLEAN) {
476                                 printf("NAND read error %d at offset %08llX\n",
477                                                 ret, off);
478                                 continue;
479                         }
480
481                         switch (genimg_get_format(buffer)) {
482 #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
483                         case IMAGE_FORMAT_LEGACY:
484                                 header = (const image_header_t *)buffer;
485
486                                 len = image_get_image_size(header);
487                                 nand_imls_legacyimage(nand, nand_dev, off, len);
488                                 break;
489 #endif
490 #if defined(CONFIG_FIT)
491                         case IMAGE_FORMAT_FIT:
492                                 len = fit_get_size(buffer);
493                                 nand_imls_fitimage(nand, nand_dev, off, len);
494                                 break;
495 #endif
496                         }
497                 }
498         }
499
500         return 0;
501 }
502 #endif
503
504 #if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
505 static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
506 {
507         int ret_nor = 0, ret_nand = 0;
508
509 #if defined(CONFIG_CMD_IMLS)
510         ret_nor = do_imls_nor();
511 #endif
512
513 #if defined(CONFIG_CMD_IMLS_NAND)
514         ret_nand = do_imls_nand();
515 #endif
516
517         if (ret_nor)
518                 return ret_nor;
519
520         if (ret_nand)
521                 return ret_nand;
522
523         return (0);
524 }
525
526 U_BOOT_CMD(
527         imls,   1,              1,      do_imls,
528         "list all images found in flash",
529         "\n"
530         "    - Prints information about all images found at sector/block\n"
531         "      boundaries in nor/nand flash."
532 );
533 #endif
534
535 #ifdef CONFIG_CMD_BOOTZ
536
537 int __weak bootz_setup(ulong image, ulong *start, ulong *end)
538 {
539         /* Please define bootz_setup() for your platform */
540
541         puts("Your platform's zImage format isn't supported yet!\n");
542         return -1;
543 }
544
545 /*
546  * zImage booting support
547  */
548 static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
549                         char * const argv[], bootm_headers_t *images)
550 {
551         int ret;
552         ulong zi_start, zi_end;
553
554         ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
555                               images, 1);
556
557         /* Setup Linux kernel zImage entry point */
558         if (!argc) {
559                 images->ep = load_addr;
560                 debug("*  kernel: default image load address = 0x%08lx\n",
561                                 load_addr);
562         } else {
563                 images->ep = simple_strtoul(argv[0], NULL, 16);
564                 debug("*  kernel: cmdline image address = 0x%08lx\n",
565                         images->ep);
566         }
567
568         ret = bootz_setup(images->ep, &zi_start, &zi_end);
569         if (ret != 0)
570                 return 1;
571
572         lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);
573
574         /*
575          * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
576          * have a header that provide this informaiton.
577          */
578         if (bootm_find_ramdisk_fdt(flag, argc, argv))
579                 return 1;
580
581         return 0;
582 }
583
584 int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
585 {
586         int ret;
587
588         /* Consume 'bootz' */
589         argc--; argv++;
590
591         if (bootz_start(cmdtp, flag, argc, argv, &images))
592                 return 1;
593
594         /*
595          * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
596          * disable interrupts ourselves
597          */
598         bootm_disable_interrupts();
599
600         images.os.os = IH_OS_LINUX;
601         ret = do_bootm_states(cmdtp, flag, argc, argv,
602                               BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
603                               BOOTM_STATE_OS_GO,
604                               &images, 1);
605
606         return ret;
607 }
608
609 #ifdef CONFIG_SYS_LONGHELP
610 static char bootz_help_text[] =
611         "[addr [initrd[:size]] [fdt]]\n"
612         "    - boot Linux zImage stored in memory\n"
613         "\tThe argument 'initrd' is optional and specifies the address\n"
614         "\tof the initrd in memory. The optional argument ':size' allows\n"
615         "\tspecifying the size of RAW initrd.\n"
616 #if defined(CONFIG_OF_LIBFDT)
617         "\tWhen booting a Linux kernel which requires a flat device-tree\n"
618         "\ta third argument is required which is the address of the\n"
619         "\tdevice-tree blob. To boot that kernel without an initrd image,\n"
620         "\tuse a '-' for the second argument. If you do not pass a third\n"
621         "\ta bd_info struct will be passed instead\n"
622 #endif
623         "";
624 #endif
625
626 U_BOOT_CMD(
627         bootz,  CONFIG_SYS_MAXARGS,     1,      do_bootz,
628         "boot Linux zImage image from memory", bootz_help_text
629 );
630 #endif  /* CONFIG_CMD_BOOTZ */
631
632 #ifdef CONFIG_CMD_BOOTI
633 /* See Documentation/arm64/booting.txt in the Linux kernel */
634 struct Image_header {
635         uint32_t        code0;          /* Executable code */
636         uint32_t        code1;          /* Executable code */
637         uint64_t        text_offset;    /* Image load offset, LE */
638         uint64_t        image_size;     /* Effective Image size, LE */
639         uint64_t        res1;           /* reserved */
640         uint64_t        res2;           /* reserved */
641         uint64_t        res3;           /* reserved */
642         uint64_t        res4;           /* reserved */
643         uint32_t        magic;          /* Magic number */
644         uint32_t        res5;
645 };
646
647 #define LINUX_ARM64_IMAGE_MAGIC 0x644d5241
648
649 static int booti_setup(bootm_headers_t *images)
650 {
651         struct Image_header *ih;
652         uint64_t dst;
653
654         ih = (struct Image_header *)map_sysmem(images->ep, 0);
655
656         if (ih->magic != le32_to_cpu(LINUX_ARM64_IMAGE_MAGIC)) {
657                 puts("Bad Linux ARM64 Image magic!\n");
658                 return 1;
659         }
660         
661         if (ih->image_size == 0) {
662                 puts("Image lacks image_size field, assuming 16MiB\n");
663                 ih->image_size = (16 << 20);
664         }
665
666         /*
667          * If we are not at the correct run-time location, set the new
668          * correct location and then move the image there.
669          */
670         dst = gd->bd->bi_dram[0].start + le32_to_cpu(ih->text_offset);
671         if (images->ep != dst) {
672                 void *src;
673
674                 debug("Moving Image from 0x%lx to 0x%llx\n", images->ep, dst);
675
676                 src = (void *)images->ep;
677                 images->ep = dst;
678                 memmove((void *)dst, src, le32_to_cpu(ih->image_size));
679         }
680
681         return 0;
682 }
683
684 /*
685  * Image booting support
686  */
687 static int booti_start(cmd_tbl_t *cmdtp, int flag, int argc,
688                         char * const argv[], bootm_headers_t *images)
689 {
690         int ret;
691         struct Image_header *ih;
692
693         ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
694                               images, 1);
695
696         /* Setup Linux kernel Image entry point */
697         if (!argc) {
698                 images->ep = load_addr;
699                 debug("*  kernel: default image load address = 0x%08lx\n",
700                                 load_addr);
701         } else {
702                 images->ep = simple_strtoul(argv[0], NULL, 16);
703                 debug("*  kernel: cmdline image address = 0x%08lx\n",
704                         images->ep);
705         }
706
707         ret = booti_setup(images);
708         if (ret != 0)
709                 return 1;
710
711         ih = (struct Image_header *)map_sysmem(images->ep, 0);
712
713         lmb_reserve(&images->lmb, images->ep, le32_to_cpu(ih->image_size));
714
715         /*
716          * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
717          * have a header that provide this informaiton.
718          */
719         if (bootm_find_ramdisk_fdt(flag, argc, argv))
720                 return 1;
721
722         return 0;
723 }
724
725 int do_booti(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
726 {
727         int ret;
728
729         /* Consume 'booti' */
730         argc--; argv++;
731
732         if (booti_start(cmdtp, flag, argc, argv, &images))
733                 return 1;
734
735         /*
736          * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
737          * disable interrupts ourselves
738          */
739         bootm_disable_interrupts();
740
741         images.os.os = IH_OS_LINUX;
742         ret = do_bootm_states(cmdtp, flag, argc, argv,
743                               BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
744                               BOOTM_STATE_OS_GO,
745                               &images, 1);
746
747         return ret;
748 }
749
750 #ifdef CONFIG_SYS_LONGHELP
751 static char booti_help_text[] =
752         "[addr [initrd[:size]] [fdt]]\n"
753         "    - boot Linux Image stored in memory\n"
754         "\tThe argument 'initrd' is optional and specifies the address\n"
755         "\tof the initrd in memory. The optional argument ':size' allows\n"
756         "\tspecifying the size of RAW initrd.\n"
757 #if defined(CONFIG_OF_LIBFDT)
758         "\tSince booting a Linux kernelrequires a flat device-tree\n"
759         "\ta third argument is required which is the address of the\n"
760         "\tdevice-tree blob. To boot that kernel without an initrd image,\n"
761         "\tuse a '-' for the second argument.\n"
762 #endif
763         "";
764 #endif
765
766 U_BOOT_CMD(
767         booti,  CONFIG_SYS_MAXARGS,     1,      do_booti,
768         "boot arm64 Linux Image image from memory", booti_help_text
769 );
770 #endif  /* CONFIG_CMD_BOOTI */