1 // SPDX-License-Identifier: BSD-2-Clause
3 * Copyright (C) 2016 The Android Open Source Project
10 #include <fastboot-internal.h>
18 * image_size - final fastboot image size
20 static u32 image_size;
23 * fastboot_bytes_received - number of bytes received in the current download
25 static u32 fastboot_bytes_received;
28 * fastboot_bytes_expected - number of bytes expected in the current download
30 static u32 fastboot_bytes_expected;
32 static void okay(char *, char *);
33 static void getvar(char *, char *);
34 static void download(char *, char *);
35 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
36 static void flash(char *, char *);
37 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 #if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT)
43 static void oem_format(char *, char *);
48 void (*dispatch)(char *cmd_parameter, char *response);
49 } commands[FASTBOOT_COMMAND_COUNT] = {
50 [FASTBOOT_COMMAND_GETVAR] = {
54 [FASTBOOT_COMMAND_DOWNLOAD] = {
55 .command = "download",
58 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
59 [FASTBOOT_COMMAND_FLASH] = {
63 [FASTBOOT_COMMAND_ERASE] = {
68 [FASTBOOT_COMMAND_BOOT] = {
72 [FASTBOOT_COMMAND_CONTINUE] = {
73 .command = "continue",
76 [FASTBOOT_COMMAND_REBOOT] = {
80 [FASTBOOT_COMMAND_REBOOT_BOOTLOADER] = {
81 .command = "reboot-bootloader",
82 .dispatch = reboot_bootloader
84 [FASTBOOT_COMMAND_REBOOT_FASTBOOTD] = {
85 .command = "reboot-fastboot",
86 .dispatch = reboot_fastbootd
88 [FASTBOOT_COMMAND_REBOOT_RECOVERY] = {
89 .command = "reboot-recovery",
90 .dispatch = reboot_recovery
92 [FASTBOOT_COMMAND_SET_ACTIVE] = {
93 .command = "set_active",
96 #if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT)
97 [FASTBOOT_COMMAND_OEM_FORMAT] = {
98 .command = "oem format",
99 .dispatch = oem_format,
105 * fastboot_handle_command - Handle fastboot command
107 * @cmd_string: Pointer to command string
108 * @response: Pointer to fastboot response buffer
110 * Return: Executed command, or -1 if not recognized
112 int fastboot_handle_command(char *cmd_string, char *response)
117 cmd_parameter = cmd_string;
118 strsep(&cmd_parameter, ":");
120 for (i = 0; i < FASTBOOT_COMMAND_COUNT; i++) {
121 if (!strcmp(commands[i].command, cmd_string)) {
122 if (commands[i].dispatch) {
123 commands[i].dispatch(cmd_parameter,
132 pr_err("command %s not recognized.\n", cmd_string);
133 fastboot_fail("unrecognized command", response);
138 * okay() - Send bare OKAY response
140 * @cmd_parameter: Pointer to command parameter
141 * @response: Pointer to fastboot response buffer
143 * Send a bare OKAY fastboot response. This is used where the command is
144 * valid, but all the work is done after the response has been sent (e.g.
147 static void okay(char *cmd_parameter, char *response)
149 fastboot_okay(NULL, response);
153 * getvar() - Read a config/version variable
155 * @cmd_parameter: Pointer to command parameter
156 * @response: Pointer to fastboot response buffer
158 static void getvar(char *cmd_parameter, char *response)
160 fastboot_getvar(cmd_parameter, response);
164 * fastboot_download() - Start a download transfer from the client
166 * @cmd_parameter: Pointer to command parameter
167 * @response: Pointer to fastboot response buffer
169 static void download(char *cmd_parameter, char *response)
173 if (!cmd_parameter) {
174 fastboot_fail("Expected command parameter", response);
177 fastboot_bytes_received = 0;
178 fastboot_bytes_expected = simple_strtoul(cmd_parameter, &tmp, 16);
179 if (fastboot_bytes_expected == 0) {
180 fastboot_fail("Expected nonzero image size", response);
184 * Nothing to download yet. Response is of the form:
185 * [DATA|FAIL]$cmd_parameter
187 * where cmd_parameter is an 8 digit hexadecimal number
189 if (fastboot_bytes_expected > fastboot_buf_size) {
190 fastboot_fail(cmd_parameter, response);
192 printf("Starting download of %d bytes\n",
193 fastboot_bytes_expected);
194 fastboot_response("DATA", response, "%s", cmd_parameter);
199 * fastboot_data_remaining() - return bytes remaining in current transfer
201 * Return: Number of bytes left in the current download
203 u32 fastboot_data_remaining(void)
205 return fastboot_bytes_expected - fastboot_bytes_received;
209 * fastboot_data_download() - Copy image data to fastboot_buf_addr.
211 * @fastboot_data: Pointer to received fastboot data
212 * @fastboot_data_len: Length of received fastboot data
213 * @response: Pointer to fastboot response buffer
215 * Copies image data from fastboot_data to fastboot_buf_addr. Writes to
216 * response. fastboot_bytes_received is updated to indicate the number
217 * of bytes that have been transferred.
219 * On completion sets image_size and ${filesize} to the total size of the
222 void fastboot_data_download(const void *fastboot_data,
223 unsigned int fastboot_data_len,
226 #define BYTES_PER_DOT 0x20000
227 u32 pre_dot_num, now_dot_num;
229 if (fastboot_data_len == 0 ||
230 (fastboot_bytes_received + fastboot_data_len) >
231 fastboot_bytes_expected) {
232 fastboot_fail("Received invalid data length",
236 /* Download data to fastboot_buf_addr */
237 memcpy(fastboot_buf_addr + fastboot_bytes_received,
238 fastboot_data, fastboot_data_len);
240 pre_dot_num = fastboot_bytes_received / BYTES_PER_DOT;
241 fastboot_bytes_received += fastboot_data_len;
242 now_dot_num = fastboot_bytes_received / BYTES_PER_DOT;
244 if (pre_dot_num != now_dot_num) {
246 if (!(now_dot_num % 74))
253 * fastboot_data_complete() - Mark current transfer complete
255 * @response: Pointer to fastboot response buffer
257 * Set image_size and ${filesize} to the total size of the downloaded image.
259 void fastboot_data_complete(char *response)
261 /* Download complete. Respond with "OKAY" */
262 fastboot_okay(NULL, response);
263 printf("\ndownloading of %d bytes finished\n", fastboot_bytes_received);
264 image_size = fastboot_bytes_received;
265 env_set_hex("filesize", image_size);
266 fastboot_bytes_expected = 0;
267 fastboot_bytes_received = 0;
270 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
272 * flash() - write the downloaded image to the indicated partition.
274 * @cmd_parameter: Pointer to partition name
275 * @response: Pointer to fastboot response buffer
277 * Writes the previously downloaded image to the partition indicated by
278 * cmd_parameter. Writes to response.
280 static void flash(char *cmd_parameter, char *response)
282 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
283 fastboot_mmc_flash_write(cmd_parameter, fastboot_buf_addr, image_size,
286 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND)
287 fastboot_nand_flash_write(cmd_parameter, fastboot_buf_addr, image_size,
293 * erase() - erase the indicated partition.
295 * @cmd_parameter: Pointer to partition name
296 * @response: Pointer to fastboot response buffer
298 * Erases the partition indicated by cmd_parameter (clear to 0x00s). Writes
301 static void erase(char *cmd_parameter, char *response)
303 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
304 fastboot_mmc_erase(cmd_parameter, response);
306 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND)
307 fastboot_nand_erase(cmd_parameter, response);
313 * reboot_bootloader() - Sets reboot bootloader flag.
315 * @cmd_parameter: Pointer to command parameter
316 * @response: Pointer to fastboot response buffer
318 static void reboot_bootloader(char *cmd_parameter, char *response)
320 if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_BOOTLOADER))
321 fastboot_fail("Cannot set reboot flag", response);
323 fastboot_okay(NULL, response);
327 * reboot_fastbootd() - Sets reboot fastboot flag.
329 * @cmd_parameter: Pointer to command parameter
330 * @response: Pointer to fastboot response buffer
332 static void reboot_fastbootd(char *cmd_parameter, char *response)
334 if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_FASTBOOTD))
335 fastboot_fail("Cannot set fastboot flag", response);
337 fastboot_okay(NULL, response);
341 * reboot_recovery() - Sets reboot recovery flag.
343 * @cmd_parameter: Pointer to command parameter
344 * @response: Pointer to fastboot response buffer
346 static void reboot_recovery(char *cmd_parameter, char *response)
348 if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_RECOVERY))
349 fastboot_fail("Cannot set recovery flag", response);
351 fastboot_okay(NULL, response);
354 #if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT)
356 * oem_format() - Execute the OEM format command
358 * @cmd_parameter: Pointer to command parameter
359 * @response: Pointer to fastboot response buffer
361 static void oem_format(char *cmd_parameter, char *response)
365 if (!env_get("partitions")) {
366 fastboot_fail("partitions not set", response);
368 sprintf(cmdbuf, "gpt write mmc %x $partitions",
369 CONFIG_FASTBOOT_FLASH_MMC_DEV);
370 if (run_command(cmdbuf, 0))
371 fastboot_fail("", response);
373 fastboot_okay(NULL, response);