public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 7/7] FAT: Make it possible to read from any file position
@ 2012-07-19 22:03 Benoît Thébaudeau
  2012-07-19 22:44 ` Mike Frysinger
  0 siblings, 1 reply; 16+ messages in thread
From: Benoît Thébaudeau @ 2012-07-19 22:03 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Beno?t Th?baudeau <benoit.thebaudeau@advansee.com>
Cc: Wolfgang Denk <wd@denx.de>
---
 .../fs/fat/fat.c                                   |   90 ++++++++++++++++----
 1 file changed, 72 insertions(+), 18 deletions(-)

diff --git u-boot-66714b1.orig/fs/fat/fat.c u-boot-66714b1/fs/fat/fat.c
index 8ac8b85..709a5eb 100644
--- u-boot-66714b1.orig/fs/fat/fat.c
+++ u-boot-66714b1/fs/fat/fat.c
@@ -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;

^ permalink raw reply related	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2012-09-28 16:17 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-19 22:03 [U-Boot] [PATCH 7/7] FAT: Make it possible to read from any file position Benoît Thébaudeau
2012-07-19 22:44 ` Mike Frysinger
2012-07-19 23:17   ` Benoît Thébaudeau
2012-07-20  3:02     ` Mike Frysinger
2012-07-20 13:22       ` [U-Boot] [PATCH v2 8/8] " Benoît Thébaudeau
2012-09-02 15:28         ` Wolfgang Denk
2012-09-03 14:17           ` Benoît Thébaudeau
2012-09-14 20:49             ` Tom Rini
2012-09-14 22:03               ` Benoît Thébaudeau
2012-09-14 22:02                 ` Tom Rini
2012-09-22 20:32                   ` Benoît Thébaudeau
2012-09-18 18:14         ` [U-Boot] [PATCH v3] " Benoît Thébaudeau
2012-09-27 16:20           ` [U-Boot] [U-Boot, " Tom Rini
2012-09-28 11:32             ` Benoît Thébaudeau
2012-09-28 15:34               ` Stephen Warren
2012-09-28 16:17                 ` Tom Rini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox