Message ID | 20190913141930.15784-8-patrick.delaunay@st.com |
---|---|
State | Changes Requested |
Delegated to: | Lukasz Majewski |
Headers | show |
Series | dfu: update dfu stack and add MTD backend | expand |
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")) > + 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 { 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
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 {
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(-)