[U-Boot] [PATCH 01/14] dfu: cosmetic: cleanup sf to avoid checkpatch error

Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/dfu/dfu.c | 7 ++++--- drivers/dfu/dfu_sf.c | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index d2b67b18cf..e9db7f8d66 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -478,14 +478,15 @@ int dfu_config_entities(char *env, char *interface, char *devstr)
const char *dfu_get_dev_type(enum dfu_device_type t) { - const char *dev_t[] = {NULL, "eMMC", "OneNAND", "NAND", "RAM", "SF" }; + const char *const dev_t[] = {NULL, "eMMC", "OneNAND", "NAND", "RAM", + "SF"}; return dev_t[t]; }
const char *dfu_get_layout(enum dfu_layout l) { - const char *dfu_layout[] = {NULL, "RAW_ADDR", "FAT", "EXT2", - "EXT3", "EXT4", "RAM_ADDR" }; + const char *const dfu_layout[] = {NULL, "RAW_ADDR", "FAT", "EXT2", + "EXT3", "EXT4", "RAM_ADDR" }; return dfu_layout[l]; }
diff --git a/drivers/dfu/dfu_sf.c b/drivers/dfu/dfu_sf.c index 066e7670d1..b78fcfd3a1 100644 --- a/drivers/dfu/dfu_sf.c +++ b/drivers/dfu/dfu_sf.c @@ -19,7 +19,7 @@ static int dfu_get_medium_size_sf(struct dfu_entity *dfu, u64 *size) }
static int dfu_read_medium_sf(struct dfu_entity *dfu, u64 offset, void *buf, - long *len) + long *len) { return spi_flash_read(dfu->data.sf.dev, dfu->data.sf.start + offset, *len, buf); @@ -32,7 +32,7 @@ static u64 find_sector(struct dfu_entity *dfu, u64 start, u64 offset) }
static int dfu_write_medium_sf(struct dfu_entity *dfu, - u64 offset, void *buf, long *len) + u64 offset, void *buf, long *len) { int ret;

Copy the partition support from NAND backend to SF, support part and partubi option. In case of ubi partition, erase the rest of the partition as it is mandatory for UBI.
for example:
U-Boot> env set dfu_alt_info "spl part 0 1;\ u-boot part 0 2;u-boot-env part 0 3;UBI partubi 0 4" U-Boot> dfu 0 sf 0:0:10000000:0
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/dfu/dfu_sf.c | 51 ++++++++++++++++++++++++++++++++++++++++++++ include/dfu.h | 2 ++ 2 files changed, 53 insertions(+)
diff --git a/drivers/dfu/dfu_sf.c b/drivers/dfu/dfu_sf.c index b78fcfd3a1..d401b76c2e 100644 --- a/drivers/dfu/dfu_sf.c +++ b/drivers/dfu/dfu_sf.c @@ -10,6 +10,8 @@ #include <dfu.h> #include <spi.h> #include <spi_flash.h> +#include <jffs2/load_kernel.h> +#include <linux/mtd/mtd.h>
static int dfu_get_medium_size_sf(struct dfu_entity *dfu, u64 *size) { @@ -52,11 +54,33 @@ static int dfu_write_medium_sf(struct dfu_entity *dfu,
static int dfu_flush_medium_sf(struct dfu_entity *dfu) { + u64 off, length; + + if (!dfu->data.sf.ubi) + return 0; + + /* in case of ubi partition, erase rest of the partition */ + off = find_sector(dfu, dfu->data.sf.start, dfu->offset); + /* last write ended with unaligned length jump to next */ + if (off != dfu->data.sf.start + dfu->offset) + off += dfu->data.sf.dev->sector_size; + length = dfu->data.sf.start + dfu->data.sf.size - off; + if (length) + return spi_flash_erase(dfu->data.sf.dev, off, length); + return 0; }
static unsigned int dfu_polltimeout_sf(struct dfu_entity *dfu) { + /* + * Currently, Poll Timeout != 0 is only needed on nand + * ubi partition, as sectors which are not used need + * to be erased + */ + if (dfu->data.sf.ubi) + return DFU_MANIFEST_POLL_TIMEOUT; + return DFU_DEFAULT_POLL_TIMEOUT; }
@@ -133,6 +157,33 @@ int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s) dfu->data.sf.start = simple_strtoul(s, &s, 16); s++; dfu->data.sf.size = simple_strtoul(s, &s, 16); + } else if ((!strcmp(st, "part")) || (!strcmp(st, "partubi"))) { + char mtd_id[32]; + struct mtd_device *mtd_dev; + u8 part_num; + struct part_info *pi; + int ret, dev, part; + + dfu->layout = DFU_RAW_ADDR; + + dev = simple_strtoul(s, &s, 10); + s++; + part = simple_strtoul(s, &s, 10); + + sprintf(mtd_id, "%s%d,%d", "nor", dev, part - 1); + printf("using id '%s'\n", mtd_id); + + mtdparts_init(); + + ret = find_dev_and_part(mtd_id, &mtd_dev, &part_num, &pi); + if (ret != 0) { + printf("Could not locate '%s'\n", mtd_id); + return -1; + } + dfu->data.sf.start = pi->offset; + dfu->data.sf.size = pi->size; + if (!strcmp(st, "partubi")) + dfu->data.sf.ubi = 1; } else { printf("%s: Memory layout (%s) not supported!\n", __func__, st); spi_flash_free(dfu->data.sf.dev); diff --git a/include/dfu.h b/include/dfu.h index 145a1576a3..bf51ab74a5 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -77,6 +77,8 @@ struct sf_internal_data { /* RAW programming */ u64 start; u64 size; + /* for sf/ubi use */ + unsigned int ubi; };
#define DFU_NAME_SIZE 32

On Fri, 13 Sep 2019 16:19:18 +0200 Patrick Delaunay patrick.delaunay@st.com wrote:
Copy the partition support from NAND backend to SF, support part and partubi option. In case of ubi partition, erase the rest of the partition as it is mandatory for UBI.
for example:
U-Boot> env set dfu_alt_info "spl part 0 1;\ u-boot part 0 2;u-boot-env part 0 3;UBI partubi 0 4" U-Boot> dfu 0 sf 0:0:10000000:0
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
drivers/dfu/dfu_sf.c | 51 ++++++++++++++++++++++++++++++++++++++++++++ include/dfu.h | 2 ++ 2 files changed, 53 insertions(+)
diff --git a/drivers/dfu/dfu_sf.c b/drivers/dfu/dfu_sf.c index b78fcfd3a1..d401b76c2e 100644 --- a/drivers/dfu/dfu_sf.c +++ b/drivers/dfu/dfu_sf.c @@ -10,6 +10,8 @@ #include <dfu.h> #include <spi.h> #include <spi_flash.h> +#include <jffs2/load_kernel.h> +#include <linux/mtd/mtd.h>
static int dfu_get_medium_size_sf(struct dfu_entity *dfu, u64 *size) { @@ -52,11 +54,33 @@ static int dfu_write_medium_sf(struct dfu_entity *dfu, static int dfu_flush_medium_sf(struct dfu_entity *dfu) {
- u64 off, length;
- if (!dfu->data.sf.ubi)
return 0;
- /* in case of ubi partition, erase rest of the partition */
- off = find_sector(dfu, dfu->data.sf.start, dfu->offset);
- /* last write ended with unaligned length jump to next */
- if (off != dfu->data.sf.start + dfu->offset)
off += dfu->data.sf.dev->sector_size;
- length = dfu->data.sf.start + dfu->data.sf.size - off;
- if (length)
return spi_flash_erase(dfu->data.sf.dev, off,
length); + return 0; }
static unsigned int dfu_polltimeout_sf(struct dfu_entity *dfu) {
- /*
* Currently, Poll Timeout != 0 is only needed on nand
* ubi partition, as sectors which are not used need
* to be erased
*/
- if (dfu->data.sf.ubi)
return DFU_MANIFEST_POLL_TIMEOUT;
- return DFU_DEFAULT_POLL_TIMEOUT;
}
@@ -133,6 +157,33 @@ int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s) dfu->data.sf.start = simple_strtoul(s, &s, 16); s++; dfu->data.sf.size = simple_strtoul(s, &s, 16);
- } else if ((!strcmp(st, "part")) || (!strcmp(st,
"partubi"))) {
char mtd_id[32];
struct mtd_device *mtd_dev;
u8 part_num;
struct part_info *pi;
int ret, dev, part;
dfu->layout = DFU_RAW_ADDR;
dev = simple_strtoul(s, &s, 10);
s++;
part = simple_strtoul(s, &s, 10);
sprintf(mtd_id, "%s%d,%d", "nor", dev, part - 1);
printf("using id '%s'\n", mtd_id);
mtdparts_init();
ret = find_dev_and_part(mtd_id, &mtd_dev, &part_num,
&pi);
if (ret != 0) {
printf("Could not locate '%s'\n", mtd_id);
return -1;
}
dfu->data.sf.start = pi->offset;
dfu->data.sf.size = pi->size;
if (!strcmp(st, "partubi"))
} else { printf("%s: Memory layout (%s) not supported!\n",dfu->data.sf.ubi = 1;
__func__, st); spi_flash_free(dfu->data.sf.dev); diff --git a/include/dfu.h b/include/dfu.h index 145a1576a3..bf51ab74a5 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -77,6 +77,8 @@ struct sf_internal_data { /* RAW programming */ u64 start; u64 size;
- /* for sf/ubi use */
- unsigned int ubi;
};
#define DFU_NAME_SIZE 32
Acked-by: Lukasz Majewski lukma@denx.de
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

Split the function dfu_config_entities with 2 new functions - dfu_alt_init - dfu_alt_add
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/dfu/dfu.c | 51 ++++++++++++++++++++++++++++++++++++----------- include/dfu.h | 2 ++ 2 files changed, 41 insertions(+), 12 deletions(-)
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index e9db7f8d66..900a844d15 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -439,13 +439,12 @@ void dfu_free_entities(void) alt_num_cnt = 0; }
-int dfu_config_entities(char *env, char *interface, char *devstr) +int dfu_alt_init(int num, struct dfu_entity **dfu) { - struct dfu_entity *dfu; - int i, ret; char *s; + int ret;
- dfu_alt_num = dfu_find_alt_num(env); + dfu_alt_num = num; debug("%s: dfu_alt_num=%d\n", __func__, dfu_alt_num);
dfu_hash_algo = NULL; @@ -456,21 +455,49 @@ int dfu_config_entities(char *env, char *interface, char *devstr) pr_err("Hash algorithm %s not supported\n", s); }
- dfu = calloc(sizeof(*dfu), dfu_alt_num); - if (!dfu) + *dfu = calloc(sizeof(struct dfu_entity), dfu_alt_num); + if (!*dfu) + return -1; + + return 0; +} + +int dfu_alt_add(struct dfu_entity *dfu, char *interface, char *devstr, char *s) +{ + struct dfu_entity *p_dfu; + int ret; + + if (alt_num_cnt >= dfu_alt_num) + return -1; + + p_dfu = &dfu[alt_num_cnt]; + ret = dfu_fill_entity(p_dfu, s, alt_num_cnt, interface, devstr); + if (ret) return -1; - for (i = 0; i < dfu_alt_num; i++) {
+ list_add_tail(&p_dfu->list, &dfu_list); + alt_num_cnt++; + + return 0; +} + +int dfu_config_entities(char *env, char *interface, char *devstr) +{ + struct dfu_entity *dfu; + int i, ret; + char *s; + + ret = dfu_alt_init(dfu_find_alt_num(env), &dfu); + if (ret) + return -1; + + for (i = 0; i < dfu_alt_num; i++) { s = strsep(&env, ";"); - ret = dfu_fill_entity(&dfu[i], s, alt_num_cnt, interface, - devstr); + ret = dfu_alt_add(dfu, interface, devstr, s); if (ret) { /* We will free "dfu" in dfu_free_entities() */ return -1; } - - list_add_tail(&dfu[i].list, &dfu_list); - alt_num_cnt++; }
return 0; diff --git a/include/dfu.h b/include/dfu.h index bf51ab74a5..7d60ffc228 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -143,6 +143,8 @@ struct dfu_entity { #ifdef CONFIG_SET_DFU_ALT_INFO void set_dfu_alt_info(char *interface, char *devstr); #endif +int dfu_alt_init(int num, struct dfu_entity **dfu); +int dfu_alt_add(struct dfu_entity *dfu, char *interface, char *devstr, char *s); int dfu_config_entities(char *s, char *interface, char *devstr); void dfu_free_entities(void); void dfu_show_entities(void);

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.
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"
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 91a750a4fc..33491d0bc9 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 900a844d15..8bd5216017 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -53,6 +53,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; @@ -69,7 +117,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"); @@ -83,6 +135,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) { @@ -100,6 +153,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;
@@ -118,6 +175,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; }

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.
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"
My two remarks:
1. As you mentioned above - the current behavior must be preserved (this is my main concern).
2. You added the example of usage to the commit message. Could you also add it to the ./doc/README.dfu (not yet present) file ?
Anyway, thanks for your work :-)
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
Acked-by: Lukasz Majewski lukma@denx.de
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 91a750a4fc..33491d0bc9 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 900a844d15..8bd5216017 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -53,6 +53,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; @@ -69,7 +117,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"); @@ -83,6 +135,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) { @@ -100,6 +153,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;
@@ -118,6 +175,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

Hi Lukasz,
From: Lukasz Majewski lukma@denx.de Sent: mardi 17 septembre 2019 12:26 To: Patrick DELAUNAY patrick.delaunay@st.com Cc: u-boot@lists.denx.de; U-Boot STM32 <uboot-stm32@st-md- mailman.stormreply.com> Subject: Re: [PATCH 04/14] dfu: allow to manage DFU on several devices Importance: High
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.
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"
My two remarks:
- As you mentioned above - the current behavior must be preserved (this is my
main concern).
I agree, it was also my concern.
I don't indicated it clearly by I test it on my board and it but it is preserved.
For example, on my stm32mp1 board :
STM32MP> env set dfu_alt_info "sdcard_fsbl1 part 0 1;sdcard_fsbl2 part 0 2;sdcard_ssbl part 0 3;sdcard_bootfs part 0 4;sdcard_vendorfs part 0 5;sdcard_rootfs part 0 6" STM32MP> dfu 0 mmc 0
On the host side
dfu-util -l dfu-util 0.9
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. Copyright 2010-2016 Tormod Volden and Stefan Schmidt This program is Free Software and has ABSOLUTELY NO WARRANTY Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
Found DFU: [0483:df11] ver=0200, devnum=17, cfg=1, intf=0, path="3-1.3.1", alt=5, name="sdcard_rootfs", serial="002700333338511934383330" Found DFU: [0483:df11] ver=0200, devnum=17, cfg=1, intf=0, path="3-1.3.1", alt=4, name="sdcard_vendorfs", serial="002700333338511934383330" Found DFU: [0483:df11] ver=0200, devnum=17, cfg=1, intf=0, path="3-1.3.1", alt=3, name="sdcard_bootfs", serial="002700333338511934383330" Found DFU: [0483:df11] ver=0200, devnum=17, cfg=1, intf=0, path="3-1.3.1", alt=2, name="sdcard_ssbl", serial="002700333338511934383330" Found DFU: [0483:df11] ver=0200, devnum=17, cfg=1, intf=0, path="3-1.3.1", alt=1, name="sdcard_fsbl2", serial="002700333338511934383330" Found DFU: [0483:df11] ver=0200, devnum=17, cfg=1, intf=0, path="3-1.3.1", alt=0, name="sdcard_fsbl1", serial="002700333338511934383330"
- You added the example of usage to the commit message. Could you also add it
to the ./doc/README.dfu (not yet present) file ?
Yes I willl create the file in V2
Anyway, thanks for your work :-)
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
Acked-by: Lukasz Majewski lukma@denx.de
Regards
Patrick

This patch allows into the DFU backend to indicate that there is no remaining data (for EOF for example). That allows users to read a buffer greater than the device size; the dfu stack stops the read request when the backend return a length=0 without error.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/dfu/dfu.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 8bd5216017..50919fcae9 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -396,6 +396,8 @@ static int dfu_read_buffer_fill(struct dfu_entity *dfu, void *buf, int size) debug("%s: Read error!\n", __func__); return ret; } + if (dfu->b_left == 0) + break; dfu->offset += dfu->b_left; dfu->r_left -= dfu->b_left;

Hi Patrick,
This patch allows into the DFU backend to indicate that there is no remaining data (for EOF for example). That allows users to read a buffer greater than the device size; the dfu stack stops the read request when the backend return a length=0 without error.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
drivers/dfu/dfu.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 8bd5216017..50919fcae9 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -396,6 +396,8 @@ static int dfu_read_buffer_fill(struct dfu_entity *dfu, void *buf, int size) debug("%s: Read error!\n", __func__); return ret; }
if (dfu->b_left == 0)
break;
I guess that this is the use case for sending commands?
Could you provide a more descriptive use case for this change (the description in the above commit message is not enough for me to get it).
dfu->offset += dfu->b_left; dfu->r_left -= dfu->b_left;
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

Hi Lukasz,
From: Lukasz Majewski lukma@denx.de Sent: mardi 17 septembre 2019 12:29
Hi Patrick,
This patch allows into the DFU backend to indicate that there is no remaining data (for EOF for example). That allows users to read a buffer greater than the device size; the dfu stack stops the read request when the backend return a length=0 without error.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
drivers/dfu/dfu.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 8bd5216017..50919fcae9 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -396,6 +396,8 @@ static int dfu_read_buffer_fill(struct dfu_entity *dfu, void *buf, int size) debug("%s: Read error!\n", __func__); return ret; }
if (dfu->b_left == 0)
break;
I guess that this is the use case for sending commands?
Yes,
The use-case is for virtual partition, also used for "command".
Command is requested by updload in the associated alternate And result is done by reading on the same alternate.
During enumeration I set the size of the alternate at the maximum size of the answer.... This test allow to read, without error, until the backend / callback read at the requested offset with a offset = 0.
Could you provide a more descriptive use case for this change (the description in the above commit message is not enough for me to get it).
Yes, I will update the comment in V2.
The issue is the DFU read size is limited by get_medium_size = r_left and the stack expectes that read is allowed up to this size.
Today the DFU backend can't indicate to the DFU stack when the end of available data to read is reached, without and raising error. Because in dfu_read_buffer_fill the loop is infinite until - read_medium raised a error - size = 0 - no more to read in DFU buffer (r_left = 0)
This patch allow the backend to indicate that that it can't provide no more data to fill the DFU buffer, by setting b_left =0 even is the available size id is lower of the total size indicated by get_medium_size.
For USB DFU stack point of view, it is acceptable (read lenght < requested size in DFU_UPLOAD and the transaction is stopped).
It is never a issue for flash device (where chunk are always completely read, b_left will be never 0) but it is usefulll for virtual partition when we only know the max size of this alternate.
Without this patch, I have a infinite loop, when for on backend the result of read_medium is 0 (OK) but dfu->b_left = 0 => r_left is not decreased and size is not updated I try an other solution: raised a error when no more date is available but in this case the data read is not correctly managed in the loop.
PS: It is used in my example for stm32mp1
=> board/st/stm32mp1/stm32mp1.c
I force size to size = 1KB for all virtual partition , in dfu_get_medium_size_virt.
But in fucntio called dfu_read_medium_virt, I limit the size the each virtual partition in dfu_otp_read...
=> only 8 bytes for pmic (in dfu_pmic_read, the second read at offset 8, misc_read return -EACCES)
dfu-util -d 0483:5720 -a 26 -U pmic.bin dfu-util 0.9
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. Copyright 2010-2016 Tormod Volden and Stefan Schmidt This program is Free Software and has ABSOLUTELY NO WARRANTY Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
Opening DFU capable USB device... ID 0483:df11 Run-time device DFU version 0110 Claiming USB DFU Interface... Setting Alternate Setting #26 ... Determining device status: state = dfuIDLE, status = 0 dfuIDLE, continuing DFU mode device DFU version 0110 Device returned transfer size 4096 Copying data from DFU device to PC Upload [=========================] 100% 8 bytes Upload done.
===> but 1KB for otp
dfu-util -d 0483:5720 -a 25 -U otp.bin dfu-util 0.9
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. Copyright 2010-2016 Tormod Volden and Stefan Schmidt This program is Free Software and has ABSOLUTELY NO WARRANTY Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
Opening DFU capable USB device... ID 0483:df11 Run-time device DFU version 0110 Claiming USB DFU Interface... Setting Alternate Setting #25 ... Determining device status: state = dfuIDLE, status = 0 dfuIDLE, continuing DFU mode device DFU version 0110 Device returned transfer size 4096 Copying data from DFU device to PC Upload [=========================] 100% 1024 bytes Upload done.
dfu->offset += dfu->b_left; dfu->r_left -= dfu->b_left;
Best regards,
Lukasz Majewski
Best regards
Patrick Delaunay

Add DFU backend for MTD device: allow to read and write on any MTD device (RAW or SPI)
For example :
set dfu_alt_info "nand_raw raw 0x0 0x100000" dfu 0 mtd nand0
This MTD backend provides the same level than dfu nand backend for NAND in RAW mode and sf backend for NOR; So it can replace booth of them but it can also add support of spi-nand.
set dfu_alt_info "nand_raw raw 0x0 0x100000" dfu 0 mtd spi-nand0
The backend code is based on the MTD command introduced by commit 5db66b3aee6f ("cmd: mtd: add 'mtd' command")
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/dfu/Kconfig | 6 ++ drivers/dfu/Makefile | 1 + drivers/dfu/dfu.c | 5 +- drivers/dfu/dfu_mtd.c | 230 ++++++++++++++++++++++++++++++++++++++++++ include/dfu.h | 21 ++++ 5 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 drivers/dfu/dfu_mtd.c
diff --git a/drivers/dfu/Kconfig b/drivers/dfu/Kconfig index 4692736c9d..ee664a331b 100644 --- a/drivers/dfu/Kconfig +++ b/drivers/dfu/Kconfig @@ -46,5 +46,11 @@ config DFU_SF This option enables using DFU to read and write to SPI flash based storage.
+config DFU_MTD + bool "MTD back end for DFU" + depends on MTD + help + This option enables using DFU to read and write to on any MTD device. + endif endmenu diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile index 4164f342ac..ebb119f398 100644 --- a/drivers/dfu/Makefile +++ b/drivers/dfu/Makefile @@ -5,6 +5,7 @@
obj-$(CONFIG_$(SPL_)DFU) += dfu.o obj-$(CONFIG_$(SPL_)DFU_MMC) += dfu_mmc.o +obj-$(CONFIG_$(SPL_)DFU_MTD) += dfu_mtd.o obj-$(CONFIG_$(SPL_)DFU_NAND) += dfu_nand.o obj-$(CONFIG_$(SPL_)DFU_RAM) += dfu_ram.o obj-$(CONFIG_$(SPL_)DFU_SF) += dfu_sf.o diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 50919fcae9..4f4a07b790 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -462,6 +462,9 @@ static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt, if (strcmp(interface, "mmc") == 0) { if (dfu_fill_entity_mmc(dfu, devstr, s)) return -1; + } else if (strcmp(interface, "mtd") == 0) { + if (dfu_fill_entity_mtd(dfu, devstr, s)) + return -1; } else if (strcmp(interface, "nand") == 0) { if (dfu_fill_entity_nand(dfu, devstr, s)) return -1; @@ -566,7 +569,7 @@ int dfu_config_entities(char *env, char *interface, char *devstr) const char *dfu_get_dev_type(enum dfu_device_type t) { const char *const dev_t[] = {NULL, "eMMC", "OneNAND", "NAND", "RAM", - "SF"}; + "SF", "MTD"}; return dev_t[t]; }
diff --git a/drivers/dfu/dfu_mtd.c b/drivers/dfu/dfu_mtd.c new file mode 100644 index 0000000000..1168a6e278 --- /dev/null +++ b/drivers/dfu/dfu_mtd.c @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * dfu_mtd.c -- DFU for MTD device. + * + * Copyright (C) 2019,STMicroelectronics - All Rights Reserved + * + * Based on dfu_nand.c + */ + +#include <common.h> +#include <dfu.h> +#include <mtd.h> + +static bool mtd_is_aligned_with_block_size(struct mtd_info *mtd, u64 size) +{ + return !do_div(size, mtd->erasesize); +} + +static int mtd_block_op(enum dfu_op op, struct dfu_entity *dfu, + u64 offset, void *buf, long *len) +{ + u64 off, lim, remaining; + struct mtd_info *mtd = dfu->data.mtd.info; + struct mtd_oob_ops io_op = {}; + int ret = 0; + bool has_pages = mtd->type == MTD_NANDFLASH || + mtd->type == MTD_MLCNANDFLASH; + + /* if buf == NULL return total size of the area */ + if (!buf) { + *len = dfu->data.mtd.size; + return 0; + } + + off = dfu->data.mtd.start + offset + dfu->bad_skip; + lim = dfu->data.mtd.start + dfu->data.mtd.size; + + if (off >= lim) { + printf("Limit reached 0x%llx\n", lim); + *len = 0; + return op == DFU_OP_READ ? 0 : -EIO; + } + /* limit request with the available size */ + if (off + *len >= lim) + *len = lim - off; + + if (!mtd_is_aligned_with_block_size(mtd, off)) { + printf("Offset not aligned with a block (0x%x)\n", + mtd->erasesize); + return 0; + } + + /* first erase */ + if (op == DFU_OP_WRITE) { + struct erase_info erase_op = {}; + + erase_op.mtd = mtd; + erase_op.addr = off; + erase_op.len = round_up(*len, mtd->erasesize); + erase_op.scrub = 0; + + while (erase_op.len) { + if (erase_op.addr + erase_op.len > lim) { + printf("Limit reached 0x%llx while erasing at offset 0x%llx\n", + lim, off); + return -EIO; + } + + ret = mtd_erase(mtd, &erase_op); + /* Abort if its not a bad block error */ + if (ret != -EIO) + break; + + printf("Skipping bad block at 0x%08llx\n", + erase_op.fail_addr); + + /* Continue erase behind bad block */ + erase_op.len -= erase_op.fail_addr - erase_op.addr; + erase_op.addr = erase_op.fail_addr + mtd->erasesize; + } + if (ret && ret != -EIO) { + printf("Failure while erasing at offset 0x%llx\n", + erase_op.fail_addr); + return 0; + } + } + + io_op.mode = MTD_OPS_AUTO_OOB; + io_op.len = *len; + if (has_pages && io_op.len > mtd->writesize) + io_op.len = mtd->writesize; + io_op.ooblen = 0; + io_op.datbuf = buf; + io_op.oobbuf = NULL; + + /* Loop over to do the actual read/write */ + remaining = *len; + while (remaining) { + if (off + remaining > lim) { + printf("Limit reached 0x%llx while %s at offset 0x%llx\n", + lim, op == DFU_OP_READ ? "reading" : "writing", + off); + if (op == DFU_OP_READ) { + *len -= remaining; + return 0; + } else { + return -EIO; + } + } + + /* Skip the block if it is bad */ + if (mtd_is_aligned_with_block_size(mtd, off) && + mtd_block_isbad(mtd, off)) { + off += mtd->erasesize; + dfu->bad_skip += mtd->erasesize; + continue; + } + + if (op == DFU_OP_READ) + ret = mtd_read_oob(mtd, off, &io_op); + else + ret = mtd_write_oob(mtd, off, &io_op); + + if (ret) { + printf("Failure while %s at offset 0x%llx\n", + op == DFU_OP_READ ? "reading" : "writing", off); + return -EIO; + } + + off += io_op.retlen; + remaining -= io_op.retlen; + io_op.datbuf += io_op.retlen; + io_op.len = remaining; + if (has_pages && io_op.len > mtd->writesize) + io_op.len = mtd->writesize; + } + + return ret; +} + +static int dfu_get_medium_size_mtd(struct dfu_entity *dfu, u64 *size) +{ + *size = dfu->data.mtd.info->size; + + return 0; +} + +static int dfu_read_medium_mtd(struct dfu_entity *dfu, u64 offset, void *buf, + long *len) +{ + int ret = -1; + + switch (dfu->layout) { + case DFU_RAW_ADDR: + ret = mtd_block_op(DFU_OP_READ, dfu, offset, buf, len); + break; + default: + printf("%s: Layout (%s) not (yet) supported!\n", __func__, + dfu_get_layout(dfu->layout)); + } + + return ret; +} + +static int dfu_write_medium_mtd(struct dfu_entity *dfu, + u64 offset, void *buf, long *len) +{ + int ret = -1; + + switch (dfu->layout) { + case DFU_RAW_ADDR: + ret = mtd_block_op(DFU_OP_WRITE, dfu, offset, buf, len); + break; + default: + printf("%s: Layout (%s) not (yet) supported!\n", __func__, + dfu_get_layout(dfu->layout)); + } + + return ret; +} + +static int dfu_flush_medium_mtd(struct dfu_entity *dfu) +{ + return 0; +} + +static unsigned int dfu_polltimeout_mtd(struct dfu_entity *dfu) +{ + return DFU_DEFAULT_POLL_TIMEOUT; +} + +int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char *s) +{ + char *st; + struct mtd_info *mtd; + bool has_pages; + + mtd = get_mtd_device_nm(devstr); + if (IS_ERR_OR_NULL(mtd)) + return -ENODEV; + put_mtd_device(mtd); + + dfu->dev_type = DFU_DEV_MTD; + dfu->data.mtd.info = mtd; + + has_pages = mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH; + dfu->max_buf_size = has_pages ? mtd->erasesize : 0; + + st = strsep(&s, " "); + if (!strcmp(st, "raw")) { + dfu->layout = DFU_RAW_ADDR; + dfu->data.mtd.start = simple_strtoul(s, &s, 16); + s++; + dfu->data.mtd.size = simple_strtoul(s, &s, 16); + } else { + printf("%s: (%s) not supported!\n", __func__, st); + return -1; + } + + dfu->get_medium_size = dfu_get_medium_size_mtd; + dfu->read_medium = dfu_read_medium_mtd; + dfu->write_medium = dfu_write_medium_mtd; + dfu->flush_medium = dfu_flush_medium_mtd; + dfu->poll_timeout = dfu_polltimeout_mtd; + + /* initial state */ + dfu->inited = 0; + + return 0; +} diff --git a/include/dfu.h b/include/dfu.h index 7d60ffc228..924952f805 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -22,6 +22,7 @@ enum dfu_device_type { DFU_DEV_NAND, DFU_DEV_RAM, DFU_DEV_SF, + DFU_DEV_MTD, };
enum dfu_layout { @@ -55,6 +56,14 @@ struct mmc_internal_data { unsigned int part; };
+struct mtd_internal_data { + struct mtd_info *info; + + /* RAW programming */ + u64 start; + u64 size; +}; + struct nand_internal_data { /* RAW programming */ u64 start; @@ -105,6 +114,7 @@ struct dfu_entity {
union { struct mmc_internal_data mmc; + struct mtd_internal_data mtd; struct nand_internal_data nand; struct ram_internal_data ram; struct sf_internal_data sf; @@ -249,6 +259,17 @@ static inline int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, } #endif
+#if CONFIG_IS_ENABLED(DFU_MTD) +int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char *s); +#else +static inline int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, + char *s) +{ + puts("MTD support not available!\n"); + return -1; +} +#endif + /** * dfu_tftp_write - Write TFTP data to DFU medium *

Hi Patrick,
Add DFU backend for MTD device: allow to read and write on any MTD device (RAW or SPI)
For example :
set dfu_alt_info "nand_raw raw 0x0 0x100000" dfu 0 mtd nand0
This MTD backend provides the same level than dfu nand
^^^^^ - shouldn't there be "functionality" or such?
backend for NAND in RAW mode and sf backend for NOR; So it can replace booth of them but it can also add support of spi-nand.
If I understood correctly - it allows reading "raw" data from MTD device - NAND, SPI-NOR and SPI-NAND?
set dfu_alt_info "nand_raw raw 0x0 0x100000" dfu 0 mtd spi-nand0
The backend code is based on the MTD command introduced by commit 5db66b3aee6f ("cmd: mtd: add 'mtd' command")
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
drivers/dfu/Kconfig | 6 ++ drivers/dfu/Makefile | 1 + drivers/dfu/dfu.c | 5 +- drivers/dfu/dfu_mtd.c | 230 ++++++++++++++++++++++++++++++++++++++++++ include/dfu.h | 21 ++++ 5 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 drivers/dfu/dfu_mtd.c
diff --git a/drivers/dfu/Kconfig b/drivers/dfu/Kconfig index 4692736c9d..ee664a331b 100644 --- a/drivers/dfu/Kconfig +++ b/drivers/dfu/Kconfig @@ -46,5 +46,11 @@ config DFU_SF This option enables using DFU to read and write to SPI flash based storage.
+config DFU_MTD
- bool "MTD back end for DFU"
- depends on MTD
- help
This option enables using DFU to read and write to on any
MTD device. + endif endmenu diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile index 4164f342ac..ebb119f398 100644 --- a/drivers/dfu/Makefile +++ b/drivers/dfu/Makefile @@ -5,6 +5,7 @@
obj-$(CONFIG_$(SPL_)DFU) += dfu.o obj-$(CONFIG_$(SPL_)DFU_MMC) += dfu_mmc.o +obj-$(CONFIG_$(SPL_)DFU_MTD) += dfu_mtd.o obj-$(CONFIG_$(SPL_)DFU_NAND) += dfu_nand.o obj-$(CONFIG_$(SPL_)DFU_RAM) += dfu_ram.o obj-$(CONFIG_$(SPL_)DFU_SF) += dfu_sf.o diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 50919fcae9..4f4a07b790 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -462,6 +462,9 @@ static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt, if (strcmp(interface, "mmc") == 0) { if (dfu_fill_entity_mmc(dfu, devstr, s)) return -1;
- } else if (strcmp(interface, "mtd") == 0) {
if (dfu_fill_entity_mtd(dfu, devstr, s))
} else if (strcmp(interface, "nand") == 0) { if (dfu_fill_entity_nand(dfu, devstr, s)) return -1;return -1;
@@ -566,7 +569,7 @@ int dfu_config_entities(char *env, char *interface, char *devstr) const char *dfu_get_dev_type(enum dfu_device_type t) { const char *const dev_t[] = {NULL, "eMMC", "OneNAND", "NAND", "RAM",
"SF"};
return dev_t[t];"SF", "MTD"};
}
diff --git a/drivers/dfu/dfu_mtd.c b/drivers/dfu/dfu_mtd.c new file mode 100644 index 0000000000..1168a6e278 --- /dev/null +++ b/drivers/dfu/dfu_mtd.c @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- dfu_mtd.c -- DFU for MTD device.
- Copyright (C) 2019,STMicroelectronics - All Rights Reserved
- Based on dfu_nand.c
- */
+#include <common.h> +#include <dfu.h> +#include <mtd.h>
+static bool mtd_is_aligned_with_block_size(struct mtd_info *mtd, u64 size) +{
- return !do_div(size, mtd->erasesize);
+}
+static int mtd_block_op(enum dfu_op op, struct dfu_entity *dfu,
u64 offset, void *buf, long *len)
+{
- u64 off, lim, remaining;
- struct mtd_info *mtd = dfu->data.mtd.info;
- struct mtd_oob_ops io_op = {};
- int ret = 0;
- bool has_pages = mtd->type == MTD_NANDFLASH ||
mtd->type == MTD_MLCNANDFLASH;
- /* if buf == NULL return total size of the area */
- if (!buf) {
*len = dfu->data.mtd.size;
return 0;
- }
- off = dfu->data.mtd.start + offset + dfu->bad_skip;
- lim = dfu->data.mtd.start + dfu->data.mtd.size;
- if (off >= lim) {
printf("Limit reached 0x%llx\n", lim);
*len = 0;
return op == DFU_OP_READ ? 0 : -EIO;
- }
- /* limit request with the available size */
- if (off + *len >= lim)
*len = lim - off;
- if (!mtd_is_aligned_with_block_size(mtd, off)) {
printf("Offset not aligned with a block (0x%x)\n",
mtd->erasesize);
return 0;
- }
- /* first erase */
- if (op == DFU_OP_WRITE) {
struct erase_info erase_op = {};
erase_op.mtd = mtd;
erase_op.addr = off;
erase_op.len = round_up(*len, mtd->erasesize);
erase_op.scrub = 0;
while (erase_op.len) {
if (erase_op.addr + erase_op.len > lim) {
printf("Limit reached 0x%llx while
erasing at offset 0x%llx\n",
lim, off);
return -EIO;
}
ret = mtd_erase(mtd, &erase_op);
/* Abort if its not a bad block error */
if (ret != -EIO)
break;
printf("Skipping bad block at 0x%08llx\n",
erase_op.fail_addr);
/* Continue erase behind bad block */
erase_op.len -= erase_op.fail_addr -
erase_op.addr;
erase_op.addr = erase_op.fail_addr +
mtd->erasesize;
}
if (ret && ret != -EIO) {
printf("Failure while erasing at offset
0x%llx\n",
erase_op.fail_addr);
return 0;
}
- }
- io_op.mode = MTD_OPS_AUTO_OOB;
- io_op.len = *len;
- if (has_pages && io_op.len > mtd->writesize)
io_op.len = mtd->writesize;
- io_op.ooblen = 0;
- io_op.datbuf = buf;
- io_op.oobbuf = NULL;
- /* Loop over to do the actual read/write */
- remaining = *len;
- while (remaining) {
if (off + remaining > lim) {
printf("Limit reached 0x%llx while %s at
offset 0x%llx\n",
lim, op == DFU_OP_READ ? "reading" :
"writing",
off);
if (op == DFU_OP_READ) {
*len -= remaining;
return 0;
} else {
return -EIO;
}
}
/* Skip the block if it is bad */
if (mtd_is_aligned_with_block_size(mtd, off) &&
mtd_block_isbad(mtd, off)) {
off += mtd->erasesize;
dfu->bad_skip += mtd->erasesize;
continue;
}
if (op == DFU_OP_READ)
ret = mtd_read_oob(mtd, off, &io_op);
else
ret = mtd_write_oob(mtd, off, &io_op);
if (ret) {
printf("Failure while %s at offset 0x%llx\n",
op == DFU_OP_READ ? "reading" :
"writing", off);
return -EIO;
}
off += io_op.retlen;
remaining -= io_op.retlen;
io_op.datbuf += io_op.retlen;
io_op.len = remaining;
if (has_pages && io_op.len > mtd->writesize)
io_op.len = mtd->writesize;
- }
- return ret;
+}
+static int dfu_get_medium_size_mtd(struct dfu_entity *dfu, u64 *size) +{
- *size = dfu->data.mtd.info->size;
- return 0;
+}
+static int dfu_read_medium_mtd(struct dfu_entity *dfu, u64 offset, void *buf,
long *len)
+{
- int ret = -1;
- switch (dfu->layout) {
- case DFU_RAW_ADDR:
ret = mtd_block_op(DFU_OP_READ, dfu, offset, buf,
len);
break;
- default:
printf("%s: Layout (%s) not (yet) supported!\n",
__func__,
dfu_get_layout(dfu->layout));
- }
- return ret;
+}
+static int dfu_write_medium_mtd(struct dfu_entity *dfu,
u64 offset, void *buf, long *len)
+{
- int ret = -1;
- switch (dfu->layout) {
- case DFU_RAW_ADDR:
ret = mtd_block_op(DFU_OP_WRITE, dfu, offset, buf,
len);
break;
- default:
printf("%s: Layout (%s) not (yet) supported!\n",
__func__,
dfu_get_layout(dfu->layout));
- }
- return ret;
+}
+static int dfu_flush_medium_mtd(struct dfu_entity *dfu) +{
- return 0;
+}
+static unsigned int dfu_polltimeout_mtd(struct dfu_entity *dfu) +{
- return DFU_DEFAULT_POLL_TIMEOUT;
+}
+int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char *s) +{
- char *st;
- struct mtd_info *mtd;
- bool has_pages;
- mtd = get_mtd_device_nm(devstr);
- if (IS_ERR_OR_NULL(mtd))
return -ENODEV;
- put_mtd_device(mtd);
- dfu->dev_type = DFU_DEV_MTD;
- dfu->data.mtd.info = mtd;
- has_pages = mtd->type == MTD_NANDFLASH || mtd->type ==
MTD_MLCNANDFLASH;
- dfu->max_buf_size = has_pages ? mtd->erasesize : 0;
- st = strsep(&s, " ");
- if (!strcmp(st, "raw")) {
dfu->layout = DFU_RAW_ADDR;
dfu->data.mtd.start = simple_strtoul(s, &s, 16);
s++;
dfu->data.mtd.size = simple_strtoul(s, &s, 16);
- } else {
printf("%s: (%s) not supported!\n", __func__, st);
return -1;
- }
- dfu->get_medium_size = dfu_get_medium_size_mtd;
- dfu->read_medium = dfu_read_medium_mtd;
- dfu->write_medium = dfu_write_medium_mtd;
- dfu->flush_medium = dfu_flush_medium_mtd;
- dfu->poll_timeout = dfu_polltimeout_mtd;
- /* initial state */
- dfu->inited = 0;
- return 0;
+} diff --git a/include/dfu.h b/include/dfu.h index 7d60ffc228..924952f805 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -22,6 +22,7 @@ enum dfu_device_type { DFU_DEV_NAND, DFU_DEV_RAM, DFU_DEV_SF,
- DFU_DEV_MTD,
};
enum dfu_layout { @@ -55,6 +56,14 @@ struct mmc_internal_data { unsigned int part; };
+struct mtd_internal_data {
- struct mtd_info *info;
- /* RAW programming */
- u64 start;
- u64 size;
+};
struct nand_internal_data { /* RAW programming */ u64 start; @@ -105,6 +114,7 @@ struct dfu_entity {
union { struct mmc_internal_data mmc;
struct nand_internal_data nand; struct ram_internal_data ram; struct sf_internal_data sf;struct mtd_internal_data mtd;
@@ -249,6 +259,17 @@ static inline int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, } #endif
+#if CONFIG_IS_ENABLED(DFU_MTD) +int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char *s); +#else +static inline int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr,
char *s)
+{
- puts("MTD support not available!\n");
- return -1;
+} +#endif
/**
- dfu_tftp_write - Write TFTP data to DFU medium
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

Hi,
From: Lukasz Majewski lukma@denx.de Sent: mardi 17 septembre 2019 12:36
Hi Patrick,
Add DFU backend for MTD device: allow to read and write on any MTD device (RAW or SPI)
For example :
set dfu_alt_info "nand_raw raw 0x0 0x100000" dfu 0 mtd nand0
This MTD backend provides the same level than dfu nand
^^^^^ - shouldn't there be "functionality" or such?
backend for NAND in RAW mode and sf backend for NOR; So it can replace booth of them but it can also add support of spi-nand.
If I understood correctly - it allows reading "raw" data from MTD device - NAND, SPI-NOR and SPI-NAND?
Yes, "all MTD devices" : NAND, SPI-NOR, SPI-NAND
My message wasn't clear except if you know the driver organization, I update it in V2
drivers/mtd/raw drivers/mtd/nand drivers/mtd/spi
and potentially also ONENAND als o (not tested) with drivers/mtd/onenand
set dfu_alt_info "nand_raw raw 0x0 0x100000" dfu 0 mtd spi-nand0
The backend code is based on the MTD command introduced by commit 5db66b3aee6f ("cmd: mtd: add 'mtd' command")
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
Best regards,
Lukasz Majewski
--
Beast regards
Patrick

Add the support of MTD partition for the MTD backend.
The expected dfu_alt_info for one alternate on the mtd device : <name> part <part_id> <name> partubi <part_id>
"partubi" also erase up to the end of the partition after write operation.
For example: dfu_alt_info = "spl part 1;u-boot part 2; UBI partubi 3"
U-Boot> dfu 0 mtd nand0
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/dfu/dfu_mtd.c | 78 ++++++++++++++++++++++++++++++++++++++++++- include/dfu.h | 2 ++ 2 files changed, 79 insertions(+), 1 deletion(-)
diff --git a/drivers/dfu/dfu_mtd.c b/drivers/dfu/dfu_mtd.c index 1168a6e278..223b0fe977 100644 --- a/drivers/dfu/dfu_mtd.c +++ b/drivers/dfu/dfu_mtd.c @@ -10,6 +10,7 @@ #include <common.h> #include <dfu.h> #include <mtd.h> +#include <jffs2/load_kernel.h>
static bool mtd_is_aligned_with_block_size(struct mtd_info *mtd, u64 size) { @@ -181,11 +182,49 @@ static int dfu_write_medium_mtd(struct dfu_entity *dfu,
static int dfu_flush_medium_mtd(struct dfu_entity *dfu) { + struct mtd_info *mtd = dfu->data.mtd.info; + int ret; + + /* in case of ubi partition, erase rest of the partition */ + if (dfu->data.nand.ubi) { + struct erase_info erase_op = {}; + + erase_op.mtd = dfu->data.mtd.info; + erase_op.addr = round_up(dfu->data.mtd.start + dfu->offset + + dfu->bad_skip, mtd->erasesize); + erase_op.len = dfu->data.mtd.start + dfu->data.mtd.size - + erase_op.addr; + erase_op.scrub = 0; + + while (erase_op.len) { + ret = mtd_erase(mtd, &erase_op); + /* Abort if its not a bad block error */ + if (ret != -EIO) + break; + + printf("Skipping bad block at 0x%08llx\n", + erase_op.fail_addr); + + /* Skip bad block and continue behind it */ + erase_op.addr = erase_op.fail_addr + mtd->erasesize; + erase_op.len = dfu->data.mtd.start + + dfu->data.mtd.size - + erase_op.addr; + } + } return 0; }
static unsigned int dfu_polltimeout_mtd(struct dfu_entity *dfu) { + /* + * Currently, Poll Timeout != 0 is only needed on nand + * ubi partition, as sectors which are not used need + * to be erased + */ + if (dfu->data.nand.ubi) + return DFU_MANIFEST_POLL_TIMEOUT; + return DFU_DEFAULT_POLL_TIMEOUT; }
@@ -194,6 +233,7 @@ int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char *s) char *st; struct mtd_info *mtd; bool has_pages; + int ret, part;
mtd = get_mtd_device_nm(devstr); if (IS_ERR_OR_NULL(mtd)) @@ -212,11 +252,47 @@ int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char *s) dfu->data.mtd.start = simple_strtoul(s, &s, 16); s++; dfu->data.mtd.size = simple_strtoul(s, &s, 16); + } else if ((!strcmp(st, "part")) || (!strcmp(st, "partubi"))) { + char mtd_id[32]; + struct mtd_device *mtd_dev; + u8 part_num; + struct part_info *pi; + + dfu->layout = DFU_RAW_ADDR; + + part = simple_strtoul(s, &s, 10); + + sprintf(mtd_id, "%s,%d", devstr, part - 1); + printf("using id '%s'\n", mtd_id); + + mtdparts_init(); + + ret = find_dev_and_part(mtd_id, &mtd_dev, &part_num, &pi); + if (ret != 0) { + printf("Could not locate '%s'\n", mtd_id); + return -1; + } + + dfu->data.mtd.start = pi->offset; + dfu->data.mtd.size = pi->size; + if (!strcmp(st, "partubi")) + dfu->data.mtd.ubi = 1; } else { - printf("%s: (%s) not supported!\n", __func__, st); + printf("%s: Memory layout (%s) not supported!\n", __func__, st); return -1; }
+ if (!mtd_is_aligned_with_block_size(mtd, dfu->data.mtd.start)) { + printf("Offset not aligned with a block (0x%x)\n", + mtd->erasesize); + return -EINVAL; + } + if (!mtd_is_aligned_with_block_size(mtd, dfu->data.mtd.size)) { + printf("Size not aligned with a block (0x%x)\n", + mtd->erasesize); + return -EINVAL; + } + dfu->get_medium_size = dfu_get_medium_size_mtd; dfu->read_medium = dfu_read_medium_mtd; dfu->write_medium = dfu_write_medium_mtd; diff --git a/include/dfu.h b/include/dfu.h index 924952f805..a90732cc43 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -62,6 +62,8 @@ struct mtd_internal_data { /* RAW programming */ u64 start; u64 size; + /* for ubi partition */ + unsigned int ubi; };
struct nand_internal_data {

Hi Patrick,
Add the support of MTD partition for the MTD backend.
The expected dfu_alt_info for one alternate on the mtd device : <name> part <part_id> <name> partubi <part_id>
"partubi" also erase up to the end of the partition after write operation.
For example: dfu_alt_info = "spl part 1;u-boot part 2; UBI partubi 3"
U-Boot> dfu 0 mtd nand0
The above information shall also be placed to dedicated ./doc/README.dfu file.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
Acked-by: Lukasz Majewski lukma@denx.de
drivers/dfu/dfu_mtd.c | 78 ++++++++++++++++++++++++++++++++++++++++++- include/dfu.h | 2 ++ 2 files changed, 79 insertions(+), 1 deletion(-)
diff --git a/drivers/dfu/dfu_mtd.c b/drivers/dfu/dfu_mtd.c index 1168a6e278..223b0fe977 100644 --- a/drivers/dfu/dfu_mtd.c +++ b/drivers/dfu/dfu_mtd.c @@ -10,6 +10,7 @@ #include <common.h> #include <dfu.h> #include <mtd.h> +#include <jffs2/load_kernel.h>
static bool mtd_is_aligned_with_block_size(struct mtd_info *mtd, u64 size) { @@ -181,11 +182,49 @@ static int dfu_write_medium_mtd(struct dfu_entity *dfu, static int dfu_flush_medium_mtd(struct dfu_entity *dfu) {
- struct mtd_info *mtd = dfu->data.mtd.info;
- int ret;
- /* in case of ubi partition, erase rest of the partition */
- if (dfu->data.nand.ubi) {
struct erase_info erase_op = {};
erase_op.mtd = dfu->data.mtd.info;
erase_op.addr = round_up(dfu->data.mtd.start +
dfu->offset +
dfu->bad_skip,
mtd->erasesize);
erase_op.len = dfu->data.mtd.start +
dfu->data.mtd.size -
erase_op.addr;
erase_op.scrub = 0;
while (erase_op.len) {
ret = mtd_erase(mtd, &erase_op);
/* Abort if its not a bad block error */
if (ret != -EIO)
break;
printf("Skipping bad block at 0x%08llx\n",
erase_op.fail_addr);
/* Skip bad block and continue behind it */
erase_op.addr = erase_op.fail_addr +
mtd->erasesize;
erase_op.len = dfu->data.mtd.start +
dfu->data.mtd.size -
erase_op.addr;
}
- } return 0;
}
static unsigned int dfu_polltimeout_mtd(struct dfu_entity *dfu) {
- /*
* Currently, Poll Timeout != 0 is only needed on nand
* ubi partition, as sectors which are not used need
* to be erased
*/
- if (dfu->data.nand.ubi)
return DFU_MANIFEST_POLL_TIMEOUT;
- return DFU_DEFAULT_POLL_TIMEOUT;
}
@@ -194,6 +233,7 @@ int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char *s) char *st; struct mtd_info *mtd; bool has_pages;
int ret, part;
mtd = get_mtd_device_nm(devstr); if (IS_ERR_OR_NULL(mtd))
@@ -212,11 +252,47 @@ int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char *s) dfu->data.mtd.start = simple_strtoul(s, &s, 16); s++; dfu->data.mtd.size = simple_strtoul(s, &s, 16);
- } else if ((!strcmp(st, "part")) || (!strcmp(st,
"partubi"))) {
char mtd_id[32];
struct mtd_device *mtd_dev;
u8 part_num;
struct part_info *pi;
dfu->layout = DFU_RAW_ADDR;
part = simple_strtoul(s, &s, 10);
sprintf(mtd_id, "%s,%d", devstr, part - 1);
printf("using id '%s'\n", mtd_id);
mtdparts_init();
ret = find_dev_and_part(mtd_id, &mtd_dev, &part_num,
&pi);
if (ret != 0) {
printf("Could not locate '%s'\n", mtd_id);
return -1;
}
dfu->data.mtd.start = pi->offset;
dfu->data.mtd.size = pi->size;
if (!strcmp(st, "partubi"))
} else {dfu->data.mtd.ubi = 1;
printf("%s: (%s) not supported!\n", __func__, st);
printf("%s: Memory layout (%s) not supported!\n",
__func__, st); return -1; }
- if (!mtd_is_aligned_with_block_size(mtd,
dfu->data.mtd.start)) {
printf("Offset not aligned with a block (0x%x)\n",
mtd->erasesize);
return -EINVAL;
- }
- if (!mtd_is_aligned_with_block_size(mtd,
dfu->data.mtd.size)) {
printf("Size not aligned with a block (0x%x)\n",
mtd->erasesize);
return -EINVAL;
- }
- dfu->get_medium_size = dfu_get_medium_size_mtd; dfu->read_medium = dfu_read_medium_mtd; dfu->write_medium = dfu_write_medium_mtd;
diff --git a/include/dfu.h b/include/dfu.h index 924952f805..a90732cc43 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -62,6 +62,8 @@ struct mtd_internal_data { /* RAW programming */ u64 start; u64 size;
- /* for ubi partition */
- unsigned int ubi;
};
struct nand_internal_data {
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

Hi,
From: Lukasz Majewski lukma@denx.de Sent: mardi 17 septembre 2019 12:39
Hi Patrick,
Add the support of MTD partition for the MTD backend.
The expected dfu_alt_info for one alternate on the mtd device : <name> part <part_id> <name> partubi <part_id>
"partubi" also erase up to the end of the partition after write operation.
For example: dfu_alt_info = "spl part 1;u-boot part 2; UBI partubi 3"
U-Boot> dfu 0 mtd nand0
The above information shall also be placed to dedicated ./doc/README.dfu file.
Yes, I will add informations in V2
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
Acked-by: Lukasz Majewski lukma@denx.de
Best regards,
Patrick Delaunay

Add a virtual DFU backend to allow board specific read and write (for OTP update for example).
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/dfu/Kconfig | 7 ++++++ drivers/dfu/Makefile | 1 + drivers/dfu/dfu.c | 5 ++++- drivers/dfu/dfu_virt.c | 49 ++++++++++++++++++++++++++++++++++++++++++ include/dfu.h | 22 +++++++++++++++++++ 5 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 drivers/dfu/dfu_virt.c
diff --git a/drivers/dfu/Kconfig b/drivers/dfu/Kconfig index ee664a331b..c0e6e5d8f0 100644 --- a/drivers/dfu/Kconfig +++ b/drivers/dfu/Kconfig @@ -52,5 +52,12 @@ config DFU_MTD help This option enables using DFU to read and write to on any MTD device.
+config DFU_VIRT + bool "VIRTUAL flash back end for DFU" + help + This option enables using DFU to read and write to VIRTUAL device + used at board level to manage specific behavior + (OTP update for example). + endif endmenu diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile index ebb119f398..0d7925c083 100644 --- a/drivers/dfu/Makefile +++ b/drivers/dfu/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_$(SPL_)DFU_NAND) += dfu_nand.o obj-$(CONFIG_$(SPL_)DFU_RAM) += dfu_ram.o obj-$(CONFIG_$(SPL_)DFU_SF) += dfu_sf.o obj-$(CONFIG_$(SPL_)DFU_TFTP) += dfu_tftp.o +obj-$(CONFIG_$(SPL_)DFU_VIRT) += dfu_virt.o diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 4f4a07b790..2697235c24 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -474,6 +474,9 @@ static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt, } else if (strcmp(interface, "sf") == 0) { if (dfu_fill_entity_sf(dfu, devstr, s)) return -1; + } else if (strcmp(interface, "virt") == 0) { + if (dfu_fill_entity_virt(dfu, devstr, s)) + return -1; } else { printf("%s: Device %s not (yet) supported!\n", __func__, interface); @@ -569,7 +572,7 @@ int dfu_config_entities(char *env, char *interface, char *devstr) const char *dfu_get_dev_type(enum dfu_device_type t) { const char *const dev_t[] = {NULL, "eMMC", "OneNAND", "NAND", "RAM", - "SF", "MTD"}; + "SF", "MTD", "VIRT"}; return dev_t[t]; }
diff --git a/drivers/dfu/dfu_virt.c b/drivers/dfu/dfu_virt.c new file mode 100644 index 0000000000..ea8c71f100 --- /dev/null +++ b/drivers/dfu/dfu_virt.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2019, STMicroelectronics - All Rights Reserved + */ +#include <common.h> +#include <dfu.h> +#include <errno.h> +#include <malloc.h> + +int __weak dfu_write_medium_virt(struct dfu_entity *dfu, u64 offset, + void *buf, long *len) +{ + debug("%s: off=0x%llx, len=0x%x\n", __func__, offset, (u32)*len); + + return 0; +} + +int __weak dfu_get_medium_size_virt(struct dfu_entity *dfu, u64 *size) +{ + *size = 0; + + return 0; +} + +int __weak dfu_read_medium_virt(struct dfu_entity *dfu, u64 offset, + void *buf, long *len) +{ + debug("%s: off=0x%llx, len=0x%x\n", __func__, offset, (u32)*len); + *len = 0; + + return 0; +} + +int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr, char *s) +{ + debug("%s: devstr = %s\n", __func__, devstr); + + dfu->dev_type = DFU_DEV_VIRT; + dfu->layout = DFU_RAW_ADDR; + dfu->data.virt.dev_num = simple_strtoul(devstr, NULL, 10); + + dfu->write_medium = dfu_write_medium_virt; + dfu->get_medium_size = dfu_get_medium_size_virt; + dfu->read_medium = dfu_read_medium_virt; + + dfu->inited = 0; + + return 0; +} diff --git a/include/dfu.h b/include/dfu.h index a90732cc43..4de7d35914 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -23,6 +23,7 @@ enum dfu_device_type { DFU_DEV_RAM, DFU_DEV_SF, DFU_DEV_MTD, + DFU_DEV_VIRT, };
enum dfu_layout { @@ -92,6 +93,10 @@ struct sf_internal_data { unsigned int ubi; };
+struct virt_internal_data { + int dev_num; +}; + #define DFU_NAME_SIZE 32 #ifndef CONFIG_SYS_DFU_DATA_BUF_SIZE #define CONFIG_SYS_DFU_DATA_BUF_SIZE (1024*1024*8) /* 8 MiB */ @@ -120,6 +125,7 @@ struct dfu_entity { struct nand_internal_data nand; struct ram_internal_data ram; struct sf_internal_data sf; + struct virt_internal_data virt; } data;
int (*get_medium_size)(struct dfu_entity *dfu, u64 *size); @@ -272,6 +278,22 @@ static inline int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, } #endif
+#ifdef CONFIG_DFU_VIRT +int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr, char *s); +int dfu_write_medium_virt(struct dfu_entity *dfu, u64 offset, + void *buf, long *len); +int dfu_get_medium_size_virt(struct dfu_entity *dfu, u64 *size); +int dfu_read_medium_virt(struct dfu_entity *dfu, u64 offset, + void *buf, long *len); +#else +static inline int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr, + char *s) +{ + puts("VIRT support not available!\n"); + return -1; +} +#endif + /** * dfu_tftp_write - Write TFTP data to DFU medium *

Hi Patrick,
Add a virtual DFU backend to allow board specific read and write (for OTP update for example).
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
drivers/dfu/Kconfig | 7 ++++++ drivers/dfu/Makefile | 1 + drivers/dfu/dfu.c | 5 ++++- drivers/dfu/dfu_virt.c | 49 ++++++++++++++++++++++++++++++++++++++++++ include/dfu.h | 22 +++++++++++++++++++ 5 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 drivers/dfu/dfu_virt.c
diff --git a/drivers/dfu/Kconfig b/drivers/dfu/Kconfig index ee664a331b..c0e6e5d8f0 100644 --- a/drivers/dfu/Kconfig +++ b/drivers/dfu/Kconfig @@ -52,5 +52,12 @@ config DFU_MTD help This option enables using DFU to read and write to on any MTD device. +config DFU_VIRT
- bool "VIRTUAL flash back end for DFU"
- help
This option enables using DFU to read and write to VIRTUAL
device
used at board level to manage specific behavior
(OTP update for example).
endif endmenu diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile index ebb119f398..0d7925c083 100644 --- a/drivers/dfu/Makefile +++ b/drivers/dfu/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_$(SPL_)DFU_NAND) += dfu_nand.o obj-$(CONFIG_$(SPL_)DFU_RAM) += dfu_ram.o obj-$(CONFIG_$(SPL_)DFU_SF) += dfu_sf.o obj-$(CONFIG_$(SPL_)DFU_TFTP) += dfu_tftp.o +obj-$(CONFIG_$(SPL_)DFU_VIRT) += dfu_virt.o diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 4f4a07b790..2697235c24 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -474,6 +474,9 @@ static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt, } else if (strcmp(interface, "sf") == 0) { if (dfu_fill_entity_sf(dfu, devstr, s)) return -1;
- } else if (strcmp(interface, "virt") == 0) {
if (dfu_fill_entity_virt(dfu, devstr, s))
} else { printf("%s: Device %s not (yet) supported!\n", __func__, interface);return -1;
@@ -569,7 +572,7 @@ int dfu_config_entities(char *env, char *interface, char *devstr) const char *dfu_get_dev_type(enum dfu_device_type t) { const char *const dev_t[] = {NULL, "eMMC", "OneNAND", "NAND", "RAM",
"SF", "MTD"};
return dev_t[t];"SF", "MTD", "VIRT"};
}
diff --git a/drivers/dfu/dfu_virt.c b/drivers/dfu/dfu_virt.c new file mode 100644 index 0000000000..ea8c71f100 --- /dev/null +++ b/drivers/dfu/dfu_virt.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/*
- Copyright (C) 2019, STMicroelectronics - All Rights Reserved
- */
+#include <common.h> +#include <dfu.h> +#include <errno.h> +#include <malloc.h>
+int __weak dfu_write_medium_virt(struct dfu_entity *dfu, u64 offset,
void *buf, long *len)
+{
- debug("%s: off=0x%llx, len=0x%x\n", __func__, offset,
(u32)*len); +
- return 0;
+}
+int __weak dfu_get_medium_size_virt(struct dfu_entity *dfu, u64 *size) +{
- *size = 0;
- return 0;
+}
+int __weak dfu_read_medium_virt(struct dfu_entity *dfu, u64 offset,
void *buf, long *len)
+{
- debug("%s: off=0x%llx, len=0x%x\n", __func__, offset,
(u32)*len);
- *len = 0;
- return 0;
+}
+int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr, char *s) +{
- debug("%s: devstr = %s\n", __func__, devstr);
- dfu->dev_type = DFU_DEV_VIRT;
- dfu->layout = DFU_RAW_ADDR;
- dfu->data.virt.dev_num = simple_strtoul(devstr, NULL, 10);
- dfu->write_medium = dfu_write_medium_virt;
- dfu->get_medium_size = dfu_get_medium_size_virt;
- dfu->read_medium = dfu_read_medium_virt;
- dfu->inited = 0;
- return 0;
+} diff --git a/include/dfu.h b/include/dfu.h index a90732cc43..4de7d35914 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -23,6 +23,7 @@ enum dfu_device_type { DFU_DEV_RAM, DFU_DEV_SF, DFU_DEV_MTD,
- DFU_DEV_VIRT,
};
enum dfu_layout { @@ -92,6 +93,10 @@ struct sf_internal_data { unsigned int ubi; };
+struct virt_internal_data {
- int dev_num;
+};
#define DFU_NAME_SIZE 32 #ifndef CONFIG_SYS_DFU_DATA_BUF_SIZE #define CONFIG_SYS_DFU_DATA_BUF_SIZE (1024*1024*8) /* 8 MiB */ @@ -120,6 +125,7 @@ struct dfu_entity { struct nand_internal_data nand; struct ram_internal_data ram; struct sf_internal_data sf;
struct virt_internal_data virt;
} data;
int (*get_medium_size)(struct dfu_entity *dfu, u64 *size);
@@ -272,6 +278,22 @@ static inline int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, } #endif
+#ifdef CONFIG_DFU_VIRT +int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr, char *s); +int dfu_write_medium_virt(struct dfu_entity *dfu, u64 offset,
void *buf, long *len);
+int dfu_get_medium_size_virt(struct dfu_entity *dfu, u64 *size); +int dfu_read_medium_virt(struct dfu_entity *dfu, u64 offset,
void *buf, long *len);
+#else +static inline int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr,
char *s)
+{
- puts("VIRT support not available!\n");
- return -1;
+} +#endif
/**
- dfu_tftp_write - Write TFTP data to DFU medium
Acked-by: Lukasz Majewski lukma@denx.de
I will test this patch series (if it don't break current setup) and provide the feedback.
As you mentioned - this series is heading to 2020.01, so I will put it into next (if no regression is found on BBB).
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

Add weak callback to allow board specific behavior - flush - initiated
This patch prepare usage of DFU back end for communication with STM32CubeProgrammer on stm32mp1 platform with stm32prog command.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/dfu/dfu.c | 19 +++++++++++++++++++ include/dfu.h | 2 ++ 2 files changed, 21 insertions(+)
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 2697235c24..f12c5afc66 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -22,6 +22,22 @@ static int dfu_alt_num; static int alt_num_cnt; static struct hash_algo *dfu_hash_algo;
+/* + * The purpose of the dfu_flush_callback() function is to + * provide callback for dfu user + */ +__weak void dfu_flush_callback(struct dfu_entity *dfu) +{ +} + +/* + * The purpose of the dfu_flush_callback() function is to + * provide callback for dfu user + */ +__weak void dfu_initiated_callback(struct dfu_entity *dfu) +{ +} + /* * The purpose of the dfu_usb_get_reset() function is to * provide information if after USB_DETACH request @@ -263,6 +279,7 @@ int dfu_transaction_initiate(struct dfu_entity *dfu, bool read) }
dfu->inited = 1; + dfu_initiated_callback(dfu);
return 0; } @@ -282,6 +299,8 @@ int dfu_flush(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) printf("\nDFU complete %s: 0x%08x\n", dfu_hash_algo->name, dfu->crc);
+ dfu_flush_callback(dfu); + dfu_transaction_cleanup(dfu);
return ret; diff --git a/include/dfu.h b/include/dfu.h index 4de7d35914..5d85cc35ef 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -182,6 +182,8 @@ 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); +void dfu_flush_callback(struct dfu_entity *dfu); +void dfu_initiated_callback(struct dfu_entity *dfu);
/* * dfu_defer_flush - pointer to store dfu_entity for deferred flashing.

Hi Patrick,
Add weak callback to allow board specific behavior
- flush
- initiated
This patch prepare usage of DFU back end for communication with STM32CubeProgrammer on stm32mp1 platform with stm32prog command.
As I've said previously - please add this use case and info to ./doc/README.dtu.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
drivers/dfu/dfu.c | 19 +++++++++++++++++++ include/dfu.h | 2 ++ 2 files changed, 21 insertions(+)
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 2697235c24..f12c5afc66 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -22,6 +22,22 @@ static int dfu_alt_num; static int alt_num_cnt; static struct hash_algo *dfu_hash_algo;
+/*
- The purpose of the dfu_flush_callback() function is to
- provide callback for dfu user
- */
+__weak void dfu_flush_callback(struct dfu_entity *dfu) +{ +}
+/*
- The purpose of the dfu_flush_callback() function is to
- provide callback for dfu user
Please update this repeated comment.
- */
+__weak void dfu_initiated_callback(struct dfu_entity *dfu) +{ +}
/*
- The purpose of the dfu_usb_get_reset() function is to
- provide information if after USB_DETACH request
@@ -263,6 +279,7 @@ int dfu_transaction_initiate(struct dfu_entity *dfu, bool read) }
dfu->inited = 1;
dfu_initiated_callback(dfu);
return 0;
} @@ -282,6 +299,8 @@ int dfu_flush(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) printf("\nDFU complete %s: 0x%08x\n", dfu_hash_algo->name, dfu->crc);
dfu_flush_callback(dfu);
dfu_transaction_cleanup(dfu);
return ret;
diff --git a/include/dfu.h b/include/dfu.h index 4de7d35914..5d85cc35ef 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -182,6 +182,8 @@ 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); +void dfu_flush_callback(struct dfu_entity *dfu); +void dfu_initiated_callback(struct dfu_entity *dfu); /*
- dfu_defer_flush - pointer to store dfu_entity for deferred
flashing.
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

Hi,
From: Lukasz Majewski lukma@denx.de Sent: mardi 17 septembre 2019 12:45
Hi Patrick,
Add weak callback to allow board specific behavior
- flush
- initiated
This patch prepare usage of DFU back end for communication with STM32CubeProgrammer on stm32mp1 platform with stm32prog command.
As I've said previously - please add this use case and info to ./doc/README.dtu.
Yes
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
drivers/dfu/dfu.c | 19 +++++++++++++++++++ include/dfu.h | 2 ++ 2 files changed, 21 insertions(+)
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 2697235c24..f12c5afc66 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -22,6 +22,22 @@ static int dfu_alt_num; static int alt_num_cnt; static struct hash_algo *dfu_hash_algo;
+/*
- The purpose of the dfu_flush_callback() function is to
- provide callback for dfu user
- */
+__weak void dfu_flush_callback(struct dfu_entity *dfu) { }
+/*
- The purpose of the dfu_flush_callback() function is to
- provide callback for dfu user
Please update this repeated comment.
Yes, in V2
- */
+__weak void dfu_initiated_callback(struct dfu_entity *dfu) +{ +}
/*
- The purpose of the dfu_usb_get_reset() function is to
- provide information if after USB_DETACH request
@@ -263,6 +279,7 @@ int dfu_transaction_initiate(struct dfu_entity *dfu, bool read) }
dfu->inited = 1;
dfu_initiated_callback(dfu);
return 0;
} @@ -282,6 +299,8 @@ int dfu_flush(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) printf("\nDFU complete %s: 0x%08x\n", dfu_hash_algo->name, dfu->crc);
dfu_flush_callback(dfu);
dfu_transaction_cleanup(dfu);
return ret;
diff --git a/include/dfu.h b/include/dfu.h index 4de7d35914..5d85cc35ef 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -182,6 +182,8 @@ 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); +void dfu_flush_callback(struct dfu_entity *dfu); +void dfu_initiated_callback(struct dfu_entity *dfu); /*
- dfu_defer_flush - pointer to store dfu_entity for deferred
flashing.
Best regards,
Lukasz Majewski
--
Best regards Patrick

Add support of DFU for MMC, MTD, RAM and MTD command.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
configs/stm32mp15_basic_defconfig | 4 ++++ configs/stm32mp15_optee_defconfig | 4 ++++ configs/stm32mp15_trusted_defconfig | 4 ++++ 3 files changed, 12 insertions(+)
diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index 09785b5dc1..bc9018684d 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -34,6 +34,7 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_GPT=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y +CONFIG_CMD_MTD=y CONFIG_CMD_REMOTEPROC=y CONFIG_CMD_SF=y CONFIG_CMD_SPI=y @@ -62,6 +63,9 @@ CONFIG_ENV_UBI_PART="UBI" CONFIG_ENV_UBI_VOLUME="uboot_config" CONFIG_ENV_UBI_VOLUME_REDUND="uboot_config_r" CONFIG_STM32_ADC=y +CONFIG_DFU_MMC=y +CONFIG_DFU_RAM=y +CONFIG_DFU_MTD=y CONFIG_USB_FUNCTION_FASTBOOT=y CONFIG_FASTBOOT_BUF_ADDR=0xC0000000 CONFIG_FASTBOOT_BUF_SIZE=0x02000000 diff --git a/configs/stm32mp15_optee_defconfig b/configs/stm32mp15_optee_defconfig index 177cbc7d5f..8d3d2e8508 100644 --- a/configs/stm32mp15_optee_defconfig +++ b/configs/stm32mp15_optee_defconfig @@ -23,6 +23,7 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_GPT=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y +CONFIG_CMD_MTD=y CONFIG_CMD_REMOTEPROC=y CONFIG_CMD_SF=y CONFIG_CMD_SPI=y @@ -49,6 +50,9 @@ CONFIG_ENV_UBI_PART="UBI" CONFIG_ENV_UBI_VOLUME="uboot_config" CONFIG_ENV_UBI_VOLUME_REDUND="uboot_config_r" CONFIG_STM32_ADC=y +CONFIG_DFU_MMC=y +CONFIG_DFU_RAM=y +CONFIG_DFU_MTD=y CONFIG_USB_FUNCTION_FASTBOOT=y CONFIG_FASTBOOT_BUF_ADDR=0xC0000000 CONFIG_FASTBOOT_BUF_SIZE=0x02000000 diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig index 71ad1157ec..8da8c4e22a 100644 --- a/configs/stm32mp15_trusted_defconfig +++ b/configs/stm32mp15_trusted_defconfig @@ -22,6 +22,7 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_GPT=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y +CONFIG_CMD_MTD=y CONFIG_CMD_REMOTEPROC=y CONFIG_CMD_SF=y CONFIG_CMD_SPI=y @@ -48,6 +49,9 @@ CONFIG_ENV_UBI_PART="UBI" CONFIG_ENV_UBI_VOLUME="uboot_config" CONFIG_ENV_UBI_VOLUME_REDUND="uboot_config_r" CONFIG_STM32_ADC=y +CONFIG_DFU_MMC=y +CONFIG_DFU_RAM=y +CONFIG_DFU_MTD=y CONFIG_USB_FUNCTION_FASTBOOT=y CONFIG_FASTBOOT_BUF_ADDR=0xC0000000 CONFIG_FASTBOOT_BUF_SIZE=0x02000000

Generate automatically dfu_alt_info for the supported device. The simple command "dfu 0" allows to start the dfu stack on usb 0 for the supported devices: - dfu mtd for nand0 - dfu mtd for nor0 - dfu mmc for SDCard - dfu mmc for eMMC - dfu ram for images in DDR
The DUF alternate use the "part", "partubi" and "mmcpart" options to select the correct MTD or GPT partition or the eMMC hw boot partition.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
board/st/stm32mp1/README | 111 +++++++++++++++++++++++++++++++++++ board/st/stm32mp1/stm32mp1.c | 51 ++++++++++++++++ include/configs/stm32mp1.h | 32 ++++++++++ 3 files changed, 194 insertions(+)
diff --git a/board/st/stm32mp1/README b/board/st/stm32mp1/README index c807e0842e..f2069bcefa 100644 --- a/board/st/stm32mp1/README +++ b/board/st/stm32mp1/README @@ -390,3 +390,114 @@ B/ Automatically by using FIT feature and generic DISTRO bootcmd the correct configuration => stm32mp157c-ev1-m4 => stm32mp157c-dk2-m4 + +11. DFU support +=============== + +The DFU is supported on ST board. +The env variable dfu_alt_info is automatically build, and all +the memory present on the ST boards are exported. + +The mode is started by + +STM32MP> dfu 0 + +On EV1 board: + +STM32MP> dfu 0 list + +DFU alt settings list: +dev: RAM alt: 0 name: uImage layout: RAM_ADDR +dev: RAM alt: 1 name: devicetree.dtb layout: RAM_ADDR +dev: RAM alt: 2 name: uramdisk.image.gz layout: RAM_ADDR +dev: eMMC alt: 3 name: sdcard_fsbl1 layout: RAW_ADDR +dev: eMMC alt: 4 name: sdcard_fsbl2 layout: RAW_ADDR +dev: eMMC alt: 5 name: sdcard_ssbl layout: RAW_ADDR +dev: eMMC alt: 6 name: sdcard_bootfs layout: RAW_ADDR +dev: eMMC alt: 7 name: sdcard_vendorfs layout: RAW_ADDR +dev: eMMC alt: 8 name: sdcard_rootfs layout: RAW_ADDR +dev: eMMC alt: 9 name: sdcard_userfs layout: RAW_ADDR +dev: eMMC alt: 10 name: emmc_fsbl1 layout: RAW_ADDR +dev: eMMC alt: 11 name: emmc_fsbl2 layout: RAW_ADDR +dev: eMMC alt: 12 name: emmc_ssbl layout: RAW_ADDR +dev: eMMC alt: 13 name: emmc_bootfs layout: RAW_ADDR +dev: eMMC alt: 14 name: emmc_vendorfs layout: RAW_ADDR +dev: eMMC alt: 15 name: emmc_rootfs layout: RAW_ADDR +dev: eMMC alt: 16 name: emmc_userfs layout: RAW_ADDR +dev: MTD alt: 17 name: nor_fsbl1 layout: RAW_ADDR +dev: MTD alt: 18 name: nor_fsbl2 layout: RAW_ADDR +dev: MTD alt: 19 name: nor_ssbl layout: RAW_ADDR +dev: MTD alt: 20 name: nor_env layout: RAW_ADDR +dev: MTD alt: 21 name: nand_fsbl layout: RAW_ADDR +dev: MTD alt: 22 name: nand_ssbl1 layout: RAW_ADDR +dev: MTD alt: 23 name: nand_ssbl2 layout: RAW_ADDR +dev: MTD alt: 24 name: nand_UBI layout: RAW_ADDR +dev: VIRT alt: 25 name: OTP layout: RAW_ADDR +dev: VIRT alt: 26 name: PMIC layout: RAW_ADDR + +All the supported device are exported for dfu-util tool: + +$> dfu-util -l +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=26, name="PMIC", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=25, name="OTP", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=24, name="nand_UBI", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=23, name="nand_ssbl2", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=22, name="nand_ssbl1", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=21, name="nand_fsbl", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=20, name="nor_env", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=19, name="nor_ssbl", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=18, name="nor_fsbl2", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=17, name="nor_fsbl1", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=16, name="emmc_userfs", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=15, name="emmc_rootfs", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=14, name="emmc_vendorfs", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=13, name="emmc_bootfs", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=12, name="emmc_ssbl", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=11, name="emmc_fsbl2", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=10, name="emmc_fsbl1", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=9, name="sdcard_userfs", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=8, name="sdcard_rootfs", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=7, name="sdcard_vendorfs", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=6, name="sdcard_bootfs", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=5, name="sdcard_ssbl", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=4, name="sdcard_fsbl2", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=3, name="sdcard_fsbl1", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=2, name="uramdisk.image.gz", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=1, name="devicetree.dtb", serial="002700333338511934383330" +Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=0, name="uImage", serial="002700333338511934383330" + +You can update the boot device: + +#SDCARD +$> dfu-util -d 0483:5720 -a 3 -D tf-a-stm32mp157c-ev1-trusted.stm32 +$> dfu-util -d 0483:5720 -a 4 -D tf-a-stm32mp157c-ev1-trusted.stm32 +$> dfu-util -d 0483:5720 -a 5 -D u-boot-stm32mp157c-ev1-trusted.img +$> dfu-util -d 0483:5720 -a 6 -D st-image-bootfs-openstlinux-weston-stm32mp1.ext4 +$> dfu-util -d 0483:5720 -a 7 -D st-image-vendorfs-openstlinux-weston-stm32mp1.ext4 +$> dfu-util -d 0483:5720 -a 8 -D st-image-weston-openstlinux-weston-stm32mp1.ext4 +$> dfu-util -d 0483:5720 -a 9 -D st-image-userfs-openstlinux-weston-stm32mp1.ext4 + +#EMMC +$> dfu-util -d 0483:5720 -a 10 -D tf-a-stm32mp157c-ev1-trusted.stm32 +$> dfu-util -d 0483:5720 -a 11 -D tf-a-stm32mp157c-ev1-trusted.stm32 +$> dfu-util -d 0483:5720 -a 12 -D u-boot-stm32mp157c-ev1-trusted.img +$> dfu-util -d 0483:5720 -a 13 -D st-image-bootfs-openstlinux-weston-stm32mp1.ext4 +$> dfu-util -d 0483:5720 -a 14 -D st-image-vendorfs-openstlinux-weston-stm32mp1.ext4 +$> dfu-util -d 0483:5720 -a 15 -D st-image-weston-openstlinux-weston-stm32mp1.ext4 +$> dfu-util -d 0483:5720 -a 16 -D st-image-userfs-openstlinux-weston-stm32mp1.ext4 + +#NOR +$> dfu-util -d 0483:5720 -a 17 -D tf-a-stm32mp157c-ev1-trusted.stm32 +$> dfu-util -d 0483:5720 -a 18 -D tf-a-stm32mp157c-ev1-trusted.stm32 +$> dfu-util -d 0483:5720 -a 19 -D u-boot-stm32mp157c-ev1-trusted.img + +#NAND (UBI partition used for NAND only boot or NOR + NAND boot) +$> dfu-util -d 0483:5720 -a 21 -D tf-a-stm32mp157c-ev1-trusted.stm32 +$> dfu-util -d 0483:5720 -a 22 -D u-boot-stm32mp157c-ev1-trusted.img +$> dfu-util -d 0483:5720 -a 23 -D u-boot-stm32mp157c-ev1-trusted.img +$> dfu-util -d 0483:5720 -a 24 -D st-image-weston-openstlinux-weston-stm32mp1_nand_4_256_multivolume.ubi + +And you can also dump the OTP and the PMIC NVM with: + +$> dfu-util -d 0483:5720 -a 25 -U otp.bin +$> dfu-util -d 0483:5720 -a 26 -U pmic.bin diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 18f9b84876..62855988e9 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -14,6 +14,7 @@ #include <generic-phy.h> #include <i2c.h> #include <led.h> +#include <memalign.h> #include <misc.h> #include <mtd.h> #include <mtd_node.h> @@ -903,6 +904,56 @@ int ft_board_setup(void *blob, bd_t *bd) } #endif
+#ifdef CONFIG_SET_DFU_ALT_INFO +#define DFU_ALT_BUF_LEN SZ_1K + +static void board_get_alt_info(const char *dev, char *buff) +{ + char var_name[32] = "dfu_alt_info_"; + int ret; + + ALLOC_CACHE_ALIGN_BUFFER(char, tmp_alt, DFU_ALT_BUF_LEN); + + /* name of env variable to read = dfu_alt_info_<dev> */ + strcat(var_name, dev); + ret = env_get_f(var_name, tmp_alt, DFU_ALT_BUF_LEN); + if (ret) { + if (buff[0] != '\0') + strcat(buff, "&"); + strncat(buff, tmp_alt, DFU_ALT_BUF_LEN); + } +} + +void set_dfu_alt_info(char *interface, char *devstr) +{ + struct udevice *dev; + + ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN); + + if (env_get("dfu_alt_info")) + return; + + memset(buf, 0, sizeof(buf)); + + board_get_alt_info("ram", buf); + + if (!uclass_get_device(UCLASS_MMC, 0, &dev)) + board_get_alt_info("mmc0", buf); + + if (!uclass_get_device(UCLASS_MMC, 1, &dev)) + board_get_alt_info("mmc1", buf); + + if (!uclass_get_device(UCLASS_SPI_FLASH, 0, &dev)) + board_get_alt_info("nor0", buf); + + if (!uclass_get_device(UCLASS_MTD, 0, &dev)) + board_get_alt_info("nand0", buf); + + env_set("dfu_alt_info", buf); + puts("DFU alt info setting: done\n"); +} +#endif + static void board_copro_image_process(ulong fw_image, size_t fw_size) { int ret, id = 0; /* Copro id fixed to 0 as only one coproc on mp1 */ diff --git a/include/configs/stm32mp1.h b/include/configs/stm32mp1.h index 92660fe2a0..4f9024229e 100644 --- a/include/configs/stm32mp1.h +++ b/include/configs/stm32mp1.h @@ -83,6 +83,8 @@ #define CONFIG_SYS_MTDPARTS_RUNTIME #endif
+#define CONFIG_SET_DFU_ALT_INFO + /*****************************************************************************/ #ifdef CONFIG_DISTRO_DEFAULTS /*****************************************************************************/ @@ -136,6 +138,34 @@ #define STM32MP_MTDPARTS #endif
+#define STM32MP_DFU_ALT_RAM \ + "dfu_alt_info_ram=ram 0=" \ + "uImage ram ${kernel_addr_r} 0x2000000;" \ + "devicetree.dtb ram ${fdt_addr_r} 0x100000;" \ + "uramdisk.image.gz ram ${ramdisk_addr_r} 0x10000000\0" + +#ifdef CONFIG_SET_DFU_ALT_INFO +#define STM32MP_DFU_ALT_INFO \ + "dfu_alt_info_nor0=mtd nor0=" \ + "nor_fsbl1 part 1;nor_fsbl2 part 2;" \ + "nor_ssbl part 3;nor_env part 4\0" \ + "dfu_alt_info_nand0=mtd nand0="\ + "nand_fsbl part 1;nand_ssbl1 part 2;" \ + "nand_ssbl2 part 3;nand_UBI partubi 4\0" \ + "dfu_alt_info_mmc0=mmc 0=" \ + "sdcard_fsbl1 part 0 1;sdcard_fsbl2 part 0 2;" \ + "sdcard_ssbl part 0 3;sdcard_bootfs part 0 4;" \ + "sdcard_vendorfs part 0 5;sdcard_rootfs part 0 6;" \ + "sdcard_userfs part 0 7\0" \ + "dfu_alt_info_mmc1=mmc 1=" \ + "emmc_fsbl1 raw 0x0 0x200 mmcpart 1;" \ + "emmc_fsbl2 raw 0x0 0x200 mmcpart 2;emmc_ssbl part 1 1;" \ + "emmc_bootfs part 1 2;emmc_vendorfs part 1 3;" \ + "emmc_rootfs part 1 4;emmc_userfs part 1 5\0" +#else +#define STM32MP_DFU_ALT_INFO +#endif + /* * memory layout for 32M uncompressed/compressed kernel, * 1M fdt, 1M script, 1M pxe and 1M for splashimage @@ -157,6 +187,8 @@ " then env set env_default 0;env save;fi\0" \ STM32MP_BOOTCMD \ STM32MP_MTDPARTS \ + STM32MP_DFU_ALT_RAM \ + STM32MP_DFU_ALT_INFO \ BOOTENV \ "boot_net_usb_start=true\0"

Activate the support of SPI NAND in stm32mp1 U-Boot.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
configs/stm32mp15_basic_defconfig | 1 + configs/stm32mp15_optee_defconfig | 1 + configs/stm32mp15_trusted_defconfig | 1 + 3 files changed, 3 insertions(+)
diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index bc9018684d..8e90505070 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -86,6 +86,7 @@ CONFIG_STM32_SDMMC2=y CONFIG_MTD=y CONFIG_NAND=y CONFIG_NAND_STM32_FMC2=y +CONFIG_MTD_SPI_NAND=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_MACRONIX=y diff --git a/configs/stm32mp15_optee_defconfig b/configs/stm32mp15_optee_defconfig index 8d3d2e8508..387de0ad35 100644 --- a/configs/stm32mp15_optee_defconfig +++ b/configs/stm32mp15_optee_defconfig @@ -73,6 +73,7 @@ CONFIG_STM32_SDMMC2=y CONFIG_MTD=y CONFIG_NAND=y CONFIG_NAND_STM32_FMC2=y +CONFIG_MTD_SPI_NAND=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_MACRONIX=y diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig index 8da8c4e22a..29c23c634d 100644 --- a/configs/stm32mp15_trusted_defconfig +++ b/configs/stm32mp15_trusted_defconfig @@ -72,6 +72,7 @@ CONFIG_STM32_SDMMC2=y CONFIG_MTD=y CONFIG_NAND=y CONFIG_NAND_STM32_FMC2=y +CONFIG_MTD_SPI_NAND=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_MACRONIX=y

This patch adds the support of the spi nand device in mtdparts command and in dfu_alt_info.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
board/st/stm32mp1/stm32mp1.c | 32 +++++++++++++++++++++++++++++--- include/configs/stm32mp1.h | 10 ++++++++-- 2 files changed, 37 insertions(+), 5 deletions(-)
diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 62855988e9..e4bdf05cd7 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -862,8 +862,9 @@ static void board_get_mtdparts(const char *dev,
void board_mtdparts_default(const char **mtdids, const char **mtdparts) { + struct mtd_info *mtd; struct udevice *dev; - static char parts[2 * MTDPARTS_LEN + 1]; + static char parts[3 * MTDPARTS_LEN + 1]; static char ids[MTDIDS_LEN + 1]; static bool mtd_initialized;
@@ -876,8 +877,24 @@ void board_mtdparts_default(const char **mtdids, const char **mtdparts) memset(parts, 0, sizeof(parts)); memset(ids, 0, sizeof(ids));
- if (!uclass_get_device(UCLASS_MTD, 0, &dev)) + /* probe all MTD devices */ + for (uclass_first_device(UCLASS_MTD, &dev); + dev; + uclass_next_device(&dev)) { + pr_debug("mtd device = %s\n", dev->name); + } + + mtd = get_mtd_device_nm("nand0"); + if (!IS_ERR_OR_NULL(mtd)) { board_get_mtdparts("nand0", ids, parts); + put_mtd_device(mtd); + } + + mtd = get_mtd_device_nm("spi-nand0"); + if (!IS_ERR_OR_NULL(mtd)) { + board_get_mtdparts("spi-nand0", ids, parts); + put_mtd_device(mtd); + }
if (!uclass_get_device(UCLASS_SPI_FLASH, 0, &dev)) board_get_mtdparts("nor0", ids, parts); @@ -927,6 +944,7 @@ static void board_get_alt_info(const char *dev, char *buff) void set_dfu_alt_info(char *interface, char *devstr) { struct udevice *dev; + struct mtd_info *mtd;
ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN);
@@ -935,6 +953,9 @@ void set_dfu_alt_info(char *interface, char *devstr)
memset(buf, 0, sizeof(buf));
+ /* probe all MTD devices */ + mtd_probe_devices(); + board_get_alt_info("ram", buf);
if (!uclass_get_device(UCLASS_MMC, 0, &dev)) @@ -946,9 +967,14 @@ void set_dfu_alt_info(char *interface, char *devstr) if (!uclass_get_device(UCLASS_SPI_FLASH, 0, &dev)) board_get_alt_info("nor0", buf);
- if (!uclass_get_device(UCLASS_MTD, 0, &dev)) + mtd = get_mtd_device_nm("nand0"); + if (!IS_ERR_OR_NULL(mtd)) board_get_alt_info("nand0", buf);
+ mtd = get_mtd_device_nm("spi-nand0"); + if (!IS_ERR_OR_NULL(mtd)) + board_get_alt_info("spi-nand0", buf); + env_set("dfu_alt_info", buf); puts("DFU alt info setting: done\n"); } diff --git a/include/configs/stm32mp1.h b/include/configs/stm32mp1.h index 4f9024229e..145a644efa 100644 --- a/include/configs/stm32mp1.h +++ b/include/configs/stm32mp1.h @@ -124,12 +124,15 @@ /* with OPTEE: define specific MTD partitions = teeh, teed, teex */ #define STM32MP_MTDPARTS \ "mtdparts_nor0=256k(fsbl1),256k(fsbl2),2m(ssbl),256k(u-boot-env),256k(teeh),256k(teed),256k(teex),-(nor_user)\0" \ - "mtdparts_nand0=2m(fsbl),2m(ssbl1),2m(ssbl2),512k(teeh),512k(teed),512k(teex),-(UBI)\0" + "mtdparts_nand0=2m(fsbl),2m(ssbl1),2m(ssbl2),512k(teeh),512k(teed),512k(teex),-(UBI)\0" \ + "mtdparts_spi-nand0=2m(fsbl),2m(ssbl1),2m(ssbl2),"\ + "512k(teeh),512k(teed),512k(teex),-(UBI)\0"
#else /* CONFIG_STM32MP1_OPTEE */ #define STM32MP_MTDPARTS \ "mtdparts_nor0=256k(fsbl1),256k(fsbl2),2m(ssbl),256k(u-boot-env),-(nor_user)\0" \ - "mtdparts_nand0=2m(fsbl),2m(ssbl1),2m(ssbl2),-(UBI)\0" + "mtdparts_nand0=2m(fsbl),2m(ssbl1),2m(ssbl2),-(UBI)\0" \ + "mtdparts_spi-nand0=2m(fsbl),2m(ssbl1),2m(ssbl2),-(UBI)\0"
#endif /* CONFIG_STM32MP1_OPTEE */
@@ -152,6 +155,9 @@ "dfu_alt_info_nand0=mtd nand0="\ "nand_fsbl part 1;nand_ssbl1 part 2;" \ "nand_ssbl2 part 3;nand_UBI partubi 4\0" \ + "dfu_alt_info_spi-nand0=mtd spi-nand0="\ + "spi-nand_fsbl part 1;spi-nand_ssbl1 part 2;" \ + "spi-nand_ssbl2 part 3;spi-nand_UBI partubi 4\0" \ "dfu_alt_info_mmc0=mmc 0=" \ "sdcard_fsbl1 part 0 1;sdcard_fsbl2 part 0 2;" \ "sdcard_ssbl part 0 3;sdcard_bootfs part 0 4;" \

Add read for OTP and PMIC NVM with alternates on virtual DFU device.
Serie-cc: Boris Brezillon boris.brezillon@bootlin.com Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
board/st/stm32mp1/stm32mp1.c | 83 +++++++++++++++++++++++++++++ configs/stm32mp15_basic_defconfig | 1 + configs/stm32mp15_optee_defconfig | 1 + configs/stm32mp15_trusted_defconfig | 1 + 4 files changed, 86 insertions(+)
diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index e4bdf05cd7..6045850c05 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -975,9 +975,92 @@ void set_dfu_alt_info(char *interface, char *devstr) if (!IS_ERR_OR_NULL(mtd)) board_get_alt_info("spi-nand0", buf);
+#ifdef CONFIG_DFU_VIRT + strncat(buf, "&virt 0=OTP", DFU_ALT_BUF_LEN); + + if (IS_ENABLED(CONFIG_PMIC_STPMIC1)) + strncat(buf, "&virt 1=PMIC", DFU_ALT_BUF_LEN); +#endif + env_set("dfu_alt_info", buf); puts("DFU alt info setting: done\n"); } + +#if CONFIG_IS_ENABLED(DFU_VIRT) +#include <dfu.h> +#include <power/stpmic1.h> + +int dfu_otp_read(u64 offset, u8 *buffer, long *size) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(stm32mp_bsec), + &dev); + if (ret) + return ret; + + ret = misc_read(dev, offset + STM32_BSEC_OTP_OFFSET, buffer, *size); + if (ret >= 0) { + *size = ret; + ret = 0; + } + + return 0; +} + +int dfu_pmic_read(u64 offset, u8 *buffer, long *size) +{ + int ret; +#ifdef CONFIG_PMIC_STPMIC1 + struct udevice *dev; + + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(stpmic1_nvm), + &dev); + if (ret) + return ret; + + ret = misc_read(dev, 0xF8 + offset, buffer, *size); + if (ret >= 0) { + *size = ret; + ret = 0; + } + if (ret == -EACCES) { + *size = 0; + ret = 0; + } +#else + pr_err("PMIC update not supported"); + ret = -EOPNOTSUPP; +#endif + + return ret; +} + +int dfu_read_medium_virt(struct dfu_entity *dfu, u64 offset, + void *buf, long *len) +{ + switch (dfu->data.virt.dev_num) { + case 0x0: + return dfu_otp_read(offset, buf, len); + case 0x1: + return dfu_pmic_read(offset, buf, len); + } + *len = 0; + return 0; +} + +int __weak dfu_get_medium_size_virt(struct dfu_entity *dfu, u64 *size) +{ + *size = SZ_1K; + + return 0; +} + +#endif + #endif
static void board_copro_image_process(ulong fw_image, size_t fw_size) diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index 8e90505070..a15e3c32b1 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -66,6 +66,7 @@ CONFIG_STM32_ADC=y CONFIG_DFU_MMC=y CONFIG_DFU_RAM=y CONFIG_DFU_MTD=y +CONFIG_DFU_VIRT=y CONFIG_USB_FUNCTION_FASTBOOT=y CONFIG_FASTBOOT_BUF_ADDR=0xC0000000 CONFIG_FASTBOOT_BUF_SIZE=0x02000000 diff --git a/configs/stm32mp15_optee_defconfig b/configs/stm32mp15_optee_defconfig index 387de0ad35..3b8a90de2d 100644 --- a/configs/stm32mp15_optee_defconfig +++ b/configs/stm32mp15_optee_defconfig @@ -53,6 +53,7 @@ CONFIG_STM32_ADC=y CONFIG_DFU_MMC=y CONFIG_DFU_RAM=y CONFIG_DFU_MTD=y +CONFIG_DFU_VIRT=y CONFIG_USB_FUNCTION_FASTBOOT=y CONFIG_FASTBOOT_BUF_ADDR=0xC0000000 CONFIG_FASTBOOT_BUF_SIZE=0x02000000 diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig index 29c23c634d..bcbd8a5c4e 100644 --- a/configs/stm32mp15_trusted_defconfig +++ b/configs/stm32mp15_trusted_defconfig @@ -52,6 +52,7 @@ CONFIG_STM32_ADC=y CONFIG_DFU_MMC=y CONFIG_DFU_RAM=y CONFIG_DFU_MTD=y +CONFIG_DFU_VIRT=y CONFIG_USB_FUNCTION_FASTBOOT=y CONFIG_FASTBOOT_BUF_ADDR=0xC0000000 CONFIG_FASTBOOT_BUF_SIZE=0x02000000

On Fri, 13 Sep 2019 16:19:17 +0200 Patrick Delaunay patrick.delaunay@st.com wrote:
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
drivers/dfu/dfu.c | 7 ++++--- drivers/dfu/dfu_sf.c | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index d2b67b18cf..e9db7f8d66 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -478,14 +478,15 @@ int dfu_config_entities(char *env, char *interface, char *devstr) const char *dfu_get_dev_type(enum dfu_device_type t) {
- const char *dev_t[] = {NULL, "eMMC", "OneNAND", "NAND",
"RAM", "SF" };
- const char *const dev_t[] = {NULL, "eMMC", "OneNAND",
"NAND", "RAM",
return dev_t[t];"SF"};
}
const char *dfu_get_layout(enum dfu_layout l) {
- const char *dfu_layout[] = {NULL, "RAW_ADDR", "FAT", "EXT2",
"EXT3", "EXT4",
"RAM_ADDR" };
- const char *const dfu_layout[] = {NULL, "RAW_ADDR", "FAT",
"EXT2",
"EXT3", "EXT4", "RAM_ADDR"
}; return dfu_layout[l]; }
diff --git a/drivers/dfu/dfu_sf.c b/drivers/dfu/dfu_sf.c index 066e7670d1..b78fcfd3a1 100644 --- a/drivers/dfu/dfu_sf.c +++ b/drivers/dfu/dfu_sf.c @@ -19,7 +19,7 @@ static int dfu_get_medium_size_sf(struct dfu_entity *dfu, u64 *size) }
static int dfu_read_medium_sf(struct dfu_entity *dfu, u64 offset, void *buf,
long *len)
long *len)
{ return spi_flash_read(dfu->data.sf.dev, dfu->data.sf.start + offset, *len, buf); @@ -32,7 +32,7 @@ static u64 find_sector(struct dfu_entity *dfu, u64 start, u64 offset) }
static int dfu_write_medium_sf(struct dfu_entity *dfu,
u64 offset, void *buf, long *len)
u64 offset, void *buf, long *len)
{ int ret;
Acked-by: Lukasz Majewski lukma@denx.de
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
participants (3)
-
Lukasz Majewski
-
Patrick DELAUNAY
-
Patrick Delaunay