fs: API changes enabling extra parameter to return size of type loff_t

The sandbox/ext4/fat/generic fs commands do not gracefully deal with files
greater than 2GB. Negative values are returned in such cases.

To handle 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 <suriyan.r@gmail.com>
Acked-by: Simon Glass <sjg@chromium.org>
[trini: Update board/gdsys/p1022/controlcenterd-id.c,
drivers/fpga/zynqpl.c for changes]
Signed-off-by: Tom Rini <trini@ti.com>
diff --git a/fs/fs.c b/fs/fs.c
index e4ad6bc..3da7860 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -47,19 +47,21 @@
 	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;
 }
@@ -88,9 +90,11 @@
 		     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);
 	int (*uuid)(char *uuid_str);
 };
@@ -106,7 +110,11 @@
 		.exists = fat_exists,
 		.size = fat_size,
 		.read = fat_read_file,
+#ifdef CONFIG_FAT_WRITE
+		.write = file_fat_write,
+#else
 		.write = fs_write_unsupported,
+#endif
 		.uuid = fs_uuid_unsupported,
 	},
 #endif
@@ -120,7 +128,11 @@
 		.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
 		.uuid = ext4fs_uuid,
 	},
 #endif
@@ -251,20 +263,21 @@
 	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;
@@ -275,11 +288,11 @@
 	 * 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;
 	}
@@ -288,17 +301,18 @@
 	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;
 	}
@@ -310,7 +324,7 @@
 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;
@@ -318,8 +332,7 @@
 	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);
@@ -333,9 +346,10 @@
 	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;
 
@@ -377,12 +391,12 @@
 		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");
@@ -426,9 +440,10 @@
 {
 	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)
@@ -437,8 +452,8 @@
 	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);
@@ -446,12 +461,12 @@
 		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");