
Hi Patrick,
Add support of DFU for several interface/device with one command.
The format for "dfu_alt_info" in this case is : interface with devstring'='alternate list (';' separated) and each interface is separated by '&'
The previous behavior is always supported.
Good.
One example for NOR (bootloaders) + NAND (rootfs in UBI):
U-Boot> env set dfu_alt_info \ "sf 0:0:10000000:0=spl part 0 1;u-boot part 0 2; \ u-boot-env part 0 3&nand 0=UBI partubi 0,3"
U-Boot> dfu 0 list
DFU alt settings list: dev: SF alt: 0 name: spl layout: RAW_ADDR dev: SF alt: 1 name: ssbl layout: RAW_ADDR dev: SF alt: 2 name: u-boot-env layout: RAW_ADDR dev: NAND alt: 3 name: UBI layout: RAW_ADDR
U-Boot> dfu 0
$> dfu-util -l
Found DFU: [0483:5720] ver=9999, devnum=96, cfg=1, intf=0, alt=3, name="UBI", serial="002700333338511934383330" Found DFU: [0483:5720] ver=9999, devnum=96, cfg=1, intf=0, alt=2, name="u-boot-env", serial="002700333338511934383330" Found DFU: [0483:5720] ver=9999, devnum=96, cfg=1, intf=0, alt=1, name="u-boot", serial="002700333338511934383330" Found DFU: [0483:5720] ver=9999, devnum=96, cfg=1, intf=0, alt=0, name="spl", serial="002700333338511934383330"
Please add this info (with above example usage) to ./doc/README.dfu (in a similar way as I did it some time ago for ./doc/README.dfutftp).
I also think that it would be beneficial for the community to add a separate entry (in this file) for the description of ST's way to program their platform with this code.
(I mean simple howto for people who would like to start playing around with ST & U-Boot & DFU).
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
cmd/dfu.c | 21 +++++++++++-------- drivers/dfu/dfu.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 9 deletions(-)
diff --git a/cmd/dfu.c b/cmd/dfu.c index 91a750a..33491d0 100644 --- a/cmd/dfu.c +++ b/cmd/dfu.c @@ -21,23 +21,28 @@ static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
- if (argc < 4)
- if (argc < 2) return CMD_RET_USAGE;
#ifdef CONFIG_DFU_OVER_USB char *usb_controller = argv[1]; #endif #if defined(CONFIG_DFU_OVER_USB) || defined(CONFIG_DFU_OVER_TFTP)
- char *interface = argv[2];
- char *devstring = argv[3];
- char *interface = NULL;
- char *devstring = NULL;
- if (argc >= 4) {
interface = argv[2];
devstring = argv[3];
- }
#endif
int ret = 0; #ifdef CONFIG_DFU_OVER_TFTP unsigned long addr = 0; if (!strcmp(argv[1], "tftp")) {
if (argc == 5)
addr = simple_strtoul(argv[4], NULL, 0);
if (argc == 5 || argc == 3)
addr = simple_strtoul(argv[argc - 1], NULL,
0); return update_tftp(addr, interface, devstring); } @@ -48,7 +53,7 @@ static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) goto done;
ret = CMD_RET_SUCCESS;
- if (argc > 4 && strcmp(argv[4], "list") == 0) {
- if (strcmp(argv[argc - 1], "list") == 0) { dfu_show_entities(); goto done; }
@@ -67,7 +72,7 @@ U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu, "Device Firmware Upgrade", "" #ifdef CONFIG_DFU_OVER_USB
- "<USB_controller> <interface> <dev> [list]\n"
- "<USB_controller> [<interface> <dev>] [list]\n" " - device firmware upgrade via <USB_controller>\n" " on device <dev>, attached to interface\n" " <interface>\n"
@@ -77,7 +82,7 @@ U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu, #ifdef CONFIG_DFU_OVER_USB "dfu " #endif
- "tftp <interface> <dev> [<addr>]\n"
- "tftp [<interface> <dev>] [<addr>]\n" " - device firmware upgrade via TFTP\n" " on device <dev>, attached to interface\n" " <interface>\n"
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 79a652e..01ec690 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -52,6 +52,54 @@ static int dfu_find_alt_num(const char *s) return ++i; }
+/*
- treat dfu_alt_info with several interface information
- to allow DFU on several device with one command,
- the string format is
- interface devstring'='alternate list (';' separated)
- and each interface separated by '&'
- */
+int dfu_config_interfaces(char *env) +{
- struct dfu_entity *dfu;
- char *s, *i, *d, *a, *part;
- int ret = -EINVAL;
- int n = 1;
- s = env;
- for (; *s; s++) {
if (*s == ';')
n++;
if (*s == '&')
n++;
- }
- ret = dfu_alt_init(n, &dfu);
- if (ret)
return ret;
- s = env;
- while (s) {
ret = -EINVAL;
i = strsep(&s, " ");
if (!i)
break;
d = strsep(&s, "=");
if (!d)
break;
a = strsep(&s, "&");
if (!a)
a = s;
do {
part = strsep(&a, ";");
ret = dfu_alt_add(dfu, i, d, part);
if (ret)
return ret;
} while (a);
- }
- return ret;
+}
int dfu_init_env_entities(char *interface, char *devstr) { const char *str_env; @@ -68,7 +116,11 @@ int dfu_init_env_entities(char *interface, char *devstr) }
env_bkp = strdup(str_env);
- ret = dfu_config_entities(env_bkp, interface, devstr);
- if (!interface && !devstr)
ret = dfu_config_interfaces(env_bkp);
- else
ret = dfu_config_entities(env_bkp, interface,
devstr); + if (ret) { pr_err("DFU entities configuration failed!\n"); pr_err("(partition table does not match dfu_alt_info?)\n"); @@ -82,6 +134,7 @@ done:
static unsigned char *dfu_buf; static unsigned long dfu_buf_size; +static enum dfu_device_type dfu_buf_device_type;
unsigned char *dfu_free_buf(void) { @@ -99,6 +152,10 @@ unsigned char *dfu_get_buf(struct dfu_entity *dfu) { char *s;
- /* manage several entity with several contraint */
- if (dfu_buf && dfu->dev_type != dfu_buf_device_type)
dfu_free_buf();
- if (dfu_buf != NULL) return dfu_buf;
@@ -117,6 +174,7 @@ unsigned char *dfu_get_buf(struct dfu_entity *dfu) printf("%s: Could not memalign 0x%lx bytes\n", __func__, dfu_buf_size);
- dfu_buf_device_type = dfu->dev_type; return dfu_buf;
}
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de