]> git.ipfire.org Git - thirdparty/u-boot.git/blame - drivers/fastboot/fb_getvar.c
Revert "Merge patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet""
[thirdparty/u-boot.git] / drivers / fastboot / fb_getvar.c
CommitLineData
f73a7df9
AK
1// SPDX-License-Identifier: BSD-2-Clause
2/*
3 * Copyright (C) 2016 The Android Open Source Project
4 */
5
d678a59d 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>
e6f6f9e6 13#include <part.h>
f73a7df9 14#include <version.h>
1e94b46f 15#include <linux/printk.h>
f73a7df9
AK
16
17static void getvar_version(char *var_parameter, char *response);
29a81142 18static void getvar_version_bootloader(char *var_parameter, char *response);
f73a7df9
AK
19static void getvar_downloadsize(char *var_parameter, char *response);
20static void getvar_serialno(char *var_parameter, char *response);
21static void getvar_version_baseband(char *var_parameter, char *response);
22static void getvar_product(char *var_parameter, char *response);
d73d9fb7 23static void getvar_platform(char *var_parameter, char *response);
f73a7df9 24static void getvar_current_slot(char *var_parameter, char *response);
f73a7df9 25static void getvar_has_slot(char *var_parameter, char *response);
f73a7df9 26static void getvar_partition_type(char *part_name, char *response);
f73a7df9 27static void getvar_partition_size(char *part_name, char *response);
139db354 28static void getvar_is_userspace(char *var_parameter, char *response);
f73a7df9
AK
29
30static const struct {
31 const char *variable;
475aa9aa 32 bool list;
f73a7df9
AK
33 void (*dispatch)(char *var_parameter, char *response);
34} getvar_dispatch[] = {
35 {
36 .variable = "version",
475aa9aa
IA
37 .dispatch = getvar_version,
38 .list = true,
f73a7df9
AK
39 }, {
40 .variable = "version-bootloader",
475aa9aa
IA
41 .dispatch = getvar_version_bootloader,
42 .list = true
f73a7df9
AK
43 }, {
44 .variable = "downloadsize",
475aa9aa
IA
45 .dispatch = getvar_downloadsize,
46 .list = true
f73a7df9
AK
47 }, {
48 .variable = "max-download-size",
475aa9aa
IA
49 .dispatch = getvar_downloadsize,
50 .list = true
f73a7df9
AK
51 }, {
52 .variable = "serialno",
475aa9aa
IA
53 .dispatch = getvar_serialno,
54 .list = true
f73a7df9
AK
55 }, {
56 .variable = "version-baseband",
475aa9aa
IA
57 .dispatch = getvar_version_baseband,
58 .list = true
f73a7df9
AK
59 }, {
60 .variable = "product",
475aa9aa
IA
61 .dispatch = getvar_product,
62 .list = true
d73d9fb7
ER
63 }, {
64 .variable = "platform",
475aa9aa
IA
65 .dispatch = getvar_platform,
66 .list = true
f73a7df9
AK
67 }, {
68 .variable = "current-slot",
475aa9aa
IA
69 .dispatch = getvar_current_slot,
70 .list = true
64d6bfb6 71#if IS_ENABLED(CONFIG_FASTBOOT_FLASH)
f73a7df9 72 }, {
4c829466 73 .variable = "has-slot",
475aa9aa
IA
74 .dispatch = getvar_has_slot,
75 .list = false
220f6551 76#endif
7cb10e51 77#if IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC)
f73a7df9
AK
78 }, {
79 .variable = "partition-type",
475aa9aa
IA
80 .dispatch = getvar_partition_type,
81 .list = false
f73a7df9 82#endif
64d6bfb6 83#if IS_ENABLED(CONFIG_FASTBOOT_FLASH)
f73a7df9
AK
84 }, {
85 .variable = "partition-size",
475aa9aa
IA
86 .dispatch = getvar_partition_size,
87 .list = false
f73a7df9 88#endif
139db354
SP
89 }, {
90 .variable = "is-userspace",
475aa9aa
IA
91 .dispatch = getvar_is_userspace,
92 .list = true
f73a7df9
AK
93 }
94};
95
f23a87d5
SP
96/**
97 * Get partition number and size for any storage type.
98 *
99 * Can be used to check if partition with specified name exists.
100 *
101 * If error occurs, this function guarantees to fill @p response with fail
102 * string. @p response can be rewritten in caller, if needed.
103 *
104 * @param[in] part_name Info for which partition name to look for
105 * @param[in,out] response Pointer to fastboot response buffer
293a6dfe 106 * @param[out] size If not NULL, will contain partition size
185f812c 107 * Return: Partition number or negative value on error
f23a87d5
SP
108 */
109static int getvar_get_part_info(const char *part_name, char *response,
110 size_t *size)
111{
112 int r;
f23a87d5 113 struct blk_desc *dev_desc;
d0379900 114 struct disk_partition disk_part;
f23a87d5
SP
115 struct part_info *part_info;
116
7cb10e51 117 if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC)) {
d0379900
PD
118 r = fastboot_mmc_get_part_info(part_name, &dev_desc, &disk_part,
119 response);
120 if (r >= 0 && size)
121 *size = disk_part.size * disk_part.blksz;
c6228edf 122 } else if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_NAND)) {
d0379900
PD
123 r = fastboot_nand_get_part_info(part_name, &part_info, response);
124 if (r >= 0 && size)
125 *size = part_info->size;
126 } else {
127 fastboot_fail("this storage is not supported in bootloader", response);
128 r = -ENODEV;
129 }
f23a87d5
SP
130
131 return r;
132}
f23a87d5 133
f73a7df9
AK
134static void getvar_version(char *var_parameter, char *response)
135{
136 fastboot_okay(FASTBOOT_VERSION, response);
137}
138
29a81142 139static void getvar_version_bootloader(char *var_parameter, char *response)
f73a7df9
AK
140{
141 fastboot_okay(U_BOOT_VERSION, response);
142}
143
144static void getvar_downloadsize(char *var_parameter, char *response)
145{
146 fastboot_response("OKAY", response, "0x%08x", fastboot_buf_size);
147}
148
149static void getvar_serialno(char *var_parameter, char *response)
150{
151 const char *tmp = env_get("serial#");
152
153 if (tmp)
154 fastboot_okay(tmp, response);
155 else
156 fastboot_fail("Value not set", response);
157}
158
159static void getvar_version_baseband(char *var_parameter, char *response)
160{
161 fastboot_okay("N/A", response);
162}
163
164static void getvar_product(char *var_parameter, char *response)
165{
166 const char *board = env_get("board");
167
168 if (board)
169 fastboot_okay(board, response);
170 else
171 fastboot_fail("Board not set", response);
172}
173
d73d9fb7
ER
174static void getvar_platform(char *var_parameter, char *response)
175{
176 const char *p = env_get("platform");
177
178 if (p)
179 fastboot_okay(p, response);
180 else
181 fastboot_fail("platform not set", response);
182}
183
f73a7df9
AK
184static void getvar_current_slot(char *var_parameter, char *response)
185{
97a0c6ff
SP
186 /* A/B not implemented, for now always return "a" */
187 fastboot_okay("a", response);
f73a7df9
AK
188}
189
d0379900 190static void __maybe_unused getvar_has_slot(char *part_name, char *response)
f73a7df9 191{
220f6551
IO
192 char part_name_wslot[PART_NAME_LEN];
193 size_t len;
194 int r;
195
196 if (!part_name || part_name[0] == '\0')
197 goto fail;
198
199 /* part_name_wslot = part_name + "_a" */
200 len = strlcpy(part_name_wslot, part_name, PART_NAME_LEN - 3);
61582872 201 if (len >= PART_NAME_LEN - 3)
220f6551
IO
202 goto fail;
203 strcat(part_name_wslot, "_a");
204
205 r = getvar_get_part_info(part_name_wslot, response, NULL);
206 if (r >= 0) {
207 fastboot_okay("yes", response); /* part exists and slotted */
208 return;
209 }
210
211 r = getvar_get_part_info(part_name, response, NULL);
212 if (r >= 0)
213 fastboot_okay("no", response); /* part exists but not slotted */
214
215 /* At this point response is filled with okay or fail string */
216 return;
217
218fail:
219 fastboot_fail("invalid partition name", response);
f73a7df9
AK
220}
221
d0379900 222static void __maybe_unused getvar_partition_type(char *part_name, char *response)
f73a7df9
AK
223{
224 int r;
225 struct blk_desc *dev_desc;
0528979f 226 struct disk_partition part_info;
f73a7df9
AK
227
228 r = fastboot_mmc_get_part_info(part_name, &dev_desc, &part_info,
229 response);
230 if (r >= 0) {
231 r = fs_set_blk_dev_with_part(dev_desc, r);
232 if (r < 0)
233 fastboot_fail("failed to set partition", response);
234 else
235 fastboot_okay(fs_get_type_name(), response);
236 }
237}
f73a7df9 238
d0379900 239static void __maybe_unused getvar_partition_size(char *part_name, char *response)
f73a7df9
AK
240{
241 int r;
242 size_t size;
243
f23a87d5 244 r = getvar_get_part_info(part_name, response, &size);
f73a7df9
AK
245 if (r >= 0)
246 fastboot_response("OKAY", response, "0x%016zx", size);
247}
f73a7df9 248
139db354
SP
249static void getvar_is_userspace(char *var_parameter, char *response)
250{
251 fastboot_okay("no", response);
252}
253
475aa9aa
IA
254static int current_all_dispatch;
255void fastboot_getvar_all(char *response)
256{
257 /*
258 * Find a dispatch getvar that can be listed and send
259 * it as INFO until we reach the end.
260 */
261 while (current_all_dispatch < ARRAY_SIZE(getvar_dispatch)) {
262 if (!getvar_dispatch[current_all_dispatch].list) {
263 current_all_dispatch++;
264 continue;
265 }
266
267 char envstr[FASTBOOT_RESPONSE_LEN] = { 0 };
268
269 getvar_dispatch[current_all_dispatch].dispatch(NULL, envstr);
270
271 char *envstr_start = envstr;
272
273 if (!strncmp("OKAY", envstr, 4) || !strncmp("FAIL", envstr, 4))
274 envstr_start += 4;
275
276 fastboot_response("INFO", response, "%s: %s",
277 getvar_dispatch[current_all_dispatch].variable,
278 envstr_start);
279
280 current_all_dispatch++;
281 return;
282 }
283
284 fastboot_response("OKAY", response, NULL);
285 current_all_dispatch = 0;
286}
287
f73a7df9
AK
288/**
289 * fastboot_getvar() - Writes variable indicated by cmd_parameter to response.
290 *
291 * @cmd_parameter: Pointer to command parameter
292 * @response: Pointer to fastboot response buffer
293 *
294 * Look up cmd_parameter first as an environment variable of the form
295 * fastboot.<cmd_parameter>, if that exists return use its value to set
296 * response.
297 *
298 * Otherwise lookup the name of variable and execute the appropriate
299 * function to return the requested value.
300 */
301void fastboot_getvar(char *cmd_parameter, char *response)
302{
303 if (!cmd_parameter) {
304 fastboot_fail("missing var", response);
475aa9aa
IA
305 } else if (!strncmp("all", cmd_parameter, 3) && strlen(cmd_parameter) == 3) {
306 current_all_dispatch = 0;
307 fastboot_response(FASTBOOT_MULTIRESPONSE_START, response, NULL);
f73a7df9
AK
308 } else {
309#define FASTBOOT_ENV_PREFIX "fastboot."
310 int i;
311 char *var_parameter = cmd_parameter;
312 char envstr[FASTBOOT_RESPONSE_LEN];
313 const char *s;
314
315 snprintf(envstr, sizeof(envstr) - 1,
316 FASTBOOT_ENV_PREFIX "%s", cmd_parameter);
317 s = env_get(envstr);
318 if (s) {
319 fastboot_response("OKAY", response, "%s", s);
320 return;
321 }
322
323 strsep(&var_parameter, ":");
324 for (i = 0; i < ARRAY_SIZE(getvar_dispatch); ++i) {
325 if (!strcmp(getvar_dispatch[i].variable,
326 cmd_parameter)) {
327 getvar_dispatch[i].dispatch(var_parameter,
328 response);
329 return;
330 }
331 }
332 pr_warn("WARNING: unknown variable: %s\n", cmd_parameter);
333 fastboot_fail("Variable not implemented", response);
334 }
335}