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