in lsvmutils/vfat.c [963:1159]
int VFATInit(
Blkdev* dev,
VFAT** vfatOut)
{
int rc = -1;
VFAT* vfat = NULL;
if (!dev || !vfatOut)
GOTO(done);
/* Allocate the vfat object */
if (!(vfat = Calloc(1, sizeof(VFAT))))
GOTO(done);
/* Read the BPB */
if (BlkdevRead(dev, 0, &vfat->bpb, sizeof(vfat->bpb)) != 0)
GOTO(done);
/* Check signature of BPB */
{
const UINT8* p = vfat->bpb.jmpBoot;
if (!(p[0] == 0xEB && p[2] == 0x90) && !(p[0] == 0xE9))
GOTO(done);
}
/* See if there is an FSI (FAT32 only) */
if (GetFATType(&vfat->bpb) == FAT32)
{
/* Read the BPB */
if (BlkdevRead(
dev,
vfat->bpb.u.s32.FSInfo,
&vfat->fsi,
sizeof(vfat->fsi)) != 0)
{
GOTO(done);
}
/* Check signatures of FSI */
if (vfat->fsi.LeadSig != 0x41615252 || vfat->fsi.TrailSig != 0xAA550000)
GOTO(done);
}
/* Set the block device */
vfat->dev = dev;
/* Reject sector sizes that are not 512 */
if (vfat->bpb.BytsPerSec != VFAT_SECTOR_SIZE)
GOTO(done);
/* Precompute some useful values */
{
/* Compute VFAT.FATSz */
if (vfat->bpb.FATSz16 != 0)
vfat->FATSz = vfat->bpb.FATSz16;
else
vfat->FATSz = vfat->bpb.u.s32.FATSz32;
/* Compute VFAT.TotSec */
if (vfat->bpb.TotSec16 != 0)
vfat->TotSec = vfat->bpb.TotSec16;
else
vfat->TotSec = vfat->bpb.TotSec32;
/* Compute VFAT.RootDirSectors */
vfat->RootDirSectors =
((vfat->bpb.RootEntCnt * 32) + (vfat->bpb.BytsPerSec - 1)) /
vfat->bpb.BytsPerSec;
/* Compute VFAT.FirstRootDirSecNum */
vfat->FirstRootDirSecNum = vfat->bpb.ResvdSecCnt +
(vfat->bpb.NumFATs * vfat->FATSz);
/* Compute VFAT.FirstDataSector */
vfat->FirstDataSector = vfat->bpb.ResvdSecCnt +
(vfat->bpb.NumFATs * vfat->FATSz) + vfat->RootDirSectors;
/* Compute VFAT.DataSec */
vfat->DataSec = vfat->TotSec -
(vfat->bpb.ResvdSecCnt + (vfat->bpb.NumFATs * vfat->FATSz) +
vfat->RootDirSectors);
/* Compute VFAT.CountOfClusters */
vfat->CountOfClusters = vfat->DataSec / vfat->bpb.SecPerClus;
/* Compute cluster size in bytes */
vfat->ClusterSize = vfat->bpb.SecPerClus * vfat->bpb.BytsPerSec;
}
/* Determine Type of FAT */
if (vfat->CountOfClusters < 4085)
vfat->FATType = FAT12;
else if (vfat->CountOfClusters < 65525)
vfat->FATType = FAT16;
else
vfat->FATType = FAT32;
/* Load one of the FATs into memory */
{
UINTN nbytes = vfat->FATSz * vfat->bpb.BytsPerSec;
if (BufReserve(&vfat->fat, nbytes) != 0)
GOTO(done);
if (BlkdevRead(
vfat->dev,
vfat->bpb.ResvdSecCnt,
vfat->fat.data,
nbytes) != 0)
{
GOTO(done);
}
vfat->fat.size += nbytes;
/* If more than one FAT, read the second one in an compare */
if (vfat->bpb.NumFATs > 1)
{
Buf buf = BUF_INITIALIZER;
if (BufReserve(&buf, nbytes) != 0)
GOTO(done);
if (BlkdevRead(
vfat->dev,
vfat->bpb.ResvdSecCnt + vfat->FATSz,
buf.data,
nbytes) != 0)
{
BufRelease(&buf);
GOTO(done);
}
buf.size += nbytes;
if (buf.size != vfat->fat.size ||
Memcmp(buf.data, vfat->fat.data, buf.size) != 0)
{
BufRelease(&buf);
GOTO(done);
}
BufRelease(&buf);
}
#if 0
HexDump(vfat->fat.data, vfat->fat.size);
#endif
}
/* Load the root directory into memory */
if (vfat->FATType == FAT32)
{
/* Read the root directory file into memory */
if (ReadClusters(vfat, vfat->bpb.u.s32.RootClus, &vfat->rootdir) != 0)
GOTO(done);
vfat->rootdirClustno = vfat->bpb.u.s32.RootClus;
}
else
{
UINTN nbytes = vfat->RootDirSectors * vfat->bpb.BytsPerSec;
if (BufReserve(&vfat->rootdir, nbytes) != 0)
GOTO(done);
if (BlkdevRead(
vfat->dev,
vfat->FirstRootDirSecNum,
vfat->rootdir.data,
nbytes) != 0)
{
GOTO(done);
}
vfat->rootdir.size += nbytes;
vfat->rootdirClustno = 0;
}
*vfatOut = vfat;
rc = 0;
done:
if (rc != 0)
{
if (vfat)
{
/* Don't let VFATRelease() free the caller's device */
vfat->dev = NULL;
VFATRelease(vfat);
}
}
return rc;
}