diff mbox series

[U-Boot,v3,13/13] net: fastboot: Merge AOSP UDP fastboot

Message ID 1526288948-24977-14-git-send-email-alex.kiernan@gmail.com
State Superseded
Delegated to: Joe Hershberger
Headers show
Series Add fastboot UDP support | expand

Commit Message

Alex Kiernan May 14, 2018, 9:09 a.m. UTC
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>
Signed-off-by: Jocelyn Bohr <bohr@google.com>
---

Changes in v3:
- use FASTBOOT as our guard in Kconfig not a list of USB || UDP
- correct mis-translation from AOSP introduced when cleaning up for
  checkpatch - we should write when buffer is not NULL, rather than
  erasing, and erase when buffer is NULL
- use CMD_RET_USAGE from do_fastboot
- remove do_fastboot_udp from cmd/net.c and rewrite using net_loop()
- rename timed_send_info to fastboot_send_info, rename fastboot_send_info to
  fastboot_udp_send_info
- replace FASTBOOT_HEADER_SIZE with sizeof(struct fastboot_header)
- move start time into timed_send_info() rather than passing it in
- make calls to fastboot_udp_send_info a runtime dependency, not a compile
  time one
- set ${filesize} to size of downloaded image
- add progress meter from USB path during download
- add support for 'oem format' command from the USB path
- rename 'fastbootcmd' to 'fastboot_bootcmd' to make clear that this is the
  fastboot boot command
- make getvar implementation table driven
- add fastboot_buf_addr, fastboot_buf_size to override buffer address and
  size
- return correct filesystem type in getvar partition-type on MMC
- process "fastboot." prefixed env variables in getvar first so you
  can override the normal values (this also lets you set a fs type for
  NAND devices)
- squash subsequent patches which change this code into this one:
  - If the fastboot flash/erase commands are disabled, remove that support
    so we still build correctly.
  - Add NAND support to fastboot UDP flash/erase commands
  - If we don't have a partition name passed, report it as not found.
  - Change the behaviour of the fastboot net code such that
    "reboot-bootloader" is no longer written to CONFIG_FASTBOOT_BUF_ADDR for
    use as a marker on reboot (the AOSP code in common/android-bootloader.c
    uses this marker - this code could be reinstated there if that gets
    merged).
  - Merge USB and UDP boot code. The USB implementation stays the same, but
    UDP no longer passes an fdt. We introduce a new environment variable
    'fastboot_bootcmd' which if set overrides the hardcoded boot command,
    setting this then allows the UDP implementation to remain the same. If
    after running 'fastboot_bootcmd' the board has not booted, control is
    returned to U-Boot and the fastboot process ends.
  - Separate the fastboot protocol handling from the fastboot UDP code in
    preparation for reusing it in the USB code.

Changes in v2:
- ensure fastboot syntax is backward compatible - 'fastboot 0' means
  'fastboot usb 0'

 cmd/fastboot.c                |  91 ++++++++++++-
 drivers/fastboot/Kconfig      |  15 ++
 drivers/fastboot/Makefile     |   2 +
 drivers/fastboot/fb_command.c | 258 +++++++++++++++++++++++++++++++++++
 drivers/fastboot/fb_common.c  |  48 +++++++
 drivers/fastboot/fb_getvar.c  | 222 ++++++++++++++++++++++++++++++
 drivers/fastboot/fb_mmc.c     |  67 ++++++++-
 drivers/fastboot/fb_nand.c    |  12 +-
 include/fastboot.h            |  47 +++++++
 include/fb_mmc.h              |   8 +-
 include/fb_nand.h             |  10 +-
 include/net.h                 |   2 +-
 include/net/fastboot.h        |  21 +++
 net/Makefile                  |   1 +
 net/fastboot.c                | 310 ++++++++++++++++++++++++++++++++++++++++++
 net/net.c                     |   7 +
 16 files changed, 1105 insertions(+), 16 deletions(-)
 create mode 100644 drivers/fastboot/fb_command.c
 create mode 100644 drivers/fastboot/fb_getvar.c
 create mode 100644 include/net/fastboot.h
 create mode 100644 net/fastboot.c

Comments

Simon Glass May 14, 2018, 7:53 p.m. UTC | #1
Hi Alex,

On 14 May 2018 at 03:09, 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>
> Signed-off-by: Jocelyn Bohr <bohr@google.com>
> ---
>
> Changes in v3:
> - use FASTBOOT as our guard in Kconfig not a list of USB || UDP
> - correct mis-translation from AOSP introduced when cleaning up for
>   checkpatch - we should write when buffer is not NULL, rather than
>   erasing, and erase when buffer is NULL
> - use CMD_RET_USAGE from do_fastboot
> - remove do_fastboot_udp from cmd/net.c and rewrite using net_loop()
> - rename timed_send_info to fastboot_send_info, rename fastboot_send_info to
>   fastboot_udp_send_info
> - replace FASTBOOT_HEADER_SIZE with sizeof(struct fastboot_header)
> - move start time into timed_send_info() rather than passing it in
> - make calls to fastboot_udp_send_info a runtime dependency, not a compile
>   time one
> - set ${filesize} to size of downloaded image
> - add progress meter from USB path during download
> - add support for 'oem format' command from the USB path
> - rename 'fastbootcmd' to 'fastboot_bootcmd' to make clear that this is the
>   fastboot boot command
> - make getvar implementation table driven
> - add fastboot_buf_addr, fastboot_buf_size to override buffer address and
>   size
> - return correct filesystem type in getvar partition-type on MMC
> - process "fastboot." prefixed env variables in getvar first so you
>   can override the normal values (this also lets you set a fs type for
>   NAND devices)
> - squash subsequent patches which change this code into this one:
>   - If the fastboot flash/erase commands are disabled, remove that support
>     so we still build correctly.
>   - Add NAND support to fastboot UDP flash/erase commands
>   - If we don't have a partition name passed, report it as not found.
>   - Change the behaviour of the fastboot net code such that
>     "reboot-bootloader" is no longer written to CONFIG_FASTBOOT_BUF_ADDR for
>     use as a marker on reboot (the AOSP code in common/android-bootloader.c
>     uses this marker - this code could be reinstated there if that gets
>     merged).
>   - Merge USB and UDP boot code. The USB implementation stays the same, but
>     UDP no longer passes an fdt. We introduce a new environment variable
>     'fastboot_bootcmd' which if set overrides the hardcoded boot command,
>     setting this then allows the UDP implementation to remain the same. If
>     after running 'fastboot_bootcmd' the board has not booted, control is
>     returned to U-Boot and the fastboot process ends.
>   - Separate the fastboot protocol handling from the fastboot UDP code in
>     preparation for reusing it in the USB code.
>
> Changes in v2:
> - ensure fastboot syntax is backward compatible - 'fastboot 0' means
>   'fastboot usb 0'
>
>  cmd/fastboot.c                |  91 ++++++++++++-
>  drivers/fastboot/Kconfig      |  15 ++
>  drivers/fastboot/Makefile     |   2 +
>  drivers/fastboot/fb_command.c | 258 +++++++++++++++++++++++++++++++++++
>  drivers/fastboot/fb_common.c  |  48 +++++++
>  drivers/fastboot/fb_getvar.c  | 222 ++++++++++++++++++++++++++++++
>  drivers/fastboot/fb_mmc.c     |  67 ++++++++-
>  drivers/fastboot/fb_nand.c    |  12 +-
>  include/fastboot.h            |  47 +++++++
>  include/fb_mmc.h              |   8 +-
>  include/fb_nand.h             |  10 +-
>  include/net.h                 |   2 +-
>  include/net/fastboot.h        |  21 +++
>  net/Makefile                  |   1 +
>  net/fastboot.c                | 310 ++++++++++++++++++++++++++++++++++++++++++
>  net/net.c                     |   7 +
>  16 files changed, 1105 insertions(+), 16 deletions(-)
>  create mode 100644 drivers/fastboot/fb_command.c
>  create mode 100644 drivers/fastboot/fb_getvar.c
>  create mode 100644 include/net/fastboot.h
>  create mode 100644 net/fastboot.c

Reviewed-by: Simon Glass <sjg@chromium.org>

Please can you add function comments to the rest of the fastboot.h
stuff, see if you can remove the global variables in that file, and
also add function comments to non-trivial static functions?

Regards,
Simon
Alex Kiernan May 14, 2018, 9:11 p.m. UTC | #2
On Mon, May 14, 2018 at 8:53 PM Simon Glass <sjg@chromium.org> wrote:

> Hi Alex,

> On 14 May 2018 at 03:09, 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>
> > Signed-off-by: Jocelyn Bohr <bohr@google.com>
> > ---
> >
> > Changes in v3:
> > - use FASTBOOT as our guard in Kconfig not a list of USB || UDP
> > - correct mis-translation from AOSP introduced when cleaning up for
> >   checkpatch - we should write when buffer is not NULL, rather than
> >   erasing, and erase when buffer is NULL
> > - use CMD_RET_USAGE from do_fastboot
> > - remove do_fastboot_udp from cmd/net.c and rewrite using net_loop()
> > - rename timed_send_info to fastboot_send_info, rename
fastboot_send_info to
> >   fastboot_udp_send_info
> > - replace FASTBOOT_HEADER_SIZE with sizeof(struct fastboot_header)
> > - move start time into timed_send_info() rather than passing it in
> > - make calls to fastboot_udp_send_info a runtime dependency, not a
compile
> >   time one
> > - set ${filesize} to size of downloaded image
> > - add progress meter from USB path during download
> > - add support for 'oem format' command from the USB path
> > - rename 'fastbootcmd' to 'fastboot_bootcmd' to make clear that this is
the
> >   fastboot boot command
> > - make getvar implementation table driven
> > - add fastboot_buf_addr, fastboot_buf_size to override buffer address
and
> >   size
> > - return correct filesystem type in getvar partition-type on MMC
> > - process "fastboot." prefixed env variables in getvar first so you
> >   can override the normal values (this also lets you set a fs type for
> >   NAND devices)
> > - squash subsequent patches which change this code into this one:
> >   - If the fastboot flash/erase commands are disabled, remove that
support
> >     so we still build correctly.
> >   - Add NAND support to fastboot UDP flash/erase commands
> >   - If we don't have a partition name passed, report it as not found.
> >   - Change the behaviour of the fastboot net code such that
> >     "reboot-bootloader" is no longer written to
CONFIG_FASTBOOT_BUF_ADDR for
> >     use as a marker on reboot (the AOSP code in
common/android-bootloader.c
> >     uses this marker - this code could be reinstated there if that gets
> >     merged).
> >   - Merge USB and UDP boot code. The USB implementation stays the same,
but
> >     UDP no longer passes an fdt. We introduce a new environment variable
> >     'fastboot_bootcmd' which if set overrides the hardcoded boot
command,
> >     setting this then allows the UDP implementation to remain the same.
If
> >     after running 'fastboot_bootcmd' the board has not booted, control
is
> >     returned to U-Boot and the fastboot process ends.
> >   - Separate the fastboot protocol handling from the fastboot UDP code
in
> >     preparation for reusing it in the USB code.
> >
> > Changes in v2:
> > - ensure fastboot syntax is backward compatible - 'fastboot 0' means
> >   'fastboot usb 0'
> >
> >  cmd/fastboot.c                |  91 ++++++++++++-
> >  drivers/fastboot/Kconfig      |  15 ++
> >  drivers/fastboot/Makefile     |   2 +
> >  drivers/fastboot/fb_command.c | 258 +++++++++++++++++++++++++++++++++++
> >  drivers/fastboot/fb_common.c  |  48 +++++++
> >  drivers/fastboot/fb_getvar.c  | 222 ++++++++++++++++++++++++++++++
> >  drivers/fastboot/fb_mmc.c     |  67 ++++++++-
> >  drivers/fastboot/fb_nand.c    |  12 +-
> >  include/fastboot.h            |  47 +++++++
> >  include/fb_mmc.h              |   8 +-
> >  include/fb_nand.h             |  10 +-
> >  include/net.h                 |   2 +-
> >  include/net/fastboot.h        |  21 +++
> >  net/Makefile                  |   1 +
> >  net/fastboot.c                | 310
++++++++++++++++++++++++++++++++++++++++++
> >  net/net.c                     |   7 +
> >  16 files changed, 1105 insertions(+), 16 deletions(-)
> >  create mode 100644 drivers/fastboot/fb_command.c
> >  create mode 100644 drivers/fastboot/fb_getvar.c
> >  create mode 100644 include/net/fastboot.h
> >  create mode 100644 net/fastboot.c

> Reviewed-by: Simon Glass <sjg@chromium.org>

> Please can you add function comments to the rest of the fastboot.h
> stuff, see if you can remove the global variables in that file, and
> also add function comments to non-trivial static functions?


Will do... I don't think I can easily make the remaining globals go away,
but I can certainly put them behind accessor functions.

--
Alex Kiernan
Simon Glass May 15, 2018, 4:05 p.m. UTC | #3
Hi Alex,

On 15 May 2018 at 07:11, Alex Kiernan <alex.kiernan@gmail.com> wrote:
> On Mon, May 14, 2018 at 8:53 PM Simon Glass <sjg@chromium.org> wrote:
>
>> Hi Alex,
>
>> On 14 May 2018 at 03:09, 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>
>> > Signed-off-by: Jocelyn Bohr <bohr@google.com>
>> > ---
>> >
>> > Changes in v3:
>> > - use FASTBOOT as our guard in Kconfig not a list of USB || UDP
>> > - correct mis-translation from AOSP introduced when cleaning up for
>> >   checkpatch - we should write when buffer is not NULL, rather than
>> >   erasing, and erase when buffer is NULL
>> > - use CMD_RET_USAGE from do_fastboot
>> > - remove do_fastboot_udp from cmd/net.c and rewrite using net_loop()
>> > - rename timed_send_info to fastboot_send_info, rename
> fastboot_send_info to
>> >   fastboot_udp_send_info
>> > - replace FASTBOOT_HEADER_SIZE with sizeof(struct fastboot_header)
>> > - move start time into timed_send_info() rather than passing it in
>> > - make calls to fastboot_udp_send_info a runtime dependency, not a
> compile
>> >   time one
>> > - set ${filesize} to size of downloaded image
>> > - add progress meter from USB path during download
>> > - add support for 'oem format' command from the USB path
>> > - rename 'fastbootcmd' to 'fastboot_bootcmd' to make clear that this is
> the
>> >   fastboot boot command
>> > - make getvar implementation table driven
>> > - add fastboot_buf_addr, fastboot_buf_size to override buffer address
> and
>> >   size
>> > - return correct filesystem type in getvar partition-type on MMC
>> > - process "fastboot." prefixed env variables in getvar first so you
>> >   can override the normal values (this also lets you set a fs type for
>> >   NAND devices)
>> > - squash subsequent patches which change this code into this one:
>> >   - If the fastboot flash/erase commands are disabled, remove that
> support
>> >     so we still build correctly.
>> >   - Add NAND support to fastboot UDP flash/erase commands
>> >   - If we don't have a partition name passed, report it as not found.
>> >   - Change the behaviour of the fastboot net code such that
>> >     "reboot-bootloader" is no longer written to
> CONFIG_FASTBOOT_BUF_ADDR for
>> >     use as a marker on reboot (the AOSP code in
> common/android-bootloader.c
>> >     uses this marker - this code could be reinstated there if that gets
>> >     merged).
>> >   - Merge USB and UDP boot code. The USB implementation stays the same,
> but
>> >     UDP no longer passes an fdt. We introduce a new environment variable
>> >     'fastboot_bootcmd' which if set overrides the hardcoded boot
> command,
>> >     setting this then allows the UDP implementation to remain the same.
> If
>> >     after running 'fastboot_bootcmd' the board has not booted, control
> is
>> >     returned to U-Boot and the fastboot process ends.
>> >   - Separate the fastboot protocol handling from the fastboot UDP code
> in
>> >     preparation for reusing it in the USB code.
>> >
>> > Changes in v2:
>> > - ensure fastboot syntax is backward compatible - 'fastboot 0' means
>> >   'fastboot usb 0'
>> >
>> >  cmd/fastboot.c                |  91 ++++++++++++-
>> >  drivers/fastboot/Kconfig      |  15 ++
>> >  drivers/fastboot/Makefile     |   2 +
>> >  drivers/fastboot/fb_command.c | 258 +++++++++++++++++++++++++++++++++++
>> >  drivers/fastboot/fb_common.c  |  48 +++++++
>> >  drivers/fastboot/fb_getvar.c  | 222 ++++++++++++++++++++++++++++++
>> >  drivers/fastboot/fb_mmc.c     |  67 ++++++++-
>> >  drivers/fastboot/fb_nand.c    |  12 +-
>> >  include/fastboot.h            |  47 +++++++
>> >  include/fb_mmc.h              |   8 +-
>> >  include/fb_nand.h             |  10 +-
>> >  include/net.h                 |   2 +-
>> >  include/net/fastboot.h        |  21 +++
>> >  net/Makefile                  |   1 +
>> >  net/fastboot.c                | 310
> ++++++++++++++++++++++++++++++++++++++++++
>> >  net/net.c                     |   7 +
>> >  16 files changed, 1105 insertions(+), 16 deletions(-)
>> >  create mode 100644 drivers/fastboot/fb_command.c
>> >  create mode 100644 drivers/fastboot/fb_getvar.c
>> >  create mode 100644 include/net/fastboot.h
>> >  create mode 100644 net/fastboot.c
>
>> Reviewed-by: Simon Glass <sjg@chromium.org>
>
>> Please can you add function comments to the rest of the fastboot.h
>> stuff, see if you can remove the global variables in that file, and
>> also add function comments to non-trivial static functions?
>
>
> Will do... I don't think I can easily make the remaining globals go away,
> but I can certainly put them behind accessor functions.

If you can't make them go away, or put them in a struct, then I don't
think you should bother with accessor function, which just mess up the
code IMO.

Regards,
Simon
Alex Kiernan May 16, 2018, 3:37 p.m. UTC | #4
On Tue, May 15, 2018 at 5:05 PM Simon Glass <sjg@chromium.org> wrote:

> Hi Alex,

> On 15 May 2018 at 07:11, Alex Kiernan <alex.kiernan@gmail.com> wrote:
> > On Mon, May 14, 2018 at 8:53 PM Simon Glass <sjg@chromium.org> wrote:
> >
> >> Hi Alex,
> >
> >> On 14 May 2018 at 03:09, 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>
> >> > Signed-off-by: Jocelyn Bohr <bohr@google.com>
> >> > ---
> >> >
> >> > Changes in v3:
> >> > - use FASTBOOT as our guard in Kconfig not a list of USB || UDP
> >> > - correct mis-translation from AOSP introduced when cleaning up for
> >> >   checkpatch - we should write when buffer is not NULL, rather than
> >> >   erasing, and erase when buffer is NULL
> >> > - use CMD_RET_USAGE from do_fastboot
> >> > - remove do_fastboot_udp from cmd/net.c and rewrite using net_loop()
> >> > - rename timed_send_info to fastboot_send_info, rename
> > fastboot_send_info to
> >> >   fastboot_udp_send_info
> >> > - replace FASTBOOT_HEADER_SIZE with sizeof(struct fastboot_header)
> >> > - move start time into timed_send_info() rather than passing it in
> >> > - make calls to fastboot_udp_send_info a runtime dependency, not a
> > compile
> >> >   time one
> >> > - set ${filesize} to size of downloaded image
> >> > - add progress meter from USB path during download
> >> > - add support for 'oem format' command from the USB path
> >> > - rename 'fastbootcmd' to 'fastboot_bootcmd' to make clear that this
is
> > the
> >> >   fastboot boot command
> >> > - make getvar implementation table driven
> >> > - add fastboot_buf_addr, fastboot_buf_size to override buffer address
> > and
> >> >   size
> >> > - return correct filesystem type in getvar partition-type on MMC
> >> > - process "fastboot." prefixed env variables in getvar first so you
> >> >   can override the normal values (this also lets you set a fs type
for
> >> >   NAND devices)
> >> > - squash subsequent patches which change this code into this one:
> >> >   - If the fastboot flash/erase commands are disabled, remove that
> > support
> >> >     so we still build correctly.
> >> >   - Add NAND support to fastboot UDP flash/erase commands
> >> >   - If we don't have a partition name passed, report it as not found.
> >> >   - Change the behaviour of the fastboot net code such that
> >> >     "reboot-bootloader" is no longer written to
> > CONFIG_FASTBOOT_BUF_ADDR for
> >> >     use as a marker on reboot (the AOSP code in
> > common/android-bootloader.c
> >> >     uses this marker - this code could be reinstated there if that
gets
> >> >     merged).
> >> >   - Merge USB and UDP boot code. The USB implementation stays the
same,
> > but
> >> >     UDP no longer passes an fdt. We introduce a new environment
variable
> >> >     'fastboot_bootcmd' which if set overrides the hardcoded boot
> > command,
> >> >     setting this then allows the UDP implementation to remain the
same.
> > If
> >> >     after running 'fastboot_bootcmd' the board has not booted,
control
> > is
> >> >     returned to U-Boot and the fastboot process ends.
> >> >   - Separate the fastboot protocol handling from the fastboot UDP
code
> > in
> >> >     preparation for reusing it in the USB code.
> >> >
> >> > Changes in v2:
> >> > - ensure fastboot syntax is backward compatible - 'fastboot 0' means
> >> >   'fastboot usb 0'
> >> >
> >> >  cmd/fastboot.c                |  91 ++++++++++++-
> >> >  drivers/fastboot/Kconfig      |  15 ++
> >> >  drivers/fastboot/Makefile     |   2 +
> >> >  drivers/fastboot/fb_command.c | 258
+++++++++++++++++++++++++++++++++++
> >> >  drivers/fastboot/fb_common.c  |  48 +++++++
> >> >  drivers/fastboot/fb_getvar.c  | 222 ++++++++++++++++++++++++++++++
> >> >  drivers/fastboot/fb_mmc.c     |  67 ++++++++-
> >> >  drivers/fastboot/fb_nand.c    |  12 +-
> >> >  include/fastboot.h            |  47 +++++++
> >> >  include/fb_mmc.h              |   8 +-
> >> >  include/fb_nand.h             |  10 +-
> >> >  include/net.h                 |   2 +-
> >> >  include/net/fastboot.h        |  21 +++
> >> >  net/Makefile                  |   1 +
> >> >  net/fastboot.c                | 310
> > ++++++++++++++++++++++++++++++++++++++++++
> >> >  net/net.c                     |   7 +
> >> >  16 files changed, 1105 insertions(+), 16 deletions(-)
> >> >  create mode 100644 drivers/fastboot/fb_command.c
> >> >  create mode 100644 drivers/fastboot/fb_getvar.c
> >> >  create mode 100644 include/net/fastboot.h
> >> >  create mode 100644 net/fastboot.c
> >
> >> Reviewed-by: Simon Glass <sjg@chromium.org>
> >
> >> Please can you add function comments to the rest of the fastboot.h
> >> stuff, see if you can remove the global variables in that file, and
> >> also add function comments to non-trivial static functions?
> >
> >
> > Will do... I don't think I can easily make the remaining globals go
away,
> > but I can certainly put them behind accessor functions.

> If you can't make them go away, or put them in a struct, then I don't
> think you should bother with accessor function, which just mess up the
> code IMO.

So it was a worthwhile exercise to go through it again... I got two more of
the globals into statics (and a function to return the amount of data we
still expect to transfer), which left the buffer address, buffer size, and
the progress callback to keep the protocol alive, all of which are only
used inside drivers/fastboot itself, which I'll move to a
fastboot-internal.h


--
Alex Kiernan
diff mbox series

Patch

diff --git a/cmd/fastboot.c b/cmd/fastboot.c
index a5ec5f4..557257a 100644
--- a/cmd/fastboot.c
+++ b/cmd/fastboot.c
@@ -10,10 +10,32 @@ 
 #include <command.h>
 #include <console.h>
 #include <g_dnl.h>
+#include <fastboot.h>
+#include <net.h>
 #include <usb.h>
 
-static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+static int do_fastboot_udp(int argc, char *const argv[],
+			   uintptr_t buf_addr, size_t buf_size)
 {
+#if CONFIG_IS_ENABLED(UDP_FUNCTION_FASTBOOT)
+	int err = net_loop(FASTBOOT);
+
+	if (err < 0) {
+		printf("fastboot udp error: %d\n", err);
+		return CMD_RET_FAILURE;
+	}
+
+	return CMD_RET_SUCCESS;
+#else
+	pr_err("Fastboot UDP not enabled\n");
+	return CMD_RET_FAILURE;
+#endif
+}
+
+static int do_fastboot_usb(int argc, char *const argv[],
+			   uintptr_t buf_addr, size_t buf_size)
+{
+#if CONFIG_IS_ENABLED(USB_FUNCTION_FASTBOOT)
 	int controller_index;
 	char *usb_controller;
 	int ret;
@@ -58,11 +80,70 @@  exit:
 	board_usb_cleanup(controller_index, USB_INIT_DEVICE);
 
 	return ret;
+#else
+	pr_err("Fastboot USB not enabled\n");
+	return CMD_RET_FAILURE;
+#endif
+}
+
+static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	uintptr_t buf_addr = (uintptr_t)NULL;
+	size_t buf_size = 0;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	while (argc > 1 && **(argv + 1) == '-') {
+		char *arg = *++argv;
+
+		--argc;
+		while (*++arg) {
+			switch (*arg) {
+			case 'l':
+				if (--argc <= 0)
+					return CMD_RET_USAGE;
+				buf_addr = simple_strtoul(*++argv, NULL, 16);
+				goto NXTARG;
+
+			case 's':
+				if (--argc <= 0)
+					return CMD_RET_USAGE;
+				buf_size = simple_strtoul(*++argv, NULL, 16);
+				goto NXTARG;
+
+			default:
+				return CMD_RET_USAGE;
+			}
+		}
+NXTARG:
+		;
+	}
+
+	fastboot_init((void *)buf_addr, buf_size);
+
+	if (!strcmp(argv[1], "udp"))
+		return do_fastboot_udp(argc, argv, buf_addr, buf_size);
+
+	if (!strcmp(argv[1], "usb")) {
+		argv++;
+		argc--;
+	}
+
+	return do_fastboot_usb(argc, argv, buf_addr, buf_size);
 }
 
+#ifdef CONFIG_SYS_LONGHELP
+static char fastboot_help_text[] =
+	"[-l addr] [-s size] usb <controller> | udp\n"
+	"\taddr - address of buffer used during data transfers ("
+	__stringify(CONFIG_FASTBOOT_BUF_ADDR) ")\n"
+	"\tsize - size of buffer used during data transfers ("
+	__stringify(CONFIG_FASTBOOT_BUF_SIZE) ")"
+	;
+#endif
+
 U_BOOT_CMD(
-	fastboot, 2, 1, do_fastboot,
-	"use USB Fastboot protocol",
-	"<USB_controller>\n"
-	"    - run as a fastboot usb device"
+	fastboot, CONFIG_SYS_MAXARGS, 1, do_fastboot,
+	"run as a fastboot usb or udp device", fastboot_help_text
 );
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig
index 51c5789..a79f456 100644
--- a/drivers/fastboot/Kconfig
+++ b/drivers/fastboot/Kconfig
@@ -14,6 +14,13 @@  config USB_FUNCTION_FASTBOOT
 	help
 	  This enables the USB part of the fastboot gadget.
 
+config UDP_FUNCTION_FASTBOOT
+	depends on NET
+	select FASTBOOT
+	bool "Enable fastboot protocol over UDP"
+	help
+	  This enables the fastboot protocol over UDP.
+
 if FASTBOOT
 
 config FASTBOOT_BUF_ADDR
@@ -118,6 +125,14 @@  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".
 
+config FASTBOOT_CMD_OEM_FORMAT
+	bool "Enable the 'oem format' command"
+	depends on FASTBOOT_FLASH_MMC && CMD_GPT
+	help
+	  Add support for the "oem format" command from a client. This
+	  relies on the env variable partitions to contain the list of
+	  partitions as required by the gpt command.
+
 endif # FASTBOOT
 
 endmenu
diff --git a/drivers/fastboot/Makefile b/drivers/fastboot/Makefile
index e4bd389..149bd02 100644
--- a/drivers/fastboot/Makefile
+++ b/drivers/fastboot/Makefile
@@ -1,6 +1,8 @@ 
 # SPDX-License-Identifier:      GPL-2.0+
 
 obj-y += fb_common.o
+obj-y += fb_getvar.o
+obj-y += fb_command.o
 
 obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fb_mmc.o
 obj-$(CONFIG_FASTBOOT_FLASH_NAND) += fb_nand.o
diff --git a/drivers/fastboot/fb_command.c b/drivers/fastboot/fb_command.c
new file mode 100644
index 0000000..34bf9a2
--- /dev/null
+++ b/drivers/fastboot/fb_command.c
@@ -0,0 +1,258 @@ 
+// 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 <fb_nand.h>
+#include <part.h>
+#include <stdlib.h>
+
+/* Fastboot download parameters */
+static u32 image_size;
+u32 fastboot_bytes_received;
+u32 fastboot_bytes_expected;
+
+static void fb_okay(char *, char *);
+static void fb_getvar(char *, char *);
+static void fb_download(char *, char *);
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
+static void fb_flash(char *, char *);
+static void fb_erase(char *, char *);
+#endif
+static void fb_reboot_bootloader(char *, char *);
+#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT)
+static void fb_oem_format(char *, char *);
+#endif
+
+static const struct {
+	const char *command;
+	void (*dispatch)(char *cmd_parameter, char *response);
+} fb_commands[FASTBOOT_COMMAND_COUNT] = {
+	[FASTBOOT_COMMAND_GETVAR] = {
+		.command = "getvar",
+		.dispatch = fb_getvar
+	},
+	[FASTBOOT_COMMAND_DOWNLOAD] = {
+		.command = "download",
+		.dispatch = fb_download
+	},
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
+	[FASTBOOT_COMMAND_FLASH] =  {
+		.command = "flash",
+		.dispatch = fb_flash
+	},
+	[FASTBOOT_COMMAND_ERASE] =  {
+		.command = "erase",
+		.dispatch = fb_erase
+	},
+#endif
+	[FASTBOOT_COMMAND_BOOT] =  {
+		.command = "boot",
+		.dispatch = fb_okay
+	},
+	[FASTBOOT_COMMAND_CONTINUE] =  {
+		.command = "continue",
+		.dispatch = fb_okay
+	},
+	[FASTBOOT_COMMAND_REBOOT] =  {
+		.command = "reboot",
+		.dispatch = fb_okay
+	},
+	[FASTBOOT_COMMAND_REBOOT_BOOTLOADER] =  {
+		.command = "reboot-bootloader",
+		.dispatch = fb_reboot_bootloader
+	},
+	[FASTBOOT_COMMAND_SET_ACTIVE] =  {
+		.command = "set_active",
+		.dispatch = fb_okay
+	},
+#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT)
+	[FASTBOOT_COMMAND_OEM_FORMAT] = {
+		.command = "oem format",
+		.dispatch = fb_oem_format,
+	},
+#endif
+};
+
+int fastboot_handle_command(char *cmd_string, char *response)
+{
+	int i;
+	char *cmd_parameter;
+
+	cmd_parameter = cmd_string;
+	strsep(&cmd_parameter, ":");
+
+	for (i = 0; i < FASTBOOT_COMMAND_COUNT; i++) {
+		if (!strcmp(fb_commands[i].command, cmd_string)) {
+			if (fb_commands[i].dispatch) {
+				fb_commands[i].dispatch(cmd_parameter,
+							response);
+				return i;
+			} else {
+				break;
+			}
+		}
+	}
+
+	pr_err("command %s not recognized.\n", cmd_string);
+	fastboot_fail("unrecognized command", response);
+	return -1;
+}
+
+static void fb_okay(char *cmd_parameter, char *response)
+{
+	fastboot_okay(NULL, response);
+}
+
+static void fb_getvar(char *cmd_parameter, char *response)
+{
+	fastboot_getvar(cmd_parameter, response);
+}
+
+static void fb_download(char *cmd_parameter, char *response)
+{
+	char *tmp;
+
+	if (!cmd_parameter) {
+		fastboot_fail("Expected command parameter", response);
+		return;
+	}
+	fastboot_bytes_received = 0;
+	fastboot_bytes_expected = simple_strtoul(cmd_parameter, &tmp, 16);
+	if (fastboot_bytes_expected == 0) {
+		fastboot_fail("Expected nonzero image size", response);
+		return;
+	}
+	/*
+	 * Nothing to download yet. Response is of the form:
+	 * [DATA|FAIL]$cmd_parameter
+	 *
+	 * where cmd_parameter is an 8 digit hexadecimal number
+	 */
+	if (fastboot_bytes_expected > fastboot_buf_size) {
+		fastboot_fail(cmd_parameter, response);
+	} else {
+		printf("Starting download of %d bytes\n",
+		       fastboot_bytes_expected);
+		fastboot_response("DATA", response, "%s", cmd_parameter);
+	}
+}
+
+/**
+ * Copies image data from fastboot_data to fastboot_buf_addr.
+ * Writes to response.
+ *
+ * @param fastboot_data        Pointer to received fastboot data
+ * @param fastboot_data_len    Length of received fastboot data
+ * @param response             Pointer to fastboot response buffer
+ */
+void fastboot_download_data(const void *fastboot_data,
+			    unsigned int fastboot_data_len,
+			    char *response)
+{
+	if (fastboot_data_len == 0 &&
+	    fastboot_bytes_received >= fastboot_bytes_expected) {
+		/* Download complete. Respond with "OKAY" */
+		fastboot_okay(NULL, response);
+		printf("\ndownloading of %d bytes finished\n",
+		       fastboot_bytes_received);
+		image_size = fastboot_bytes_received;
+		env_set_hex("filesize", image_size);
+		fastboot_bytes_expected = 0;
+		fastboot_bytes_received = 0;
+	} else {
+#define BYTES_PER_DOT  0x20000
+		u32 pre_dot_num, now_dot_num;
+
+		if (fastboot_data_len == 0 ||
+		    (fastboot_bytes_received + fastboot_data_len) >
+		    fastboot_bytes_expected) {
+			fastboot_fail("Received invalid data length",
+				      response);
+			return;
+		}
+		/* Download data to fastboot_buf_addr */
+		memcpy(fastboot_buf_addr + fastboot_bytes_received,
+		       fastboot_data, fastboot_data_len);
+
+		pre_dot_num = fastboot_bytes_received / BYTES_PER_DOT;
+		fastboot_bytes_received += fastboot_data_len;
+		now_dot_num = fastboot_bytes_received / BYTES_PER_DOT;
+
+		if (pre_dot_num != now_dot_num) {
+			putc('.');
+			if (!(now_dot_num % 74))
+				putc('\n');
+		}
+	}
+}
+
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
+/**
+ * Writes the previously downloaded image to the partition indicated by
+ * cmd_parameter. Writes to response.
+ *
+ * @param response    Pointer to fastboot response buffer
+ */
+static void fb_flash(char *cmd_parameter, char *response)
+{
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
+	fb_mmc_flash_write(cmd_parameter, fastboot_buf_addr, image_size,
+			   response);
+#endif
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND)
+	fb_nand_flash_write(cmd_parameter, fastboot_buf_addr, image_size,
+			    response);
+#endif
+}
+
+/**
+ * Erases the partition indicated by cmd_parameter (clear to 0x00s). Writes
+ * to response.
+ *
+ * @param response    Pointer to fastboot response buffer
+ */
+static void fb_erase(char *cmd_parameter, 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
+
+/**
+ * Sets reboot bootloader flag if requested. Writes to response.
+ *
+ * @param response    Pointer to fastboot response buffer
+ */
+static void fb_reboot_bootloader(char *cmd_parameter, char *response)
+{
+	if (fastboot_set_reboot_flag())
+		fastboot_fail("Cannot set reboot flag", response);
+	else
+		fastboot_okay(NULL, response);
+}
+
+#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT)
+static void fb_oem_format(char *cmd_parameter, char *response)
+{
+	char cmdbuf[32];
+
+	if (!env_get("partitions")) {
+		fastboot_fail("partitions not set", response);
+	} else {
+		sprintf(cmdbuf, "gpt write mmc %x $partitions",
+			CONFIG_FASTBOOT_FLASH_MMC_DEV);
+		if (run_command(cmdbuf, 0))
+			fastboot_fail("", response);
+		else
+			fastboot_okay(NULL, response);
+	}
+}
+#endif
diff --git a/drivers/fastboot/fb_common.c b/drivers/fastboot/fb_common.c
index e74f3a0..4cbcbb1 100644
--- a/drivers/fastboot/fb_common.c
+++ b/drivers/fastboot/fb_common.c
@@ -12,6 +12,13 @@ 
 
 #include <common.h>
 #include <fastboot.h>
+#include <net/fastboot.h>
+
+/* fastboot download buffer */
+void *fastboot_buf_addr;
+u32 fastboot_buf_size;
+
+void (*fastboot_progress_callback)(const char *msg);
 
 /**
  * Writes a response to response buffer of the form "$tag$reason".
@@ -52,3 +59,44 @@  int __weak fastboot_set_reboot_flag(void)
 {
 	return -ENOSYS;
 }
+
+void fastboot_boot(void *addr)
+{
+	char *s;
+
+	s = env_get("fastboot_bootcmd");
+	if (s) {
+		run_command(s, CMD_FLAG_ENV);
+	} else {
+		static char boot_addr_start[12];
+		static char *const bootm_args[] = {
+			"bootm", boot_addr_start, NULL
+		};
+
+		snprintf(boot_addr_start, sizeof(boot_addr_start) - 1,
+			 "0x%lx", (long)addr);
+		printf("Booting kernel at %s...\n\n\n", boot_addr_start);
+
+		do_bootm(NULL, 0, 2, bootm_args);
+
+		/*
+		 * This only happens if image is somehow faulty so we start
+		 * over. We deliberately leave this policy to the invocation
+		 * of fastbootcmd if that's what's being run
+		 */
+		do_reset(NULL, 0, 0, NULL);
+	}
+}
+
+void fastboot_set_progress_callback(void (*progress)(const char *msg))
+{
+	fastboot_progress_callback = progress;
+}
+
+void fastboot_init(void *buf_addr, u32 buf_size)
+{
+	fastboot_buf_addr = buf_addr ? buf_addr :
+				       (void *)CONFIG_FASTBOOT_BUF_ADDR;
+	fastboot_buf_size = buf_size ? buf_size : CONFIG_FASTBOOT_BUF_SIZE;
+	fastboot_set_progress_callback(NULL);
+}
diff --git a/drivers/fastboot/fb_getvar.c b/drivers/fastboot/fb_getvar.c
new file mode 100644
index 0000000..7fc46c3
--- /dev/null
+++ b/drivers/fastboot/fb_getvar.c
@@ -0,0 +1,222 @@ 
+// 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 <fb_nand.h>
+#include <fs.h>
+#include <version.h>
+
+static void fb_getvar_version(char *var_parameter, char *response);
+static void fb_getvar_bootloader_version(char *var_parameter, char *response);
+static void fb_getvar_downloadsize(char *var_parameter, char *response);
+static void fb_getvar_serialno(char *var_parameter, char *response);
+static void fb_getvar_version_baseband(char *var_parameter, char *response);
+static void fb_getvar_product(char *var_parameter, char *response);
+static void fb_getvar_current_slot(char *var_parameter, char *response);
+static void fb_getvar_slot_suffixes(char *var_parameter, char *response);
+static void fb_getvar_has_slot(char *var_parameter, char *response);
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
+static void fb_getvar_partition_type(char *part_name, char *response);
+#endif
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
+static void fb_getvar_partition_size(char *part_name, char *response);
+#endif
+
+static const struct {
+	const char *variable;
+	void (*dispatch)(char *var_parameter, char *response);
+} fb_getvar_dispatch[] = {
+	{
+		.variable = "version",
+		.dispatch = fb_getvar_version
+	}, {
+		.variable = "bootloader-version",
+		.dispatch = fb_getvar_bootloader_version
+	}, {
+		.variable = "version-bootloader",
+		.dispatch = fb_getvar_bootloader_version
+	}, {
+		.variable = "downloadsize",
+		.dispatch = fb_getvar_downloadsize
+	}, {
+		.variable = "max-download-size",
+		.dispatch = fb_getvar_downloadsize
+	}, {
+		.variable = "serialno",
+		.dispatch = fb_getvar_serialno
+	}, {
+		.variable = "version-baseband",
+		.dispatch = fb_getvar_version_baseband
+	}, {
+		.variable = "product",
+		.dispatch = fb_getvar_product
+	}, {
+		.variable = "current-slot",
+		.dispatch = fb_getvar_current_slot
+	}, {
+		.variable = "slot-suffixes",
+		.dispatch = fb_getvar_slot_suffixes
+	}, {
+		.variable = "has_slot",
+		.dispatch = fb_getvar_has_slot
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
+	}, {
+		.variable = "partition-type",
+		.dispatch = fb_getvar_partition_type
+#endif
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
+	}, {
+		.variable = "partition-size",
+		.dispatch = fb_getvar_partition_size
+#endif
+	}
+};
+
+static void fb_getvar_version(char *var_parameter, char *response)
+{
+	fastboot_okay(FASTBOOT_VERSION, response);
+}
+
+static void fb_getvar_bootloader_version(char *var_parameter, char *response)
+{
+	fastboot_okay(U_BOOT_VERSION, response);
+}
+
+static void fb_getvar_downloadsize(char *var_parameter, char *response)
+{
+	fastboot_response("OKAY", response, "0x%08x", fastboot_buf_size);
+}
+
+static void fb_getvar_serialno(char *var_parameter, char *response)
+{
+	const char *tmp = env_get("serial#");
+
+	if (tmp)
+		fastboot_okay(tmp, response);
+	else
+		fastboot_fail("Value not set", response);
+}
+
+static void fb_getvar_version_baseband(char *var_parameter, char *response)
+{
+	fastboot_okay("N/A", response);
+}
+
+static void fb_getvar_product(char *var_parameter, char *response)
+{
+	const char *board = env_get("board");
+
+	if (board)
+		fastboot_okay(board, response);
+	else
+		fastboot_fail("Board not set", response);
+}
+
+static void fb_getvar_current_slot(char *var_parameter, char *response)
+{
+	/* A/B not implemented, for now always return _a */
+	fastboot_okay("_a", response);
+}
+
+static void fb_getvar_slot_suffixes(char *var_parameter, char *response)
+{
+	fastboot_okay("_a,_b", response);
+}
+
+static void fb_getvar_has_slot(char *part_name, char *response)
+{
+	if (part_name && (!strcmp(part_name, "boot") ||
+			  !strcmp(part_name, "system")))
+		fastboot_okay("yes", response);
+	else
+		fastboot_okay("no", response);
+}
+
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
+static void fb_getvar_partition_type(char *part_name, char *response)
+{
+	int r;
+	struct blk_desc *dev_desc;
+	disk_partition_t part_info;
+
+	r = fastboot_mmc_get_part_info(part_name, &dev_desc, &part_info,
+				       response);
+	if (r >= 0) {
+		r = fs_set_blk_dev_with_part(dev_desc, r);
+		if (r < 0)
+			fastboot_fail("failed to set partition", response);
+		else
+			fastboot_okay(fs_get_type_name(), response);
+	}
+}
+#endif
+
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
+static void fb_getvar_partition_size(char *part_name, char *response)
+{
+	int r;
+	size_t size;
+
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
+	struct blk_desc *dev_desc;
+	disk_partition_t part_info;
+
+	r = fastboot_mmc_get_part_info(part_name, &dev_desc, &part_info,
+				       response);
+	if (r >= 0)
+		size = part_info.size;
+#endif
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND)
+	struct part_info *part_info;
+
+	r = fastboot_nand_get_part_info(part_name, &part_info, response);
+	if (r >= 0)
+		size = part_info->size;
+#endif
+	if (r >= 0)
+		fastboot_response("OKAY", response, "0x%016zx", size);
+}
+#endif
+
+/**
+ * Writes ascii string specified by cmd_parameter to response.
+ *
+ * @param cmd_parameter	Point to command parameter
+ * @param response	Pointer to fastboot response buffer
+ */
+void fastboot_getvar(char *cmd_parameter, char *response)
+{
+	if (!cmd_parameter) {
+		fastboot_fail("missing var", response);
+	} else {
+#define FASTBOOT_ENV_PREFIX	"fastboot."
+		int i;
+		char *var_parameter = cmd_parameter;
+		char envstr[FASTBOOT_RESPONSE_LEN];
+		const char *s;
+
+		snprintf(envstr, sizeof(envstr) - 1,
+			 FASTBOOT_ENV_PREFIX "%s", cmd_parameter);
+		s = env_get(envstr);
+		if (s) {
+			fastboot_response("OKAY", response, "%s", s);
+			return;
+		}
+
+		strsep(&var_parameter, ":");
+		for (i = 0; i < ARRAY_SIZE(fb_getvar_dispatch); ++i) {
+			if (!strcmp(fb_getvar_dispatch[i].variable,
+				    cmd_parameter)) {
+				fb_getvar_dispatch[i].dispatch(var_parameter,
+							       response);
+				return;
+			}
+		}
+		pr_warn("WARNING: unknown variable: %s\n", cmd_parameter);
+		fastboot_fail("Variable not implemented", response);
+	}
+}
diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c
index 038905f..69a78be 100644
--- a/drivers/fastboot/fb_mmc.c
+++ b/drivers/fastboot/fb_mmc.c
@@ -15,6 +15,8 @@ 
 #include <linux/compat.h>
 #include <android_image.h>
 
+#define FASTBOOT_MAX_BLK_WRITE 16384
+
 #define BOOT_PARTITION_NAME "boot"
 
 struct fb_mmc_sparse {
@@ -43,13 +45,40 @@  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) {
+			if (fastboot_progress_callback)
+				fastboot_progress_callback("writing");
+			blks_written = blk_dwrite(block_dev, blk, cur_blkcnt,
+						  buffer + (i * block_dev->blksz));
+		} else {
+			if (fastboot_progress_callback)
+				fastboot_progress_callback("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,
@@ -60,7 +89,7 @@  static lbaint_t fb_mmc_sparse_reserve(struct sparse_storage *info,
 
 static void write_raw_image(struct blk_desc *dev_desc, disk_partition_t *info,
 		const char *part_name, void *buffer,
-		unsigned int download_bytes, char *response)
+		u32 download_bytes, char *response)
 {
 	lbaint_t blkcnt;
 	lbaint_t blks;
@@ -77,7 +106,8 @@  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);
@@ -148,7 +178,7 @@  static lbaint_t fb_mmc_get_boot_header(struct blk_desc *dev_desc,
  */
 static int fb_mmc_update_zimage(struct blk_desc *dev_desc,
 				void *download_buffer,
-				unsigned int download_bytes,
+				u32 download_bytes,
 				char *response)
 {
 	uintptr_t hdr_addr;			/* boot image header address */
@@ -251,8 +281,32 @@  static int fb_mmc_update_zimage(struct blk_desc *dev_desc,
 }
 #endif
 
+int fastboot_mmc_get_part_info(char *part_name, struct blk_desc **dev_desc,
+			       disk_partition_t *part_info, char *response)
+{
+	int r;
+
+	*dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
+	if (!*dev_desc) {
+		fastboot_fail("block device not found", response);
+		return -ENOENT;
+	}
+	if (!part_name) {
+		fastboot_fail("partition not found", response);
+		return -ENOENT;
+	}
+
+	r = part_get_info_by_name_or_alias(*dev_desc, part_name, part_info);
+	if (r < 0) {
+		fastboot_fail("partition not found", response);
+		return r;
+	}
+
+	return r;
+}
+
 void fb_mmc_flash_write(const char *cmd, void *download_buffer,
-			unsigned int download_bytes, char *response)
+			u32 download_bytes, char *response)
 {
 	struct blk_desc *dev_desc;
 	disk_partition_t info;
@@ -389,7 +443,8 @@  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\n", dev_desc->devnum);
 		fastboot_fail("failed erasing from device", response);
diff --git a/drivers/fastboot/fb_nand.c b/drivers/fastboot/fb_nand.c
index 849a6f1..a7cbc34 100644
--- a/drivers/fastboot/fb_nand.c
+++ b/drivers/fastboot/fb_nand.c
@@ -88,7 +88,7 @@  static int _fb_nand_erase(struct mtd_info *mtd, struct part_info *part)
 }
 
 static int _fb_nand_write(struct mtd_info *mtd, struct part_info *part,
-			  void *buffer, unsigned int offset,
+			  void *buffer, u32 offset,
 			  size_t length, size_t *written)
 {
 	int flags = WITH_WR_VERIFY;
@@ -145,8 +145,16 @@  static lbaint_t fb_nand_sparse_reserve(struct sparse_storage *info,
 	return blkcnt + bad_blocks;
 }
 
+int fastboot_nand_get_part_info(char *part_name, struct part_info **part_info,
+				char *response)
+{
+	struct mtd_info *mtd = NULL;
+
+	return fb_nand_lookup(part_name, &mtd, part_info, response);
+}
+
 void fb_nand_flash_write(const char *cmd, void *download_buffer,
-			 unsigned int download_bytes, char *response)
+			 u32 download_bytes, char *response)
 {
 	struct part_info *part;
 	struct mtd_info *mtd = NULL;
diff --git a/include/fastboot.h b/include/fastboot.h
index 593e6a7..3d9ffc6 100644
--- a/include/fastboot.h
+++ b/include/fastboot.h
@@ -15,8 +15,39 @@ 
 #define FASTBOOT_VERSION	"0.4"
 
 /* The 64 defined bytes plus \0 */
+#define FASTBOOT_COMMAND_LEN	(64 + 1)
 #define FASTBOOT_RESPONSE_LEN	(64 + 1)
 
+/**
+ * All known commands to fastboot
+ */
+enum {
+	FASTBOOT_COMMAND_GETVAR = 0,
+	FASTBOOT_COMMAND_DOWNLOAD,
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
+	FASTBOOT_COMMAND_FLASH,
+	FASTBOOT_COMMAND_ERASE,
+#endif
+	FASTBOOT_COMMAND_BOOT,
+	FASTBOOT_COMMAND_CONTINUE,
+	FASTBOOT_COMMAND_REBOOT,
+	FASTBOOT_COMMAND_REBOOT_BOOTLOADER,
+	FASTBOOT_COMMAND_SET_ACTIVE,
+#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT)
+	FASTBOOT_COMMAND_OEM_FORMAT,
+#endif
+
+	FASTBOOT_COMMAND_COUNT
+};
+
+extern void *fastboot_buf_addr;
+extern u32 fastboot_buf_size;
+
+extern u32 fastboot_bytes_received;
+extern u32 fastboot_bytes_expected;
+
+extern void (*fastboot_progress_callback)(const char *msg);
+
 void fastboot_response(const char *tag, char *response,
 		       const char *format, ...)
 	__attribute__ ((format (__printf__, 3, 4)));
@@ -24,4 +55,20 @@  void fastboot_response(const char *tag, char *response,
 void fastboot_fail(const char *reason, char *response);
 void fastboot_okay(const char *reason, char *response);
 int fastboot_set_reboot_flag(void);
+
+/**
+ * Writes ascii string specified by cmd_parameter to response.
+ *
+ * @param cmd_parameter	Pointer to variable name
+ * @param response	Pointer to fastboot response buffer
+ */
+void fastboot_getvar(char *cmd_parameter, char *response);
+
+void fastboot_init(void *buf_addr, u32 buf_size);
+void fastboot_set_progress_callback(void (*progress)(const char *msg));
+
+void fastboot_boot(void *addr);
+int fastboot_handle_command(char *cmd_string, char *response);
+void fastboot_download_data(const void *fastboot_data,
+			    unsigned int fastboot_data_len, char *response);
 #endif /* _FASTBOOT_H_ */
diff --git a/include/fb_mmc.h b/include/fb_mmc.h
index 39a960c..ae01f99 100644
--- a/include/fb_mmc.h
+++ b/include/fb_mmc.h
@@ -3,6 +3,12 @@ 
  * Copyright 2014 Broadcom Corporation.
  */
 
+#ifndef _FB_MMC_H_
+#define _FB_MMC_H_
+
+int fastboot_mmc_get_part_info(char *part_name, struct blk_desc **dev_desc,
+			       disk_partition_t *part_info, char *response);
 void fb_mmc_flash_write(const char *cmd, void *download_buffer,
-			unsigned int download_bytes, char *response);
+			u32 download_bytes, char *response);
 void fb_mmc_erase(const char *cmd, char *response);
+#endif
diff --git a/include/fb_nand.h b/include/fb_nand.h
index 2c92a4e..937f9e4 100644
--- a/include/fb_nand.h
+++ b/include/fb_nand.h
@@ -4,6 +4,14 @@ 
  * Copyright 2015 Free Electrons.
  */
 
+#ifndef _FB_NAND_H_
+#define _FB_NAND_H_
+
+#include <jffs2/load_kernel.h>
+
+int fastboot_nand_get_part_info(char *part_name, struct part_info **part_info,
+				char *response);
 void fb_nand_flash_write(const char *cmd, void *download_buffer,
-			 unsigned int download_bytes, char *response);
+			 u32 download_bytes, char *response);
 void fb_nand_erase(const char *cmd, char *response);
+#endif
diff --git a/include/net.h b/include/net.h
index 65f51d7..5760685 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 */
diff --git a/include/net/fastboot.h b/include/net/fastboot.h
new file mode 100644
index 0000000..6860209
--- /dev/null
+++ b/include/net/fastboot.h
@@ -0,0 +1,21 @@ 
+/* 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);
+
+/**********************************************************************/
+
+#endif /* __NET_FASTBOOT_H__ */
diff --git a/net/Makefile b/net/Makefile
index d1e8e01..0746687 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -23,6 +23,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..8ec2aa5
--- /dev/null
+++ b/net/fastboot.c
@@ -0,0 +1,310 @@ 
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#include <common.h>
+#include <fastboot.h>
+#include <net.h>
+#include <net/fastboot.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 DATA_SIZE (PACKET_SIZE - sizeof(struct fastboot_header))
+
+/* 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;
+
+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 boot_downloaded_image(void);
+
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
+/**
+ * Send an INFO packet during long commands
+ *
+ * @param msg: String describing the reason for waiting
+ */
+static void fastboot_udp_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 */
+	fastboot_response("INFO", response, "%s", msg);
+	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);
+}
+
+/**
+ * Send an INFO packet during long commands based on timer. An INFO packet
+ * is sent if the time is 30 seconds after start. Else, noop.
+ *
+ * @param msg:    String describing the reason for waiting
+ */
+static void fastboot_timed_send_info(const char *msg)
+{
+	static ulong start;
+
+	/* 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_udp_send_info(msg);
+	}
+}
+#endif
+
+/**
+ * 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;
+	static char command[FASTBOOT_COMMAND_LEN];
+	static int cmd = -1;
+	static bool pending_command;
+	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 == FASTBOOT_COMMAND_DOWNLOAD) {
+			fastboot_download_data(fastboot_data, fastboot_data_len,
+					       response);
+		} else if (!pending_command) {
+			strlcpy(command, fastboot_data,
+				min((size_t)fastboot_data_len + 1,
+				    sizeof(command)));
+			pending_command = true;
+		} else {
+			cmd = fastboot_handle_command(command, response);
+			pending_command = false;
+		}
+		/*
+		 * 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)) {
+		switch (cmd) {
+		case FASTBOOT_COMMAND_BOOT:
+			boot_downloaded_image();
+			break;
+
+		case FASTBOOT_COMMAND_CONTINUE:
+			net_set_state(NETLOOP_SUCCESS);
+			break;
+
+		case FASTBOOT_COMMAND_REBOOT:
+		case FASTBOOT_COMMAND_REBOOT_BOOTLOADER:
+			do_reset(NULL, 0, 0, NULL);
+			break;
+		}
+	}
+
+	if (!strncmp("OKAY", response, 4) || !strncmp("FAIL", response, 4))
+		cmd = -1;
+}
+
+/**
+ * Boots into downloaded image.
+ */
+static void boot_downloaded_image(void)
+{
+	fastboot_boot(fastboot_buf_addr);
+	net_set_state(NETLOOP_SUCCESS);
+}
+
+/**
+ * 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 < sizeof(struct fastboot_header) || 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;
+
+	fastboot_set_progress_callback(fastboot_timed_send_info);
+	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 7f85211..a4932f4 100644
--- a/net/net.c
+++ b/net/net.c
@@ -87,6 +87,7 @@ 
 #include <environment.h>
 #include <errno.h>
 #include <net.h>
+#include <net/fastboot.h>
 #include <net/tftp.h>
 #if defined(CONFIG_LED_STATUS)
 #include <miiphy.h>
@@ -451,6 +452,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 +1328,7 @@  common:
 		/* Fall through */
 
 	case NETCONS:
+	case FASTBOOT:
 	case TFTPSRV:
 		if (net_ip.s_addr == 0) {
 			puts("*** ERROR: `ipaddr' not set\n");