[U-Boot] [PATCH 9/9] dfu: Support larger than memory transfers.

Pantelis Antoniou panto at antoniou-consulting.com
Fri Jan 4 18:23:03 CET 2013


Hi Kasim,

On Jan 3, 2013, at 10:30 AM, kasim ling wrote:

> Hi, Pantelis,
> A little confusion about FAT fs write supporting,
> 
> 
> On Sat, Dec 1, 2012 at 12:51 AM, Pantelis Antoniou
> <panto at antoniou-consulting.com> wrote:
>> 
>> 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 the limitation (and the crashes when you transfered
>> any file larger than 4MB).
>> On top of that reduces the huge dfu buffer from 4MB to just 64K, which
>> was over the top.
>> 
>> 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 at antoniou-consulting.com>
>> ---
>> drivers/dfu/dfu.c     | 244 +++++++++++++++++++++++++++++++++++++++-----------
>> drivers/dfu/dfu_mmc.c |  82 +++++++++++------
>> include/dfu.h         |  21 ++++-
>> 3 files changed, 264 insertions(+), 83 deletions(-)
> 
>> diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
>> index 083d745..29a2c2e 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 {
>> @@ -30,35 +31,48 @@ enum dfu_mmc_op {
>> };
>> 
>> 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;
>> 
>> -       sprintf(cmd_buf, "mmc %s 0x%x %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)
>> +       /* if buf == NULL return total size of the area */
>> +       if (buf == NULL) {
>>                *len = dfu->data.mmc.lba_blk_size * dfu->data.mmc.lba_size;
>> +               return 0;
>> +       }
>> +
>> +       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 (blk_start + blk_count >
>> +                       dfu->data.mmc.lba_start + dfu->data.mmc.lba_size) {
>> +               debug("%s: block_op out of bounds\n", __func__);
>> +               return -1;
>> +       }
>> +
>> +       sprintf(cmd_buf, "mmc %s %p %x %x",
>> +               op == DFU_OP_READ ? "read" : "write",
>> +                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, buf, len);
>> +       return mmc_block_op(DFU_OP_WRITE, dfu, offset, buf, len);
>> }
>> 
>> -static inline int mmc_block_read(struct dfu_entity *dfu, void *buf, long *len)
>> +static inline int mmc_block_read(struct dfu_entity *dfu,
>> +               u64 offset, void *buf, long *len)
>> {
>> -       return mmc_block_op(DFU_OP_READ, dfu, buf, len);
>> +       return mmc_block_op(DFU_OP_READ, dfu, offset, buf, len);
>> }
>> 
>> 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;
>> @@ -66,12 +80,17 @@ static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
>> 
>>        switch (dfu->layout) {
>>        case DFU_FS_FAT:
>> -               sprintf(cmd_buf, "fat%s mmc %d:%d 0x%x %s %lx",
>> +               sprintf(cmd_buf, "fat%s mmc %d:%d 0x%x %s %lx %llx",
>>                        op == DFU_OP_READ ? "load" : "write",
>>                        dfu->data.mmc.dev, dfu->data.mmc.part,
>> -                       (unsigned int) buf, dfu->name, *len);
>> +                       (unsigned int) buf, dfu->name, *len, offset);
> Did you tested it on FAT partitions? According to do_fat_fswrite()
> defined in common/cmd_fat.c, the "fatwrite" command does not support
> "offset" argument.
> 

No I haven't had a use case either for fat or ext2/3/4.

So I guess it is as broken as it was before.
If you want to write to a file, make sure it's smaller than the
DFU buffer.

One of these days the file access functions must be fixed.
> 
> Thanks,
> Alex

Regards

-- Pantelis



More information about the U-Boot mailing list