[U-Boot] [PATCH] FAT on non standard sector size devices

Remy Bohmer linux at bohmer.net
Wed Nov 12 20:21:40 CET 2008


Hello Luri,

2008/11/12 Igor Luri <iluri at aotek.es>:
> 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.

I will try to find a gap tomorrow to test it on mainline.
I will keep you informed!

Kind Regards,

Remy


>
> 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
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
>


More information about the U-Boot mailing list