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 conditions.

Signed-off-by: Suriyan Ramasami <[email protected]>

---

Changes in v5:
* Simon - update fs.h with comments for fs_read/fs_write/fs_size
* Simon - test/fs/fs-test.sh. Many changes as listed under
*   Add README file to document how to run it
*   Generate output in a sandbox environment
*   Add one line comments on shell variables used
*   Avoid camel case through out
*   Path to UBOOT is variable at top
*   Print PASSED or FAILED at end, and set return code, 0 if OK, 1 otherwise

Changes in v4:
* Support generic fs write commands
* Sync up behavior of fs load vs fatload and ext4load
* Albert - change -ve to negative in commit message

Changes in v3:
* Added testcase to test writes
* Correct function set_contents() in fs/fat/fat_write.c

Changes in v2:
* Added test case for fat/ext4 in test/fs/testfs.sh
* md5sum: call map_sysmem() for buffer that md5_wd will work on

Changes in 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              |  41 ++--
 include/os.h              |   2 +-
 include/sandboxfs.h       |   8 +-
 test/fs/README            |   4 +
 test/fs/fs-test.sh        | 462 ++++++++++++++++++++++++++++++++++++++++++++++
 25 files changed, 807 insertions(+), 259 deletions(-)
 create mode 100644 test/fs/README
 create mode 100755 test/fs/fs-test.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 cccc06a..cab5465 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -1892,6 +1892,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
@@ -1909,8 +1910,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) {
@@ -1921,8 +1922,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));
@@ -2004,8 +2006,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);
@@ -2020,6 +2022,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);
@@ -2036,7 +2039,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;
@@ -2170,11 +2173,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;
@@ -2191,10 +2193,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..6bd17c8 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -51,32 +51,41 @@ int fs_ls(const char *dirname);
 int fs_exists(const char *filename);
 
 /*
- * Determine a file's size
+ * fs_size - Determine a file's size
  *
- * Returns the file's size in bytes, or a negative value if it doesn't exist.
+ * @filename: Name of the file
+ * @size: Size of file
+ * @return 0 if ok with valid *size, negative on error
  */
-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(),
- * to address "addr", starting at byte offset "offset", and reading "len"
- * bytes. "offset" may be 0 to read from the start of the file. "len" may be
- * 0 to read the entire file. Note that not all filesystem types support
- * either/both offset!=0 or len!=0.
+ * fs_read - Read file from the partition previously set by fs_set_blk_dev()
+ * Note that not all filesystem types support either/both offset!=0 or len!=0.
  *
- * Returns number of bytes read on success. Returns <= 0 on error.
+ * @filename: Name of file to read from
+ * @addr: The address to read into
+ * @offset: The offset in file to read from
+ * @len: The number of bytes to read. Maybe 0 to read entire file
+ * @actread: The actual number of bytes read
+ * @return 0 if ok with valid *actread, -1 on error conditions
  */
-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(),
- * from address "addr", starting at byte offset "offset", and writing "len"
- * bytes. "offset" may be 0 to write to the start of the file. Note that not
- * all filesystem types support offset!=0.
+ * fs_write - Write file to the partition previously set by fs_set_blk_dev()
+ * Note that not all filesystem types support offset!=0.
  *
- * Returns number of bytes read on success. Returns <= 0 on error.
+ * @filename: Name of file to read from
+ * @addr: The address to read into
+ * @offset: The offset in file to read from. Maybe 0 to write to start of file
+ * @len: The number of bytes to write
+ * @actwrite: The actual number of bytes written
+ * @return 0 if ok with valid *actwrite, -1 on error conditions
  */
-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);
 
 /*
  * 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/README b/test/fs/README
new file mode 100644
index 0000000..6d900ef
--- /dev/null
+++ b/test/fs/README
@@ -0,0 +1,4 @@
+How to run the test-fs.sh script.
+---------------------------------
+
+1. Invoke script as: test/fs/test-fs.sh from the u-boot base directory.
diff --git a/test/fs/fs-test.sh b/test/fs/fs-test.sh
new file mode 100755
index 0000000..506dbd6
--- /dev/null
+++ b/test/fs/fs-test.sh
@@ -0,0 +1,462 @@
+#!/bin/bash
+# (C) Copyright 2014 Suriyan Ramasami
+#
+#  SPDX-License-Identifier:    GPL-2.0+
+#
+
+# Check if the pre-requisite binaries exist. If not inform and exit.
+PREREQ_BINS="md5sum mkfs.ext4 mkfs.vfat mount umount dd fallocate mkdir"
+
+for prereq in $PREREQ_BINS; do
+       if [ ! -x `which $prereq` ]; then
+               echo "Missing $prereq binary. Exiting!"
+               exit
+       fi
+       if [ ! -c /dev/urandom ]; then
+               echo "Missing character special /dev/urandom. Exiting!"
+               exit
+       fi
+done
+
+# All generated output files from this test will be in $OUT_DIR
+# Hence everything is sandboxed.
+OUT_DIR="sandbox/test/fs"
+mkdir -p $OUT_DIR
+
+# If 1st param is "clean", then clean out the generated files and exit
+if [ "$1" = "clean" ]; then
+       rm -rf "$OUT_DIR"
+       echo "Cleaned up generated files. Exiting"
+       exit
+fi
+
+# Generate sandbox u-boot - gleaned from /test/dm/test-dm.sh
+unset CROSS_COMPILE
+NUM_CPUS=$(cat /proc/cpuinfo |grep -c processor)
+make O=sandbox sandbox_config
+make O=sandbox -s -j${NUM_CPUS}
+
+# Location of generated sandbox u-boot
+UBOOT="./sandbox/u-boot"
+
+# Check if UBOOT exists
+if [ ! -x "$UBOOT" ]; then
+       echo "$UBOOT does not exist or is not executable"
+       echo "Build error?"
+       echo "Please run this script as ./test/fs/`basename $0`"
+       exit
+fi
+
+# Our mount directory will be in the sandbox as ./sandbox/mnt
+MOUNT_DIR="${OUT_DIR}/mnt"
+
+# The file system image we create will have the $IMG prefix.
+IMG="${OUT_DIR}/3GB"
+
+# $SMALL_FILE is the name of the 1MB file in the file system image
+SMALL_FILE="1MB.file"
+
+# $BIG_FILE is the name of the 2.5GB file in the file system image
+BIG_FILE="2.5GB.file"
+
+# $MD5_FILE will have the expected md5s when we do the test
+# They shall have a suffix which represents their file system (ext4/vfat)
+MD5_FILE="${OUT_DIR}/md5s.list"
+
+# $OUT shall be the prefix of the test output. Their suffix will be .out
+OUT="${OUT_DIR}/fs-test"
+
+# Initialize TESTS and TESTS_INDEX for results
+TESTS=""
+TESTS_INDEX=0
+
+# Clean out all generated files other than the file system images
+# We save time by not deleting and recreating the file system images
+rm -f ${MD5_FILE}.* ${OUT}.*
+
+# Full Path of the 1 MB file that shall be created in the fs image.
+MB1="${MOUNT_DIR}/${SMALL_FILE}"
+GB2p5="${MOUNT_DIR}/${BIG_FILE}"
+
+# ************************
+# * Functions start here *
+# ************************
+
+# 1st parameter is the name of the image file to be created
+# 2nd parameter is the filesystem - vfat ext4 etc
+function create_image() {
+
+       # Create image if not already present - saves time, while debugging
+       if [ ! -f "$1" ]; then
+               fallocate -l 3G "$1" &> /dev/null
+               if [ "$2" = "ext4" ]; then
+                       mkfs."$2" "$1" &> /dev/null <<EOF
+y
+EOF
+               else
+                       mkfs."$2" "$1" &> /dev/null
+               fi
+       fi
+}
+
+# 1st parameter is the FS type: vfat/ext4
+# 2nd parameter is the name of small file
+# Returns filename which can be used for vfat or ext4 for writing
+function fname_for_write() {
+
+       case $1 in
+               ext4)
+                       # ext4 needs absolute path name of file
+                       echo /$2
+                       ;;
+
+               *)
+                       echo $2
+                       ;;
+       esac
+}
+
+# 1st parameter is image file
+# 2nd parameter is file system type - vfat/ext4
+# 3rd parameter is name of small file
+# 4th parameter is name of big file
+# 5th parameter is fs or nonfs - to dictate generic fs commands or
+# otherwise
+# UBOOT is set in env
+function test_image() {
+
+       # Convert vfat to fat so that commands issued are correct.
+       if [ "$2" = "vfat" ]; then
+               PREFIX="fat"
+       else
+               PREFIX="$2"
+       fi
+
+       if [ "$5" = "fs" ]; then
+               PREFIX=""
+       fi
+
+       WRITE_FILE=`fname_for_write $2 $3`
+
+       # 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
+
+       $UBOOT << EOF
+
+sb bind 0 "$1"
+${PREFIX}ls host 0:0 /
+#
+# 1MB is 0x0010 0000
+${PREFIX}size host 0:0 $3
+printenv filesize
+setenv filesize
+
+# 2.5GB (1024*1024*2500) is 0x9C40 0000
+${PREFIX}size host 0:0 $4
+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 $3
+printenv filesize
+md5sum 0x01000008 \$filesize
+setenv filesize
+
+# First 1MB of big file
+${PREFIX}load host 0:0 0x01000008 $4 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 $4 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 $4 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 $4 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 $4 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 $4 0x00200000 0x9C300000
+printenv filesize
+#
+
+# Read 1MB from small file
+${PREFIX}load host 0:0 0x01000008 $3
+# Write it back to test the writes
+${PREFIX}write host 0:0 0x01000008 $WRITE_FILE \$filesize
+mw.b 0x01000008 00 100
+${PREFIX}load host 0:0 0x01000008 $WRITE_FILE
+md5sum 0x01000008 \$filesize
+setenv filesize
+#
+reset
+
+EOF
+}
+
+# 1st argument is the name of the image file.
+# 2nd argument is the file where we generate the md5s of the files
+# generated with the appropriate start and length that we use to test.
+# It creates the necessary files in the image to test.
+# $GB2p5 is the path of the big file (2.5 GB)
+# $MB1 is the path of the small file (1 MB)
+# $MOUNT_DIR is the path we can use to mount the image file.
+function create_files() {
+
+       # Mount the image so we can populate it.
+       mkdir -p "$MOUNT_DIR"
+       sudo mount -o loop "$1" "$MOUNT_DIR"
+
+       # Create 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.
+       if [ ! -f "${GB2p5}" ]; then
+               sudo dd if=/dev/urandom of="${GB2p5}" bs=1M count=1 \
+                       &> /dev/null
+               sudo dd if=/dev/urandom of="${GB2p5}" bs=1M count=2 seek=2047 \
+                       &> /dev/null
+               sudo dd if=/dev/urandom of="${GB2p5}" bs=1M count=1 seek=2499 \
+                       &> /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 \
+                       &> /dev/null
+       fi
+
+       # Delete the small file which possibly is written as part of a
+       # previous test.
+       sudo rm -f "${MOUNT_DIR}/*.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 > "$2"
+
+       # 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 >> "$2"
+
+       # One from end of file.
+       dd if="${GB2p5}" bs=1M skip=2499 count=1 \
+               2> /dev/null | md5sum >> "$2"
+
+       # One from the last 1MB chunk of 2GB
+       dd if="${GB2p5}" bs=1M skip=2047 count=1 \
+               2> /dev/null | md5sum >> "$2"
+
+       # One from the start 1MB chunk from 2GB
+       dd if="${GB2p5}" bs=1M skip=2048 count=1 \
+               2> /dev/null | md5sum >> "$2"
+
+       # One 1MB chunk crossing the 2GB boundary
+       dd if="${GB2p5}" bs=512K skip=4095 count=2 \
+               2> /dev/null | md5sum >> "$2"
+
+       sync
+       sudo umount "$MOUNT_DIR"
+       rmdir "$MOUNT_DIR"
+}
+
+# 1st parameter is the text to print
+# if $? is 0 its a pass, else a fail
+# As a side effect it shall update env variable PASS and FAIL
+function pass_fail() {
+
+       if [ $? -eq 0 ]; then
+               echo pass - "$1"
+               PASS=$((PASS + 1))
+       else
+               echo FAIL - "$1"
+               FAIL=$((FAIL + 1))
+       fi
+}
+
+# 1st parameter is the string which leads to an md5 generation
+# 2nd parameter is the file we grep, for that string
+# 3rd parameter is the name of the file which has md5s in it
+# 4th parameter is the line # in the md5 file that we match it against
+# This function checks if the md5 of the file in the sandbox matches
+# that calculated while generating the file
+check_md5() {
+
+       # md5sum in u-boot has output of form:
+       # md5 for 01000008 ... 01100007 ==> <md5>
+       # the 7th field is the actual md5
+       md5_src=`grep -A6 "$1" "$2" | grep "md5 for"`
+       md5_src=($md5_src)
+       md5_src=${md5_src[6]}
+
+       # The md5 list, each line is of the form:
+       # - <md5>
+       # the 2nd field is the actual md5
+       md5_dst=`sed -n $4p $3`
+       md5_dst=($md5_dst)
+       md5_dst=${md5_dst[0]}
+
+       # For a pass they should match.
+       [ "$md5_src" = "$md5_dst" ]
+       pass_fail "$1"
+}
+
+# 1st parameter is the name of the output file to check
+# 2nd parameter is the name of the file containing the md5 expected
+# 3rd parameter is the name of the small file
+# 4th parameter is the name of the big file
+# 5th paramter is the name of the written file
+# This function checks the output file for correct results.
+function check_results() {
+
+       echo "** Start $1"
+
+       PASS=0
+       FAIL=0
+
+       # Check if the ls is showing correct results for 2.5 gb file
+       grep -A6 "ls host 0:0" "$1" | grep 2621440000 | grep -iq "$4"
+       pass_fail "ls host 0:0 of $4"
+
+       # Check if the ls is showing correct results for 1 mb file
+       grep -A6 "ls host 0:0" "$1" | grep 1048576 | grep -iq "$3"
+       pass_fail "ls host 0:0 of $3"
+
+       # Check size command on 1MB.file
+       grep -A3 "size host 0:0 $3" "$1" | grep -q "filesize=100000"
+       pass_fail "size host 0:0 $3"
+
+       # Check size command on 2.5GB.file
+       grep -A3 "size host 0:0 $4" "$1" \
+               | grep -q "filesize=9c400000"
+       pass_fail "size host 0:0 $4"
+
+       # Check read full mb of 1MB.file
+       grep -A6 "load host 0:0 0x01000008 $3" "$1" | \
+               grep -q "filesize=100000"
+       pass_fail "load host 0:0 0x01000008 $3 size"
+       check_md5 "load host 0:0 0x01000008 $3" "$1" "$2" 1
+
+       # Check first mb of 2.5GB.file
+       grep -A6 "load host 0:0 0x01000008 $4 0x00100000 0x0" \
+               "$1" | grep -q "filesize=100000"
+       pass_fail "load host 0:0 0x01000008 $4 0x00100000 0x0 size"
+       check_md5 "load host 0:0 0x01000008 $4 0x00100000 0x0" \
+               "$1" "$2" 2
+
+       # Check last mb of 2.5GB.file
+       grep -A6 "load host 0:0 0x01000008 $4 0x00100000 0x9C300000" \
+               "$1" | grep -q "filesize=100000"
+       pass_fail "load host 0:0 0x01000008 $4 0x00100000 0x9C300000 size"
+       check_md5 "load host 0:0 0x01000008 $4 0x00100000 0x9C300000" \
+               "$1" "$2" 3
+
+       # Check last 1mb chunk of 2gb from 2.5GB file
+       grep -A6 "load host 0:0 0x01000008 $4 0x00100000 0x7FF00000" \
+               "$1" | grep -q "filesize=100000"
+       pass_fail "load host 0:0 0x01000008 $4 0x00100000 0x7FF00000 size"
+       check_md5 "load host 0:0 0x01000008 $4 0x00100000 0x7FF00000" \
+               "$1" "$2" 4
+
+       # Check first 1mb chunk after 2gb from 2.5GB file
+       grep -A6 "load host 0:0 0x01000008 $4 0x00100000 0x80000000" \
+               "$1" | grep -q "filesize=100000"
+       pass_fail "load host 0:0 0x01000008 $4 0x00100000 0x80000000 size"
+       check_md5 "load host 0:0 0x01000008 $4 0x00100000 0x80000000" \
+               "$1" "$2" 5
+
+       # Check 1mb chunk crossing the 2gb boundary from 2.5GB file
+       grep -A6 "load host 0:0 0x01000008 $4 0x00100000 0x7FF80000" \
+               "$1" | grep -q "filesize=100000"
+       pass_fail "load host 0:0 0x01000008 $4 0x00100000 0x7FF80000 size"
+       check_md5 "load host 0:0 0x01000008 $4 0x00100000 0x7FF80000" \
+               "$1" "$2" 6
+
+       # Check 2mb chunk from the last 1MB of 2.5GB file - generic failure case
+       grep -A6 "load host 0:0 0x01000008 $4 0x00200000 0x9C300000" \
+               "$1" | grep -q 'Error: "filesize" not defined'
+       pass_fail "load host 0:0 0x01000008 $4 0x00200000 0x9C300000 size"
+
+       # Check 1mb chunk write
+       grep -A3 "write host 0:0 0x01000008 $5" \
+               "$1" | egrep -q '1048576 bytes written|update journal'
+       pass_fail "write host 0:0 0x01000008 $5"
+       check_md5 "load host 0:0 0x01000008 $5" \
+               "$1" "$2" 1
+       echo "** End $1"
+}
+
+# ********************
+# * End of functions *
+# ********************
+
+# Track TOTAL_FAIL and TOTAL_PASS
+TOTAL_FAIL=0
+TOTAL_PASS=0
+
+# In each loop, for a given file system image, we test both the
+# fs command, like load/size/write and the file system specific command
+# like: ext4load/ext4size/ext4write
+for fs in ext4 vfat; do
+
+       echo "Creating $fs image if not already present."
+       IMAGE=${IMG}.${fs}.img
+       create_image $IMAGE $fs
+
+       echo "Creating files in $fs image if not already present."
+       MD5_FILE_FS="${MD5_FILE}.${fs}"
+       create_files $IMAGE $MD5_FILE_FS
+
+       OUT_FILE="${OUT}.${fs}.out"
+       test_image $IMAGE $fs $SMALL_FILE $BIG_FILE nonfs \
+               > $OUT_FILE
+       check_results $OUT_FILE $MD5_FILE_FS $SMALL_FILE $BIG_FILE \
+               $WRITE_FILE
+       echo "Summary: PASS: $PASS FAIL: $FAIL"
+       TOTAL_FAIL=$((TOTAL_FAIL + FAIL))
+       TOTAL_PASS=$((TOTAL_PASS + PASS))
+
+       echo "Creating files in $fs image if not already present."
+       create_files $IMAGE $MD5_FILE_FS
+
+       OUT_FILE="${OUT}.fs.${fs}.out"
+       test_image $IMAGE $fs $SMALL_FILE $BIG_FILE fs \
+               > ${OUT_FILE}
+       check_results $OUT_FILE $MD5_FILE_FS $SMALL_FILE $BIG_FILE \
+               $WRITE_FILE
+       echo "Summary: PASS: $PASS FAIL: $FAIL"
+       echo "--------------------------------------------"
+       TOTAL_FAIL=$((TOTAL_FAIL + FAIL))
+       TOTAL_PASS=$((TOTAL_PASS + PASS))
+done
+
+echo "Total Summary: TOTAL PASS: $TOTAL_PASS TOTAL FAIL: $TOTAL_FAIL"
+echo "--------------------------------------------"
+if [ $TOTAL_FAIL -eq 0 ]; then
+       echo "PASSED"
+       exit 0
+else
+       echo "FAILED"
+       exit 1
+fi
-- 
1.9.1

_______________________________________________
U-Boot mailing list
[email protected]
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to