[U-Boot] [RFC PATCH v2 20/20] fastboot: net: Split fastboot protocol out from net
Alex Kiernan
alex.kiernan at gmail.com
Mon Apr 30 08:32:54 UTC 2018
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.kiernan at 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
More information about the U-Boot
mailing list