[U-Boot] [PATCH v4 0/9] dfu: tftp: update: Support for DFU upgrades via ETH (TFTP)

This commit series enables DFU subsystem to use ETH and TFTP protocol as a medium for downloading data, which should bring substantial speedup for writing large files (like rootfs).
Please read provided ./doc/README.dfutftp documentation entry for more information.
Those patches should be applied on the u-boot/master branch: SHA1: 8d77576371381ade83de475bb639949b44941e8c
Lukasz Majewski (9): doc: dfu: tftp: README entry for TFTP extension of DFU net: tftp: Move tftp.h file from ./net to ./include/net tftp: update: Allow some parts of the code to be reused when CONFIG_SYS_NO_FLASH is set dfu: tftp: update: Provide tftp support for the DFU subsystem dfu: tftp: update: Add dfu_write_from_mem_addr() function update: tftp: dfu: Extend update_tftp() function to support DFU dfu: command: Extend "dfu" command to handle receiving data via TFTP dfu: tftp: Kconfig: Add Kconfig entry for dfu tftp feature dfu: tftp: Kconfig: Enable DFU_TFTP support on the am335x_boneblack_defconfig
common/Makefile | 1 + common/cmd_dfu.c | 20 +++++++ common/cmd_fitupd.c | 2 +- common/main.c | 2 +- common/update.c | 58 +++++++++++++------ configs/am335x_boneblack_defconfig | 1 + doc/README.dfutftp | 114 +++++++++++++++++++++++++++++++++++++ doc/README.update | 7 +++ drivers/dfu/Kconfig | 10 ++++ drivers/dfu/Makefile | 1 + drivers/dfu/dfu.c | 37 ++++++++++++ drivers/dfu/dfu_tftp.c | 65 +++++++++++++++++++++ include/dfu.h | 41 +++++++++++++ include/net.h | 14 ++++- {net => include/net}/tftp.h | 0 net/bootp.c | 2 +- net/net.c | 2 +- net/rarp.c | 2 +- net/tftp.c | 2 +- 19 files changed, 357 insertions(+), 24 deletions(-) create mode 100644 doc/README.dfutftp create mode 100644 drivers/dfu/dfu_tftp.c rename {net => include/net}/tftp.h (100%)

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@majess.pl Reviewed-by: Simon Glass sjg@chromium.org Acked-by: Joe Hershberger joe.hershberger@ni.com --- Changes for v2: - Remove section regarding update_tftp() specific environment variables
Changes for v3: - Add link to this document in the ./doc/README.update file
Changes for v4: - Words misspell correction - Added transfer speed measurement for pure DFU USB transfer
Change-Id: Ic4956aadb589cc7c081b16f6f746bc5d86213ea0 --- doc/README.dfutftp | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++ doc/README.update | 7 ++++ 2 files changed, 121 insertions(+) create mode 100644 doc/README.dfutftp
diff --git a/doc/README.dfutftp b/doc/README.dfutftp new file mode 100644 index 0000000..0257f0d --- /dev/null +++ b/doc/README.dfutftp @@ -0,0 +1,114 @@ +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 the 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 DFU for +upgrading firmware (e.g. kernel, u-boot, rootfs, etc.) +via TFTP protocol. + +By using Ethernet (TFTP protocol to be precise) it is +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 rev. C (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 DFU TFTP update +(CONFIG_DFU_TFTP) described in ./doc/README.update. + +The "dfu" command has been extended to support transfer via TFTP - one +needs to type for example "dfu tftp 0 mmc 0" + +This feature does not depend on "fitupd" command enabled. + +As of this writing (SHA1:8d77576371381ade83de475bb639949b44941e8c v2015.10-rc2) +the update.c code is not enabled (CONFIG_UPDATE_TFTP) by any board in the +contemporary u-boot tree. + + +Environment variables +--------------------- + +The "dfu tftp" command can be used in the "preboot" environment variable +(when it is enabled by defining CONFIG_PREBOOT). +This is the preferable way of using this command in the early boot stage +as opposed to legacy update_tftp() function invocation. + + +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. + +For 33MiB test image the transfer rate was 1MiB/s for ETH over USB and 200KiB/s +for pure DFU USB transfer. + +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. If required, to update firmware on boot, put the "dfu tftp 0 mmc 0" in the + "preboot" env variable. Otherwise use this command from u-boot prompt. + +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@1 { + description = "U-Boot binary"; + +should look like + + images { + u-boot.bin@1 { + description = "U-Boot binary"; + +where "u-boot.bin" is the DFU entity name to be stored. + + + +To do +----- + +* Extend dfu-util command to support TFTP based transfers +* Upload support (via TFTP) diff --git a/doc/README.update b/doc/README.update index a7f4d9e..eab124c 100644 --- a/doc/README.update +++ b/doc/README.update @@ -93,3 +93,10 @@ Example .its files An example containing three updates. It can be used to update Linux kernel, ramdisk and FDT blob stored in Flash. The procedure for preparing the update file is similar to the example above. + +TFTP update via DFU +------------------- + +- It is now possible to update firmware (bootloader, kernel, rootfs, etc.) via + TFTP by using DFU (Device Firmware Upgrade). More information can be found in + ./doc/README.dfutftp documentation entry.

This change gives the ability to reuse the <tftp.h> header file by other subsystems (like e.g. dfu).
Without this change compilation error emerges for the legacy update.c file.
Signed-off-by: Lukasz Majewski l.majewski@majess.pl Acked-by: Joe Hershberger joe.hershberger@ni.com --- Changes for v2: - Move tftp.h from ./include to ./include/net/ directory
Changes for v3: - Generate the patch set to avoid deleting and creating new files (git should just "move" them)
Changes for v4: - None
Change-Id: Idb26f766c3a72a47bec596f5f3c68f5ef632766a --- {net => include/net}/tftp.h | 0 net/bootp.c | 2 +- net/net.c | 2 +- net/rarp.c | 2 +- net/tftp.c | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename {net => include/net}/tftp.h (100%)
diff --git a/net/tftp.h b/include/net/tftp.h similarity index 100% rename from net/tftp.h rename to include/net/tftp.h diff --git a/net/bootp.c b/net/bootp.c index 43466af..b2f8ad4 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -11,8 +11,8 @@ #include <common.h> #include <command.h> #include <net.h> +#include <net/tftp.h> #include "bootp.h" -#include "tftp.h" #include "nfs.h" #ifdef CONFIG_STATUS_LED #include <status_led.h> diff --git a/net/net.c b/net/net.c index 67e0ad2..61e010f 100644 --- a/net/net.c +++ b/net/net.c @@ -86,6 +86,7 @@ #include <environment.h> #include <errno.h> #include <net.h> +#include <net/tftp.h> #if defined(CONFIG_STATUS_LED) #include <miiphy.h> #include <status_led.h> @@ -105,7 +106,6 @@ #if defined(CONFIG_CMD_SNTP) #include "sntp.h" #endif -#include "tftp.h"
DECLARE_GLOBAL_DATA_PTR;
diff --git a/net/rarp.c b/net/rarp.c index 4ce2f37..1fa11b6 100644 --- a/net/rarp.c +++ b/net/rarp.c @@ -8,10 +8,10 @@ #include <common.h> #include <command.h> #include <net.h> +#include <net/tftp.h> #include "nfs.h" #include "bootp.h" #include "rarp.h" -#include "tftp.h"
#define TIMEOUT 5000UL /* Milliseconds before trying BOOTP again */ #ifndef CONFIG_NET_RETRY_COUNT diff --git a/net/tftp.c b/net/tftp.c index 89be32a..1a51131 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -10,7 +10,7 @@ #include <command.h> #include <mapmem.h> #include <net.h> -#include "tftp.h" +#include <net/tftp.h> #include "bootp.h" #ifdef CONFIG_SYS_DIRECT_FLASH_TFTP #include <flash.h>

Up till now it was impossible to use code from update.c when system was not equipped with raw FLASH memory. Such behavior prevented DFU from reusing this code.
Signed-off-by: Lukasz Majewski l.majewski@majess.pl Acked-by: Joe Hershberger joe.hershberger@ni.com Reviewed-by: Simon Glass sjg@chromium.org
--- Changes for v2: - None
Changes for v3: - None
Changes for v4: - None
Change-Id: If79887d3ad3a7aa09fe91d60d7155cf021118bbf --- common/update.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/common/update.c b/common/update.c index 1c6aa18..542915c 100644 --- a/common/update.c +++ b/common/update.c @@ -13,10 +13,6 @@ #error "CONFIG_FIT and CONFIG_OF_LIBFDT are required for auto-update feature" #endif
-#if defined(CONFIG_SYS_NO_FLASH) -#error "CONFIG_SYS_NO_FLASH defined, but FLASH is required for auto-update feature" -#endif - #include <command.h> #include <flash.h> #include <net.h> @@ -41,11 +37,11 @@
extern ulong tftp_timeout_ms; extern int tftp_timeout_count_max; -extern flash_info_t flash_info[]; extern ulong load_addr; - +#ifndef CONFIG_SYS_NO_FLASH +extern flash_info_t flash_info[]; static uchar *saved_prot_info; - +#endif static int update_load(char *filename, ulong msec_max, int cnt_max, ulong addr) { int size, rv; @@ -94,6 +90,7 @@ static int update_load(char *filename, ulong msec_max, int cnt_max, ulong addr) return rv; }
+#ifndef CONFIG_SYS_NO_FLASH static int update_flash_protect(int prot, ulong addr_first, ulong addr_last) { uchar *sp_info_ptr; @@ -165,9 +162,11 @@ static int update_flash_protect(int prot, ulong addr_first, ulong addr_last)
return 0; } +#endif
static int update_flash(ulong addr_source, ulong addr_first, ulong size) { +#ifndef CONFIG_SYS_NO_FLASH ulong addr_last = addr_first + size - 1;
/* round last address to the sector boundary */ @@ -203,7 +202,7 @@ static int update_flash(ulong addr_source, ulong addr_first, ulong size) printf("Error: could not protect flash sectors\n"); return 1; } - +#endif return 0; }

This commit adds initial support for using tftp for downloading and upgrading firmware on the device.
Signed-off-by: Lukasz Majewski l.majewski@majess.pl Acked-by: Joe Hershberger joe.hershberger@ni.com
--- Changes for v2: - Return -ENOSYS instead of plain -1 - Remove interface and devstring env variables reading in the dfu_tftp_write() - Those parameters are now passed to dfu_tftp_write() function as its arguments
Changes for v3: - None
Changes for v4: - Comment for dfu_tftp_write() function added to <dfu.h>
Change-Id: I9ff1c6a27188c0dabf5e6a65a70f66ba3bad3350 --- drivers/dfu/Makefile | 1 + drivers/dfu/dfu_tftp.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/dfu.h | 26 ++++++++++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 drivers/dfu/dfu_tftp.c
diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile index cebea30..61f2b71 100644 --- a/drivers/dfu/Makefile +++ b/drivers/dfu/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_DFU_MMC) += dfu_mmc.o obj-$(CONFIG_DFU_NAND) += dfu_nand.o obj-$(CONFIG_DFU_RAM) += dfu_ram.o obj-$(CONFIG_DFU_SF) += dfu_sf.o +obj-$(CONFIG_DFU_TFTP) += dfu_tftp.o diff --git a/drivers/dfu/dfu_tftp.c b/drivers/dfu/dfu_tftp.c new file mode 100644 index 0000000..cd71708 --- /dev/null +++ b/drivers/dfu/dfu_tftp.c @@ -0,0 +1,65 @@ +/* + * (C) Copyright 2015 + * Lukasz Majewski l.majewski@majess.pl + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <malloc.h> +#include <errno.h> +#include <dfu.h> + +int dfu_tftp_write(char *dfu_entity_name, unsigned int addr, unsigned int len, + char *interface, char *devstring) +{ + char *s, *sb; + int alt_setting_num, ret; + struct dfu_entity *dfu; + + debug("%s: name: %s addr: 0x%x len: %d device: %s:%s\n", __func__, + dfu_entity_name, addr, len, interface, devstring); + + ret = dfu_init_env_entities(interface, devstring); + if (ret) + goto done; + + /* + * We need to copy name pointed by *dfu_entity_name since this text + * is the integral part of the FDT image. + * Any implicit modification (i.e. done by strsep()) will corrupt + * the FDT image and prevent other images to be stored. + */ + s = strdup(dfu_entity_name); + sb = s; + if (!s) { + ret = -ENOMEM; + goto done; + } + + strsep(&s, "@"); + debug("%s: image name: %s strlen: %d\n", __func__, sb, strlen(sb)); + + alt_setting_num = dfu_get_alt(sb); + free(sb); + if (alt_setting_num < 0) { + error("Alt setting [%d] to write not found!", + alt_setting_num); + ret = -ENODEV; + goto done; + } + + dfu = dfu_get_entity(alt_setting_num); + if (!dfu) { + error("DFU entity for alt: %d not found!", alt_setting_num); + ret = -ENODEV; + goto done; + } + + ret = dfu_write_from_mem_addr(dfu, (void *)addr, len); + +done: + dfu_free_entities(); + + return ret; +} diff --git a/include/dfu.h b/include/dfu.h index 7d31abd..2153d00 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -207,5 +207,31 @@ static inline int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, } #endif
+/** + * dfu_tftp_write - Write TFTP data to DFU medium + * + * This function is storing data received via TFTP on DFU supported medium. + * + * @param dfu_entity_name - name of DFU entity to write + * @param addr - address of data buffer to write + * @param len - number of bytes + * @param interface - destination DFU medium (e.g. "mmc") + * @param devstring - instance number of destination DFU medium (e.g. "1") + * + * @return 0 on success, otherwise error code + */ +#ifdef CONFIG_DFU_TFTP +int dfu_tftp_write(char *dfu_entity_name, unsigned int addr, unsigned int len, + char *interface, char *devstring); +#else +static inline int dfu_tftp_write(char *dfu_entity_name, unsigned int addr, + unsigned int len, char *interface, + char *devstring) +{ + puts("TFTP write support for DFU not available!\n"); + return -ENOSYS; +} +#endif + int dfu_add(struct usb_configuration *c); #endif /* __DFU_ENTITY_H_ */

This function allows writing via DFU data stored from fixed buffer address (like e.g. loadaddr env variable).
Such predefined buffers are used in the update_tftp() code. In fact this function is a wrapper on the dfu_write() and dfu_flush().
Signed-off-by: Lukasz Majewski l.majewski@majess.pl Acked-by: Joe Hershberger joe.hershberger@ni.com --- Changes for v2: - Use min() macro instead of comparison - Change definition of left variable to be unsigned long - this allowed safe usage of min() macro
Changes for v3: - Move new function description to ./include/dfu.h
Changes for v4: - None
Change-Id: Ia4c36602398100139a0b2faf1b8827baf6b67aaa --- drivers/dfu/dfu.c | 37 +++++++++++++++++++++++++++++++++++++ include/dfu.h | 15 +++++++++++++++ 2 files changed, 52 insertions(+)
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 2267dbf..6cf240d 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -568,3 +568,40 @@ int dfu_get_alt(char *name)
return -ENODEV; } + +int dfu_write_from_mem_addr(struct dfu_entity *dfu, void *buf, int size) +{ + unsigned long dfu_buf_size, write, left = size; + int i, ret = 0; + void *dp = buf; + + /* + * Here we must call dfu_get_buf(dfu) first to be sure that dfu_buf_size + * has been properly initialized - e.g. if "dfu_bufsiz" has been taken + * into account. + */ + dfu_get_buf(dfu); + dfu_buf_size = dfu_get_buf_size(); + debug("%s: dfu buf size: %lu\n", __func__, dfu_buf_size); + + for (i = 0; left > 0; i++) { + write = min(dfu_buf_size, left); + + debug("%s: dp: 0x%p left: %lu write: %lu\n", __func__, + dp, left, write); + ret = dfu_write(dfu, dp, write, i); + if (ret) { + error("DFU write failed\n"); + return ret; + } + + dp += write; + left -= write; + } + + ret = dfu_flush(dfu, NULL, 0, i); + if (ret) + error("DFU flush failed!"); + + return ret; +} diff --git a/include/dfu.h b/include/dfu.h index 2153d00..6118dc2 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -162,6 +162,21 @@ bool dfu_usb_get_reset(void); int dfu_read(struct dfu_entity *de, void *buf, int size, int blk_seq_num); int dfu_write(struct dfu_entity *de, void *buf, int size, int blk_seq_num); int dfu_flush(struct dfu_entity *de, void *buf, int size, int blk_seq_num); + +/** + * dfu_write_from_mem_addr - write data from memory to DFU managed medium + * + * This function adds support for writing data starting from fixed memory + * address (like $loadaddr) to dfu managed medium (e.g. NAND, MMC, file system) + * + * @param dfu - dfu entity to which we want to store data + * @param buf - fixed memory addres from where data starts + * @param size - number of bytes to write + * + * @return - 0 on success, other value on failure + */ +int dfu_write_from_mem_addr(struct dfu_entity *dfu, void *buf, int size); + /* Device specific */ #ifdef CONFIG_DFU_MMC extern int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s);

This code allows using DFU defined mediums for storing data received via TFTP protocol.
It reuses and preserves functionality of legacy code at common/update.c.
The update_tftp() function now accepts parameters - namely medium device name and its number (e.g. mmc 1).
Without this information passed old behavior is preserved.
Signed-off-by: Lukasz Majewski l.majewski@majess.pl Acked-by: Joe Hershberger joe.hershberger@ni.com --- Changes for v2: - Remove env variables from update_tftp() function - Add parameters to update_tftp() function - without them old behavior is preserved - Stop compilation when legacy flags (CONFIG_UPDATE_TFTP and CONFIG_SYS_NO_FLASH) are wrongly defined - In the u-boot code legacy calls to update_tftp(0UL) have been changed to update_tftp(0UL, NULL, NULL)
Changes for v3: - Add proper update_tftp() function description in the ./include/net.h file
Changes for v4: - Provide input data checks (interface && devstring) to preserve the old behavior of update_tftp() function. Moreover, when interface or devstring equals to NULL a error code is returned. - Return immediately with proper error code when write of one of firmware data images fails.
Change-Id: I6ea454b480302d763f91cdf39a689a5af2046bdb --- common/Makefile | 1 + common/cmd_fitupd.c | 2 +- common/main.c | 2 +- common/update.c | 47 +++++++++++++++++++++++++++++++++++++---------- include/net.h | 14 ++++++++++++-- 5 files changed, 52 insertions(+), 14 deletions(-)
diff --git a/common/Makefile b/common/Makefile index dc82433..9ff1ab6 100644 --- a/common/Makefile +++ b/common/Makefile @@ -209,6 +209,7 @@ obj-$(CONFIG_LYNXKDI) += lynxkdi.o obj-$(CONFIG_MENU) += menu.o obj-$(CONFIG_MODEM_SUPPORT) += modem.o obj-$(CONFIG_UPDATE_TFTP) += update.o +obj-$(CONFIG_DFU_TFTP) += update.o obj-$(CONFIG_USB_KEYBOARD) += usb_kbd.o obj-$(CONFIG_CMD_DFU) += cmd_dfu.o obj-$(CONFIG_CMD_GPT) += cmd_gpt.o diff --git a/common/cmd_fitupd.c b/common/cmd_fitupd.c index b045974..78b8747 100644 --- a/common/cmd_fitupd.c +++ b/common/cmd_fitupd.c @@ -23,7 +23,7 @@ static int do_fitupd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (argc == 2) addr = simple_strtoul(argv[1], NULL, 16);
- return update_tftp(addr); + return update_tftp(addr, NULL, NULL); }
U_BOOT_CMD(fitupd, 2, 0, do_fitupd, diff --git a/common/main.c b/common/main.c index 2979fbe..ead0cd1 100644 --- a/common/main.c +++ b/common/main.c @@ -75,7 +75,7 @@ void main_loop(void) run_preboot_environment_command();
#if defined(CONFIG_UPDATE_TFTP) - update_tftp(0UL); + update_tftp(0UL, NULL, NULL); #endif /* CONFIG_UPDATE_TFTP */
s = bootdelay_process(); diff --git a/common/update.c b/common/update.c index 542915c..1da80b7 100644 --- a/common/update.c +++ b/common/update.c @@ -13,11 +13,17 @@ #error "CONFIG_FIT and CONFIG_OF_LIBFDT are required for auto-update feature" #endif
+#if defined(CONFIG_UPDATE_TFTP) && defined(CONFIG_SYS_NO_FLASH) +#error "CONFIG_UPDATE_TFTP and CONFIG_SYS_NO_FLASH needed for legacy behaviour" +#endif + #include <command.h> #include <flash.h> #include <net.h> #include <net/tftp.h> #include <malloc.h> +#include <dfu.h> +#include <errno.h>
/* env variable holding the location of the update file */ #define UPDATE_FILE_ENV "updatefile" @@ -222,13 +228,24 @@ static int update_fit_getparams(const void *fit, int noffset, ulong *addr, return 0; }
-int update_tftp(ulong addr) +int update_tftp(ulong addr, char *interface, char *devstring) { - char *filename, *env_addr; - int images_noffset, ndepth, noffset; + char *filename, *env_addr, *fit_image_name; ulong update_addr, update_fladdr, update_size; - void *fit; + int images_noffset, ndepth, noffset; + bool update_tftp_dfu; int ret = 0; + void *fit; + + if (interface == NULL && devstring == NULL) { + update_tftp_dfu = false; + } else if (interface && devstring) { + update_tftp_dfu = true; + } else { + error("Interface: %s and devstring: %s not supported!\n", + interface, devstring); + return -EINVAL; + }
/* use already present image */ if (addr) @@ -277,8 +294,8 @@ got_update_file: if (ndepth != 1) goto next_node;
- printf("Processing update '%s' :", - fit_get_name(fit, noffset, NULL)); + fit_image_name = (char *)fit_get_name(fit, noffset, NULL); + printf("Processing update '%s' :", fit_image_name);
if (!fit_image_verify(fit, noffset)) { printf("Error: invalid update hash, aborting\n"); @@ -294,10 +311,20 @@ got_update_file: ret = 1; goto next_node; } - if (update_flash(update_addr, update_fladdr, update_size)) { - printf("Error: can't flash update, aborting\n"); - ret = 1; - goto next_node; + + if (!update_tftp_dfu) { + if (update_flash(update_addr, update_fladdr, + update_size)) { + printf("Error: can't flash update, aborting\n"); + ret = 1; + goto next_node; + } + } else if (fit_image_check_type(fit, noffset, + IH_TYPE_FIRMWARE)) { + ret = dfu_tftp_write(fit_image_name, update_addr, + update_size, interface, devstring); + if (ret) + return ret; } next_node: noffset = fdt_next_node(fit, noffset, &ndepth); diff --git a/include/net.h b/include/net.h index d09bec9..f1671e3 100644 --- a/include/net.h +++ b/include/net.h @@ -813,8 +813,18 @@ void copy_filename(char *dst, const char *src, int size); /* get a random source port */ unsigned int random_port(void);
-/* Update U-Boot over TFTP */ -int update_tftp(ulong addr); +/** + * update_tftp - Update firmware over TFTP (via DFU) + * + * This function updates board's firmware via TFTP + * + * @param addr - memory address where data is stored + * @param interface - the DFU medium name - e.g. "mmc" + * @param devstring - the DFU medium number - e.g. "1" + * + * @return - 0 on success, other value on failure + */ +int update_tftp(ulong addr, char *interface, char *devstring);
/**********************************************************************/

The "dfu" command has been extended to support transfers via TFTP protocol.
Signed-off-by: Lukasz Majewski l.majewski@majess.pl Reviewed-by: Simon Glass sjg@chromium.org Acked-by: Joe Hershberger joe.hershberger@ni.com --- Changes for v2: - Remove "dfutftp" command - Modify "dfu" command to support optional [tftp] parameter - Only one flag (CONFIG_DFU_TFTP) needs to be enabled
Changes for v3: - Remove #ifdef CONFIG_DFU_TFTP to guard including <net.h> - Do not use usb_controller variable in the 'dfu tftp' case - Make the tftp as the explicit parameter for the 'dfu tftp' command - Correct help message for 'dfu tftp' command
Changes for v4: - None
Change-Id: I0f55ad0e7096acf3ba52705b3c55d1d397edc8f2 --- common/cmd_dfu.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c index 857148f..f060db7 100644 --- a/common/cmd_dfu.c +++ b/common/cmd_dfu.c @@ -1,6 +1,9 @@ /* * cmd_dfu.c -- dfu command * + * Copyright (C) 2015 + * Lukasz Majewski l.majewski@majess.pl + * * Copyright (C) 2012 Samsung Electronics * authors: Andrzej Pietrasiewicz andrzej.p@samsung.com * Lukasz Majewski l.majewski@samsung.com @@ -13,6 +16,7 @@ #include <dfu.h> #include <g_dnl.h> #include <usb.h> +#include <net.h>
static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { @@ -26,6 +30,15 @@ static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) char *devstring = argv[3];
int ret, i = 0; +#ifdef CONFIG_DFU_TFTP + unsigned long addr = 0; + if (!strcmp(argv[1], "tftp")) { + if (argc == 5) + addr = simple_strtoul(argv[4], NULL, 0); + + return update_tftp(addr, interface, devstring); + } +#endif
ret = dfu_init_env_entities(interface, devstring); if (ret) @@ -89,4 +102,11 @@ U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu, " on device <dev>, attached to interface\n" " <interface>\n" " [list] - list available alt settings\n" +#ifdef CONFIG_DFU_TFTP + "dfu tftp <interface> <dev> [<addr>]\n" + " - device firmware upgrade via TFTP\n" + " on device <dev>, attached to interface\n" + " <interface>\n" + " [<addr>] - address where FIT image has been stored\n" +#endif );

The dfu tftp feature can be now enabled via Kconfig. This commit provides necessary code for it.
Signed-off-by: Lukasz Majewski l.majewski@majess.pl --- Changes for v3: - New patch
Changes for v4: - Replace "Enable support for performing Device Firmware Upgrade via TFTP" with "DFU via TFTP"
Change-Id: Icd24aa8852f0c9c0828d0a3f2af01ebdea12fc73 --- drivers/dfu/Kconfig | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/drivers/dfu/Kconfig b/drivers/dfu/Kconfig index e69de29..4fe2219 100644 --- a/drivers/dfu/Kconfig +++ b/drivers/dfu/Kconfig @@ -0,0 +1,10 @@ +menu "DFU support" + +config DFU_TFTP + bool "DFU via TFTP" + help + This option allows performing update of DFU managed medium with data + send via TFTP boot. + Detailed description of this feature can be found at ./doc/README.dfutftp + +endmenu

This commit enables support for DFU_TFTP on the am335x bone black device.
Signed-off-by: Lukasz Majewski l.majewski@majess.pl
--- Changes for v3: - New patch
Changes for v4: - None
Change-Id: Ia418b394df142cfa294ef87c9a1b748410332b0e --- configs/am335x_boneblack_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/am335x_boneblack_defconfig b/configs/am335x_boneblack_defconfig index 60339c8..f1ff65f 100644 --- a/configs/am335x_boneblack_defconfig +++ b/configs/am335x_boneblack_defconfig @@ -8,3 +8,4 @@ CONFIG_SYS_EXTRA_OPTIONS="EMMC_BOOT" # CONFIG_CMD_FLASH is not set # CONFIG_CMD_SETEXPR is not set CONFIG_SPI_FLASH=y +CONFIG_DFU_TFTP=y

Hi Lukasz,
On Sun, Aug 23, 2015 at 5:21 PM, Lukasz Majewski l.majewski@majess.pl wrote:
This commit enables support for DFU_TFTP on the am335x bone black device.
Signed-off-by: Lukasz Majewski l.majewski@majess.pl
Acked-by: Joe Hershberger joe.hershberger@ni.com

Hi Lukasz,
On Sun, Aug 23, 2015 at 5:21 PM, Lukasz Majewski l.majewski@majess.pl wrote:
This commit series enables DFU subsystem to use ETH and TFTP protocol as a medium for downloading data, which should bring substantial speedup for writing large files (like rootfs).
Please read provided ./doc/README.dfutftp documentation entry for more information.
Those patches should be applied on the u-boot/master branch: SHA1: 8d77576371381ade83de475bb639949b44941e8c
Do you want to pull this into the DFU tree or through the net tree?
-Joe

On Mon, 24 Aug 2015 22:07:16 -0500 Joe Hershberger joe.hershberger@gmail.com wrote:
Hi Lukasz,
On Sun, Aug 23, 2015 at 5:21 PM, Lukasz Majewski l.majewski@majess.pl wrote:
This commit series enables DFU subsystem to use ETH and TFTP protocol as a medium for downloading data, which should bring substantial speedup for writing large files (like rootfs).
Please read provided ./doc/README.dfutftp documentation entry for more information.
Those patches should be applied on the u-boot/master branch: SHA1: 8d77576371381ade83de475bb639949b44941e8c
Do you want to pull this into the DFU tree or through the net tree?
-Joe
I think that this patch series fits better to DFU tree. Since I've got your ACKs there is not problem to take them there.
Thanks one more time for your review.
Best regards, Lukasz Majewski

Hi Joe,
Hi Lukasz,
On Sun, Aug 23, 2015 at 5:21 PM, Lukasz Majewski l.majewski@majess.pl wrote:
This commit series enables DFU subsystem to use ETH and TFTP protocol as a medium for downloading data, which should bring substantial speedup for writing large files (like rootfs).
Please read provided ./doc/README.dfutftp documentation entry for more information.
Those patches should be applied on the u-boot/master branch: SHA1: 8d77576371381ade83de475bb639949b44941e8c
Do you want to pull this into the DFU tree or through the net tree?
-Joe
I've pulled this patch series to u-boot-dfu tree.
Thanks for support!

Hi Lukasz,
On Wed, Aug 26, 2015 at 10:10 AM, Lukasz Majewski l.majewski@samsung.com wrote:
Hi Joe,
Hi Lukasz,
On Sun, Aug 23, 2015 at 5:21 PM, Lukasz Majewski l.majewski@majess.pl wrote:
This commit series enables DFU subsystem to use ETH and TFTP protocol as a medium for downloading data, which should bring substantial speedup for writing large files (like rootfs).
Please read provided ./doc/README.dfutftp documentation entry for more information.
Those patches should be applied on the u-boot/master branch: SHA1: 8d77576371381ade83de475bb639949b44941e8c
Do you want to pull this into the DFU tree or through the net tree?
-Joe
I've pulled this patch series to u-boot-dfu tree.
Thanks for support!
No problem. It turned out good.
-Joe
participants (3)
-
Joe Hershberger
-
Lukasz Majewski
-
Lukasz Majewski