Separate the fastboot protocol handling from the fastboot UDP code in preparation for reusing it in the USB code.
Signed-off-by: Alex Kiernan <alex.kier...@gmail.com> --- Changes in v2: None drivers/fastboot/Makefile | 1 + drivers/fastboot/fb_packet.c | 249 +++++++++++++++++++++++++++++++++++++++++++ include/fastboot.h | 3 + net/fastboot.c | 234 +--------------------------------------- 4 files changed, 258 insertions(+), 229 deletions(-) create mode 100644 drivers/fastboot/fb_packet.c diff --git a/drivers/fastboot/Makefile b/drivers/fastboot/Makefile index 9af4073..c0106a7 100644 --- a/drivers/fastboot/Makefile +++ b/drivers/fastboot/Makefile @@ -2,6 +2,7 @@ obj-y += fb_common.o obj-y += fb_getvar.o +obj-y += fb_packet.o obj-$(CONFIG_FASTBOOT_FLASH) += image-sparse.o obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fb_mmc.o diff --git a/drivers/fastboot/fb_packet.c b/drivers/fastboot/fb_packet.c new file mode 100644 index 0000000..fbe5668 --- /dev/null +++ b/drivers/fastboot/fb_packet.c @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2016 The Android Open Source Project + */ + +#include <common.h> +#include <fastboot.h> +#include <fb_mmc.h> +#include <part.h> +#include <stdlib.h> +#include <version.h> + +/* Parsed from first fastboot command packet */ +static char *cmd_string; +static char *cmd_parameter; +static int cmd = -1; + +/* Fastboot download parameters */ +static unsigned int bytes_received; +static unsigned int bytes_expected; +static unsigned int image_size; + +static void cb_okay(char *, char *, unsigned int, char *); +static void cb_getvar(char *, char *, unsigned int, char *); +static void cb_download(char *, char *, unsigned int, char *); +#if CONFIG_IS_ENABLED(FASTBOOT_FLASH) +static void cb_flash(char *, char *, unsigned int, char *); +static void cb_erase(char *, char *, unsigned int, char *); +#endif +static void cb_continue(char *, char *, unsigned int, char *); +static void cb_reboot_bootloader(char *, char *, unsigned int, char *); + +static void (*fb_net_dispatch[])(char *cmd_parameter, + char *fastboot_data, + unsigned int fastboot_data_len, + char *response) = { + [FB_CMD_GETVAR] = cb_getvar, + [FB_CMD_DOWNLOAD] = cb_download, + [FB_CMD_VERIFY] = NULL, +#if CONFIG_IS_ENABLED(FASTBOOT_FLASH) + [FB_CMD_FLASH] = cb_flash, + [FB_CMD_ERASE] = cb_erase, +#else + [FB_CMD_FLASH] = NULL, + [FB_CMD_ERASE] = NULL, +#endif + [FB_CMD_BOOT] = cb_okay, + [FB_CMD_CONTINUE] = cb_continue, + [FB_CMD_REBOOT] = cb_okay, + [FB_CMD_REBOOT_BOOTLOADER] = cb_reboot_bootloader, + [FB_CMD_POWERDOWN] = NULL, + [FB_CMD_SET_ACTIVE] = cb_okay, + [FB_CMD_UPLOAD] = NULL, +}; + +static void cleanup_command_data(void); + +int fastboot_packet_handle(char *fastboot_data, + unsigned int fastboot_data_len, char *response) +{ + if (!cmd_string) { + /* Parse command and send ack */ + cmd_parameter = fastboot_data; + cmd_string = strsep(&cmd_parameter, ":"); + cmd_string = strdup(cmd_string); + cmd = fastboot_lookup_command(cmd_string); + if (cmd_parameter) + cmd_parameter = strdup(cmd_parameter); + } else { + if (cmd >= 0) { + void (*fb_call)(char *cmd_parameter, + char *fastboot_data, + unsigned int fastboot_data_len, + char *response); + fb_call = fb_net_dispatch[cmd]; + if (fb_call) { + fb_call(cmd_parameter, fastboot_data, + fastboot_data_len, response); + } else { + pr_err("command %s not implemented.\n", + cmd_string); + fastboot_fail("unrecognized command", + response); + } + } else { + pr_err("command %s not recognized.\n", + cmd_string); + fastboot_fail("unrecognized command", response); + } + } + return cmd; +} + +void fastboot_after_response(char *response) +{ + /* OKAY and FAIL indicate command is complete */ + if (!strncmp("OKAY", response, 4) || !strncmp("FAIL", response, 4)) + cleanup_command_data(); +} + +static void cb_okay(char *cmd_parameter, char *fastboot_data, + unsigned int fastboot_data_len, char *response) +{ + fastboot_okay(NULL, response); +} + +static void cb_getvar(char *cmd_parameter, char *fastboot_data, + unsigned int fastboot_data_len, char *response) +{ + fb_getvar(cmd_parameter, response); +} + +/** + * Copies image data from fastboot_data to CONFIG_FASTBOOT_BUF_ADDR. + * Writes to response. + * + * @param fastboot_data Pointer to received fastboot data + * @param fastboot_data_len Length of received fastboot data + * @param repsonse Pointer to fastboot response buffer + */ +static void cb_download(char *cmd_parameter, char *fastboot_data, + unsigned int fastboot_data_len, char *response) +{ + char *tmp; + + if (bytes_expected == 0) { + if (!cmd_parameter) { + fastboot_fail("Expected command parameter", response); + return; + } + bytes_expected = simple_strtoul(cmd_parameter, &tmp, 16); + if (bytes_expected == 0) { + fastboot_fail("Expected nonzero image size", response); + return; + } + } + if (fastboot_data_len == 0 && bytes_received == 0) { + /* Nothing to download yet. Response is of the form: + * [DATA|FAIL]$cmd_parameter + * + * where cmd_parameter is an 8 digit hexadecimal number + */ + if (bytes_expected > CONFIG_FASTBOOT_BUF_SIZE) + fastboot_fail(cmd_parameter, response); + else + fastboot_response("DATA", response, "%s", + cmd_parameter); + } else if (fastboot_data_len == 0 && + (bytes_received >= bytes_expected)) { + /* Download complete. Respond with "OKAY" */ + fastboot_okay(NULL, response); + image_size = bytes_received; + bytes_expected = 0; + bytes_received = 0; + } else { + if (fastboot_data_len == 0 || + (bytes_received + fastboot_data_len) > bytes_expected) { + fastboot_fail("Received invalid data length", + response); + return; + } + /* Download data to CONFIG_FASTBOOT_BUF_ADDR */ + memcpy((void *)CONFIG_FASTBOOT_BUF_ADDR + bytes_received, + fastboot_data, fastboot_data_len); + bytes_received += fastboot_data_len; + } +} + +#if CONFIG_IS_ENABLED(FASTBOOT_FLASH) +/** + * Writes the previously downloaded image to the partition indicated by + * cmd_parameter. Writes to response. + * + * @param repsonse Pointer to fastboot response buffer + */ +static void cb_flash(char *cmd_parameter, char *fastboot_data, + unsigned int fastboot_data_len, char *response) +{ +#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC) + fb_mmc_flash_write(cmd_parameter, (void *)CONFIG_FASTBOOT_BUF_ADDR, + image_size, response); +#endif +#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND) + fb_nand_flash_write(cmd_parameter, (void *)CONFIG_FASTBOOT_BUF_ADDR, + image_size, response); +#endif +} + +/** + * Erases the partition indicated by cmd_parameter (clear to 0x00s). Writes + * to response. + * + * @param repsonse Pointer to fastboot response buffer + */ +static void cb_erase(char *cmd_parameter, char *fastboot_data, + unsigned int fastboot_data_len, char *response) +{ +#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC) + fb_mmc_erase(cmd_parameter, response); +#endif +#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND) + fb_nand_erase(cmd_parameter, response); +#endif +} +#endif + +/** + * Continues normal boot process by exiting fastboot server. Writes + * to response. + * + * @param repsonse Pointer to fastboot response buffer + */ +static void cb_continue(char *cmd_parameter, char *fastboot_data, + unsigned int fastboot_data_len, char *response) +{ + net_set_state(NETLOOP_SUCCESS); + fastboot_okay(NULL, response); +} + +/** + * Sets reboot bootloader flag if requested. Writes to response. + * + * @param repsonse Pointer to fastboot response buffer + */ +static void cb_reboot_bootloader(char *cmd_parameter, char *fastboot_data, + unsigned int fastboot_data_len, char *response) +{ + if (fb_set_reboot_flag()) + fastboot_fail("Cannot set reboot flag", response); + else + fastboot_okay(NULL, response); +} + +/** + * Frees any resources allocated during current fastboot command. + */ +static void cleanup_command_data(void) +{ + /* cmd_parameter and cmd_string potentially point to memory allocated by + * strdup + */ + if (cmd_parameter) + free(cmd_parameter); + if (cmd_string) + free(cmd_string); + cmd_parameter = NULL; + cmd_string = NULL; + cmd = -1; +} diff --git a/include/fastboot.h b/include/fastboot.h index 64f9939..4a02554 100644 --- a/include/fastboot.h +++ b/include/fastboot.h @@ -77,4 +77,7 @@ int strcmp_l1(const char *s1, const char *s2); int fastboot_lookup_command(const char *cmd_string); int fb_set_reboot_flag(void); void fastboot_boot(void *addr); +int fastboot_packet_handle(char *fastboot_data, + unsigned int fastboot_data_len, char *response); +void fastboot_after_response(char *response); #endif /* _FASTBOOT_H_ */ diff --git a/net/fastboot.c b/net/fastboot.c index a07b1ad..97f75a5 100644 --- a/net/fastboot.c +++ b/net/fastboot.c @@ -5,12 +5,8 @@ #include <common.h> #include <fastboot.h> -#include <fb_mmc.h> #include <net.h> #include <net/fastboot.h> -#include <part.h> -#include <stdlib.h> -#include <version.h> /* Fastboot port # defined in spec */ #define WELL_KNOWN_PORT 5554 @@ -42,56 +38,13 @@ static const unsigned short fb_udp_version = 1; static uchar last_packet[PACKET_SIZE]; static unsigned int last_packet_len; -/* Parsed from first fastboot command packet */ -static char *cmd_string; -static char *cmd_parameter; - -/* Fastboot download parameters */ -static unsigned int bytes_received; -static unsigned int bytes_expected; -static unsigned int image_size; - static struct in_addr fastboot_remote_ip; /* The UDP port at their end */ static int fastboot_remote_port; /* The UDP port at our end */ static int fastboot_our_port; -static void cb_okay(char *, char *, unsigned int, char *); -static void cb_getvar(char *, char *, unsigned int, char *); -static void cb_download(char *, char *, unsigned int, char *); -#if CONFIG_IS_ENABLED(FASTBOOT_FLASH) -static void cb_flash(char *, char *, unsigned int, char *); -static void cb_erase(char *, char *, unsigned int, char *); -#endif -static void cb_continue(char *, char *, unsigned int, char *); -static void cb_reboot_bootloader(char *, char *, unsigned int, char *); - -static void (*fb_net_dispatch[])(char *cmd_parameter, - char *fastboot_data, - unsigned int fastboot_data_len, - char *response) = { - [FB_CMD_GETVAR] = cb_getvar, - [FB_CMD_DOWNLOAD] = cb_download, - [FB_CMD_VERIFY] = NULL, -#if CONFIG_IS_ENABLED(FASTBOOT_FLASH) - [FB_CMD_FLASH] = cb_flash, - [FB_CMD_ERASE] = cb_erase, -#else - [FB_CMD_FLASH] = NULL, - [FB_CMD_ERASE] = NULL, -#endif - [FB_CMD_BOOT] = cb_okay, - [FB_CMD_CONTINUE] = cb_continue, - [FB_CMD_REBOOT] = cb_okay, - [FB_CMD_REBOOT_BOOTLOADER] = cb_reboot_bootloader, - [FB_CMD_POWERDOWN] = NULL, - [FB_CMD_SET_ACTIVE] = cb_okay, - [FB_CMD_UPLOAD] = NULL, -}; - static void boot_downloaded_image(void); -static void cleanup_command_data(void); void fastboot_send_info(const char *msg) { @@ -185,36 +138,8 @@ static void fastboot_send(struct fastboot_header fb_header, char *fastboot_data, packet += strlen(error_msg); break; case FASTBOOT_FASTBOOT: - if (!cmd_string) { - /* Parse command and send ack */ - cmd_parameter = fastboot_data; - cmd_string = strsep(&cmd_parameter, ":"); - cmd_string = strdup(cmd_string); - if (cmd_parameter) - cmd_parameter = strdup(cmd_parameter); - } else { - cmd = fastboot_lookup_command(cmd_string); - if (cmd >= 0) { - void (*fb_call)(char *cmd_parameter, - char *fastboot_data, - unsigned int fastboot_data_len, - char *response); - fb_call = fb_net_dispatch[cmd]; - if (fb_call) { - fb_call(cmd_parameter, fastboot_data, - fastboot_data_len, response); - } else { - pr_err("command %s not implemented.\n", - cmd_string); - fastboot_fail("unrecognized command", - response); - } - } else { - pr_err("command %s not recognized.\n", - cmd_string); - fastboot_fail("unrecognized command", response); - } - } + cmd = fastboot_packet_handle(fastboot_data, fastboot_data_len, + response); /* Sent some INFO packets, need to update sequence number in * header */ @@ -245,148 +170,15 @@ static void fastboot_send(struct fastboot_header fb_header, char *fastboot_data, if (!strncmp("OKAY", response, 4)) { if (cmd == FB_CMD_BOOT) { boot_downloaded_image(); + } else if (cmd == FB_CMD_CONTINUE) { + net_set_state(NETLOOP_SUCCESS); } else if (cmd == FB_CMD_REBOOT || cmd == FB_CMD_REBOOT_BOOTLOADER) { do_reset(NULL, 0, 0, NULL); } } - /* OKAY and FAIL indicate command is complete */ - if (!strncmp("OKAY", response, 4) || !strncmp("FAIL", response, 4)) - cleanup_command_data(); -} - -static void cb_okay(char *cmd_parameter, char *fastboot_data, - unsigned int fastboot_data_len, char *response) -{ - fastboot_okay(NULL, response); -} - -static void cb_getvar(char *cmd_parameter, char *fastboot_data, - unsigned int fastboot_data_len, char *response) -{ - fb_getvar(cmd_parameter, response); -} - -/** - * Copies image data from fastboot_data to CONFIG_FASTBOOT_BUF_ADDR. - * Writes to response. - * - * @param fastboot_data Pointer to received fastboot data - * @param fastboot_data_len Length of received fastboot data - * @param repsonse Pointer to fastboot response buffer - */ -static void cb_download(char *cmd_parameter, char *fastboot_data, - unsigned int fastboot_data_len, char *response) -{ - char *tmp; - - if (bytes_expected == 0) { - if (!cmd_parameter) { - fastboot_fail("Expected command parameter", response); - return; - } - bytes_expected = simple_strtoul(cmd_parameter, &tmp, 16); - if (bytes_expected == 0) { - fastboot_fail("Expected nonzero image size", response); - return; - } - } - if (fastboot_data_len == 0 && bytes_received == 0) { - /* Nothing to download yet. Response is of the form: - * [DATA|FAIL]$cmd_parameter - * - * where cmd_parameter is an 8 digit hexadecimal number - */ - if (bytes_expected > CONFIG_FASTBOOT_BUF_SIZE) - fastboot_fail(cmd_parameter, response); - else - fastboot_response("DATA", response, "%s", - cmd_parameter); - } else if (fastboot_data_len == 0 && - (bytes_received >= bytes_expected)) { - /* Download complete. Respond with "OKAY" */ - fastboot_okay(NULL, response); - image_size = bytes_received; - bytes_expected = 0; - bytes_received = 0; - } else { - if (fastboot_data_len == 0 || - (bytes_received + fastboot_data_len) > bytes_expected) { - fastboot_fail("Received invalid data length", - response); - return; - } - /* Download data to CONFIG_FASTBOOT_BUF_ADDR */ - memcpy((void *)CONFIG_FASTBOOT_BUF_ADDR + bytes_received, - fastboot_data, fastboot_data_len); - bytes_received += fastboot_data_len; - } -} - -#if CONFIG_IS_ENABLED(FASTBOOT_FLASH) -/** - * Writes the previously downloaded image to the partition indicated by - * cmd_parameter. Writes to response. - * - * @param repsonse Pointer to fastboot response buffer - */ -static void cb_flash(char *cmd_parameter, char *fastboot_data, - unsigned int fastboot_data_len, char *response) -{ -#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC) - fb_mmc_flash_write(cmd_parameter, (void *)CONFIG_FASTBOOT_BUF_ADDR, - image_size, response); -#endif -#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND) - fb_nand_flash_write(cmd_parameter, (void *)CONFIG_FASTBOOT_BUF_ADDR, - image_size, response); -#endif -} - -/** - * Erases the partition indicated by cmd_parameter (clear to 0x00s). Writes - * to response. - * - * @param repsonse Pointer to fastboot response buffer - */ -static void cb_erase(char *cmd_parameter, char *fastboot_data, - unsigned int fastboot_data_len, char *response) -{ -#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC) - fb_mmc_erase(cmd_parameter, response); -#endif -#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND) - fb_nand_erase(cmd_parameter, response); -#endif -} -#endif - -/** - * Continues normal boot process by exiting fastboot server. Writes - * to response. - * - * @param repsonse Pointer to fastboot response buffer - */ -static void cb_continue(char *cmd_parameter, char *fastboot_data, - unsigned int fastboot_data_len, char *response) -{ - net_set_state(NETLOOP_SUCCESS); - fastboot_okay(NULL, response); -} - -/** - * Sets reboot bootloader flag if requested. Writes to response. - * - * @param repsonse Pointer to fastboot response buffer - */ -static void cb_reboot_bootloader(char *cmd_parameter, char *fastboot_data, - unsigned int fastboot_data_len, char *response) -{ - if (fb_set_reboot_flag()) - fastboot_fail("Cannot set reboot flag", response); - else - fastboot_okay(NULL, response); + fastboot_after_response(response); } /** @@ -399,22 +191,6 @@ static void boot_downloaded_image(void) } /** - * Frees any resources allocated during current fastboot command. - */ -static void cleanup_command_data(void) -{ - /* cmd_parameter and cmd_string potentially point to memory allocated by - * strdup - */ - if (cmd_parameter) - free(cmd_parameter); - if (cmd_string) - free(cmd_string); - cmd_parameter = NULL; - cmd_string = NULL; -} - -/** * Incoming UDP packet handler. * * @param packet Pointer to incoming UDP packet -- 2.7.4 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot