[U-Boot] [PATCH v4 1/1] fs: fat/ext4/sandbox: Deal with files greater than 2GB

Suriyan Ramasami suriyan.r at gmail.com
Tue Oct 28 15:26:32 CET 2014


Hello Simon,

On Mon, Oct 27, 2014 at 4:55 PM, Simon Glass <sjg at chromium.org> wrote:
> Hi Suriyan,
>
> On 27 October 2014 13:48, Suriyan Ramasami <suriyan.r at gmail.com> wrote:
>> The commands fatls/ext4ls give negative values when dealing with files
>> greater than 2GB.
>> The commands fatsize/ext4size do not update the variable filesize for
>> these files.
>>
>> To deal with this, the fs functions have been modified to take an additional
>> parameter of type "* loff_t" which is then populated. The return value of the
>> fs functions are used only for error contitions.
>
> This is important work and it's great to see this happening. I have a
> few minor comments below and I'd like some help in getting this
> running myself. The basic approach looks sound to me.
>

Thanks for the encouraging comments. Much appreciated!

>>
>> Signed-off-by: Suriyan Ramasami <suriyan.r at gmail.com>
>>
>> ---
>> v4:
>> * Support generic fs write commands
>> * Sync up behavior of fs load vs fatload and ext4load
>> * albert - change -ve to negative in commit message
>>
>> v3:
>> * Added testcase to test writes
>> * Correct function set_contents() in fs/fat/fat_write.c
>>
>> v2:
>> * Added test case for fat/ext4 in test/fs/testfs.sh
>> * md5sum: call map_sysmem() for buffer that md5_wd will work on
>>
>> v1:
>> * First try.
>> ---
>>  arch/sandbox/cpu/os.c     |  11 +-
>>  arch/sandbox/cpu/state.c  |   6 +-
>>  common/board_f.c          |   6 +-
>>  common/cmd_ext4.c         |  61 ++-------
>>  common/cmd_fat.c          |   9 +-
>>  common/cmd_fs.c           |  17 +++
>>  common/cmd_md5sum.c       |  12 +-
>>  common/env_fat.c          |   4 +-
>>  fs/ext4/ext4_common.c     |  24 ++--
>>  fs/ext4/ext4_common.h     |   4 +-
>>  fs/ext4/ext4_write.c      |  32 +++++
>>  fs/ext4/ext4fs.c          |  37 ++---
>>  fs/fat/fat.c              | 124 +++++++++--------
>>  fs/fat/fat_write.c        |  59 ++++----
>>  fs/fat/file.c             |   7 +-
>>  fs/fs.c                   |  77 ++++++-----
>>  fs/sandbox/sandboxfs.c    |  25 ++--
>>  include/configs/sandbox.h |   2 +
>>  include/ext4fs.h          |  13 +-
>>  include/fat.h             |  19 +--
>>  include/fs.h              |   8 +-
>>  include/os.h              |   2 +-
>>  include/sandboxfs.h       |   8 +-
>>  test/fs/testfs.sh         | 334 ++++++++++++++++++++++++++++++++++++++++++++++
>>  24 files changed, 655 insertions(+), 246 deletions(-)
>>  create mode 100755 test/fs/testfs.sh
>>
>> diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
>> index 1c4aa3f..43872e8 100644
>> --- a/arch/sandbox/cpu/os.c
>> +++ b/arch/sandbox/cpu/os.c
>> @@ -385,7 +385,7 @@ const char *os_dirent_get_typename(enum os_dirent_t type)
>>         return os_dirent_typename[OS_FILET_UNKNOWN];
>>  }
>>
>> -ssize_t os_get_filesize(const char *fname)
>> +int os_get_filesize(const char *fname, loff_t *size)
>>  {
>>         struct stat buf;
>>         int ret;
>> @@ -393,7 +393,8 @@ ssize_t os_get_filesize(const char *fname)
>>         ret = stat(fname, &buf);
>>         if (ret)
>>                 return ret;
>> -       return buf.st_size;
>> +       *size = buf.st_size;
>> +       return 0;
>>  }
>>
>>  void os_putc(int ch)
>> @@ -427,10 +428,10 @@ int os_read_ram_buf(const char *fname)
>>  {
>>         struct sandbox_state *state = state_get_current();
>>         int fd, ret;
>> -       int size;
>> +       loff_t size;
>>
>> -       size = os_get_filesize(fname);
>> -       if (size < 0)
>> +       ret = os_get_filesize(fname, &size);
>> +       if (ret < 0)
>>                 return -ENOENT;
>>         if (size != state->ram_size)
>>                 return -ENOSPC;
>> diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c
>> index 59adad6..07d2aea 100644
>> --- a/arch/sandbox/cpu/state.c
>> +++ b/arch/sandbox/cpu/state.c
>> @@ -49,12 +49,12 @@ static int state_ensure_space(int extra_size)
>>
>>  static int state_read_file(struct sandbox_state *state, const char *fname)
>>  {
>> -       int size;
>> +       loff_t size;
>>         int ret;
>>         int fd;
>>
>> -       size = os_get_filesize(fname);
>> -       if (size < 0) {
>> +       ret = os_get_filesize(fname, &size);
>> +       if (ret < 0) {
>>                 printf("Cannot find sandbox state file '%s'\n", fname);
>>                 return -ENOENT;
>>         }
>> diff --git a/common/board_f.c b/common/board_f.c
>> index b5bebc9..1fae112 100644
>> --- a/common/board_f.c
>> +++ b/common/board_f.c
>> @@ -285,7 +285,7 @@ static int read_fdt_from_file(void)
>>         struct sandbox_state *state = state_get_current();
>>         const char *fname = state->fdt_fname;
>>         void *blob;
>> -       ssize_t size;
>> +       loff_t size;
>>         int err;
>>         int fd;
>>
>> @@ -298,8 +298,8 @@ static int read_fdt_from_file(void)
>>                 return -EINVAL;
>>         }
>>
>> -       size = os_get_filesize(fname);
>> -       if (size < 0) {
>> +       err = os_get_filesize(fname, &size);
>> +       if (err < 0) {
>>                 printf("Failed to file FDT file '%s'\n", fname);
>>                 return -ENOENT;
>>         }
>> diff --git a/common/cmd_ext4.c b/common/cmd_ext4.c
>> index ecfc6d3..19423d1 100644
>> --- a/common/cmd_ext4.c
>> +++ b/common/cmd_ext4.c
>> @@ -61,61 +61,16 @@ int do_ext4_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
>>
>>  #if defined(CONFIG_CMD_EXT4_WRITE)
>>  int do_ext4_write(cmd_tbl_t *cmdtp, int flag, int argc,
>> -                               char *const argv[])
>> +                 char *const argv[])
>>  {
>> -       const char *filename = "/";
>> -       int dev, part;
>> -       unsigned long ram_address;
>> -       unsigned long file_size;
>> -       disk_partition_t info;
>> -       block_dev_desc_t *dev_desc;
>> -
>> -       if (argc < 6)
>> -               return cmd_usage(cmdtp);
>> -
>> -       part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1);
>> -       if (part < 0)
>> -               return 1;
>> -
>> -       dev = dev_desc->dev;
>> -
>> -       /* get the filename */
>> -       filename = argv[4];
>> -
>> -       /* get the address in hexadecimal format (string to int) */
>> -       ram_address = simple_strtoul(argv[3], NULL, 16);
>> -
>> -       /* get the filesize in hexadecimal format */
>> -       file_size = simple_strtoul(argv[5], NULL, 16);
>> -
>> -       /* set the device as block device */
>> -       ext4fs_set_blk_dev(dev_desc, &info);
>> -
>> -       /* mount the filesystem */
>> -       if (!ext4fs_mount(info.size)) {
>> -               printf("Bad ext4 partition %s %d:%d\n", argv[1], dev, part);
>> -               goto fail;
>> -       }
>> -
>> -       /* start write */
>> -       if (ext4fs_write(filename, (unsigned char *)ram_address, file_size)) {
>> -               printf("** Error ext4fs_write() **\n");
>> -               goto fail;
>> -       }
>> -       ext4fs_close();
>> -
>> -       return 0;
>> -
>> -fail:
>> -       ext4fs_close();
>> -
>> -       return 1;
>> +       return do_save(cmdtp, flag, argc, argv, FS_TYPE_EXT);
>>  }
>>
>> -U_BOOT_CMD(ext4write, 6, 1, do_ext4_write,
>> -       "create a file in the root directory",
>> -       "<interface> <dev[:part]> <addr> <absolute filename path> [sizebytes]\n"
>> -       "    - create a file in / directory");
>> +U_BOOT_CMD(ext4write, 7, 1, do_ext4_write,
>> +          "create a file in the root directory",
>> +          "<interface> <dev[:part]> <addr> <absolute filename path>\n"
>> +          "    [sizebytes] [file offset]\n"
>> +          "    - create a file in / directory");
>>
>>  #endif
>>
>> @@ -132,7 +87,7 @@ U_BOOT_CMD(ext4ls, 4, 1, do_ext4_ls,
>>            "<interface> <dev[:part]> [directory]\n"
>>            "    - list files from 'dev' on 'interface' in a 'directory'");
>>
>> -U_BOOT_CMD(ext4load, 6, 0, do_ext4_load,
>> +U_BOOT_CMD(ext4load, 7, 0, do_ext4_load,
>>            "load binary file from a Ext4 filesystem",
>>            "<interface> [<dev[:part]> [addr [filename [bytes [pos]]]]]\n"
>>            "    - load binary file 'filename' from 'dev' on 'interface'\n"
>> diff --git a/common/cmd_fat.c b/common/cmd_fat.c
>> index 633fbf1..186835a 100644
>> --- a/common/cmd_fat.c
>> +++ b/common/cmd_fat.c
>> @@ -100,7 +100,8 @@ U_BOOT_CMD(
>>  static int do_fat_fswrite(cmd_tbl_t *cmdtp, int flag,
>>                 int argc, char * const argv[])
>>  {
>> -       long size;
>> +       loff_t size;
>> +       int ret;
>>         unsigned long addr;
>>         unsigned long count;
>>         block_dev_desc_t *dev_desc = NULL;
>> @@ -127,15 +128,15 @@ static int do_fat_fswrite(cmd_tbl_t *cmdtp, int flag,
>>         count = simple_strtoul(argv[5], NULL, 16);
>>
>>         buf = map_sysmem(addr, count);
>> -       size = file_fat_write(argv[4], buf, count);
>> +       ret = file_fat_write(argv[4], buf, 0, count, &size);
>>         unmap_sysmem(buf);
>> -       if (size == -1) {
>> +       if (ret == -1) {
>>                 printf("\n** Unable to write \"%s\" from %s %d:%d **\n",
>>                         argv[4], argv[1], dev, part);
>>                 return 1;
>>         }
>>
>> -       printf("%ld bytes written\n", size);
>> +       printf("%llu bytes written\n", size);
>>
>>         return 0;
>>  }
>> diff --git a/common/cmd_fs.c b/common/cmd_fs.c
>> index 6754340..56e4b3c 100644
>> --- a/common/cmd_fs.c
>> +++ b/common/cmd_fs.c
>> @@ -51,6 +51,23 @@ U_BOOT_CMD(
>>         "      If 'pos' is 0 or omitted, the file is read from the start."
>>  )
>>
>> +static int do_save_wrapper(cmd_tbl_t *cmdtp, int flag, int argc,
>> +                               char * const argv[])
>> +{
>> +       return do_save(cmdtp, flag, argc, argv, FS_TYPE_ANY);
>> +}
>> +
>> +U_BOOT_CMD(
>> +       write,  7,      0,      do_save_wrapper,
>> +       "write file to a filesystem",
>> +       "<interface> [<dev[:part]> [<addr> [<filename> [bytes [pos]]]]]\n"
>> +       "    - Write binary file 'filename' to partition 'part' on device\n"
>> +       "       type 'interface' instance 'dev' from addr 'addr' in memory.\n"
>> +       "      'bytes' gives the size to save in bytes and is mandatory.\n"
>> +       "      'pos' gives the file byte position to start writing to.\n"
>> +       "      If 'pos' is 0 or omitted, the file is written from the start."
>> +)
>> +
>>  static int do_ls_wrapper(cmd_tbl_t *cmdtp, int flag, int argc,
>>                                 char * const argv[])
>>  {
>> diff --git a/common/cmd_md5sum.c b/common/cmd_md5sum.c
>> index 3ac8cc4..d22ace5 100644
>> --- a/common/cmd_md5sum.c
>> +++ b/common/cmd_md5sum.c
>> @@ -11,6 +11,7 @@
>>  #include <common.h>
>>  #include <command.h>
>>  #include <u-boot/md5.h>
>> +#include <asm/io.h>
>>
>>  /*
>>   * Store the resulting sum to an address or variable
>> @@ -79,6 +80,7 @@ int do_md5sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
>>         int verify = 0;
>>         int ac;
>>         char * const *av;
>> +       void *buf;
>>
>>         if (argc < 3)
>>                 return CMD_RET_USAGE;
>> @@ -96,7 +98,9 @@ int do_md5sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
>>         addr = simple_strtoul(*av++, NULL, 16);
>>         len = simple_strtoul(*av++, NULL, 16);
>>
>> -       md5_wd((unsigned char *) addr, len, output, CHUNKSZ_MD5);
>> +       buf = map_sysmem(addr, len);
>> +       md5_wd(buf, len, output, CHUNKSZ_MD5);
>> +       unmap_sysmem(buf);
>>
>>         if (!verify) {
>>                 printf("md5 for %08lx ... %08lx ==> ", addr, addr + len - 1);
>> @@ -135,6 +139,7 @@ static int do_md5sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
>>         unsigned long addr, len;
>>         unsigned int i;
>>         u8 output[16];
>> +       void *buf;
>>
>>         if (argc < 3)
>>                 return CMD_RET_USAGE;
>> @@ -142,7 +147,10 @@ static int do_md5sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
>>         addr = simple_strtoul(argv[1], NULL, 16);
>>         len = simple_strtoul(argv[2], NULL, 16);
>>
>> -       md5_wd((unsigned char *) addr, len, output, CHUNKSZ_MD5);
>> +       buf = map_sysmem(addr, len);
>> +       md5_wd(buf, len, output, CHUNKSZ_MD5);
>> +       unmap_sysmem(buf);
>> +
>>         printf("md5 for %08lx ... %08lx ==> ", addr, addr + len - 1);
>>         for (i = 0; i < 16; i++)
>>                 printf("%02x", output[i]);
>> diff --git a/common/env_fat.c b/common/env_fat.c
>> index 8db0160..9a6ce63 100644
>> --- a/common/env_fat.c
>> +++ b/common/env_fat.c
>> @@ -41,6 +41,7 @@ int saveenv(void)
>>         disk_partition_t info;
>>         int dev, part;
>>         int err;
>> +       loff_t size;
>>
>>         err = env_export(&env_new);
>>         if (err)
>> @@ -59,7 +60,8 @@ int saveenv(void)
>>                 return 1;
>>         }
>>
>> -       err = file_fat_write(FAT_ENV_FILE, (void *)&env_new, sizeof(env_t));
>> +       err = file_fat_write(FAT_ENV_FILE, (void *)&env_new, sizeof(env_t),
>> +                            &size);
>>         if (err == -1) {
>>                 printf("\n** Unable to write \"%s\" from %s%d:%d **\n",
>>                         FAT_ENV_FILE, FAT_ENV_INTERFACE, dev, part);
>> diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
>> index 33d69c9..3b8df3f 100644
>> --- a/fs/ext4/ext4_common.c
>> +++ b/fs/ext4/ext4_common.c
>> @@ -1891,6 +1891,7 @@ int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name,
>>  {
>>         unsigned int fpos = 0;
>>         int status;
>> +       loff_t actread;
>>         struct ext2fs_node *diro = (struct ext2fs_node *) dir;
>>
>>  #ifdef DEBUG
>> @@ -1908,8 +1909,8 @@ int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name,
>>
>>                 status = ext4fs_read_file(diro, fpos,
>>                                            sizeof(struct ext2_dirent),
>> -                                          (char *) &dirent);
>> -               if (status < 1)
>> +                                          (char *)&dirent, &actread);
>> +               if (status < 0)
>>                         return 0;
>>
>>                 if (dirent.namelen != 0) {
>> @@ -1920,8 +1921,9 @@ int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name,
>>                         status = ext4fs_read_file(diro,
>>                                                   fpos +
>>                                                   sizeof(struct ext2_dirent),
>> -                                                 dirent.namelen, filename);
>> -                       if (status < 1)
>> +                                                 dirent.namelen, filename,
>> +                                                 &actread);
>> +                       if (status < 0)
>>                                 return 0;
>>
>>                         fdiro = zalloc(sizeof(struct ext2fs_node));
>> @@ -2003,8 +2005,8 @@ int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name,
>>                                         printf("< ? > ");
>>                                         break;
>>                                 }
>> -                               printf("%10d %s\n",
>> -                                       __le32_to_cpu(fdiro->inode.size),
>> +                               printf("%10u %s\n",
>> +                                      __le32_to_cpu(fdiro->inode.size),
>>                                         filename);
>>                         }
>>                         free(fdiro);
>> @@ -2019,6 +2021,7 @@ static char *ext4fs_read_symlink(struct ext2fs_node *node)
>>         char *symlink;
>>         struct ext2fs_node *diro = node;
>>         int status;
>> +       loff_t actread;
>>
>>         if (!diro->inode_read) {
>>                 status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode);
>> @@ -2035,7 +2038,7 @@ static char *ext4fs_read_symlink(struct ext2fs_node *node)
>>         } else {
>>                 status = ext4fs_read_file(diro, 0,
>>                                            __le32_to_cpu(diro->inode.size),
>> -                                          symlink);
>> +                                          symlink, &actread);
>>                 if (status == 0) {
>>                         free(symlink);
>>                         return 0;
>> @@ -2169,11 +2172,10 @@ int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode,
>>         return 1;
>>  }
>>
>> -int ext4fs_open(const char *filename)
>> +int ext4fs_open(const char *filename, loff_t *len)
>>  {
>>         struct ext2fs_node *fdiro = NULL;
>>         int status;
>> -       int len;
>>
>>         if (ext4fs_root == NULL)
>>                 return -1;
>> @@ -2190,10 +2192,10 @@ int ext4fs_open(const char *filename)
>>                 if (status == 0)
>>                         goto fail;
>>         }
>> -       len = __le32_to_cpu(fdiro->inode.size);
>> +       *len = __le32_to_cpu(fdiro->inode.size);
>>         ext4fs_file = fdiro;
>>
>> -       return len;
>> +       return 0;
>>  fail:
>>         ext4fs_free_node(fdiro, &ext4fs_root->diropen);
>>
>> diff --git a/fs/ext4/ext4_common.h b/fs/ext4/ext4_common.h
>> index 5fa1719..48fd2ac 100644
>> --- a/fs/ext4/ext4_common.h
>> +++ b/fs/ext4/ext4_common.h
>> @@ -50,8 +50,8 @@ static inline void *zalloc(size_t size)
>>
>>  int ext4fs_read_inode(struct ext2_data *data, int ino,
>>                       struct ext2_inode *inode);
>> -int ext4fs_read_file(struct ext2fs_node *node, int pos,
>> -               unsigned int len, char *buf);
>> +int ext4fs_read_file(struct ext2fs_node *node, loff_t pos, loff_t len,
>> +                    char *buf, loff_t *actread);
>>  int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode,
>>                         struct ext2fs_node **foundnode, int expecttype);
>>  int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name,
>> diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c
>> index 648a596..f7c52cc 100644
>> --- a/fs/ext4/ext4_write.c
>> +++ b/fs/ext4/ext4_write.c
>> @@ -975,3 +975,35 @@ fail:
>>
>>         return -1;
>>  }
>> +
>> +int ext4_write_file(const char *filename, void *buf, loff_t offset,
>> +                   loff_t len, loff_t *actwrite)
>> +{
>> +       int ret;
>> +
>> +       if (offset != 0) {
>> +               printf("** Cannot support non-zero offset **\n");
>> +               return -1;
>> +       }
>> +
>> +       /* mount the filesystem */
>> +       if (!ext4fs_mount(0)) {
>> +               printf("** Error Bad ext4 partition **\n");
>> +               goto fail;
>> +       }
>> +
>> +       ret = ext4fs_write(filename, buf, len);
>> +
>> +       if (ret) {
>> +               printf("** Error ext4fs_write() **\n");
>> +               goto fail;
>> +       }
>> +       ext4fs_close();
>> +
>> +       return 0;
>> +
>> +fail:
>> +       ext4fs_close();
>> +
>> +       return -1;
>> +}
>> diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c
>> index cbdc220..ae1c47d 100644
>> --- a/fs/ext4/ext4fs.c
>> +++ b/fs/ext4/ext4fs.c
>> @@ -45,8 +45,8 @@ void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot)
>>   * Optimized read file API : collects and defers contiguous sector
>>   * reads into one potentially more efficient larger sequential read action
>>   */
>> -int ext4fs_read_file(struct ext2fs_node *node, int pos,
>> -               unsigned int len, char *buf)
>> +int ext4fs_read_file(struct ext2fs_node *node, loff_t pos,
>> +               loff_t len, char *buf, loff_t *actread)
>>  {
>>         struct ext_filesystem *fs = get_fs();
>>         int i;
>> @@ -150,7 +150,8 @@ int ext4fs_read_file(struct ext2fs_node *node, int pos,
>>                 previous_block_number = -1;
>>         }
>>
>> -       return len;
>> +       *actread  = len;
>> +       return 0;
>>  }
>>
>>  int ext4fs_ls(const char *dirname)
>> @@ -176,23 +177,24 @@ int ext4fs_ls(const char *dirname)
>>
>>  int ext4fs_exists(const char *filename)
>>  {
>> -       int file_len;
>> +       loff_t file_len;
>> +       int ret;
>>
>> -       file_len = ext4fs_open(filename);
>> -       return file_len >= 0;
>> +       ret = ext4fs_open(filename, &file_len);
>> +       return ret == 0;
>>  }
>>
>> -int ext4fs_size(const char *filename)
>> +int ext4fs_size(const char *filename, loff_t *size)
>>  {
>> -       return ext4fs_open(filename);
>> +       return ext4fs_open(filename, size);
>>  }
>>
>> -int ext4fs_read(char *buf, unsigned len)
>> +int ext4fs_read(char *buf, loff_t len, loff_t *actread)
>>  {
>>         if (ext4fs_root == NULL || ext4fs_file == NULL)
>>                 return 0;
>>
>> -       return ext4fs_read_file(ext4fs_file, 0, len, buf);
>> +       return ext4fs_read_file(ext4fs_file, 0, len, buf, actread);
>>  }
>>
>>  int ext4fs_probe(block_dev_desc_t *fs_dev_desc,
>> @@ -208,18 +210,19 @@ int ext4fs_probe(block_dev_desc_t *fs_dev_desc,
>>         return 0;
>>  }
>>
>> -int ext4_read_file(const char *filename, void *buf, int offset, int len)
>> +int ext4_read_file(const char *filename, void *buf, loff_t offset, loff_t len,
>> +                  loff_t *len_read)
>>  {
>> -       int file_len;
>> -       int len_read;
>> +       loff_t file_len;
>> +       int ret;
>>
>>         if (offset != 0) {
>>                 printf("** Cannot support non-zero offset **\n");
>>                 return -1;
>>         }
>>
>> -       file_len = ext4fs_open(filename);
>> -       if (file_len < 0) {
>> +       ret = ext4fs_open(filename, &file_len);
>> +       if (ret < 0) {
>>                 printf("** File not found %s **\n", filename);
>>                 return -1;
>>         }
>> @@ -227,7 +230,7 @@ int ext4_read_file(const char *filename, void *buf, int offset, int len)
>>         if (len == 0)
>>                 len = file_len;
>>
>> -       len_read = ext4fs_read(buf, len);
>> +       ret = ext4fs_read(buf, len, len_read);
>>
>> -       return len_read;
>> +       return ret;
>>  }
>> diff --git a/fs/fat/fat.c b/fs/fat/fat.c
>> index 561921f..df8705f 100644
>> --- a/fs/fat/fat.c
>> +++ b/fs/fat/fat.c
>> @@ -317,32 +317,33 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size)
>>  /*
>>   * Read at most 'maxsize' bytes from 'pos' in the file associated with 'dentptr'
>>   * into 'buffer'.
>> - * Return the number of bytes read or -1 on fatal errors.
>> + * Update the number of bytes read in *gotsize or return -1 on fatal errors.
>>   */
>>  __u8 get_contents_vfatname_block[MAX_CLUSTSIZE]
>>         __aligned(ARCH_DMA_MINALIGN);
>>
>> -static long
>> -get_contents(fsdata *mydata, dir_entry *dentptr, unsigned long pos,
>> -            __u8 *buffer, unsigned long maxsize)
>> +static int
>> +get_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos,
>> +            __u8 *buffer, loff_t maxsize, loff_t *gotsize)
>>  {
>> -       unsigned long filesize = FAT2CPU32(dentptr->size), gotsize = 0;
>> +       loff_t filesize = FAT2CPU32(dentptr->size);
>>         unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
>>         __u32 curclust = START(dentptr);
>>         __u32 endclust, newclust;
>> -       unsigned long actsize;
>> +       loff_t actsize;
>>
>> -       debug("Filesize: %ld bytes\n", filesize);
>> +       *gotsize = 0;
>> +       debug("Filesize: %llu bytes\n", filesize);
>>
>>         if (pos >= filesize) {
>> -               debug("Read position past EOF: %lu\n", pos);
>> -               return gotsize;
>> +               debug("Read position past EOF: %llu\n", pos);
>> +               return 0;
>>         }
>>
>>         if (maxsize > 0 && filesize > pos + maxsize)
>>                 filesize = pos + maxsize;
>>
>> -       debug("%ld bytes\n", filesize);
>> +       debug("%llu bytes\n", filesize);
>>
>>         actsize = bytesperclust;
>>
>> @@ -352,7 +353,7 @@ get_contents(fsdata *mydata, dir_entry *dentptr, unsigned long pos,
>>                 if (CHECK_CLUST(curclust, mydata->fatsize)) {
>>                         debug("curclust: 0x%x\n", curclust);
>>                         debug("Invalid FAT entry\n");
>> -                       return gotsize;
>> +                       return 0;
>>                 }
>>                 actsize += bytesperclust;
>>         }
>> @@ -373,16 +374,16 @@ get_contents(fsdata *mydata, dir_entry *dentptr, unsigned long pos,
>>                 filesize -= actsize;
>>                 actsize -= pos;
>>                 memcpy(buffer, get_contents_vfatname_block + pos, actsize);
>> -               gotsize += actsize;
>> +               *gotsize += actsize;
>>                 if (!filesize)
>> -                       return gotsize;
>> +                       return 0;
>>                 buffer += actsize;
>>
>>                 curclust = get_fatent(mydata, curclust);
>>                 if (CHECK_CLUST(curclust, mydata->fatsize)) {
>>                         debug("curclust: 0x%x\n", curclust);
>>                         debug("Invalid FAT entry\n");
>> -                       return gotsize;
>> +                       return 0;
>>                 }
>>         }
>>
>> @@ -398,7 +399,7 @@ get_contents(fsdata *mydata, dir_entry *dentptr, unsigned long pos,
>>                         if (CHECK_CLUST(newclust, mydata->fatsize)) {
>>                                 debug("curclust: 0x%x\n", newclust);
>>                                 debug("Invalid FAT entry\n");
>> -                               return gotsize;
>> +                               return 0;
>>                         }
>>                         endclust = newclust;
>>                         actsize += bytesperclust;
>> @@ -410,14 +411,14 @@ get_contents(fsdata *mydata, dir_entry *dentptr, unsigned long pos,
>>                         printf("Error reading cluster\n");
>>                         return -1;
>>                 }
>> -               gotsize += actsize;
>> -               return gotsize;
>> +               *gotsize += actsize;
>> +               return 0;
>>  getit:
>>                 if (get_cluster(mydata, curclust, buffer, (int)actsize) != 0) {
>>                         printf("Error reading cluster\n");
>>                         return -1;
>>                 }
>> -               gotsize += (int)actsize;
>> +               *gotsize += (int)actsize;
>>                 filesize -= actsize;
>>                 buffer += actsize;
>>
>> @@ -425,7 +426,7 @@ getit:
>>                 if (CHECK_CLUST(curclust, mydata->fatsize)) {
>>                         debug("curclust: 0x%x\n", curclust);
>>                         printf("Invalid FAT entry\n");
>> -                       return gotsize;
>> +                       return 0;
>>                 }
>>                 actsize = bytesperclust;
>>                 endclust = curclust;
>> @@ -633,8 +634,8 @@ static dir_entry *get_dentfromdir(fsdata *mydata, int startsect,
>>                                                 }
>>                                                 if (doit) {
>>                                                         if (dirc == ' ') {
>> -                                                               printf(" %8ld   %s%c\n",
>> -                                                                       (long)FAT2CPU32(dentptr->size),
>> +                                                               printf(" %8u   %s%c\n",
>> +                                                                      FAT2CPU32(dentptr->size),
>>                                                                         l_name,
>>                                                                         dirc);
>>                                                         } else {
>> @@ -690,8 +691,8 @@ static dir_entry *get_dentfromdir(fsdata *mydata, int startsect,
>>
>>                                 if (doit) {
>>                                         if (dirc == ' ') {
>> -                                               printf(" %8ld   %s%c\n",
>> -                                                       (long)FAT2CPU32(dentptr->size),
>> +                                               printf(" %8u   %s%c\n",
>> +                                                      FAT2CPU32(dentptr->size),
>>                                                         s_name, dirc);
>>                                         } else {
>>                                                 printf("            %s%c\n",
>> @@ -806,9 +807,9 @@ exit:
>>  __u8 do_fat_read_at_block[MAX_CLUSTSIZE]
>>         __aligned(ARCH_DMA_MINALIGN);
>>
>> -long
>> -do_fat_read_at(const char *filename, unsigned long pos, void *buffer,
>> -              unsigned long maxsize, int dols, int dogetsize)
>> +int
>> +do_fat_read_at(const char *filename, loff_t pos, void *buffer, loff_t maxsize,
>> +              int dols, int dogetsize, loff_t *size)
>>  {
>>         char fnamecopy[2048];
>>         boot_sector bs;
>> @@ -821,7 +822,7 @@ do_fat_read_at(const char *filename, unsigned long pos, void *buffer,
>>         __u32 cursect;
>>         int idx, isdir = 0;
>>         int files = 0, dirs = 0;
>> -       long ret = -1;
>> +       int ret = -1;
>>         int firsttime;
>>         __u32 root_cluster = 0;
>>         int rootdir_size = 0;
>> @@ -974,8 +975,8 @@ do_fat_read_at(const char *filename, unsigned long pos, void *buffer,
>>                                                 }
>>                                                 if (doit) {
>>                                                         if (dirc == ' ') {
>> -                                                               printf(" %8ld   %s%c\n",
>> -                                                                       (long)FAT2CPU32(dentptr->size),
>> +                                                               printf(" %8u   %s%c\n",
>> +                                                                      FAT2CPU32(dentptr->size),
>>                                                                         l_name,
>>                                                                         dirc);
>>                                                         } else {
>> @@ -1032,8 +1033,8 @@ do_fat_read_at(const char *filename, unsigned long pos, void *buffer,
>>                                 }
>>                                 if (doit) {
>>                                         if (dirc == ' ') {
>> -                                               printf(" %8ld   %s%c\n",
>> -                                                       (long)FAT2CPU32(dentptr->size),
>> +                                               printf(" %8u   %s%c\n",
>> +                                                      FAT2CPU32(dentptr->size),
>>                                                         s_name, dirc);
>>                                         } else {
>>                                                 printf("            %s%c\n",
>> @@ -1102,7 +1103,7 @@ do_fat_read_at(const char *filename, unsigned long pos, void *buffer,
>>                         if (dols == LS_ROOT) {
>>                                 printf("\n%d file(s), %d dir(s)\n\n",
>>                                        files, dirs);
>> -                               ret = 0;
>> +                               *size = 0;
>>                         }
>>                         goto exit;
>>                 }
>> @@ -1141,7 +1142,7 @@ rootdir_done:
>>                 if (get_dentfromdir(mydata, startsect, subname, dentptr,
>>                                      isdir ? 0 : dols) == NULL) {
>>                         if (dols && !isdir)
>> -                               ret = 0;
>> +                               *size = 0;
>>                         goto exit;
>>                 }
>>
>> @@ -1152,21 +1153,24 @@ rootdir_done:
>>                         subname = nextname;
>>         }
>>
>> -       if (dogetsize)
>> -               ret = FAT2CPU32(dentptr->size);
>> -       else
>> -               ret = get_contents(mydata, dentptr, pos, buffer, maxsize);
>> -       debug("Size: %d, got: %ld\n", FAT2CPU32(dentptr->size), ret);
>> +       if (dogetsize) {
>> +               *size = FAT2CPU32(dentptr->size);
>> +               ret = 0;
>> +       } else {
>> +               ret = get_contents(mydata, dentptr, pos, buffer, maxsize, size);
>> +       }
>> +       debug("Size: %u, got: %llu\n", FAT2CPU32(dentptr->size), *size);
>>
>>  exit:
>>         free(mydata->fatbuf);
>>         return ret;
>>  }
>>
>> -long
>> -do_fat_read(const char *filename, void *buffer, unsigned long maxsize, int dols)
>> +int
>> +do_fat_read(const char *filename, void *buffer, loff_t maxsize, int dols,
>> +           loff_t *actread)
>>  {
>> -       return do_fat_read_at(filename, 0, buffer, maxsize, dols, 0);
>> +       return do_fat_read_at(filename, 0, buffer, maxsize, dols, 0, actread);
>>  }
>>
>>  int file_fat_detectfs(void)
>> @@ -1233,44 +1237,50 @@ int file_fat_detectfs(void)
>>
>>  int file_fat_ls(const char *dir)
>>  {
>> -       return do_fat_read(dir, NULL, 0, LS_YES);
>> +       loff_t size;
>> +
>> +       return do_fat_read(dir, NULL, 0, LS_YES, &size);
>>  }
>>
>>  int fat_exists(const char *filename)
>>  {
>> -       int sz;
>> -       sz = do_fat_read_at(filename, 0, NULL, 0, LS_NO, 1);
>> -       return sz >= 0;
>> +       int ret;
>> +       loff_t size;
>> +       ret = do_fat_read_at(filename, 0, NULL, 0, LS_NO, 1, &size);
>> +       return ret == 0;
>>  }
>>
>> -int fat_size(const char *filename)
>> +int fat_size(const char *filename, loff_t *size)
>>  {
>> -       return do_fat_read_at(filename, 0, NULL, 0, LS_NO, 1);
>> +       return do_fat_read_at(filename, 0, NULL, 0, LS_NO, 1, size);
>>  }
>>
>> -long file_fat_read_at(const char *filename, unsigned long pos, void *buffer,
>> -                     unsigned long maxsize)
>> +int file_fat_read_at(const char *filename, loff_t pos, void *buffer,
>> +                    loff_t maxsize, loff_t *actread)
>>  {
>>         printf("reading %s\n", filename);
>> -       return do_fat_read_at(filename, pos, buffer, maxsize, LS_NO, 0);
>> +       return do_fat_read_at(filename, pos, buffer, maxsize, LS_NO, 0,
>> +                             actread);
>>  }
>>
>> -long file_fat_read(const char *filename, void *buffer, unsigned long maxsize)
>> +int file_fat_read(const char *filename, void *buffer, loff_t maxsize,
>> +                 loff_t *actread)
>>  {
>> -       return file_fat_read_at(filename, 0, buffer, maxsize);
>> +       return file_fat_read_at(filename, 0, buffer, maxsize, actread);
>>  }
>>
>> -int fat_read_file(const char *filename, void *buf, int offset, int len)
>> +int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len,
>> +                 loff_t *actread)
>>  {
>> -       int len_read;
>> +       int ret;
>>
>> -       len_read = file_fat_read_at(filename, offset, buf, len);
>> -       if (len_read == -1) {
>> +       ret = file_fat_read_at(filename, offset, buf, len, actread);
>> +       if (ret < 0) {
>>                 printf("** Unable to read file %s **\n", filename);
>>                 return -1;
>>         }
>>
>> -       return len_read;
>> +       return 0;
>>  }
>>
>>  void fat_close(void)
>> diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
>> index 24ed5d3..b0c4611 100644
>> --- a/fs/fat/fat_write.c
>> +++ b/fs/fat/fat_write.c
>> @@ -660,24 +660,26 @@ static int clear_fatent(fsdata *mydata, __u32 entry)
>>  /*
>>   * Write at most 'maxsize' bytes from 'buffer' into
>>   * the file associated with 'dentptr'
>> - * Return the number of bytes read or -1 on fatal errors.
>> + * Update the number of bytes written in *gotsize and return 0
>> + * or return -1 on fatal errors.
>>   */
>>  static int
>>  set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer,
>> -             unsigned long maxsize)
>> +             loff_t maxsize, loff_t *gotsize)
>>  {
>> -       unsigned long filesize = FAT2CPU32(dentptr->size), gotsize = 0;
>> +       loff_t filesize = FAT2CPU32(dentptr->size);
>>         unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
>>         __u32 curclust = START(dentptr);
>>         __u32 endclust = 0, newclust = 0;
>> -       unsigned long actsize;
>> +       loff_t actsize;
>>
>> -       debug("Filesize: %ld bytes\n", filesize);
>> +       *gotsize = 0;
>> +       debug("Filesize: %llu bytes\n", filesize);
>>
>>         if (maxsize > 0 && filesize > maxsize)
>>                 filesize = maxsize;
>>
>> -       debug("%ld bytes\n", filesize);
>> +       debug("%llu bytes\n", filesize);
>>
>>         actsize = bytesperclust;
>>         endclust = curclust;
>> @@ -692,7 +694,7 @@ set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer,
>>                         if (CHECK_CLUST(newclust, mydata->fatsize)) {
>>                                 debug("curclust: 0x%x\n", newclust);
>>                                 debug("Invalid FAT entry\n");
>> -                               return gotsize;
>> +                               return 0;
>>                         }
>>                         endclust = newclust;
>>                         actsize += bytesperclust;
>> @@ -706,7 +708,7 @@ set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer,
>>                 }
>>
>>                 /* set remaining bytes */
>> -               gotsize += (int)actsize;
>> +               *gotsize += actsize;
>>                 filesize -= actsize;
>>                 buffer += actsize;
>>                 actsize = filesize;
>> @@ -715,7 +717,7 @@ set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer,
>>                         debug("error: writing cluster\n");
>>                         return -1;
>>                 }
>> -               gotsize += actsize;
>> +               *gotsize += actsize;
>>
>>                 /* Mark end of file in FAT */
>>                 if (mydata->fatsize == 16)
>> @@ -724,20 +726,20 @@ set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer,
>>                         newclust = 0xfffffff;
>>                 set_fatent_value(mydata, endclust, newclust);
>>
>> -               return gotsize;
>> +               return 0;
>>  getit:
>>                 if (set_cluster(mydata, curclust, buffer, (int)actsize) != 0) {
>>                         debug("error: writing cluster\n");
>>                         return -1;
>>                 }
>> -               gotsize += (int)actsize;
>> +               *gotsize += actsize;
>>                 filesize -= actsize;
>>                 buffer += actsize;
>>
>>                 if (CHECK_CLUST(curclust, mydata->fatsize)) {
>>                         debug("curclust: 0x%x\n", curclust);
>>                         debug("Invalid FAT entry\n");
>> -                       return gotsize;
>> +                       return 0;
>>                 }
>>                 actsize = bytesperclust;
>>                 curclust = endclust = newclust;
>> @@ -766,7 +768,7 @@ static void fill_dentry(fsdata *mydata, dir_entry *dentptr,
>>   * exceed the size of the block device
>>   * Return -1 when overflow occurs, otherwise return 0
>>   */
>> -static int check_overflow(fsdata *mydata, __u32 clustnum, unsigned long size)
>> +static int check_overflow(fsdata *mydata, __u32 clustnum, loff_t size)
>>  {
>>         __u32 startsect, sect_num;
>>
>> @@ -924,7 +926,7 @@ static dir_entry *find_directory_entry(fsdata *mydata, int startsect,
>>  }
>>
>>  static int do_fat_write(const char *filename, void *buffer,
>> -       unsigned long size)
>> +       loff_t size, loff_t *actwrite)
>>  {
>>         dir_entry *dentptr, *retdent;
>>         __u32 startsect;
>> @@ -936,8 +938,8 @@ static int do_fat_write(const char *filename, void *buffer,
>>         int cursect;
>>         int ret = -1, name_len;
>>         char l_filename[VFAT_MAXLEN_BYTES];
>> -       int write_size = size;
>>
>> +       *actwrite = size;
>>         dir_curclust = 0;
>>
>>         if (read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) {
>> @@ -1015,7 +1017,7 @@ static int do_fat_write(const char *filename, void *buffer,
>>
>>                 ret = check_overflow(mydata, start_cluster, size);
>>                 if (ret) {
>> -                       printf("Error: %ld overflow\n", size);
>> +                       printf("Error: %llu overflow\n", size);
>>                         goto exit;
>>                 }
>>
>> @@ -1025,13 +1027,12 @@ static int do_fat_write(const char *filename, void *buffer,
>>                         goto exit;
>>                 }
>>
>> -               ret = set_contents(mydata, retdent, buffer, size);
>> +               ret = set_contents(mydata, retdent, buffer, size, actwrite);
>>                 if (ret < 0) {
>>                         printf("Error: writing contents\n");
>>                         goto exit;
>>                 }
>> -               write_size = ret;
>> -               debug("attempt to write 0x%x bytes\n", write_size);
>> +               debug("attempt to write 0x%llx bytes\n", *actwrite);
>>
>>                 /* Flush fat buffer */
>>                 ret = flush_fat_buffer(mydata);
>> @@ -1061,7 +1062,7 @@ static int do_fat_write(const char *filename, void *buffer,
>>
>>                 ret = check_overflow(mydata, start_cluster, size);
>>                 if (ret) {
>> -                       printf("Error: %ld overflow\n", size);
>> +                       printf("Error: %llu overflow\n", size);
>>                         goto exit;
>>                 }
>>
>> @@ -1069,13 +1070,13 @@ static int do_fat_write(const char *filename, void *buffer,
>>                 fill_dentry(mydata, empty_dentptr, filename,
>>                         start_cluster, size, 0x20);
>>
>> -               ret = set_contents(mydata, empty_dentptr, buffer, size);
>> +               ret = set_contents(mydata, empty_dentptr, buffer, size,
>> +                                  actwrite);
>>                 if (ret < 0) {
>>                         printf("Error: writing contents\n");
>>                         goto exit;
>>                 }
>> -               write_size = ret;
>> -               debug("attempt to write 0x%x bytes\n", write_size);
>> +               debug("attempt to write 0x%llx bytes\n", *actwrite);
>>
>>                 /* Flush fat buffer */
>>                 ret = flush_fat_buffer(mydata);
>> @@ -1096,11 +1097,17 @@ static int do_fat_write(const char *filename, void *buffer,
>>
>>  exit:
>>         free(mydata->fatbuf);
>> -       return ret < 0 ? ret : write_size;
>> +       return ret;
>>  }
>>
>> -int file_fat_write(const char *filename, void *buffer, unsigned long maxsize)
>> +int file_fat_write(const char *filename, void *buffer, loff_t offset,
>> +                  loff_t maxsize, loff_t *actwrite)
>>  {
>> +       if (offset != 0) {
>> +               printf("Error: non zero offset is currently not suported.\n");
>> +               return -1;
>> +       }
>> +
>>         printf("writing %s\n", filename);
>> -       return do_fat_write(filename, buffer, maxsize);
>> +       return do_fat_write(filename, buffer, maxsize, actwrite);
>>  }
>> diff --git a/fs/fat/file.c b/fs/fat/file.c
>> index d910c46..b608883 100644
>> --- a/fs/fat/file.c
>> +++ b/fs/fat/file.c
>> @@ -162,8 +162,8 @@ file_ls(const char *dir)
>>         return filesystems[current_filesystem].ls(arg);
>>  }
>>
>> -long
>> -file_read(const char *filename, void *buffer, unsigned long maxsize)
>> +int
>> +file_read(const char *filename, void *buffer, loff_t maxsize, loff_t *actread)
>>  {
>>         char fullpath[1024];
>>         const char *arg;
>> @@ -180,5 +180,6 @@ file_read(const char *filename, void *buffer, unsigned long maxsize)
>>                 arg = fullpath;
>>         }
>>
>> -       return filesystems[current_filesystem].read(arg, buffer, maxsize);
>> +       return filesystems[current_filesystem].read(arg, buffer, maxsize,
>> +                                                   actread);
>>  }
>> diff --git a/fs/fs.c b/fs/fs.c
>> index dd680f3..0f5a1f4 100644
>> --- a/fs/fs.c
>> +++ b/fs/fs.c
>> @@ -46,19 +46,21 @@ static inline int fs_exists_unsupported(const char *filename)
>>         return 0;
>>  }
>>
>> -static inline int fs_size_unsupported(const char *filename)
>> +static inline int fs_size_unsupported(const char *filename, loff_t *size)
>>  {
>>         return -1;
>>  }
>>
>>  static inline int fs_read_unsupported(const char *filename, void *buf,
>> -                                     int offset, int len)
>> +                                     loff_t offset, loff_t len,
>> +                                     loff_t *actread)
>>  {
>>         return -1;
>>  }
>>
>>  static inline int fs_write_unsupported(const char *filename, void *buf,
>> -                                     int offset, int len)
>> +                                     loff_t offset, loff_t len,
>> +                                     loff_t *actwrite)
>>  {
>>         return -1;
>>  }
>> @@ -82,9 +84,11 @@ struct fstype_info {
>>                      disk_partition_t *fs_partition);
>>         int (*ls)(const char *dirname);
>>         int (*exists)(const char *filename);
>> -       int (*size)(const char *filename);
>> -       int (*read)(const char *filename, void *buf, int offset, int len);
>> -       int (*write)(const char *filename, void *buf, int offset, int len);
>> +       int (*size)(const char *filename, loff_t *size);
>> +       int (*read)(const char *filename, void *buf, loff_t offset,
>> +                   loff_t len, loff_t *actread);
>> +       int (*write)(const char *filename, void *buf, loff_t offset,
>> +                    loff_t len, loff_t *actwrite);
>>         void (*close)(void);
>>  };
>>
>> @@ -99,7 +103,11 @@ static struct fstype_info fstypes[] = {
>>                 .exists = fat_exists,
>>                 .size = fat_size,
>>                 .read = fat_read_file,
>> +#ifdef CONFIG_FAT_WRITE
>> +               .write = file_fat_write,
>> +#else
>>                 .write = fs_write_unsupported,
>> +#endif
>>         },
>>  #endif
>>  #ifdef CONFIG_FS_EXT4
>> @@ -112,7 +120,11 @@ static struct fstype_info fstypes[] = {
>>                 .exists = ext4fs_exists,
>>                 .size = ext4fs_size,
>>                 .read = ext4_read_file,
>> +#ifdef CONFIG_CMD_EXT4_WRITE
>> +               .write = ext4_write_file,
>> +#else
>>                 .write = fs_write_unsupported,
>> +#endif
>>         },
>>  #endif
>>  #ifdef CONFIG_SANDBOX
>> @@ -233,20 +245,21 @@ int fs_exists(const char *filename)
>>         return ret;
>>  }
>>
>> -int fs_size(const char *filename)
>> +int fs_size(const char *filename, loff_t *size)
>>  {
>>         int ret;
>>
>>         struct fstype_info *info = fs_get_info(fs_type);
>>
>> -       ret = info->size(filename);
>> +       ret = info->size(filename, size);
>>
>>         fs_close();
>>
>>         return ret;
>>  }
>>
>> -int fs_read(const char *filename, ulong addr, int offset, int len)
>> +int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
>> +           loff_t *actread)
>>  {
>>         struct fstype_info *info = fs_get_info(fs_type);
>>         void *buf;
>> @@ -257,11 +270,11 @@ int fs_read(const char *filename, ulong addr, int offset, int len)
>>          * means read the whole file.
>>          */
>>         buf = map_sysmem(addr, len);
>> -       ret = info->read(filename, buf, offset, len);
>> +       ret = info->read(filename, buf, offset, len, actread);
>>         unmap_sysmem(buf);
>>
>>         /* If we requested a specific number of bytes, check we got it */
>> -       if (ret >= 0 && len && ret != len) {
>> +       if (ret == 0 && len && *actread != len) {
>>                 printf("** Unable to read file %s **\n", filename);
>>                 ret = -1;
>>         }
>> @@ -270,17 +283,18 @@ int fs_read(const char *filename, ulong addr, int offset, int len)
>>         return ret;
>>  }
>>
>> -int fs_write(const char *filename, ulong addr, int offset, int len)
>> +int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len,
>> +            loff_t *actwrite)
>>  {
>>         struct fstype_info *info = fs_get_info(fs_type);
>>         void *buf;
>>         int ret;
>>
>>         buf = map_sysmem(addr, len);
>> -       ret = info->write(filename, buf, offset, len);
>> +       ret = info->write(filename, buf, offset, len, actwrite);
>>         unmap_sysmem(buf);
>>
>> -       if (ret >= 0 && ret != len) {
>> +       if (ret < 0 && len != *actwrite) {
>>                 printf("** Unable to write file %s **\n", filename);
>>                 ret = -1;
>>         }
>> @@ -292,7 +306,7 @@ int fs_write(const char *filename, ulong addr, int offset, int len)
>>  int do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
>>                 int fstype)
>>  {
>> -       int size;
>> +       loff_t size;
>>
>>         if (argc != 4)
>>                 return CMD_RET_USAGE;
>> @@ -300,8 +314,7 @@ int do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
>>         if (fs_set_blk_dev(argv[1], argv[2], fstype))
>>                 return 1;
>>
>> -       size = fs_size(argv[3]);
>> -       if (size < 0)
>> +       if (fs_size(argv[3], &size) < 0)
>>                 return CMD_RET_FAILURE;
>>
>>         setenv_hex("filesize", size);
>> @@ -315,9 +328,10 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
>>         unsigned long addr;
>>         const char *addr_str;
>>         const char *filename;
>> -       unsigned long bytes;
>> -       unsigned long pos;
>> -       int len_read;
>> +       loff_t bytes;
>> +       loff_t pos;
>> +       loff_t len_read;
>> +       int ret;
>>         unsigned long time;
>>         char *ep;
>>
>> @@ -359,12 +373,12 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
>>                 pos = 0;
>>
>>         time = get_timer(0);
>> -       len_read = fs_read(filename, addr, pos, bytes);
>> +       ret = fs_read(filename, addr, pos, bytes, &len_read);
>>         time = get_timer(time);
>> -       if (len_read <= 0)
>> +       if (ret < 0)
>>                 return 1;
>>
>> -       printf("%d bytes read in %lu ms", len_read, time);
>> +       printf("%llu bytes read in %lu ms", len_read, time);
>>         if (time > 0) {
>>                 puts(" (");
>>                 print_size(len_read / time * 1000, "/s");
>> @@ -408,9 +422,10 @@ int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
>>  {
>>         unsigned long addr;
>>         const char *filename;
>> -       unsigned long bytes;
>> -       unsigned long pos;
>> -       int len;
>> +       loff_t bytes;
>> +       loff_t pos;
>> +       loff_t len;
>> +       int ret;
>>         unsigned long time;
>>
>>         if (argc < 6 || argc > 7)
>> @@ -419,8 +434,8 @@ int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
>>         if (fs_set_blk_dev(argv[1], argv[2], fstype))
>>                 return 1;
>>
>> -       filename = argv[3];
>> -       addr = simple_strtoul(argv[4], NULL, 16);
>> +       addr = simple_strtoul(argv[3], NULL, 16);
>> +       filename = argv[4];
>>         bytes = simple_strtoul(argv[5], NULL, 16);
>>         if (argc >= 7)
>>                 pos = simple_strtoul(argv[6], NULL, 16);
>> @@ -428,12 +443,12 @@ int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
>>                 pos = 0;
>>
>>         time = get_timer(0);
>> -       len = fs_write(filename, addr, pos, bytes);
>> +       ret = fs_write(filename, addr, pos, bytes, &len);
>>         time = get_timer(time);
>> -       if (len <= 0)
>> +       if (ret < 0)
>>                 return 1;
>>
>> -       printf("%d bytes written in %lu ms", len, time);
>> +       printf("%llu bytes written in %lu ms", len, time);
>>         if (time > 0) {
>>                 puts(" (");
>>                 print_size(len / time * 1000, "/s");
>> diff --git a/fs/sandbox/sandboxfs.c b/fs/sandbox/sandboxfs.c
>> index ba6402c..d4d8378 100644
>> --- a/fs/sandbox/sandboxfs.c
>> +++ b/fs/sandbox/sandboxfs.c
>> @@ -16,7 +16,7 @@ int sandbox_fs_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info)
>>  long sandbox_fs_read_at(const char *filename, unsigned long pos,
>>                              void *buffer, unsigned long maxsize)
>>  {
>> -       ssize_t size;
>> +       loff_t size;
>>         int fd, ret;
>>
>>         fd = os_open(filename, OS_O_RDONLY);
>> @@ -27,8 +27,16 @@ long sandbox_fs_read_at(const char *filename, unsigned long pos,
>>                 os_close(fd);
>>                 return ret;
>>         }
>> -       if (!maxsize)
>> -               maxsize = os_get_filesize(filename);
>> +       if (!maxsize) {
>> +               ret = os_get_filesize(filename, &size);
>> +               if (ret) {
>> +                       os_close(fd);
>> +                       return ret;
>> +               }
>> +
>> +               maxsize = size;
>> +       }
>> +
>>         size = os_read(fd, buffer, maxsize);
>>         os_close(fd);
>>
>> @@ -74,15 +82,16 @@ int sandbox_fs_ls(const char *dirname)
>>
>>  int sandbox_fs_exists(const char *filename)
>>  {
>> -       ssize_t sz;
>> +       loff_t sz;
>> +       int ret;
>>
>> -       sz = os_get_filesize(filename);
>> -       return sz >= 0;
>> +       ret = os_get_filesize(filename, &sz);
>> +       return ret == 0;
>>  }
>>
>> -int sandbox_fs_size(const char *filename)
>> +int sandbox_fs_size(const char *filename, loff_t *size)
>>  {
>> -       return os_get_filesize(filename);
>> +       return os_get_filesize(filename, size);
>>  }
>>
>>  void sandbox_fs_close(void)
>> diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
>> index ee4b244..2b03841 100644
>> --- a/include/configs/sandbox.h
>> +++ b/include/configs/sandbox.h
>> @@ -48,6 +48,7 @@
>>  #define CONFIG_ANDROID_BOOT_IMAGE
>>
>>  #define CONFIG_FS_FAT
>> +#define CONFIG_FAT_WRITE
>>  #define CONFIG_FS_EXT4
>>  #define CONFIG_EXT4_WRITE
>>  #define CONFIG_CMD_FAT
>> @@ -57,6 +58,7 @@
>>  #define CONFIG_DOS_PARTITION
>>  #define CONFIG_HOST_MAX_DEVICES 4
>>  #define CONFIG_CMD_FS_GENERIC
>> +#define CONFIG_CMD_MD5SUM
>>
>>  #define CONFIG_SYS_VSNPRINTF
>>
>> diff --git a/include/ext4fs.h b/include/ext4fs.h
>> index 6c419f3..7630057 100644
>> --- a/include/ext4fs.h
>> +++ b/include/ext4fs.h
>> @@ -125,24 +125,27 @@ int ext4fs_init(void);
>>  void ext4fs_deinit(void);
>>  int ext4fs_filename_check(char *filename);
>>  int ext4fs_write(const char *fname, unsigned char *buffer,
>> -                               unsigned long sizebytes);
>> +                unsigned long sizebytes);
>> +int ext4_write_file(const char *filename, void *buf, loff_t offset, loff_t len,
>> +                   loff_t *actwrite);
>>  #endif
>>
>>  struct ext_filesystem *get_fs(void);
>> -int ext4fs_open(const char *filename);
>> -int ext4fs_read(char *buf, unsigned len);
>> +int ext4fs_open(const char *filename, loff_t *len);
>> +int ext4fs_read(char *buf, loff_t len, loff_t *actread);
>>  int ext4fs_mount(unsigned part_length);
>>  void ext4fs_close(void);
>>  void ext4fs_reinit_global(void);
>>  int ext4fs_ls(const char *dirname);
>>  int ext4fs_exists(const char *filename);
>> -int ext4fs_size(const char *filename);
>> +int ext4fs_size(const char *filename, loff_t *size);
>>  void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot);
>>  int ext4fs_devread(lbaint_t sector, int byte_offset, int byte_len, char *buf);
>>  void ext4fs_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info);
>>  long int read_allocated_block(struct ext2_inode *inode, int fileblock);
>>  int ext4fs_probe(block_dev_desc_t *fs_dev_desc,
>>                  disk_partition_t *fs_partition);
>> -int ext4_read_file(const char *filename, void *buf, int offset, int len);
>> +int ext4_read_file(const char *filename, void *buf, loff_t offset, loff_t len,
>> +                  loff_t *actread);
>>  int ext4_read_superblock(char *buffer);
>>  #endif
>> diff --git a/include/fat.h b/include/fat.h
>> index 20ca3f3..7a57533 100644
>> --- a/include/fat.h
>> +++ b/include/fat.h
>> @@ -178,8 +178,8 @@ typedef struct {
>>
>>  typedef int    (file_detectfs_func)(void);
>>  typedef int    (file_ls_func)(const char *dir);
>> -typedef long   (file_read_func)(const char *filename, void *buffer,
>> -                                unsigned long maxsize);
>> +typedef int    (file_read_func)(const char *filename, void *buffer,
>> +                                loff_t maxsize, loff_t *actread);
>>
>>  struct filesystem {
>>         file_detectfs_func      *detect;
>> @@ -198,15 +198,18 @@ int file_cd(const char *path);
>>  int file_fat_detectfs(void);
>>  int file_fat_ls(const char *dir);
>>  int fat_exists(const char *filename);
>> -int fat_size(const char *filename);
>> -long file_fat_read_at(const char *filename, unsigned long pos, void *buffer,
>> -                     unsigned long maxsize);
>> -long file_fat_read(const char *filename, void *buffer, unsigned long maxsize);
>> +int fat_size(const char *filename, loff_t *size);
>> +int file_fat_read_at(const char *filename, loff_t pos, void *buffer,
>> +                    loff_t maxsize, loff_t *actread);
>> +int file_fat_read(const char *filename, void *buffer, loff_t maxsize,
>> +                 loff_t *actread);
>>  const char *file_getfsname(int idx);
>>  int fat_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info);
>>  int fat_register_device(block_dev_desc_t *dev_desc, int part_no);
>>
>> -int file_fat_write(const char *filename, void *buffer, unsigned long maxsize);
>> -int fat_read_file(const char *filename, void *buf, int offset, int len);
>> +int file_fat_write(const char *filename, void *buf, loff_t offset, loff_t len,
>> +                  loff_t *actwrite);
>> +int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len,
>> +                 loff_t *actread);
>>  void fat_close(void);
>>  #endif /* _FAT_H_ */
>> diff --git a/include/fs.h b/include/fs.h
>> index 06a45f2..61ff572 100644
>> --- a/include/fs.h
>> +++ b/include/fs.h
>> @@ -55,7 +55,7 @@ int fs_exists(const char *filename);
>>   *
>>   * Returns the file's size in bytes, or a negative value if it doesn't exist.
>>   */
>> -int fs_size(const char *filename);
>> +int fs_size(const char *filename, loff_t *size);
>>
>>  /*
>>   * Read file "filename" from the partition previously set by fs_set_blk_dev(),
>> @@ -66,7 +66,8 @@ int fs_size(const char *filename);
>>   *
>>   * Returns number of bytes read on success. Returns <= 0 on error.
>>   */
>> -int fs_read(const char *filename, ulong addr, int offset, int len);
>> +int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
>> +           loff_t *actread);
>>
>>  /*
>>   * Write file "filename" to the partition previously set by fs_set_blk_dev(),
>> @@ -76,7 +77,8 @@ int fs_read(const char *filename, ulong addr, int offset, int len);
>>   *
>>   * Returns number of bytes read on success. Returns <= 0 on error.
>>   */
>> -int fs_write(const char *filename, ulong addr, int offset, int len);
>> +int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len,
>> +            loff_t *actwrite);
>
> Can you please update the comments for functions you have changed?.
> Also the comment style is generally like this:
>
> /**
>  * setenv_addr - Set an environment variable to an address in hex
>  *
>  * @varname: Environment variable to set
>  * @addr: Value to set it to
>  * @return 0 if ok, 1 on error
>  */
>
> So you have each argument listed explicitly. I think this should be
> done in fs.h since this documents the interface.
>

I shall do so in my next version.

>>
>>  /*
>>   * Common implementation for various filesystem commands, optionally limited
>> diff --git a/include/os.h b/include/os.h
>> index 0230a7f..cfefc8c 100644
>> --- a/include/os.h
>> +++ b/include/os.h
>> @@ -219,7 +219,7 @@ const char *os_dirent_get_typename(enum os_dirent_t type);
>>   * @param fname                Filename to check
>>   * @return size of file, or -1 if an error ocurred
>>   */
>> -ssize_t os_get_filesize(const char *fname);
>> +int os_get_filesize(const char *fname, loff_t *size);
>>
>>  /**
>>   * Write a character to the controlling OS terminal
>> diff --git a/include/sandboxfs.h b/include/sandboxfs.h
>> index e7c3262..ea11168 100644
>> --- a/include/sandboxfs.h
>> +++ b/include/sandboxfs.h
>> @@ -26,8 +26,10 @@ long sandbox_fs_read_at(const char *filename, unsigned long pos,
>>  void sandbox_fs_close(void);
>>  int sandbox_fs_ls(const char *dirname);
>>  int sandbox_fs_exists(const char *filename);
>> -int sandbox_fs_size(const char *filename);
>> -int fs_read_sandbox(const char *filename, void *buf, int offset, int len);
>> -int fs_write_sandbox(const char *filename, void *buf, int offset, int len);
>> +int sandbox_fs_size(const char *filename, loff_t *size);
>> +int fs_read_sandbox(const char *filename, void *buf, loff_t offset, loff_t len,
>> +                   loff_t *size);
>> +int fs_write_sandbox(const char *filename, void *buf, loff_t offset,
>> +                    loff_t len, loff_t *actwrite);
>>
>>  #endif
>> diff --git a/test/fs/testfs.sh b/test/fs/testfs.sh
>> new file mode 100755
>> index 0000000..140fa10
>> --- /dev/null
>> +++ b/test/fs/testfs.sh
>> @@ -0,0 +1,334 @@
>> +#!/bin/bash
>> +# (C) Copyright 2014 Suriyan Ramasami
>> +#
>> +#  SPDX-License-Identifier:    GPL-2.0+
>> +#
>> +
>> +# Call with parameter clean to remove all its generated files and exit
>
> You should make this file executable, also remove blank line at end
> (use patman to send patches!)
>

I shall try patman out in my next version.

> Can you add documentation here on how to run it? I got this:
>

Currently, it needs to be run from cd ing into the u-boot/test/fs/ directory.

> $ sh test/fs/testfs.sh
> Creating ext4 image if not already present.
> Creating files in ext4 image if not already present.
> rmdir: failed to remove `tmpmount': Device or resource busy
> test/fs/testfs.sh: line 71: ../../u-boot: Is a directory
> ------------------- Start test.output.ext4.out ---------------------
> FAIL - ls host 0:0 of 2.5 GB file
> FAIL - ls host 0:0 of 1 MB file
> FAIL - size host 0:0 1MB.file
> FAIL - size host 0:0 2.5GB.file
> FAIL - load host 0:0 0x01000008 1MB.file sz
> FAIL - load host 0:0 0x01000008 1MB.file
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x0 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x0
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x9C300000 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x9C300000
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x7FF00000 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x7FF00000
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x80000000 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x80000000
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x7FF80000 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x7FF80000
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00200000 0x9C300000 sz
> FAIL - write host 0:0 0x01000008 /1MB.file.w
> FAIL - load host 0:0 0x01000008 /1MB.file.w
> ------------------- End test.output.ext4.out ---------------------
>
> Creating files in ext4 image if not already present.
> rmdir: failed to remove `tmpmount': Device or resource busy
> test/fs/testfs.sh: line 71: ../../u-boot: Is a directory
> ------------------- Start test.output.fs.ext4.out ---------------------
> FAIL - ls host 0:0 of 2.5 GB file
> FAIL - ls host 0:0 of 1 MB file
> FAIL - size host 0:0 1MB.file
> FAIL - size host 0:0 2.5GB.file
> FAIL - load host 0:0 0x01000008 1MB.file sz
> FAIL - load host 0:0 0x01000008 1MB.file
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x0 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x0
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x9C300000 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x9C300000
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x7FF00000 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x7FF00000
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x80000000 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x80000000
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x7FF80000 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x7FF80000
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00200000 0x9C300000 sz
> FAIL - write host 0:0 0x01000008 /1MB.file.w
> FAIL - load host 0:0 0x01000008 /1MB.file.w
> ------------------- End test.output.fs.ext4.out ---------------------
>
> Creating vfat image if not already present.
> Creating files in vfat image if not already present.
> rmdir: failed to remove `tmpmount': Device or resource busy
> test/fs/testfs.sh: line 71: ../../u-boot: Is a directory
> ------------------- Start test.output.fat.out ---------------------
> FAIL - ls host 0:0 of 2.5 GB file
> FAIL - ls host 0:0 of 1 MB file
> FAIL - size host 0:0 1MB.file
> FAIL - size host 0:0 2.5GB.file
> FAIL - load host 0:0 0x01000008 1MB.file sz
> FAIL - load host 0:0 0x01000008 1MB.file
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x0 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x0
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x9C300000 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x9C300000
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x7FF00000 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x7FF00000
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x80000000 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x80000000
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x7FF80000 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x7FF80000
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00200000 0x9C300000 sz
> FAIL - write host 0:0 0x01000008 1MB.file.w
> FAIL - load host 0:0 0x01000008 1MB.file.w
> ------------------- End test.output.fat.out ---------------------
>
> Creating files in vfat image if not already present.
> rmdir: failed to remove `tmpmount': Device or resource busy
> test/fs/testfs.sh: line 71: ../../u-boot: Is a directory
> ------------------- Start test.output.fs.fat.out ---------------------
> FAIL - ls host 0:0 of 2.5 GB file
> FAIL - ls host 0:0 of 1 MB file
> FAIL - size host 0:0 1MB.file
> FAIL - size host 0:0 2.5GB.file
> FAIL - load host 0:0 0x01000008 1MB.file sz
> FAIL - load host 0:0 0x01000008 1MB.file
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x0 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x0
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x9C300000 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x9C300000
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x7FF00000 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x7FF00000
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x80000000 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x80000000
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x7FF80000 sz
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00100000 0x7FF80000
> FAIL - load host 0:0 0x01000008 2.5GB.file 0x00200000 0x9C300000 sz
> FAIL - write host 0:0 0x01000008 1MB.file.w
> FAIL - load host 0:0 0x01000008 1MB.file.w
> ------------------- End test.output.fs.fat.out ---------------------
>
>
> clean is a nice feature, but perhaps you could create all the files in
> a subdirectory?
>

I shall use the sandbox approach in my next version.

>> +
>> +IMG=./3GB
>> +TMPMOUNT=tmpmount
>> +SFILE=1MB.file
>> +BFILE=2.5GB.file
>
> SMALL_FILE
> BIG_FILE
>
>> +MD5FILE=./md5s.list
>
> Please add a one-line comment documenting these.
>

OK

>> +
>> +# Output files
>> +OUT=test.output
>> +
>> +# All out files will have the above prefix and a .out suffix
>> +rm -f ${MD5FILE}.* ${OUT}.*.out
>> +
>> +if [ "$1" = "clean" ]; then
>> +       rm -f *.img
>> +       exit
>> +fi
>> +
>> +MB1=${TMPMOUNT}/${SFILE}
>> +GB2p5=${TMPMOUNT}/${BFILE}
>> +
>> +# 1st parameter is the prefix name of the image file
>> +# 2nd parameter is the filesystem - vfat ext4 etc
>> +# The final image file is $1.$2.img
>> +# Returns the actual image created.
>> +function CreateImg() {
>
> We should avoid camel case, so create_image() is better I think. (up
> to you, but IMO the abbreviation to img is unnecessary when it's
> already pretty short)
>
>> +       THE_IMG=$1.$2.img
>
> How about IMAGE instead of THE_IMG?

OK, and shall avoid camel case (I somehow seem to love camel case)

>
>> +
>> +       # Create image if not already present - saves time, while debugging
>> +
>> +       if [ ! -f ${THE_IMG} ]; then
>> +               fallocate -l 3G ${THE_IMG} &> /dev/null
>> +               if [ "$2" = "ext4" ]; then
>> +                       mkfs.${2} ${THE_IMG} &> /dev/null <<EOF
>> +y
>> +EOF
>> +               else
>> +                       mkfs.${2} ${THE_IMG} &> /dev/null
>> +               fi
>> +       fi
>> +       echo "${THE_IMG}"
>> +}
>> +
>> +# First parameter is image file
>> +# Second parameter which is prepended to the ls/load commands
>> +#   Example: load vs fatload
>> +# Assumes SFILE and BFILE are set in env
>> +function TestImg() {
>> +       THE_IMG="${1}"
>> +       PREFIX="${2}"
>> +
>> +       # In u-boot commands, <interface> stands for host or hostfs
>> +       # hostfs maps to the host fs.
>> +       # host maps to the "sb bind" that we do
>> +
>> +       # Set up the write file name
>> +       if [ "$PREFIX" = "fat" ]; then
>> +               WFILE=1MB.file.w
>
> You quote the one a few lines below so should be consistent and quote this one.

Ok

>
>> +       fi
>> +       if [ "$PREFIX" = "ext4" ]; then
>> +               WFILE="/1MB.file.w"
>> +       fi
>> +
>> +       ../../u-boot << EOF
>
> The path to U-Boot should be a variable at the top. Also I suggest it
> goes in the 'sandbox' directory rather than requiring an in-tree
> build.
>

OK

>> +
>> +sb bind 0 ${THE_IMG}
>> +${PREFIX}ls host 0:0 /
>> +#
>> +# 1MB is 0x0010 0000
>> +${PREFIX}size host 0:0 ${SFILE}
>> +printenv filesize
>> +setenv filesize
>> +
>> +# 2.5GB (1024*1024*2500) is 0x9C40 0000
>> +${PREFIX}size host 0:0 ${BFILE}
>> +printenv filesize
>> +setenv filesize
>> +
>> +# Notes about load operation
>> +# If I use 0x01000000 I get DMA misaligned error message
>> +# Last two parameters are size and offset.
>> +
>> +# Read full 1MB of small file
>> +${PREFIX}load host 0:0 0x01000008 ${SFILE}
>> +printenv filesize
>> +md5sum 0x01000008 \$filesize
>> +setenv filesize
>> +
>> +# First 1MB of big file
>> +${PREFIX}load host 0:0 0x01000008 ${BFILE} 0x00100000 0x0
>> +printenv filesize
>> +md5sum 0x01000008 \$filesize
>> +setenv filesize
>> +
>> +# Last 1MB of big file - fails for ext as no offset support
>> +${PREFIX}load host 0:0 0x01000008 ${BFILE} 0x00100000 0x9C300000
>> +printenv filesize
>> +md5sum 0x01000008 \$filesize
>> +setenv filesize
>> +
>> +# One from the last 1MB chunk of 2GB - fails for ext
>> +${PREFIX}load host 0:0 0x01000008 ${BFILE} 0x00100000 0x7FF00000
>> +printenv filesize
>> +md5sum 0x01000008 \$filesize
>> +setenv filesize
>> +
>> +# One from the start 1MB chunk from 2GB - fails for ext
>> +${PREFIX}load host 0:0 0x01000008 ${BFILE} 0x00100000 0x80000000
>> +printenv filesize
>> +md5sum 0x01000008 \$filesize
>> +setenv filesize
>> +
>> +# One 1MB chunk crossing the 2GB boundary - fails for ext
>> +${PREFIX}load host 0:0 0x01000008 ${BFILE} 0x00100000 0x7FF80000
>> +printenv filesize
>> +md5sum 0x01000008 \$filesize
>> +setenv filesize
>> +
>> +# 2MB chunk from the last 1MB of big file - Generic failure case
>> +${PREFIX}load host 0:0 0x01000008 ${BFILE} 0x00200000 0x9C300000
>> +printenv filesize
>> +#
>> +
>> +# Read 1MB from small file
>> +${PREFIX}load host 0:0 0x01000008 ${SFILE}
>> +# Write it back to test the writes
>> +${PREFIX}write host 0:0 0x01000008 ${WFILE} \$filesize
>> +mw.b 0x01000008 00 100
>> +${PREFIX}load host 0:0 0x01000008 ${WFILE}
>> +md5sum 0x01000008 \$filesize
>> +setenv filesize
>> +#
>> +reset
>> +
>> +EOF
>> +}
>> +
>> +# Assume 1st argument is the name of the image file.
>> +# Assume 2nd argument is the file where we generate the md5s of the
>
> You should remove 'Assume'.
>

OK

>> +# files generated with the appropriate start and length that we use to test
>> +function CreateFilesInImg() {
>> +       THE_IMG="$1"
>
> IMAGE?
>

OK

>> +       MD5OUT="$2"
>> +
>> +       # Create a big file in this image.
>> +       # Note that we work only on the start 1MB, couple MBs in the 2GB range
>> +       # and the last 1 MB of the huge 2.5GB file.
>> +       # So, just put random values only in those areas.
>> +       mkdir -p ${TMPMOUNT}
>> +       sudo mount -o loop ${THE_IMG} ${TMPMOUNT}
>> +       if [ ! -f ${GB2p5} ]; then
>> +               sudo dd if=/dev/urandom of=${GB2p5} bs=1M count=1 \
>> +                       2> /dev/null
>> +               sudo dd if=/dev/urandom of=${GB2p5} bs=1M count=2 seek=2047 \
>> +                       2> /dev/null
>> +               sudo dd if=/dev/urandom of=${GB2p5} bs=1M count=1 seek=2499 \
>> +                       2> /dev/null
>> +       fi
>> +
>> +       # Create a small file in this image.
>> +       if [ ! -f ${MB1} ]; then
>> +               sudo dd if=/dev/urandom of=${MB1} bs=1M count=1 2> /dev/null
>> +       fi
>> +
>> +       # Delete the small file which possibly is written as part of a
>> +       # previous test.
>> +       sudo rm -f ${TMPMOUNT}/*.w
>> +
>> +       # Generate the md5sums of reads that we will test against small file
>> +       dd if=${MB1} bs=1M skip=0 count=1 2> /dev/null | md5sum > ${MD5OUT}
>> +
>> +       # Generate the md5sums of reads that we will test against big file
>> +       # One from beginning of file.
>> +       dd if=${GB2p5} bs=1M skip=0 count=1 2> /dev/null | md5sum >> ${MD5OUT}
>> +
>> +       # One from end of file.
>> +       dd if=${GB2p5} bs=1M skip=2499 count=1 \
>> +               2> /dev/null | md5sum >> ${MD5OUT}
>> +
>> +       # One from the last 1MB chunk of 2GB
>> +       dd if=${GB2p5} bs=1M skip=2047 count=1 \
>> +               2> /dev/null | md5sum >> ${MD5OUT}
>> +
>> +       # One from the start 1MB chunk from 2GB
>> +       dd if=${GB2p5} bs=1M skip=2048 count=1 \
>> +               2> /dev/null | md5sum >> ${MD5OUT}
>> +
>> +       # One 1MB chunk crossing the 2GB boundary
>> +       dd if=${GB2p5} bs=512K skip=4095 count=2 \
>> +               2> /dev/null | md5sum >> ${MD5OUT}
>> +
>> +       sync
>> +       sudo umount tmpmount
>> +       rmdir tmpmount
>> +}
>> +
>> +# First parameter is the text
>> +# if $? is 0 its a pass, else a fail
>> +function PassFail() {
>> +
>> +       if [ $? -eq 0 ]; then
>> +               echo pass - "$1"
>> +       else
>> +               echo FAIL - "$1"
>> +       fi
>> +}
>> +
>
> Note here about what this function does.
>

OK

>> +# Parameter 1 is the string which leads to an md5 generation
>> +# Parameter 2 is the file we grep for that string
>> +# Parameter 3 is the name of the file which has md5s in it
>> +# Parameter 4 is the line # in the md5 file that we match it against
>> +CheckMD5() {
>
> check_md5 - please fix camel case globally.
>

OK

>> +
>> +       md5src=`grep -A6 "$1" "$2" | grep "md5 for"`
>> +       md5src=($md5src)
>> +       md5src=${md5src[6]}
>> +       md5dst=`sed -n $4p $3`
>> +       md5dst=($md5dst)
>> +       md5dst=${md5dst[0]}
>> +       [ "$md5src" = "$md5dst" ]
>> +       PassFail "$1"
>> +}
>> +
>
> What does the function do?
>

Shall document it in the next version

>> +# First parameter is the name of the output file to check
>> +# Second parameter is the name of the file containing the md5 expected
>> +# Assume SFILE, BFILE and WFILE are set
>> +function CheckResults() {
>> +       OUTFILE="$1"
>> +       MD5="$2"
>> +
>> +       echo "------------------- Start $1 ---------------------"
>> +       # Check if the ls is showing correct results for 2.5 gb file
>> +       grep -A6 "ls host 0:0" $OUTFILE | grep 2621440000 | grep -iq 2.5gb.file
>> +       PassFail "ls host 0:0 of 2.5 GB file"
>> +
>> +       # Check if the ls is showing correct results for 1 mb file
>> +       grep -A6 "ls host 0:0" $OUTFILE | grep 1048576 | grep -iq 1mb.file
>> +       PassFail "ls host 0:0 of 1 MB file"
>> +
>> +       # Check size command on 1MB.file
>> +       grep -A3 "size host 0:0 ${SFILE}" $OUTFILE | grep -q "filesize=100000"
>> +       PassFail "size host 0:0 ${SFILE}"
>> +
>> +       # Check size command on 2.5GB.file
>> +       grep -A3 "size host 0:0 ${BFILE}" $OUTFILE \
>> +               | grep -q "filesize=9c400000"
>> +       PassFail "size host 0:0 ${BFILE}"
>> +
>> +       # Check read full mb of 1MB.file
>> +       grep -A6 "load host 0:0 0x01000008 ${SFILE}" $OUTFILE | \
>> +               grep -q "filesize=100000"
>> +       PassFail "load host 0:0 0x01000008 ${SFILE} sz"
>> +       CheckMD5 "load host 0:0 0x01000008 ${SFILE}" $OUTFILE $MD5 1
>> +
>> +       # Check first mb of 2.5GB.file
>> +       grep -A6 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x0" \
>> +               $OUTFILE | grep -q "filesize=100000"
>> +       PassFail "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x0 sz"
>> +       CheckMD5 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x0" \
>> +               $OUTFILE $MD5 2
>> +
>> +       # Check last mb of 2.5GB.file
>> +       grep -A6 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x9C300000" \
>> +               $OUTFILE | grep -q "filesize=100000"
>> +       PassFail "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x9C300000 sz"
>> +       CheckMD5 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x9C300000" \
>> +               $OUTFILE $MD5 3
>> +
>> +       # Check last 1mb chunk of 2gb from 2.5GB file
>> +       grep -A6 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x7FF00000" \
>> +               $OUTFILE | grep -q "filesize=100000"
>> +       PassFail "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x7FF00000 sz"
>> +       CheckMD5 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x7FF00000" \
>> +               $OUTFILE $MD5 4
>> +
>> +       # Check first 1mb chunk after 2gb from 2.5GB file
>> +       grep -A6 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x80000000" \
>> +               $OUTFILE | grep -q "filesize=100000"
>> +       PassFail "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x80000000 sz"
>> +       CheckMD5 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x80000000" \
>> +               $OUTFILE $MD5 5
>> +
>> +       # Check 1mb chunk crossing the 2gb boundary from 2.5GB file
>> +       grep -A6 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x7FF80000" \
>> +               $OUTFILE | grep -q "filesize=100000"
>> +       PassFail "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x7FF80000 sz"
>> +       CheckMD5 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x7FF80000" \
>> +               $OUTFILE $MD5 6
>> +
>> +       # Check 2mb chunk from the last 1MB of 2.5GB file - generic failure case
>> +       grep -A6 "load host 0:0 0x01000008 ${BFILE} 0x00200000 0x9C300000" \
>> +               $OUTFILE | grep -q 'Error: "filesize" not defined'
>> +       PassFail "load host 0:0 0x01000008 ${BFILE} 0x00200000 0x9C300000 sz"
>> +
>> +       # Check 1mb chunk write
>> +       grep -A3 "write host 0:0 0x01000008 ${WFILE}" \
>> +               $OUTFILE | egrep -q '1048576 bytes written|update journal'
>> +       PassFail "write host 0:0 0x01000008 ${WFILE}"
>> +       CheckMD5 "load host 0:0 0x01000008 ${WFILE}" \
>> +               $OUTFILE $MD5 1
>> +       echo "------------------- End $1 ---------------------"
>> +       echo ""
>> +}
>> +
>> +for fs in ext4 fat; do
>
> Can you just use vfat and remove this 'if' below?
>

OK.

>> +
>> +       if [ $fs = "fat" ]; then
>> +               FS=vfat
>> +       else
>> +               FS=$fs
>> +       fi
>> +       echo "Creating $FS image if not already present."
>> +       ACTIMG=`CreateImg ${IMG} ${FS}`
>> +
>> +       echo "Creating files in $FS image if not already present."
>> +       CreateFilesInImg ${ACTIMG} ${MD5FILE}.${fs}
>> +
>> +       TestImg ${ACTIMG} ${fs} > ${OUT}.${fs}.out
>> +       CheckResults ${OUT}.${fs}.out ${MD5FILE}.${fs}
>> +
>> +       echo "Creating files in $FS image if not already present."
>> +       CreateFilesInImg ${ACTIMG} ${MD5FILE}.${fs}
>> +
>> +       TestImg ${ACTIMG} "" > ${OUT}.fs.${fs}.out
>> +       CheckResults ${OUT}.fs.${fs}.out ${MD5FILE}.${fs}
>> +done
>
> It should print 'PASSED' or 'FAILED' at the end and set the return
> code to 0 if OK, 1 if not.
>

OK. Shall incorporate that in the next version.

Thanks for the review!
- Suriyan

> Regards,
> Simon


More information about the U-Boot mailing list