diff options
| -rw-r--r-- | fs/fat/fat.c | 97 | ||||
| -rw-r--r-- | include/fat.h | 20 | 
2 files changed, 67 insertions, 50 deletions
| diff --git a/fs/fat/fat.c b/fs/fat/fat.c index c450bf692..a34446900 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -27,6 +27,7 @@  #include <common.h>  #include <config.h> +#include <exports.h>  #include <fat.h>  #include <asm/byteorder.h>  #include <part.h> @@ -69,8 +70,7 @@ static 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[dev_desc->blksz];  	disk_partition_t info;  	if (!dev_desc->block_read) @@ -209,12 +209,12 @@ static __u32 get_fatent (fsdata *mydata, __u32 entry)  	/* Read a new block of FAT entries into the cache. */  	if (bufnum != mydata->fatbufnum) { -		__u32 getsize = FATBUFSIZE / FS_BLOCK_SIZE; +		__u32 getsize = FATBUFSIZE / mydata->sect_size;  		__u8 *bufptr = mydata->fatbuf;  		__u32 fatlength = mydata->fatlength;  		__u32 startblock = bufnum * FATBUFBLOCKS; -		fatlength *= SECTOR_SIZE;	/* We want it in bytes now */ +		fatlength *= mydata->sect_size;	/* We want it in bytes now */  		startblock += mydata->fat_sect;	/* Offset from start of disk */  		if (getsize > fatlength) @@ -291,21 +291,21 @@ get_cluster (fsdata *mydata, __u32 clustnum, __u8 *buffer,  	debug("gc - clustnum: %d, startsect: %d\n", clustnum, startsect); -	if (disk_read(startsect, size / FS_BLOCK_SIZE, buffer) < 0) { +	if (disk_read(startsect, size / mydata->sect_size, buffer) < 0) {  		debug("Error reading data\n");  		return -1;  	} -	if (size % FS_BLOCK_SIZE) { -		__u8 tmpbuf[FS_BLOCK_SIZE]; +	if (size % mydata->sect_size) { +		__u8 tmpbuf[mydata->sect_size]; -		idx = size / FS_BLOCK_SIZE; +		idx = size / mydata->sect_size;  		if (disk_read(startsect + idx, 1, tmpbuf) < 0) {  			debug("Error reading data\n");  			return -1;  		} -		buffer += idx * FS_BLOCK_SIZE; +		buffer += idx * mydata->sect_size; -		memcpy(buffer, tmpbuf, size % FS_BLOCK_SIZE); +		memcpy(buffer, tmpbuf, size % mydata->sect_size);  		return 0;  	} @@ -322,7 +322,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->sect_size;  	__u32 curclust = START(dentptr);  	__u32 endclust, newclust;  	unsigned long actsize; @@ -441,7 +441,7 @@ get_vfatname (fsdata *mydata, int curclust, __u8 *cluster,  	dir_slot *slotptr = (dir_slot *)retdent;  	__u8 *buflimit = cluster + ((curclust == 0) ?  					LINEAR_PREFETCH_SIZE : -					(mydata->clust_size * SECTOR_SIZE) +					(mydata->clust_size * mydata->sect_size)  				   );  	__u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff;  	int idx = 0; @@ -473,7 +473,7 @@ get_vfatname (fsdata *mydata, int curclust, __u8 *cluster,  		}  		if (get_cluster(mydata, curclust, get_vfatname_block, -				mydata->clust_size * SECTOR_SIZE) != 0) { +				mydata->clust_size * mydata->sect_size) != 0) {  			debug("Error: reading directory block\n");  			return -1;  		} @@ -555,7 +555,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->sect_size) != 0) {  			debug("Error: reading directory block\n");  			return NULL;  		} @@ -702,13 +702,24 @@ 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; +	int ret = 0; + +	if (cur_dev == NULL) { +		debug("Error: no device selected\n"); +		return -1; +	} + +	block = malloc(cur_dev->blksz); +	if (block == NULL) { +		debug("Error: allocating block\n"); +		return -1; +	}  	if (disk_read (0, 1, block) < 0) {  		debug("Error: reading block\n"); -		return -1; +		goto fail;  	}  	memcpy(bs, block, sizeof(boot_sector)); @@ -736,20 +747,24 @@ read_bootsectandvi (boot_sector *bs, volume_info *volinfo, int *fatsize)  	if (*fatsize == 32) {  		if (strncmp(FAT32_SIGN, vistart->fs_type, SIGNLEN) == 0) -			return 0; +			goto exit;  	} else {  		if (strncmp(FAT12_SIGN, vistart->fs_type, SIGNLEN) == 0) {  			*fatsize = 12; -			return 0; +			goto exit;  		}  		if (strncmp(FAT16_SIGN, vistart->fs_type, SIGNLEN) == 0) {  			*fatsize = 16; -			return 0; +			goto exit;  		}  	}  	debug("Error: broken fs_type sign\n"); -	return -1; +fail: +	ret = -1; +exit: +	free(block); +	return ret;  }  __attribute__ ((__aligned__ (__alignof__ (dir_entry)))) @@ -770,7 +785,7 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,  	__u32 cursect;  	int idx, isdir = 0;  	int files = 0, dirs = 0; -	long ret = 0; +	long ret = -1;  	int firsttime;  	__u32 root_cluster;  	int rootdir_size = 0; @@ -793,6 +808,7 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,  	cursect = mydata->rootdir_sect  		= mydata->fat_sect + mydata->fatlength * bs.fats; +	mydata->sect_size = (bs.sector_size[1] << 8) + bs.sector_size[0];  	mydata->clust_size = bs.cluster_size;  	if (mydata->fatsize == 32) { @@ -802,13 +818,18 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,  		rootdir_size = ((bs.dir_entries[1]  * (int)256 +  				 bs.dir_entries[0]) *  				 sizeof(dir_entry)) / -				 SECTOR_SIZE; +				 mydata->sect_size;  		mydata->data_begin = mydata->rootdir_sect +  					rootdir_size -  					(mydata->clust_size * 2);  	}  	mydata->fatbufnum = -1; +	mydata->fatbuf = malloc(FATBUFSIZE); +	if (mydata->fatbuf == NULL) { +		debug("Error: allocating memory\n"); +		return -1; +	}  #ifdef CONFIG_SUPPORT_VFAT  	debug("VFAT Support enabled\n"); @@ -819,8 +840,9 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,  	       "Data begins at: %d\n",  	       root_cluster,  	       mydata->rootdir_sect, -	       mydata->rootdir_sect * SECTOR_SIZE, mydata->data_begin); -	debug("Cluster size: %d\n", mydata->clust_size); +	       mydata->rootdir_sect * mydata->sect_size, mydata->data_begin); +	debug("Sector size: %d, cluster size: %d\n", mydata->sect_size, +	      mydata->clust_size);  	/* "cwd" is always the root... */  	while (ISDIRDELIM(*filename)) @@ -832,7 +854,7 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,  	if (*fnamecopy == '\0') {  		if (!dols) -			return -1; +			goto exit;  		dols = LS_ROOT;  	} else if ((idx = dirdelim(fnamecopy)) >= 0) { @@ -857,10 +879,10 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,  		if (disk_read(cursect,  				(mydata->fatsize == 32) ?  				(mydata->clust_size) : -				LINEAR_PREFETCH_SIZE / SECTOR_SIZE, +				LINEAR_PREFETCH_SIZE / mydata->sect_size,  				do_fat_read_block) < 0) {  			debug("Error: reading rootdir block\n"); -			return -1; +			goto exit;  		}  		dentptr = (dir_entry *) do_fat_read_block; @@ -933,9 +955,9 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,  				if (dols == LS_ROOT) {  					printf("\n%d file(s), %d dir(s)\n\n",  						files, dirs); -					return 0; +					ret = 0;  				} -				return -1; +				goto exit;  			}  #ifdef CONFIG_SUPPORT_VFAT  			else if (dols == LS_ROOT && @@ -987,7 +1009,7 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,  			}  			if (isdir && !(dentptr->attr & ATTR_DIR)) -				return -1; +				goto exit;  			debug("RootName: %s", s_name);  			debug(", start: 0x%x", START(dentptr)); @@ -1031,10 +1053,9 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,  			if (dols == LS_ROOT) {  				printf("\n%d file(s), %d dir(s)\n\n",  				       files, dirs); -				return 0; -			} else { -				return -1; +				ret = 0;  			} +			goto exit;  		}  	}  rootdir_done: @@ -1071,13 +1092,13 @@ rootdir_done:  		if (get_dentfromdir(mydata, startsect, subname, dentptr,  				     isdir ? 0 : dols) == NULL) {  			if (dols && !isdir) -				return 0; -			return -1; +				ret = 0; +			goto exit;  		}  		if (idx >= 0) {  			if (!(dentptr->attr & ATTR_DIR)) -				return -1; +				goto exit;  			subname = nextname;  		}  	} @@ -1085,6 +1106,8 @@ rootdir_done:  	ret = get_contents(mydata, dentptr, buffer, maxsize);  	debug("Size: %d, got: %ld\n", FAT2CPU32(dentptr->size), ret); +exit: +	free(mydata->fatbuf);  	return ret;  } diff --git a/include/fat.h b/include/fat.h index afb2116e8..c2465d2d3 100644 --- a/include/fat.h +++ b/include/fat.h @@ -33,22 +33,15 @@  /* Maximum Long File Name length supported here is 128 UTF-16 code units */  #define VFAT_MAXLEN_BYTES	256 /* Maximum LFN buffer in bytes */  #define VFAT_MAXSEQ		9   /* Up to 9 of 13 2-byte UTF-16 entries */ -#define LINEAR_PREFETCH_SIZE	(SECTOR_SIZE*2) /* Prefetch buffer size */ - -#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 LINEAR_PREFETCH_SIZE	(mydata->sect_size*2) /* Prefetch buffer size */  #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->sect_size / sizeof(dir_entry)) +#define DIRENTSPERCLUST	((mydata->clust_size * mydata->sect_size) / \ +			 sizeof(dir_entry))  #define FATBUFBLOCKS	6 -#define FATBUFSIZE	(FS_BLOCK_SIZE*FATBUFBLOCKS) +#define FATBUFSIZE	(mydata->sect_size * FATBUFBLOCKS)  #define FAT12BUFSIZE	((FATBUFSIZE*2)/3)  #define FAT16BUFSIZE	(FATBUFSIZE/2)  #define FAT32BUFSIZE	(FATBUFSIZE/4) @@ -181,11 +174,12 @@ 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	fatlength;	/* Length of FAT in sectors */  	__u16	fat_sect;	/* Starting sector of the FAT */  	__u16	rootdir_sect;	/* Start sector of root directory */ +	__u16	sect_size;	/* Size of sectors in bytes */  	__u16	clust_size;	/* Size of clusters in sectors */  	short	data_begin;	/* The sector of the first cluster, can be negative */  	int	fatbufnum;	/* Used by get_fatent, init to -1 */ |