]>
Commit | Line | Data |
---|---|---|
f73a7df9 AK |
1 | // SPDX-License-Identifier: BSD-2-Clause |
2 | /* | |
3 | * Copyright (C) 2016 The Android Open Source Project | |
4 | */ | |
5 | ||
6 | #include <common.h> | |
7b51b576 | 7 | #include <env.h> |
f73a7df9 AK |
8 | #include <fastboot.h> |
9 | #include <fastboot-internal.h> | |
10 | #include <fb_mmc.h> | |
11 | #include <fb_nand.h> | |
12 | #include <fs.h> | |
13 | #include <version.h> | |
14 | ||
15 | static void getvar_version(char *var_parameter, char *response); | |
29a81142 | 16 | static void getvar_version_bootloader(char *var_parameter, char *response); |
f73a7df9 AK |
17 | static void getvar_downloadsize(char *var_parameter, char *response); |
18 | static void getvar_serialno(char *var_parameter, char *response); | |
19 | static void getvar_version_baseband(char *var_parameter, char *response); | |
20 | static void getvar_product(char *var_parameter, char *response); | |
d73d9fb7 | 21 | static void getvar_platform(char *var_parameter, char *response); |
f73a7df9 | 22 | static void getvar_current_slot(char *var_parameter, char *response); |
220f6551 | 23 | #if CONFIG_IS_ENABLED(FASTBOOT_FLASH) |
f73a7df9 | 24 | static void getvar_has_slot(char *var_parameter, char *response); |
220f6551 | 25 | #endif |
f73a7df9 AK |
26 | #if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC) |
27 | static void getvar_partition_type(char *part_name, char *response); | |
28 | #endif | |
29 | #if CONFIG_IS_ENABLED(FASTBOOT_FLASH) | |
30 | static void getvar_partition_size(char *part_name, char *response); | |
31 | #endif | |
139db354 | 32 | static void getvar_is_userspace(char *var_parameter, char *response); |
f73a7df9 AK |
33 | |
34 | static const struct { | |
35 | const char *variable; | |
36 | void (*dispatch)(char *var_parameter, char *response); | |
37 | } getvar_dispatch[] = { | |
38 | { | |
39 | .variable = "version", | |
40 | .dispatch = getvar_version | |
f73a7df9 AK |
41 | }, { |
42 | .variable = "version-bootloader", | |
29a81142 | 43 | .dispatch = getvar_version_bootloader |
f73a7df9 AK |
44 | }, { |
45 | .variable = "downloadsize", | |
46 | .dispatch = getvar_downloadsize | |
47 | }, { | |
48 | .variable = "max-download-size", | |
49 | .dispatch = getvar_downloadsize | |
50 | }, { | |
51 | .variable = "serialno", | |
52 | .dispatch = getvar_serialno | |
53 | }, { | |
54 | .variable = "version-baseband", | |
55 | .dispatch = getvar_version_baseband | |
56 | }, { | |
57 | .variable = "product", | |
58 | .dispatch = getvar_product | |
d73d9fb7 ER |
59 | }, { |
60 | .variable = "platform", | |
61 | .dispatch = getvar_platform | |
f73a7df9 AK |
62 | }, { |
63 | .variable = "current-slot", | |
64 | .dispatch = getvar_current_slot | |
220f6551 | 65 | #if CONFIG_IS_ENABLED(FASTBOOT_FLASH) |
f73a7df9 | 66 | }, { |
4c829466 | 67 | .variable = "has-slot", |
f73a7df9 | 68 | .dispatch = getvar_has_slot |
220f6551 | 69 | #endif |
f73a7df9 AK |
70 | #if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC) |
71 | }, { | |
72 | .variable = "partition-type", | |
73 | .dispatch = getvar_partition_type | |
74 | #endif | |
75 | #if CONFIG_IS_ENABLED(FASTBOOT_FLASH) | |
76 | }, { | |
77 | .variable = "partition-size", | |
78 | .dispatch = getvar_partition_size | |
79 | #endif | |
139db354 SP |
80 | }, { |
81 | .variable = "is-userspace", | |
82 | .dispatch = getvar_is_userspace | |
f73a7df9 AK |
83 | } |
84 | }; | |
85 | ||
f23a87d5 SP |
86 | #if CONFIG_IS_ENABLED(FASTBOOT_FLASH) |
87 | /** | |
88 | * Get partition number and size for any storage type. | |
89 | * | |
90 | * Can be used to check if partition with specified name exists. | |
91 | * | |
92 | * If error occurs, this function guarantees to fill @p response with fail | |
93 | * string. @p response can be rewritten in caller, if needed. | |
94 | * | |
95 | * @param[in] part_name Info for which partition name to look for | |
96 | * @param[in,out] response Pointer to fastboot response buffer | |
97 | * @param[out] size If not NULL, will contain partition size (in blocks) | |
98 | * @return Partition number or negative value on error | |
99 | */ | |
100 | static int getvar_get_part_info(const char *part_name, char *response, | |
101 | size_t *size) | |
102 | { | |
103 | int r; | |
104 | # if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC) | |
105 | struct blk_desc *dev_desc; | |
106 | disk_partition_t part_info; | |
107 | ||
108 | r = fastboot_mmc_get_part_info(part_name, &dev_desc, &part_info, | |
109 | response); | |
110 | if (r >= 0 && size) | |
111 | *size = part_info.size; | |
112 | # elif CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND) | |
113 | struct part_info *part_info; | |
114 | ||
115 | r = fastboot_nand_get_part_info(part_name, &part_info, response); | |
116 | if (r >= 0 && size) | |
117 | *size = part_info->size; | |
118 | # else | |
119 | fastboot_fail("this storage is not supported in bootloader", response); | |
120 | r = -ENODEV; | |
121 | # endif | |
122 | ||
123 | return r; | |
124 | } | |
125 | #endif | |
126 | ||
f73a7df9 AK |
127 | static void getvar_version(char *var_parameter, char *response) |
128 | { | |
129 | fastboot_okay(FASTBOOT_VERSION, response); | |
130 | } | |
131 | ||
29a81142 | 132 | static void getvar_version_bootloader(char *var_parameter, char *response) |
f73a7df9 AK |
133 | { |
134 | fastboot_okay(U_BOOT_VERSION, response); | |
135 | } | |
136 | ||
137 | static void getvar_downloadsize(char *var_parameter, char *response) | |
138 | { | |
139 | fastboot_response("OKAY", response, "0x%08x", fastboot_buf_size); | |
140 | } | |
141 | ||
142 | static void getvar_serialno(char *var_parameter, char *response) | |
143 | { | |
144 | const char *tmp = env_get("serial#"); | |
145 | ||
146 | if (tmp) | |
147 | fastboot_okay(tmp, response); | |
148 | else | |
149 | fastboot_fail("Value not set", response); | |
150 | } | |
151 | ||
152 | static void getvar_version_baseband(char *var_parameter, char *response) | |
153 | { | |
154 | fastboot_okay("N/A", response); | |
155 | } | |
156 | ||
157 | static void getvar_product(char *var_parameter, char *response) | |
158 | { | |
159 | const char *board = env_get("board"); | |
160 | ||
161 | if (board) | |
162 | fastboot_okay(board, response); | |
163 | else | |
164 | fastboot_fail("Board not set", response); | |
165 | } | |
166 | ||
d73d9fb7 ER |
167 | static void getvar_platform(char *var_parameter, char *response) |
168 | { | |
169 | const char *p = env_get("platform"); | |
170 | ||
171 | if (p) | |
172 | fastboot_okay(p, response); | |
173 | else | |
174 | fastboot_fail("platform not set", response); | |
175 | } | |
176 | ||
f73a7df9 AK |
177 | static void getvar_current_slot(char *var_parameter, char *response) |
178 | { | |
97a0c6ff SP |
179 | /* A/B not implemented, for now always return "a" */ |
180 | fastboot_okay("a", response); | |
f73a7df9 AK |
181 | } |
182 | ||
220f6551 | 183 | #if CONFIG_IS_ENABLED(FASTBOOT_FLASH) |
f73a7df9 AK |
184 | static void getvar_has_slot(char *part_name, char *response) |
185 | { | |
220f6551 IO |
186 | char part_name_wslot[PART_NAME_LEN]; |
187 | size_t len; | |
188 | int r; | |
189 | ||
190 | if (!part_name || part_name[0] == '\0') | |
191 | goto fail; | |
192 | ||
193 | /* part_name_wslot = part_name + "_a" */ | |
194 | len = strlcpy(part_name_wslot, part_name, PART_NAME_LEN - 3); | |
195 | if (len > PART_NAME_LEN - 3) | |
196 | goto fail; | |
197 | strcat(part_name_wslot, "_a"); | |
198 | ||
199 | r = getvar_get_part_info(part_name_wslot, response, NULL); | |
200 | if (r >= 0) { | |
201 | fastboot_okay("yes", response); /* part exists and slotted */ | |
202 | return; | |
203 | } | |
204 | ||
205 | r = getvar_get_part_info(part_name, response, NULL); | |
206 | if (r >= 0) | |
207 | fastboot_okay("no", response); /* part exists but not slotted */ | |
208 | ||
209 | /* At this point response is filled with okay or fail string */ | |
210 | return; | |
211 | ||
212 | fail: | |
213 | fastboot_fail("invalid partition name", response); | |
f73a7df9 | 214 | } |
220f6551 | 215 | #endif |
f73a7df9 AK |
216 | |
217 | #if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC) | |
218 | static void getvar_partition_type(char *part_name, char *response) | |
219 | { | |
220 | int r; | |
221 | struct blk_desc *dev_desc; | |
222 | disk_partition_t part_info; | |
223 | ||
224 | r = fastboot_mmc_get_part_info(part_name, &dev_desc, &part_info, | |
225 | response); | |
226 | if (r >= 0) { | |
227 | r = fs_set_blk_dev_with_part(dev_desc, r); | |
228 | if (r < 0) | |
229 | fastboot_fail("failed to set partition", response); | |
230 | else | |
231 | fastboot_okay(fs_get_type_name(), response); | |
232 | } | |
233 | } | |
234 | #endif | |
235 | ||
236 | #if CONFIG_IS_ENABLED(FASTBOOT_FLASH) | |
237 | static void getvar_partition_size(char *part_name, char *response) | |
238 | { | |
239 | int r; | |
240 | size_t size; | |
241 | ||
f23a87d5 | 242 | r = getvar_get_part_info(part_name, response, &size); |
f73a7df9 AK |
243 | if (r >= 0) |
244 | fastboot_response("OKAY", response, "0x%016zx", size); | |
245 | } | |
246 | #endif | |
247 | ||
139db354 SP |
248 | static void getvar_is_userspace(char *var_parameter, char *response) |
249 | { | |
250 | fastboot_okay("no", response); | |
251 | } | |
252 | ||
f73a7df9 AK |
253 | /** |
254 | * fastboot_getvar() - Writes variable indicated by cmd_parameter to response. | |
255 | * | |
256 | * @cmd_parameter: Pointer to command parameter | |
257 | * @response: Pointer to fastboot response buffer | |
258 | * | |
259 | * Look up cmd_parameter first as an environment variable of the form | |
260 | * fastboot.<cmd_parameter>, if that exists return use its value to set | |
261 | * response. | |
262 | * | |
263 | * Otherwise lookup the name of variable and execute the appropriate | |
264 | * function to return the requested value. | |
265 | */ | |
266 | void fastboot_getvar(char *cmd_parameter, char *response) | |
267 | { | |
268 | if (!cmd_parameter) { | |
269 | fastboot_fail("missing var", response); | |
270 | } else { | |
271 | #define FASTBOOT_ENV_PREFIX "fastboot." | |
272 | int i; | |
273 | char *var_parameter = cmd_parameter; | |
274 | char envstr[FASTBOOT_RESPONSE_LEN]; | |
275 | const char *s; | |
276 | ||
277 | snprintf(envstr, sizeof(envstr) - 1, | |
278 | FASTBOOT_ENV_PREFIX "%s", cmd_parameter); | |
279 | s = env_get(envstr); | |
280 | if (s) { | |
281 | fastboot_response("OKAY", response, "%s", s); | |
282 | return; | |
283 | } | |
284 | ||
285 | strsep(&var_parameter, ":"); | |
286 | for (i = 0; i < ARRAY_SIZE(getvar_dispatch); ++i) { | |
287 | if (!strcmp(getvar_dispatch[i].variable, | |
288 | cmd_parameter)) { | |
289 | getvar_dispatch[i].dispatch(var_parameter, | |
290 | response); | |
291 | return; | |
292 | } | |
293 | } | |
294 | pr_warn("WARNING: unknown variable: %s\n", cmd_parameter); | |
295 | fastboot_fail("Variable not implemented", response); | |
296 | } | |
297 | } |