blob: 63fd38ddee1325a3cb37f6244003a03bdfd41b0a [file] [log] [blame]
Alex Kiernanf73a7df2018-05-29 15:30:53 +00001// SPDX-License-Identifier: BSD-2-Clause
2/*
3 * Copyright (C) 2016 The Android Open Source Project
4 */
5
6#include <common.h>
7#include <fastboot.h>
8#include <fastboot-internal.h>
9#include <fb_mmc.h>
10#include <fb_nand.h>
11#include <fs.h>
12#include <version.h>
13
14static void getvar_version(char *var_parameter, char *response);
15static void getvar_bootloader_version(char *var_parameter, char *response);
16static void getvar_downloadsize(char *var_parameter, char *response);
17static void getvar_serialno(char *var_parameter, char *response);
18static void getvar_version_baseband(char *var_parameter, char *response);
19static void getvar_product(char *var_parameter, char *response);
Eugeniu Roscad73d9fb2019-04-09 21:11:40 +020020static void getvar_platform(char *var_parameter, char *response);
Alex Kiernanf73a7df2018-05-29 15:30:53 +000021static void getvar_current_slot(char *var_parameter, char *response);
22static void getvar_slot_suffixes(char *var_parameter, char *response);
23static void getvar_has_slot(char *var_parameter, char *response);
24#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
25static void getvar_partition_type(char *part_name, char *response);
26#endif
27#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
28static void getvar_partition_size(char *part_name, char *response);
29#endif
30
31static const struct {
32 const char *variable;
33 void (*dispatch)(char *var_parameter, char *response);
34} getvar_dispatch[] = {
35 {
36 .variable = "version",
37 .dispatch = getvar_version
38 }, {
39 .variable = "bootloader-version",
40 .dispatch = getvar_bootloader_version
41 }, {
42 .variable = "version-bootloader",
43 .dispatch = getvar_bootloader_version
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
59 }, {
Eugeniu Roscad73d9fb2019-04-09 21:11:40 +020060 .variable = "platform",
61 .dispatch = getvar_platform
62 }, {
Alex Kiernanf73a7df2018-05-29 15:30:53 +000063 .variable = "current-slot",
64 .dispatch = getvar_current_slot
65 }, {
66 .variable = "slot-suffixes",
67 .dispatch = getvar_slot_suffixes
68 }, {
Eugeniu Rosca4c829462019-03-26 17:46:14 +010069 .variable = "has-slot",
Alex Kiernanf73a7df2018-05-29 15:30:53 +000070 .dispatch = getvar_has_slot
71#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
72 }, {
73 .variable = "partition-type",
74 .dispatch = getvar_partition_type
75#endif
76#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
77 }, {
78 .variable = "partition-size",
79 .dispatch = getvar_partition_size
80#endif
81 }
82};
83
Sam Protsenkof23a87d2019-06-13 21:11:08 +030084#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
85/**
86 * Get partition number and size for any storage type.
87 *
88 * Can be used to check if partition with specified name exists.
89 *
90 * If error occurs, this function guarantees to fill @p response with fail
91 * string. @p response can be rewritten in caller, if needed.
92 *
93 * @param[in] part_name Info for which partition name to look for
94 * @param[in,out] response Pointer to fastboot response buffer
95 * @param[out] size If not NULL, will contain partition size (in blocks)
96 * @return Partition number or negative value on error
97 */
98static int getvar_get_part_info(const char *part_name, char *response,
99 size_t *size)
100{
101 int r;
102# if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
103 struct blk_desc *dev_desc;
104 disk_partition_t part_info;
105
106 r = fastboot_mmc_get_part_info(part_name, &dev_desc, &part_info,
107 response);
108 if (r >= 0 && size)
109 *size = part_info.size;
110# elif CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND)
111 struct part_info *part_info;
112
113 r = fastboot_nand_get_part_info(part_name, &part_info, response);
114 if (r >= 0 && size)
115 *size = part_info->size;
116# else
117 fastboot_fail("this storage is not supported in bootloader", response);
118 r = -ENODEV;
119# endif
120
121 return r;
122}
123#endif
124
Alex Kiernanf73a7df2018-05-29 15:30:53 +0000125static void getvar_version(char *var_parameter, char *response)
126{
127 fastboot_okay(FASTBOOT_VERSION, response);
128}
129
130static void getvar_bootloader_version(char *var_parameter, char *response)
131{
132 fastboot_okay(U_BOOT_VERSION, response);
133}
134
135static void getvar_downloadsize(char *var_parameter, char *response)
136{
137 fastboot_response("OKAY", response, "0x%08x", fastboot_buf_size);
138}
139
140static void getvar_serialno(char *var_parameter, char *response)
141{
142 const char *tmp = env_get("serial#");
143
144 if (tmp)
145 fastboot_okay(tmp, response);
146 else
147 fastboot_fail("Value not set", response);
148}
149
150static void getvar_version_baseband(char *var_parameter, char *response)
151{
152 fastboot_okay("N/A", response);
153}
154
155static void getvar_product(char *var_parameter, char *response)
156{
157 const char *board = env_get("board");
158
159 if (board)
160 fastboot_okay(board, response);
161 else
162 fastboot_fail("Board not set", response);
163}
164
Eugeniu Roscad73d9fb2019-04-09 21:11:40 +0200165static void getvar_platform(char *var_parameter, char *response)
166{
167 const char *p = env_get("platform");
168
169 if (p)
170 fastboot_okay(p, response);
171 else
172 fastboot_fail("platform not set", response);
173}
174
Alex Kiernanf73a7df2018-05-29 15:30:53 +0000175static void getvar_current_slot(char *var_parameter, char *response)
176{
Sam Protsenko97a0c6f2019-06-13 00:49:45 +0300177 /* A/B not implemented, for now always return "a" */
178 fastboot_okay("a", response);
Alex Kiernanf73a7df2018-05-29 15:30:53 +0000179}
180
181static void getvar_slot_suffixes(char *var_parameter, char *response)
182{
Sam Protsenko97a0c6f2019-06-13 00:49:45 +0300183 fastboot_okay("a,b", response);
Alex Kiernanf73a7df2018-05-29 15:30:53 +0000184}
185
186static void getvar_has_slot(char *part_name, char *response)
187{
188 if (part_name && (!strcmp(part_name, "boot") ||
189 !strcmp(part_name, "system")))
190 fastboot_okay("yes", response);
191 else
192 fastboot_okay("no", response);
193}
194
195#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
196static void getvar_partition_type(char *part_name, char *response)
197{
198 int r;
199 struct blk_desc *dev_desc;
200 disk_partition_t part_info;
201
202 r = fastboot_mmc_get_part_info(part_name, &dev_desc, &part_info,
203 response);
204 if (r >= 0) {
205 r = fs_set_blk_dev_with_part(dev_desc, r);
206 if (r < 0)
207 fastboot_fail("failed to set partition", response);
208 else
209 fastboot_okay(fs_get_type_name(), response);
210 }
211}
212#endif
213
214#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
215static void getvar_partition_size(char *part_name, char *response)
216{
217 int r;
218 size_t size;
219
Sam Protsenkof23a87d2019-06-13 21:11:08 +0300220 r = getvar_get_part_info(part_name, response, &size);
Alex Kiernanf73a7df2018-05-29 15:30:53 +0000221 if (r >= 0)
222 fastboot_response("OKAY", response, "0x%016zx", size);
223}
224#endif
225
226/**
227 * fastboot_getvar() - Writes variable indicated by cmd_parameter to response.
228 *
229 * @cmd_parameter: Pointer to command parameter
230 * @response: Pointer to fastboot response buffer
231 *
232 * Look up cmd_parameter first as an environment variable of the form
233 * fastboot.<cmd_parameter>, if that exists return use its value to set
234 * response.
235 *
236 * Otherwise lookup the name of variable and execute the appropriate
237 * function to return the requested value.
238 */
239void fastboot_getvar(char *cmd_parameter, char *response)
240{
241 if (!cmd_parameter) {
242 fastboot_fail("missing var", response);
243 } else {
244#define FASTBOOT_ENV_PREFIX "fastboot."
245 int i;
246 char *var_parameter = cmd_parameter;
247 char envstr[FASTBOOT_RESPONSE_LEN];
248 const char *s;
249
250 snprintf(envstr, sizeof(envstr) - 1,
251 FASTBOOT_ENV_PREFIX "%s", cmd_parameter);
252 s = env_get(envstr);
253 if (s) {
254 fastboot_response("OKAY", response, "%s", s);
255 return;
256 }
257
258 strsep(&var_parameter, ":");
259 for (i = 0; i < ARRAY_SIZE(getvar_dispatch); ++i) {
260 if (!strcmp(getvar_dispatch[i].variable,
261 cmd_parameter)) {
262 getvar_dispatch[i].dispatch(var_parameter,
263 response);
264 return;
265 }
266 }
267 pr_warn("WARNING: unknown variable: %s\n", cmd_parameter);
268 fastboot_fail("Variable not implemented", response);
269 }
270}