* [U-Boot] [PATCH v5 0/9] Improve DFU support, enable for am335x_evm
@ 2013-03-08 17:37 Tom Rini
2013-03-08 17:37 ` [U-Boot] [PATCH v5 1/9] README: Document current DFU CONFIG options Tom Rini
` (8 more replies)
0 siblings, 9 replies; 23+ messages in thread
From: Tom Rini @ 2013-03-08 17:37 UTC (permalink / raw)
To: u-boot
This series does a few things. I've updated Pantelis Antoniou's patch
that allows for transfering of files larger than 4MiB to still allow for
filesystem writes to work. I also document the existing DFU CONFIG
options, and then the new options this series adds. Then we update
nand_(read|write)_skip_bad so that we can add DFU support for NAND
(started by Pantelis). Finally, we enable all of this for am335x_evm.
This series has been compile-tested on all ARM and PowerPC targets and
run-time tested on am335x_evm for NAND and MMC and eMMC.
This series depends on u-boot-usb/master but with a09f955 removed (as we
replace that patch here).
--
Tom
Changes in v5:
- New patch to document existing DFU CONFIG options
- Rework Pantelis' "dfu: Support larger than memory transfers" to not
break filesystem writing
- New patch to re-align defines in <dfu.h>
- Document CONFIG_DFU_NAND in README
- Add RAW MMC examples to include/configs/am335x_evm.h
Changes in v4:
- Further reword nand_util.c comments, from Scott
- In nand_write_skip_bad make sure *actual is 0 for YAFFS2 errors too,
reminded by Scott.
- In cmd_nand.c don't drop the size is less than maxsize check in
arg_off_size as other nand functions need this still (Scott).
- Add patch to fix CONFIG_CMD_NAND_YAFFS
Changes in v3:
- Reworked skip_check_len changes to just add accounting for *used to
the logic.
- Allow for actual to be NULL in nand_(read|write)_skip_bad, only DFU
calls this with a non-NULL parameter. Make sure the comments for both
functions explain the parameters and their behavior.
- Other style changes requested by Scott.
- As nand_(write|read)_skip_bad passes back just a used length now.
- Rework logic in nand_block_op for nand_(read|write)_skip_bad returning
just a size for actual used length.
- Remove unused externs from drivers/dfu/dfu_nand.c
- Fix checkpatch.pl warnings in include/configs/am335x_evm.h
Changes in v2:
- NAND skip_check_len changes reworked to allow
nand_(read|write)_skip_bad to return this information to the caller.
- nand_block_op calls nand_(read|write)_skip_bad directly.
- Bugfix in dfu_nand to make sure we set dfu->skip_bad to 0 on each
iteration.
- Add CONFIG_CMD_MTDPARTS and relevant information to am335x_evm
- Enable DFU for NAND and MMC, set dfu_alt_info_(nand|mmc) as examples
for both in am335x_evm.h
- Increase CONFIG_SYS_MAXARGS due to hush parsing bugs that would
otherwise prevent 'setenv dfu_alt_info ${dfu_alt_info_nand}' on
am335x_evm
Pantelis Antoniou (4):
dfu: Support larger than memory transfers.
dfu: NAND specific routines for DFU operation
am335x_evm: Define CONFIG_SYS_CACHELINE_SIZE
am335x_evm: Enable DFU for NAND and MMC, provide example alt_infos
Tom Rini (5):
README: Document current DFU CONFIG options
dfu: Change indentation of defines in <dfu.h>
nand: Extend nand_(read|write)_skip_bad with *actual and limit
parameters
cmd_nand.c: Fix CONFIG_CMD_NAND_YAFFS
am335x_evm: Add CONFIG_CMD_MTDPARTS and relevant defaults
README | 23 ++++
common/cmd_nand.c | 55 +++++----
common/env_nand.c | 3 +-
drivers/dfu/Makefile | 1 +
drivers/dfu/dfu.c | 251 +++++++++++++++++++++++++++++++++---------
drivers/dfu/dfu_mmc.c | 116 ++++++++++++++-----
drivers/dfu/dfu_nand.c | 195 ++++++++++++++++++++++++++++++++
drivers/mtd/nand/nand_util.c | 68 ++++++++++--
include/configs/am335x_evm.h | 52 ++++++++-
include/dfu.h | 53 ++++++++-
include/nand.h | 4 +-
11 files changed, 700 insertions(+), 121 deletions(-)
create mode 100644 drivers/dfu/dfu_nand.c
--
1.7.9.5
^ permalink raw reply [flat|nested] 23+ messages in thread
* [U-Boot] [PATCH v5 1/9] README: Document current DFU CONFIG options
2013-03-08 17:37 [U-Boot] [PATCH v5 0/9] Improve DFU support, enable for am335x_evm Tom Rini
@ 2013-03-08 17:37 ` Tom Rini
2013-03-08 17:37 ` [U-Boot] [PATCH v5 2/9] dfu: Support larger than memory transfers Tom Rini
` (7 subsequent siblings)
8 siblings, 0 replies; 23+ messages in thread
From: Tom Rini @ 2013-03-08 17:37 UTC (permalink / raw)
To: u-boot
Add documentation for the current DFU config options. DFU is a standard
USB device class so more information is available from usb.org
Signed-off-by: Tom Rini <trini@ti.com>
---
Changes in v5:
- New patch to document existing DFU CONFIG options
Changes in v4: None
Changes in v3: None
Changes in v2: None
README | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/README b/README
index 42544ce..900ae5f 100644
--- a/README
+++ b/README
@@ -1325,6 +1325,19 @@ The following options need to be configured:
CONFIG_SH_MMCIF_CLK
Define the clock frequency for MMCIF
+- USB Device Firmware Update (DFU) class support:
+ CONFIG_DFU_FUNCTION
+ This enables the USB portion of the DFU USB class
+
+ CONFIG_CMD_DFU
+ This enables the command "dfu" which is used to have
+ U-Boot create a DFU class device via USB. This command
+ requires that the "dfu_alt_info" environment variable be
+ set and define the alt settings to expose to the host.
+
+ CONFIG_DFU_MMC
+ This enables support for exposing (e)MMC devices via DFU.
+
- Journaling Flash filesystem support:
CONFIG_JFFS2_NAND, CONFIG_JFFS2_NAND_OFF, CONFIG_JFFS2_NAND_SIZE,
CONFIG_JFFS2_NAND_DEV
--
1.7.9.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [U-Boot] [PATCH v5 2/9] dfu: Support larger than memory transfers.
2013-03-08 17:37 [U-Boot] [PATCH v5 0/9] Improve DFU support, enable for am335x_evm Tom Rini
2013-03-08 17:37 ` [U-Boot] [PATCH v5 1/9] README: Document current DFU CONFIG options Tom Rini
@ 2013-03-08 17:37 ` Tom Rini
2013-03-11 9:38 ` Lukasz Majewski
2013-03-08 17:37 ` [U-Boot] [PATCH v5 3/9] dfu: Change indentation of defines in <dfu.h> Tom Rini
` (6 subsequent siblings)
8 siblings, 1 reply; 23+ messages in thread
From: Tom Rini @ 2013-03-08 17:37 UTC (permalink / raw)
To: u-boot
From: Pantelis Antoniou <panto@antoniou-consulting.com>
Previously we didn't support upload/download larger than available
memory. This is pretty bad when you have to update your root filesystem
for example.
This patch removes that limitation (and the crashes when you transfered
any file larger than 4MB) by making raw image writes be done in chunks
and making file maximum size be configurable.
The sequence number is a 16 bit counter; make sure we handle rollover
correctly. This fixes the wrong transfers for large (> 256MB) images.
Also utilize a variable to handle initialization, so that we don't rely
on just the counter sent by the host.
Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
Signed-off-by: Tom Rini <trini@ti.com>
---
Changes in v5:
- Rework Pantelis' "dfu: Support larger than memory transfers" to not
break filesystem writing
Changes in v4: None
Changes in v3: None
Changes in v2: None
README | 7 ++
drivers/dfu/dfu.c | 245 ++++++++++++++++++++++++++++++++++++++-----------
drivers/dfu/dfu_mmc.c | 116 +++++++++++++++++------
include/dfu.h | 26 +++++-
4 files changed, 310 insertions(+), 84 deletions(-)
diff --git a/README b/README
index 900ae5f..154b82f 100644
--- a/README
+++ b/README
@@ -1338,6 +1338,13 @@ The following options need to be configured:
CONFIG_DFU_MMC
This enables support for exposing (e)MMC devices via DFU.
+ CONFIG_SYS_DFU_MAX_FILE_SIZE
+ When updating files rather than the raw storage device,
+ we use a static buffer to copy the file into and then write
+ the buffer once we've been given the whole file. Define
+ this to the maximum filesize (in bytes) for the buffer.
+ Default is 4 MiB if undefined.
+
- Journaling Flash filesystem support:
CONFIG_JFFS2_NAND, CONFIG_JFFS2_NAND_OFF, CONFIG_JFFS2_NAND_SIZE,
CONFIG_JFFS2_NAND_DEV
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
index e8477fb..2fecf77 100644
--- a/drivers/dfu/dfu.c
+++ b/drivers/dfu/dfu.c
@@ -44,90 +44,229 @@ static int dfu_find_alt_num(const char *s)
static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
dfu_buf[DFU_DATA_BUF_SIZE];
+static int dfu_write_buffer_drain(struct dfu_entity *dfu)
+{
+ long w_size;
+ int ret;
+
+ /* flush size? */
+ w_size = dfu->i_buf - dfu->i_buf_start;
+ if (w_size == 0)
+ return 0;
+
+ /* update CRC32 */
+ dfu->crc = crc32(dfu->crc, dfu->i_buf_start, w_size);
+
+ ret = dfu->write_medium(dfu, dfu->offset, dfu->i_buf_start, &w_size);
+ if (ret)
+ debug("%s: Write error!\n", __func__);
+
+ /* point back */
+ dfu->i_buf = dfu->i_buf_start;
+
+ /* update offset */
+ dfu->offset += w_size;
+
+ puts("#");
+
+ return ret;
+}
+
int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
{
- static unsigned char *i_buf;
- static int i_blk_seq_num;
- long w_size = 0;
int ret = 0;
+ int tret;
+
+ debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x "
+ "offset: 0x%llx bufoffset: 0x%x\n",
+ __func__, dfu->name, buf, size, blk_seq_num, dfu->offset,
+ dfu->i_buf - dfu->i_buf_start);
+
+ if (!dfu->inited) {
+ /* initial state */
+ dfu->crc = 0;
+ dfu->offset = 0;
+ dfu->i_blk_seq_num = 0;
+ dfu->i_buf_start = dfu_buf;
+ dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
+ dfu->i_buf = dfu->i_buf_start;
+
+ dfu->inited = 1;
+ }
- debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf: 0x%p\n",
- __func__, dfu->name, buf, size, blk_seq_num, i_buf);
+ if (dfu->i_blk_seq_num != blk_seq_num) {
+ printf("%s: Wrong sequence number! [%d] [%d]\n",
+ __func__, dfu->i_blk_seq_num, blk_seq_num);
+ return -1;
+ }
- if (blk_seq_num == 0) {
- i_buf = dfu_buf;
- i_blk_seq_num = 0;
+ /* DFU 1.1 standard says:
+ * The wBlockNum field is a block sequence number. It increments each
+ * time a block is transferred, wrapping to zero from 65,535. It is used
+ * to provide useful context to the DFU loader in the device."
+ *
+ * This means that it's a 16 bit counter that roll-overs at
+ * 0xffff -> 0x0000. By having a typical 4K transfer block
+ * we roll-over at exactly 256MB. Not very fun to debug.
+ *
+ * Handling rollover, and having an inited variable,
+ * makes things work.
+ */
+
+ /* handle rollover */
+ dfu->i_blk_seq_num = (dfu->i_blk_seq_num + 1) & 0xffff;
+
+ /* flush buffer if overflow */
+ if ((dfu->i_buf + size) > dfu->i_buf_end) {
+ tret = dfu_write_buffer_drain(dfu);
+ if (ret == 0)
+ ret = tret;
}
- if (i_blk_seq_num++ != blk_seq_num) {
- printf("%s: Wrong sequence number! [%d] [%d]\n",
- __func__, i_blk_seq_num, blk_seq_num);
+ /* we should be in buffer now (if not then size too large) */
+ if ((dfu->i_buf + size) > dfu->i_buf_end) {
+ printf("%s: Wrong size! [%d] [%d] - %d\n",
+ __func__, dfu->i_blk_seq_num, blk_seq_num, size);
return -1;
}
- memcpy(i_buf, buf, size);
- i_buf += size;
+ memcpy(dfu->i_buf, buf, size);
+ dfu->i_buf += size;
+ /* if end or if buffer full flush */
+ if (size == 0 || (dfu->i_buf + size) > dfu->i_buf_end) {
+ tret = dfu_write_buffer_drain(dfu);
+ if (ret == 0)
+ ret = tret;
+ }
+
+ /* end? */
if (size == 0) {
- /* Integrity check (if needed) */
- debug("%s: %s %d [B] CRC32: 0x%x\n", __func__, dfu->name,
- i_buf - dfu_buf, crc32(0, dfu_buf, i_buf - dfu_buf));
+ /* Now try and flush to the medium if needed. */
+ if (dfu->flush_medium)
+ ret = dfu->flush_medium(dfu);
+ printf("\nDFU complete CRC32: 0x%08x\n", dfu->crc);
- w_size = i_buf - dfu_buf;
- ret = dfu->write_medium(dfu, dfu_buf, &w_size);
- if (ret)
- debug("%s: Write error!\n", __func__);
+ /* clear everything */
+ dfu->crc = 0;
+ dfu->offset = 0;
+ dfu->i_blk_seq_num = 0;
+ dfu->i_buf_start = dfu_buf;
+ dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
+ dfu->i_buf = dfu->i_buf_start;
+
+ dfu->inited = 0;
- i_blk_seq_num = 0;
- i_buf = NULL;
- return ret;
}
- return ret;
+ return ret = 0 ? size : ret;
+}
+
+static int dfu_read_buffer_fill(struct dfu_entity *dfu, void *buf, int size)
+{
+ long chunk;
+ int ret, readn;
+
+ readn = 0;
+ while (size > 0) {
+
+ /* get chunk that can be read */
+ chunk = min(size, dfu->b_left);
+ /* consume */
+ if (chunk > 0) {
+ memcpy(buf, dfu->i_buf, chunk);
+ dfu->crc = crc32(dfu->crc, buf, chunk);
+ dfu->i_buf += chunk;
+ dfu->b_left -= chunk;
+ size -= chunk;
+ buf += chunk;
+ readn += chunk;
+ }
+
+ /* all done */
+ if (size > 0) {
+ /* no more to read */
+ if (dfu->r_left == 0)
+ break;
+
+ dfu->i_buf = dfu->i_buf_start;
+ dfu->b_left = dfu->i_buf_end - dfu->i_buf_start;
+
+ /* got to read, but buffer is empty */
+ if (dfu->b_left > dfu->r_left)
+ dfu->b_left = dfu->r_left;
+ ret = dfu->read_medium(dfu, dfu->offset, dfu->i_buf,
+ &dfu->b_left);
+ if (ret != 0) {
+ debug("%s: Read error!\n", __func__);
+ return ret;
+ }
+ dfu->offset += dfu->b_left;
+ dfu->r_left -= dfu->b_left;
+
+ puts("#");
+ }
+ }
+
+ return readn;
}
int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
{
- static unsigned char *i_buf;
- static int i_blk_seq_num;
- static long r_size;
- static u32 crc;
int ret = 0;
debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf: 0x%p\n",
- __func__, dfu->name, buf, size, blk_seq_num, i_buf);
-
- if (blk_seq_num == 0) {
- i_buf = dfu_buf;
- ret = dfu->read_medium(dfu, i_buf, &r_size);
- debug("%s: %s %ld [B]\n", __func__, dfu->name, r_size);
- i_blk_seq_num = 0;
- /* Integrity check (if needed) */
- crc = crc32(0, dfu_buf, r_size);
+ __func__, dfu->name, buf, size, blk_seq_num, dfu->i_buf);
+
+ if (!dfu->inited) {
+ ret = dfu->read_medium(dfu, 0, NULL, &dfu->r_left);
+ if (ret != 0) {
+ debug("%s: failed to get r_left\n", __func__);
+ return ret;
+ }
+
+ debug("%s: %s %ld [B]\n", __func__, dfu->name, dfu->r_left);
+
+ dfu->i_blk_seq_num = 0;
+ dfu->crc = 0;
+ dfu->offset = 0;
+ dfu->i_buf_start = dfu_buf;
+ dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
+ dfu->i_buf = dfu->i_buf_start;
+ dfu->b_left = 0;
+
+ dfu->inited = 1;
}
- if (i_blk_seq_num++ != blk_seq_num) {
+ if (dfu->i_blk_seq_num != blk_seq_num) {
printf("%s: Wrong sequence number! [%d] [%d]\n",
- __func__, i_blk_seq_num, blk_seq_num);
+ __func__, dfu->i_blk_seq_num, blk_seq_num);
return -1;
}
+ /* handle rollover */
+ dfu->i_blk_seq_num = (dfu->i_blk_seq_num + 1) & 0xffff;
- if (r_size >= size) {
- memcpy(buf, i_buf, size);
- i_buf += size;
- r_size -= size;
- return size;
- } else {
- memcpy(buf, i_buf, r_size);
- i_buf += r_size;
- debug("%s: %s CRC32: 0x%x\n", __func__, dfu->name, crc);
- puts("UPLOAD ... done\nCtrl+C to exit ...\n");
+ ret = dfu_read_buffer_fill(dfu, buf, size);
+ if (ret < 0) {
+ printf("%s: Failed to fill buffer\n", __func__);
+ return -1;
+ }
+
+ if (ret < size) {
+ debug("%s: %s CRC32: 0x%x\n", __func__, dfu->name, dfu->crc);
+ puts("\nUPLOAD ... done\nCtrl+C to exit ...\n");
- i_buf = NULL;
- i_blk_seq_num = 0;
- crc = 0;
- return r_size;
+ dfu->i_blk_seq_num = 0;
+ dfu->crc = 0;
+ dfu->offset = 0;
+ dfu->i_buf_start = dfu_buf;
+ dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
+ dfu->i_buf = dfu->i_buf_start;
+ dfu->b_left = 0;
+
+ dfu->inited = 0;
}
+
return ret;
}
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
index 083d745..2d5ffd8 100644
--- a/drivers/dfu/dfu_mmc.c
+++ b/drivers/dfu/dfu_mmc.c
@@ -22,6 +22,7 @@
#include <common.h>
#include <malloc.h>
#include <errno.h>
+#include <div64.h>
#include <dfu.h>
enum dfu_mmc_op {
@@ -29,36 +30,67 @@ enum dfu_mmc_op {
DFU_OP_WRITE,
};
+static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
+ dfu_file_buf[CONFIG_SYS_DFU_MAX_FILE_SIZE];
+static long dfu_file_buf_len;
+
static int mmc_block_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
- void *buf, long *len)
+ u64 offset, void *buf, long *len)
{
char cmd_buf[DFU_CMD_BUF_SIZE];
+ u32 blk_start, blk_count;
+
+ /*
+ * We must ensure that we work in lba_blk_size chunks, so ALIGN
+ * this value.
+ */
+ *len = ALIGN(*len, dfu->data.mmc.lba_blk_size);
+
+ blk_start = dfu->data.mmc.lba_start +
+ (u32)lldiv(offset, dfu->data.mmc.lba_blk_size);
+ blk_count = *len / dfu->data.mmc.lba_blk_size;
+ if (*len + blk_start >
+ dfu->data.mmc.lba_size * dfu->data.mmc.lba_size) {
+ puts("Request would exceed designated area!\n");
+ return -EINVAL;
+ }
- sprintf(cmd_buf, "mmc %s 0x%x %x %x",
+ sprintf(cmd_buf, "mmc %s %p %x %x",
op == DFU_OP_READ ? "read" : "write",
- (unsigned int) buf,
- dfu->data.mmc.lba_start,
- dfu->data.mmc.lba_size);
-
- if (op == DFU_OP_READ)
- *len = dfu->data.mmc.lba_blk_size * dfu->data.mmc.lba_size;
+ buf, blk_start, blk_count);
debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
return run_command(cmd_buf, 0);
}
-static inline int mmc_block_write(struct dfu_entity *dfu, void *buf, long *len)
+static inline int mmc_block_write(struct dfu_entity *dfu,
+ u64 offset, void *buf, long *len)
+{
+ return mmc_block_op(DFU_OP_WRITE, dfu, offset, buf, len);
+}
+
+static inline int mmc_block_read(struct dfu_entity *dfu,
+ u64 offset, void *buf, long *len)
{
- return mmc_block_op(DFU_OP_WRITE, dfu, buf, len);
+ return mmc_block_op(DFU_OP_READ, dfu, offset, buf, len);
}
-static inline int mmc_block_read(struct dfu_entity *dfu, void *buf, long *len)
+static int mmc_file_buffer(struct dfu_entity *dfu, void *buf, long *len)
{
- return mmc_block_op(DFU_OP_READ, dfu, buf, len);
+ if (dfu_file_buf_len + *len > CONFIG_SYS_DFU_MAX_FILE_SIZE) {
+ dfu_file_buf_len = 0;
+ return -EINVAL;
+ }
+
+ /* Add to the current buffer. */
+ memcpy(dfu_file_buf + dfu_file_buf_len, buf, *len);
+ dfu_file_buf_len += *len;
+
+ return 0;
}
static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
- void *buf, long *len)
+ u64 offset, void *buf, long *len)
{
char cmd_buf[DFU_CMD_BUF_SIZE];
char *str_env;
@@ -70,8 +102,15 @@ static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
op == DFU_OP_READ ? "load" : "write",
dfu->data.mmc.dev, dfu->data.mmc.part,
(unsigned int) buf, dfu->name, *len);
+ if (op == DFU_OP_READ && offset != 0)
+ sprintf(cmd_buf + strlen(cmd_buf), " %llx", offset);
break;
case DFU_FS_EXT4:
+ if (offset != 0) {
+ debug("%s: Offset value %llx != 0 not supported!\n",
+ __func__, offset);
+ return -1;
+ }
sprintf(cmd_buf, "ext4%s mmc %d:%d /%s 0x%x %ld",
op == DFU_OP_READ ? "load" : "write",
dfu->data.mmc.dev, dfu->data.mmc.part,
@@ -80,6 +119,7 @@ static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
default:
printf("%s: Layout (%s) not (yet) supported!\n", __func__,
dfu_get_layout(dfu->layout));
+ return -1;
}
debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
@@ -102,27 +142,24 @@ static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
return ret;
}
-static inline int mmc_file_write(struct dfu_entity *dfu, void *buf, long *len)
+static inline int mmc_file_read(struct dfu_entity *dfu,
+ u64 offset, void *buf, long *len)
{
- return mmc_file_op(DFU_OP_WRITE, dfu, buf, len);
+ return mmc_file_op(DFU_OP_READ, dfu, offset, buf, len);
}
-static inline int mmc_file_read(struct dfu_entity *dfu, void *buf, long *len)
-{
- return mmc_file_op(DFU_OP_READ, dfu, buf, len);
-}
-
-int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
+int dfu_write_medium_mmc(struct dfu_entity *dfu,
+ u64 offset, void *buf, long *len)
{
int ret = -1;
switch (dfu->layout) {
case DFU_RAW_ADDR:
- ret = mmc_block_write(dfu, buf, len);
+ ret = mmc_block_write(dfu, offset, buf, len);
break;
case DFU_FS_FAT:
case DFU_FS_EXT4:
- ret = mmc_file_write(dfu, buf, len);
+ ret = mmc_file_buffer(dfu, buf, len);
break;
default:
printf("%s: Layout (%s) not (yet) supported!\n", __func__,
@@ -132,17 +169,34 @@ int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
return ret;
}
-int dfu_read_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
+int dfu_flush_medium_mmc(struct dfu_entity *dfu)
+{
+ int ret = 0;
+
+ if (dfu->layout != DFU_RAW_ADDR) {
+ /* Do stuff here. */
+ ret = mmc_file_op(DFU_OP_WRITE, dfu, 0, &dfu_file_buf,
+ &dfu_file_buf_len);
+
+ /* Now that we're done */
+ dfu_file_buf_len = 0;
+ }
+
+ return ret;
+}
+
+int dfu_read_medium_mmc(struct dfu_entity *dfu, u64 offset, void *buf,
+ long *len)
{
int ret = -1;
switch (dfu->layout) {
case DFU_RAW_ADDR:
- ret = mmc_block_read(dfu, buf, len);
+ ret = mmc_block_read(dfu, offset, buf, len);
break;
case DFU_FS_FAT:
case DFU_FS_EXT4:
- ret = mmc_file_read(dfu, buf, len);
+ ret = mmc_file_read(dfu, offset, buf, len);
break;
default:
printf("%s: Layout (%s) not (yet) supported!\n", __func__,
@@ -181,13 +235,15 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
mmc = find_mmc_device(dev);
if (mmc == NULL || mmc_init(mmc)) {
- printf("%s: could not find mmc device #%d!\n", __func__, dev);
+ printf("%s: could not find mmc device #%d!\n",
+ __func__, dev);
return -ENODEV;
}
blk_dev = &mmc->block_dev;
if (get_partition_info(blk_dev, part, &partinfo) != 0) {
- printf("%s: could not find partition #%d on mmc device #%d!\n",
+ printf("%s: could not find partition #%d "
+ "on mmc device #%d!\n",
__func__, part, dev);
return -ENODEV;
}
@@ -208,6 +264,10 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
dfu->read_medium = dfu_read_medium_mmc;
dfu->write_medium = dfu_write_medium_mmc;
+ dfu->flush_medium = dfu_flush_medium_mmc;
+
+ /* initial state */
+ dfu->inited = 0;
return 0;
}
diff --git a/include/dfu.h b/include/dfu.h
index 5350d79..5182c6c 100644
--- a/include/dfu.h
+++ b/include/dfu.h
@@ -59,7 +59,10 @@ static inline unsigned int get_mmc_blk_size(int dev)
#define DFU_NAME_SIZE 32
#define DFU_CMD_BUF_SIZE 128
-#define DFU_DATA_BUF_SIZE (1024*1024*4) /* 4 MiB */
+#define DFU_DATA_BUF_SIZE (64 << 10) /* 64 KiB */
+#ifndef CONFIG_SYS_DFU_MAX_FILE_SIZE
+#define CONFIG_SYS_DFU_MAX_FILE_SIZE (4 << 20) /* 4 MiB */
+#endif
struct dfu_entity {
char name[DFU_NAME_SIZE];
@@ -73,10 +76,27 @@ struct dfu_entity {
struct mmc_internal_data mmc;
} data;
- int (*read_medium)(struct dfu_entity *dfu, void *buf, long *len);
- int (*write_medium)(struct dfu_entity *dfu, void *buf, long *len);
+ int (*read_medium)(struct dfu_entity *dfu,
+ u64 offset, void *buf, long *len);
+
+ int (*write_medium)(struct dfu_entity *dfu,
+ u64 offset, void *buf, long *len);
+
+ int (*flush_medium)(struct dfu_entity *dfu);
struct list_head list;
+
+ /* on the fly state */
+ u32 crc;
+ u64 offset;
+ int i_blk_seq_num;
+ u8 *i_buf;
+ u8 *i_buf_start;
+ u8 *i_buf_end;
+ long r_left;
+ long b_left;
+
+ unsigned int inited:1;
};
int dfu_config_entities(char *s, char *interface, int num);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [U-Boot] [PATCH v5 3/9] dfu: Change indentation of defines in <dfu.h>
2013-03-08 17:37 [U-Boot] [PATCH v5 0/9] Improve DFU support, enable for am335x_evm Tom Rini
2013-03-08 17:37 ` [U-Boot] [PATCH v5 1/9] README: Document current DFU CONFIG options Tom Rini
2013-03-08 17:37 ` [U-Boot] [PATCH v5 2/9] dfu: Support larger than memory transfers Tom Rini
@ 2013-03-08 17:37 ` Tom Rini
2013-03-08 17:37 ` [U-Boot] [PATCH v5 4/9] nand: Extend nand_(read|write)_skip_bad with *actual and limit parameters Tom Rini
` (5 subsequent siblings)
8 siblings, 0 replies; 23+ messages in thread
From: Tom Rini @ 2013-03-08 17:37 UTC (permalink / raw)
To: u-boot
Signed-off-by: Tom Rini <trini@ti.com>
---
Changes in v5:
- New patch to re-align defines in <dfu.h>
Changes in v4: None
Changes in v3: None
Changes in v2: None
include/dfu.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/dfu.h b/include/dfu.h
index 5182c6c..0aae856 100644
--- a/include/dfu.h
+++ b/include/dfu.h
@@ -57,8 +57,8 @@ static inline unsigned int get_mmc_blk_size(int dev)
return find_mmc_device(dev)->read_bl_len;
}
-#define DFU_NAME_SIZE 32
-#define DFU_CMD_BUF_SIZE 128
+#define DFU_NAME_SIZE 32
+#define DFU_CMD_BUF_SIZE 128
#define DFU_DATA_BUF_SIZE (64 << 10) /* 64 KiB */
#ifndef CONFIG_SYS_DFU_MAX_FILE_SIZE
#define CONFIG_SYS_DFU_MAX_FILE_SIZE (4 << 20) /* 4 MiB */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [U-Boot] [PATCH v5 4/9] nand: Extend nand_(read|write)_skip_bad with *actual and limit parameters
2013-03-08 17:37 [U-Boot] [PATCH v5 0/9] Improve DFU support, enable for am335x_evm Tom Rini
` (2 preceding siblings ...)
2013-03-08 17:37 ` [U-Boot] [PATCH v5 3/9] dfu: Change indentation of defines in <dfu.h> Tom Rini
@ 2013-03-08 17:37 ` Tom Rini
2013-03-09 1:00 ` Scott Wood
2013-03-08 17:37 ` [U-Boot] [PATCH v5 5/9] cmd_nand.c: Fix CONFIG_CMD_NAND_YAFFS Tom Rini
` (4 subsequent siblings)
8 siblings, 1 reply; 23+ messages in thread
From: Tom Rini @ 2013-03-08 17:37 UTC (permalink / raw)
To: u-boot
We make these two functions take a size_t pointer to how much space
was used on NAND to read or write the buffer (when reads/writes happen)
so that bad blocks can be accounted for. We also make them take an
loff_t limit on how much data can be read or written. This means that
we can now catch the case of when writing to a partition would exceed
the partition size due to bad blocks. To do this we also need to make
check_skip_len count not just complete blocks used but partial ones as
well. All callers of nand_(read|write)_skip_bad are adjusted to call
these with the most sensible limits available.
The changes were started by Pantelis and finished by Tom.
Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
Signed-off-by: Tom Rini <trini@ti.com>
---
Changes in v5: None
Changes in v4:
- Further reword nand_util.c comments, from Scott
- In nand_write_skip_bad make sure *actual is 0 for YAFFS2 errors too,
reminded by Scott.
- In cmd_nand.c don't drop the size is less than maxsize check in
arg_off_size as other nand functions need this still (Scott).
Changes in v3:
- Reworked skip_check_len changes to just add accounting for *used to
the logic.
- Allow for actual to be NULL in nand_(read|write)_skip_bad, only DFU
calls this with a non-NULL parameter. Make sure the comments for both
functions explain the parameters and their behavior.
- Other style changes requested by Scott.
- As nand_(write|read)_skip_bad passes back just a used length now.
Changes in v2:
- NAND skip_check_len changes reworked to allow
nand_(read|write)_skip_bad to return this information to the caller.
common/cmd_nand.c | 53 ++++++++++++++++++--------------
common/env_nand.c | 3 +-
drivers/mtd/nand/nand_util.c | 68 +++++++++++++++++++++++++++++++++++++-----
include/nand.h | 4 +--
4 files changed, 95 insertions(+), 33 deletions(-)
diff --git a/common/cmd_nand.c b/common/cmd_nand.c
index 32348f3..76f4d3f 100644
--- a/common/cmd_nand.c
+++ b/common/cmd_nand.c
@@ -137,7 +137,8 @@ static inline int str2long(const char *p, ulong *num)
return *p != '\0' && *endptr == '\0';
}
-static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size)
+static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size,
+ loff_t *maxsize)
{
#ifdef CONFIG_CMD_MTDPARTS
struct mtd_device *dev;
@@ -160,6 +161,7 @@ static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size)
*off = part->offset;
*size = part->size;
+ *maxsize = part->size;
*idx = dev->id->num;
ret = set_dev(*idx);
@@ -173,10 +175,11 @@ static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size)
#endif
}
-static int arg_off(const char *arg, int *idx, loff_t *off, loff_t *maxsize)
+static int arg_off(const char *arg, int *idx, loff_t *off, loff_t *size,
+ loff_t *maxsize)
{
if (!str2off(arg, off))
- return get_part(arg, idx, off, maxsize);
+ return get_part(arg, idx, off, size, maxsize);
if (*off >= nand_info[*idx].size) {
puts("Offset exceeds device limit\n");
@@ -184,36 +187,35 @@ static int arg_off(const char *arg, int *idx, loff_t *off, loff_t *maxsize)
}
*maxsize = nand_info[*idx].size - *off;
+ *size = *maxsize;
return 0;
}
static int arg_off_size(int argc, char *const argv[], int *idx,
- loff_t *off, loff_t *size)
+ loff_t *off, loff_t *size, loff_t *maxsize)
{
int ret;
- loff_t maxsize = 0;
if (argc == 0) {
*off = 0;
*size = nand_info[*idx].size;
+ *maxsize = *size;
goto print;
}
- ret = arg_off(argv[0], idx, off, &maxsize);
+ ret = arg_off(argv[0], idx, off, size, maxsize);
if (ret)
return ret;
- if (argc == 1) {
- *size = maxsize;
+ if (argc == 1)
goto print;
- }
if (!str2off(argv[1], size)) {
printf("'%s' is not a number\n", argv[1]);
return -1;
}
- if (*size > maxsize) {
+ if (*size > *maxsize) {
puts("Size exceeds partition or device limit\n");
return -1;
}
@@ -307,7 +309,8 @@ int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
if (argc < 3)
goto usage;
- if (arg_off(argv[2], &idx, &addr, &maxsize)) {
+ /* We don't care about size, or maxsize. */
+ if (arg_off(argv[2], &idx, &addr, &maxsize, &maxsize)) {
puts("Offset or partition name expected\n");
return 1;
}
@@ -426,7 +429,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int i, ret = 0;
ulong addr;
- loff_t off, size;
+ loff_t off, size, maxsize;
char *cmd, *s;
nand_info_t *nand;
#ifdef CONFIG_SYS_NAND_QUIET
@@ -551,7 +554,8 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
printf("\nNAND %s: ", cmd);
/* skip first two or three arguments, look for offset and size */
- if (arg_off_size(argc - o, argv + o, &dev, &off, &size) != 0)
+ if (arg_off_size(argc - o, argv + o, &dev, &off, &size,
+ &maxsize) != 0)
return 1;
nand = &nand_info[dev];
@@ -619,7 +623,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (s && !strcmp(s, ".raw")) {
raw = 1;
- if (arg_off(argv[3], &dev, &off, &size))
+ if (arg_off(argv[3], &dev, &off, &size, &maxsize))
return 1;
if (argc > 4 && !str2long(argv[4], &pagecount)) {
@@ -635,7 +639,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
rwsize = pagecount * (nand->writesize + nand->oobsize);
} else {
if (arg_off_size(argc - 3, argv + 3, &dev,
- &off, &size) != 0)
+ &off, &size, &maxsize) != 0)
return 1;
rwsize = size;
@@ -645,9 +649,11 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
!strcmp(s, ".e") || !strcmp(s, ".i")) {
if (read)
ret = nand_read_skip_bad(nand, off, &rwsize,
+ NULL, maxsize,
(u_char *)addr);
else
ret = nand_write_skip_bad(nand, off, &rwsize,
+ NULL, maxsize,
(u_char *)addr, 0);
#ifdef CONFIG_CMD_NAND_TRIMFFS
} else if (!strcmp(s, ".trimffs")) {
@@ -655,8 +661,8 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
printf("Unknown nand command suffix '%s'\n", s);
return 1;
}
- ret = nand_write_skip_bad(nand, off, &rwsize,
- (u_char *)addr,
+ ret = nand_write_skip_bad(nand, off, &rwsize, NULL,
+ maxsize, (u_char *)addr,
WITH_DROP_FFS);
#endif
#ifdef CONFIG_CMD_NAND_YAFFS
@@ -665,8 +671,8 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
printf("Unknown nand command suffix '%s'.\n", s);
return 1;
}
- ret = nand_write_skip_bad(nand, off, &rwsize,
- (u_char *)addr,
+ ret = nand_write_skip_bad(nand, off, &rwsize, NULL,
+ maxsize, (u_char *)addr,
WITH_INLINE_OOB);
#endif
} else if (!strcmp(s, ".oob")) {
@@ -775,7 +781,8 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (s && !strcmp(s, ".allexcept"))
allexcept = 1;
- if (arg_off_size(argc - 2, argv + 2, &dev, &off, &size) < 0)
+ if (arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
+ &maxsize) < 0)
return 1;
if (!nand_unlock(&nand_info[dev], off, size, allexcept)) {
@@ -873,7 +880,8 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset);
cnt = nand->writesize;
- r = nand_read_skip_bad(nand, offset, &cnt, (u_char *) addr);
+ r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->size,
+ (u_char *) addr);
if (r) {
puts("** Read error\n");
bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
@@ -905,7 +913,8 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
}
bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
- r = nand_read_skip_bad(nand, offset, &cnt, (u_char *) addr);
+ r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->size,
+ (u_char *) addr);
if (r) {
puts("** Read error\n");
bootstage_error(BOOTSTAGE_ID_NAND_READ);
diff --git a/common/env_nand.c b/common/env_nand.c
index 5b69889..b745822 100644
--- a/common/env_nand.c
+++ b/common/env_nand.c
@@ -281,7 +281,8 @@ int readenv(size_t offset, u_char *buf)
} else {
char_ptr = &buf[amount_loaded];
if (nand_read_skip_bad(&nand_info[0], offset,
- &len, char_ptr))
+ &len, NULL,
+ nand_info[0].size, char_ptr))
return 1;
offset += blocksize;
diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c
index ff2d348..4727f9c 100644
--- a/drivers/mtd/nand/nand_util.c
+++ b/drivers/mtd/nand/nand_util.c
@@ -416,11 +416,13 @@ int nand_unlock(struct mtd_info *mtd, loff_t start, size_t length,
* @param nand NAND device
* @param offset offset in flash
* @param length image length
+ * @param used length of flash needed for the requested length
* @return 0 if the image fits and there are no bad blocks
* 1 if the image fits, but there are bad blocks
* -1 if the image does not fit
*/
-static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length)
+static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length,
+ size_t *used)
{
size_t len_excl_bad = 0;
int ret = 0;
@@ -442,8 +444,13 @@ static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length)
ret = 1;
offset += block_len;
+ *used += block_len;
}
+ /* If the length is not a multiple of block_len, adjust. */
+ if (len_excl_bad > length)
+ *used -= (len_excl_bad - length);
+
return ret;
}
@@ -476,23 +483,36 @@ static size_t drop_ffs(const nand_info_t *nand, const u_char *buf,
* Write image to NAND flash.
* Blocks that are marked bad are skipped and the is written to the next
* block instead as long as the image is short enough to fit even after
- * skipping the bad blocks.
+ * skipping the bad blocks. Due to bad blocks we may not be able to
+ * perform the requested write. In the case where the write would
+ * extend beyond the end of the NAND device, both length and actual (if
+ * not NULL) are set to 0. In the case where the write would extend
+ * beyond the limit we are passed, length is set to 0 and actual is set
+ * to the required length.
*
* @param nand NAND device
* @param offset offset in flash
* @param length buffer length
+ * @param actual set to size required to write length worth of
+ * buffer or 0 on error, if not NULL
+ * @param lim maximum size that actual may be in order to not
+ * exceed the buffer
* @param buffer buffer to read from
* @param flags flags modifying the behaviour of the write to NAND
* @return 0 in case of success
*/
int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
- u_char *buffer, int flags)
+ size_t *actual, loff_t lim, u_char *buffer, int flags)
{
int rval = 0, blocksize;
size_t left_to_write = *length;
+ size_t used_for_write = 0;
u_char *p_buffer = buffer;
int need_skip;
+ if (actual)
+ *actual = 0;
+
#ifdef CONFIG_CMD_NAND_YAFFS
if (flags & WITH_YAFFS_OOB) {
if (flags & ~WITH_YAFFS_OOB)
@@ -529,13 +549,23 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
return -EINVAL;
}
- need_skip = check_skip_len(nand, offset, *length);
+ need_skip = check_skip_len(nand, offset, *length, &used_for_write);
+
+ if (actual)
+ *actual = used_for_write;
+
if (need_skip < 0) {
printf("Attempt to write outside the flash area\n");
*length = 0;
return -EINVAL;
}
+ if (used_for_write > lim) {
+ puts("Size of write exceeds partition or device limit\n");
+ *length = 0;
+ return -EFBIG;
+ }
+
if (!need_skip && !(flags & WITH_DROP_FFS)) {
rval = nand_write(nand, offset, length, buffer);
if (rval == 0)
@@ -626,36 +656,58 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
*
* Read image from NAND flash.
* Blocks that are marked bad are skipped and the next block is read
- * instead as long as the image is short enough to fit even after skipping the
- * bad blocks.
+ * instead as long as the image is short enough to fit even after
+ * skipping the bad blocks. Due to bad blocks we may not be able to
+ * perform the requested read. In the case where the read would extend
+ * beyond the end of the NAND device, both length and actual (if not
+ * NULL) are set to 0. In the case where the read would extend beyond
+ * the limit we are passed, length is set to 0 and actual is set to the
+ * required length.
*
* @param nand NAND device
* @param offset offset in flash
* @param length buffer length, on return holds number of read bytes
+ * @param actual set to size required to read length worth of buffer or 0
+ * on error, if not NULL
+ * @param lim maximum size that actual may be in order to not exceed the
+ * buffer
* @param buffer buffer to write to
* @return 0 in case of success
*/
int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
- u_char *buffer)
+ size_t *actual, loff_t lim, u_char *buffer)
{
int rval;
size_t left_to_read = *length;
+ size_t used_for_read = 0;
u_char *p_buffer = buffer;
int need_skip;
if ((offset & (nand->writesize - 1)) != 0) {
printf("Attempt to read non page-aligned data\n");
*length = 0;
+ if (actual)
+ *actual = 0;
return -EINVAL;
}
- need_skip = check_skip_len(nand, offset, *length);
+ need_skip = check_skip_len(nand, offset, *length, &used_for_read);
+
+ if (actual)
+ *actual = used_for_read;
+
if (need_skip < 0) {
printf("Attempt to read outside the flash area\n");
*length = 0;
return -EINVAL;
}
+ if (used_for_read > lim) {
+ puts("Size of read exceeds partition or device limit\n");
+ *length = 0;
+ return -EFBIG;
+ }
+
if (!need_skip) {
rval = nand_read(nand, offset, length, buffer);
if (!rval || rval == -EUCLEAN)
diff --git a/include/nand.h b/include/nand.h
index dded4e2..f0f3bf9 100644
--- a/include/nand.h
+++ b/include/nand.h
@@ -129,7 +129,7 @@ struct nand_erase_options {
typedef struct nand_erase_options nand_erase_options_t;
int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
- u_char *buffer);
+ size_t *actual, loff_t lim, u_char *buffer);
#define WITH_YAFFS_OOB (1 << 0) /* whether write with yaffs format. This flag
* is a 'mode' meaning it cannot be mixed with
@@ -137,7 +137,7 @@ int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
#define WITH_DROP_FFS (1 << 1) /* drop trailing all-0xff pages */
int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
- u_char *buffer, int flags);
+ size_t *actual, loff_t lim, u_char *buffer, int flags);
int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts);
int nand_torture(nand_info_t *nand, loff_t offset);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [U-Boot] [PATCH v5 5/9] cmd_nand.c: Fix CONFIG_CMD_NAND_YAFFS
2013-03-08 17:37 [U-Boot] [PATCH v5 0/9] Improve DFU support, enable for am335x_evm Tom Rini
` (3 preceding siblings ...)
2013-03-08 17:37 ` [U-Boot] [PATCH v5 4/9] nand: Extend nand_(read|write)_skip_bad with *actual and limit parameters Tom Rini
@ 2013-03-08 17:37 ` Tom Rini
2013-03-08 17:37 ` [U-Boot] [PATCH v5 6/9] dfu: NAND specific routines for DFU operation Tom Rini
` (3 subsequent siblings)
8 siblings, 0 replies; 23+ messages in thread
From: Tom Rini @ 2013-03-08 17:37 UTC (permalink / raw)
To: u-boot
The flag changed from WITH_INLINE_OOB to WITH_YAFFS_OOB by accident in
418396e.
Signed-off-by: Tom Rini <trini@ti.com>
---
Changes in v5: None
Changes in v4:
- Add patch to fix CONFIG_CMD_NAND_YAFFS
Changes in v3: None
Changes in v2: None
common/cmd_nand.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/common/cmd_nand.c b/common/cmd_nand.c
index 76f4d3f..d9010d2 100644
--- a/common/cmd_nand.c
+++ b/common/cmd_nand.c
@@ -673,7 +673,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
ret = nand_write_skip_bad(nand, off, &rwsize, NULL,
maxsize, (u_char *)addr,
- WITH_INLINE_OOB);
+ WITH_YAFFS_OOB);
#endif
} else if (!strcmp(s, ".oob")) {
/* out-of-band data */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [U-Boot] [PATCH v5 6/9] dfu: NAND specific routines for DFU operation
2013-03-08 17:37 [U-Boot] [PATCH v5 0/9] Improve DFU support, enable for am335x_evm Tom Rini
` (4 preceding siblings ...)
2013-03-08 17:37 ` [U-Boot] [PATCH v5 5/9] cmd_nand.c: Fix CONFIG_CMD_NAND_YAFFS Tom Rini
@ 2013-03-08 17:37 ` Tom Rini
2013-03-09 1:08 ` Scott Wood
2013-03-08 17:37 ` [U-Boot] [PATCH v5 7/9] am335x_evm: Define CONFIG_SYS_CACHELINE_SIZE Tom Rini
` (2 subsequent siblings)
8 siblings, 1 reply; 23+ messages in thread
From: Tom Rini @ 2013-03-08 17:37 UTC (permalink / raw)
To: u-boot
From: Pantelis Antoniou <panto@antoniou-consulting.com>
Support for NAND storage devices to work with the DFU framework.
Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
Signed-off-by: Tom Rini <trini@ti.com>
---
Changes in v5:
- Document CONFIG_DFU_NAND in README
Changes in v4: None
Changes in v3:
- Rework logic in nand_block_op for nand_(read|write)_skip_bad returning
just a size for actual used length.
- Remove unused externs from drivers/dfu/dfu_nand.c
Changes in v2:
- nand_block_op calls nand_(read|write)_skip_bad directly.
- Bugfix in dfu_nand to make sure we set dfu->skip_bad to 0 on each
iteration.
README | 3 +
drivers/dfu/Makefile | 1 +
drivers/dfu/dfu.c | 8 ++
drivers/dfu/dfu_nand.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++
include/dfu.h | 23 ++++++
5 files changed, 230 insertions(+)
create mode 100644 drivers/dfu/dfu_nand.c
diff --git a/README b/README
index 154b82f..c70251e 100644
--- a/README
+++ b/README
@@ -1338,6 +1338,9 @@ The following options need to be configured:
CONFIG_DFU_MMC
This enables support for exposing (e)MMC devices via DFU.
+ CONFIG_DFU_NAND
+ This enables support for exposing NAND devices via DFU.
+
CONFIG_SYS_DFU_MAX_FILE_SIZE
When updating files rather than the raw storage device,
we use a static buffer to copy the file into and then write
diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
index 7b717bc..153095d 100644
--- a/drivers/dfu/Makefile
+++ b/drivers/dfu/Makefile
@@ -27,6 +27,7 @@ LIB = $(obj)libdfu.o
COBJS-$(CONFIG_DFU_FUNCTION) += dfu.o
COBJS-$(CONFIG_DFU_MMC) += dfu_mmc.o
+COBJS-$(CONFIG_DFU_NAND) += dfu_nand.o
SRCS := $(COBJS-y:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS-y))
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
index 2fecf77..84139bd 100644
--- a/drivers/dfu/dfu.c
+++ b/drivers/dfu/dfu.c
@@ -86,6 +86,7 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
/* initial state */
dfu->crc = 0;
dfu->offset = 0;
+ dfu->bad_skip = 0;
dfu->i_blk_seq_num = 0;
dfu->i_buf_start = dfu_buf;
dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
@@ -235,6 +236,8 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
dfu->i_buf = dfu->i_buf_start;
dfu->b_left = 0;
+ dfu->bad_skip = 0;
+
dfu->inited = 1;
}
@@ -264,6 +267,8 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
dfu->i_buf = dfu->i_buf_start;
dfu->b_left = 0;
+ dfu->bad_skip = 0;
+
dfu->inited = 0;
}
@@ -286,6 +291,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, s))
return -1;
+ } else if (strcmp(interface, "nand") == 0) {
+ if (dfu_fill_entity_nand(dfu, s))
+ return -1;
} else {
printf("%s: Device %s not (yet) supported!\n",
__func__, interface);
diff --git a/drivers/dfu/dfu_nand.c b/drivers/dfu/dfu_nand.c
new file mode 100644
index 0000000..b7f60dd
--- /dev/null
+++ b/drivers/dfu/dfu_nand.c
@@ -0,0 +1,195 @@
+/*
+ * dfu_nand.c -- DFU for NAND routines.
+ *
+ * Copyright (C) 2012-2013 Texas Instruments, Inc.
+ *
+ * Based on dfu_mmc.c which is:
+ * Copyright (C) 2012 Samsung Electronics
+ * author: Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <errno.h>
+#include <div64.h>
+#include <dfu.h>
+#include <linux/mtd/mtd.h>
+#include <jffs2/load_kernel.h>
+#include <nand.h>
+
+enum dfu_nand_op {
+ DFU_OP_READ = 1,
+ DFU_OP_WRITE,
+};
+
+static int nand_block_op(enum dfu_nand_op op, struct dfu_entity *dfu,
+ u64 offset, void *buf, long *len)
+{
+ loff_t start;
+ size_t count, actual;
+ int ret;
+ int dev;
+ nand_info_t *nand;
+
+ /* if buf == NULL return total size of the area */
+ if (buf == NULL) {
+ *len = dfu->data.nand.size;
+ return 0;
+ }
+
+ start = dfu->data.nand.start + offset + dfu->bad_skip;
+ count = *len;
+ if (start + count >
+ dfu->data.nand.start + dfu->data.nand.size) {
+ printf("%s: block_op out of bounds\n", __func__);
+ return -1;
+ }
+
+ dev = nand_curr_device;
+ if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
+ !nand_info[dev].name) {
+ printf("%s: invalid nand device\n", __func__);
+ return -1;
+ }
+
+ nand = &nand_info[dev];
+
+ if (op == DFU_OP_READ)
+ ret = nand_read_skip_bad(nand, start, &count, &actual,
+ nand->size, buf);
+ else
+ ret = nand_write_skip_bad(nand, start, &count, &actual,
+ nand->size, buf, 0);
+
+ if (ret != 0) {
+ printf("%s: nand_%s_skip_bad call failed at %llx!\n",
+ __func__, op == DFU_OP_READ ? "read" : "write",
+ start);
+ return ret;
+ }
+
+ /*
+ * Find out where we stopped writing data. This can be deeper into
+ * the NAND than we expected due to having to skip bad blocks. So
+ * we must take this into account for the next write, if any.
+ */
+ if (actual > count) {
+ printf("%s: skipped 0x%x bad bytes at 0x%llx\n", __func__,
+ actual - count, start);
+ dfu->bad_skip += actual - count;
+ }
+
+ return ret;
+}
+
+static inline int nand_block_write(struct dfu_entity *dfu,
+ u64 offset, void *buf, long *len)
+{
+ return nand_block_op(DFU_OP_WRITE, dfu, offset, buf, len);
+}
+
+static inline int nand_block_read(struct dfu_entity *dfu,
+ u64 offset, void *buf, long *len)
+{
+ return nand_block_op(DFU_OP_READ, dfu, offset, buf, len);
+}
+
+static int dfu_write_medium_nand(struct dfu_entity *dfu,
+ u64 offset, void *buf, long *len)
+{
+ int ret = -1;
+
+ switch (dfu->layout) {
+ case DFU_RAW_ADDR:
+ ret = nand_block_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_read_medium_nand(struct dfu_entity *dfu, u64 offset, void *buf,
+ long *len)
+{
+ int ret = -1;
+
+ switch (dfu->layout) {
+ case DFU_RAW_ADDR:
+ ret = nand_block_read(dfu, offset, buf, len);
+ break;
+ default:
+ printf("%s: Layout (%s) not (yet) supported!\n", __func__,
+ dfu_get_layout(dfu->layout));
+ }
+
+ return ret;
+}
+
+int dfu_fill_entity_nand(struct dfu_entity *dfu, char *s)
+{
+ char *st;
+ int ret, dev, part;
+
+ dfu->dev_type = DFU_DEV_NAND;
+ st = strsep(&s, " ");
+ if (!strcmp(st, "raw")) {
+ dfu->layout = DFU_RAW_ADDR;
+ dfu->data.nand.start = simple_strtoul(s, &s, 16);
+ s++;
+ dfu->data.nand.size = simple_strtoul(s, &s, 16);
+ } else if (!strcmp(st, "part")) {
+ char mtd_id[32];
+ struct mtd_device *mtd_dev;
+ u8 part_num;
+ struct part_info *pi;
+
+ dfu->layout = DFU_RAW_ADDR;
+
+ dev = simple_strtoul(s, &s, 10);
+ s++;
+ part = simple_strtoul(s, &s, 10);
+
+ sprintf(mtd_id, "%s%d,%d", "nand", 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.nand.start = pi->offset;
+ dfu->data.nand.size = pi->size;
+
+ } else {
+ printf("%s: Memory layout (%s) not supported!\n", __func__, st);
+ return -1;
+ }
+
+ dfu->read_medium = dfu_read_medium_nand;
+ dfu->write_medium = dfu_write_medium_nand;
+
+ /* initial state */
+ dfu->inited = 0;
+
+ return 0;
+}
diff --git a/include/dfu.h b/include/dfu.h
index 0aae856..e856a37 100644
--- a/include/dfu.h
+++ b/include/dfu.h
@@ -52,6 +52,15 @@ struct mmc_internal_data {
unsigned int part;
};
+struct nand_internal_data {
+ /* RAW programming */
+ u64 start;
+ u64 size;
+
+ unsigned int dev;
+ unsigned int part;
+};
+
static inline unsigned int get_mmc_blk_size(int dev)
{
return find_mmc_device(dev)->read_bl_len;
@@ -74,6 +83,7 @@ struct dfu_entity {
union {
struct mmc_internal_data mmc;
+ struct nand_internal_data nand;
} data;
int (*read_medium)(struct dfu_entity *dfu,
@@ -96,6 +106,8 @@ struct dfu_entity {
long r_left;
long b_left;
+ u32 bad_skip; /* for nand use */
+
unsigned int inited:1;
};
@@ -120,4 +132,15 @@ static inline int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
return -1;
}
#endif
+
+#ifdef CONFIG_DFU_NAND
+extern int dfu_fill_entity_nand(struct dfu_entity *dfu, char *s);
+#else
+static inline int dfu_fill_entity_nand(struct dfu_entity *dfu, char *s)
+{
+ puts("NAND support not available!\n");
+ return -1;
+}
+#endif
+
#endif /* __DFU_ENTITY_H_ */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [U-Boot] [PATCH v5 7/9] am335x_evm: Define CONFIG_SYS_CACHELINE_SIZE
2013-03-08 17:37 [U-Boot] [PATCH v5 0/9] Improve DFU support, enable for am335x_evm Tom Rini
` (5 preceding siblings ...)
2013-03-08 17:37 ` [U-Boot] [PATCH v5 6/9] dfu: NAND specific routines for DFU operation Tom Rini
@ 2013-03-08 17:37 ` Tom Rini
2013-03-08 17:37 ` [U-Boot] [PATCH v5 8/9] am335x_evm: Add CONFIG_CMD_MTDPARTS and relevant defaults Tom Rini
2013-03-08 17:37 ` [U-Boot] [PATCH v5 9/9] am335x_evm: Enable DFU for NAND and MMC, provide example alt_infos Tom Rini
8 siblings, 0 replies; 23+ messages in thread
From: Tom Rini @ 2013-03-08 17:37 UTC (permalink / raw)
To: u-boot
From: Pantelis Antoniou <panto@antoniou-consulting.com>
drivers/usb/gadget/composite.c requires that this is defined early.
Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
Signed-off-by: Tom Rini <trini@ti.com>
Acked-by: Tom Rini <trini@ti.com>
---
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None
include/configs/am335x_evm.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index 33ee2c4..59647d1 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -39,6 +39,8 @@
#define CONFIG_SETUP_MEMORY_TAGS
#define CONFIG_INITRD_TAG
+#define CONFIG_SYS_CACHELINE_SIZE 64
+
/* commands to include */
#include <config_cmd_default.h>
--
1.7.9.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [U-Boot] [PATCH v5 8/9] am335x_evm: Add CONFIG_CMD_MTDPARTS and relevant defaults
2013-03-08 17:37 [U-Boot] [PATCH v5 0/9] Improve DFU support, enable for am335x_evm Tom Rini
` (6 preceding siblings ...)
2013-03-08 17:37 ` [U-Boot] [PATCH v5 7/9] am335x_evm: Define CONFIG_SYS_CACHELINE_SIZE Tom Rini
@ 2013-03-08 17:37 ` Tom Rini
2013-03-08 17:37 ` [U-Boot] [PATCH v5 9/9] am335x_evm: Enable DFU for NAND and MMC, provide example alt_infos Tom Rini
8 siblings, 0 replies; 23+ messages in thread
From: Tom Rini @ 2013-03-08 17:37 UTC (permalink / raw)
To: u-boot
Signed-off-by: Tom Rini <trini@ti.com>
---
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2:
- Add CONFIG_CMD_MTDPARTS and relevant information to am335x_evm
include/configs/am335x_evm.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index 59647d1..61b861d 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -60,6 +60,8 @@
"fdtfile=\0" \
"console=ttyO0,115200n8\0" \
"optargs=\0" \
+ "mtdids=" MTDIDS_DEFAULT "\0" \
+ "mtdparts=" MTDPARTS_DEFAULT "\0" \
"mmcdev=0\0" \
"mmcroot=/dev/mmcblk0p2 ro\0" \
"mmcrootfstype=ext4 rootwait\0" \
@@ -341,6 +343,13 @@
/* NAND support */
#ifdef CONFIG_NAND
#define CONFIG_CMD_NAND
+#define CONFIG_CMD_MTDPARTS
+#define MTDIDS_DEFAULT "nand0=omap2-nand.0"
+#define MTDPARTS_DEFAULT "mtdparts=omap2-nand.0:128k(SPL)," \
+ "128k(SPL.backup1)," \
+ "128k(SPL.backup2)," \
+ "128k(SPL.backup3),1920k(u-boot)," \
+ "128k(u-boot-env),5m(kernel),-(rootfs)"
#define CONFIG_NAND_OMAP_GPMC
#define GPMC_NAND_ECC_LP_x16_LAYOUT 1
#define CONFIG_SYS_NAND_BASE (0x08000000) /* physical address */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [U-Boot] [PATCH v5 9/9] am335x_evm: Enable DFU for NAND and MMC, provide example alt_infos
2013-03-08 17:37 [U-Boot] [PATCH v5 0/9] Improve DFU support, enable for am335x_evm Tom Rini
` (7 preceding siblings ...)
2013-03-08 17:37 ` [U-Boot] [PATCH v5 8/9] am335x_evm: Add CONFIG_CMD_MTDPARTS and relevant defaults Tom Rini
@ 2013-03-08 17:37 ` Tom Rini
8 siblings, 0 replies; 23+ messages in thread
From: Tom Rini @ 2013-03-08 17:37 UTC (permalink / raw)
To: u-boot
From: Pantelis Antoniou <panto@antoniou-consulting.com>
- Add CONFIG_DFU_NAND, CONFIG_DFU_MMC
- Set dfu_alt_info_nand, dfu_alt_info_emmc and dfu_alt_info_mmc to show
working examples for those cases.
- Increase CONFIG_SYS_MAXARGS due to hush parsing bugs that would
otherwise disallow 'setenv dfu_alt_info ${dfu_alt_info_nand}'.
- Enable CONFIG_FAT_WRITE to allow updating on MMC
Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
Signed-off-by: Tom Rini <trini@ti.com>
---
Changes in v5:
- Add RAW MMC examples to include/configs/am335x_evm.h
Changes in v4: None
Changes in v3:
- Fix checkpatch.pl warnings in include/configs/am335x_evm.h
Changes in v2:
- Enable DFU for NAND and MMC, set dfu_alt_info_(nand|mmc) as examples
for both in am335x_evm.h
- Increase CONFIG_SYS_MAXARGS due to hush parsing bugs that would
otherwise prevent 'setenv dfu_alt_info ${dfu_alt_info_nand}' on
am335x_evm
include/configs/am335x_evm.h | 41 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 39 insertions(+), 2 deletions(-)
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index 61b861d..6b487c2 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -62,6 +62,9 @@
"optargs=\0" \
"mtdids=" MTDIDS_DEFAULT "\0" \
"mtdparts=" MTDPARTS_DEFAULT "\0" \
+ "dfu_alt_info_mmc=" DFU_ALT_INFO_MMC "\0" \
+ "dfu_alt_info_emmc=rawemmc mmc 0 3751936\0" \
+ "dfu_alt_info_nand=" DFU_ALT_INFO_NAND "\0" \
"mmcdev=0\0" \
"mmcroot=/dev/mmcblk0p2 ro\0" \
"mmcrootfstype=ext4 rootwait\0" \
@@ -118,8 +121,8 @@
#define CONFIG_CMD_ECHO
-/* max number of command args */
-#define CONFIG_SYS_MAXARGS 16
+/* We set the max number of command args high to avoid HUSH bugs. */
+#define CONFIG_SYS_MAXARGS 64
/* Console I/O Buffer Size */
#define CONFIG_SYS_CBSIZE 512
@@ -148,6 +151,7 @@
#define CONFIG_CMD_MMC
#define CONFIG_DOS_PARTITION
#define CONFIG_CMD_FAT
+#define CONFIG_FAT_WRITE
#define CONFIG_CMD_EXT2
#define CONFIG_SPI
@@ -158,6 +162,38 @@
#define CONFIG_CMD_SF
#define CONFIG_SF_DEFAULT_SPEED (24000000)
+/* USB Composite download gadget - g_dnl */
+#define CONFIG_USB_GADGET
+#define CONFIG_USBDOWNLOAD_GADGET
+
+/* USB TI's IDs */
+#define CONFIG_USBD_HS
+#define CONFIG_G_DNL_VENDOR_NUM 0x0403
+#define CONFIG_G_DNL_PRODUCT_NUM 0xBD00
+#define CONFIG_G_DNL_MANUFACTURER "Texas Instruments"
+
+/* USB Device Firmware Update support */
+#define CONFIG_DFU_FUNCTION
+#define CONFIG_DFU_MMC
+#define CONFIG_DFU_NAND
+#define CONFIG_CMD_DFU
+#define DFU_ALT_INFO_MMC \
+ "boot part 0 1;" \
+ "rootfs part 0 2;" \
+ "MLO fat 0 1;" \
+ "MLO.raw mmc 100 100;" \
+ "u-boot.img.raw mmc 300 3C0;" \
+ "u-boot.img fat 0 1;" \
+ "uEnv.txt fat 0 1"
+#define DFU_ALT_INFO_NAND \
+ "SPL part 0 1;" \
+ "SPL.backup1 part 0 2;" \
+ "SPL.backup2 part 0 3;" \
+ "SPL.backup3 part 0 4;" \
+ "u-boot part 0 5;" \
+ "kernel part 0 7;" \
+ "rootfs part 0 8"
+
/* Physical Memory Map */
#define CONFIG_NR_DRAM_BANKS 1 /* 1 bank of DRAM */
#define PHYS_DRAM_1 0x80000000 /* DRAM Bank #1 */
@@ -302,6 +338,7 @@
#define CONFIG_MUSB_GADGET
#define CONFIG_MUSB_PIO_ONLY
#define CONFIG_USB_GADGET_DUALSPEED
+#define CONFIG_USB_GADGET_VBUS_DRAW 2
#define CONFIG_MUSB_HOST
#define CONFIG_AM335X_USB0
#define CONFIG_AM335X_USB0_MODE MUSB_PERIPHERAL
--
1.7.9.5
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [U-Boot] [PATCH v5 4/9] nand: Extend nand_(read|write)_skip_bad with *actual and limit parameters
2013-03-08 17:37 ` [U-Boot] [PATCH v5 4/9] nand: Extend nand_(read|write)_skip_bad with *actual and limit parameters Tom Rini
@ 2013-03-09 1:00 ` Scott Wood
0 siblings, 0 replies; 23+ messages in thread
From: Scott Wood @ 2013-03-09 1:00 UTC (permalink / raw)
To: u-boot
On 03/08/2013 11:37:23 AM, Tom Rini wrote:
> We make these two functions take a size_t pointer to how much space
> was used on NAND to read or write the buffer (when reads/writes
> happen)
> so that bad blocks can be accounted for. We also make them take an
> loff_t limit on how much data can be read or written. This means that
> we can now catch the case of when writing to a partition would exceed
> the partition size due to bad blocks. To do this we also need to make
> check_skip_len count not just complete blocks used but partial ones as
> well. All callers of nand_(read|write)_skip_bad are adjusted to call
> these with the most sensible limits available.
>
> The changes were started by Pantelis and finished by Tom.
>
> Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
> Signed-off-by: Tom Rini <trini@ti.com>
> ---
> Changes in v5: None
> Changes in v4:
> - Further reword nand_util.c comments, from Scott
> - In nand_write_skip_bad make sure *actual is 0 for YAFFS2 errors too,
> reminded by Scott.
> - In cmd_nand.c don't drop the size is less than maxsize check in
> arg_off_size as other nand functions need this still (Scott).
>
> Changes in v3:
> - Reworked skip_check_len changes to just add accounting for *used to
> the logic.
> - Allow for actual to be NULL in nand_(read|write)_skip_bad, only DFU
> calls this with a non-NULL parameter. Make sure the comments for
> both
> functions explain the parameters and their behavior.
> - Other style changes requested by Scott.
> - As nand_(write|read)_skip_bad passes back just a used length now.
>
> Changes in v2:
> - NAND skip_check_len changes reworked to allow
> nand_(read|write)_skip_bad to return this information to the caller.
>
> common/cmd_nand.c | 53 ++++++++++++++++++--------------
> common/env_nand.c | 3 +-
> drivers/mtd/nand/nand_util.c | 68
> +++++++++++++++++++++++++++++++++++++-----
> include/nand.h | 4 +--
> 4 files changed, 95 insertions(+), 33 deletions(-)
Acked-by: Scott Wood <scottwood@freescale.com>
-Scott
^ permalink raw reply [flat|nested] 23+ messages in thread
* [U-Boot] [PATCH v5 6/9] dfu: NAND specific routines for DFU operation
2013-03-08 17:37 ` [U-Boot] [PATCH v5 6/9] dfu: NAND specific routines for DFU operation Tom Rini
@ 2013-03-09 1:08 ` Scott Wood
2013-03-13 20:04 ` Tom Rini
0 siblings, 1 reply; 23+ messages in thread
From: Scott Wood @ 2013-03-09 1:08 UTC (permalink / raw)
To: u-boot
On 03/08/2013 11:37:25 AM, Tom Rini wrote:
> From: Pantelis Antoniou <panto@antoniou-consulting.com>
>
> Support for NAND storage devices to work with the DFU framework.
>
> Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
> Signed-off-by: Tom Rini <trini@ti.com>
> ---
> Changes in v5:
> - Document CONFIG_DFU_NAND in README
>
> Changes in v4: None
> Changes in v3:
> - Rework logic in nand_block_op for nand_(read|write)_skip_bad
> returning
> just a size for actual used length.
> - Remove unused externs from drivers/dfu/dfu_nand.c
>
> Changes in v2:
> - nand_block_op calls nand_(read|write)_skip_bad directly.
> - Bugfix in dfu_nand to make sure we set dfu->skip_bad to 0 on each
> iteration.
>
> README | 3 +
> drivers/dfu/Makefile | 1 +
> drivers/dfu/dfu.c | 8 ++
> drivers/dfu/dfu_nand.c | 195
> ++++++++++++++++++++++++++++++++++++++++++++++++
> include/dfu.h | 23 ++++++
> 5 files changed, 230 insertions(+)
> create mode 100644 drivers/dfu/dfu_nand.c
>
> diff --git a/README b/README
> index 154b82f..c70251e 100644
> --- a/README
> +++ b/README
> @@ -1338,6 +1338,9 @@ The following options need to be configured:
> CONFIG_DFU_MMC
> This enables support for exposing (e)MMC devices via
> DFU.
>
> + CONFIG_DFU_NAND
> + This enables support for exposing NAND devices via DFU.
> +
> CONFIG_SYS_DFU_MAX_FILE_SIZE
> When updating files rather than the raw storage device,
> we use a static buffer to copy the file into and then
> write
> diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
> index 7b717bc..153095d 100644
> --- a/drivers/dfu/Makefile
> +++ b/drivers/dfu/Makefile
> @@ -27,6 +27,7 @@ LIB = $(obj)libdfu.o
>
> COBJS-$(CONFIG_DFU_FUNCTION) += dfu.o
> COBJS-$(CONFIG_DFU_MMC) += dfu_mmc.o
> +COBJS-$(CONFIG_DFU_NAND) += dfu_nand.o
>
> SRCS := $(COBJS-y:.o=.c)
> OBJS := $(addprefix $(obj),$(COBJS-y))
> diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
> index 2fecf77..84139bd 100644
> --- a/drivers/dfu/dfu.c
> +++ b/drivers/dfu/dfu.c
> @@ -86,6 +86,7 @@ int dfu_write(struct dfu_entity *dfu, void *buf,
> int size, int blk_seq_num)
> /* initial state */
> dfu->crc = 0;
> dfu->offset = 0;
> + dfu->bad_skip = 0;
> dfu->i_blk_seq_num = 0;
> dfu->i_buf_start = dfu_buf;
> dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
> @@ -235,6 +236,8 @@ int dfu_read(struct dfu_entity *dfu, void *buf,
> int size, int blk_seq_num)
> dfu->i_buf = dfu->i_buf_start;
> dfu->b_left = 0;
>
> + dfu->bad_skip = 0;
> +
> dfu->inited = 1;
> }
>
> @@ -264,6 +267,8 @@ int dfu_read(struct dfu_entity *dfu, void *buf,
> int size, int blk_seq_num)
> dfu->i_buf = dfu->i_buf_start;
> dfu->b_left = 0;
>
> + dfu->bad_skip = 0;
> +
> dfu->inited = 0;
> }
>
> @@ -286,6 +291,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, s))
> return -1;
> + } else if (strcmp(interface, "nand") == 0) {
> + if (dfu_fill_entity_nand(dfu, s))
> + return -1;
> } else {
> printf("%s: Device %s not (yet) supported!\n",
> __func__, interface);
> diff --git a/drivers/dfu/dfu_nand.c b/drivers/dfu/dfu_nand.c
> new file mode 100644
> index 0000000..b7f60dd
> --- /dev/null
> +++ b/drivers/dfu/dfu_nand.c
> @@ -0,0 +1,195 @@
> +/*
> + * dfu_nand.c -- DFU for NAND routines.
> + *
> + * Copyright (C) 2012-2013 Texas Instruments, Inc.
> + *
> + * Based on dfu_mmc.c which is:
> + * Copyright (C) 2012 Samsung Electronics
> + * author: Lukasz Majewski <l.majewski@samsung.com>
> + *
> + * This program is free software; you can redistribute it and/or
> modify
> + * it under the terms of the GNU General Public License as published
> by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
> 02111-1307 USA
> + */
> +
> +#include <common.h>
> +#include <malloc.h>
> +#include <errno.h>
> +#include <div64.h>
> +#include <dfu.h>
> +#include <linux/mtd/mtd.h>
> +#include <jffs2/load_kernel.h>
> +#include <nand.h>
> +
> +enum dfu_nand_op {
> + DFU_OP_READ = 1,
> + DFU_OP_WRITE,
> +};
> +
> +static int nand_block_op(enum dfu_nand_op op, struct dfu_entity *dfu,
> + u64 offset, void *buf, long *len)
> +{
> + loff_t start;
> + size_t count, actual;
> + int ret;
> + int dev;
> + nand_info_t *nand;
> +
> + /* if buf == NULL return total size of the area */
> + if (buf == NULL) {
> + *len = dfu->data.nand.size;
> + return 0;
> + }
> +
> + start = dfu->data.nand.start + offset + dfu->bad_skip;
> + count = *len;
> + if (start + count >
> + dfu->data.nand.start + dfu->data.nand.size) {
> + printf("%s: block_op out of bounds\n", __func__);
> + return -1;
> + }
> +
> + dev = nand_curr_device;
> + if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
> + !nand_info[dev].name) {
> + printf("%s: invalid nand device\n", __func__);
> + return -1;
> + }
> +
> + nand = &nand_info[dev];
> +
> + if (op == DFU_OP_READ)
> + ret = nand_read_skip_bad(nand, start, &count, &actual,
> + nand->size, buf);
> + else
> + ret = nand_write_skip_bad(nand, start, &count, &actual,
> + nand->size, buf, 0);
Shouldn't "lim" be "dfu->data.nand.start + dfu->data.nand.size - start"?
This should let you get rid of the bounds check above, which doesn't
factor in bad blocks that have yet to be encountered.
> + if (ret != 0) {
> + printf("%s: nand_%s_skip_bad call failed at %llx!\n",
> + __func__, op == DFU_OP_READ ? "read" :
> "write",
> + start);
> + return ret;
> + }
> +
> + /*
> + * Find out where we stopped writing data. This can be deeper
> into
> + * the NAND than we expected due to having to skip bad blocks.
> So
> + * we must take this into account for the next write, if any.
> + */
> + if (actual > count) {
> + printf("%s: skipped 0x%x bad bytes at 0x%llx\n",
> __func__,
> + actual - count, start);
> + dfu->bad_skip += actual - count;
> + }
Hmm, the message suggests the bad blocks are at "start" rather than
somewhere between "start" and "start + actual".
nand_write_skip_bad() already prints a message when actually skipping
the block, so you probably don't need any print here.
-Scott
^ permalink raw reply [flat|nested] 23+ messages in thread
* [U-Boot] [PATCH v5 2/9] dfu: Support larger than memory transfers.
2013-03-08 17:37 ` [U-Boot] [PATCH v5 2/9] dfu: Support larger than memory transfers Tom Rini
@ 2013-03-11 9:38 ` Lukasz Majewski
2013-03-11 10:03 ` Lukasz Majewski
2013-03-11 11:36 ` [U-Boot] Nand flash (supports ONFI) TigerLiu at viatech.com.cn
0 siblings, 2 replies; 23+ messages in thread
From: Lukasz Majewski @ 2013-03-11 9:38 UTC (permalink / raw)
To: u-boot
Hi Tom,
> From: Pantelis Antoniou <panto@antoniou-consulting.com>
>
> Previously we didn't support upload/download larger than available
> memory. This is pretty bad when you have to update your root
> filesystem for example.
>
> This patch removes that limitation (and the crashes when you
> transfered any file larger than 4MB) by making raw image writes be
> done in chunks and making file maximum size be configurable.
>
> The sequence number is a 16 bit counter; make sure we handle rollover
> correctly. This fixes the wrong transfers for large (> 256MB) images.
>
> Also utilize a variable to handle initialization, so that we don't
> rely on just the counter sent by the host.
>
> Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
> Signed-off-by: Tom Rini <trini@ti.com>
Acked-by: Lukasz Majewski <l.majewski@samsung.com>
Test-hw: Exynos 4210 (Trats)
Tested-by: Lukasz Majewski <l.majewski@samsung.com>
> ---
> Changes in v5:
> - Rework Pantelis' "dfu: Support larger than memory transfers" to not
> break filesystem writing
>
> Changes in v4: None
> Changes in v3: None
> Changes in v2: None
>
> README | 7 ++
> drivers/dfu/dfu.c | 245
> ++++++++++++++++++++++++++++++++++++++-----------
> drivers/dfu/dfu_mmc.c | 116 +++++++++++++++++------
> include/dfu.h | 26 +++++- 4 files changed, 310
> insertions(+), 84 deletions(-)
>
> diff --git a/README b/README
> index 900ae5f..154b82f 100644
> --- a/README
> +++ b/README
> @@ -1338,6 +1338,13 @@ The following options need to be configured:
> CONFIG_DFU_MMC
> This enables support for exposing (e)MMC devices via
> DFU.
> + CONFIG_SYS_DFU_MAX_FILE_SIZE
> + When updating files rather than the raw storage
> device,
> + we use a static buffer to copy the file into and
> then write
> + the buffer once we've been given the whole file.
> Define
> + this to the maximum filesize (in bytes) for the
> buffer.
> + Default is 4 MiB if undefined.
> +
> - Journaling Flash filesystem support:
> CONFIG_JFFS2_NAND, CONFIG_JFFS2_NAND_OFF,
> CONFIG_JFFS2_NAND_SIZE, CONFIG_JFFS2_NAND_DEV
> diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
> index e8477fb..2fecf77 100644
> --- a/drivers/dfu/dfu.c
> +++ b/drivers/dfu/dfu.c
> @@ -44,90 +44,229 @@ static int dfu_find_alt_num(const char *s)
> static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
> dfu_buf[DFU_DATA_BUF_SIZE];
>
> +static int dfu_write_buffer_drain(struct dfu_entity *dfu)
> +{
> + long w_size;
> + int ret;
> +
> + /* flush size? */
> + w_size = dfu->i_buf - dfu->i_buf_start;
> + if (w_size == 0)
> + return 0;
> +
> + /* update CRC32 */
> + dfu->crc = crc32(dfu->crc, dfu->i_buf_start, w_size);
> +
> + ret = dfu->write_medium(dfu, dfu->offset, dfu->i_buf_start,
> &w_size);
> + if (ret)
> + debug("%s: Write error!\n", __func__);
> +
> + /* point back */
> + dfu->i_buf = dfu->i_buf_start;
> +
> + /* update offset */
> + dfu->offset += w_size;
> +
> + puts("#");
> +
> + return ret;
> +}
> +
> int dfu_write(struct dfu_entity *dfu, void *buf, int size, int
> blk_seq_num) {
> - static unsigned char *i_buf;
> - static int i_blk_seq_num;
> - long w_size = 0;
> int ret = 0;
> + int tret;
> +
> + debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x "
> + "offset: 0x%llx bufoffset: 0x%x\n",
> + __func__, dfu->name, buf, size, blk_seq_num,
> dfu->offset,
> + dfu->i_buf - dfu->i_buf_start);
> +
> + if (!dfu->inited) {
> + /* initial state */
> + dfu->crc = 0;
> + dfu->offset = 0;
> + dfu->i_blk_seq_num = 0;
> + dfu->i_buf_start = dfu_buf;
> + dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
> + dfu->i_buf = dfu->i_buf_start;
> +
> + dfu->inited = 1;
> + }
>
> - debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf:
> 0x%p\n",
> - __func__, dfu->name, buf, size, blk_seq_num, i_buf);
> + if (dfu->i_blk_seq_num != blk_seq_num) {
> + printf("%s: Wrong sequence number! [%d] [%d]\n",
> + __func__, dfu->i_blk_seq_num, blk_seq_num);
> + return -1;
> + }
>
> - if (blk_seq_num == 0) {
> - i_buf = dfu_buf;
> - i_blk_seq_num = 0;
> + /* DFU 1.1 standard says:
> + * The wBlockNum field is a block sequence number. It
> increments each
> + * time a block is transferred, wrapping to zero from
> 65,535. It is used
> + * to provide useful context to the DFU loader in the
> device."
> + *
> + * This means that it's a 16 bit counter that roll-overs at
> + * 0xffff -> 0x0000. By having a typical 4K transfer block
> + * we roll-over at exactly 256MB. Not very fun to debug.
> + *
> + * Handling rollover, and having an inited variable,
> + * makes things work.
> + */
> +
> + /* handle rollover */
> + dfu->i_blk_seq_num = (dfu->i_blk_seq_num + 1) & 0xffff;
> +
> + /* flush buffer if overflow */
> + if ((dfu->i_buf + size) > dfu->i_buf_end) {
> + tret = dfu_write_buffer_drain(dfu);
> + if (ret == 0)
> + ret = tret;
> }
>
> - if (i_blk_seq_num++ != blk_seq_num) {
> - printf("%s: Wrong sequence number! [%d] [%d]\n",
> - __func__, i_blk_seq_num, blk_seq_num);
> + /* we should be in buffer now (if not then size too large) */
> + if ((dfu->i_buf + size) > dfu->i_buf_end) {
> + printf("%s: Wrong size! [%d] [%d] - %d\n",
> + __func__, dfu->i_blk_seq_num, blk_seq_num,
> size); return -1;
> }
>
> - memcpy(i_buf, buf, size);
> - i_buf += size;
> + memcpy(dfu->i_buf, buf, size);
> + dfu->i_buf += size;
>
> + /* if end or if buffer full flush */
> + if (size == 0 || (dfu->i_buf + size) > dfu->i_buf_end) {
> + tret = dfu_write_buffer_drain(dfu);
> + if (ret == 0)
> + ret = tret;
> + }
> +
> + /* end? */
> if (size == 0) {
> - /* Integrity check (if needed) */
> - debug("%s: %s %d [B] CRC32: 0x%x\n", __func__,
> dfu->name,
> - i_buf - dfu_buf, crc32(0, dfu_buf, i_buf -
> dfu_buf));
> + /* Now try and flush to the medium if needed. */
> + if (dfu->flush_medium)
> + ret = dfu->flush_medium(dfu);
> + printf("\nDFU complete CRC32: 0x%08x\n", dfu->crc);
>
> - w_size = i_buf - dfu_buf;
> - ret = dfu->write_medium(dfu, dfu_buf, &w_size);
> - if (ret)
> - debug("%s: Write error!\n", __func__);
> + /* clear everything */
> + dfu->crc = 0;
> + dfu->offset = 0;
> + dfu->i_blk_seq_num = 0;
> + dfu->i_buf_start = dfu_buf;
> + dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
> + dfu->i_buf = dfu->i_buf_start;
> +
> + dfu->inited = 0;
>
> - i_blk_seq_num = 0;
> - i_buf = NULL;
> - return ret;
> }
>
> - return ret;
> + return ret = 0 ? size : ret;
> +}
> +
> +static int dfu_read_buffer_fill(struct dfu_entity *dfu, void *buf,
> int size) +{
> + long chunk;
> + int ret, readn;
> +
> + readn = 0;
> + while (size > 0) {
> +
> + /* get chunk that can be read */
> + chunk = min(size, dfu->b_left);
> + /* consume */
> + if (chunk > 0) {
> + memcpy(buf, dfu->i_buf, chunk);
> + dfu->crc = crc32(dfu->crc, buf, chunk);
> + dfu->i_buf += chunk;
> + dfu->b_left -= chunk;
> + size -= chunk;
> + buf += chunk;
> + readn += chunk;
> + }
> +
> + /* all done */
> + if (size > 0) {
> + /* no more to read */
> + if (dfu->r_left == 0)
> + break;
> +
> + dfu->i_buf = dfu->i_buf_start;
> + dfu->b_left = dfu->i_buf_end -
> dfu->i_buf_start; +
> + /* got to read, but buffer is empty */
> + if (dfu->b_left > dfu->r_left)
> + dfu->b_left = dfu->r_left;
> + ret = dfu->read_medium(dfu, dfu->offset,
> dfu->i_buf,
> + &dfu->b_left);
> + if (ret != 0) {
> + debug("%s: Read error!\n", __func__);
> + return ret;
> + }
> + dfu->offset += dfu->b_left;
> + dfu->r_left -= dfu->b_left;
> +
> + puts("#");
> + }
> + }
> +
> + return readn;
> }
>
> int dfu_read(struct dfu_entity *dfu, void *buf, int size, int
> blk_seq_num) {
> - static unsigned char *i_buf;
> - static int i_blk_seq_num;
> - static long r_size;
> - static u32 crc;
> int ret = 0;
>
> debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf:
> 0x%p\n",
> - __func__, dfu->name, buf, size, blk_seq_num, i_buf);
> -
> - if (blk_seq_num == 0) {
> - i_buf = dfu_buf;
> - ret = dfu->read_medium(dfu, i_buf, &r_size);
> - debug("%s: %s %ld [B]\n", __func__, dfu->name,
> r_size);
> - i_blk_seq_num = 0;
> - /* Integrity check (if needed) */
> - crc = crc32(0, dfu_buf, r_size);
> + __func__, dfu->name, buf, size, blk_seq_num,
> dfu->i_buf); +
> + if (!dfu->inited) {
> + ret = dfu->read_medium(dfu, 0, NULL, &dfu->r_left);
> + if (ret != 0) {
> + debug("%s: failed to get r_left\n",
> __func__);
> + return ret;
> + }
> +
> + debug("%s: %s %ld [B]\n", __func__, dfu->name,
> dfu->r_left); +
> + dfu->i_blk_seq_num = 0;
> + dfu->crc = 0;
> + dfu->offset = 0;
> + dfu->i_buf_start = dfu_buf;
> + dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
> + dfu->i_buf = dfu->i_buf_start;
> + dfu->b_left = 0;
> +
> + dfu->inited = 1;
> }
>
> - if (i_blk_seq_num++ != blk_seq_num) {
> + if (dfu->i_blk_seq_num != blk_seq_num) {
> printf("%s: Wrong sequence number! [%d] [%d]\n",
> - __func__, i_blk_seq_num, blk_seq_num);
> + __func__, dfu->i_blk_seq_num, blk_seq_num);
> return -1;
> }
> + /* handle rollover */
> + dfu->i_blk_seq_num = (dfu->i_blk_seq_num + 1) & 0xffff;
>
> - if (r_size >= size) {
> - memcpy(buf, i_buf, size);
> - i_buf += size;
> - r_size -= size;
> - return size;
> - } else {
> - memcpy(buf, i_buf, r_size);
> - i_buf += r_size;
> - debug("%s: %s CRC32: 0x%x\n", __func__, dfu->name,
> crc);
> - puts("UPLOAD ... done\nCtrl+C to exit ...\n");
> + ret = dfu_read_buffer_fill(dfu, buf, size);
> + if (ret < 0) {
> + printf("%s: Failed to fill buffer\n", __func__);
> + return -1;
> + }
> +
> + if (ret < size) {
> + debug("%s: %s CRC32: 0x%x\n", __func__, dfu->name,
> dfu->crc);
> + puts("\nUPLOAD ... done\nCtrl+C to exit ...\n");
>
> - i_buf = NULL;
> - i_blk_seq_num = 0;
> - crc = 0;
> - return r_size;
> + dfu->i_blk_seq_num = 0;
> + dfu->crc = 0;
> + dfu->offset = 0;
> + dfu->i_buf_start = dfu_buf;
> + dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
> + dfu->i_buf = dfu->i_buf_start;
> + dfu->b_left = 0;
> +
> + dfu->inited = 0;
> }
> +
> return ret;
> }
>
> diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
> index 083d745..2d5ffd8 100644
> --- a/drivers/dfu/dfu_mmc.c
> +++ b/drivers/dfu/dfu_mmc.c
> @@ -22,6 +22,7 @@
> #include <common.h>
> #include <malloc.h>
> #include <errno.h>
> +#include <div64.h>
> #include <dfu.h>
>
> enum dfu_mmc_op {
> @@ -29,36 +30,67 @@ enum dfu_mmc_op {
> DFU_OP_WRITE,
> };
>
> +static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
> +
> dfu_file_buf[CONFIG_SYS_DFU_MAX_FILE_SIZE]; +static long
> dfu_file_buf_len; +
> static int mmc_block_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
> - void *buf, long *len)
> + u64 offset, void *buf, long *len)
> {
> char cmd_buf[DFU_CMD_BUF_SIZE];
> + u32 blk_start, blk_count;
> +
> + /*
> + * We must ensure that we work in lba_blk_size chunks, so
> ALIGN
> + * this value.
> + */
> + *len = ALIGN(*len, dfu->data.mmc.lba_blk_size);
> +
> + blk_start = dfu->data.mmc.lba_start +
> + (u32)lldiv(offset,
> dfu->data.mmc.lba_blk_size);
> + blk_count = *len / dfu->data.mmc.lba_blk_size;
> + if (*len + blk_start >
> + dfu->data.mmc.lba_size *
> dfu->data.mmc.lba_size) {
> + puts("Request would exceed designated area!\n");
> + return -EINVAL;
> + }
>
> - sprintf(cmd_buf, "mmc %s 0x%x %x %x",
> + sprintf(cmd_buf, "mmc %s %p %x %x",
> op == DFU_OP_READ ? "read" : "write",
> - (unsigned int) buf,
> - dfu->data.mmc.lba_start,
> - dfu->data.mmc.lba_size);
> -
> - if (op == DFU_OP_READ)
> - *len = dfu->data.mmc.lba_blk_size *
> dfu->data.mmc.lba_size;
> + buf, blk_start, blk_count);
>
> debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
> return run_command(cmd_buf, 0);
> }
>
> -static inline int mmc_block_write(struct dfu_entity *dfu, void *buf,
> long *len) +static inline int mmc_block_write(struct dfu_entity *dfu,
> + u64 offset, void *buf, long *len)
> +{
> + return mmc_block_op(DFU_OP_WRITE, dfu, offset, buf, len);
> +}
> +
> +static inline int mmc_block_read(struct dfu_entity *dfu,
> + u64 offset, void *buf, long *len)
> {
> - return mmc_block_op(DFU_OP_WRITE, dfu, buf, len);
> + return mmc_block_op(DFU_OP_READ, dfu, offset, buf, len);
> }
>
> -static inline int mmc_block_read(struct dfu_entity *dfu, void *buf,
> long *len) +static int mmc_file_buffer(struct dfu_entity *dfu, void
> *buf, long *len) {
> - return mmc_block_op(DFU_OP_READ, dfu, buf, len);
> + if (dfu_file_buf_len + *len > CONFIG_SYS_DFU_MAX_FILE_SIZE) {
> + dfu_file_buf_len = 0;
> + return -EINVAL;
> + }
> +
> + /* Add to the current buffer. */
> + memcpy(dfu_file_buf + dfu_file_buf_len, buf, *len);
> + dfu_file_buf_len += *len;
> +
> + return 0;
> }
>
> static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
> - void *buf, long *len)
> + u64 offset, void *buf, long *len)
> {
> char cmd_buf[DFU_CMD_BUF_SIZE];
> char *str_env;
> @@ -70,8 +102,15 @@ static int mmc_file_op(enum dfu_mmc_op op, struct
> dfu_entity *dfu, op == DFU_OP_READ ? "load" : "write",
> dfu->data.mmc.dev, dfu->data.mmc.part,
> (unsigned int) buf, dfu->name, *len);
> + if (op == DFU_OP_READ && offset != 0)
> + sprintf(cmd_buf + strlen(cmd_buf), " %llx",
> offset); break;
> case DFU_FS_EXT4:
> + if (offset != 0) {
> + debug("%s: Offset value %llx != 0 not
> supported!\n",
> + __func__, offset);
> + return -1;
> + }
> sprintf(cmd_buf, "ext4%s mmc %d:%d /%s 0x%x %ld",
> op == DFU_OP_READ ? "load" : "write",
> dfu->data.mmc.dev, dfu->data.mmc.part,
> @@ -80,6 +119,7 @@ static int mmc_file_op(enum dfu_mmc_op op, struct
> dfu_entity *dfu, default:
> printf("%s: Layout (%s) not (yet) supported!\n",
> __func__, dfu_get_layout(dfu->layout));
> + return -1;
> }
>
> debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
> @@ -102,27 +142,24 @@ static int mmc_file_op(enum dfu_mmc_op op,
> struct dfu_entity *dfu, return ret;
> }
>
> -static inline int mmc_file_write(struct dfu_entity *dfu, void *buf,
> long *len) +static inline int mmc_file_read(struct dfu_entity *dfu,
> + u64 offset, void *buf, long *len)
> {
> - return mmc_file_op(DFU_OP_WRITE, dfu, buf, len);
> + return mmc_file_op(DFU_OP_READ, dfu, offset, buf, len);
> }
>
> -static inline int mmc_file_read(struct dfu_entity *dfu, void *buf,
> long *len) -{
> - return mmc_file_op(DFU_OP_READ, dfu, buf, len);
> -}
> -
> -int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf, long
> *len) +int dfu_write_medium_mmc(struct dfu_entity *dfu,
> + u64 offset, void *buf, long *len)
> {
> int ret = -1;
>
> switch (dfu->layout) {
> case DFU_RAW_ADDR:
> - ret = mmc_block_write(dfu, buf, len);
> + ret = mmc_block_write(dfu, offset, buf, len);
> break;
> case DFU_FS_FAT:
> case DFU_FS_EXT4:
> - ret = mmc_file_write(dfu, buf, len);
> + ret = mmc_file_buffer(dfu, buf, len);
> break;
> default:
> printf("%s: Layout (%s) not (yet) supported!\n",
> __func__, @@ -132,17 +169,34 @@ int dfu_write_medium_mmc(struct
> dfu_entity *dfu, void *buf, long *len) return ret;
> }
>
> -int dfu_read_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
> +int dfu_flush_medium_mmc(struct dfu_entity *dfu)
> +{
> + int ret = 0;
> +
> + if (dfu->layout != DFU_RAW_ADDR) {
> + /* Do stuff here. */
> + ret = mmc_file_op(DFU_OP_WRITE, dfu, 0,
> &dfu_file_buf,
> + &dfu_file_buf_len);
> +
> + /* Now that we're done */
> + dfu_file_buf_len = 0;
> + }
> +
> + return ret;
> +}
> +
> +int dfu_read_medium_mmc(struct dfu_entity *dfu, u64 offset, void
> *buf,
> + long *len)
> {
> int ret = -1;
>
> switch (dfu->layout) {
> case DFU_RAW_ADDR:
> - ret = mmc_block_read(dfu, buf, len);
> + ret = mmc_block_read(dfu, offset, buf, len);
> break;
> case DFU_FS_FAT:
> case DFU_FS_EXT4:
> - ret = mmc_file_read(dfu, buf, len);
> + ret = mmc_file_read(dfu, offset, buf, len);
> break;
> default:
> printf("%s: Layout (%s) not (yet) supported!\n",
> __func__, @@ -181,13 +235,15 @@ int dfu_fill_entity_mmc(struct
> dfu_entity *dfu, char *s)
> mmc = find_mmc_device(dev);
> if (mmc == NULL || mmc_init(mmc)) {
> - printf("%s: could not find mmc device
> #%d!\n", __func__, dev);
> + printf("%s: could not find mmc device
> #%d!\n",
> + __func__, dev);
> return -ENODEV;
> }
>
> blk_dev = &mmc->block_dev;
> if (get_partition_info(blk_dev, part, &partinfo) !=
> 0) {
> - printf("%s: could not find partition #%d on
> mmc device #%d!\n",
> + printf("%s: could not find partition #%d "
> + "on mmc device #%d!\n",
> __func__, part, dev);
> return -ENODEV;
> }
> @@ -208,6 +264,10 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu,
> char *s)
> dfu->read_medium = dfu_read_medium_mmc;
> dfu->write_medium = dfu_write_medium_mmc;
> + dfu->flush_medium = dfu_flush_medium_mmc;
> +
> + /* initial state */
> + dfu->inited = 0;
>
> return 0;
> }
> diff --git a/include/dfu.h b/include/dfu.h
> index 5350d79..5182c6c 100644
> --- a/include/dfu.h
> +++ b/include/dfu.h
> @@ -59,7 +59,10 @@ static inline unsigned int get_mmc_blk_size(int
> dev)
> #define DFU_NAME_SIZE 32
> #define DFU_CMD_BUF_SIZE 128
> -#define DFU_DATA_BUF_SIZE (1024*1024*4) /* 4 MiB */
> +#define DFU_DATA_BUF_SIZE (64 << 10) /* 64 KiB
> */ +#ifndef CONFIG_SYS_DFU_MAX_FILE_SIZE
> +#define CONFIG_SYS_DFU_MAX_FILE_SIZE (4 << 20) /* 4
> MiB */ +#endif
>
> struct dfu_entity {
> char name[DFU_NAME_SIZE];
> @@ -73,10 +76,27 @@ struct dfu_entity {
> struct mmc_internal_data mmc;
> } data;
>
> - int (*read_medium)(struct dfu_entity *dfu, void *buf, long
> *len);
> - int (*write_medium)(struct dfu_entity *dfu, void *buf, long
> *len);
> + int (*read_medium)(struct dfu_entity *dfu,
> + u64 offset, void *buf, long *len);
> +
> + int (*write_medium)(struct dfu_entity *dfu,
> + u64 offset, void *buf, long *len);
> +
> + int (*flush_medium)(struct dfu_entity *dfu);
>
> struct list_head list;
> +
> + /* on the fly state */
> + u32 crc;
> + u64 offset;
> + int i_blk_seq_num;
> + u8 *i_buf;
> + u8 *i_buf_start;
> + u8 *i_buf_end;
> + long r_left;
> + long b_left;
> +
> + unsigned int inited:1;
> };
>
> int dfu_config_entities(char *s, char *interface, int num);
--
Best regards,
Lukasz Majewski
Samsung R&D Poland (SRPOL) | Linux Platform Group
^ permalink raw reply [flat|nested] 23+ messages in thread
* [U-Boot] [PATCH v5 2/9] dfu: Support larger than memory transfers.
2013-03-11 9:38 ` Lukasz Majewski
@ 2013-03-11 10:03 ` Lukasz Majewski
2013-03-11 12:55 ` Tom Rini
` (2 more replies)
2013-03-11 11:36 ` [U-Boot] Nand flash (supports ONFI) TigerLiu at viatech.com.cn
1 sibling, 3 replies; 23+ messages in thread
From: Lukasz Majewski @ 2013-03-11 10:03 UTC (permalink / raw)
To: u-boot
Hi Tom,
>
> > From: Pantelis Antoniou <panto@antoniou-consulting.com>
> >
> > Previously we didn't support upload/download larger than available
> > memory. This is pretty bad when you have to update your root
> > filesystem for example.
> >
> > This patch removes that limitation (and the crashes when you
> > transfered any file larger than 4MB) by making raw image writes be
> > done in chunks and making file maximum size be configurable.
> >
> > The sequence number is a 16 bit counter; make sure we handle
> > rollover correctly. This fixes the wrong transfers for large (>
> > 256MB) images.
> >
> > Also utilize a variable to handle initialization, so that we don't
> > rely on just the counter sent by the host.
> >
> > Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
> > Signed-off-by: Tom Rini <trini@ti.com>
>
> Acked-by: Lukasz Majewski <l.majewski@samsung.com>
>
> Test-hw: Exynos 4210 (Trats)
>
> Tested-by: Lukasz Majewski <l.majewski@samsung.com>
Sorry but, I've found a regression for reading image from a file
system. It happens with EXT4 mmc read (like uImage).
mmc_file_op: ext4load mmc 0:2 /uImage 0x0 0 0x7f95dc98
** File not found 0x0 **
dfu: Read error!
ext4load params:
ext4load - load binary file from a Ext4 filesystem
Usage:
ext4load <interface> <dev[:part]> [addr] [filename] [bytes]
- load binary file 'filename' from 'dev' on 'interface'
to address 'addr' from ext4 filesystem.
All numeric parameters are assumed to be hex.
Some parameters are wrong (buffer - 0x0) and some are switched (address
and filename).
Please find more details below:
>
> > ---
> > Changes in v5:
> > - Rework Pantelis' "dfu: Support larger than memory transfers" to
> > not break filesystem writing
> >
> > Changes in v4: None
> > Changes in v3: None
> > Changes in v2: None
> >
> > README | 7 ++
> > drivers/dfu/dfu.c | 245
> > ++++++++++++++++++++++++++++++++++++++-----------
> > drivers/dfu/dfu_mmc.c | 116 +++++++++++++++++------
> > include/dfu.h | 26 +++++- 4 files changed, 310
> > insertions(+), 84 deletions(-)
> >
> > +static int dfu_write_buffer_drain(struct dfu_entity *dfu)
> > +{
> > + long w_size;
> > + int ret;
> > +
> > + /* flush size? */
> > + w_size = dfu->i_buf - dfu->i_buf_start;
> > + if (w_size == 0)
> > + return 0;
> > +
> > + /* update CRC32 */
> > + dfu->crc = crc32(dfu->crc, dfu->i_buf_start, w_size);
> > +
> > + ret = dfu->write_medium(dfu, dfu->offset, dfu->i_buf_start,
> > &w_size);
> > + if (ret)
> > + debug("%s: Write error!\n", __func__);
> > +
> > + /* point back */
> > + dfu->i_buf = dfu->i_buf_start;
> > +
> > + /* update offset */
> > + dfu->offset += w_size;
> > +
> > + puts("#");
> > +
> > + return ret;
> > +}
> > +
> > int dfu_write(struct dfu_entity *dfu, void *buf, int size, int
> > blk_seq_num) {
> > - static unsigned char *i_buf;
> > - static int i_blk_seq_num;
> > - long w_size = 0;
> > int ret = 0;
> > + int tret;
> > +
> > + debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x "
> > + "offset: 0x%llx bufoffset: 0x%x\n",
> > + __func__, dfu->name, buf, size, blk_seq_num,
> > dfu->offset,
> > + dfu->i_buf - dfu->i_buf_start);
> > +
> > + if (!dfu->inited) {
> > + /* initial state */
> > + dfu->crc = 0;
> > + dfu->offset = 0;
> > + dfu->i_blk_seq_num = 0;
> > + dfu->i_buf_start = dfu_buf;
> > + dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
> > + dfu->i_buf = dfu->i_buf_start;
> > +
> > + dfu->inited = 1;
> > + }
> >
> > - debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf:
> > 0x%p\n",
> > - __func__, dfu->name, buf, size, blk_seq_num, i_buf);
> > + if (dfu->i_blk_seq_num != blk_seq_num) {
> > + printf("%s: Wrong sequence number! [%d] [%d]\n",
> > + __func__, dfu->i_blk_seq_num, blk_seq_num);
> > + return -1;
> > + }
> >
> > - if (blk_seq_num == 0) {
> > - i_buf = dfu_buf;
> > - i_blk_seq_num = 0;
> > + /* DFU 1.1 standard says:
> > + * The wBlockNum field is a block sequence number. It
> > increments each
> > + * time a block is transferred, wrapping to zero from
> > 65,535. It is used
> > + * to provide useful context to the DFU loader in the
> > device."
> > + *
> > + * This means that it's a 16 bit counter that roll-overs at
> > + * 0xffff -> 0x0000. By having a typical 4K transfer block
> > + * we roll-over at exactly 256MB. Not very fun to debug.
> > + *
> > + * Handling rollover, and having an inited variable,
> > + * makes things work.
> > + */
> > +
> > + /* handle rollover */
> > + dfu->i_blk_seq_num = (dfu->i_blk_seq_num + 1) & 0xffff;
> > +
> > + /* flush buffer if overflow */
> > + if ((dfu->i_buf + size) > dfu->i_buf_end) {
> > + tret = dfu_write_buffer_drain(dfu);
> > + if (ret == 0)
> > + ret = tret;
> > }
> >
> > - if (i_blk_seq_num++ != blk_seq_num) {
> > - printf("%s: Wrong sequence number! [%d] [%d]\n",
> > - __func__, i_blk_seq_num, blk_seq_num);
> > + /* we should be in buffer now (if not then size too large)
> > */
> > + if ((dfu->i_buf + size) > dfu->i_buf_end) {
> > + printf("%s: Wrong size! [%d] [%d] - %d\n",
> > + __func__, dfu->i_blk_seq_num, blk_seq_num,
> > size); return -1;
> > }
> >
> > - memcpy(i_buf, buf, size);
> > - i_buf += size;
> > + memcpy(dfu->i_buf, buf, size);
> > + dfu->i_buf += size;
> >
> > + /* if end or if buffer full flush */
> > + if (size == 0 || (dfu->i_buf + size) > dfu->i_buf_end) {
> > + tret = dfu_write_buffer_drain(dfu);
> > + if (ret == 0)
> > + ret = tret;
> > + }
> > +
> > + /* end? */
> > if (size == 0) {
> > - /* Integrity check (if needed) */
> > - debug("%s: %s %d [B] CRC32: 0x%x\n", __func__,
> > dfu->name,
> > - i_buf - dfu_buf, crc32(0, dfu_buf, i_buf -
> > dfu_buf));
> > + /* Now try and flush to the medium if needed. */
> > + if (dfu->flush_medium)
> > + ret = dfu->flush_medium(dfu);
> > + printf("\nDFU complete CRC32: 0x%08x\n", dfu->crc);
> >
> > - w_size = i_buf - dfu_buf;
> > - ret = dfu->write_medium(dfu, dfu_buf, &w_size);
> > - if (ret)
> > - debug("%s: Write error!\n", __func__);
> > + /* clear everything */
> > + dfu->crc = 0;
> > + dfu->offset = 0;
> > + dfu->i_blk_seq_num = 0;
> > + dfu->i_buf_start = dfu_buf;
> > + dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
> > + dfu->i_buf = dfu->i_buf_start;
> > +
> > + dfu->inited = 0;
> >
> > - i_blk_seq_num = 0;
> > - i_buf = NULL;
> > - return ret;
> > }
> >
> > - return ret;
> > + return ret = 0 ? size : ret;
> > +}
> > +
> > +static int dfu_read_buffer_fill(struct dfu_entity *dfu, void *buf,
> > int size) +{
> > + long chunk;
> > + int ret, readn;
> > +
> > + readn = 0;
> > + while (size > 0) {
> > +
> > + /* get chunk that can be read */
> > + chunk = min(size, dfu->b_left);
> > + /* consume */
> > + if (chunk > 0) {
> > + memcpy(buf, dfu->i_buf, chunk);
> > + dfu->crc = crc32(dfu->crc, buf, chunk);
> > + dfu->i_buf += chunk;
> > + dfu->b_left -= chunk;
> > + size -= chunk;
> > + buf += chunk;
> > + readn += chunk;
> > + }
> > +
> > + /* all done */
> > + if (size > 0) {
> > + /* no more to read */
> > + if (dfu->r_left == 0)
> > + break;
> > +
> > + dfu->i_buf = dfu->i_buf_start;
> > + dfu->b_left = dfu->i_buf_end -
> > dfu->i_buf_start; +
> > + /* got to read, but buffer is empty */
> > + if (dfu->b_left > dfu->r_left)
> > + dfu->b_left = dfu->r_left;
> > + ret = dfu->read_medium(dfu, dfu->offset,
> > dfu->i_buf,
> > + &dfu->b_left);
> > + if (ret != 0) {
> > + debug("%s: Read error!\n",
> > __func__);
> > + return ret;
> > + }
> > + dfu->offset += dfu->b_left;
> > + dfu->r_left -= dfu->b_left;
> > +
> > + puts("#");
> > + }
> > + }
> > +
> > + return readn;
> > }
> >
> > int dfu_read(struct dfu_entity *dfu, void *buf, int size, int
> > blk_seq_num) {
> > - static unsigned char *i_buf;
> > - static int i_blk_seq_num;
> > - static long r_size;
> > - static u32 crc;
> > int ret = 0;
> >
> > debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf:
> > 0x%p\n",
> > - __func__, dfu->name, buf, size, blk_seq_num, i_buf);
> > -
> > - if (blk_seq_num == 0) {
> > - i_buf = dfu_buf;
> > - ret = dfu->read_medium(dfu, i_buf, &r_size);
> > - debug("%s: %s %ld [B]\n", __func__, dfu->name,
> > r_size);
> > - i_blk_seq_num = 0;
> > - /* Integrity check (if needed) */
> > - crc = crc32(0, dfu_buf, r_size);
> > + __func__, dfu->name, buf, size, blk_seq_num,
> > dfu->i_buf); +
> > + if (!dfu->inited) {
> > + ret = dfu->read_medium(dfu, 0, NULL, &dfu->r_left);
^^^^^^^^^^^^ this call causes read error. I
suppose, that it is an initial "read". Does
it read the whole file at once?
The problem is that the command is fromatted in a
wrong way.
On the other hand write operations works on Trats.
--
Best regards,
Lukasz Majewski
Samsung R&D Poland (SRPOL) | Linux Platform Group
^ permalink raw reply [flat|nested] 23+ messages in thread
* [U-Boot] Nand flash (supports ONFI)
2013-03-11 9:38 ` Lukasz Majewski
2013-03-11 10:03 ` Lukasz Majewski
@ 2013-03-11 11:36 ` TigerLiu at viatech.com.cn
2013-03-11 11:56 ` Jagan Teki
1 sibling, 1 reply; 23+ messages in thread
From: TigerLiu at viatech.com.cn @ 2013-03-11 11:36 UTC (permalink / raw)
To: u-boot
Hi, experts:
I want to know which specific nand chip supports ONFI interface spec?
I have googled , but not find any product manual.
Best wishes,
^ permalink raw reply [flat|nested] 23+ messages in thread
* [U-Boot] Nand flash (supports ONFI)
2013-03-11 11:36 ` [U-Boot] Nand flash (supports ONFI) TigerLiu at viatech.com.cn
@ 2013-03-11 11:56 ` Jagan Teki
2013-03-12 2:19 ` TigerLiu at viatech.com.cn
0 siblings, 1 reply; 23+ messages in thread
From: Jagan Teki @ 2013-03-11 11:56 UTC (permalink / raw)
To: u-boot
Hi,
On Mon, Mar 11, 2013 at 5:06 PM, <TigerLiu@viatech.com.cn> wrote:
> Hi, experts:
> I want to know which specific nand chip supports ONFI interface spec?
> I have googled , but not find any product manual.
Spansion ML series and Micron MT29F series flashes have onfi read
parameter page support.
Thanks,
Jagan.
>
> Best wishes,
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
^ permalink raw reply [flat|nested] 23+ messages in thread
* [U-Boot] [PATCH v5 2/9] dfu: Support larger than memory transfers.
2013-03-11 10:03 ` Lukasz Majewski
@ 2013-03-11 12:55 ` Tom Rini
2013-03-13 15:05 ` Tom Rini
2013-03-13 15:25 ` Tom Rini
2 siblings, 0 replies; 23+ messages in thread
From: Tom Rini @ 2013-03-11 12:55 UTC (permalink / raw)
To: u-boot
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 03/11/2013 06:03 AM, Lukasz Majewski wrote:
> Hi Tom,
>
>
>>
>>> From: Pantelis Antoniou <panto@antoniou-consulting.com>
>>>
>>> Previously we didn't support upload/download larger than
>>> available memory. This is pretty bad when you have to update
>>> your root filesystem for example.
>>>
>>> This patch removes that limitation (and the crashes when you
>>> transfered any file larger than 4MB) by making raw image writes
>>> be done in chunks and making file maximum size be
>>> configurable.
>>>
>>> The sequence number is a 16 bit counter; make sure we handle
>>> rollover correctly. This fixes the wrong transfers for large
>>> (> 256MB) images.
>>>
>>> Also utilize a variable to handle initialization, so that we
>>> don't rely on just the counter sent by the host.
>>>
>>> Signed-off-by: Pantelis Antoniou
>>> <panto@antoniou-consulting.com> Signed-off-by: Tom Rini
>>> <trini@ti.com>
>>
>> Acked-by: Lukasz Majewski <l.majewski@samsung.com>
>>
>> Test-hw: Exynos 4210 (Trats)
>>
>> Tested-by: Lukasz Majewski <l.majewski@samsung.com>
>
> Sorry but, I've found a regression for reading image from a file
> system. It happens with EXT4 mmc read (like uImage).
Can you please confirm read works as-is today? It's possible that
when I tried I was using (what I've now called) a marginal SD card
I've finally written too much to the front sectors on, but it wasn't
working for me at all. I'll try and reproduce as well. That said,
there is a problem:
> mmc_file_op: ext4load mmc 0:2 /uImage 0x0 0 0x7f95dc98 ** File not
> found 0x0 ** dfu: Read error!
>
> ext4load params: ext4load - load binary file from a Ext4
> filesystem
>
> Usage: ext4load <interface> <dev[:part]> [addr] [filename] [bytes]
> - load binary file 'filename' from 'dev' on 'interface' to address
> 'addr' from ext4 filesystem. All numeric parameters are assumed to
> be hex.
>
> Some parameters are wrong (buffer - 0x0) and some are switched
> (address and filename).
I just noticed last week that ext4load has the syntax backwards from
fatload for address/filename :( And in this case it's passing in too
many params, so I will fix that.
>>> + __func__, dfu->name, buf, size, blk_seq_num,
>>> dfu->i_buf); + + if (!dfu->inited) { + ret =
>>> dfu->read_medium(dfu, 0, NULL, &dfu->r_left);
> ^^^^^^^^^^^^ this call causes read error. I suppose, that it is an
> initial "read". Does it read the whole file at once?
I'll double check what's going on over here.
- --
Tom
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
iQIcBAEBAgAGBQJRPdQ+AAoJENk4IS6UOR1WYzgP/RwNBOTJ7XPM9mrFFU+3UtyA
Z/tUwuyghitC/rBBPuUyoml6Oq+9oVtCd89uZyjYjFUh68HKGSZ6a+XaLl1KC9Yr
n/3m91CXgnJAdh3TcrGoX6Gg9dVPb0vomLZpyZg/UK71PNnXcFI9BAvkXlfwUi1r
KbPDF10WzNq4qACELdwHKP8gumhBvgB+qyCHjFRalD/jk9HS1Nv7rIpgng2eQpbv
kGyRzZRJNmJ5s0/XSlg6G+XP9seE23oAw1eLZRO3bF33PcynC1L2R96iBLU4dIcQ
BHQp3jC+3m7v543eXqNvBaBJDIuABkqm8Or0xdw18T8d0unci+VxRXNvVlI2VrdL
fhhj47cSEKzAEJ6KTzwwvZl4CUnqfExPds/yTWl5CF+PNukw91b7kZca2uOuEtkM
htbQthvt7jzaD5Ji0U8R3FF3cJ39g1XVOARpY1hzPeHMrX83b5dHFPg0LDEj31qK
FWkNElx4MHgu2Cir8cBWGaFwAHxXqyG9VfPX2LwHD6zCLHmKryq+UlH+KfZgi3UE
u0vDxH24jeGccDc6BIXgJdDvt8AN8SQgXtpV6xrCWEPYR90GBpM8/yOIeTbxzuky
hTi2Ke8VxIGYmVWBDQ/YtKoANL1peiZuFB/DmoMA9d6WbQDkZbmgI0lQ+3x6kZxs
WRBsQxgaW4Yf6nIUv5X3
=t1hs
-----END PGP SIGNATURE-----
^ permalink raw reply [flat|nested] 23+ messages in thread
* [U-Boot] Nand flash (supports ONFI)
2013-03-11 11:56 ` Jagan Teki
@ 2013-03-12 2:19 ` TigerLiu at viatech.com.cn
0 siblings, 0 replies; 23+ messages in thread
From: TigerLiu at viatech.com.cn @ 2013-03-12 2:19 UTC (permalink / raw)
To: u-boot
Hi, Jagan:
Got it!
Thank you!
I have downloaded a MT29F16G08A data sheet.
Best wishes,
-----????-----
???: Jagan Teki [mailto:jagannadh.teki at gmail.com]
????: 2013?3?11? 19:56
???: Tiger Liu
??: u-boot at lists.denx.de
??: Re: [U-Boot] Nand flash (supports ONFI)
Hi,
On Mon, Mar 11, 2013 at 5:06 PM, <TigerLiu@viatech.com.cn> wrote:
> Hi, experts:
> I want to know which specific nand chip supports ONFI interface spec?
> I have googled , but not find any product manual.
Spansion ML series and Micron MT29F series flashes have onfi read
parameter page support.
Thanks,
Jagan.
>
> Best wishes,
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
^ permalink raw reply [flat|nested] 23+ messages in thread
* [U-Boot] [PATCH v5 2/9] dfu: Support larger than memory transfers.
2013-03-11 10:03 ` Lukasz Majewski
2013-03-11 12:55 ` Tom Rini
@ 2013-03-13 15:05 ` Tom Rini
2013-03-13 15:25 ` Tom Rini
2 siblings, 0 replies; 23+ messages in thread
From: Tom Rini @ 2013-03-13 15:05 UTC (permalink / raw)
To: u-boot
On Mon, Mar 11, 2013 at 11:03:41AM +0100, Lukasz Majewski wrote:
> Hi Tom,
>
>
> >
> > > From: Pantelis Antoniou <panto@antoniou-consulting.com>
> > >
> > > Previously we didn't support upload/download larger than available
> > > memory. This is pretty bad when you have to update your root
> > > filesystem for example.
> > >
> > > This patch removes that limitation (and the crashes when you
> > > transfered any file larger than 4MB) by making raw image writes be
> > > done in chunks and making file maximum size be configurable.
> > >
> > > The sequence number is a 16 bit counter; make sure we handle
> > > rollover correctly. This fixes the wrong transfers for large (>
> > > 256MB) images.
> > >
> > > Also utilize a variable to handle initialization, so that we don't
> > > rely on just the counter sent by the host.
> > >
> > > Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
> > > Signed-off-by: Tom Rini <trini@ti.com>
> >
> > Acked-by: Lukasz Majewski <l.majewski@samsung.com>
> >
> > Test-hw: Exynos 4210 (Trats)
> >
> > Tested-by: Lukasz Majewski <l.majewski@samsung.com>
>
> Sorry but, I've found a regression for reading image from a file
> system. It happens with EXT4 mmc read (like uImage).
>
> mmc_file_op: ext4load mmc 0:2 /uImage 0x0 0 0x7f95dc98
> ** File not found 0x0 **
> dfu: Read error!
>
> ext4load params:
> ext4load - load binary file from a Ext4 filesystem
>
> Usage:
> ext4load <interface> <dev[:part]> [addr] [filename] [bytes]
This is a bug, but this is not a regression. As I sent in another
email, the issue is that ext4write takes arguments backwards from
fatwrite/fatload/ext4load so the line here has always been wrong.
--
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20130313/d8ce1aca/attachment.pgp>
^ permalink raw reply [flat|nested] 23+ messages in thread
* [U-Boot] [PATCH v5 2/9] dfu: Support larger than memory transfers.
2013-03-11 10:03 ` Lukasz Majewski
2013-03-11 12:55 ` Tom Rini
2013-03-13 15:05 ` Tom Rini
@ 2013-03-13 15:25 ` Tom Rini
2013-03-13 19:57 ` Tom Rini
2 siblings, 1 reply; 23+ messages in thread
From: Tom Rini @ 2013-03-13 15:25 UTC (permalink / raw)
To: u-boot
On Mon, Mar 11, 2013 at 11:03:41AM +0100, Lukasz Majewski wrote:
[snip]
> > > - if (blk_seq_num == 0) {
> > > - i_buf = dfu_buf;
> > > - ret = dfu->read_medium(dfu, i_buf, &r_size);
> > > - debug("%s: %s %ld [B]\n", __func__, dfu->name,
> > > r_size);
> > > - i_blk_seq_num = 0;
> > > - /* Integrity check (if needed) */
> > > - crc = crc32(0, dfu_buf, r_size);
> > > + __func__, dfu->name, buf, size, blk_seq_num,
> > > dfu->i_buf); +
> > > + if (!dfu->inited) {
> > > + ret = dfu->read_medium(dfu, 0, NULL, &dfu->r_left);
> ^^^^^^^^^^^^ this call causes read error. I
> suppose, that it is an initial "read". Does
> it read the whole file at once?
>
> The problem is that the command is fromatted in a
> wrong way.
And we're also passing NULL as the buffer to read into? That also can't
be good. I'll spend a little time here and see what's going on.
--
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20130313/50cf9255/attachment.pgp>
^ permalink raw reply [flat|nested] 23+ messages in thread
* [U-Boot] [PATCH v5 2/9] dfu: Support larger than memory transfers.
2013-03-13 15:25 ` Tom Rini
@ 2013-03-13 19:57 ` Tom Rini
2013-03-14 8:22 ` Lukasz Majewski
0 siblings, 1 reply; 23+ messages in thread
From: Tom Rini @ 2013-03-13 19:57 UTC (permalink / raw)
To: u-boot
On Wed, Mar 13, 2013 at 11:25:42AM -0400, Tom Rini wrote:
> On Mon, Mar 11, 2013 at 11:03:41AM +0100, Lukasz Majewski wrote:
>
> [snip]
> > > > - if (blk_seq_num == 0) {
> > > > - i_buf = dfu_buf;
> > > > - ret = dfu->read_medium(dfu, i_buf, &r_size);
> > > > - debug("%s: %s %ld [B]\n", __func__, dfu->name,
> > > > r_size);
> > > > - i_blk_seq_num = 0;
> > > > - /* Integrity check (if needed) */
> > > > - crc = crc32(0, dfu_buf, r_size);
> > > > + __func__, dfu->name, buf, size, blk_seq_num,
> > > > dfu->i_buf); +
> > > > + if (!dfu->inited) {
> > > > + ret = dfu->read_medium(dfu, 0, NULL, &dfu->r_left);
> > ^^^^^^^^^^^^ this call causes read error. I
> > suppose, that it is an initial "read". Does
> > it read the whole file at once?
> >
> > The problem is that the command is fromatted in a
> > wrong way.
>
> And we're also passing NULL as the buffer to read into? That also can't
> be good. I'll spend a little time here and see what's going on.
OK, I see and have fixed some minor issues here, but without any of
these patches, I'm not seeing DFU read work at all for raw. I keep
getting "Wrong sequence number!" errors on the U-Boot side. Using
dfu-util 0.5 from Ubuntu 12.04 still. I'm inclined to push back and
say, after fixing a few calls now that I re-read my code, DFU read is
broken and set that aside as another problem to get fixed.
--
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20130313/f9ddaa89/attachment.pgp>
^ permalink raw reply [flat|nested] 23+ messages in thread
* [U-Boot] [PATCH v5 6/9] dfu: NAND specific routines for DFU operation
2013-03-09 1:08 ` Scott Wood
@ 2013-03-13 20:04 ` Tom Rini
0 siblings, 0 replies; 23+ messages in thread
From: Tom Rini @ 2013-03-13 20:04 UTC (permalink / raw)
To: u-boot
On Fri, Mar 08, 2013 at 07:08:27PM -0600, Scott Wood wrote:
> On 03/08/2013 11:37:25 AM, Tom Rini wrote:
> >From: Pantelis Antoniou <panto@antoniou-consulting.com>
> >
> >Support for NAND storage devices to work with the DFU framework.
> >
> >Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
> >Signed-off-by: Tom Rini <trini@ti.com>
> >---
> >Changes in v5:
> >- Document CONFIG_DFU_NAND in README
> >
> >Changes in v4: None
> >Changes in v3:
> >- Rework logic in nand_block_op for nand_(read|write)_skip_bad
> >returning
> > just a size for actual used length.
> >- Remove unused externs from drivers/dfu/dfu_nand.c
> >
> >Changes in v2:
> >- nand_block_op calls nand_(read|write)_skip_bad directly.
> >- Bugfix in dfu_nand to make sure we set dfu->skip_bad to 0 on each
> > iteration.
> >
> > README | 3 +
> > drivers/dfu/Makefile | 1 +
> > drivers/dfu/dfu.c | 8 ++
> > drivers/dfu/dfu_nand.c | 195
> >++++++++++++++++++++++++++++++++++++++++++++++++
> > include/dfu.h | 23 ++++++
> > 5 files changed, 230 insertions(+)
> > create mode 100644 drivers/dfu/dfu_nand.c
> >
> >diff --git a/README b/README
> >index 154b82f..c70251e 100644
> >--- a/README
> >+++ b/README
> >@@ -1338,6 +1338,9 @@ The following options need to be configured:
> > CONFIG_DFU_MMC
> > This enables support for exposing (e)MMC devices via DFU.
> >
> >+ CONFIG_DFU_NAND
> >+ This enables support for exposing NAND devices via DFU.
> >+
> > CONFIG_SYS_DFU_MAX_FILE_SIZE
> > When updating files rather than the raw storage device,
> > we use a static buffer to copy the file into and then write
> >diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
> >index 7b717bc..153095d 100644
> >--- a/drivers/dfu/Makefile
> >+++ b/drivers/dfu/Makefile
> >@@ -27,6 +27,7 @@ LIB = $(obj)libdfu.o
> >
> > COBJS-$(CONFIG_DFU_FUNCTION) += dfu.o
> > COBJS-$(CONFIG_DFU_MMC) += dfu_mmc.o
> >+COBJS-$(CONFIG_DFU_NAND) += dfu_nand.o
> >
> > SRCS := $(COBJS-y:.o=.c)
> > OBJS := $(addprefix $(obj),$(COBJS-y))
> >diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
> >index 2fecf77..84139bd 100644
> >--- a/drivers/dfu/dfu.c
> >+++ b/drivers/dfu/dfu.c
> >@@ -86,6 +86,7 @@ int dfu_write(struct dfu_entity *dfu, void *buf,
> >int size, int blk_seq_num)
> > /* initial state */
> > dfu->crc = 0;
> > dfu->offset = 0;
> >+ dfu->bad_skip = 0;
> > dfu->i_blk_seq_num = 0;
> > dfu->i_buf_start = dfu_buf;
> > dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
> >@@ -235,6 +236,8 @@ int dfu_read(struct dfu_entity *dfu, void
> >*buf, int size, int blk_seq_num)
> > dfu->i_buf = dfu->i_buf_start;
> > dfu->b_left = 0;
> >
> >+ dfu->bad_skip = 0;
> >+
> > dfu->inited = 1;
> > }
> >
> >@@ -264,6 +267,8 @@ int dfu_read(struct dfu_entity *dfu, void
> >*buf, int size, int blk_seq_num)
> > dfu->i_buf = dfu->i_buf_start;
> > dfu->b_left = 0;
> >
> >+ dfu->bad_skip = 0;
> >+
> > dfu->inited = 0;
> > }
> >
> >@@ -286,6 +291,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, s))
> > return -1;
> >+ } else if (strcmp(interface, "nand") == 0) {
> >+ if (dfu_fill_entity_nand(dfu, s))
> >+ return -1;
> > } else {
> > printf("%s: Device %s not (yet) supported!\n",
> > __func__, interface);
> >diff --git a/drivers/dfu/dfu_nand.c b/drivers/dfu/dfu_nand.c
> >new file mode 100644
> >index 0000000..b7f60dd
> >--- /dev/null
> >+++ b/drivers/dfu/dfu_nand.c
> >@@ -0,0 +1,195 @@
> >+/*
> >+ * dfu_nand.c -- DFU for NAND routines.
> >+ *
> >+ * Copyright (C) 2012-2013 Texas Instruments, Inc.
> >+ *
> >+ * Based on dfu_mmc.c which is:
> >+ * Copyright (C) 2012 Samsung Electronics
> >+ * author: Lukasz Majewski <l.majewski@samsung.com>
> >+ *
> >+ * This program is free software; you can redistribute it and/or
> >modify
> >+ * it under the terms of the GNU General Public License as
> >published by
> >+ * the Free Software Foundation; either version 2 of the License, or
> >+ * (at your option) any later version.
> >+ *
> >+ * This program is distributed in the hope that it will be useful,
> >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> >+ * GNU General Public License for more details.
> >+ *
> >+ * You should have received a copy of the GNU General Public License
> >+ * along with this program; if not, write to the Free Software
> >+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
> >02111-1307 USA
> >+ */
> >+
> >+#include <common.h>
> >+#include <malloc.h>
> >+#include <errno.h>
> >+#include <div64.h>
> >+#include <dfu.h>
> >+#include <linux/mtd/mtd.h>
> >+#include <jffs2/load_kernel.h>
> >+#include <nand.h>
> >+
> >+enum dfu_nand_op {
> >+ DFU_OP_READ = 1,
> >+ DFU_OP_WRITE,
> >+};
> >+
> >+static int nand_block_op(enum dfu_nand_op op, struct dfu_entity *dfu,
> >+ u64 offset, void *buf, long *len)
> >+{
> >+ loff_t start;
> >+ size_t count, actual;
> >+ int ret;
> >+ int dev;
> >+ nand_info_t *nand;
> >+
> >+ /* if buf == NULL return total size of the area */
> >+ if (buf == NULL) {
> >+ *len = dfu->data.nand.size;
> >+ return 0;
> >+ }
> >+
> >+ start = dfu->data.nand.start + offset + dfu->bad_skip;
> >+ count = *len;
> >+ if (start + count >
> >+ dfu->data.nand.start + dfu->data.nand.size) {
> >+ printf("%s: block_op out of bounds\n", __func__);
> >+ return -1;
> >+ }
> >+
> >+ dev = nand_curr_device;
> >+ if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
> >+ !nand_info[dev].name) {
> >+ printf("%s: invalid nand device\n", __func__);
> >+ return -1;
> >+ }
> >+
> >+ nand = &nand_info[dev];
> >+
> >+ if (op == DFU_OP_READ)
> >+ ret = nand_read_skip_bad(nand, start, &count, &actual,
> >+ nand->size, buf);
> >+ else
> >+ ret = nand_write_skip_bad(nand, start, &count, &actual,
> >+ nand->size, buf, 0);
>
> Shouldn't "lim" be "dfu->data.nand.start + dfu->data.nand.size - start"?
>
> This should let you get rid of the bounds check above, which doesn't
> factor in bad blocks that have yet to be encountered.
Good point, will re-work.
> >+ if (ret != 0) {
> >+ printf("%s: nand_%s_skip_bad call failed at %llx!\n",
> >+ __func__, op == DFU_OP_READ ? "read" : "write",
> >+ start);
> >+ return ret;
> >+ }
> >+
> >+ /*
> >+ * Find out where we stopped writing data. This can be deeper
> >into
> >+ * the NAND than we expected due to having to skip bad blocks.
> >So
> >+ * we must take this into account for the next write, if any.
> >+ */
> >+ if (actual > count) {
> >+ printf("%s: skipped 0x%x bad bytes at 0x%llx\n", __func__,
> >+ actual - count, start);
> >+ dfu->bad_skip += actual - count;
> >+ }
>
> Hmm, the message suggests the bad blocks are at "start" rather than
> somewhere between "start" and "start + actual".
>
> nand_write_skip_bad() already prints a message when actually
> skipping the block, so you probably don't need any print here.
OK, I'll just drop that. Thanks!
--
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20130313/044180dd/attachment.pgp>
^ permalink raw reply [flat|nested] 23+ messages in thread
* [U-Boot] [PATCH v5 2/9] dfu: Support larger than memory transfers.
2013-03-13 19:57 ` Tom Rini
@ 2013-03-14 8:22 ` Lukasz Majewski
0 siblings, 0 replies; 23+ messages in thread
From: Lukasz Majewski @ 2013-03-14 8:22 UTC (permalink / raw)
To: u-boot
Hi Tom,
> On Wed, Mar 13, 2013 at 11:25:42AM -0400, Tom Rini wrote:
>
> > On Mon, Mar 11, 2013 at 11:03:41AM +0100, Lukasz Majewski wrote:
> >
> > [snip]
> > > > > - if (blk_seq_num == 0) {
> > > > > - i_buf = dfu_buf;
> > > > > - ret = dfu->read_medium(dfu, i_buf, &r_size);
> > > > > - debug("%s: %s %ld [B]\n", __func__,
> > > > > dfu->name, r_size);
> > > > > - i_blk_seq_num = 0;
> > > > > - /* Integrity check (if needed) */
> > > > > - crc = crc32(0, dfu_buf, r_size);
> > > > > + __func__, dfu->name, buf, size, blk_seq_num,
> > > > > dfu->i_buf); +
> > > > > + if (!dfu->inited) {
> > > > > + ret = dfu->read_medium(dfu, 0, NULL,
> > > > > &dfu->r_left);
> > > ^^^^^^^^^^^^ this call causes read
> > > error. I suppose, that it is an initial "read". Does
> > > it read the whole file at once?
> > >
> > > The problem is that the command is fromatted in a
> > > wrong way.
> >
> > And we're also passing NULL as the buffer to read into? That also
> > can't be good. I'll spend a little time here and see what's going
> > on.
>
> OK, I see and have fixed some minor issues here, but without any of
> these patches, I'm not seeing DFU read work at all for raw. I keep
> getting "Wrong sequence number!" errors on the U-Boot side. Using
> dfu-util 0.5 from Ubuntu 12.04 still. I'm inclined to push back and
> say, after fixing a few calls now that I re-read my code, DFU read is
> broken and set that aside as another problem to get fixed.
>
Ok, lets first fix the download (with yours patch series).
The DFU read can be fixed later, for example after Marek sends pull
request for u-boot-usb branch.
Anyway thanks for looking into the problem.
--
Best regards,
Lukasz Majewski
Samsung R&D Poland (SRPOL) | Linux Platform Group
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2013-03-14 8:22 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-08 17:37 [U-Boot] [PATCH v5 0/9] Improve DFU support, enable for am335x_evm Tom Rini
2013-03-08 17:37 ` [U-Boot] [PATCH v5 1/9] README: Document current DFU CONFIG options Tom Rini
2013-03-08 17:37 ` [U-Boot] [PATCH v5 2/9] dfu: Support larger than memory transfers Tom Rini
2013-03-11 9:38 ` Lukasz Majewski
2013-03-11 10:03 ` Lukasz Majewski
2013-03-11 12:55 ` Tom Rini
2013-03-13 15:05 ` Tom Rini
2013-03-13 15:25 ` Tom Rini
2013-03-13 19:57 ` Tom Rini
2013-03-14 8:22 ` Lukasz Majewski
2013-03-11 11:36 ` [U-Boot] Nand flash (supports ONFI) TigerLiu at viatech.com.cn
2013-03-11 11:56 ` Jagan Teki
2013-03-12 2:19 ` TigerLiu at viatech.com.cn
2013-03-08 17:37 ` [U-Boot] [PATCH v5 3/9] dfu: Change indentation of defines in <dfu.h> Tom Rini
2013-03-08 17:37 ` [U-Boot] [PATCH v5 4/9] nand: Extend nand_(read|write)_skip_bad with *actual and limit parameters Tom Rini
2013-03-09 1:00 ` Scott Wood
2013-03-08 17:37 ` [U-Boot] [PATCH v5 5/9] cmd_nand.c: Fix CONFIG_CMD_NAND_YAFFS Tom Rini
2013-03-08 17:37 ` [U-Boot] [PATCH v5 6/9] dfu: NAND specific routines for DFU operation Tom Rini
2013-03-09 1:08 ` Scott Wood
2013-03-13 20:04 ` Tom Rini
2013-03-08 17:37 ` [U-Boot] [PATCH v5 7/9] am335x_evm: Define CONFIG_SYS_CACHELINE_SIZE Tom Rini
2013-03-08 17:37 ` [U-Boot] [PATCH v5 8/9] am335x_evm: Add CONFIG_CMD_MTDPARTS and relevant defaults Tom Rini
2013-03-08 17:37 ` [U-Boot] [PATCH v5 9/9] am335x_evm: Enable DFU for NAND and MMC, provide example alt_infos Tom Rini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox