#include <common.h>
#include <config.h>
+#include <exports.h>
#include <fat.h>
#include <asm/byteorder.h>
#include <part.h>
int fat_register_device (block_dev_desc_t * dev_desc, int part_no)
{
- unsigned char buffer[SECTOR_SIZE];
-
- disk_partition_t info;
+ unsigned char buffer[dev_desc->blksz];
if (!dev_desc->block_read)
return -1;
defined(CONFIG_CMD_USB) || \
defined(CONFIG_MMC) || \
defined(CONFIG_SYSTEMACE) )
- /* First we assume there is a MBR */
- if (!get_partition_info(dev_desc, part_no, &info)) {
- part_offset = info.start;
- cur_part = part_no;
- } else if ((strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET], "FAT", 3) == 0) ||
- (strncmp((char *)&buffer[DOS_FS32_TYPE_OFFSET], "FAT32", 5) == 0)) {
- /* ok, we assume we are on a PBR only */
- cur_part = 1;
- part_offset = 0;
- } else {
- printf("** Partition %d not valid on device %d **\n",
- part_no, dev_desc->dev);
- return -1;
+ {
+ disk_partition_t info;
+
+ /* First we assume there is a MBR */
+ if (!get_partition_info(dev_desc, part_no, &info)) {
+ part_offset = info.start;
+ cur_part = part_no;
+ } else if ((strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET],
+ "FAT", 3) == 0) ||
+ (strncmp((char *)&buffer[DOS_FS32_TYPE_OFFSET],
+ "FAT32", 5) == 0)) {
+ /* ok, we assume we are on a PBR only */
+ cur_part = 1;
+ part_offset = 0;
+ } else {
+ printf("** Partition %d not valid on device %d **\n",
+ part_no, dev_desc->dev);
+ return -1;
+ }
}
-
#else
if ((strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET], "FAT", 3) == 0) ||
(strncmp((char *)&buffer[DOS_FS32_TYPE_OFFSET], "FAT32", 5) == 0)) {
/* ok, we assume we are on a PBR only */
cur_part = 1;
part_offset = 0;
- info.start = part_offset;
} else {
/* FIXME we need to determine the start block of the
* partition where the DOS FS resides. This can be done
/* Read a new block of FAT entries into the cache. */
if (bufnum != mydata->fatbufnum) {
- int getsize = FATBUFSIZE / FS_BLOCK_SIZE;
+ __u32 getsize = FATBUFBLOCKS;
__u8 *bufptr = mydata->fatbuf;
__u32 fatlength = mydata->fatlength;
__u32 startblock = bufnum * FATBUFBLOCKS;
- fatlength *= SECTOR_SIZE; /* We want it in bytes now */
- startblock += mydata->fat_sect; /* Offset from start of disk */
-
if (getsize > fatlength)
getsize = fatlength;
+
+ fatlength *= mydata->sect_size; /* We want it in bytes now */
+ startblock += mydata->fat_sect; /* Offset from start of disk */
+
if (disk_read(startblock, getsize, bufptr) < 0) {
debug("Error reading FAT blocks\n");
return ret;
get_cluster (fsdata *mydata, __u32 clustnum, __u8 *buffer,
unsigned long size)
{
- int idx = 0;
+ __u32 idx = 0;
__u32 startsect;
if (clustnum > 0) {
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;
}
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;
{
dir_entry *realdent;
dir_slot *slotptr = (dir_slot *)retdent;
- __u8 *nextclust = cluster + mydata->clust_size * SECTOR_SIZE;
+ __u8 *buflimit = cluster + mydata->sect_size * ((curclust == 0) ?
+ PREFETCH_BLOCKS :
+ mydata->clust_size);
__u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff;
int idx = 0;
- while ((__u8 *)slotptr < nextclust) {
+ if (counter > VFAT_MAXSEQ) {
+ debug("Error: VFAT name is too long\n");
+ return -1;
+ }
+
+ while ((__u8 *)slotptr < buflimit) {
if (counter == 0)
break;
if (((slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff) != counter)
counter--;
}
- if ((__u8 *)slotptr >= nextclust) {
+ if ((__u8 *)slotptr >= buflimit) {
dir_slot *slotptr2;
- slotptr--;
+ if (curclust == 0)
+ return -1;
curclust = get_fatent(mydata, curclust);
if (CHECK_CLUST(curclust, mydata->fatsize)) {
debug("curclust: 0x%x\n", curclust);
}
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;
}
slotptr2 = (dir_slot *)get_vfatname_block;
- while (slotptr2->id > 0x01)
+ while (counter > 0) {
+ if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK)
+ & 0xff) != counter)
+ return -1;
slotptr2++;
+ counter--;
+ }
/* Save the real directory entry */
- realdent = (dir_entry *)slotptr2 + 1;
- while ((__u8 *)slotptr2 >= get_vfatname_block) {
- slot2str(slotptr2, l_name, &idx);
+ realdent = (dir_entry *)slotptr2;
+ while ((__u8 *)slotptr2 > get_vfatname_block) {
slotptr2--;
+ slot2str(slotptr2, l_name, &idx);
}
} else {
/* Save the real directory entry */
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;
}
dentptr = (dir_entry *)get_dentfromdir_block;
for (i = 0; i < DIRENTSPERCLUST; i++) {
- char s_name[14], l_name[256];
+ char s_name[14], l_name[VFAT_MAXLEN_BYTES];
l_name[0] = '\0';
if (dentptr->name[0] == DELETED_FLAG) {
}
if ((dentptr->attr & ATTR_VOLUME)) {
#ifdef CONFIG_SUPPORT_VFAT
- if ((dentptr->attr & ATTR_VFAT) &&
- (dentptr-> name[0] & LAST_LONG_ENTRY_MASK)) {
+ if ((dentptr->attr & ATTR_VFAT) == ATTR_VFAT &&
+ (dentptr->name[0] & LAST_LONG_ENTRY_MASK)) {
prevcksum = ((dir_slot *)dentptr)->alias_checksum;
get_vfatname(mydata, curclust,
get_dentfromdir_block,
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));
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))))
dir_entry *dentptr;
__u16 prevcksum = 0xffff;
char *subname = "";
- int cursect;
+ __u32 cursect;
int idx, isdir = 0;
int files = 0, dirs = 0;
- long ret = 0;
+ long ret = -1;
int firsttime;
- int root_cluster;
+ __u32 root_cluster = 0;
+ int rootdir_size = 0;
int j;
if (read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) {
return -1;
}
- root_cluster = bs.root_cluster;
-
- if (mydata->fatsize == 32)
+ if (mydata->fatsize == 32) {
+ root_cluster = bs.root_cluster;
mydata->fatlength = bs.fat32_length;
- else
+ } else {
mydata->fatlength = bs.fat_length;
+ }
mydata->fat_sect = bs.reserved;
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) {
mydata->data_begin = mydata->rootdir_sect -
(mydata->clust_size * 2);
} else {
- int rootdir_size;
-
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");
"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))
if (*fnamecopy == '\0') {
if (!dols)
- return -1;
+ goto exit;
dols = LS_ROOT;
} else if ((idx = dirdelim(fnamecopy)) >= 0) {
debug("FAT read sect=%d, clust_size=%d, DIRENTSPERBLOCK=%d\n",
cursect, mydata->clust_size, DIRENTSPERBLOCK);
- if (disk_read(cursect, mydata->clust_size, do_fat_read_block) < 0) {
+ if (disk_read(cursect,
+ (mydata->fatsize == 32) ?
+ (mydata->clust_size) :
+ PREFETCH_BLOCKS,
+ do_fat_read_block) < 0) {
debug("Error: reading rootdir block\n");
- return -1;
+ goto exit;
}
dentptr = (dir_entry *) do_fat_read_block;
for (i = 0; i < DIRENTSPERBLOCK; i++) {
- char s_name[14], l_name[256];
+ char s_name[14], l_name[VFAT_MAXLEN_BYTES];
l_name[0] = '\0';
+ if (dentptr->name[0] == DELETED_FLAG) {
+ dentptr++;
+ continue;
+ }
if ((dentptr->attr & ATTR_VOLUME)) {
#ifdef CONFIG_SUPPORT_VFAT
- if ((dentptr->attr & ATTR_VFAT) &&
+ if ((dentptr->attr & ATTR_VFAT) == ATTR_VFAT &&
(dentptr->name[0] & LAST_LONG_ENTRY_MASK)) {
prevcksum =
((dir_slot *)dentptr)->alias_checksum;
- get_vfatname(mydata, 0,
+ get_vfatname(mydata,
+ root_cluster,
do_fat_read_block,
dentptr, l_name);
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 &&
}
if (isdir && !(dentptr->attr & ATTR_DIR))
- return -1;
+ goto exit;
debug("RootName: %s", s_name);
debug(", start: 0x%x", START(dentptr));
* root directory clusters when a cluster has been
* completely processed.
*/
- if ((mydata->fatsize == 32) && (++j == mydata->clust_size)) {
- int nxtsect;
- int nxt_clust;
+ ++j;
+ int fat32_end = 0;
+ if ((mydata->fatsize == 32) && (j == mydata->clust_size)) {
+ int nxtsect = 0;
+ int nxt_clust = 0;
nxt_clust = get_fatent(mydata, root_cluster);
+ fat32_end = CHECK_CLUST(nxt_clust, 32);
nxtsect = mydata->data_begin +
(nxt_clust * mydata->clust_size);
- debug("END LOOP: sect=%d, root_clust=%d, "
- "n_sect=%d, n_clust=%d\n",
- cursect, root_cluster,
- nxtsect, nxt_clust);
-
root_cluster = nxt_clust;
cursect = nxtsect;
} else {
cursect++;
}
+
+ /* If end of rootdir reached */
+ if ((mydata->fatsize == 32 && fat32_end) ||
+ (mydata->fatsize != 32 && j == rootdir_size)) {
+ if (dols == LS_ROOT) {
+ printf("\n%d file(s), %d dir(s)\n\n",
+ files, dirs);
+ ret = 0;
+ }
+ goto exit;
+ }
}
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;
}
}
ret = get_contents(mydata, dentptr, buffer, maxsize);
debug("Size: %d, got: %ld\n", FAT2CPU32(dentptr->size), ret);
+exit:
+ free(mydata->fatbuf);
return ret;
}