1 // SPDX-License-Identifier: BSD-2-Clause
3 * Copyright (C) 2016 The Android Open Source Project
10 #include <fastboot-internal.h>
17 * image_size - final fastboot image size
19 static u32 image_size
;
22 * fastboot_bytes_received - number of bytes received in the current download
24 static u32 fastboot_bytes_received
;
27 * fastboot_bytes_expected - number of bytes expected in the current download
29 static u32 fastboot_bytes_expected
;
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 *);
47 void (*dispatch
)(char *cmd_parameter
, char *response
);
48 } commands
[FASTBOOT_COMMAND_COUNT
] = {
49 [FASTBOOT_COMMAND_GETVAR
] = {
53 [FASTBOOT_COMMAND_DOWNLOAD
] = {
54 .command
= "download",
57 [FASTBOOT_COMMAND_FLASH
] = {
59 .dispatch
= CONFIG_IS_ENABLED(FASTBOOT_FLASH
, (flash
), (NULL
))
61 [FASTBOOT_COMMAND_ERASE
] = {
63 .dispatch
= CONFIG_IS_ENABLED(FASTBOOT_FLASH
, (erase
), (NULL
))
65 [FASTBOOT_COMMAND_BOOT
] = {
69 [FASTBOOT_COMMAND_CONTINUE
] = {
70 .command
= "continue",
73 [FASTBOOT_COMMAND_REBOOT
] = {
77 [FASTBOOT_COMMAND_REBOOT_BOOTLOADER
] = {
78 .command
= "reboot-bootloader",
79 .dispatch
= reboot_bootloader
81 [FASTBOOT_COMMAND_REBOOT_FASTBOOTD
] = {
82 .command
= "reboot-fastboot",
83 .dispatch
= reboot_fastbootd
85 [FASTBOOT_COMMAND_REBOOT_RECOVERY
] = {
86 .command
= "reboot-recovery",
87 .dispatch
= reboot_recovery
89 [FASTBOOT_COMMAND_SET_ACTIVE
] = {
90 .command
= "set_active",
93 [FASTBOOT_COMMAND_OEM_FORMAT
] = {
94 .command
= "oem format",
95 .dispatch
= CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT
, (oem_format
), (NULL
))
97 [FASTBOOT_COMMAND_OEM_PARTCONF
] = {
98 .command
= "oem partconf",
99 .dispatch
= CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_PARTCONF
, (oem_partconf
), (NULL
))
101 [FASTBOOT_COMMAND_OEM_BOOTBUS
] = {
102 .command
= "oem bootbus",
103 .dispatch
= CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_BOOTBUS
, (oem_bootbus
), (NULL
))
105 [FASTBOOT_COMMAND_OEM_RUN
] = {
106 .command
= "oem run",
107 .dispatch
= CONFIG_IS_ENABLED(FASTBOOT_OEM_RUN
, (run_ucmd
), (NULL
))
109 [FASTBOOT_COMMAND_UCMD
] = {
111 .dispatch
= CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT
, (run_ucmd
), (NULL
))
113 [FASTBOOT_COMMAND_ACMD
] = {
115 .dispatch
= CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT
, (run_acmd
), (NULL
))
120 * fastboot_handle_command - Handle fastboot command
122 * @cmd_string: Pointer to command string
123 * @response: Pointer to fastboot response buffer
125 * Return: Executed command, or -1 if not recognized
127 int fastboot_handle_command(char *cmd_string
, char *response
)
132 cmd_parameter
= cmd_string
;
133 strsep(&cmd_parameter
, ":");
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
,
142 pr_err("command %s not supported.\n", cmd_string
);
143 fastboot_fail("Unsupported command", response
);
149 pr_err("command %s not recognized.\n", cmd_string
);
150 fastboot_fail("unrecognized command", response
);
155 * okay() - Send bare OKAY response
157 * @cmd_parameter: Pointer to command parameter
158 * @response: Pointer to fastboot response buffer
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.
164 static void okay(char *cmd_parameter
, char *response
)
166 fastboot_okay(NULL
, response
);
170 * getvar() - Read a config/version variable
172 * @cmd_parameter: Pointer to command parameter
173 * @response: Pointer to fastboot response buffer
175 static void getvar(char *cmd_parameter
, char *response
)
177 fastboot_getvar(cmd_parameter
, response
);
181 * fastboot_download() - Start a download transfer from the client
183 * @cmd_parameter: Pointer to command parameter
184 * @response: Pointer to fastboot response buffer
186 static void download(char *cmd_parameter
, char *response
)
190 if (!cmd_parameter
) {
191 fastboot_fail("Expected command parameter", response
);
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
);
201 * Nothing to download yet. Response is of the form:
202 * [DATA|FAIL]$cmd_parameter
204 * where cmd_parameter is an 8 digit hexadecimal number
206 if (fastboot_bytes_expected
> fastboot_buf_size
) {
207 fastboot_fail(cmd_parameter
, response
);
209 printf("Starting download of %d bytes\n",
210 fastboot_bytes_expected
);
211 fastboot_response("DATA", response
, "%s", cmd_parameter
);
216 * fastboot_data_remaining() - return bytes remaining in current transfer
218 * Return: Number of bytes left in the current download
220 u32
fastboot_data_remaining(void)
222 return fastboot_bytes_expected
- fastboot_bytes_received
;
226 * fastboot_data_download() - Copy image data to fastboot_buf_addr.
228 * @fastboot_data: Pointer to received fastboot data
229 * @fastboot_data_len: Length of received fastboot data
230 * @response: Pointer to fastboot response buffer
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.
236 * On completion sets image_size and ${filesize} to the total size of the
239 void fastboot_data_download(const void *fastboot_data
,
240 unsigned int fastboot_data_len
,
243 #define BYTES_PER_DOT 0x20000
244 u32 pre_dot_num
, now_dot_num
;
246 if (fastboot_data_len
== 0 ||
247 (fastboot_bytes_received
+ fastboot_data_len
) >
248 fastboot_bytes_expected
) {
249 fastboot_fail("Received invalid data length",
253 /* Download data to fastboot_buf_addr */
254 memcpy(fastboot_buf_addr
+ fastboot_bytes_received
,
255 fastboot_data
, fastboot_data_len
);
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
;
261 if (pre_dot_num
!= now_dot_num
) {
263 if (!(now_dot_num
% 74))
270 * fastboot_data_complete() - Mark current transfer complete
272 * @response: Pointer to fastboot response buffer
274 * Set image_size and ${filesize} to the total size of the downloaded image.
276 void fastboot_data_complete(char *response
)
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;
288 * flash() - write the downloaded image to the indicated partition.
290 * @cmd_parameter: Pointer to partition name
291 * @response: Pointer to fastboot response buffer
293 * Writes the previously downloaded image to the partition indicated by
294 * cmd_parameter. Writes to response.
296 static void __maybe_unused
flash(char *cmd_parameter
, char *response
)
298 if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC
))
299 fastboot_mmc_flash_write(cmd_parameter
, fastboot_buf_addr
,
300 image_size
, response
);
302 if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_NAND
))
303 fastboot_nand_flash_write(cmd_parameter
, fastboot_buf_addr
,
304 image_size
, response
);
308 * erase() - erase the indicated partition.
310 * @cmd_parameter: Pointer to partition name
311 * @response: Pointer to fastboot response buffer
313 * Erases the partition indicated by cmd_parameter (clear to 0x00s). Writes
316 static void __maybe_unused
erase(char *cmd_parameter
, char *response
)
318 if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC
))
319 fastboot_mmc_erase(cmd_parameter
, response
);
321 if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_NAND
))
322 fastboot_nand_erase(cmd_parameter
, response
);
326 * run_ucmd() - Execute the UCmd command
328 * @cmd_parameter: Pointer to command parameter
329 * @response: Pointer to fastboot response buffer
331 static void __maybe_unused
run_ucmd(char *cmd_parameter
, char *response
)
333 if (!cmd_parameter
) {
334 pr_err("missing slot suffix\n");
335 fastboot_fail("missing command", response
);
339 if (run_command(cmd_parameter
, 0))
340 fastboot_fail("", response
);
342 fastboot_okay(NULL
, response
);
345 static char g_a_cmd_buff
[64];
347 void fastboot_acmd_complete(void)
349 run_command(g_a_cmd_buff
, 0);
353 * run_acmd() - Execute the ACmd command
355 * @cmd_parameter: Pointer to command parameter
356 * @response: Pointer to fastboot response buffer
358 static void __maybe_unused
run_acmd(char *cmd_parameter
, char *response
)
360 if (!cmd_parameter
) {
361 pr_err("missing slot suffix\n");
362 fastboot_fail("missing command", response
);
366 if (strlen(cmd_parameter
) > sizeof(g_a_cmd_buff
)) {
367 pr_err("too long command\n");
368 fastboot_fail("too long command", response
);
372 strcpy(g_a_cmd_buff
, cmd_parameter
);
373 fastboot_okay(NULL
, response
);
377 * reboot_bootloader() - Sets reboot bootloader flag.
379 * @cmd_parameter: Pointer to command parameter
380 * @response: Pointer to fastboot response buffer
382 static void reboot_bootloader(char *cmd_parameter
, char *response
)
384 if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_BOOTLOADER
))
385 fastboot_fail("Cannot set reboot flag", response
);
387 fastboot_okay(NULL
, response
);
391 * reboot_fastbootd() - Sets reboot fastboot flag.
393 * @cmd_parameter: Pointer to command parameter
394 * @response: Pointer to fastboot response buffer
396 static void reboot_fastbootd(char *cmd_parameter
, char *response
)
398 if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_FASTBOOTD
))
399 fastboot_fail("Cannot set fastboot flag", response
);
401 fastboot_okay(NULL
, response
);
405 * reboot_recovery() - Sets reboot recovery flag.
407 * @cmd_parameter: Pointer to command parameter
408 * @response: Pointer to fastboot response buffer
410 static void reboot_recovery(char *cmd_parameter
, char *response
)
412 if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_RECOVERY
))
413 fastboot_fail("Cannot set recovery flag", response
);
415 fastboot_okay(NULL
, response
);
419 * oem_format() - Execute the OEM format command
421 * @cmd_parameter: Pointer to command parameter
422 * @response: Pointer to fastboot response buffer
424 static void __maybe_unused
oem_format(char *cmd_parameter
, char *response
)
427 const int mmc_dev
= config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC
,
428 CONFIG_FASTBOOT_FLASH_MMC_DEV
, -1);
430 if (!env_get("partitions")) {
431 fastboot_fail("partitions not set", response
);
433 sprintf(cmdbuf
, "gpt write mmc %x $partitions", mmc_dev
);
434 if (run_command(cmdbuf
, 0))
435 fastboot_fail("", response
);
437 fastboot_okay(NULL
, response
);
442 * oem_partconf() - Execute the OEM partconf command
444 * @cmd_parameter: Pointer to command parameter
445 * @response: Pointer to fastboot response buffer
447 static void __maybe_unused
oem_partconf(char *cmd_parameter
, char *response
)
450 const int mmc_dev
= config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC
,
451 CONFIG_FASTBOOT_FLASH_MMC_DEV
, -1);
453 if (!cmd_parameter
) {
454 fastboot_fail("Expected command parameter", response
);
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
);
464 fastboot_okay(NULL
, response
);
468 * oem_bootbus() - Execute the OEM bootbus command
470 * @cmd_parameter: Pointer to command parameter
471 * @response: Pointer to fastboot response buffer
473 static void __maybe_unused
oem_bootbus(char *cmd_parameter
, char *response
)
476 const int mmc_dev
= config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC
,
477 CONFIG_FASTBOOT_FLASH_MMC_DEV
, -1);
479 if (!cmd_parameter
) {
480 fastboot_fail("Expected command parameter", response
);
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
);
490 fastboot_okay(NULL
, response
);