Skip to contentSkip to conversation

FAT: Make it possible to read from any file position

PATCH Superseded Benoît Thébaudeau 5 participants 16 messages Jul 19, 2012 – Sep 28, 2012 VFAT/FAT/msdos filesystem

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

PATCH 7/7 FAT: Make it possible to read from any file position

When storage devices contain files larger than the embedded RAM, it is useful to be able to read these files by chunks, e.g. for a software update to the embedded NAND Flash from an external storage device (USB stick, SD card, etc.).

Hence, this patch makes it possible by adding a new FAT API to read files from a given position.

---
 .../fs/fat/fat.c                                   |   90 ++++++++++++++++----
 1 file changed, 72 insertions(+), 18 deletions(-)
fs/fat/fat.c +72 -18
index 8ac8b85..709a5eb 100644
@@ -329,13 +329,16 @@ get_cluster (fsdata *mydata, __u32 clustnum, __u8 *buffer,
 }
 
 /*
- * Read at most 'maxsize' bytes from the file associated with 'dentptr'
+ * 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.
  */
+__u8 get_contents_vfatname_block[MAX_CLUSTSIZE]
+	__aligned(ARCH_DMA_MINALIGN);
+
 static long
-get_contents (fsdata *mydata, dir_entry *dentptr, __u8 *buffer,
-	      unsigned long maxsize)
+get_contents (fsdata *mydata, dir_entry *dentptr, unsigned long pos,
+	      __u8 *buffer, unsigned long maxsize)
 {
 	unsigned long filesize = FAT2CPU32(dentptr->size), gotsize = 0;
 	unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
@@ -345,12 +348,59 @@ get_contents (fsdata *mydata, dir_entry *dentptr, __u8 *buffer,
 
 	debug("Filesize: %ld bytes\n", filesize);
 
-	if (maxsize > 0 && filesize > maxsize)
-		filesize = maxsize;
+	if (pos >= filesize) {
+		debug("Read position past EOF: %lu\n", pos);
+		return gotsize;
+	}
+
+	if (maxsize > 0 && filesize > pos + maxsize)
+		filesize = pos + maxsize;
 
 	debug("%ld bytes\n", filesize);
 
 	actsize = bytesperclust;
+
+	/* go to cluster at pos */
+	while (actsize <= pos) {
+		curclust = get_fatent(mydata, curclust);
+		if (CHECK_CLUST(curclust, mydata->fatsize)) {
+			debug("curclust: 0x%x\n", curclust);
+			debug("Invalid FAT entry\n");
+			return gotsize;
+		}
+		actsize += bytesperclust;
+	}
+
+	/* actsize > pos */
+	actsize -= bytesperclust;
+	filesize -= actsize;
+	pos -= actsize;
+
+	/* align to beginning of next cluster if any */
+	if (pos) {
+		actsize = min(filesize, bytesperclust);
+		if (get_cluster(mydata, curclust, get_contents_vfatname_block,
+				(int)actsize) != 0) {
+			printf("Error reading cluster\n");
+			return -1;
+		}
+		filesize -= actsize;
+		actsize -= pos;
+		memcpy(buffer, get_contents_vfatname_block + pos, actsize);
+		gotsize += actsize;
+		if (!filesize)
+			return gotsize;
+		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;
+		}
+	}
+
+	actsize = bytesperclust;
 	endclust = curclust;
 
 	do {
@@ -434,9 +484,6 @@ static int slot2str (dir_slot *slotptr, char *l_name, int *idx)
  * into 'retdent'
  * Return 0 on success, -1 otherwise.
  */
-__u8 get_vfatname_block[MAX_CLUSTSIZE]
-	__aligned(ARCH_DMA_MINALIGN);
-
 static int
 get_vfatname (fsdata *mydata, int curclust, __u8 *cluster,
 	      dir_entry *retdent, char *l_name)
@@ -475,13 +522,13 @@ get_vfatname (fsdata *mydata, int curclust, __u8 *cluster,
 			return -1;
 		}
 
-		if (get_cluster(mydata, curclust, get_vfatname_block,
+		if (get_cluster(mydata, curclust, get_contents_vfatname_block,
 				mydata->clust_size * mydata->sect_size) != 0) {
 			debug("Error: reading directory block\n");
 			return -1;
 		}
 
-		slotptr2 = (dir_slot *)get_vfatname_block;
+		slotptr2 = (dir_slot *)get_contents_vfatname_block;
 		while (counter > 0) {
 			if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK)
 			    & 0xff) != counter)
@@ -492,7 +539,7 @@ get_vfatname (fsdata *mydata, int curclust, __u8 *cluster,
 
 		/* Save the real directory entry */
 		realdent = (dir_entry *)slotptr2;
-		while ((__u8 *)slotptr2 > get_vfatname_block) {
+		while ((__u8 *)slotptr2 > get_contents_vfatname_block) {
 			slotptr2--;
 			slot2str(slotptr2, l_name, &idx);
 		}
@@ -771,12 +818,12 @@ exit:
 	return ret;
 }
 
-__u8 do_fat_read_block[MAX_CLUSTSIZE]
+__u8 do_fat_read_at_block[MAX_CLUSTSIZE]
 	__aligned(ARCH_DMA_MINALIGN);
 
 long
-do_fat_read (const char *filename, void *buffer, unsigned long maxsize,
-	     int dols)
+do_fat_read_at (const char *filename, unsigned long pos, void *buffer,
+		unsigned long maxsize, int dols)
 {
 	char fnamecopy[2048];
 	boot_sector bs;
@@ -890,12 +937,12 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,
 					(mydata->fatsize == 32) ?
 					(mydata->clust_size) :
 					PREFETCH_BLOCKS,
-					do_fat_read_block) < 0) {
+					do_fat_read_at_block) < 0) {
 				debug("Error: reading rootdir block\n");
 				goto exit;
 			}
 
-			dentptr = (dir_entry *) do_fat_read_block;
+			dentptr = (dir_entry *) do_fat_read_at_block;
 		}
 
 		for (i = 0; i < DIRENTSPERBLOCK; i++) {
@@ -915,7 +962,7 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,
 
 					get_vfatname(mydata,
 						     root_cluster,
-						     do_fat_read_block,
+						     do_fat_read_at_block,
 						     dentptr, l_name);
 
 					if (dols == LS_ROOT) {
@@ -1118,7 +1165,7 @@ rootdir_done:
 			subname = nextname;
 	}
 
-	ret = get_contents(mydata, dentptr, buffer, maxsize);
+	ret = get_contents(mydata, dentptr, pos, buffer, maxsize);
 	debug("Size: %d, got: %ld\n", FAT2CPU32(dentptr->size), ret);
 
 exit:
@@ -1126,6 +1173,13 @@ exit:
 	return ret;
 }
 
+long
+do_fat_read (const char *filename, void *buffer, unsigned long maxsize,
+	     int dols)
+{
+	return do_fat_read_at(filename, 0, buffer, maxsize, dols);
+}
+
 int file_fat_detectfs (void)
 {
 	boot_sector bs;
#1 lore raw

PATCH 7/7 FAT: Make it possible to read from any file position

fs/fat/fat.c get_cluster (fsdata *mydata, __u32 clustnum, __u8 *buffer, · line 337

Quoted 5 lines · On Thursday 19 July 2012 18:03:06 Beno?t Th?baudeau wrote:
fs/fat/fat.c +2 -0
 
+__u8 get_contents_vfatname_block[MAX_CLUSTSIZE]
+	__aligned(ARCH_DMA_MINALIGN);

is there any reason for this to be exported ? could you mark it static ?

fs/fat/fat.c get_cluster (fsdata *mydata, __u32 clustnum, __u8 *buffer, · line 340

Quoted 4 lines

static long

fs/fat/fat.c +1 -2
-get_contents (fsdata *mydata, dir_entry *dentptr, __u8 *buffer,
-	      unsigned long maxsize)
+get_contents (fsdata *mydata, dir_entry *dentptr, unsigned long pos,

delete the space before the "("

fs/fat/fat.c exit: · line 825

Quoted 4 lines

long

fs/fat/fat.c +1 -2
-do_fat_read (const char *filename, void *buffer, unsigned long maxsize,
-	     int dols)
+do_fat_read_at (const char *filename, unsigned long pos, void *buffer,

delete the space before the "("

fs/fat/fat.c exit: · line 1177

Quoted 2 lines
fs/fat/fat.c +2 -0
+long
+do_fat_read (const char *filename, void *buffer, unsigned long maxsize,

no spaces before that "("
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120719/ced33472/attachment.pgp>

#2 lore raw

PATCH 7/7 FAT: Make it possible to read from any file position

Quoted 9 lines · On Friday 20 July 2012 00:44:52 Mike Frysinger wrote:

fs/fat/fat.c get_cluster (fsdata *mydata, __u32 clustnum, __u8 *buffer, · line 337

Quoted 5 lines · On Thursday 19 July 2012 18:03:06 Beno?t Th?baudeau wrote:
fs/fat/fat.c +2 -0
 
+__u8 get_contents_vfatname_block[MAX_CLUSTSIZE]
+	__aligned(ARCH_DMA_MINALIGN);

is there any reason for this to be exported ? could you mark it static ?

I'll do that. There are probably other variables in fat.c missing static, so I'll do a dedicated patch before this series. That will shift the patch numbers. How should I repost the new version of the series? Should I keep the message ID of each patch even if the numbering changes, or should I post a v2 completely separately from v1?

Quoted 17 lines
Quoted 5 lines

static long

fs/fat/fat.c +1 -2
-get_contents (fsdata *mydata, dir_entry *dentptr, __u8 *buffer,
-	      unsigned long maxsize)
+get_contents (fsdata *mydata, dir_entry *dentptr, unsigned long

pos,

delete the space before the "("

Quoted 6 lines

long
-do_fat_read (const char *filename, void *buffer, unsigned long maxsize,

fs/fat/fat.c +1 -1
-	     int dols)
+do_fat_read_at (const char *filename, unsigned long pos, void

*buffer,

delete the space before the "("

Quoted 5 lines
Quoted 3 lines
fs/fat/fat.c +2 -0
+long
+do_fat_read (const char *filename, void *buffer, unsigned long

maxsize,

no spaces before that "("

I'll add a cosmetic patch for that in a prequel.

Regards,
Beno?t

#3 lore raw

PATCH 7/7 FAT: Make it possible to read from any file position

Quoted 11 lines · On Thursday 19 July 2012 19:17:31 Beno?t Th?baudeau wrote:
Quoted 9 lines · On Friday 20 July 2012 00:44:52 Mike Frysinger wrote:

fs/fat/fat.c get_cluster (fsdata *mydata, __u32 clustnum, __u8 *buffer, · line 337

Quoted 5 lines · On Thursday 19 July 2012 18:03:06 Beno?t Th?baudeau wrote:
fs/fat/fat.c +2 -0
 
+__u8 get_contents_vfatname_block[MAX_CLUSTSIZE]
+	__aligned(ARCH_DMA_MINALIGN);

is there any reason for this to be exported ? could you mark it static ?

Quoted 5 lines

I'll do that. There are probably other variables in fat.c missing static, so I'll do a dedicated patch before this series. That will shift the patch numbers. How should I repost the new version of the series? Should I keep the message ID of each patch even if the numbering changes, or should I post a v2 completely separately from v1?

it's easier on everyone to do this. you might want to look at tools/patman/ as a way for managing the review process.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120719/d0029746/attachment.pgp>

#4 lore raw

PATCH v2 8/8 FAT: Make it possible to read from any file position

When storage devices contain files larger than the embedded RAM, it is useful to be able to read these files by chunks, e.g. for a software update to the embedded NAND Flash from an external storage device (USB stick, SD card, etc.).

Hence, this patch makes it possible by adding a new FAT API to read files from a given position.

---
Changes for v2:
- Patch renumbering because of the new v2 1/8.
- Possible code style changes due to the new v2 1/8.
- Add missing vairable renaming to fat_write.c.

 .../fs/fat/fat.c                                   |   88 ++++++++++++++++----
 .../fs/fat/fat_write.c                             |   18 ++--
 2 files changed, 80 insertions(+), 26 deletions(-)
fs/fat/fat.c +71 -17
index 19f6a8c..8c94b28 100644
@@ -328,13 +328,16 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size)
 }
 
 /*
- * Read at most 'maxsize' bytes from the file associated with 'dentptr'
+ * 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.
  */
+__u8 get_contents_vfatname_block[MAX_CLUSTSIZE]
+	__aligned(ARCH_DMA_MINALIGN);
+
 static long
-get_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer,
-	     unsigned long maxsize)
+get_contents(fsdata *mydata, dir_entry *dentptr, unsigned long pos,
+	     __u8 *buffer, unsigned long maxsize)
 {
 	unsigned long filesize = FAT2CPU32(dentptr->size), gotsize = 0;
 	unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
@@ -344,12 +347,59 @@ get_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer,
 
 	debug("Filesize: %ld bytes\n", filesize);
 
-	if (maxsize > 0 && filesize > maxsize)
-		filesize = maxsize;
+	if (pos >= filesize) {
+		debug("Read position past EOF: %lu\n", pos);
+		return gotsize;
+	}
+
+	if (maxsize > 0 && filesize > pos + maxsize)
+		filesize = pos + maxsize;
 
 	debug("%ld bytes\n", filesize);
 
 	actsize = bytesperclust;
+
+	/* go to cluster at pos */
+	while (actsize <= pos) {
+		curclust = get_fatent(mydata, curclust);
+		if (CHECK_CLUST(curclust, mydata->fatsize)) {
+			debug("curclust: 0x%x\n", curclust);
+			debug("Invalid FAT entry\n");
+			return gotsize;
+		}
+		actsize += bytesperclust;
+	}
+
+	/* actsize > pos */
+	actsize -= bytesperclust;
+	filesize -= actsize;
+	pos -= actsize;
+
+	/* align to beginning of next cluster if any */
+	if (pos) {
+		actsize = min(filesize, bytesperclust);
+		if (get_cluster(mydata, curclust, get_contents_vfatname_block,
+				(int)actsize) != 0) {
+			printf("Error reading cluster\n");
+			return -1;
+		}
+		filesize -= actsize;
+		actsize -= pos;
+		memcpy(buffer, get_contents_vfatname_block + pos, actsize);
+		gotsize += actsize;
+		if (!filesize)
+			return gotsize;
+		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;
+		}
+	}
+
+	actsize = bytesperclust;
 	endclust = curclust;
 
 	do {
@@ -433,9 +483,6 @@ static int slot2str(dir_slot *slotptr, char *l_name, int *idx)
  * into 'retdent'
  * Return 0 on success, -1 otherwise.
  */
-__u8 get_vfatname_block[MAX_CLUSTSIZE]
-	__aligned(ARCH_DMA_MINALIGN);
-
 static int
 get_vfatname(fsdata *mydata, int curclust, __u8 *cluster,
 	     dir_entry *retdent, char *l_name)
@@ -474,13 +521,13 @@ get_vfatname(fsdata *mydata, int curclust, __u8 *cluster,
 			return -1;
 		}
 
-		if (get_cluster(mydata, curclust, get_vfatname_block,
+		if (get_cluster(mydata, curclust, get_contents_vfatname_block,
 				mydata->clust_size * mydata->sect_size) != 0) {
 			debug("Error: reading directory block\n");
 			return -1;
 		}
 
-		slotptr2 = (dir_slot *)get_vfatname_block;
+		slotptr2 = (dir_slot *)get_contents_vfatname_block;
 		while (counter > 0) {
 			if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK)
 			    & 0xff) != counter)
@@ -491,7 +538,7 @@ get_vfatname(fsdata *mydata, int curclust, __u8 *cluster,
 
 		/* Save the real directory entry */
 		realdent = (dir_entry *)slotptr2;
-		while ((__u8 *)slotptr2 > get_vfatname_block) {
+		while ((__u8 *)slotptr2 > get_contents_vfatname_block) {
 			slotptr2--;
 			slot2str(slotptr2, l_name, &idx);
 		}
@@ -770,11 +817,12 @@ exit:
 	return ret;
 }
 
-__u8 do_fat_read_block[MAX_CLUSTSIZE]
+__u8 do_fat_read_at_block[MAX_CLUSTSIZE]
 	__aligned(ARCH_DMA_MINALIGN);
 
 long
-do_fat_read(const char *filename, void *buffer, unsigned long maxsize, int dols)
+do_fat_read_at(const char *filename, unsigned long pos, void *buffer,
+	       unsigned long maxsize, int dols)
 {
 	char fnamecopy[2048];
 	boot_sector bs;
@@ -888,12 +936,12 @@ do_fat_read(const char *filename, void *buffer, unsigned long maxsize, int dols)
 					(mydata->fatsize == 32) ?
 					(mydata->clust_size) :
 					PREFETCH_BLOCKS,
-					do_fat_read_block) < 0) {
+					do_fat_read_at_block) < 0) {
 				debug("Error: reading rootdir block\n");
 				goto exit;
 			}
 
-			dentptr = (dir_entry *) do_fat_read_block;
+			dentptr = (dir_entry *) do_fat_read_at_block;
 		}
 
 		for (i = 0; i < DIRENTSPERBLOCK; i++) {
@@ -913,7 +961,7 @@ do_fat_read(const char *filename, void *buffer, unsigned long maxsize, int dols)
 
 					get_vfatname(mydata,
 						     root_cluster,
-						     do_fat_read_block,
+						     do_fat_read_at_block,
 						     dentptr, l_name);
 
 					if (dols == LS_ROOT) {
@@ -1116,7 +1164,7 @@ rootdir_done:
 			subname = nextname;
 	}
 
-	ret = get_contents(mydata, dentptr, buffer, maxsize);
+	ret = get_contents(mydata, dentptr, pos, buffer, maxsize);
 	debug("Size: %d, got: %ld\n", FAT2CPU32(dentptr->size), ret);
 
 exit:
@@ -1124,6 +1172,12 @@ exit:
 	return ret;
 }
 
+long
+do_fat_read(const char *filename, void *buffer, unsigned long maxsize, int dols)
+{
+	return do_fat_read_at(filename, 0, buffer, maxsize, dols);
+}
+
 int file_fat_detectfs(void)
 {
 	boot_sector bs;
fs/fat/fat_write.c +9 -9
index a6181e7..5829adf 100644
@@ -328,7 +328,7 @@ static void flush_dir_table(fsdata *mydata, dir_entry **dentptr);
 static void
 fill_dir_slot(fsdata *mydata, dir_entry **dentptr, const char *l_name)
 {
-	dir_slot *slotptr = (dir_slot *)get_vfatname_block;
+	dir_slot *slotptr = (dir_slot *)get_contents_vfatname_block;
 	__u8 counter = 0, checksum;
 	int idx = 0, ret;
 	char s_name[16];
@@ -373,7 +373,7 @@ static __u32 dir_curclust;
  * a slot) into 'l_name'. If successful also copy the real directory entry
  * into 'retdent'
  * If additional adjacent cluster for directory entries is read into memory,
- * then 'get_vfatname_block' is copied into 'get_dentfromdir_block' and
+ * then 'get_contents_vfatname_block' is copied into 'get_dentfromdir_block' and
  * the location of the real directory entry is returned by 'retdent'
  * Return 0 on success, -1 otherwise.
  */
@@ -416,13 +416,13 @@ get_long_file_name(fsdata *mydata, int curclust, __u8 *cluster,
 
 		dir_curclust = curclust;
 
-		if (get_cluster(mydata, curclust, get_vfatname_block,
+		if (get_cluster(mydata, curclust, get_contents_vfatname_block,
 				mydata->clust_size * mydata->sect_size) != 0) {
 			debug("Error: reading directory block\n");
 			return -1;
 		}
 
-		slotptr2 = (dir_slot *)get_vfatname_block;
+		slotptr2 = (dir_slot *)get_contents_vfatname_block;
 		while (counter > 0) {
 			if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK)
 			    & 0xff) != counter)
@@ -433,7 +433,7 @@ get_long_file_name(fsdata *mydata, int curclust, __u8 *cluster,
 
 		/* Save the real directory entry */
 		realdent = (dir_entry *)slotptr2;
-		while ((__u8 *)slotptr2 > get_vfatname_block) {
+		while ((__u8 *)slotptr2 > get_contents_vfatname_block) {
 			slotptr2--;
 			slot2str(slotptr2, l_name, &idx);
 		}
@@ -459,9 +459,9 @@ get_long_file_name(fsdata *mydata, int curclust, __u8 *cluster,
 	*retdent = realdent;
 
 	if (slotptr2) {
-		memcpy(get_dentfromdir_block, get_vfatname_block,
+		memcpy(get_dentfromdir_block, get_contents_vfatname_block,
 			mydata->clust_size * mydata->sect_size);
-		cur_position = (__u8 *)realdent - get_vfatname_block;
+		cur_position = (__u8 *)realdent - get_contents_vfatname_block;
 		*retdent = (dir_entry *) &get_dentfromdir_block[cur_position];
 	}
 
@@ -980,11 +980,11 @@ static int do_fat_write(const char *filename, void *buffer,
 	if (disk_read(cursect,
 		(mydata->fatsize == 32) ?
 		(mydata->clust_size) :
-		PREFETCH_BLOCKS, do_fat_read_block) < 0) {
+		PREFETCH_BLOCKS, do_fat_read_at_block) < 0) {
 		debug("Error: reading rootdir block\n");
 		goto exit;
 	}
-	dentptr = (dir_entry *) do_fat_read_block;
+	dentptr = (dir_entry *) do_fat_read_at_block;
 
 	name_len = strlen(filename);
 	if (name_len >= VFAT_MAXLEN_BYTES)
#5 lore raw

PATCH v2 8/8 FAT: Make it possible to read from any file position

Dear Beno?t Th?baudeau,

Quoted 15 lines · In message <[email protected]> you…

When storage devices contain files larger than the embedded RAM, it is usef> ul to be able to read these files by chunks, e.g. for a software update to the embedded NAND Flash from an external storage device (USB stick, SD card, et> c.).

Hence, this patch makes it possible by adding a new FAT API to read files f> rom a given position.

---
Changes for v2:
- Patch renumbering because of the new v2 1/8.
- Possible code style changes due to the new v2 1/8.
- Add missing vairable renaming to fat_write.c.

Quoted 3 lines
 .../fs/fat/fat.c                                   |   88 ++++++++++++++++> ----
 .../fs/fat/fat_write.c                             |   18 ++--
 2 files changed, 80 insertions(+), 26 deletions(-)

I don't see any command line interface to actually use this code.

How would I put this to use?

Skipped for now.

Best regards,

Wolfgang Denk

Signature · 7 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"Obviously, a major malfunction has occurred."
              -- Steve Nesbitt, voice of Mission Control, January 28,
                 1986, as the shuttle Challenger exploded within view
                 of the grandstands.
#6 lore raw

PATCH v2 8/8 FAT: Make it possible to read from any file position

Dear Wolfgang Denk,

Quoted 24 lines · Wolfgang Denk

Dear Beno?t Th?baudeau,

In message <[email protected]> you

Quoted 19 lines · wrote:

When storage devices contain files larger than the embedded RAM, it is usef> ul to
be able to read these files by chunks, e.g. for a software update to the
embedded NAND Flash from an external storage device (USB stick, SD card, et> c.).

Hence, this patch makes it possible by adding a new FAT API to read files f> rom a
given position.

---
Changes for v2:
- Patch renumbering because of the new v2 1/8.
- Possible code style changes due to the new v2 1/8.
- Add missing vairable renaming to fat_write.c.

Quoted 8 lines
Quoted 4 lines
 .../fs/fat/fat.c                                   |   88
 ++++++++++++++++> ----
 .../fs/fat/fat_write.c                             |   18 ++--
 2 files changed, 80 insertions(+), 26 deletions(-)

I don't see any command line interface to actually use this code.

How would I put this to use?

Here is the current "fatload" command line interface:
fatload <interface> <dev[:part]> <addr> <filename> [bytes]

Do you prefer to change it to:
fatload <interface> <dev[:part]> <addr> <filename> [offset] [bytes]

or to have a new dedicated command, or something else?

Best regards,
Beno?t

#7 lore raw

PATCH v2 8/8 FAT: Make it possible to read from any file position

Quoted 36 lines · Beno??t Th??baudeau

Dear Wolfgang Denk,

Quoted 24 lines · Wolfgang Denk

Dear Beno??t Th??baudeau,

In message <[email protected]> you

Quoted 19 lines · wrote:

When storage devices contain files larger than the embedded RAM, it is usef> ul to
be able to read these files by chunks, e.g. for a software update to the
embedded NAND Flash from an external storage device (USB stick, SD card, et> c.).

Hence, this patch makes it possible by adding a new FAT API to read files f> rom a
given position.

---
Changes for v2:
- Patch renumbering because of the new v2 1/8.
- Possible code style changes due to the new v2 1/8.
- Add missing vairable renaming to fat_write.c.

Quoted 8 lines
Quoted 4 lines
 .../fs/fat/fat.c                                   |   88
 ++++++++++++++++> ----
 .../fs/fat/fat_write.c                             |   18 ++--
 2 files changed, 80 insertions(+), 26 deletions(-)

I don't see any command line interface to actually use this code.

How would I put this to use?

Quoted 7 lines

Here is the current "fatload" command line interface:
fatload <interface> <dev[:part]> <addr> <filename> [bytes]

Do you prefer to change it to:
fatload <interface> <dev[:part]> <addr> <filename> [offset] [bytes]

or to have a new dedicated command, or something else?

Lets go with:
fatload <interface> <dev[:part]> <addr> <filename> [bytes] [offset] and update the long help text to mention both bytes and offset and that offset requires bytes.

Signature · 8 lines
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120914/a2619e25/attachment.pgp>
#8 lore raw

PATCH v2 8/8 FAT: Make it possible to read from any file position

Quoted 49 lines · Tom Rini
Quoted 48 lines · Beno??t Th??baudeau

Dear Wolfgang Denk,

Quoted 29 lines · Wolfgang Denk

Dear Beno??t Th??baudeau,

In message <[email protected]> you

Quoted 24 lines · wrote:

When storage devices contain files larger than the embedded RAM, it
is usef> ul to
be able to read these files by chunks, e.g. for a software update
to the
embedded NAND Flash from an external storage device (USB stick, SD
card, et> c.).

Hence, this patch makes it possible by adding a new FAT API to read
files f> rom a
given position.

Signed-off-by: Beno??t Th??baudeau <[email protected]>
Cc: Wolfgang Denk <[email protected]>
---
Changes for v2:
- Patch renumbering because of the new v2 1/8.
- Possible code style changes due to the new v2 1/8.
- Add missing vairable renaming to fat_write.c.

Quoted 8 lines
Quoted 4 lines
 .../fs/fat/fat.c                                   |   88
 ++++++++++++++++> ----
 .../fs/fat/fat_write.c                             |   18 ++--
 2 files changed, 80 insertions(+), 26 deletions(-)

I don't see any command line interface to actually use this code.

How would I put this to use?

Here is the current "fatload" command line interface:
fatload <interface> <dev[:part]> <addr> <filename> [bytes]

Do you prefer to change it to:
fatload <interface> <dev[:part]> <addr> <filename> [offset] [bytes]

Quoted 7 lines
Quoted 1 line

or to have a new dedicated command, or something else?

Lets go with:
fatload <interface> <dev[:part]> <addr> <filename> [bytes] [offset] and
update the long help text to mention both bytes and offset and that offset requires bytes.

OK. Do you want that in an update of this patch or in a separate patch?

You're right: Having [bytes] before [offset] will avoid breaking the current users of this command. However, this has one drawback: fatls first has to be used to get the file size (with [offset] first, 0 could be easily used for offset to access [bytes]). Hence, still with [bytes] first, would you like to have some special bytes value (let's say -1 or any negative value) meaning "from offset to end of file"?

Best regards,
Beno?t

#9 lore raw

PATCH v2 8/8 FAT: Make it possible to read from any file position

Quoted 52 lines · Beno?t Th?baudeau
Quoted 51 lines · Tom Rini
Quoted 49 lines · Beno??t Th??baudeau

Dear Wolfgang Denk,

Quoted 29 lines · Wolfgang Denk

Dear Beno??t Th??baudeau,

In message <[email protected]> you

Quoted 24 lines · wrote:

When storage devices contain files larger than the embedded RAM, it
is usef> ul to
be able to read these files by chunks, e.g. for a software update
to the
embedded NAND Flash from an external storage device (USB stick, SD
card, et> c.).

Hence, this patch makes it possible by adding a new FAT API to read
files f> rom a
given position.

Signed-off-by: Beno??t Th??baudeau <[email protected]>
Cc: Wolfgang Denk <[email protected]>
---
Changes for v2:
- Patch renumbering because of the new v2 1/8.
- Possible code style changes due to the new v2 1/8.
- Add missing vairable renaming to fat_write.c.

Quoted 8 lines
Quoted 4 lines
 .../fs/fat/fat.c                                   |   88
 ++++++++++++++++> ----
 .../fs/fat/fat_write.c                             |   18 ++--
 2 files changed, 80 insertions(+), 26 deletions(-)

I don't see any command line interface to actually use this code.

How would I put this to use?

Here is the current "fatload" command line interface:
fatload <interface> <dev[:part]> <addr> <filename> [bytes]

Do you prefer to change it to:
fatload <interface> <dev[:part]> <addr> <filename> [offset] [bytes]

or to have a new dedicated command, or something else?

Quoted 7 lines
Quoted 5 lines

Lets go with:
fatload <interface> <dev[:part]> <addr> <filename> [bytes] [offset] and
update the long help text to mention both bytes and offset and that offset requires bytes.

OK. Do you want that in an update of this patch or in a separate patch?

New patch to replace this.

Quoted 6 lines

You're right: Having [bytes] before [offset] will avoid breaking the current users of this command. However, this has one drawback: fatls first has to be used to get the file size (with [offset] first, 0 could be easily used for offset to access [bytes]). Hence, still with [bytes] first, would you like to have some special bytes value (let's say -1 or any negative value) meaning "from offset to end of file"?

Lets go with -1 meaning until end of file since we don't have a good way today to determine total filesize.

Signature · 1 line
Tom
#10 lore raw

PATCH v2 8/8 FAT: Make it possible to read from any file position

Quoted 80 lines · Tom Rini
Quoted 62 lines · Beno?t Th?baudeau
Quoted 53 lines · Tom Rini
Quoted 42 lines · Beno??t Th??baudeau

Dear Wolfgang Denk,

Quoted 34 lines · Wolfgang Denk

Dear Beno??t Th??baudeau,

In message <[email protected]> you

Quoted 24 lines · wrote:

When storage devices contain files larger than the embedded RAM, it
is usef> ul to
be able to read these files by chunks, e.g. for a software update
to the
embedded NAND Flash from an external storage device (USB stick, SD
card, et> c.).

Hence, this patch makes it possible by adding a new FAT API to read
files f> rom a
given position.

Signed-off-by: Beno??t Th??baudeau <[email protected]>
Cc: Wolfgang Denk <[email protected]>
---
Changes for v2:
- Patch renumbering because of the new v2 1/8.
- Possible code style changes due to the new v2 1/8.
- Add missing vairable renaming to fat_write.c.

Quoted 4 lines
 .../fs/fat/fat.c                                   |   88
 ++++++++++++++++> ----
 .../fs/fat/fat_write.c                             |   18 ++--
 2 files changed, 80 insertions(+), 26 deletions(-)
Quoted 4 lines

I don't see any command line interface to actually use this code.

How would I put this to use?

Quoted 8 lines

Here is the current "fatload" command line interface:
fatload <interface> <dev[:part]> <addr> <filename> [bytes]

Do you prefer to change it to:
fatload <interface> <dev[:part]> <addr> <filename> [offset] [bytes]

or to have a new dedicated command, or something else?

Quoted 7 lines

Lets go with:
fatload <interface> <dev[:part]> <addr> <filename> [bytes] [offset]
and
update the long help text to mention both bytes and offset and that
offset requires bytes.

Quoted 2 lines

OK. Do you want that in an update of this patch or in a separate patch?

New patch to replace this.

Quoted 11 lines

You're right: Having [bytes] before [offset] will avoid breaking the current
users of this command. However, this has one drawback: fatls first has to be
used to get the file size (with [offset] first, 0 could be easily used for
offset to access [bytes]). Hence, still with [bytes] first, would you like to
have some special bytes value (let's say -1 or any negative value) meaning "from
offset to end of file"?

Quoted 3 lines

Lets go with -1 meaning until end of file since we don't have a good way
today to determine total filesize.

OK. I took 0 instead of -1 because 0 already had this behavior.

Done here:
http://patchwork.ozlabs.org/patch/184793/

Best regards,
Beno?t

#11 lore raw

PATCH v3 1/1 FAT: Make it possible to read from any file position

In reply to Benoît Thébaudeau

When storage devices contain files larger than the embedded RAM, it is useful to be able to read these files by chunks, e.g. for a software update to the embedded NAND Flash from an external storage device (USB stick, SD card, etc.).

Hence, this patch makes it possible by adding a new FAT API to read files from a given position. This patch also adds this feature to the fatload command.

---
Changes for v2:
- Add missing variable renaming to fat_write.c.
Changes for v3:
- Make this new feature available through the fatload command.

 .../common/cmd_fat.c                               |   25 +++--
 .../fs/fat/fat.c                                   |   98 ++++++++++++++++----
 .../fs/fat/fat_write.c                             |   18 ++--
 .../include/fat.h                                  |    2 +
 4 files changed, 105 insertions(+), 38 deletions(-)
common/cmd_fat.c +15 -10
index 559a16d..2e34c54 100644
@@ -37,7 +37,8 @@ int do_fat_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	long size;
 	unsigned long offset;
-	unsigned long count;
+	unsigned long count = 0;
+	unsigned long pos = 0;
 	char buf [12];
 	block_dev_desc_t *dev_desc=NULL;
 	int dev=0;
@@ -46,7 +47,7 @@ int do_fat_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 	if (argc < 5) {
 		printf( "usage: fatload <interface> <dev[:part]> "
-			"<addr> <filename> [bytes]\n");
+			"<addr> <filename> [bytes [pos]]\n");
 		return 1;
 	}
 
@@ -69,11 +70,11 @@ int do_fat_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		return 1;
 	}
 	offset = simple_strtoul(argv[3], NULL, 16);
-	if (argc == 6)
+	if (argc >= 6)
 		count = simple_strtoul(argv[5], NULL, 16);
-	else
-		count = 0;
-	size = file_fat_read(argv[4], (unsigned char *)offset, count);
+	if (argc >= 7)
+		pos = simple_strtoul(argv[6], NULL, 16);
+	size = file_fat_read_at(argv[4], pos, (unsigned char *)offset, count);
 
 	if(size==-1) {
 		printf("\n** Unable to read \"%s\" from %s %d:%d **\n",
@@ -91,11 +92,15 @@ int do_fat_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 
 U_BOOT_CMD(
-	fatload,	6,	0,	do_fat_fsload,
+	fatload,	7,	0,	do_fat_fsload,
 	"load binary file from a dos filesystem",
-	"<interface> <dev[:part]>  <addr> <filename> [bytes]\n"
-	"    - load binary file 'filename' from 'dev' on 'interface'\n"
-	"      to address 'addr' from dos filesystem"
+	"<interface> <dev[:part]>  <addr> <filename> [bytes [pos]]\n"
+	"    - Load binary file 'filename' from 'dev' on 'interface'\n"
+	"      to address 'addr' from dos filesystem.\n"
+	"      'pos' gives the file position to start loading from.\n"
+	"      If 'pos' is omitted, 0 is used. 'pos' requires 'bytes'.\n"
+	"      'bytes' gives the size to load. If 'bytes' is 0 or omitted,\n"
+	"      the load stops on end of file."
 );
 
 int do_fat_ls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
fs/fat/fat.c +79 -19

184 lines not on this page · raw message

fs/fat/fat_write.c +9 -9
index a6181e7..5829adf 100644
@@ -328,7 +328,7 @@ static void flush_dir_table(fsdata *mydata, dir_entry **dentptr);
 static void
 fill_dir_slot(fsdata *mydata, dir_entry **dentptr, const char *l_name)
 {
-	dir_slot *slotptr = (dir_slot *)get_vfatname_block;
+	dir_slot *slotptr = (dir_slot *)get_contents_vfatname_block;
 	__u8 counter = 0, checksum;
 	int idx = 0, ret;
 	char s_name[16];
@@ -373,7 +373,7 @@ static __u32 dir_curclust;
  * a slot) into 'l_name'. If successful also copy the real directory entry
  * into 'retdent'
  * If additional adjacent cluster for directory entries is read into memory,
- * then 'get_vfatname_block' is copied into 'get_dentfromdir_block' and
+ * then 'get_contents_vfatname_block' is copied into 'get_dentfromdir_block' and
  * the location of the real directory entry is returned by 'retdent'
  * Return 0 on success, -1 otherwise.
  */
@@ -416,13 +416,13 @@ get_long_file_name(fsdata *mydata, int curclust, __u8 *cluster,
 
 		dir_curclust = curclust;
 
-		if (get_cluster(mydata, curclust, get_vfatname_block,
+		if (get_cluster(mydata, curclust, get_contents_vfatname_block,
 				mydata->clust_size * mydata->sect_size) != 0) {
 			debug("Error: reading directory block\n");
 			return -1;
 		}
 
-		slotptr2 = (dir_slot *)get_vfatname_block;
+		slotptr2 = (dir_slot *)get_contents_vfatname_block;
 		while (counter > 0) {
 			if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK)
 			    & 0xff) != counter)
@@ -433,7 +433,7 @@ get_long_file_name(fsdata *mydata, int curclust, __u8 *cluster,
 
 		/* Save the real directory entry */
 		realdent = (dir_entry *)slotptr2;
-		while ((__u8 *)slotptr2 > get_vfatname_block) {
+		while ((__u8 *)slotptr2 > get_contents_vfatname_block) {
 			slotptr2--;
 			slot2str(slotptr2, l_name, &idx);
 		}
@@ -459,9 +459,9 @@ get_long_file_name(fsdata *mydata, int curclust, __u8 *cluster,
 	*retdent = realdent;
 
 	if (slotptr2) {
-		memcpy(get_dentfromdir_block, get_vfatname_block,
+		memcpy(get_dentfromdir_block, get_contents_vfatname_block,
 			mydata->clust_size * mydata->sect_size);
-		cur_position = (__u8 *)realdent - get_vfatname_block;
+		cur_position = (__u8 *)realdent - get_contents_vfatname_block;
 		*retdent = (dir_entry *) &get_dentfromdir_block[cur_position];
 	}
 
@@ -980,11 +980,11 @@ static int do_fat_write(const char *filename, void *buffer,
 	if (disk_read(cursect,
 		(mydata->fatsize == 32) ?
 		(mydata->clust_size) :
-		PREFETCH_BLOCKS, do_fat_read_block) < 0) {
+		PREFETCH_BLOCKS, do_fat_read_at_block) < 0) {
 		debug("Error: reading rootdir block\n");
 		goto exit;
 	}
-	dentptr = (dir_entry *) do_fat_read_block;
+	dentptr = (dir_entry *) do_fat_read_at_block;
 
 	name_len = strlen(filename);
 	if (name_len >= VFAT_MAXLEN_BYTES)
include/fat.h +2 -0
index f1b4a0d..cc85b06 100644
@@ -208,6 +208,8 @@ file_read_func		file_fat_read;
 int file_cd(const char *path);
 int file_fat_detectfs(void);
 int file_fat_ls(const char *dir);
+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);
 const char *file_getfsname(int idx);
 int fat_register_device(block_dev_desc_t *dev_desc, int part_no);
#12 lore raw

PATCH v3 1/1 FAT: Make it possible to read from any file position

Quoted 10 lines · Beno?t Th?baudeau

When storage devices contain files larger than the embedded RAM, it is useful to be able to read these files by chunks, e.g. for a software update to the embedded NAND Flash from an external storage device (USB stick, SD card, etc.).

Hence, this patch makes it possible by adding a new FAT API to read files from a given position. This patch also adds this feature to the fatload command.

With a reformatting of the commit message and making the changes re-apply to master, I've applied this to u-boot/master, thanks!

Signature · 8 lines
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120927/88f22428/attachment.pgp>
#13 lore raw

PATCH v3 1/1 FAT: Make it possible to read from any file position

Hi Tom,

Quoted 14 lines · Tom Rini
Quoted 12 lines · Beno?t Th?baudeau

When storage devices contain files larger than the embedded RAM, it is useful to
be able to read these files by chunks, e.g. for a software update to the
embedded NAND Flash from an external storage device (USB stick, SD card, etc.).

Hence, this patch makes it possible by adding a new FAT API to read files from a
given position. This patch also adds this feature to the fatload command.

Quoted 6 lines
Quoted 3 lines

With a reformatting of the commit message and making the changes re-apply to master, I've applied this to u-boot/master, thanks!

Perfect.

I have a concern regarding the two patches that came in between:
[1] http://git.denx.de/cgi-bin/gitweb.cgi?p=u-boot.git;a=commitdiff;h=cfda5aeab89d73779e26f0d34cf10f64caa67431
[2] http://git.denx.de/cgi-bin/gitweb.cgi?p=u-boot.git;a=commitdiff;h=10a37fd7a40826c43a63591855346adf1a1ac02d

Perhaps I'm wrong, and I admit I have not tested them, but looking at the code, it seems to me that [2] breaks the "-" in the following feature of [1]:
"With the common function "dev:part" can come from the environment and a '-' can be used in that case."
Hence, tests like "if (argc < 5)" in do_fat_fsload() get broken.

Also, the command usage message marks dev:part as optional, but it does not say that this should actually be replaced by "-" if skipped.

Best regards,
Beno?t

#14 lore raw

PATCH v3 1/1 FAT: Make it possible to read from any file position

Quoted 26 lines · Beno?t Th?baudeau

Hi Tom,

Quoted 14 lines · Tom Rini
Quoted 12 lines · Beno?t Th?baudeau

When storage devices contain files larger than the embedded RAM, it is useful to
be able to read these files by chunks, e.g. for a software update to the
embedded NAND Flash from an external storage device (USB stick, SD card, etc.).

Hence, this patch makes it possible by adding a new FAT API to read files from a
given position. This patch also adds this feature to the fatload command.

Quoted 6 lines
Quoted 3 lines

With a reformatting of the commit message and making the changes re-apply to master, I've applied this to u-boot/master, thanks!

Perfect.

Quoted 8 lines

I have a concern regarding the two patches that came in between:
[1] http://git.denx.de/cgi-bin/gitweb.cgi?p=u-boot.git;a=commitdiff;h=cfda5aeab89d73779e26f0d34cf10f64caa67431
[2] http://git.denx.de/cgi-bin/gitweb.cgi?p=u-boot.git;a=commitdiff;h=10a37fd7a40826c43a63591855346adf1a1ac02d

Perhaps I'm wrong, and I admit I have not tested them, but looking at the code, it seems to me that [2] breaks the "-" in the following feature of [1]:
"With the common function "dev:part" can come from the environment and a '-' can be used in that case."

I've sent a patch to fix this.

#15 lore raw

PATCH v3 1/1 FAT: Make it possible to read from any file position

Quoted 31 lines · Stephen Warren
Quoted 30 lines · Beno??t Th??baudeau

Hi Tom,

Quoted 14 lines · Tom Rini
Quoted 12 lines · Beno?t Th?baudeau

When storage devices contain files larger than the embedded RAM, it is useful to
be able to read these files by chunks, e.g. for a software update to the
embedded NAND Flash from an external storage device (USB stick, SD card, etc.).

Hence, this patch makes it possible by adding a new FAT API to read files from a
given position. This patch also adds this feature to the fatload command.

Quoted 6 lines
Quoted 3 lines

With a reformatting of the commit message and making the changes re-apply to master, I've applied this to u-boot/master, thanks!

Perfect.

I have a concern regarding the two patches that came in between:
[1] http://git.denx.de/cgi-bin/gitweb.cgi?p=u-boot.git;a=commitdiff;h=cfda5aeab89d73779e26f0d34cf10f64caa67431
[2] http://git.denx.de/cgi-bin/gitweb.cgi?p=u-boot.git;a=commitdiff;h=10a37fd7a40826c43a63591855346adf1a1ac02d

Quoted 6 lines
Quoted 4 lines

Perhaps I'm wrong, and I admit I have not tested them, but looking at the code, it seems to me that [2] breaks the "-" in the following feature of [1]:
"With the common function "dev:part" can come from the environment and a '-' can be used in that case."

I've sent a patch to fix this.

Thanks guys, I was a little worried about that merge, but not as worried as I should have been.

Signature · 8 lines
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120928/faff753b/attachment.pgp>