[U-Boot] [PATCH] FAT on non standard sector size devices
Igor Luri
iluri at aotek.es
Wed Nov 12 17:30:58 CET 2008
Hi all!
I have done some changes sugested by Remy Bohme and finally the
following patch adds FAT support on devices of ANY sector size.
I have only tested on our custom board with u-boot 1.1.6 version. I
would appreciate if someone could test this patch on latest version.
Thanks.
Signed-off-by: Igor Luri <iluri at aotek.es>
diff --git a/include/fat.h b/include/fat.h
index 59de3fb..dad2e3d 100644
--- a/include/fat.h
+++ b/include/fat.h
@@ -31,20 +31,12 @@
#define CONFIG_SUPPORT_VFAT
-#define SECTOR_SIZE FS_BLOCK_SIZE
-
-#define FS_BLOCK_SIZE 512
-
-#if FS_BLOCK_SIZE != SECTOR_SIZE
-#error FS_BLOCK_SIZE != SECTOR_SIZE - This code needs to be fixed!
-#endif
-
#define MAX_CLUSTSIZE 65536
-#define DIRENTSPERBLOCK (FS_BLOCK_SIZE/sizeof(dir_entry))
-#define DIRENTSPERCLUST
((mydata->clust_size*SECTOR_SIZE)/sizeof(dir_entry))
+#define DIRENTSPERBLOCK (mydata->sector_size/sizeof(dir_entry))
+#define DIRENTSPERCLUST
((mydata->clust_size*mydata->sector_size)/sizeof(dir_entry))
#define FATBUFBLOCKS 6
-#define FATBUFSIZE (FS_BLOCK_SIZE*FATBUFBLOCKS)
+#define FATBUFSIZE (mydata->sector_size*FATBUFBLOCKS)
#define FAT12BUFSIZE ((FATBUFSIZE*2)/3)
#define FAT16BUFSIZE (FATBUFSIZE/2)
#define FAT32BUFSIZE (FATBUFSIZE/4)
@@ -182,8 +174,9 @@ typedef struct dir_slot {
* (see FAT32 accesses)
*/
typedef struct {
- __u8 fatbuf[FATBUFSIZE]; /* Current FAT buffer */
+ __u8 *fatbuf; /* Current FAT buffer */
int fatsize; /* Size of FAT in bits */
+ __u16 sector_size; /* Sector size */
__u16 fatlength; /* Length of FAT in sectors */
__u16 fat_sect; /* Starting sector of the FAT */
__u16 rootdir_sect; /* Start sector of root directory */
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 2f0bd8c..c24f009 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -30,6 +30,7 @@
#include <fat.h>
#include <asm/byteorder.h>
#include <part.h>
+#include <malloc.h>
/*
* Convert a string to lowercase.
@@ -67,12 +68,17 @@ int disk_read (__u32 startblock, __u32 getsize, __u8
* bufptr)
int
fat_register_device(block_dev_desc_t *dev_desc, int part_no)
{
- unsigned char buffer[SECTOR_SIZE];
+ unsigned char *buffer;
disk_partition_t info;
if (!dev_desc->block_read)
return -1;
- cur_dev = dev_desc;
+ cur_dev=dev_desc;
+
+ buffer = malloc (cur_dev->blksz);
+ if(buffer == NULL)
+ return(-1);
+
/* check if we have a MBR (on floppies we have only a PBR) */
if (dev_desc->block_read (dev_desc->dev, 0, 1, (ulong *) buffer) != 1)
{
printf ("** Can't read from device %d **\n", dev_desc->dev);
@@ -118,6 +124,7 @@ fat_register_device(block_dev_desc_t *dev_desc, int
part_no)
cur_part = 1;
}
#endif
+ free(buffer);
return 0;
}
@@ -220,12 +227,12 @@ get_fatent(fsdata *mydata, __u32 entry)
/* Read a new block of FAT entries into the cache. */
if (bufnum != mydata->fatbufnum) {
- int getsize = FATBUFSIZE/FS_BLOCK_SIZE;
+ int getsize = FATBUFSIZE/mydata->sector_size;
__u8 *bufptr = mydata->fatbuf;
__u32 fatlength = mydata->fatlength;
__u32 startblock = bufnum * FATBUFBLOCKS;
- fatlength *= SECTOR_SIZE; /* We want it in bytes now */
+ fatlength *= mydata->sector_size; /* We want it in bytes now */
startblock += mydata->fat_sect; /* Offset from start of disk */
if (getsize > fatlength) getsize = fatlength;
@@ -300,20 +307,25 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8
*buffer, unsigned long size)
}
FAT_DPRINT("gc - clustnum: %d, startsect: %d\n", clustnum, startsect);
- if (disk_read(startsect, size/FS_BLOCK_SIZE , buffer) < 0) {
+ if (disk_read(startsect, size/mydata->sector_size , buffer) < 0) {
FAT_DPRINT("Error reading data\n");
return -1;
}
- if(size % FS_BLOCK_SIZE) {
- __u8 tmpbuf[FS_BLOCK_SIZE];
- idx= size/FS_BLOCK_SIZE;
+ if(size % mydata->sector_size) {
+ __u8 * tmpbuf;
+
+ tmpbuf = (__u8*) malloc(mydata->sector_size);
+ if(tmpbuf == NULL)
+ return(-1);
+ idx= size/mydata->sector_size;
if (disk_read(startsect + idx, 1, tmpbuf) < 0) {
FAT_DPRINT("Error reading data\n");
return -1;
}
- buffer += idx*FS_BLOCK_SIZE;
+ buffer += idx*mydata->sector_size;
- memcpy(buffer, tmpbuf, size % FS_BLOCK_SIZE);
+ memcpy(buffer, tmpbuf, size % mydata->sector_size);
+ free(tmpbuf);
return 0;
}
@@ -331,7 +343,7 @@ get_contents(fsdata *mydata, dir_entry *dentptr,
__u8 *buffer,
unsigned long maxsize)
{
unsigned long filesize = FAT2CPU32(dentptr->size), gotsize = 0;
- unsigned int bytesperclust = mydata->clust_size * SECTOR_SIZE;
+ unsigned int bytesperclust = mydata->clust_size * mydata->sector_size;
__u32 curclust = START(dentptr);
__u32 endclust, newclust;
unsigned long actsize;
@@ -440,7 +452,7 @@ get_vfatname(fsdata *mydata, int curclust, __u8
*cluster,
{
dir_entry *realdent;
dir_slot *slotptr = (dir_slot*) retdent;
- __u8 *nextclust = cluster + mydata->clust_size * SECTOR_SIZE;
+ __u8 *nextclust = cluster + mydata->clust_size *
mydata->sector_size;
__u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff;
int idx = 0;
@@ -463,7 +475,7 @@ get_vfatname(fsdata *mydata, int curclust, __u8
*cluster,
return -1;
}
if (get_cluster(mydata, curclust, get_vfatname_block,
- mydata->clust_size * SECTOR_SIZE) != 0) {
+ mydata->clust_size * mydata->sector_size) != 0) {
FAT_DPRINT("Error: reading directory block\n");
return -1;
}
@@ -534,7 +546,7 @@ static dir_entry *get_dentfromdir (fsdata * mydata,
int startsect,
int i;
if (get_cluster (mydata, curclust, get_dentfromdir_block,
- mydata->clust_size * SECTOR_SIZE) != 0) {
+ mydata->clust_size * mydata->sector_size) != 0) {
FAT_DPRINT ("Error: reading directory block\n");
return NULL;
}
@@ -667,9 +679,16 @@ static dir_entry *get_dentfromdir (fsdata * mydata,
int startsect,
static int
read_bootsectandvi(boot_sector *bs, volume_info *volinfo, int *fatsize)
{
- __u8 block[FS_BLOCK_SIZE];
+ __u8 *block;
volume_info *vistart;
+ if(cur_dev == NULL)
+ return(-1);
+
+ block = (__u8 *)malloc (cur_dev->blksz);
+ if(block == NULL)
+ return(-1);
+
if (disk_read(0, 1, block) < 0) {
FAT_DPRINT("Error: reading block\n");
return -1;
@@ -680,6 +699,7 @@ read_bootsectandvi(boot_sector *bs, volume_info
*volinfo, int *fatsize)
bs->fat_length = FAT2CPU16(bs->fat_length);
bs->secs_track = FAT2CPU16(bs->secs_track);
bs->heads = FAT2CPU16(bs->heads);
+ *(__u16 *)bs->sector_size = FAT2CPU16(*(__u16 *)bs->sector_size);
#if 0 /* UNUSED */
bs->hidden = FAT2CPU32(bs->hidden);
#endif
@@ -704,7 +724,7 @@ read_bootsectandvi(boot_sector *bs, volume_info
*volinfo, int *fatsize)
/* Terminate fs_type string. Writing past the end of vistart
is ok - it's just the buffer. */
vistart->fs_type[8] = '\0';
-
+ free(block);
if (*fatsize == 32) {
if (compare_sign(FAT32_SIGN, vistart->fs_type) == 0) {
return 0;
@@ -757,6 +777,7 @@ do_fat_read (const char *filename, void *buffer,
unsigned long maxsize,
mydata->fatlength = bs.fat_length;
}
mydata->fat_sect = bs.reserved;
+ mydata->sector_size = *(__u16 *)bs.sector_size;
cursect = mydata->rootdir_sect
= mydata->fat_sect + mydata->fatlength * bs.fats;
mydata->clust_size = bs.cluster_size;
@@ -766,17 +787,20 @@ do_fat_read (const char *filename, void *buffer,
unsigned long maxsize,
- (mydata->clust_size * 2);
} else {
rootdir_size = ((bs.dir_entries[1] * (int) 256 + bs.dir_entries[0])
- * sizeof (dir_entry)) / SECTOR_SIZE;
+ * sizeof (dir_entry)) / mydata->sector_size;
mydata->data_begin = mydata->rootdir_sect + rootdir_size
- (mydata->clust_size * 2);
}
mydata->fatbufnum = -1;
+ mydata->fatbuf = (__u8 *) malloc (FATBUFSIZE);
+ if(mydata->fatbuf == NULL)
+ return(-1);
FAT_DPRINT ("FAT%d, fatlength: %d\n", mydata->fatsize,
mydata->fatlength);
FAT_DPRINT ("Rootdir begins at sector: %d, offset: %x, size: %d\n"
"Data begins at: %d\n",
- mydata->rootdir_sect, mydata->rootdir_sect * SECTOR_SIZE,
+ mydata->rootdir_sect, mydata->rootdir_sect * mydata->sector_size,
rootdir_size, mydata->data_begin);
FAT_DPRINT ("Cluster size: %d\n", mydata->clust_size);
@@ -787,8 +811,10 @@ do_fat_read (const char *filename, void *buffer,
unsigned long maxsize,
strcpy (fnamecopy, filename);
downcase (fnamecopy);
if (*fnamecopy == '\0') {
- if (!dols)
- return -1;
+ if (!dols) {
+ free(mydata->fatbuf);
+ return -1;
+ }
dols = LS_ROOT;
} else if ((idx = dirdelim (fnamecopy)) >= 0) {
isdir = 1;
@@ -806,6 +832,7 @@ do_fat_read (const char *filename, void *buffer,
unsigned long maxsize,
if (disk_read (cursect, mydata->clust_size, do_fat_read_block) < 0) {
FAT_DPRINT ("Error: reading rootdir block\n");
+ free(mydata->fatbuf);
return -1;
}
dentptr = (dir_entry *) do_fat_read_block;
@@ -856,6 +883,7 @@ do_fat_read (const char *filename, void *buffer,
unsigned long maxsize,
continue;
}
} else if (dentptr->name[0] == 0) {
+ free(mydata->fatbuf);
FAT_DPRINT ("RootDentname == NULL - %d\n", i);
if (dols == LS_ROOT) {
printf ("\n%d file(s), %d dir(s)\n\n", files, dirs);
@@ -906,9 +934,10 @@ do_fat_read (const char *filename, void *buffer,
unsigned long maxsize,
dentptr++;
continue;
}
- if (isdir && !(dentptr->attr & ATTR_DIR))
+ if (isdir && !(dentptr->attr & ATTR_DIR)) {
+ free(mydata->fatbuf);
return -1;
-
+ }
FAT_DPRINT ("RootName: %s", s_name);
FAT_DPRINT (", start: 0x%x", START (dentptr));
FAT_DPRINT (", size: 0x%x %s\n",
@@ -949,20 +978,23 @@ do_fat_read (const char *filename, void *buffer,
unsigned long maxsize,
if (get_dentfromdir (mydata, startsect, subname, dentptr,
isdir ? 0 : dols) == NULL) {
+ free(mydata->fatbuf);
if (dols && !isdir)
return 0;
return -1;
}
if (idx >= 0) {
- if (!(dentptr->attr & ATTR_DIR))
- return -1;
+ if (!(dentptr->attr & ATTR_DIR)) {
+ free(mydata->fatbuf);
+ return -1;
+ }
subname = nextname;
}
}
ret = get_contents (mydata, dentptr, buffer, maxsize);
FAT_DPRINT ("Size: %d, got: %ld\n", FAT2CPU32 (dentptr->size),
ret);
-
+ free(mydata->fatbuf);
return ret;
}
--
Igor Luri
R&D Software Department
Fagor Aotek S. Coop.
P. O. Box 144
E-20500 Mondragón-Arrasate
Tel. ++34 943 71 92 00
++34 943 71 92 01 (Ext. 44268)
Fax. ++34 943 79 92 03
www.aotek.es
More information about the U-Boot
mailing list