From: Lukasz Majewski <l.majewski@samsung.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v5 2/9] dfu: Support larger than memory transfers.
Date: Mon, 11 Mar 2013 11:03:41 +0100 [thread overview]
Message-ID: <20130311110341.1ef4cc86@amdc308.digital.local> (raw)
In-Reply-To: <20130311103812.78399a48@amdc308.digital.local>
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
next prev parent reply other threads:[~2013-03-11 10:03 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130311110341.1ef4cc86@amdc308.digital.local \
--to=l.majewski@samsung.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.