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