All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jocelyn Bohr <bohr@google.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [RFC PATCH v2 07/20] net: fastboot: Merge AOSP UDP fastboot
Date: Tue, 01 May 2018 06:28:33 +0000	[thread overview]
Message-ID: <CAPJEgOFUrhCqhELEVbg41uGdAcd4uPXD=wN0GfY6Na5a+pGCHA@mail.gmail.com> (raw)
In-Reply-To: <1525077174-6211-8-git-send-email-alex.kiernan@gmail.com>

On Mon, Apr 30, 2018 at 1:33 AM Alex Kiernan <alex.kiernan@gmail.com> wrote:

> Merge UDP fastboot support from AOSP:
>
>
> https://android.googlesource.com/platform/external/u-boot/+/android-o-mr1-iot-preview-8
>
> Signed-off-by: Alex Kiernan <alex.kiernan@gmail.com>
> Signed-off-by: Alex Deymo <deymo@google.com>
> ---
>
> Changes in v2:
> - ensure fastboot syntax is backward compatible - 'fastboot 0' means
>   'fastboot usb 0'
>
>  cmd/fastboot.c               |  35 ++-
>  cmd/net.c                    |   6 +
>  drivers/fastboot/Kconfig     |  16 +-
>  drivers/fastboot/fb_common.c |  18 ++
>  drivers/fastboot/fb_mmc.c    |  34 ++-
>  include/fastboot.h           |  13 ++
>  include/net.h                |   6 +-
>  include/net/fastboot.h       |  27 +++
>  net/Makefile                 |   1 +
>  net/fastboot.c               | 542
> +++++++++++++++++++++++++++++++++++++++++++
>  net/net.c                    |   9 +
>  11 files changed, 695 insertions(+), 12 deletions(-)
>  create mode 100644 include/net/fastboot.h
>  create mode 100644 net/fastboot.c
>
> diff --git a/cmd/fastboot.c b/cmd/fastboot.c
> index 8adcca5..68a41de 100644
> --- a/cmd/fastboot.c
> +++ b/cmd/fastboot.c
> @@ -11,17 +11,41 @@
>  #include <command.h>
>  #include <console.h>
>  #include <g_dnl.h>
> +#include <net.h>
>  #include <usb.h>
>
>  static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const
> argv[])
>  {
> +#ifdef CONFIG_USB_FUNCTION_FASTBOOT
>         int controller_index;
>         char *usb_controller;
>         int ret;
> +#endif
>
>         if (argc < 2)
>                 return CMD_RET_USAGE;
>
> +       if (!strcmp(argv[1], "udp")) {
> +#ifndef CONFIG_UDP_FUNCTION_FASTBOOT
> +               pr_err("Fastboot UDP not enabled\n");
> +               return -1;
> +#else
> +               return do_fastboot_udp(cmdtp, flag, argc, argv);
> +#endif
> +       }
> +
> +       if (!strcmp(argv[1], "usb")) {
> +               argv++;
> +               argc--;
> +       }
> +
> +       if (argc < 2)
> +               return CMD_RET_USAGE;
> +
> +#ifndef CONFIG_USB_FUNCTION_FASTBOOT
> +       pr_err("Fastboot USB not enabled\n");
> +       return -1;
> +#else
>         usb_controller = argv[1];
>         controller_index = simple_strtoul(usb_controller, NULL, 0);
>
> @@ -59,11 +83,14 @@ exit:
>         board_usb_cleanup(controller_index, USB_INIT_DEVICE);
>
>         return ret;
> +#endif
>  }
>
>  U_BOOT_CMD(
> -       fastboot, 2, 1, do_fastboot,
> -       "use USB Fastboot protocol",
> -       "<USB_controller>\n"
> -       "    - run as a fastboot usb device"
> +       fastboot, 3, 1, do_fastboot,
> +       "use USB or UDP Fastboot protocol",
> +       "[usb,udp] <USB_controller>\n"
> +       " - run as a fastboot usb or udp device\n"
> +       "   usb: specify <USB_controller>\n"
> +       "   udp: requires ip_addr set and ethernet initialized\n"
>  );
> diff --git a/cmd/net.c b/cmd/net.c
> index 67888d4..668f344 100644
> --- a/cmd/net.c
> +++ b/cmd/net.c
> @@ -74,6 +74,12 @@ U_BOOT_CMD(
>  );
>  #endif
>
> +#ifdef CONFIG_UDP_FUNCTION_FASTBOOT
> +int do_fastboot_udp(cmd_tbl_t *cmdtp, int flag, int argc, char *const
> argv[])
> +{
> +       return netboot_common(FASTBOOT, cmdtp, argc, argv);
> +}
> +#endif
>
>  #ifdef CONFIG_CMD_RARP
>  int do_rarpb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig
> index 64b94f0..53c337f 100644
> --- a/drivers/fastboot/Kconfig
> +++ b/drivers/fastboot/Kconfig
> @@ -2,6 +2,8 @@ menu "Fastboot support"
>
>  config FASTBOOT
>         bool
> +       imply ANDROID_BOOT_IMAGE
> +       imply CMD_FASTBOOT
>
>  config USB_FUNCTION_FASTBOOT
>         bool "Enable USB fastboot gadget"
> @@ -9,12 +11,17 @@ config USB_FUNCTION_FASTBOOT
>         default y if ARCH_SUNXI && USB_MUSB_GADGET
>         select FASTBOOT
>         select USB_GADGET_DOWNLOAD
> -       imply ANDROID_BOOT_IMAGE
> -       imply CMD_FASTBOOT
>         help
>           This enables the USB part of the fastboot gadget.
>
> -if USB_FUNCTION_FASTBOOT
> +config UDP_FUNCTION_FASTBOOT
> +       depends on NET
> +       select FASTBOOT
> +       bool "Enable fastboot protocol over UDP"
> +       help
> +         This enables the fastboot protocol over UDP.
> +
> +if USB_FUNCTION_FASTBOOT || UDP_FUNCTION_FASTBOOT
>
>  config FASTBOOT_BUF_ADDR
>         hex "Define FASTBOOT buffer address"
> @@ -46,6 +53,7 @@ config FASTBOOT_BUF_SIZE
>
>  config FASTBOOT_USB_DEV
>         int "USB controller number"
> +       depends on USB_FUNCTION_FASTBOOT
>         default 0
>         help
>           Some boards have USB OTG controller other than 0. Define this
> @@ -117,6 +125,6 @@ config FASTBOOT_MBR_NAME
>           specified on the "fastboot flash" command line matches the value
>           defined here. The default target name for updating MBR is "mbr".
>
> -endif # USB_FUNCTION_FASTBOOT
> +endif # USB_FUNCTION_FASTBOOT || UDP_FUNCTION_FASTBOOT
>
>  endmenu
> diff --git a/drivers/fastboot/fb_common.c b/drivers/fastboot/fb_common.c
> index fe58803..7367fbb 100644
> --- a/drivers/fastboot/fb_common.c
> +++ b/drivers/fastboot/fb_common.c
> @@ -12,6 +12,9 @@
>
>  #include <common.h>
>  #include <fastboot.h>
> +#ifdef CONFIG_UDP_FUNCTION_FASTBOOT
> +#include <net/fastboot.h>
> +#endif
>
>  /**
>   * Writes a response to response buffer of the form "$tag$reason".
> @@ -44,3 +47,18 @@ void fastboot_okay(const char *reason, char *response)
>  {
>         fastboot_response("OKAY", response, "%s", reason);
>  }
> +
> +void timed_send_info(ulong *start, const char *msg)
> +{
> +#ifdef CONFIG_UDP_FUNCTION_FASTBOOT
> +       /* Initialize timer */
> +       if (*start == 0)
> +               *start = get_timer(0);
> +       ulong time = get_timer(*start);
> +       /* Send INFO packet to host every 30 seconds */
> +       if (time >= 30000) {
> +               *start = get_timer(0);
> +               fastboot_send_info(msg);
> +       }
> +#endif
> +}
> diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c
> index 02864aa..304bda1 100644
> --- a/drivers/fastboot/fb_mmc.c
> +++ b/drivers/fastboot/fb_mmc.c
> @@ -29,6 +29,9 @@
>  #define CONFIG_FASTBOOT_MBR_NAME "mbr"
>  #endif
>
> +#define FASTBOOT_MAX_BLK_WRITE 16384
> +static ulong timer;
> +
>  #define BOOT_PARTITION_NAME "boot"
>
>  struct fb_mmc_sparse {
> @@ -57,13 +60,38 @@ static int part_get_info_by_name_or_alias(struct
> blk_desc *dev_desc,
>         return ret;
>  }
>
> +static lbaint_t fb_mmc_blk_write(struct blk_desc *block_dev, lbaint_t
> start,
> +                                lbaint_t blkcnt, const void *buffer)
> +{
> +       lbaint_t blk = start;
> +       lbaint_t blks_written;
> +       lbaint_t cur_blkcnt;
> +       lbaint_t blks = 0;
> +       int i;
> +
> +       for (i = 0; i < blkcnt; i += FASTBOOT_MAX_BLK_WRITE) {
> +               cur_blkcnt = min((int)blkcnt - i, FASTBOOT_MAX_BLK_WRITE);
> +               if (!buffer) {
> +                       timed_send_info(&timer, "writing");
> +                       blks_written = blk_dwrite(block_dev, blk,
> cur_blkcnt,
> +                                                 buffer + (i *
> block_dev->blksz));
> +               } else {
> +                       timed_send_info(&timer, "erasing");
> +                       blks_written = blk_derase(block_dev, blk,
> cur_blkcnt);
> +               }
> +               blk += blks_written;
> +               blks += blks_written;
> +       }
> +       return blks;
> +}
> +
>  static lbaint_t fb_mmc_sparse_write(struct sparse_storage *info,
>                 lbaint_t blk, lbaint_t blkcnt, const void *buffer)
>  {
>         struct fb_mmc_sparse *sparse = info->priv;
>         struct blk_desc *dev_desc = sparse->dev_desc;
>
> -       return blk_dwrite(dev_desc, blk, blkcnt, buffer);
> +       return fb_mmc_blk_write(dev_desc, blk, blkcnt, buffer);
>  }
>
>  static lbaint_t fb_mmc_sparse_reserve(struct sparse_storage *info,
> @@ -91,7 +119,7 @@ static void write_raw_image(struct blk_desc *dev_desc,
> disk_partition_t *info,
>
>         puts("Flashing Raw Image\n");
>
> -       blks = blk_dwrite(dev_desc, info->start, blkcnt, buffer);
> +       blks = fb_mmc_blk_write(dev_desc, info->start, blkcnt, buffer);
>         if (blks != blkcnt) {
>                 pr_err("failed writing to device %d\n", dev_desc->devnum);
>                 fastboot_fail("failed writing to device", response);
> @@ -399,7 +427,7 @@ void fb_mmc_erase(const char *cmd, char *response)
>         printf("Erasing blocks " LBAFU " to " LBAFU " due to alignment\n",
>                blks_start, blks_start + blks_size);
>
> -       blks = blk_derase(dev_desc, blks_start, blks_size);
> +       blks = fb_mmc_blk_write(dev_desc, blks_start, blks_size, NULL);
>         if (blks != blks_size) {
>                 pr_err("failed erasing from device %d", dev_desc->devnum);
>                 fastboot_fail("failed erasing from device", response);
> diff --git a/include/fastboot.h b/include/fastboot.h
> index 2140c94..6f69423 100644
> --- a/include/fastboot.h
> +++ b/include/fastboot.h
> @@ -23,4 +23,17 @@ void fastboot_response(const char *tag, char *response,
>  void fastboot_fail(const char *reason, char *response);
>  void fastboot_okay(const char *reason, char *response);
>
> +/**
> + * Send an INFO packet during long commands based on timer. If
> + * CONFIG_UDP_FUNCTION_FASTBOOT is defined, an INFO packet is sent
> + * if the time is 30 seconds after start. Else, noop.
> + *
> + * TODO: Handle the situation where both UDP and USB fastboot are
> + *       enabled.
> + *
> + * @param start:  Time since last INFO packet was sent.
> + * @param msg:    String describing the reason for waiting
> + */
> +void timed_send_info(ulong *start, const char *msg);
> +
>  #endif /* _FASTBOOT_H_ */
> diff --git a/include/net.h b/include/net.h
> index 3469811..890ae27 100644
> --- a/include/net.h
> +++ b/include/net.h
> @@ -535,7 +535,7 @@ extern int          net_restart_wrap;       /* Tried
> all network devices */
>
>  enum proto_t {
>         BOOTP, RARP, ARP, TFTPGET, DHCP, PING, DNS, NFS, CDP, NETCONS,
> SNTP,
> -       TFTPSRV, TFTPPUT, LINKLOCAL
> +       TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT
>  };
>
>  extern char    net_boot_file_name[1024];/* Boot File name */
> @@ -549,6 +549,10 @@ extern char *net_dns_resolve;              /* The
> host to resolve  */
>  extern char *net_dns_env_var;          /* the env var to put the ip into
> */
>  #endif
>
> +#if defined(CONFIG_UDP_FUNCTION_FASTBOOT)
> +int do_fastboot_udp(cmd_tbl_t *cmdtp, int flag, int argc, char *const
> argv[]);
> +#endif
> +
>  #if defined(CONFIG_CMD_PING)
>  extern struct in_addr net_ping_ip;     /* the ip address to ping */
>  #endif
> diff --git a/include/net/fastboot.h b/include/net/fastboot.h
> new file mode 100644
> index 0000000..c0dd033
> --- /dev/null
> +++ b/include/net/fastboot.h
> @@ -0,0 +1,27 @@
> +/* SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (C) 2016 The Android Open Source Project
> + */
> +
> +#ifndef __NET_FASTBOOT_H__
> +#define __NET_FASTBOOT_H__
> +
> +/**********************************************************************/
> +/*
> + *     Global functions and variables.
> + */
> +
> +/**
> + * Wait for incoming fastboot comands.
> + */
> +void fastboot_start_server(void);
> +/**
> + * Send an INFO packet during long commands
> + *
> + * @param msg: String describing the reason for waiting
> + */
> +void fastboot_send_info(const char *msg);
> +
> +/**********************************************************************/
> +
> +#endif /* __NET_FASTBOOT_H__ */
> diff --git a/net/Makefile b/net/Makefile
> index ce6e5ad..3489ce5 100644
> --- a/net/Makefile
> +++ b/net/Makefile
> @@ -25,6 +25,7 @@ obj-$(CONFIG_CMD_PING) += ping.o
>  obj-$(CONFIG_CMD_RARP) += rarp.o
>  obj-$(CONFIG_CMD_SNTP) += sntp.o
>  obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
> +obj-$(CONFIG_UDP_FUNCTION_FASTBOOT)  += fastboot.o
>
>  # Disable this warning as it is triggered by:
>  # sprintf(buf, index ? "foo%d" : "foo", index)
> diff --git a/net/fastboot.c b/net/fastboot.c
> new file mode 100644
> index 0000000..32cb581
> --- /dev/null
> +++ b/net/fastboot.c
> @@ -0,0 +1,542 @@
> +// 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 <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
> +
> +enum {
> +       FASTBOOT_ERROR = 0,
> +       FASTBOOT_QUERY = 1,
> +       FASTBOOT_INIT = 2,
> +       FASTBOOT_FASTBOOT = 3,
> +};
> +
> +struct __packed fastboot_header {
> +       uchar id;
> +       uchar flags;
> +       unsigned short seq;
> +};
> +
> +#define PACKET_SIZE 1024
> +#define FASTBOOT_HEADER_SIZE sizeof(struct fastboot_header)
> +#define DATA_SIZE (PACKET_SIZE - FASTBOOT_HEADER_SIZE)
> +#define FASTBOOT_VERSION "0.4"
> +
> +/* Sequence number sent for every packet */
> +static unsigned short fb_sequence_number = 1;
> +static const unsigned short fb_packet_size = PACKET_SIZE;
> +static const unsigned short fb_udp_version = 1;
> +
> +/* Keep track of last packet for resubmission */
> +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 fb_getvar(char *);
> +static void fb_download(char *, unsigned int, char *);
> +static void fb_flash(char *);
> +static void fb_erase(char *);
> +static void fb_continue(char *);
> +static void fb_reboot(char *);
> +static void boot_downloaded_image(void);
> +static void cleanup_command_data(void);
> +static void write_fb_response(const char *, const char *, char *);
> +
> +void fastboot_send_info(const char *msg)
> +{
> +       uchar *packet;
> +       uchar *packet_base;
> +       int len = 0;
> +       char response[FASTBOOT_RESPONSE_LEN] = {0};
> +
> +       struct fastboot_header fb_response_header = {
> +               .id = FASTBOOT_FASTBOOT,
> +               .flags = 0,
> +               .seq = htons(fb_sequence_number)
> +       };
> +       ++fb_sequence_number;
> +       packet = net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE;
> +       packet_base = packet;
> +
> +       /* Write headers */
> +       memcpy(packet, &fb_response_header, sizeof(fb_response_header));
> +       packet += sizeof(fb_response_header);
> +       /* Write response */
> +       write_fb_response("INFO", msg, response);
> +       memcpy(packet, response, strlen(response));
> +       packet += strlen(response);
> +
> +       len = packet - packet_base;
> +
> +       /* Save packet for retransmitting */
> +       last_packet_len = len;
> +       memcpy(last_packet, packet_base, last_packet_len);
> +
> +       net_send_udp_packet(net_server_ethaddr, fastboot_remote_ip,
> +                           fastboot_remote_port, fastboot_our_port, len);
> +}
> +
> +/**
> + * Constructs and sends a packet in response to received fastboot packet
> + *
> + * @param fb_header            Header for response packet
> + * @param fastboot_data        Pointer to received fastboot data
> + * @param fastboot_data_len    Length of received fastboot data
> + * @param retransmit           Nonzero if sending last sent packet
> + */
> +static void fastboot_send(struct fastboot_header fb_header, char
> *fastboot_data,
> +                         unsigned int fastboot_data_len, uchar retransmit)
> +{
> +       uchar *packet;
> +       uchar *packet_base;
> +       int len = 0;
> +       const char *error_msg = "An error occurred.";
> +       short tmp;
> +       struct fastboot_header fb_response_header = fb_header;
> +       char response[FASTBOOT_RESPONSE_LEN] = {0};
> +       /*
> +        *      We will always be sending some sort of packet, so
> +        *      cobble together the packet headers now.
> +        */
> +       packet = net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE;
> +       packet_base = packet;
> +
> +       /* Resend last packet */
> +       if (retransmit) {
> +               memcpy(packet, last_packet, last_packet_len);
> +               net_send_udp_packet(net_server_ethaddr, fastboot_remote_ip,
> +                                   fastboot_remote_port,
> fastboot_our_port,
> +                                   last_packet_len);
> +               return;
> +       }
> +
> +       fb_response_header.seq = htons(fb_response_header.seq);
> +       memcpy(packet, &fb_response_header, sizeof(fb_response_header));
> +       packet += sizeof(fb_response_header);
> +
> +       switch (fb_header.id) {
> +       case FASTBOOT_QUERY:
> +               tmp = htons(fb_sequence_number);
> +               memcpy(packet, &tmp, sizeof(tmp));
> +               packet += sizeof(tmp);
> +               break;
> +       case FASTBOOT_INIT:
> +               tmp = htons(fb_udp_version);
> +               memcpy(packet, &tmp, sizeof(tmp));
> +               packet += sizeof(tmp);
> +               tmp = htons(fb_packet_size);
> +               memcpy(packet, &tmp, sizeof(tmp));
> +               packet += sizeof(tmp);
> +               break;
> +       case FASTBOOT_ERROR:
> +               memcpy(packet, error_msg, strlen(error_msg));
> +               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 if (!strcmp("getvar", cmd_string)) {
> +                       fb_getvar(response);
> +               } else if (!strcmp("download", cmd_string)) {
> +                       fb_download(fastboot_data, fastboot_data_len,
> response);
> +               } else if (!strcmp("flash", cmd_string)) {
> +                       fb_flash(response);
> +               } else if (!strcmp("erase", cmd_string)) {
> +                       fb_erase(response);
> +               } else if (!strcmp("boot", cmd_string)) {
> +                       write_fb_response("OKAY", "", response);
> +               } else if (!strcmp("continue", cmd_string)) {
> +                       fb_continue(response);
> +               } else if (!strncmp("reboot", cmd_string, 6)) {
> +                       fb_reboot(response);
> +               } else if (!strcmp("set_active", cmd_string)) {
> +                       /* A/B not implemented, for now do nothing */
> +                       write_fb_response("OKAY", "", response);
> +               } else {
> +                       pr_err("command %s not implemented.\n",
> cmd_string);
> +                       write_fb_response("FAIL", "unrecognized command",
> +                                         response);
> +               }
> +               /* Sent some INFO packets, need to update sequence number
> in
> +                * header
> +                */
> +               if (fb_header.seq != fb_sequence_number) {
> +                       fb_response_header.seq = htons(fb_sequence_number);
> +                       memcpy(packet_base, &fb_response_header,
> +                              sizeof(fb_response_header));
> +               }
> +               /* Write response to packet */
> +               memcpy(packet, response, strlen(response));
> +               packet += strlen(response);
> +               break;
> +       default:
> +               pr_err("ID %d not implemented.\n", fb_header.id);
> +               return;
> +       }
> +
> +       len = packet - packet_base;
> +
> +       /* Save packet for retransmitting */
> +       last_packet_len = len;
> +       memcpy(last_packet, packet_base, last_packet_len);
> +
> +       net_send_udp_packet(net_server_ethaddr, fastboot_remote_ip,
> +                           fastboot_remote_port, fastboot_our_port, len);
> +
> +       /* Continue boot process after sending response */
> +       if (!strncmp("OKAY", response, 4)) {
> +               if (!strcmp("boot", cmd_string)) {
> +                       boot_downloaded_image();
> +               } else if (!strcmp("continue", cmd_string)) {
> +                       run_command(env_get("bootcmd"), CMD_FLAG_ENV);
> +               } else if (!strncmp("reboot", cmd_string, 6)) {
> +                       /* Matches reboot or 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();
> +}
> +
> +/**
> + * Writes ascii string specified by cmd_parameter to response.
> + *
> + * @param repsonse    Pointer to fastboot response buffer
> + */
> +static void fb_getvar(char *response)
> +{
> +       if (!cmd_parameter) {
> +               write_fb_response("FAIL", "missing var", response);
> +       } else if (!strcmp("version", cmd_parameter)) {
> +               write_fb_response("OKAY", FASTBOOT_VERSION, response);
> +       } else if (!strcmp("bootloader-version", cmd_parameter) ||
> +                  !strcmp("version-bootloader", cmd_parameter)) {
> +               write_fb_response("OKAY", U_BOOT_VERSION, response);
> +       } else if (!strcmp("downloadsize", cmd_parameter) ||
> +                  !strcmp("max-download-size", cmd_parameter)) {
> +               char buf_size_str[12];
> +
> +               sprintf(buf_size_str, "0x%08x", CONFIG_FASTBOOT_BUF_SIZE);
> +               write_fb_response("OKAY", buf_size_str, response);
> +       } else if (!strcmp("serialno", cmd_parameter)) {
> +               const char *tmp = env_get("serial#");
> +
> +               if (tmp)
> +                       write_fb_response("OKAY", tmp, response);
> +               else
> +                       write_fb_response("FAIL", "Value not set",
> response);
> +       } else if (!strcmp("version-baseband", cmd_parameter)) {
> +               write_fb_response("OKAY", "N/A", response);
> +       } else if (!strcmp("product", cmd_parameter)) {
> +               const char *board = env_get("board");
> +
> +               if (board)
> +                       write_fb_response("OKAY", board, response);
> +               else
> +                       write_fb_response("FAIL", "Board not set",
> response);
> +       } else if (!strcmp("current-slot", cmd_parameter)) {
> +               /* A/B not implemented, for now always return _a */
> +               write_fb_response("OKAY", "_a", response);
> +       } else if (!strcmp("slot-suffixes", cmd_parameter)) {
> +               write_fb_response("OKAY", "_a,_b", response);
> +       } else if (!strncmp("has-slot", cmd_parameter, 8)) {
> +               char *part_name = cmd_parameter;
> +
> +               cmd_parameter = strsep(&part_name, ":");
> +               if (!strcmp(part_name, "boot") || !strcmp(part_name,
> "system"))
> +                       write_fb_response("OKAY", "yes", response);
> +               else
> +                       write_fb_response("OKAY", "no", response);
> +       } else if (!strncmp("partition-type", cmd_parameter, 14) ||
> +                  !strncmp("partition-size", cmd_parameter, 14)) {
> +               disk_partition_t part_info;
> +               struct blk_desc *dev_desc;
> +               char *part_name = cmd_parameter;
> +               char part_size_str[20];
> +
> +               cmd_parameter = strsep(&part_name, ":");
> +               dev_desc = blk_get_dev("mmc", 0);
> +               if (!dev_desc) {
> +                       write_fb_response("FAIL", "block device not found",
> +                                         response);
> +               } else if (part_get_info_by_name(dev_desc, part_name,
> +                                                &part_info) < 0) {
> +                       write_fb_response("FAIL", "partition not found",
> +                                         response);
> +               } else if (!strncmp("partition-type", cmd_parameter, 14)) {
> +                       write_fb_response("OKAY", (char *)part_info.type,
> +                                         response);
> +               } else if (!strncmp("partition-size", cmd_parameter, 14)) {
> +                       sprintf(part_size_str, "0x%016x",
> (int)part_info.size);
> +                       write_fb_response("OKAY", part_size_str, response);
> +               }
> +       } else {
> +               printf("WARNING: unknown variable: %s\n", cmd_parameter);
> +               write_fb_response("FAIL", "Variable not implemented",
> +                                 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 fb_download(char *fastboot_data, unsigned int
> fastboot_data_len,
> +                       char *response)
> +{
> +       char *tmp;
> +
> +       if (bytes_expected == 0) {
> +               if (!cmd_parameter) {
> +                       write_fb_response("FAIL", "Expected command
> parameter",
> +                                         response);
> +                       return;
> +               }
> +               bytes_expected = simple_strtoul(cmd_parameter, &tmp, 16);
> +               if (bytes_expected == 0) {
> +                       write_fb_response("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)
> +                       write_fb_response("FAIL", cmd_parameter, response);
> +               else
> +                       write_fb_response("DATA", cmd_parameter, response);
> +       } else if (fastboot_data_len == 0 &&
> +                  (bytes_received >= bytes_expected)) {
> +               /* Download complete. Respond with "OKAY" */
> +               write_fb_response("OKAY", "", response);
> +               image_size = bytes_received;
> +               bytes_expected = 0;
> +               bytes_received = 0;
> +       } else {
> +               if (fastboot_data_len == 0 ||
> +                   (bytes_received + fastboot_data_len) > bytes_expected)
> {
> +                       write_fb_response("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;
> +       }
> +}
> +
> +/**
> + * Writes the previously downloaded image to the partition indicated by
> + * cmd_parameter. Writes to response.
> + *
> + * @param repsonse    Pointer to fastboot response buffer
> + */
> +static void fb_flash(char *response)
> +{
> +       fb_mmc_flash_write(cmd_parameter, (void *)CONFIG_FASTBOOT_BUF_ADDR,
> +                          image_size, response);
> +}
> +
> +/**
> + * Erases the partition indicated by cmd_parameter (clear to 0x00s).
> Writes
> + * to response.
> + *
> + * @param repsonse    Pointer to fastboot response buffer
> + */
> +static void fb_erase(char *response)
> +{
> +       fb_mmc_erase(cmd_parameter, response);
> +}
> +
> +/**
> + * Continues normal boot process by running "bootcmd". Writes
> + * to response.
> + *
> + * @param repsonse    Pointer to fastboot response buffer
> + */
> +static void fb_continue(char *response)
> +{
> +       char *bootcmd;
> +
> +       bootcmd = env_get("bootcmd");
> +       if (bootcmd)
> +               write_fb_response("OKAY", "", response);
> +       else
> +               write_fb_response("FAIL", "bootcmd not set", response);
> +}
> +
> +/**
> + * Sets reboot bootloader flag if requested. Writes to response.
> + *
> + * @param repsonse    Pointer to fastboot response buffer
> + */
> +static void fb_reboot(char *response)
> +{
> +       write_fb_response("OKAY", "", response);
> +       if (!strcmp("reboot-bootloader", cmd_string))
> +               strcpy((char *)CONFIG_FASTBOOT_BUF_ADDR,
> "reboot-bootloader");
> +}
> +
> +/**
> + * Boots into downloaded image.
> + */
> +static void boot_downloaded_image(void)
> +{
> +       char kernel_addr[12];
> +       char *fdt_addr = env_get("fdt_addr_r");
> +       char *const bootm_args[] = {
> +               "bootm", kernel_addr, "-", fdt_addr, NULL
> +       };
> +
> +       sprintf(kernel_addr, "0x%lx", (long)CONFIG_FASTBOOT_BUF_ADDR);
> +
> +       printf("\nBooting kernel at %s with fdt at %s...\n\n\n",
> +              kernel_addr, fdt_addr);
> +       do_bootm(NULL, 0, 4, bootm_args);
> +
> +       /* This only happens if image is faulty so we start over. */
> +       do_reset(NULL, 0, 0, NULL);
> +}
> +
> +/**
> + * Writes a response to response buffer of the form "$tag$reason".
> + *
> + * @param tag         The first part of the response
> + * @param reason      The second part of the response
> + * @param repsonse    Pointer to fastboot response buffer
> + */
> +static void write_fb_response(const char *tag, const char *reason,
> +                             char *response)
> +{
> +       strncpy(response, tag, strlen(tag));
> +       strncat(response, reason, FASTBOOT_RESPONSE_LEN - strlen(tag) - 1);
> +}
> +
> +/**
> + * 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
> + * @param dport   Destination UDP port
> + * @param sip     Source IP address
> + * @param sport   Source UDP port
> + * @param len     Packet length
> + */
> +static void fastboot_handler(uchar *packet, unsigned int dport,
> +                            struct in_addr sip, unsigned int sport,
> +                            unsigned int len)
> +{
> +       struct fastboot_header fb_header;
> +       char fastboot_data[DATA_SIZE] = {0};
> +       unsigned int fastboot_data_len = 0;
> +
> +       if (dport != fastboot_our_port)
> +               return;
> +
> +       fastboot_remote_ip = sip;
> +       fastboot_remote_port = sport;
> +
> +       if (len < FASTBOOT_HEADER_SIZE || len > PACKET_SIZE)
> +               return;
> +       memcpy(&fb_header, packet, sizeof(fb_header));
> +       fb_header.flags = 0;
> +       fb_header.seq = ntohs(fb_header.seq);
> +       packet += sizeof(fb_header);
> +       len -= sizeof(fb_header);
> +
> +       switch (fb_header.id) {
> +       case FASTBOOT_QUERY:
> +               fastboot_send(fb_header, fastboot_data, 0, 0);
> +               break;
> +       case FASTBOOT_INIT:
> +       case FASTBOOT_FASTBOOT:
> +               fastboot_data_len = len;
> +               if (len > 0)
> +                       memcpy(fastboot_data, packet, len);
> +               if (fb_header.seq == fb_sequence_number) {
> +                       fastboot_send(fb_header, fastboot_data,
> +                                     fastboot_data_len, 0);
> +                       fb_sequence_number++;
> +               } else if (fb_header.seq == fb_sequence_number - 1) {
> +                       /* Retransmit last sent packet */
> +                       fastboot_send(fb_header, fastboot_data,
> +                                     fastboot_data_len, 1);
> +               }
> +               break;
> +       default:
> +               pr_err("ID %d not implemented.\n", fb_header.id);
> +               fb_header.id = FASTBOOT_ERROR;
> +               fastboot_send(fb_header, fastboot_data, 0, 0);
> +               break;
> +       }
> +}
> +
> +void fastboot_start_server(void)
> +{
> +       printf("Using %s device\n", eth_get_name());
> +       printf("Listening for fastboot command on %pI4\n", &net_ip);
> +
> +       fastboot_our_port = WELL_KNOWN_PORT;
> +
> +       net_set_udp_handler(fastboot_handler);
> +
> +       /* zero out server ether in case the server ip has changed */
> +       memset(net_server_ethaddr, 0, 6);
> +}
> diff --git a/net/net.c b/net/net.c
> index d222c1f..554df7a 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -87,6 +87,9 @@
>  #include <environment.h>
>  #include <errno.h>
>  #include <net.h>
> +#if defined(CONFIG_UDP_FUNCTION_FASTBOOT)
> +#include <net/fastboot.h>
> +#endif
>  #include <net/tftp.h>
>  #if defined(CONFIG_LED_STATUS)
>  #include <miiphy.h>
> @@ -451,6 +454,11 @@ restart:
>                         tftp_start_server();
>                         break;
>  #endif
> +#ifdef CONFIG_UDP_FUNCTION_FASTBOOT
> +               case FASTBOOT:
> +                       fastboot_start_server();
> +                       break;
> +#endif
>  #if defined(CONFIG_CMD_DHCP)
>                 case DHCP:
>                         bootp_reset();
> @@ -1322,6 +1330,7 @@ common:
>                 /* Fall through */
>
>         case NETCONS:
> +       case FASTBOOT:
>         case TFTPSRV:
>                 if (net_ip.s_addr == 0) {
>                         puts("*** ERROR: `ipaddr' not set\n");
> --
> 2.7.4
>
>
 Signed-off-by: Jocelyn Bohr <bohr@google.com>

  reply	other threads:[~2018-05-01  6:28 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-04-30  8:32 [U-Boot] [RFC PATCH v2 00/20] Add fastboot UDP support Alex Kiernan
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 01/20] fastboot: Move fastboot to drivers/fastboot Alex Kiernan
2018-04-30 23:12   ` Simon Glass
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 02/20] fastboot: Switch dependencies on FASTBOOT to USB_FUNCTION_FASTBOOT Alex Kiernan
2018-05-03 18:19   ` Joe Hershberger
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 03/20] fastboot: Refactor fastboot_okay/fail to take response Alex Kiernan
2018-05-03 18:24   ` Joe Hershberger
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 04/20] fastboot: Extract fastboot_okay/fail to fb_common.c Alex Kiernan
2018-05-03 18:26   ` Joe Hershberger
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 05/20] fastboot: Introduce fastboot_response and refactor fastboot_okay/fail Alex Kiernan
2018-05-03 18:28   ` Joe Hershberger
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 06/20] fastboot: Correct dependencies in FASTBOOT_FLASH Alex Kiernan
2018-05-03 18:34   ` Joe Hershberger
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 07/20] net: fastboot: Merge AOSP UDP fastboot Alex Kiernan
2018-05-01  6:28   ` Jocelyn Bohr [this message]
2018-05-03 20:38   ` Joe Hershberger
2018-05-08  9:11     ` Alex Kiernan
2018-05-08 15:24       ` Joe Hershberger
2018-05-08 15:51         ` Alex Kiernan
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 08/20] net: fastboot: Support building without MMC Alex Kiernan
2018-05-03 20:39   ` Joe Hershberger
2018-05-04  6:06     ` Jocelyn Bohr
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 09/20] fastboot: Refactor write_fb_response into fastboot_okay/fail/response Alex Kiernan
2018-05-03 20:48   ` Joe Hershberger
2018-05-04  6:00     ` Jocelyn Bohr
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 10/20] fastboot: Merge USB and UDP getvar implementation Alex Kiernan
2018-05-03 20:56   ` Joe Hershberger
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 11/20] fastboot: net: Change 'continue' so it matches USB fastboot Alex Kiernan
2018-05-03 20:58   ` Joe Hershberger
2018-05-04  6:18     ` Jocelyn Bohr
2018-05-08  9:20     ` Alex Kiernan
2018-05-08 15:32       ` Joe Hershberger
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 12/20] fastboot: net: Convert command lookup to a table Alex Kiernan
2018-05-03 21:08   ` Joe Hershberger
2018-05-04  9:14     ` Alex Kiernan
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 13/20] fastboot: Merge reboot-bootloader handling Alex Kiernan
2018-05-01  6:49   ` Jocelyn Bohr
2018-05-01  7:23     ` Alex Kiernan
2018-05-01  8:21       ` Alex Kiernan
2018-05-02  5:46         ` Jocelyn Bohr
2018-05-02  5:51           ` Jocelyn Bohr
2018-05-02  8:24             ` Alex Kiernan
2018-05-03 21:15   ` Joe Hershberger
2018-05-04  7:34     ` Alex Kiernan
2018-05-04  7:44       ` Joe Hershberger
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 14/20] fastboot: Avoid re-parsing cmd_string for boot/reboot Alex Kiernan
2018-05-03 21:17   ` Joe Hershberger
2018-05-07 21:20     ` Jocelyn Bohr
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 15/20] fastboot: Merge boot common across USB and UDP Alex Kiernan
2018-05-03 21:21   ` Joe Hershberger
2018-05-07 21:59     ` Jocelyn Bohr
2018-05-08  6:08       ` Joe Hershberger
2018-05-08  6:54         ` Alex Kiernan
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 16/20] fastboot: net: Add NAND support Alex Kiernan
2018-05-03 21:24   ` Joe Hershberger
2018-05-08 16:38     ` Jocelyn Bohr
2018-05-08  6:53   ` Jocelyn Bohr
2018-05-08  7:19     ` Joe Hershberger
2018-05-08  9:09       ` Alex Kiernan
2018-05-08 16:37         ` Jocelyn Bohr
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 17/20] fastboot: Guard getvar:partition-type/size with MMC Alex Kiernan
2018-05-03 21:26   ` Joe Hershberger
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 18/20] fastboot: Check if part_name is NULL before using it Alex Kiernan
2018-05-03 21:26   ` Joe Hershberger
2018-05-08  6:55     ` Jocelyn Bohr
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 19/20] fastboot: Add missing newlines Alex Kiernan
2018-05-03 21:26   ` Joe Hershberger
2018-05-08  6:56     ` Jocelyn Bohr
2018-04-30  8:32 ` [U-Boot] [RFC PATCH v2 20/20] fastboot: net: Split fastboot protocol out from net Alex Kiernan
2018-05-03 21:29   ` Joe Hershberger
2018-05-04  6:05     ` Alex Kiernan
2018-05-02  6:33 ` [U-Boot] [RFC PATCH v2 00/20] Add fastboot UDP support Jocelyn Bohr
2018-05-02  8:14   ` Alex Kiernan
2018-05-08  7:13     ` Jocelyn Bohr

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAPJEgOFUrhCqhELEVbg41uGdAcd4uPXD=wN0GfY6Na5a+pGCHA@mail.gmail.com' \
    --to=bohr@google.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.