Merge branch 'master' of git://git.denx.de/u-boot
[platform/kernel/u-boot.git] / cmd / abootimg.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2020
4  * Sam Protsenko <joe.skb7@gmail.com>
5  */
6
7 #include <android_image.h>
8 #include <common.h>
9 #include <mapmem.h>
10
11 #define abootimg_addr() \
12         (_abootimg_addr == -1 ? image_load_addr : _abootimg_addr)
13
14 /* Please use abootimg_addr() macro to obtain the boot image address */
15 static ulong _abootimg_addr = -1;
16
17 static int abootimg_get_ver(int argc, char * const argv[])
18 {
19         const struct andr_img_hdr *hdr;
20         int res = CMD_RET_SUCCESS;
21
22         if (argc > 1)
23                 return CMD_RET_USAGE;
24
25         hdr = map_sysmem(abootimg_addr(), sizeof(*hdr));
26         if (android_image_check_header(hdr)) {
27                 printf("Error: Boot Image header is incorrect\n");
28                 res = CMD_RET_FAILURE;
29                 goto exit;
30         }
31
32         if (argc == 0)
33                 printf("%u\n", hdr->header_version);
34         else
35                 env_set_ulong(argv[0], hdr->header_version);
36
37 exit:
38         unmap_sysmem(hdr);
39         return res;
40 }
41
42 static int abootimg_get_recovery_dtbo(int argc, char * const argv[])
43 {
44         ulong addr;
45         u32 size;
46
47         if (argc > 2)
48                 return CMD_RET_USAGE;
49
50         if (!android_image_get_dtbo(abootimg_addr(), &addr, &size))
51                 return CMD_RET_FAILURE;
52
53         if (argc == 0) {
54                 printf("%lx\n", addr);
55         } else {
56                 env_set_hex(argv[0], addr);
57                 if (argc == 2)
58                         env_set_hex(argv[1], size);
59         }
60
61         return CMD_RET_SUCCESS;
62 }
63
64 static int abootimg_get_dtb_load_addr(int argc, char * const argv[])
65 {
66         const struct andr_img_hdr *hdr;
67         int res = CMD_RET_SUCCESS;
68
69         if (argc > 1)
70                 return CMD_RET_USAGE;
71
72         hdr = map_sysmem(abootimg_addr(), sizeof(*hdr));
73         if (android_image_check_header(hdr)) {
74                 printf("Error: Boot Image header is incorrect\n");
75                 res = CMD_RET_FAILURE;
76                 goto exit;
77         }
78
79         if (hdr->header_version < 2) {
80                 printf("Error: header_version must be >= 2 for this\n");
81                 res = CMD_RET_FAILURE;
82                 goto exit;
83         }
84
85         if (argc == 0)
86                 printf("%lx\n", (ulong)hdr->dtb_addr);
87         else
88                 env_set_hex(argv[0], (ulong)hdr->dtb_addr);
89
90 exit:
91         unmap_sysmem(hdr);
92         return res;
93 }
94
95 static int abootimg_get_dtb_by_index(int argc, char * const argv[])
96 {
97         const char *index_str;
98         u32 num;
99         char *endp;
100         ulong addr;
101         u32 size;
102
103         if (argc < 1 || argc > 3)
104                 return CMD_RET_USAGE;
105
106         index_str = argv[0] + strlen("--index=");
107         if (index_str[0] == '\0') {
108                 printf("Error: Wrong index num\n");
109                 return CMD_RET_FAILURE;
110         }
111
112         num = simple_strtoul(index_str, &endp, 0);
113         if (*endp != '\0') {
114                 printf("Error: Wrong index num\n");
115                 return CMD_RET_FAILURE;
116         }
117
118         if (!android_image_get_dtb_by_index(abootimg_addr(), num,
119                                             &addr, &size)) {
120                 return CMD_RET_FAILURE;
121         }
122
123         if (argc == 1) {
124                 printf("%lx\n", addr);
125         } else {
126                 if (env_set_hex(argv[1], addr)) {
127                         printf("Error: Can't set [addr_var]\n");
128                         return CMD_RET_FAILURE;
129                 }
130
131                 if (argc == 3) {
132                         if (env_set_hex(argv[2], size)) {
133                                 printf("Error: Can't set [size_var]\n");
134                                 return CMD_RET_FAILURE;
135                         }
136                 }
137         }
138
139         return CMD_RET_SUCCESS;
140 }
141
142 static int abootimg_get_dtb(int argc, char * const argv[])
143 {
144         if (argc < 1)
145                 return CMD_RET_USAGE;
146
147         if (strstr(argv[0], "--index="))
148                 return abootimg_get_dtb_by_index(argc, argv);
149
150         return CMD_RET_USAGE;
151 }
152
153 static int do_abootimg_addr(cmd_tbl_t *cmdtp, int flag, int argc,
154                             char * const argv[])
155 {
156         char *endp;
157         ulong img_addr;
158
159         if (argc != 2)
160                 return CMD_RET_USAGE;
161
162         img_addr = simple_strtoul(argv[1], &endp, 16);
163         if (*endp != '\0') {
164                 printf("Error: Wrong image address\n");
165                 return CMD_RET_FAILURE;
166         }
167
168         _abootimg_addr = img_addr;
169         return CMD_RET_SUCCESS;
170 }
171
172 static int do_abootimg_get(cmd_tbl_t *cmdtp, int flag, int argc,
173                            char * const argv[])
174 {
175         const char *param;
176
177         if (argc < 2)
178                 return CMD_RET_USAGE;
179
180         param = argv[1];
181         argc -= 2;
182         argv += 2;
183         if (!strcmp(param, "ver"))
184                 return abootimg_get_ver(argc, argv);
185         else if (!strcmp(param, "recovery_dtbo"))
186                 return abootimg_get_recovery_dtbo(argc, argv);
187         else if (!strcmp(param, "dtb_load_addr"))
188                 return abootimg_get_dtb_load_addr(argc, argv);
189         else if (!strcmp(param, "dtb"))
190                 return abootimg_get_dtb(argc, argv);
191
192         return CMD_RET_USAGE;
193 }
194
195 static int do_abootimg_dump(cmd_tbl_t *cmdtp, int flag, int argc,
196                             char * const argv[])
197 {
198         if (argc != 2)
199                 return CMD_RET_USAGE;
200
201         if (!strcmp(argv[1], "dtb")) {
202                 if (android_image_print_dtb_contents(abootimg_addr()))
203                         return CMD_RET_FAILURE;
204         } else {
205                 return CMD_RET_USAGE;
206         }
207
208         return CMD_RET_SUCCESS;
209 }
210
211 static cmd_tbl_t cmd_abootimg_sub[] = {
212         U_BOOT_CMD_MKENT(addr, 2, 1, do_abootimg_addr, "", ""),
213         U_BOOT_CMD_MKENT(dump, 2, 1, do_abootimg_dump, "", ""),
214         U_BOOT_CMD_MKENT(get, 5, 1, do_abootimg_get, "", ""),
215 };
216
217 static int do_abootimg(cmd_tbl_t *cmdtp, int flag, int argc,
218                        char * const argv[])
219 {
220         cmd_tbl_t *cp;
221
222         cp = find_cmd_tbl(argv[1], cmd_abootimg_sub,
223                           ARRAY_SIZE(cmd_abootimg_sub));
224
225         /* Strip off leading 'abootimg' command argument */
226         argc--;
227         argv++;
228
229         if (!cp || argc > cp->maxargs)
230                 return CMD_RET_USAGE;
231         if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
232                 return CMD_RET_SUCCESS;
233
234         return cp->cmd(cmdtp, flag, argc, argv);
235 }
236
237 U_BOOT_CMD(
238         abootimg, CONFIG_SYS_MAXARGS, 0, do_abootimg,
239         "manipulate Android Boot Image",
240         "addr <addr>\n"
241         "    - set the address in RAM where boot image is located\n"
242         "      ($loadaddr is used by default)\n"
243         "abootimg dump dtb\n"
244         "    - print info for all DT blobs in DTB area\n"
245         "abootimg get ver [varname]\n"
246         "    - get header version\n"
247         "abootimg get recovery_dtbo [addr_var [size_var]]\n"
248         "    - get address and size (hex) of recovery DTBO area in the image\n"
249         "      [addr_var]: variable name to contain DTBO area address\n"
250         "      [size_var]: variable name to contain DTBO area size\n"
251         "abootimg get dtb_load_addr [varname]\n"
252         "    - get load address (hex) of DTB, from image header\n"
253         "abootimg get dtb --index=<num> [addr_var [size_var]]\n"
254         "    - get address and size (hex) of DT blob in the image by index\n"
255         "      <num>: index number of desired DT blob in DTB area\n"
256         "      [addr_var]: variable name to contain DT blob address\n"
257         "      [size_var]: variable name to contain DT blob size"
258 );