blob: 327712a536c0ff4d46f3727a6c6a243b38e9516b [file] [log] [blame]
Sam Protsenko035502e2020-01-24 17:53:42 +02001// 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>
Simon Glassed38aef2020-05-10 11:40:03 -06008#include <command.h>
Simon Glass2dc9c342020-05-10 11:40:01 -06009#include <image.h>
Sam Protsenko035502e2020-01-24 17:53:42 +020010#include <mapmem.h>
11
12#define abootimg_addr() \
13 (_abootimg_addr == -1 ? image_load_addr : _abootimg_addr)
14
15/* Please use abootimg_addr() macro to obtain the boot image address */
16static ulong _abootimg_addr = -1;
Roman Stratiienko826e0be2024-05-23 07:06:07 +000017static ulong _ainit_bootimg_addr = -1;
Safae Ouajih91da3632023-02-06 00:50:04 +010018static ulong _avendor_bootimg_addr = -1;
Sam Protsenko035502e2020-01-24 17:53:42 +020019
Safae Ouajih51c981b2023-02-06 00:50:17 +010020ulong get_abootimg_addr(void)
21{
22 return (_abootimg_addr == -1 ? image_load_addr : _abootimg_addr);
23}
24
Roman Stratiienko826e0be2024-05-23 07:06:07 +000025ulong get_ainit_bootimg_addr(void)
26{
27 return _ainit_bootimg_addr;
28}
29
Safae Ouajih51c981b2023-02-06 00:50:17 +010030ulong get_avendor_bootimg_addr(void)
31{
32 return _avendor_bootimg_addr;
33}
34
Simon Glassed38aef2020-05-10 11:40:03 -060035static int abootimg_get_ver(int argc, char *const argv[])
Sam Protsenko035502e2020-01-24 17:53:42 +020036{
Safae Ouajih8656e382023-02-06 00:50:03 +010037 const struct andr_boot_img_hdr_v0 *hdr;
Sam Protsenko035502e2020-01-24 17:53:42 +020038 int res = CMD_RET_SUCCESS;
39
40 if (argc > 1)
41 return CMD_RET_USAGE;
42
43 hdr = map_sysmem(abootimg_addr(), sizeof(*hdr));
Safae Ouajih88ad0c12023-02-06 00:50:05 +010044 if (!is_android_boot_image_header(hdr)) {
Sam Protsenko035502e2020-01-24 17:53:42 +020045 printf("Error: Boot Image header is incorrect\n");
46 res = CMD_RET_FAILURE;
47 goto exit;
48 }
49
50 if (argc == 0)
51 printf("%u\n", hdr->header_version);
52 else
53 env_set_ulong(argv[0], hdr->header_version);
54
55exit:
56 unmap_sysmem(hdr);
57 return res;
58}
59
Simon Glassed38aef2020-05-10 11:40:03 -060060static int abootimg_get_recovery_dtbo(int argc, char *const argv[])
Sam Protsenko035502e2020-01-24 17:53:42 +020061{
62 ulong addr;
63 u32 size;
64
65 if (argc > 2)
66 return CMD_RET_USAGE;
67
68 if (!android_image_get_dtbo(abootimg_addr(), &addr, &size))
69 return CMD_RET_FAILURE;
70
71 if (argc == 0) {
72 printf("%lx\n", addr);
73 } else {
74 env_set_hex(argv[0], addr);
75 if (argc == 2)
76 env_set_hex(argv[1], size);
77 }
78
79 return CMD_RET_SUCCESS;
80}
81
Simon Glassed38aef2020-05-10 11:40:03 -060082static int abootimg_get_dtb_load_addr(int argc, char *const argv[])
Sam Protsenko035502e2020-01-24 17:53:42 +020083{
Sam Protsenko035502e2020-01-24 17:53:42 +020084 if (argc > 1)
85 return CMD_RET_USAGE;
Safae Ouajihbced1042023-02-06 00:50:08 +010086 struct andr_image_data img_data = {0};
87 const struct andr_boot_img_hdr_v0 *hdr;
Safae Ouajih51c981b2023-02-06 00:50:17 +010088 const struct andr_vnd_boot_img_hdr *vhdr;
Sam Protsenko035502e2020-01-24 17:53:42 +020089
90 hdr = map_sysmem(abootimg_addr(), sizeof(*hdr));
Safae Ouajih51c981b2023-02-06 00:50:17 +010091 if (get_avendor_bootimg_addr() != -1)
92 vhdr = map_sysmem(get_avendor_bootimg_addr(), sizeof(*vhdr));
93
94 if (!android_image_get_data(hdr, vhdr, &img_data)) {
95 if (get_avendor_bootimg_addr() != -1)
96 unmap_sysmem(vhdr);
Safae Ouajihbced1042023-02-06 00:50:08 +010097 unmap_sysmem(hdr);
98 return CMD_RET_FAILURE;
Sam Protsenko035502e2020-01-24 17:53:42 +020099 }
Safae Ouajih51c981b2023-02-06 00:50:17 +0100100
101 if (get_avendor_bootimg_addr() != -1)
102 unmap_sysmem(vhdr);
Safae Ouajihbced1042023-02-06 00:50:08 +0100103 unmap_sysmem(hdr);
Sam Protsenko035502e2020-01-24 17:53:42 +0200104
Safae Ouajihbced1042023-02-06 00:50:08 +0100105 if (img_data.header_version < 2) {
Sam Protsenko035502e2020-01-24 17:53:42 +0200106 printf("Error: header_version must be >= 2 for this\n");
Safae Ouajihbced1042023-02-06 00:50:08 +0100107 return CMD_RET_FAILURE;
Sam Protsenko035502e2020-01-24 17:53:42 +0200108 }
109
Safae Ouajihbced1042023-02-06 00:50:08 +0100110 if (!img_data.dtb_load_addr) {
111 printf("Error: failed to read dtb_load_addr\n");
112 return CMD_RET_FAILURE;
113 }
114
Sam Protsenko035502e2020-01-24 17:53:42 +0200115 if (argc == 0)
Safae Ouajihbced1042023-02-06 00:50:08 +0100116 printf("%lx\n", (ulong)img_data.dtb_load_addr);
Sam Protsenko035502e2020-01-24 17:53:42 +0200117 else
Safae Ouajihbced1042023-02-06 00:50:08 +0100118 env_set_hex(argv[0], (ulong)img_data.dtb_load_addr);
Sam Protsenko035502e2020-01-24 17:53:42 +0200119
Safae Ouajihbced1042023-02-06 00:50:08 +0100120 return CMD_RET_SUCCESS;
Sam Protsenko035502e2020-01-24 17:53:42 +0200121}
122
Simon Glassed38aef2020-05-10 11:40:03 -0600123static int abootimg_get_dtb_by_index(int argc, char *const argv[])
Sam Protsenko035502e2020-01-24 17:53:42 +0200124{
125 const char *index_str;
126 u32 num;
127 char *endp;
128 ulong addr;
129 u32 size;
130
131 if (argc < 1 || argc > 3)
132 return CMD_RET_USAGE;
133
134 index_str = argv[0] + strlen("--index=");
135 if (index_str[0] == '\0') {
136 printf("Error: Wrong index num\n");
137 return CMD_RET_FAILURE;
138 }
139
140 num = simple_strtoul(index_str, &endp, 0);
141 if (*endp != '\0') {
142 printf("Error: Wrong index num\n");
143 return CMD_RET_FAILURE;
144 }
145
Safae Ouajih51c981b2023-02-06 00:50:17 +0100146 if (!android_image_get_dtb_by_index(abootimg_addr(),
147 get_avendor_bootimg_addr(), num,
Sam Protsenko035502e2020-01-24 17:53:42 +0200148 &addr, &size)) {
149 return CMD_RET_FAILURE;
150 }
151
152 if (argc == 1) {
153 printf("%lx\n", addr);
154 } else {
155 if (env_set_hex(argv[1], addr)) {
156 printf("Error: Can't set [addr_var]\n");
157 return CMD_RET_FAILURE;
158 }
159
160 if (argc == 3) {
161 if (env_set_hex(argv[2], size)) {
162 printf("Error: Can't set [size_var]\n");
163 return CMD_RET_FAILURE;
164 }
165 }
166 }
167
168 return CMD_RET_SUCCESS;
169}
170
Simon Glassed38aef2020-05-10 11:40:03 -0600171static int abootimg_get_dtb(int argc, char *const argv[])
Sam Protsenko035502e2020-01-24 17:53:42 +0200172{
173 if (argc < 1)
174 return CMD_RET_USAGE;
175
176 if (strstr(argv[0], "--index="))
177 return abootimg_get_dtb_by_index(argc, argv);
178
179 return CMD_RET_USAGE;
180}
181
Simon Glassed38aef2020-05-10 11:40:03 -0600182static int do_abootimg_addr(struct cmd_tbl *cmdtp, int flag, int argc,
183 char *const argv[])
Sam Protsenko035502e2020-01-24 17:53:42 +0200184{
185 char *endp;
186 ulong img_addr;
187
Roman Stratiienko826e0be2024-05-23 07:06:07 +0000188 if (argc < 2 || argc > 4)
Sam Protsenko035502e2020-01-24 17:53:42 +0200189 return CMD_RET_USAGE;
190
Simon Glass3ff49ec2021-07-24 09:03:29 -0600191 img_addr = hextoul(argv[1], &endp);
Sam Protsenko035502e2020-01-24 17:53:42 +0200192 if (*endp != '\0') {
193 printf("Error: Wrong image address\n");
194 return CMD_RET_FAILURE;
195 }
196
197 _abootimg_addr = img_addr;
Safae Ouajih91da3632023-02-06 00:50:04 +0100198
Roman Stratiienko826e0be2024-05-23 07:06:07 +0000199 if (argc > 2) {
Safae Ouajih91da3632023-02-06 00:50:04 +0100200 img_addr = simple_strtoul(argv[2], &endp, 16);
201 if (*endp != '\0') {
Roman Stratiienko826e0be2024-05-23 07:06:07 +0000202 printf("Error: Wrong vendor_boot image address\n");
Safae Ouajih91da3632023-02-06 00:50:04 +0100203 return CMD_RET_FAILURE;
204 }
205
206 _avendor_bootimg_addr = img_addr;
207 }
208
Roman Stratiienko826e0be2024-05-23 07:06:07 +0000209 if (argc == 4) {
210 img_addr = simple_strtoul(argv[3], &endp, 16);
211 if (*endp != '\0') {
212 printf("Error: Wrong init_boot image address\n");
213 return CMD_RET_FAILURE;
214 }
215
216 _ainit_bootimg_addr = img_addr;
217 }
218
Sam Protsenko035502e2020-01-24 17:53:42 +0200219 return CMD_RET_SUCCESS;
220}
221
Simon Glassed38aef2020-05-10 11:40:03 -0600222static int do_abootimg_get(struct cmd_tbl *cmdtp, int flag, int argc,
223 char *const argv[])
Sam Protsenko035502e2020-01-24 17:53:42 +0200224{
225 const char *param;
226
227 if (argc < 2)
228 return CMD_RET_USAGE;
229
230 param = argv[1];
231 argc -= 2;
232 argv += 2;
233 if (!strcmp(param, "ver"))
234 return abootimg_get_ver(argc, argv);
235 else if (!strcmp(param, "recovery_dtbo"))
236 return abootimg_get_recovery_dtbo(argc, argv);
237 else if (!strcmp(param, "dtb_load_addr"))
238 return abootimg_get_dtb_load_addr(argc, argv);
239 else if (!strcmp(param, "dtb"))
240 return abootimg_get_dtb(argc, argv);
241
242 return CMD_RET_USAGE;
243}
244
Simon Glassed38aef2020-05-10 11:40:03 -0600245static int do_abootimg_dump(struct cmd_tbl *cmdtp, int flag, int argc,
246 char *const argv[])
Sam Protsenko035502e2020-01-24 17:53:42 +0200247{
248 if (argc != 2)
249 return CMD_RET_USAGE;
250
251 if (!strcmp(argv[1], "dtb")) {
252 if (android_image_print_dtb_contents(abootimg_addr()))
253 return CMD_RET_FAILURE;
254 } else {
255 return CMD_RET_USAGE;
256 }
257
258 return CMD_RET_SUCCESS;
259}
260
Simon Glassed38aef2020-05-10 11:40:03 -0600261static struct cmd_tbl cmd_abootimg_sub[] = {
Roman Stratiienko826e0be2024-05-23 07:06:07 +0000262 U_BOOT_CMD_MKENT(addr, 4, 1, do_abootimg_addr, "", ""),
Sam Protsenko035502e2020-01-24 17:53:42 +0200263 U_BOOT_CMD_MKENT(dump, 2, 1, do_abootimg_dump, "", ""),
264 U_BOOT_CMD_MKENT(get, 5, 1, do_abootimg_get, "", ""),
265};
266
Simon Glassed38aef2020-05-10 11:40:03 -0600267static int do_abootimg(struct cmd_tbl *cmdtp, int flag, int argc,
268 char *const argv[])
Sam Protsenko035502e2020-01-24 17:53:42 +0200269{
Simon Glassed38aef2020-05-10 11:40:03 -0600270 struct cmd_tbl *cp;
Sam Protsenko035502e2020-01-24 17:53:42 +0200271
272 cp = find_cmd_tbl(argv[1], cmd_abootimg_sub,
273 ARRAY_SIZE(cmd_abootimg_sub));
274
275 /* Strip off leading 'abootimg' command argument */
276 argc--;
277 argv++;
278
279 if (!cp || argc > cp->maxargs)
280 return CMD_RET_USAGE;
281 if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
282 return CMD_RET_SUCCESS;
283
284 return cp->cmd(cmdtp, flag, argc, argv);
285}
286
287U_BOOT_CMD(
288 abootimg, CONFIG_SYS_MAXARGS, 0, do_abootimg,
289 "manipulate Android Boot Image",
Roman Stratiienko826e0be2024-05-23 07:06:07 +0000290 "addr <boot_img_addr> [<vendor_boot_img_addr> [<init_boot_img_addr>]]\n"
Sam Protsenko035502e2020-01-24 17:53:42 +0200291 " - set the address in RAM where boot image is located\n"
292 " ($loadaddr is used by default)\n"
293 "abootimg dump dtb\n"
294 " - print info for all DT blobs in DTB area\n"
295 "abootimg get ver [varname]\n"
296 " - get header version\n"
297 "abootimg get recovery_dtbo [addr_var [size_var]]\n"
298 " - get address and size (hex) of recovery DTBO area in the image\n"
299 " [addr_var]: variable name to contain DTBO area address\n"
300 " [size_var]: variable name to contain DTBO area size\n"
301 "abootimg get dtb_load_addr [varname]\n"
302 " - get load address (hex) of DTB, from image header\n"
303 "abootimg get dtb --index=<num> [addr_var [size_var]]\n"
304 " - get address and size (hex) of DT blob in the image by index\n"
305 " <num>: index number of desired DT blob in DTB area\n"
306 " [addr_var]: variable name to contain DT blob address\n"
307 " [size_var]: variable name to contain DT blob size"
308);