]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - cmd/booti.c
cmd: pmic: add missing parameter 'value' for 'write' subcommand to help message
[karo-tx-uboot.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 #include <malloc.h>
15
16 DECLARE_GLOBAL_DATA_PTR;
17
18 /* See Documentation/arm64/booting.txt in the Linux kernel */
19 struct Image_header {
20         uint32_t        code0;          /* Executable code */
21         uint32_t        code1;          /* Executable code */
22         uint64_t        text_offset;    /* Image load offset, LE */
23         uint64_t        image_size;     /* Effective Image size, LE */
24         uint64_t        res1;           /* reserved */
25         uint64_t        res2;           /* reserved */
26         uint64_t        res3;           /* reserved */
27         uint64_t        res4;           /* reserved */
28         uint32_t        magic;          /* Magic number */
29         uint32_t        res5;
30 };
31
32 #define LINUX_ARM64_IMAGE_MAGIC 0x644d5241
33
34 static int booti_decompress(bootm_headers_t *images)
35 {
36         int ret;
37         uint8_t *bp = (void *)images->ep;
38         size_t img_size = SZ_4M;
39         size_t max_len = img_size * 4;
40         ulong decomp_len;
41         void *dst;
42
43         /* check for gzip magic */
44         if (bp[0] != 0x1f || bp[1] != 0x8b)
45                 return 0;
46
47         dst = memalign(max_len, 64);
48         if (dst == NULL) {
49                 printf("Failed to allocate %zu byte for decompressed kernel image\n",
50                         max_len);
51                 return -ENOMEM;
52         }
53
54         printf("Uncompressing Image from 0x%08lx..0x%08lx to %p..%p\n",
55                 images->ep, images->ep + img_size - 1,
56                 dst, dst + max_len - 1);
57         ret = gunzip(dst, max_len, (void *)images->ep, &decomp_len);
58         if (ret) {
59                 free(dst);
60                 return ret;
61         }
62         debug("Changing EP address from %08lx to %p\n", images->ep, dst);
63         images->ep = (uint64_t)dst;
64         return 0;
65 }
66
67 static int booti_setup(bootm_headers_t *images)
68 {
69         int ret;
70         struct Image_header *ih;
71         uint64_t dst;
72         uint64_t image_size;
73
74         ret = booti_decompress(images);
75         if (ret)
76                 return ret;
77
78         ih = (struct Image_header *)map_sysmem(images->ep, 0);
79
80         if (ih->magic != le32_to_cpu(LINUX_ARM64_IMAGE_MAGIC)) {
81                 puts("Bad Linux ARM64 Image magic!\n");
82                 return 1;
83         }
84
85         if (ih->image_size == 0) {
86                 puts("Image lacks image_size field, assuming 16MiB\n");
87                 image_size = 16 << 20;
88         } else {
89                 image_size = le64_to_cpu(ih->image_size);
90         }
91
92         /*
93          * If we are not at the correct run-time location, set the new
94          * correct location and then move the image there.
95          */
96         dst = gd->bd->bi_dram[0].start + le64_to_cpu(ih->text_offset);
97
98         unmap_sysmem(ih);
99
100         if (images->ep != dst) {
101                 void *src;
102
103                 debug("Moving Image from 0x%lx to 0x%llx\n", images->ep, dst);
104
105                 src = (void *)images->ep;
106                 images->ep = dst;
107                 memmove((void *)dst, src, image_size);
108         }
109
110         return 0;
111 }
112
113 /*
114  * Image booting support
115  */
116 static int booti_start(cmd_tbl_t *cmdtp, int flag, int argc,
117                         char * const argv[], bootm_headers_t *images)
118 {
119         int ret;
120         struct Image_header *ih;
121
122         ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
123                               images, 1);
124
125         /* Setup Linux kernel Image entry point */
126         if (!argc) {
127                 images->ep = load_addr;
128                 debug("*  kernel: default image load address = 0x%08lx\n",
129                                 load_addr);
130         } else {
131                 images->ep = simple_strtoul(argv[0], NULL, 16);
132                 debug("*  kernel: cmdline image address = 0x%08lx\n",
133                         images->ep);
134         }
135
136         ret = booti_setup(images);
137         if (ret != 0)
138                 return 1;
139
140         ih = (struct Image_header *)map_sysmem(images->ep, 0);
141
142         lmb_reserve(&images->lmb, images->ep, le32_to_cpu(ih->image_size));
143
144         unmap_sysmem(ih);
145
146         /*
147          * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
148          * have a header that provide this informaiton.
149          */
150         if (bootm_find_images(flag, argc, argv))
151                 return 1;
152
153         return 0;
154 }
155
156 int do_booti(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
157 {
158         int ret;
159
160         /* Consume 'booti' */
161         argc--; argv++;
162
163         if (booti_start(cmdtp, flag, argc, argv, &images))
164                 return 1;
165
166         /*
167          * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
168          * disable interrupts ourselves
169          */
170         bootm_disable_interrupts();
171
172         images.os.os = IH_OS_LINUX;
173         ret = do_bootm_states(cmdtp, flag, argc, argv,
174                               BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
175                               BOOTM_STATE_OS_GO,
176                               &images, 1);
177
178         return ret;
179 }
180
181 #ifdef CONFIG_SYS_LONGHELP
182 static char booti_help_text[] =
183         "[addr [initrd[:size]] [fdt]]\n"
184         "    - boot arm64 Linux Image stored in memory\n"
185         "\tThe argument 'initrd' is optional and specifies the address\n"
186         "\tof an initrd in memory. The optional parameter ':size' allows\n"
187         "\tspecifying the size of a RAW initrd.\n"
188 #if defined(CONFIG_OF_LIBFDT)
189         "\tSince booting a Linux kernel requires a flat device-tree, a\n"
190         "\tthird argument providing the address of the device-tree blob\n"
191         "\tis required. To boot a kernel with a device-tree blob but\n"
192         "\twithout an initrd image, use a '-' for the initrd argument.\n"
193 #endif
194         "";
195 #endif
196
197 U_BOOT_CMD(
198         booti,  CONFIG_SYS_MAXARGS,     1,      do_booti,
199         "boot arm64 Linux Image image from memory", booti_help_text
200 );