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