[U-Boot] [PATCH 1/8] doc: dfu: tftp: README entry for TFTP extension of DFU

Joe Hershberger joe.hershberger at gmail.com
Mon Jul 20 21:17:45 CEST 2015


Hi Lukasz,

On Mon, Jul 20, 2015 at 1:59 PM, Lukasz Majewski <l.majewski at majess.pl> wrote:
> Hi Joe,
>
>> Hi Lukasz,
>>
>> On Thu, Jul 16, 2015 at 2:59 PM, Lukasz Majewski
>> <l.majewski at majess.pl> wrote:
>> > Hi Joe,
>> >
>> > Thank you for your review.
>> >
>> >> Hi Lukasz,
>> >>
>> >> On Sun, Jul 12, 2015 at 10:30 AM, Lukasz Majewski
>> >> <l.majewski at majess.pl> wrote:
>> >> > Documentation file for DFU extension. With this functionality it
>> >> > is now possible to transfer FIT images with firmware updates via
>> >> > TFTP and use DFU backend for storing them.
>> >> >
>> >> > Signed-off-by: Lukasz Majewski <l.majewski at majess.pl>
>> >> > ---
>> >> >  doc/README.dfutftp | 153
>> >> > +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file
>> >> > changed, 153 insertions(+) create mode 100644 doc/README.dfutftp
>> >> >
>> >> > diff --git a/doc/README.dfutftp b/doc/README.dfutftp
>> >> > new file mode 100644
>> >> > index 0000000..4636321
>> >> > --- /dev/null
>> >> > +++ b/doc/README.dfutftp
>> >> > @@ -0,0 +1,153 @@
>> >> > +Device Firmware Upgrade (DFU) - extension to use TFTP
>> >> > +=====================================================
>> >> > +
>> >> > +Why?
>> >> > +----
>> >> > +
>> >> > +* Update TFTP (CONFIG_UPDATE_TFTP) only supports writing
>> >> > +code to NAND memory via TFTP.
>> >> > +* DFU supports writing data to variety of mediums (NAND,
>> >> > +eMMC, SD, partitions, RAM, etc) via USB.
>> >> > +
>> >> > +Combination of both solves their shortcomings!
>> >> > +
>> >> > +
>> >> > +Overview
>> >> > +--------
>> >> > +
>> >> > +This document briefly describes how to use BF for
>> >>
>> >> BF?
>> >
>> > It should be DFU.
>> >
>> >>
>> >> > +upgrading firmware (e.g. kernel, u-boot, rootfs, etc.)
>> >> > +via TFTP protocol.
>> >> > +
>> >> > +By using Ethernet (TFTP protocol to be precise) it was
>> >> > +possible to overcome the major problem of USB based DFU -
>> >> > +the relatively low transfer speed for large files.
>> >> > +This was caused by DFU standard, which imposed utilization
>> >> > +of only EP0 for transfer. By using Ethernet we can circumvent
>> >> > +this shortcoming.
>> >> > +
>> >> > +Beagle Bone Black (BBB) powered by TI's am335x CPU has been used
>> >> > +as a demo board.
>> >> > +
>> >> > +To utilize this feature, one needs to first enable support
>> >> > +for USB based DFU (CONFIG_DFU_*) and TFTP update
>> >> > +(CONFIG_UPDATE_TFTP) described in ./doc/README.update.
>> >>
>> >> Does it really make sense to reuse this UPDATE_TFTP config? Why not
>> >> DFU_TFTP?
>> >
>> > Enabling CONFIG_UPDATE_TFTP allows reusing parts of the legacy
>> > update_tftp() code.
>>
>> I can understand reusing the code, but that doesn't mean we should
>> force both complete features to be included.
>
> The legacy ./common/update.c was using two flags - namely
> CONFIG_UPDATE_TFTP (to allow compilation of this file) and
> CONFIG_SYS_NO_FLASH. Lack of the latter was using #error to terminate a
> compilation.

It seems the CONFIG_SYS_NO_FLASH is simply making sure that some other
required feature is included. It wasn't actually selecting this
feature.

The CONFIG_UPDATE_TFTP was actually enabling the feature. It seems
that should remain the case.

> That was the old behavior - one needed to define both flags to compile
> in the legacy code.

You actually were required to have *not* defined CONFIG_SYS_NO_FLASH.

> Moreover the CONFIG_UPDATE_TFTP is used to enable running
> update_tftp() in the early boot stage.

Yes... That could probably be left as is for now.

> My changes in the ./common/update.c file have split the code to common
> one (enabled by CONFIG_UPDATE_TFTP) and legacy one (NAND support
> specific) enabled by CONFIG_SYS_NO_FLASH.

I think you need to make the common code be enabled by seeing either
CONFIG_UPDATE_TFTP or CONFIG_DFU_TFTP.

You also need to have a check that fails if CONFIG_UPDATE_TFTP &&
CONFIG_SYS_NO_FLASH. That preserves old behavior.

>> > What I mean is that one should enable legacy CONFIG_UPDATE_TFTP as a
>> > prerequisite for using dfu tftp transfer.
>>
>> What if a new config like DFU_TFTP enabled the shared code, but not
>> the old behaviors.
>
> DFU_TFTP enables dfu specific code - not the shared code
> (at ./common/update.c).

It should also enable the shared code.

> Shared code is enabled by CONFIG_UPDATE_TFTP.

It should enable the shared code as well as the legacy-specific behavior.

>> >> > +New "dfutftp" command has been introduced to comply with present
>> >> > +USB related commands' syntax.
>> >> > +
>> >> > +This code works without "fitupd" command enabled.
>> >> > +
>> >> > +As of this writing
>> >> > (SHA1:241746e618fa725491e9ff689710c5f73ffd9139) the +update.c
>> >> > code is not enabled (CONFIG_UPDATE_TFTP) by any board in the
>> >> > +contemporary u-boot tree.
>> >>
>> >> So maybe we should remove it.
>> >
>> > This is IMHO a tricky issue. On the one hand there hasn't left any
>> > board supporting this feature in mainline (recently some old PPC
>> > boards have been removed from u-boot).
>> >
>> > One the other hand _probably_ there are deployed systems (as a
>> > derivative of the boards supported in u-boot and using this feature)
>> > which depend on this feature.
>>
>> That's fair.
>>
>> > I'd opt for leaving the original code in the tree with a fat big
>> > note about the plan to remove the legacy code in a near future (as
>> > we do it with MAKEALL script).
>>
>> OK
>>
>> >> > +
>> >> > +Environment variables
>> >> > +---------------------
>> >> > +
>> >> > +To preserve legacy behavior of TFTP update (./common/update.c)
>> >> > +code following new environment variables had been introduced:
>> >>
>> >> Another example of why you should use a new config instead of the
>> >> existing one.
>> >
>> > Could you be more specific here?
>>
>> You are adding magic env vars here because you want to have both old
>> and new behaviors at once. I think it would be better to select one at
>> build time and not add any magic.
>
> In theory you are right. In practice it is a bit more complicated - I
> will try to explain it latter in this e-mail.
>
>>
>> >> > +* "update_tftp_exec_at_boot" ["true"|"false"]
>> >> > +
>> >> > +  New usage of update_tftp allows setting the
>> >> > +  "update_tftp_exec_at_boot" env variable to allow it running
>> >> > +  at boot time.
>> >> > +  In this way update_tftp will not be executed at startup and
>> >> > reduce
>> >> > +  boot time.
>> >> > +
>> >> > +  To preserve backward compatibility for legacy boards this
>> >> > variable
>> >> > +  should be set to "true".
>> >> > +
>> >> > +  BBB note:
>> >> > +           When update tftp is not working after boot one need
>> >> > to
>> >> > +           increase values of following two configs:
>> >> > +           CONFIG_UPDATE_TFTP_MSEC_MAX and
>> >> > CONFIG_UPDATE_TFTP_CNT_MAX.
>> >> > +           Values of namely 1000 and 5 solve the issue for BBB.
>> >> > +
>> >> > +* "update_tftp_dfu" ["true"|"false"]
>> >> > +
>> >> > +  By "update_tftp_dfu" env variable we inform update_tftp that
>> >> > +  it should use dfu for writing data - in this way support for
>> >> > +  legacy usage is preserved.
>> >>
>> >> Same here... presumably a user only wants support for one or the
>> >> other compiled in. Please use a different config.
>> >
>> > The most appealing thing about update.c is that I had to add only a
>> > few lines of code to use it for my purpose. For that reason I've
>> > decided to keep as much as possible of the legacy code.
>> >
>> >>
>> >> > +* "update_tftp_dfu_interface" ["mmc"]
>> >> > +* "update_tftp_dfu_devstring" ["1"]
>> >> > +
>> >> > +  Both variables - namely
>> >> > "update_tftp_dfu_{interface|devstring}" are
>> >> > +  only taken into account when "update_tftp_dfu" is defined.
>> >> > +  They store information about interface (e.g. "mmc") and device
>> >> > number
>> >> > +  string (e.g. "1").
>> >>
>> >> It is preferable to make these parameters to a command and not
>> >> magic env variables.
>> >
>> > They can be specified in the 'dfutftp' command - which syntax is
>> > similar to 'dfu' (e.g. dfutftp 0 mmc 1).
>>
>> OK, great.
>>
>> > However, those variables are needed for automatic update after power
>> > up. In other words update_tftp() function is called very early in
>> > boot and env variables are a convenient way to specify the
>> > interface and its number.
>>
>> So this is only called early in the case of the old functionality.
>> Your new DFU features do not need an early automatic feature, right?
>
> I'm afraid that they will require some kind of update in the early
> boot state.

You should not need more than already existed for legacy, I think. So
you should not be adding any magic env vars.

>> In fact, I would argue that the old method didn't need it either and
>> never should have supported that. Things like this should simply be
>> part of the board's preboot script so we don't need this type of magic
>> stuff.
>
> Please correct me if I'm wrong.
>
> I should use another CONFIG_* to enable using common update_tftp()
> function. In this way I would avoid calling it in the early boot code.

Explained above.

> Instead, I should define proper "preboot" env variable with "dfu tftp 0
> mmc 1" command and use it for SW updating.

Correct. The preboot command should call normal commands and pass parameters.

>> >> > +  In the "dfutftp" command they are explicitly overridden.
>> >> > +  It is done deliberately, since in this command we may use
>> >> > arbitrary values. +
>> >> > +  Default values, when available during boot, are used by
>> >> > update_tftp
>> >> > +  (when dfu support is enabled) to properly setup medium device
>> >> > +  (e.g. mmc 1).
>> >> > +
>> >> > +
>> >> > +
>> >> > +Beagle Bone Black (BBB) setup
>> >> > +-----------------------------
>> >> > +
>> >> > +1. Setup tftp env variables:
>> >> > +   *  select desired eth device - 'ethact' variable
>> >> > ["ethact=cpsw"]
>> >> > +      (use "bdinfo" to check current setting)
>> >> > +   *  setup "serverip" and "ipaddr" variables
>> >> > +   *  set "loadaddr" as a fixed buffer where incoming data is
>> >> > placed
>> >> > +      ["loadaddr=0x81000000"]
>> >> > +
>> >> > +#########
>> >> > +# BONUS #
>> >> > +#########
>> >> > +It is possible to use USB interface to emulate ETH connection by
>> >> > setting +"ethact=usb_ether". In this way one can have very fast
>> >> > DFU transfer via USB.
>> >>
>> >> Is thor not faster than DFU?
>> >
>> > Yes, it is. However, DFU is standardized (which is despite of its
>> > low speed its huge advantage) - thor not.
>> >
>> >>
>> >> It seems like DFU should support a bulk endpoint if performance is
>> >> an issue, right?
>> >
>> > Yes, it should, but such modification would be not compliant with
>> > the standard.
>>
>> Who is the standards body? Can they accept suggestions for the next
>> revision? Is it worth trying to improve the standard?
>
> The last revision of DFU standard is from 2006 with Greg KH being a
> notable USB committee board member :-)
>
> I've asked him about the possibility to revise the standard but he
> replied that chances are small since Linux Foundation is not part
> of the USB standard committee anymore.

That's a shame. Oh well.

>> >>That would be more efficient than emulating Ethernet.
>> >
>> > To be more precise - I've combined the ability to use Ethernet with
>> > DFU flashing backend.
>> >
>> > In this way boards only equipped with ETH can (re)use DFU code to
>> > flash data (on MMC, NAND, filesystems, RAM, etc).
>>
>> Yes, that's very good. I was simply talking about the "BONUS" where
>> emulated Ethernet over USB is used. In that case it would be more
>> efficient to actually have a raw bulk endpoint supported by DFU.
>
> Yes, it would. Unfortunately I think that it would be very hard to
> revise the DFU standard.
>
> ETH over USB can be used on devices equipped only with USB (like
> trats/trats2 devel mobile phones). In that way DFU speed would increase.

Sure. Sounds good.

>> >> > +For 33MiB test image the transfer rate is 1MiB/s
>> >> > +
>> >> > +2. Setup update_tftp variables:
>> >> > +   *  set "updatefile" - the file name to be downloaded via TFTP
>> >> > (stored on
>> >> > +      the HOST at e.g. /srv/tftp)
>> >> > +
>> >> > +3. Setup dfutftp specific variables (as explained in
>> >> > "Environment Variables")
>> >> > +   * "update_tftp_exec_at_boot=true"
>> >> > +   * "update_tftp_dfu=true"
>> >> > +
>> >> > +4. Inspect "dfu" specific variables:
>> >> > +   * "dfu_alt_info" - information about available DFU entities
>> >> > +   * "dfu_bufsiz"   - variable to set buffer size [in bytes] -
>> >> > when it is not
>> >> > +                     possible to set large enough default buffer
>> >> > (8 MiB @ BBB) +
>> >> > +
>> >> > +
>> >> > +FIT image format for download
>> >> > +-----------------------------
>> >> > +
>> >> > +To create FIT image for download one should follow the update
>> >> > tftp README file +(./doc/README.update) with one notable
>> >> > difference: +
>> >> > +The original snippet of ./doc/uImage.FIT/update_uboot.its
>> >> > +
>> >> > +       images {
>> >> > +               update at 1 {
>> >> > +                       description = "U-Boot binary";
>> >> > +
>> >> > +should look like
>> >> > +
>> >> > +       images {
>> >> > +               u-boot.bin at 1 {
>> >> > +                       description = "U-Boot binary";
>> >> > +
>> >> > +where "u-boot.bin" is the DFU entity name to be stored.
>> >> > +
>> >> > +
>> >> > +
>> >> > +To do
>> >> > +-----
>> >> > +
>> >> > +* Extend dfu-util command (or write new one - e.g. dfueth-util)
>> >> > to support
>> >> > +  TFTP based transfers
>> >> > +
>> >> > +* Upload support (via TFTP)
>> >> > \ No newline at end of file
>> >> > --
>> >> > 2.1.4
>> >> >
>> >> > _______________________________________________
>> >> > U-Boot mailing list
>> >> > U-Boot at lists.denx.de
>> >> > http://lists.denx.de/mailman/listinfo/u-boot
>> >
>> > Best regards,
>> >
>> > Lukasz Majewski
>
> Best regards,
> Lukasz Majewski


More information about the U-Boot mailing list