cmd: Split 'bootz' and 'booti' out from 'bootm'
[oweals/u-boot.git] / cmd / booti.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 #include <common.h>
9 #include <bootm.h>
10 #include <command.h>
11 #include <image.h>
12 #include <lmb.h>
13 #include <mapmem.h>
14
15 DECLARE_GLOBAL_DATA_PTR;
16
17 /* See Documentation/arm64/booting.txt in the Linux kernel */
18 struct Image_header {
19         uint32_t        code0;          /* Executable code */
20         uint32_t        code1;          /* Executable code */
21         uint64_t        text_offset;    /* Image load offset, LE */
22         uint64_t        image_size;     /* Effective Image size, LE */
23         uint64_t        res1;           /* reserved */
24         uint64_t        res2;           /* reserved */
25         uint64_t        res3;           /* reserved */
26         uint64_t        res4;           /* reserved */
27         uint32_t        magic;          /* Magic number */
28         uint32_t        res5;
29 };
30
31 #define LINUX_ARM64_IMAGE_MAGIC 0x644d5241
32
33 static int booti_setup(bootm_headers_t *images)
34 {
35         struct Image_header *ih;
36         uint64_t dst;
37         uint64_t image_size;
38
39         ih = (struct Image_header *)map_sysmem(images->ep, 0);
40
41         if (ih->magic != le32_to_cpu(LINUX_ARM64_IMAGE_MAGIC)) {
42                 puts("Bad Linux ARM64 Image magic!\n");
43                 return 1;
44         }
45         
46         if (ih->image_size == 0) {
47                 puts("Image lacks image_size field, assuming 16MiB\n");
48                 image_size = 16 << 20;
49         } else {
50                 image_size = le64_to_cpu(ih->image_size);
51         }
52
53         /*
54          * If we are not at the correct run-time location, set the new
55          * correct location and then move the image there.
56          */
57         dst = gd->bd->bi_dram[0].start + le64_to_cpu(ih->text_offset);
58
59         unmap_sysmem(ih);
60
61         if (images->ep != dst) {
62                 void *src;
63
64                 debug("Moving Image from 0x%lx to 0x%llx\n", images->ep, dst);
65
66                 src = (void *)images->ep;
67                 images->ep = dst;
68                 memmove((void *)dst, src, image_size);
69         }
70
71         return 0;
72 }
73
74 /*
75  * Image booting support
76  */
77 static int booti_start(cmd_tbl_t *cmdtp, int flag, int argc,
78                         char * const argv[], bootm_headers_t *images)
79 {
80         int ret;
81         struct Image_header *ih;
82
83         ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
84                               images, 1);
85
86         /* Setup Linux kernel Image entry point */
87         if (!argc) {
88                 images->ep = load_addr;
89                 debug("*  kernel: default image load address = 0x%08lx\n",
90                                 load_addr);
91         } else {
92                 images->ep = simple_strtoul(argv[0], NULL, 16);
93                 debug("*  kernel: cmdline image address = 0x%08lx\n",
94                         images->ep);
95         }
96
97         ret = booti_setup(images);
98         if (ret != 0)
99                 return 1;
100
101         ih = (struct Image_header *)map_sysmem(images->ep, 0);
102
103         lmb_reserve(&images->lmb, images->ep, le32_to_cpu(ih->image_size));
104
105         unmap_sysmem(ih);
106
107         /*
108          * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
109          * have a header that provide this informaiton.
110          */
111         if (bootm_find_images(flag, argc, argv))
112                 return 1;
113
114         return 0;
115 }
116
117 int do_booti(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
118 {
119         int ret;
120
121         /* Consume 'booti' */
122         argc--; argv++;
123
124         if (booti_start(cmdtp, flag, argc, argv, &images))
125                 return 1;
126
127         /*
128          * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
129          * disable interrupts ourselves
130          */
131         bootm_disable_interrupts();
132
133         images.os.os = IH_OS_LINUX;
134         ret = do_bootm_states(cmdtp, flag, argc, argv,
135                               BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
136                               BOOTM_STATE_OS_GO,
137                               &images, 1);
138
139         return ret;
140 }
141
142 #ifdef CONFIG_SYS_LONGHELP
143 static char booti_help_text[] =
144         "[addr [initrd[:size]] [fdt]]\n"
145         "    - boot arm64 Linux Image stored in memory\n"
146         "\tThe argument 'initrd' is optional and specifies the address\n"
147         "\tof an initrd in memory. The optional parameter ':size' allows\n"
148         "\tspecifying the size of a RAW initrd.\n"
149 #if defined(CONFIG_OF_LIBFDT)
150         "\tSince booting a Linux kernel requires a flat device-tree, a\n"
151         "\tthird argument providing the address of the device-tree blob\n"
152         "\tis required. To boot a kernel with a device-tree blob but\n"
153         "\twithout an initrd image, use a '-' for the initrd argument.\n"
154 #endif
155         "";
156 #endif
157
158 U_BOOT_CMD(
159         booti,  CONFIG_SYS_MAXARGS,     1,      do_booti,
160         "boot arm64 Linux Image image from memory", booti_help_text
161 );