doc: board: ti: Move documentation from README to .rst
[platform/kernel/u-boot.git] / drivers / fastboot / fb_command.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 <command.h>
8 #include <env.h>
9 #include <fastboot.h>
10 #include <fastboot-internal.h>
11 #include <fb_mmc.h>
12 #include <fb_nand.h>
13 #include <part.h>
14 #include <stdlib.h>
15
16 /**
17  * image_size - final fastboot image size
18  */
19 static u32 image_size;
20
21 /**
22  * fastboot_bytes_received - number of bytes received in the current download
23  */
24 static u32 fastboot_bytes_received;
25
26 /**
27  * fastboot_bytes_expected - number of bytes expected in the current download
28  */
29 static u32 fastboot_bytes_expected;
30
31 static void okay(char *, char *);
32 static void getvar(char *, char *);
33 static void download(char *, char *);
34 static void flash(char *, char *);
35 static void erase(char *, char *);
36 static void reboot_bootloader(char *, char *);
37 static void reboot_fastbootd(char *, char *);
38 static void reboot_recovery(char *, char *);
39 static void oem_format(char *, char *);
40 static void oem_partconf(char *, char *);
41 static void oem_bootbus(char *, char *);
42 static void run_ucmd(char *, char *);
43 static void run_acmd(char *, char *);
44
45 static const struct {
46         const char *command;
47         void (*dispatch)(char *cmd_parameter, char *response);
48 } commands[FASTBOOT_COMMAND_COUNT] = {
49         [FASTBOOT_COMMAND_GETVAR] = {
50                 .command = "getvar",
51                 .dispatch = getvar
52         },
53         [FASTBOOT_COMMAND_DOWNLOAD] = {
54                 .command = "download",
55                 .dispatch = download
56         },
57         [FASTBOOT_COMMAND_FLASH] =  {
58                 .command = "flash",
59                 .dispatch = CONFIG_IS_ENABLED(FASTBOOT_FLASH, (flash), (NULL))
60         },
61         [FASTBOOT_COMMAND_ERASE] =  {
62                 .command = "erase",
63                 .dispatch = CONFIG_IS_ENABLED(FASTBOOT_FLASH, (erase), (NULL))
64         },
65         [FASTBOOT_COMMAND_BOOT] =  {
66                 .command = "boot",
67                 .dispatch = okay
68         },
69         [FASTBOOT_COMMAND_CONTINUE] =  {
70                 .command = "continue",
71                 .dispatch = okay
72         },
73         [FASTBOOT_COMMAND_REBOOT] =  {
74                 .command = "reboot",
75                 .dispatch = okay
76         },
77         [FASTBOOT_COMMAND_REBOOT_BOOTLOADER] =  {
78                 .command = "reboot-bootloader",
79                 .dispatch = reboot_bootloader
80         },
81         [FASTBOOT_COMMAND_REBOOT_FASTBOOTD] =  {
82                 .command = "reboot-fastboot",
83                 .dispatch = reboot_fastbootd
84         },
85         [FASTBOOT_COMMAND_REBOOT_RECOVERY] =  {
86                 .command = "reboot-recovery",
87                 .dispatch = reboot_recovery
88         },
89         [FASTBOOT_COMMAND_SET_ACTIVE] =  {
90                 .command = "set_active",
91                 .dispatch = okay
92         },
93         [FASTBOOT_COMMAND_OEM_FORMAT] = {
94                 .command = "oem format",
95                 .dispatch = CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT, (oem_format), (NULL))
96         },
97         [FASTBOOT_COMMAND_OEM_PARTCONF] = {
98                 .command = "oem partconf",
99                 .dispatch = CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_PARTCONF, (oem_partconf), (NULL))
100         },
101         [FASTBOOT_COMMAND_OEM_BOOTBUS] = {
102                 .command = "oem bootbus",
103                 .dispatch = CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_BOOTBUS, (oem_bootbus), (NULL))
104         },
105         [FASTBOOT_COMMAND_OEM_RUN] = {
106                 .command = "oem run",
107                 .dispatch = CONFIG_IS_ENABLED(FASTBOOT_OEM_RUN, (run_ucmd), (NULL))
108         },
109         [FASTBOOT_COMMAND_UCMD] = {
110                 .command = "UCmd",
111                 .dispatch = CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT, (run_ucmd), (NULL))
112         },
113         [FASTBOOT_COMMAND_ACMD] = {
114                 .command = "ACmd",
115                 .dispatch = CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT, (run_acmd), (NULL))
116         },
117 };
118
119 /**
120  * fastboot_handle_command - Handle fastboot command
121  *
122  * @cmd_string: Pointer to command string
123  * @response: Pointer to fastboot response buffer
124  *
125  * Return: Executed command, or -1 if not recognized
126  */
127 int fastboot_handle_command(char *cmd_string, char *response)
128 {
129         int i;
130         char *cmd_parameter;
131
132         cmd_parameter = cmd_string;
133         strsep(&cmd_parameter, ":");
134
135         for (i = 0; i < FASTBOOT_COMMAND_COUNT; i++) {
136                 if (!strcmp(commands[i].command, cmd_string)) {
137                         if (commands[i].dispatch) {
138                                 commands[i].dispatch(cmd_parameter,
139                                                         response);
140                                 return i;
141                         } else {
142                                 pr_err("command %s not supported.\n", cmd_string);
143                                 fastboot_fail("Unsupported command", response);
144                                 return -1;
145                         }
146                 }
147         }
148
149         pr_err("command %s not recognized.\n", cmd_string);
150         fastboot_fail("unrecognized command", response);
151         return -1;
152 }
153
154 /**
155  * okay() - Send bare OKAY response
156  *
157  * @cmd_parameter: Pointer to command parameter
158  * @response: Pointer to fastboot response buffer
159  *
160  * Send a bare OKAY fastboot response. This is used where the command is
161  * valid, but all the work is done after the response has been sent (e.g.
162  * boot, reboot etc.)
163  */
164 static void okay(char *cmd_parameter, char *response)
165 {
166         fastboot_okay(NULL, response);
167 }
168
169 /**
170  * getvar() - Read a config/version variable
171  *
172  * @cmd_parameter: Pointer to command parameter
173  * @response: Pointer to fastboot response buffer
174  */
175 static void getvar(char *cmd_parameter, char *response)
176 {
177         fastboot_getvar(cmd_parameter, response);
178 }
179
180 /**
181  * fastboot_download() - Start a download transfer from the client
182  *
183  * @cmd_parameter: Pointer to command parameter
184  * @response: Pointer to fastboot response buffer
185  */
186 static void download(char *cmd_parameter, char *response)
187 {
188         char *tmp;
189
190         if (!cmd_parameter) {
191                 fastboot_fail("Expected command parameter", response);
192                 return;
193         }
194         fastboot_bytes_received = 0;
195         fastboot_bytes_expected = hextoul(cmd_parameter, &tmp);
196         if (fastboot_bytes_expected == 0) {
197                 fastboot_fail("Expected nonzero image size", response);
198                 return;
199         }
200         /*
201          * Nothing to download yet. Response is of the form:
202          * [DATA|FAIL]$cmd_parameter
203          *
204          * where cmd_parameter is an 8 digit hexadecimal number
205          */
206         if (fastboot_bytes_expected > fastboot_buf_size) {
207                 fastboot_fail(cmd_parameter, response);
208         } else {
209                 printf("Starting download of %d bytes\n",
210                        fastboot_bytes_expected);
211                 fastboot_response("DATA", response, "%s", cmd_parameter);
212         }
213 }
214
215 /**
216  * fastboot_data_remaining() - return bytes remaining in current transfer
217  *
218  * Return: Number of bytes left in the current download
219  */
220 u32 fastboot_data_remaining(void)
221 {
222         return fastboot_bytes_expected - fastboot_bytes_received;
223 }
224
225 /**
226  * fastboot_data_download() - Copy image data to fastboot_buf_addr.
227  *
228  * @fastboot_data: Pointer to received fastboot data
229  * @fastboot_data_len: Length of received fastboot data
230  * @response: Pointer to fastboot response buffer
231  *
232  * Copies image data from fastboot_data to fastboot_buf_addr. Writes to
233  * response. fastboot_bytes_received is updated to indicate the number
234  * of bytes that have been transferred.
235  *
236  * On completion sets image_size and ${filesize} to the total size of the
237  * downloaded image.
238  */
239 void fastboot_data_download(const void *fastboot_data,
240                             unsigned int fastboot_data_len,
241                             char *response)
242 {
243 #define BYTES_PER_DOT   0x20000
244         u32 pre_dot_num, now_dot_num;
245
246         if (fastboot_data_len == 0 ||
247             (fastboot_bytes_received + fastboot_data_len) >
248             fastboot_bytes_expected) {
249                 fastboot_fail("Received invalid data length",
250                               response);
251                 return;
252         }
253         /* Download data to fastboot_buf_addr */
254         memcpy(fastboot_buf_addr + fastboot_bytes_received,
255                fastboot_data, fastboot_data_len);
256
257         pre_dot_num = fastboot_bytes_received / BYTES_PER_DOT;
258         fastboot_bytes_received += fastboot_data_len;
259         now_dot_num = fastboot_bytes_received / BYTES_PER_DOT;
260
261         if (pre_dot_num != now_dot_num) {
262                 putc('.');
263                 if (!(now_dot_num % 74))
264                         putc('\n');
265         }
266         *response = '\0';
267 }
268
269 /**
270  * fastboot_data_complete() - Mark current transfer complete
271  *
272  * @response: Pointer to fastboot response buffer
273  *
274  * Set image_size and ${filesize} to the total size of the downloaded image.
275  */
276 void fastboot_data_complete(char *response)
277 {
278         /* Download complete. Respond with "OKAY" */
279         fastboot_okay(NULL, response);
280         printf("\ndownloading of %d bytes finished\n", fastboot_bytes_received);
281         image_size = fastboot_bytes_received;
282         env_set_hex("filesize", image_size);
283         fastboot_bytes_expected = 0;
284         fastboot_bytes_received = 0;
285 }
286
287 /**
288  * flash() - write the downloaded image to the indicated partition.
289  *
290  * @cmd_parameter: Pointer to partition name
291  * @response: Pointer to fastboot response buffer
292  *
293  * Writes the previously downloaded image to the partition indicated by
294  * cmd_parameter. Writes to response.
295  */
296 static void __maybe_unused flash(char *cmd_parameter, char *response)
297 {
298         if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC))
299                 fastboot_mmc_flash_write(cmd_parameter, fastboot_buf_addr,
300                                          image_size, response);
301
302         if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_NAND))
303                 fastboot_nand_flash_write(cmd_parameter, fastboot_buf_addr,
304                                           image_size, response);
305 }
306
307 /**
308  * erase() - erase the indicated partition.
309  *
310  * @cmd_parameter: Pointer to partition name
311  * @response: Pointer to fastboot response buffer
312  *
313  * Erases the partition indicated by cmd_parameter (clear to 0x00s). Writes
314  * to response.
315  */
316 static void __maybe_unused erase(char *cmd_parameter, char *response)
317 {
318         if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC))
319                 fastboot_mmc_erase(cmd_parameter, response);
320
321         if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_NAND))
322                 fastboot_nand_erase(cmd_parameter, response);
323 }
324
325 /**
326  * run_ucmd() - Execute the UCmd command
327  *
328  * @cmd_parameter: Pointer to command parameter
329  * @response: Pointer to fastboot response buffer
330  */
331 static void __maybe_unused run_ucmd(char *cmd_parameter, char *response)
332 {
333         if (!cmd_parameter) {
334                 pr_err("missing slot suffix\n");
335                 fastboot_fail("missing command", response);
336                 return;
337         }
338
339         if (run_command(cmd_parameter, 0))
340                 fastboot_fail("", response);
341         else
342                 fastboot_okay(NULL, response);
343 }
344
345 static char g_a_cmd_buff[64];
346
347 void fastboot_acmd_complete(void)
348 {
349         run_command(g_a_cmd_buff, 0);
350 }
351
352 /**
353  * run_acmd() - Execute the ACmd command
354  *
355  * @cmd_parameter: Pointer to command parameter
356  * @response: Pointer to fastboot response buffer
357  */
358 static void __maybe_unused run_acmd(char *cmd_parameter, char *response)
359 {
360         if (!cmd_parameter) {
361                 pr_err("missing slot suffix\n");
362                 fastboot_fail("missing command", response);
363                 return;
364         }
365
366         if (strlen(cmd_parameter) > sizeof(g_a_cmd_buff)) {
367                 pr_err("too long command\n");
368                 fastboot_fail("too long command", response);
369                 return;
370         }
371
372         strcpy(g_a_cmd_buff, cmd_parameter);
373         fastboot_okay(NULL, response);
374 }
375
376 /**
377  * reboot_bootloader() - Sets reboot bootloader flag.
378  *
379  * @cmd_parameter: Pointer to command parameter
380  * @response: Pointer to fastboot response buffer
381  */
382 static void reboot_bootloader(char *cmd_parameter, char *response)
383 {
384         if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_BOOTLOADER))
385                 fastboot_fail("Cannot set reboot flag", response);
386         else
387                 fastboot_okay(NULL, response);
388 }
389
390 /**
391  * reboot_fastbootd() - Sets reboot fastboot flag.
392  *
393  * @cmd_parameter: Pointer to command parameter
394  * @response: Pointer to fastboot response buffer
395  */
396 static void reboot_fastbootd(char *cmd_parameter, char *response)
397 {
398         if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_FASTBOOTD))
399                 fastboot_fail("Cannot set fastboot flag", response);
400         else
401                 fastboot_okay(NULL, response);
402 }
403
404 /**
405  * reboot_recovery() - Sets reboot recovery flag.
406  *
407  * @cmd_parameter: Pointer to command parameter
408  * @response: Pointer to fastboot response buffer
409  */
410 static void reboot_recovery(char *cmd_parameter, char *response)
411 {
412         if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_RECOVERY))
413                 fastboot_fail("Cannot set recovery flag", response);
414         else
415                 fastboot_okay(NULL, response);
416 }
417
418 /**
419  * oem_format() - Execute the OEM format command
420  *
421  * @cmd_parameter: Pointer to command parameter
422  * @response: Pointer to fastboot response buffer
423  */
424 static void __maybe_unused oem_format(char *cmd_parameter, char *response)
425 {
426         char cmdbuf[32];
427         const int mmc_dev = config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC,
428                                                CONFIG_FASTBOOT_FLASH_MMC_DEV, -1);
429
430         if (!env_get("partitions")) {
431                 fastboot_fail("partitions not set", response);
432         } else {
433                 sprintf(cmdbuf, "gpt write mmc %x $partitions", mmc_dev);
434                 if (run_command(cmdbuf, 0))
435                         fastboot_fail("", response);
436                 else
437                         fastboot_okay(NULL, response);
438         }
439 }
440
441 /**
442  * oem_partconf() - Execute the OEM partconf command
443  *
444  * @cmd_parameter: Pointer to command parameter
445  * @response: Pointer to fastboot response buffer
446  */
447 static void __maybe_unused oem_partconf(char *cmd_parameter, char *response)
448 {
449         char cmdbuf[32];
450         const int mmc_dev = config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC,
451                                                CONFIG_FASTBOOT_FLASH_MMC_DEV, -1);
452
453         if (!cmd_parameter) {
454                 fastboot_fail("Expected command parameter", response);
455                 return;
456         }
457
458         /* execute 'mmc partconfg' command with cmd_parameter arguments*/
459         snprintf(cmdbuf, sizeof(cmdbuf), "mmc partconf %x %s 0", mmc_dev, cmd_parameter);
460         printf("Execute: %s\n", cmdbuf);
461         if (run_command(cmdbuf, 0))
462                 fastboot_fail("Cannot set oem partconf", response);
463         else
464                 fastboot_okay(NULL, response);
465 }
466
467 /**
468  * oem_bootbus() - Execute the OEM bootbus command
469  *
470  * @cmd_parameter: Pointer to command parameter
471  * @response: Pointer to fastboot response buffer
472  */
473 static void __maybe_unused oem_bootbus(char *cmd_parameter, char *response)
474 {
475         char cmdbuf[32];
476         const int mmc_dev = config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC,
477                                                CONFIG_FASTBOOT_FLASH_MMC_DEV, -1);
478
479         if (!cmd_parameter) {
480                 fastboot_fail("Expected command parameter", response);
481                 return;
482         }
483
484         /* execute 'mmc bootbus' command with cmd_parameter arguments*/
485         snprintf(cmdbuf, sizeof(cmdbuf), "mmc bootbus %x %s", mmc_dev, cmd_parameter);
486         printf("Execute: %s\n", cmdbuf);
487         if (run_command(cmdbuf, 0))
488                 fastboot_fail("Cannot set oem bootbus", response);
489         else
490                 fastboot_okay(NULL, response);
491 }