From 1bf73bdeae43f253f432489f6fe71e3bfa763706 Mon Sep 17 00:00:00 2001 From: Jiandong Zheng Date: Thu, 9 Jul 2015 14:26:40 -0700 Subject: implement Fastboot via USB OTG on bcm28155_ap boards Signed-off-by: Jiandong Zheng Signed-off-by: Steve Rae --- include/configs/bcm28155_ap.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/configs/bcm28155_ap.h b/include/configs/bcm28155_ap.h index b7c5716eae..7b48875d63 100644 --- a/include/configs/bcm28155_ap.h +++ b/include/configs/bcm28155_ap.h @@ -153,4 +153,23 @@ #define CONFIG_G_DNL_PRODUCT_NUM 0x0d02 /* nexus one */ #define CONFIG_G_DNL_MANUFACTURER "Broadcom Corporation" +/* Fastboot and USB OTG */ +#define CONFIG_USB_FUNCTION_FASTBOOT +#define CONFIG_CMD_FASTBOOT +#define CONFIG_FASTBOOT_FLASH +#define CONFIG_FASTBOOT_FLASH_MMC_DEV 0 +#define CONFIG_SYS_CACHELINE_SIZE 64 +#define CONFIG_USB_FASTBOOT_BUF_SIZE (CONFIG_SYS_SDRAM_SIZE - SZ_1M) +#define CONFIG_USB_FASTBOOT_BUF_ADDR CONFIG_SYS_SDRAM_BASE +#define CONFIG_USB_GADGET +#define CONFIG_USB_GADGET_DUALSPEED +#define CONFIG_USB_GADGET_VBUS_DRAW 0 +#define CONFIG_USB_GADGET_S3C_UDC_OTG +#define CONFIG_USB_GADGET_BCM_UDC_OTG_PHY +#define CONFIG_USB_GADGET_DOWNLOAD +#define CONFIG_USBID_ADDR 0x34052c46 +#define CONFIG_G_DNL_VENDOR_NUM 0x18d1 /* google */ +#define CONFIG_G_DNL_PRODUCT_NUM 0x0d02 /* nexus one */ +#define CONFIG_G_DNL_MANUFACTURER "Broadcom Corporation" + #endif /* __BCM28155_AP_H */ -- cgit v1.2.3 From 41d237de6acbd5d3a8fac106dbea2d00f044c4f9 Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Thu, 16 Apr 2015 10:38:34 +0200 Subject: f_thor: Dont perform reset at the end of thor Dont perform reset at the end of thor download if configured to do reset off. Reset may not be required in all cases and hence provided an option to do so. The case would be to download the images to DDR instead of flash device. Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Michal Simek --- drivers/usb/gadget/f_thor.c | 7 +++++++ drivers/usb/gadget/f_thor.h | 3 +++ 2 files changed, 10 insertions(+) diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c index 6346370cd6..2596b2ee4a 100644 --- a/drivers/usb/gadget/f_thor.c +++ b/drivers/usb/gadget/f_thor.c @@ -123,6 +123,9 @@ static int process_rqt_cmd(const struct rqt_box *rqt) send_rsp(rsp); g_dnl_unregister(); dfu_free_entities(); +#ifdef CONFIG_THOR_RESET_OFF + return RESET_DONE; +#endif run_command("reset", 0); break; case RQT_CMD_POWEROFF: @@ -728,6 +731,10 @@ int thor_handle(void) if (ret > 0) { ret = process_data(); +#ifdef CONFIG_THOR_RESET_OFF + if (ret == RESET_DONE) + break; +#endif if (ret < 0) return ret; } else { diff --git a/drivers/usb/gadget/f_thor.h b/drivers/usb/gadget/f_thor.h index 833a9d24ae..83412851dd 100644 --- a/drivers/usb/gadget/f_thor.h +++ b/drivers/usb/gadget/f_thor.h @@ -121,4 +121,7 @@ struct f_thor { #define F_NAME_BUF_SIZE 32 #define THOR_PACKET_SIZE SZ_1M /* 1 MiB */ #define THOR_STORE_UNIT_SIZE SZ_32M /* 32 MiB */ +#ifdef CONFIG_THOR_RESET_OFF +#define RESET_DONE 0xFFFFFFFF +#endif #endif /* _USB_THOR_H_ */ -- cgit v1.2.3 From 58f99df448501041a8092b281ff7adf0bd4f38ac Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Wed, 15 Apr 2015 13:42:19 +0200 Subject: usb: gadget: f_thor: Allocate request up to THOR_PACKET_SIZE Allocate request up to THOR_PACKET_SIZE not the ep0->maxpacket as the descriptors data depend on the number of descriptors and this 64 bytes were not enough and the buffer might overflow which results in memalign failures later. Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Michal Simek --- drivers/usb/gadget/f_thor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c index 2596b2ee4a..06139ee04d 100644 --- a/drivers/usb/gadget/f_thor.c +++ b/drivers/usb/gadget/f_thor.c @@ -775,7 +775,7 @@ static int thor_func_bind(struct usb_configuration *c, struct usb_function *f) goto fail; } dev->req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, - gadget->ep0->maxpacket); + THOR_PACKET_SIZE); if (!dev->req->buf) { status = -ENOMEM; goto fail; -- cgit v1.2.3 From 33a6103578680ed41a946214462703df2c3646b2 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Sat, 15 Aug 2015 11:23:45 +0200 Subject: dfu:tests: Modify dfu_gadget_test.sh to accept USB device vendor:product ID dfu-util allows filtering on USB device vendor:product ID by using the -d flag (-d 0451:d022). Such option is very handy when many DFU devices are connected to a single host PC. This commit allows testing when above situation emerges. Signed-off-by: Lukasz Majewski Reviewed-by: Simon Glass Tested-by: Lukasz Majewski Test HW - AM335x Beagle Bone Black NOTE: Max size of file to transfer: 2MiB --- test/dfu/README | 9 ++++++++- test/dfu/dfu_gadget_test.sh | 18 +++++++++++------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/test/dfu/README b/test/dfu/README index 5176aba632..408d559421 100644 --- a/test/dfu/README +++ b/test/dfu/README @@ -26,12 +26,19 @@ Example usage: setenv dfu_alt_info dfu_test.bin fat 0 6\;dfudummy.bin fat 0 6 dfu 0 mmc 0 2. On the host: - test/dfu/dfu_gadget_test.sh X Y [test file name] + test/dfu/dfu_gadget_test.sh X Y [test file name] [usb device vendor:product] e.g. test/dfu/dfu_gadget_test.sh 0 1 or e.g. test/dfu/dfu_gadget_test.sh 0 1 ./dat_960.img + or + e.g. test/dfu/dfu_gadget_test.sh 0 1 0451:d022 + or + e.g. test/dfu/dfu_gadget_test.sh 0 1 ./dat_960.img 0451:d022 ... where X and Y are dfu_test.bin's and dfudummy.bin's alt setting numbers. They can be obtained from dfu-util -l or $dfu_alt_info. It is also possible to pass optional [test file name] to force the script to test one particular file. +If many DFU devices are connected, it may be useful to filter on USB +vendor/product ID (0451:d022). +One can get them by running "lsusb" command on a host PC. diff --git a/test/dfu/dfu_gadget_test.sh b/test/dfu/dfu_gadget_test.sh index 2f5b7db58d..9c7942257b 100755 --- a/test/dfu/dfu_gadget_test.sh +++ b/test/dfu/dfu_gadget_test.sh @@ -45,18 +45,18 @@ dfu_test_file () { printf "$COLOUR_GREEN ========================================================================================= $COLOUR_DEFAULT\n" printf "File:$COLOUR_GREEN %s $COLOUR_DEFAULT\n" $1 - dfu-util -D $1 -a $TARGET_ALT_SETTING >> $LOG_FILE 2>&1 || die $? + dfu-util $USB_DEV -D $1 -a $TARGET_ALT_SETTING >> $LOG_FILE 2>&1 || die $? echo -n "TX: " calculate_md5sum $1 MD5_TX=$MD5SUM - dfu-util -D ${DIR}/dfudummy.bin -a $TARGET_ALT_SETTING_B >> $LOG_FILE 2>&1 || die $? + dfu-util $USB_DEV -D ${DIR}/dfudummy.bin -a $TARGET_ALT_SETTING_B >> $LOG_FILE 2>&1 || die $? N_FILE=$DIR$RCV_DIR${1:2}"_rcv" - dfu-util -U $N_FILE -a $TARGET_ALT_SETTING >> $LOG_FILE 2>&1 || die $? + dfu-util $USB_DEV -U $N_FILE -a $TARGET_ALT_SETTING >> $LOG_FILE 2>&1 || die $? echo -n "RX: " calculate_md5sum $N_FILE @@ -89,13 +89,17 @@ fi TARGET_ALT_SETTING=$1 TARGET_ALT_SETTING_B=$2 -if [ -n "$3" ] +file=$3 +[[ $3 == *':'* ]] && USB_DEV="-d $3" && file="" +[ $# -eq 4 ] && USB_DEV="-d $4" + +if [ -n "$file" ] then - dfu_test_file $3 + dfu_test_file $file else - for file in $DIR*.$SUFFIX + for f in $DIR*.$SUFFIX do - dfu_test_file $file + dfu_test_file $f done fi -- cgit v1.2.3 From a7e6892ffb625e5a335538f937d56005aa1480c5 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Wed, 8 Jul 2015 23:43:18 +0200 Subject: dfu: Delete superfluous initialization of the dfu_buf_size static variable After extension of the dfu_get_buf() to also setup (implicitly) the dfu_buf_size variable it is not needed to set dfu_buf_size to CONFIG_SYS_DFU_DATA_BUF_SIZE. This variable is set in the dfu_get_buf() by not only considering CONFIG_SYS_DFU_DATA_BUF but more importantly the "dfu_bufsiz" env variable. Therefore, dfu_get_buf() should be used for initialization. Signed-off-by: Lukasz Majewski Reviewed-by: Przemyslaw Marczak --- drivers/dfu/dfu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 675162d927..2267dbfb51 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -76,7 +76,7 @@ int dfu_init_env_entities(char *interface, char *devstr) } static unsigned char *dfu_buf; -static unsigned long dfu_buf_size = CONFIG_SYS_DFU_DATA_BUF_SIZE; +static unsigned long dfu_buf_size; unsigned char *dfu_free_buf(void) { -- cgit v1.2.3 From cc4f1558a72621b1ac766e54e1ab5aab824bb7dd Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Fri, 21 Aug 2015 11:02:04 +0530 Subject: h2200: Fix build error Commit <8bfc288c3955> ("usb: gadget: ether: Perform board initialization from ethernet gadget driver") added board_usb_init and board_usb_cleanup in ethernet gadget driver. But h2200 board didn't have board_usb_init and board_usb_cleanup implementations. This introduced the following build errors +drivers/usb/gadget/built-in.o: In function `usb_eth_halt': +drivers/usb/gadget/ether.c:2498: undefined reference to `board_usb_cleanup' +drivers/usb/gadget/built-in.o: In function `usb_eth_init': +drivers/usb/gadget/ether.c:2316: undefined reference to `board_usb_init' Fix it here by adding empty board_usb_init and board_usb_cleanup functions in h2200.c. Fixes: <8bfc288c3955> ("usb: gadget: ether: Perform board initialization from ethernet gadget driver") Signed-off-by: Kishon Vijay Abraham I --- board/h2200/h2200.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/board/h2200/h2200.c b/board/h2200/h2200.c index 66ae4b6906..01f8e67be1 100644 --- a/board/h2200/h2200.c +++ b/board/h2200/h2200.c @@ -59,3 +59,15 @@ int dram_init(void) gd->ram_size = CONFIG_SYS_SDRAM_SIZE; return 0; } + +#ifdef CONFIG_USB_GADGET_PXA2XX +int board_usb_init(int index, enum usb_init_type init) +{ + return 0; +} + +int board_usb_cleanup(int index, enum usb_init_type init) +{ + return 0; +} +#endif -- cgit v1.2.3 From 5a6087277c271773248e30c53ba494e328a7d476 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Mon, 24 Aug 2015 00:21:42 +0200 Subject: doc: dfu: tftp: README entry for TFTP extension of DFU 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 Reviewed-by: Simon Glass Acked-by: Joe Hershberger --- 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 0000000000..0257f0d503 --- /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 a7f4d9ebe5..eab124ce1d 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. -- cgit v1.2.3 From 346969584be509b444dd1ba0db31ca7adb47575b Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Mon, 24 Aug 2015 00:21:43 +0200 Subject: net: tftp: Move tftp.h file from ./net to ./include/net This change gives the ability to reuse the 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 Acked-by: Joe Hershberger --- include/net/tftp.h | 30 ++++++++++++++++++++++++++++++ net/bootp.c | 2 +- net/net.c | 2 +- net/rarp.c | 2 +- net/tftp.c | 2 +- net/tftp.h | 30 ------------------------------ 6 files changed, 34 insertions(+), 34 deletions(-) create mode 100644 include/net/tftp.h delete mode 100644 net/tftp.h diff --git a/include/net/tftp.h b/include/net/tftp.h new file mode 100644 index 0000000000..c411c9b2e6 --- /dev/null +++ b/include/net/tftp.h @@ -0,0 +1,30 @@ +/* + * LiMon - BOOTP/TFTP. + * + * Copyright 1994, 1995, 2000 Neil Russell. + * Copyright 2011 Comelit Group SpA + * Luca Ceresoli + * (See License) + */ + +#ifndef __TFTP_H__ +#define __TFTP_H__ + +/**********************************************************************/ +/* + * Global functions and variables. + */ + +/* tftp.c */ +void tftp_start(enum proto_t protocol); /* Begin TFTP get/put */ + +#ifdef CONFIG_CMD_TFTPSRV +void tftp_start_server(void); /* Wait for incoming TFTP put */ +#endif + +extern ulong tftp_timeout_ms; +extern int tftp_timeout_count_max; + +/**********************************************************************/ + +#endif /* __TFTP_H__ */ diff --git a/net/bootp.c b/net/bootp.c index 43466af2f3..b2f8ad4ded 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -11,8 +11,8 @@ #include #include #include +#include #include "bootp.h" -#include "tftp.h" #include "nfs.h" #ifdef CONFIG_STATUS_LED #include diff --git a/net/net.c b/net/net.c index 2a6efd85ea..a115ce2892 100644 --- a/net/net.c +++ b/net/net.c @@ -86,6 +86,7 @@ #include #include #include +#include #if defined(CONFIG_STATUS_LED) #include #include @@ -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 4ce2f37a8a..1fa11b690d 100644 --- a/net/rarp.c +++ b/net/rarp.c @@ -8,10 +8,10 @@ #include #include #include +#include #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 18ce84c202..181f0f363e 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -10,7 +10,7 @@ #include #include #include -#include "tftp.h" +#include #include "bootp.h" #ifdef CONFIG_SYS_DIRECT_FLASH_TFTP #include diff --git a/net/tftp.h b/net/tftp.h deleted file mode 100644 index c411c9b2e6..0000000000 --- a/net/tftp.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * LiMon - BOOTP/TFTP. - * - * Copyright 1994, 1995, 2000 Neil Russell. - * Copyright 2011 Comelit Group SpA - * Luca Ceresoli - * (See License) - */ - -#ifndef __TFTP_H__ -#define __TFTP_H__ - -/**********************************************************************/ -/* - * Global functions and variables. - */ - -/* tftp.c */ -void tftp_start(enum proto_t protocol); /* Begin TFTP get/put */ - -#ifdef CONFIG_CMD_TFTPSRV -void tftp_start_server(void); /* Wait for incoming TFTP put */ -#endif - -extern ulong tftp_timeout_ms; -extern int tftp_timeout_count_max; - -/**********************************************************************/ - -#endif /* __TFTP_H__ */ -- cgit v1.2.3 From 66a647238215b207addc8c9ad22f3816078a7934 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Mon, 24 Aug 2015 00:21:44 +0200 Subject: tftp: update: Allow some parts of the code to be reused when CONFIG_SYS_NO_FLASH is set 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 Acked-by: Joe Hershberger Reviewed-by: Simon Glass --- common/update.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/common/update.c b/common/update.c index 1c6aa186d0..542915ce6e 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 #include #include @@ -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; } -- cgit v1.2.3 From 2d50d68a4ca1cce82899c9f0cfca17edf34bb254 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Mon, 24 Aug 2015 00:21:45 +0200 Subject: dfu: tftp: update: Provide tftp support for the DFU subsystem This commit adds initial support for using tftp for downloading and upgrading firmware on the device. Signed-off-by: Lukasz Majewski Acked-by: Joe Hershberger --- 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 cebea30ac3..61f2b71f91 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 0000000000..cd71708231 --- /dev/null +++ b/drivers/dfu/dfu_tftp.c @@ -0,0 +1,65 @@ +/* + * (C) Copyright 2015 + * Lukasz Majewski + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +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 7d31abdf33..2153d0096d 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_ */ -- cgit v1.2.3 From 2092e4610485618ec7a676ff8e6d297ea9dca3d5 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Mon, 24 Aug 2015 00:21:46 +0200 Subject: dfu: tftp: update: Add dfu_write_from_mem_addr() function 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 Acked-by: Joe Hershberger --- 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 2267dbfb51..6cf240de22 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 2153d0096d..6118dc27b9 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); -- cgit v1.2.3 From c7ff5528439af8f1e6e10424e495eb7d6238d6c5 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Mon, 24 Aug 2015 00:21:47 +0200 Subject: update: tftp: dfu: Extend update_tftp() function to support DFU 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 Acked-by: Joe Hershberger --- 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 f4ba8782f5..556fb07592 100644 --- a/common/Makefile +++ b/common/Makefile @@ -210,6 +210,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 b0459744d9..78b8747336 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 2979fbed63..ead0cd17aa 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 542915ce6e..1da80b70f2 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 #include #include #include #include +#include +#include /* 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 d09bec9de1..f1671e38de 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); /**********************************************************************/ -- cgit v1.2.3 From c2c146fb8890841cfd60cafae69bf6e2f2cbfb1c Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Mon, 24 Aug 2015 00:21:48 +0200 Subject: dfu: command: Extend "dfu" command to handle receiving data via TFTP The "dfu" command has been extended to support transfers via TFTP protocol. Signed-off-by: Lukasz Majewski Reviewed-by: Simon Glass Acked-by: Joe Hershberger --- common/cmd_dfu.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c index 857148f8af..f060db75c6 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 + * * Copyright (C) 2012 Samsung Electronics * authors: Andrzej Pietrasiewicz * Lukasz Majewski @@ -13,6 +16,7 @@ #include #include #include +#include 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 , attached to interface\n" " \n" " [list] - list available alt settings\n" +#ifdef CONFIG_DFU_TFTP + "dfu tftp []\n" + " - device firmware upgrade via TFTP\n" + " on device , attached to interface\n" + " \n" + " [] - address where FIT image has been stored\n" +#endif ); -- cgit v1.2.3 From 585a696e4eebab3b48004cf70e1077fb38287c60 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Mon, 24 Aug 2015 00:21:49 +0200 Subject: dfu: tftp: Kconfig: Add Kconfig entry for dfu tftp feature The dfu tftp feature can be now enabled via Kconfig. This commit provides necessary code for it. Signed-off-by: Lukasz Majewski Acked-by: Joe Hershberger --- drivers/dfu/Kconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/dfu/Kconfig b/drivers/dfu/Kconfig index e69de29bb2..4fe22193b1 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 -- cgit v1.2.3 From 542e02ad41d2083c4a089d25962477c6f66cde9f Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Mon, 24 Aug 2015 00:21:50 +0200 Subject: dfu: tftp: Kconfig: Enable DFU_TFTP support on the am335x_boneblack_defconfig This commit enables support for DFU_TFTP on the am335x bone black device. Signed-off-by: Lukasz Majewski Acked-by: Joe Hershberger --- configs/am335x_boneblack_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/am335x_boneblack_defconfig b/configs/am335x_boneblack_defconfig index 60339c8725..f1ff65fa83 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 -- cgit v1.2.3 From 49b4c5c700077e387fef61a7225f92d190ee0c45 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 20 Aug 2015 17:38:05 -0600 Subject: usb: ehci: remember init mode When an EHCI device is registered in device mode, the HW isn't actually initialized at all, and hence isn't left in a running state. Consequently, when the device is deregistered, ehci_shutdown() will fail, since the HW bits it expects to see set in response to its shutdown requests will not be sent, and the message "EHCI failed to shut down host controller." will be printed. Fix ehci-hcd.c to remember whether the device was registered in host or device mode, and only call ehci_shutdown() for host mode registrations. Signed-off-by: Stephen Warren --- drivers/usb/host/ehci-hcd.c | 7 ++++++- drivers/usb/host/ehci.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 3a0d32ee2b..88b670b7f8 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1645,8 +1645,10 @@ int ehci_register(struct udevice *dev, struct ehci_hccr *hccr, ctrl->hcor = hcor; ctrl->priv = ctrl; - if (init == USB_INIT_DEVICE) + ctrl->init = init; + if (ctrl->init == USB_INIT_DEVICE) goto done; + ret = ehci_reset(ctrl); if (ret) goto err; @@ -1666,6 +1668,9 @@ int ehci_deregister(struct udevice *dev) { struct ehci_ctrl *ctrl = dev_get_priv(dev); + if (ctrl->init == USB_INIT_DEVICE) + return 0; + ehci_shutdown(ctrl); return 0; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 3379c293c4..b41c04a8b3 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -242,6 +242,7 @@ struct ehci_ops { }; struct ehci_ctrl { + enum usb_init_type init; struct ehci_hccr *hccr; /* R/O registers, not need for volatile */ struct ehci_hcor *hcor; int rootdev; -- cgit v1.2.3