Blame view

cmd/adtimg.c 5.52 KB
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
1
2
3
4
  // SPDX-License-Identifier: GPL-2.0+
  /*
   * (C) Copyright 2018 Linaro Ltd.
   * Sam Protsenko <semen.protsenko@linaro.org>
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
5
   * Eugeniu Rosca <rosca.eugeniu@gmail.com>
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
6
   */
9fb625ce0   Simon Glass   env: Move env_set...
7
  #include <env.h>
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
8
9
  #include <image-android-dt.h>
  #include <common.h>
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
10
  #define OPT_INDEX	"--index"
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
11

4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
12
13
14
15
16
17
18
  /*
   * Current/working DTB/DTBO Android image address.
   * Similar to 'working_fdt' variable in 'fdt' command.
   */
  static ulong working_img;
  
  static int do_adtimg_addr(cmd_tbl_t *cmdtp, int flag, int argc,
4c6edc288   Eugeniu Rosca   cmd: adtimg: Rena...
19
  			  char * const argv[])
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
20
21
22
23
24
25
26
27
28
  {
  	char *endp;
  	ulong hdr_addr;
  
  	if (argc != 2)
  		return CMD_RET_USAGE;
  
  	hdr_addr = simple_strtoul(argv[1], &endp, 16);
  	if (*endp != '\0') {
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
29
30
  		printf("Error: Wrong image address '%s'
  ", argv[1]);
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
31
32
  		return CMD_RET_FAILURE;
  	}
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  	/*
  	 * Allow users to set an address prior to copying the DTB/DTBO
  	 * image to that same address, i.e. skip header verification.
  	 */
  
  	working_img = hdr_addr;
  	return CMD_RET_SUCCESS;
  }
  
  static int adtimg_check_working_img(void)
  {
  	if (!working_img) {
  		printf("Error: Please, call 'adtimg addr <addr>'. Aborting!
  ");
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
47
48
  		return CMD_RET_FAILURE;
  	}
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
49
50
51
52
53
  	if (!android_dt_check_header(working_img)) {
  		printf("Error: Invalid image header at 0x%lx
  ", working_img);
  		return CMD_RET_FAILURE;
  	}
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
54
55
56
  
  	return CMD_RET_SUCCESS;
  }
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
57
58
  static int do_adtimg_dump(cmd_tbl_t *cmdtp, int flag, int argc,
  			  char * const argv[])
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
59
  {
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
60
  	if (argc != 1)
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
61
  		return CMD_RET_USAGE;
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
  	if (adtimg_check_working_img() != CMD_RET_SUCCESS)
  		return CMD_RET_FAILURE;
  
  	android_dt_print_contents(working_img);
  
  	return CMD_RET_SUCCESS;
  }
  
  static int adtimg_getopt_u32(char * const opt, char * const name, u32 *optval)
  {
  	char *endp, *str;
  	u32 val;
  
  	if (!opt || !name || !optval)
  		return CMD_RET_FAILURE;
  
  	str = strchr(opt, '=');
  	if (!str) {
  		printf("Error: Option '%s' not followed by '='
  ", name);
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
82
83
  		return CMD_RET_FAILURE;
  	}
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
84
85
86
  	if (*++str == '\0') {
  		printf("Error: Option '%s=' not followed by value
  ", name);
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
87
88
  		return CMD_RET_FAILURE;
  	}
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
89
  	val = simple_strtoul(str, &endp, 0);
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
90
  	if (*endp != '\0') {
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
91
92
  		printf("Error: Wrong integer value '%s=%s'
  ", name, str);
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
93
94
  		return CMD_RET_FAILURE;
  	}
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
95
96
97
98
99
100
101
102
103
104
  	*optval = val;
  	return CMD_RET_SUCCESS;
  }
  
  static int adtimg_getopt_index(int argc, char * const argv[], u32 *index,
  			       char **avar, char **svar)
  {
  	int ret;
  
  	if (!argv || !avar || !svar)
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
105
  		return CMD_RET_FAILURE;
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
106
107
108
  	if (argc > 3) {
  		printf("Error: Unexpected argument '%s'
  ", argv[3]);
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
109
110
  		return CMD_RET_FAILURE;
  	}
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
111
112
113
114
115
116
117
118
  	ret = adtimg_getopt_u32(argv[0], OPT_INDEX, index);
  	if (ret != CMD_RET_SUCCESS)
  		return ret;
  
  	if (argc > 1)
  		*avar = argv[1];
  	if (argc > 2)
  		*svar = argv[2];
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
119
120
121
  
  	return CMD_RET_SUCCESS;
  }
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
122
  static int adtimg_get_dt_by_index(int argc, char * const argv[])
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
123
  {
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
  	ulong addr;
  	u32 index, size;
  	int ret;
  	char *avar = NULL, *svar = NULL;
  
  	ret = adtimg_getopt_index(argc, argv, &index, &avar, &svar);
  	if (ret != CMD_RET_SUCCESS)
  		return ret;
  
  	if (!android_dt_get_fdt_by_index(working_img, index, &addr, &size))
  		return CMD_RET_FAILURE;
  
  	if (avar && svar) {
  		ret = env_set_hex(avar, addr);
  		if (ret) {
  			printf("Error: Can't set '%s' to 0x%lx
  ", avar, addr);
  			return CMD_RET_FAILURE;
  		}
  		ret = env_set_hex(svar, size);
  		if (ret) {
  			printf("Error: Can't set '%s' to 0x%x
  ", svar, size);
  			return CMD_RET_FAILURE;
  		}
  	} else if (avar) {
  		ret = env_set_hex(avar, addr);
  		if (ret) {
  			printf("Error: Can't set '%s' to 0x%lx
  ", avar, addr);
  			return CMD_RET_FAILURE;
  		}
  		printf("0x%x (%d)
  ", size, size);
  	} else {
  		printf("0x%lx, 0x%x (%d)
  ", addr, size, size);
  	}
  
  	return CMD_RET_SUCCESS;
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
164
  }
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
165
  static int adtimg_get_dt(int argc, char * const argv[])
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
166
  {
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
  	if (argc < 2) {
  		printf("Error: No options passed to '%s'
  ", argv[0]);
  		return CMD_RET_FAILURE;
  	}
  
  	/* Strip off leading 'dt' command argument */
  	argc--;
  	argv++;
  
  	if (!strncmp(argv[0], OPT_INDEX, sizeof(OPT_INDEX) - 1))
  		return adtimg_get_dt_by_index(argc, argv);
  
  	printf("Error: Option '%s' not supported
  ", argv[0]);
  	return CMD_RET_FAILURE;
  }
  
  static int do_adtimg_get(cmd_tbl_t *cmdtp, int flag, int argc,
  			 char * const argv[])
  {
  	if (argc < 2) {
  		printf("Error: No arguments passed to '%s'
  ", argv[0]);
  		return CMD_RET_FAILURE;
  	}
  
  	if (adtimg_check_working_img() != CMD_RET_SUCCESS)
  		return CMD_RET_FAILURE;
  
  	/* Strip off leading 'get' command argument */
  	argc--;
  	argv++;
  
  	if (!strcmp(argv[0], "dt"))
  		return adtimg_get_dt(argc, argv);
  
  	printf("Error: Wrong argument '%s'
  ", argv[0]);
  	return CMD_RET_FAILURE;
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
207
  }
4c6edc288   Eugeniu Rosca   cmd: adtimg: Rena...
208
  static cmd_tbl_t cmd_adtimg_sub[] = {
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
209
210
211
  	U_BOOT_CMD_MKENT(addr, CONFIG_SYS_MAXARGS, 1, do_adtimg_addr, "", ""),
  	U_BOOT_CMD_MKENT(dump, CONFIG_SYS_MAXARGS, 1, do_adtimg_dump, "", ""),
  	U_BOOT_CMD_MKENT(get, CONFIG_SYS_MAXARGS, 1, do_adtimg_get, "", ""),
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
212
  };
4c6edc288   Eugeniu Rosca   cmd: adtimg: Rena...
213
  static int do_adtimg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
214
215
  {
  	cmd_tbl_t *cp;
4c6edc288   Eugeniu Rosca   cmd: adtimg: Rena...
216
  	cp = find_cmd_tbl(argv[1], cmd_adtimg_sub, ARRAY_SIZE(cmd_adtimg_sub));
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
217

4c6edc288   Eugeniu Rosca   cmd: adtimg: Rena...
218
  	/* Strip off leading 'adtimg' command argument */
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
219
220
221
222
223
  	argc--;
  	argv++;
  
  	if (!cp || argc > cp->maxargs)
  		return CMD_RET_USAGE;
80a48dd47   Boris Brezillon   common: command: ...
224
  	if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
225
226
227
228
229
230
  		return CMD_RET_SUCCESS;
  
  	return cp->cmd(cmdtp, flag, argc, argv);
  }
  
  U_BOOT_CMD(
4c6edc288   Eugeniu Rosca   cmd: adtimg: Rena...
231
  	adtimg, CONFIG_SYS_MAXARGS, 0, do_adtimg,
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
232
  	"manipulate dtb/dtbo Android image",
4f731c795   Eugeniu Rosca   cmd: adtimg: Refa...
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
  	"addr <addr> - Set image location to <addr>
  "
  	"adtimg dump        - Print out image contents
  "
  	"adtimg get dt --index=<index> [avar [svar]]         - Get DT address/size by index
  "
  	"
  "
  	"Legend:
  "
  	"  - <addr>: DTB/DTBO image address (hex) in RAM
  "
  	"  - <index>: index (hex/dec) of desired DT in the image
  "
  	"  - <avar>: variable name to contain DT address (hex)
  "
  	"  - <svar>: variable name to contain DT size (hex)"
d03e76af5   Sam Protsenko   cmd: Add dtimg co...
250
  );