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