Merge tag 'u-boot-atmel-2019.07-b' of git://git.denx.de/u-boot-atmel
[oweals/u-boot.git] / drivers / fastboot / fb_getvar.c
1 // 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
14 static void getvar_version(char *var_parameter, char *response);
15 static void getvar_bootloader_version(char *var_parameter, char *response);
16 static void getvar_downloadsize(char *var_parameter, char *response);
17 static void getvar_serialno(char *var_parameter, char *response);
18 static void getvar_version_baseband(char *var_parameter, char *response);
19 static void getvar_product(char *var_parameter, char *response);
20 static void getvar_platform(char *var_parameter, char *response);
21 static void getvar_current_slot(char *var_parameter, char *response);
22 static void getvar_slot_suffixes(char *var_parameter, char *response);
23 static void getvar_has_slot(char *var_parameter, char *response);
24 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
25 static void getvar_partition_type(char *part_name, char *response);
26 #endif
27 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
28 static void getvar_partition_size(char *part_name, char *response);
29 #endif
30
31 static 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         }, {
60                 .variable = "platform",
61                 .dispatch = getvar_platform
62         }, {
63                 .variable = "current-slot",
64                 .dispatch = getvar_current_slot
65         }, {
66                 .variable = "slot-suffixes",
67                 .dispatch = getvar_slot_suffixes
68         }, {
69                 .variable = "has-slot",
70                 .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
84 static void getvar_version(char *var_parameter, char *response)
85 {
86         fastboot_okay(FASTBOOT_VERSION, response);
87 }
88
89 static void getvar_bootloader_version(char *var_parameter, char *response)
90 {
91         fastboot_okay(U_BOOT_VERSION, response);
92 }
93
94 static void getvar_downloadsize(char *var_parameter, char *response)
95 {
96         fastboot_response("OKAY", response, "0x%08x", fastboot_buf_size);
97 }
98
99 static void getvar_serialno(char *var_parameter, char *response)
100 {
101         const char *tmp = env_get("serial#");
102
103         if (tmp)
104                 fastboot_okay(tmp, response);
105         else
106                 fastboot_fail("Value not set", response);
107 }
108
109 static void getvar_version_baseband(char *var_parameter, char *response)
110 {
111         fastboot_okay("N/A", response);
112 }
113
114 static void getvar_product(char *var_parameter, char *response)
115 {
116         const char *board = env_get("board");
117
118         if (board)
119                 fastboot_okay(board, response);
120         else
121                 fastboot_fail("Board not set", response);
122 }
123
124 static void getvar_platform(char *var_parameter, char *response)
125 {
126         const char *p = env_get("platform");
127
128         if (p)
129                 fastboot_okay(p, response);
130         else
131                 fastboot_fail("platform not set", response);
132 }
133
134 static void getvar_current_slot(char *var_parameter, char *response)
135 {
136         /* A/B not implemented, for now always return _a */
137         fastboot_okay("_a", response);
138 }
139
140 static void getvar_slot_suffixes(char *var_parameter, char *response)
141 {
142         fastboot_okay("_a,_b", response);
143 }
144
145 static void getvar_has_slot(char *part_name, char *response)
146 {
147         if (part_name && (!strcmp(part_name, "boot") ||
148                           !strcmp(part_name, "system")))
149                 fastboot_okay("yes", response);
150         else
151                 fastboot_okay("no", response);
152 }
153
154 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
155 static void getvar_partition_type(char *part_name, char *response)
156 {
157         int r;
158         struct blk_desc *dev_desc;
159         disk_partition_t part_info;
160
161         r = fastboot_mmc_get_part_info(part_name, &dev_desc, &part_info,
162                                        response);
163         if (r >= 0) {
164                 r = fs_set_blk_dev_with_part(dev_desc, r);
165                 if (r < 0)
166                         fastboot_fail("failed to set partition", response);
167                 else
168                         fastboot_okay(fs_get_type_name(), response);
169         }
170 }
171 #endif
172
173 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
174 static void getvar_partition_size(char *part_name, char *response)
175 {
176         int r;
177         size_t size;
178
179 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
180         struct blk_desc *dev_desc;
181         disk_partition_t part_info;
182
183         r = fastboot_mmc_get_part_info(part_name, &dev_desc, &part_info,
184                                        response);
185         if (r >= 0)
186                 size = part_info.size;
187 #endif
188 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND)
189         struct part_info *part_info;
190
191         r = fastboot_nand_get_part_info(part_name, &part_info, response);
192         if (r >= 0)
193                 size = part_info->size;
194 #endif
195         if (r >= 0)
196                 fastboot_response("OKAY", response, "0x%016zx", size);
197 }
198 #endif
199
200 /**
201  * fastboot_getvar() - Writes variable indicated by cmd_parameter to response.
202  *
203  * @cmd_parameter: Pointer to command parameter
204  * @response: Pointer to fastboot response buffer
205  *
206  * Look up cmd_parameter first as an environment variable of the form
207  * fastboot.<cmd_parameter>, if that exists return use its value to set
208  * response.
209  *
210  * Otherwise lookup the name of variable and execute the appropriate
211  * function to return the requested value.
212  */
213 void fastboot_getvar(char *cmd_parameter, char *response)
214 {
215         if (!cmd_parameter) {
216                 fastboot_fail("missing var", response);
217         } else {
218 #define FASTBOOT_ENV_PREFIX     "fastboot."
219                 int i;
220                 char *var_parameter = cmd_parameter;
221                 char envstr[FASTBOOT_RESPONSE_LEN];
222                 const char *s;
223
224                 snprintf(envstr, sizeof(envstr) - 1,
225                          FASTBOOT_ENV_PREFIX "%s", cmd_parameter);
226                 s = env_get(envstr);
227                 if (s) {
228                         fastboot_response("OKAY", response, "%s", s);
229                         return;
230                 }
231
232                 strsep(&var_parameter, ":");
233                 for (i = 0; i < ARRAY_SIZE(getvar_dispatch); ++i) {
234                         if (!strcmp(getvar_dispatch[i].variable,
235                                     cmd_parameter)) {
236                                 getvar_dispatch[i].dispatch(var_parameter,
237                                                             response);
238                                 return;
239                         }
240                 }
241                 pr_warn("WARNING: unknown variable: %s\n", cmd_parameter);
242                 fastboot_fail("Variable not implemented", response);
243         }
244 }