[U-Boot] [patch 2/2] Cleanup patch Fat on non standard sector size devices

The patch below is a patch originally posted by Igor Luri. However, the patch posted on the mailinglist was not readable (base64) and thus not mergable or testable. Also tabs/spaces were malformed.
So, I merged the whole patch by hand and posted it again.
Igor can you please check if I did this cleanup properly.
Notice that the code that is being modified here does not match _any_ coding rule standard and is actually a big mess. So, I did not focus on the Coding Rules too much for this patch. I will post a seperate patch to fix this for the complete files also. ---------------- There are USB devices with sector size different than 512 bytes. In fact, I have one with 2048 bytes per sector:
scsi0 : SCSI emulation for USB Mass Storage devices Vendor: ChipsBnk Model: Flash Disk Rev: 4.00 Type: Direct-Access ANSI SCSI revision: 02 Attached scsi removable disk sda at scsi0, channel 0, id 0, lun 0 SCSI device sda: 129124 2048-byte hdwr sectors (264 MB) sda: Write Protect is off Partition check: sda: sda1 sda2 sda3 sda4
U-boot FAT filesystem code supposes that sector size is always 512 bytes, consecuently fatload and fatls commands ends up with a segmentation fault.
Attached patches adds FAT support on devices with sector size up to 8192 bytes.
Signed-off-by: Igor Luri iluri@aotek.es Signed-off-by: Remy Bohmer linux@bohmer.net --- fs/fat/fat.c | 89 ++++++++++++++++++++++++++++++++++++++++------------------ include/fat.h | 18 +++-------- 2 files changed, 68 insertions(+), 39 deletions(-)
Index: u-boot-usb.new/fs/fat/fat.c =================================================================== --- u-boot-usb.new.orig/fs/fat/fat.c 2008-11-27 21:40:25.000000000 +0100 +++ u-boot-usb.new/fs/fat/fat.c 2008-11-27 22:10:40.000000000 +0100 @@ -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 g 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; + + buffer = malloc(cur_dev->blksz); + if (!buffer) + 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 *de 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 clustn }
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) + 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 * 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,8 @@ get_vfatname(fsdata *mydata, int curclus { 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 +476,7 @@ get_vfatname(fsdata *mydata, int curclus 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; } @@ -533,8 +546,8 @@ static dir_entry *get_dentfromdir (fsdat dir_entry *dentptr; int i;
- if (get_cluster (mydata, curclust, get_dentfromdir_block, - mydata->clust_size * SECTOR_SIZE) != 0) { + if (get_cluster(mydata, curclust, get_dentfromdir_block, + mydata->clust_size * mydata->sector_size) != 0) { FAT_DPRINT ("Error: reading directory block\n"); return NULL; } @@ -667,9 +680,16 @@ static dir_entry *get_dentfromdir (fsdat 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) + return -1; + + block = (__u8 *)malloc(cur_dev->blksz); + if (!block) + return -1; + if (disk_read(0, 1, block) < 0) { FAT_DPRINT("Error: reading block\n"); return -1; @@ -680,6 +700,7 @@ read_bootsectandvi(boot_sector *bs, volu 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 +725,7 @@ read_bootsectandvi(boot_sector *bs, volu /* 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 +778,7 @@ do_fat_read (const char *filename, void 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 +788,21 @@ do_fat_read (const char *filename, void - (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) + 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 +813,10 @@ do_fat_read (const char *filename, void 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; @@ -805,8 +833,9 @@ do_fat_read (const char *filename, void int i;
if (disk_read (cursect, mydata->clust_size, do_fat_read_block) < 0) { - FAT_DPRINT ("Error: reading rootdir block\n"); - return -1; + FAT_DPRINT ("Error: reading rootdir block\n"); + free(mydata->fatbuf); + return -1; } dentptr = (dir_entry *) do_fat_read_block; for (i = 0; i < DIRENTSPERBLOCK; i++) { @@ -856,6 +885,7 @@ do_fat_read (const char *filename, void 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 +936,10 @@ do_fat_read (const char *filename, void 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 +980,24 @@ do_fat_read (const char *filename, void
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; - subname = nextname; + 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; }
Index: u-boot-usb.new/include/fat.h =================================================================== --- u-boot-usb.new.orig/include/fat.h 2008-11-27 21:40:17.000000000 +0100 +++ u-boot-usb.new/include/fat.h 2008-11-27 21:45:13.000000000 +0100 @@ -31,20 +31,13 @@
#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 +175,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 */

Dear Remy,
I have checked patches and I think there are OK.
Also, I have aplied [patch 1/2] and [patch 2/2] on git u-boot version. Then I have copied patched files (fat.h and fat.c) on our customized u-boot-1.1.6 version. Finally I have built and installed u-boot on our custom board.
I have executed fatls and fatload commands with our 2048 bytes sector USB pendrive and IT WORKS !!!!
Thanks a lot for your help.
El jue, 27-11-2008 a las 22:30 +0100, Remy Bohmer escribió:
documento de texto sencillo adjunto (fat-on-non-standard-sector-size-devices.patch) The patch below is a patch originally posted by Igor Luri. However, the patch posted on the mailinglist was not readable (base64) and thus not mergable or testable. Also tabs/spaces were malformed.
So, I merged the whole patch by hand and posted it again.
Igor can you please check if I did this cleanup properly.
Notice that the code that is being modified here does not match _any_ coding rule standard and is actually a big mess. So, I did not focus on the Coding Rules too much for this patch. I will post a seperate patch to fix this for the complete files also.
There are USB devices with sector size different than 512 bytes. In fact, I have one with 2048 bytes per sector:
scsi0 : SCSI emulation for USB Mass Storage devices Vendor: ChipsBnk Model: Flash Disk Rev: 4.00 Type: Direct-Access ANSI SCSI revision: 02 Attached scsi removable disk sda at scsi0, channel 0, id 0, lun 0 SCSI device sda: 129124 2048-byte hdwr sectors (264 MB) sda: Write Protect is off Partition check: sda: sda1 sda2 sda3 sda4
U-boot FAT filesystem code supposes that sector size is always 512 bytes, consecuently fatload and fatls commands ends up with a segmentation fault.
Attached patches adds FAT support on devices with sector size up to 8192 bytes.
Signed-off-by: Igor Luri iluri@aotek.es Signed-off-by: Remy Bohmer linux@bohmer.net
fs/fat/fat.c | 89 ++++++++++++++++++++++++++++++++++++++++------------------ include/fat.h | 18 +++-------- 2 files changed, 68 insertions(+), 39 deletions(-)
Index: u-boot-usb.new/fs/fat/fat.c
--- u-boot-usb.new.orig/fs/fat/fat.c 2008-11-27 21:40:25.000000000 +0100 +++ u-boot-usb.new/fs/fat/fat.c 2008-11-27 22:10:40.000000000 +0100 @@ -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 g 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;
buffer = malloc(cur_dev->blksz);
if (!buffer)
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 *de 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;
__u8 *bufptr = mydata->fatbuf; __u32 fatlength = mydata->fatlength; __u32 startblock = bufnum * FATBUFBLOCKS;int getsize = FATBUFSIZE / mydata->sector_size;
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 clustn }
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)
return -1;
if (disk_read(startsect + idx, 1, tmpbuf) < 0) { FAT_DPRINT("Error reading data\n"); return -1; }idx = size / mydata->sector_size;
buffer += idx*FS_BLOCK_SIZE;
buffer += idx * mydata->sector_size;
memcpy(buffer, tmpbuf, size % FS_BLOCK_SIZE);
memcpy(buffer, tmpbuf, size % mydata->sector_size);
return 0; }free(tmpbuf);
@@ -331,7 +343,7 @@ get_contents(fsdata *mydata, dir_entry * 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,8 @@ get_vfatname(fsdata *mydata, int curclus { dir_entry *realdent; dir_slot *slotptr = (dir_slot*) retdent;
- __u8 *nextclust = cluster + mydata->clust_size * SECTOR_SIZE;
- __u8 *nextclust = cluster +
__u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff; int idx = 0;mydata->clust_size * mydata->sector_size;
@@ -463,7 +476,7 @@ get_vfatname(fsdata *mydata, int curclus 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;
@@ -533,8 +546,8 @@ static dir_entry *get_dentfromdir (fsdat dir_entry *dentptr; int i;
- if (get_cluster (mydata, curclust, get_dentfromdir_block,
mydata->clust_size * SECTOR_SIZE) != 0) {
- if (get_cluster(mydata, curclust, get_dentfromdir_block,
FAT_DPRINT ("Error: reading directory block\n"); return NULL; }mydata->clust_size * mydata->sector_size) != 0) {
@@ -667,9 +680,16 @@ static dir_entry *get_dentfromdir (fsdat 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)
return -1;
block = (__u8 *)malloc(cur_dev->blksz);
if (!block)
return -1;
if (disk_read(0, 1, block) < 0) { FAT_DPRINT("Error: reading block\n"); return -1;
@@ -680,6 +700,7 @@ read_bootsectandvi(boot_sector *bs, volu 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 +725,7 @@ read_bootsectandvi(boot_sector *bs, volu /* 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 +778,7 @@ do_fat_read (const char *filename, void 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 +788,21 @@ do_fat_read (const char *filename, void - (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)
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,
rootdir_size, mydata->data_begin); FAT_DPRINT ("Cluster size: %d\n", mydata->clust_size);mydata->rootdir_sect * mydata->sector_size,
@@ -787,8 +813,10 @@ do_fat_read (const char *filename, void 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;
@@ -805,8 +833,9 @@ do_fat_read (const char *filename, void int i;
if (disk_read (cursect, mydata->clust_size, do_fat_read_block) < 0) {
FAT_DPRINT ("Error: reading rootdir block\n");
return -1;
FAT_DPRINT ("Error: reading rootdir block\n");
free(mydata->fatbuf);
} dentptr = (dir_entry *) do_fat_read_block; for (i = 0; i < DIRENTSPERBLOCK; i++) {return -1;
@@ -856,6 +885,7 @@ do_fat_read (const char *filename, void continue; } } else if (dentptr->name[0] == 0) {
FAT_DPRINT ("RootDentname == NULL - %d\n", i); if (dols == LS_ROOT) { printf ("\n%d file(s), %d dir(s)\n\n", files, dirs);free(mydata->fatbuf);
@@ -906,9 +936,10 @@ do_fat_read (const char *filename, void dentptr++; continue; }
if (isdir && !(dentptr->attr & ATTR_DIR))
if (isdir && !(dentptr->attr & ATTR_DIR)) {
return -1;free(mydata->fatbuf);
} FAT_DPRINT ("RootName: %s", s_name); FAT_DPRINT (", start: 0x%x", START (dentptr)); FAT_DPRINT (", size: 0x%x %s\n",
@@ -949,20 +980,24 @@ do_fat_read (const char *filename, void
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;
subname = nextname;
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;
}
Index: u-boot-usb.new/include/fat.h
--- u-boot-usb.new.orig/include/fat.h 2008-11-27 21:40:17.000000000 +0100 +++ u-boot-usb.new/include/fat.h 2008-11-27 21:45:13.000000000 +0100 @@ -31,20 +31,13 @@
#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 +175,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 */

Hello Igor,
2008/11/28 Igor Luri iluri@aotek.es:
Dear Remy,
I have checked patches and I think there are OK. Also, I have aplied [patch 1/2] and [patch 2/2] on git u-boot version. Then I have copied patched files (fat.h and fat.c) on our customized u-boot-1.1.6 version. Finally I have built and installed u-boot on our custom board. I have executed fatls and fatload commands with our 2048 bytes sector USB pendrive and IT WORKS !!!!
Status update: I have put this patch in the u-boot-usb 'debug' branch. It is pending there because I found a regression problem on some boards with 512 bytes sector sized USB sticks, which work without this patch. I did not found the time yet to debug this problem, because of debugging another problem... I hope you can find some time to look into this patch and see what is going wrong here. You can use the debug branch of the u-boot-usb tree.
Please let me know...
Kind Regards,
Remy
Thanks a lot for your help.
El jue, 27-11-2008 a las 22:30 +0100, Remy Bohmer escribió:
documento de texto sencillo adjunto (fat-on-non-standard-sector-size-devices.patch) The patch below is a patch originally posted by Igor Luri. However, the patch posted on the mailinglist was not readable (base64) and thus not mergable or testable. Also tabs/spaces were malformed.
So, I merged the whole patch by hand and posted it again.
Igor can you please check if I did this cleanup properly.
Notice that the code that is being modified here does not match _any_ coding rule standard and is actually a big mess. So, I did not focus on the Coding Rules too much for this patch. I will post a seperate patch to fix this for the complete files also.
There are USB devices with sector size different than 512 bytes. In fact, I have one with 2048 bytes per sector:
scsi0 : SCSI emulation for USB Mass Storage devices Vendor: ChipsBnk Model: Flash Disk Rev: 4.00 Type: Direct-Access ANSI SCSI revision: 02 Attached scsi removable disk sda at scsi0, channel 0, id 0, lun 0 SCSI device sda: 129124 2048-byte hdwr sectors (264 MB) sda: Write Protect is off Partition check: sda: sda1 sda2 sda3 sda4
U-boot FAT filesystem code supposes that sector size is always 512 bytes, consecuently fatload and fatls commands ends up with a segmentation fault.
Attached patches adds FAT support on devices with sector size up to 8192 bytes.
Signed-off-by: Igor Luri iluri@aotek.es Signed-off-by: Remy Bohmer linux@bohmer.net
fs/fat/fat.c | 89 ++++++++++++++++++++++++++++++++++++++++------------------ include/fat.h | 18 +++-------- 2 files changed, 68 insertions(+), 39 deletions(-)
Index: u-boot-usb.new/fs/fat/fat.c
--- u-boot-usb.new.orig/fs/fat/fat.c 2008-11-27 21:40:25.000000000 +0100 +++ u-boot-usb.new/fs/fat/fat.c 2008-11-27 22:10:40.000000000 +0100 @@ -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 g 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;
buffer = malloc(cur_dev->blksz);
if (!buffer)
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 *de 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 clustn }
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)
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 * 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,8 @@ get_vfatname(fsdata *mydata, int curclus { 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 +476,7 @@ get_vfatname(fsdata *mydata, int curclus 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; }
@@ -533,8 +546,8 @@ static dir_entry *get_dentfromdir (fsdat dir_entry *dentptr; int i;
if (get_cluster (mydata, curclust, get_dentfromdir_block,
mydata->clust_size * SECTOR_SIZE) != 0) {
if (get_cluster(mydata, curclust, get_dentfromdir_block,
mydata->clust_size * mydata->sector_size) != 0) { FAT_DPRINT ("Error: reading directory block\n"); return NULL; }
@@ -667,9 +680,16 @@ static dir_entry *get_dentfromdir (fsdat 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)
return -1;
block = (__u8 *)malloc(cur_dev->blksz);
if (!block)
return -1;
if (disk_read(0, 1, block) < 0) { FAT_DPRINT("Error: reading block\n"); return -1;
@@ -680,6 +700,7 @@ read_bootsectandvi(boot_sector *bs, volu 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 +725,7 @@ read_bootsectandvi(boot_sector *bs, volu /* 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 +778,7 @@ do_fat_read (const char *filename, void 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 +788,21 @@ do_fat_read (const char *filename, void - (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)
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,
FAT_DPRINT ("Cluster size: %d\n", mydata->clust_size);mydata->rootdir_sect * mydata->sector_size, rootdir_size, mydata->data_begin);
@@ -787,8 +813,10 @@ do_fat_read (const char *filename, void strcpy (fnamecopy, filename); downcase (fnamecopy); if (*fnamecopy == '\0') {
if (!dols)
return -1;
if (!dols) {
free(mydata->fatbuf);
return -1;
} else if ((idx = dirdelim (fnamecopy)) >= 0) { isdir = 1;} dols = LS_ROOT;
@@ -805,8 +833,9 @@ do_fat_read (const char *filename, void int i;
if (disk_read (cursect, mydata->clust_size, do_fat_read_block) < 0) {
FAT_DPRINT ("Error: reading rootdir block\n");
return -1;
FAT_DPRINT ("Error: reading rootdir block\n");
free(mydata->fatbuf);
return -1; } dentptr = (dir_entry *) do_fat_read_block; for (i = 0; i < DIRENTSPERBLOCK; i++) {
@@ -856,6 +885,7 @@ do_fat_read (const char *filename, void 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 +936,10 @@ do_fat_read (const char *filename, void 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 +980,24 @@ do_fat_read (const char *filename, void
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;
subname = nextname;
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;
}
Index: u-boot-usb.new/include/fat.h
--- u-boot-usb.new.orig/include/fat.h 2008-11-27 21:40:17.000000000 +0100 +++ u-boot-usb.new/include/fat.h 2008-11-27 21:45:13.000000000 +0100 @@ -31,20 +31,13 @@
#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 +175,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 */
-- 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
participants (2)
-
Igor Luri
-
Remy Bohmer