?? volume.c
字號:
if (!(pvol->v_pdsk->d_diActive.di_flags & DISK_INFO_FLAG_CHS_UNCERTAIN) &&
(pvol->v_pdsk->d_diActive.di_heads != pbpb->oldBPB.BPB_Heads ||
pvol->v_pdsk->d_diActive.di_sectors != pbpb->oldBPB.BPB_SectorsPerTrack)) {
DEBUGMSG(ZONE_INIT || ZONE_ERRORS,
(DBGTEXT("FATFS!InitVolume: driver disagrees with BPB (BPB CHS=%d:%d:%d)\n"),
(pvol->v_csecTotal + pvol->v_secBlkBias) / (pbpb->oldBPB.BPB_Heads * pbpb->oldBPB.BPB_SectorsPerTrack),
pbpb->oldBPB.BPB_Heads,
pbpb->oldBPB.BPB_SectorsPerTrack));
}
#endif
// We've seen cases where the driver thinks there are fewer sectors on
// the disk than the BPB does, which means that any I/O near the end of
// the volume will probably fail. So for now, we'll try to catch these
// cases, report them, and then adjust our values to agree with the driver.
if (pvol->v_pdsk->d_diActive.di_total_sectors < pvol->v_csecTotal + pvol->v_secBlkBias) {
DEBUGMSG(ZONE_INIT || ZONE_ERRORS,
(DBGTEXT("FATFS!InitVolume: driver reports fewer sectors than BPB! (%d vs. %d)\n"),
pvol->v_pdsk->d_diActive.di_total_sectors, pvol->v_csecTotal + pvol->v_secBlkBias));
pvol->v_csecTotal = pvol->v_pdsk->d_diActive.di_total_sectors - pvol->v_secBlkBias;
}
pvol->v_log2csecClus = Log2(pbpb->oldBPB.BPB_SectorsPerCluster);
pvol->v_log2cbSec = Log2(pbpb->oldBPB.BPB_BytesPerSector);
pvol->v_log2cblkSec = pvol->v_log2cbSec - BLOCK_LOG2;
pvol->v_log2cblkClus = pvol->v_log2cblkSec + pvol->v_log2csecClus;
pvol->v_cbClus = 1 << (pvol->v_log2cbSec + pvol->v_log2csecClus);
#ifdef FAT32
if (pbpb->oldBPB.BPB_SectorsPerFAT == 0) {
pvol->v_serialID = pbgbs->bgbsVolumeID;
memcpy(pvol->v_label, pbgbs->bgbsVolumeLabel, sizeof(pbgbs->bgbsVolumeLabel));
pvol->v_csecFAT = pbpb->BGBPB_BigSectorsPerFAT;
// Set up the FAT DSTREAM structure
pvol->v_secEndFAT = pbpb->BGBPB_BigSectorsPerFAT * (pbpb->BGBPB_ExtFlags & BGBPB_F_ActiveFATMsk);
pvol->v_secEndAllFATs = pbpb->BGBPB_BigSectorsPerFAT * pbpb->oldBPB.BPB_NumberOfFATs;
pstmFAT->s_size = pbpb->BGBPB_BigSectorsPerFAT << pvol->v_log2cbSec;
ASSERT(pstmFAT->s_run.r_start == 0);
pstmFAT->s_run.r_end = pstmFAT->s_size;
pstmFAT->s_run.r_blk = pvol->v_secEndFAT << pvol->v_log2cblkSec;
pvol->v_secEndFAT += pbpb->BGBPB_BigSectorsPerFAT;
// Set up the root directory DSTREAM structure
pstmRoot->s_size = MAX_DIRSIZE;
pstmRoot->s_clusFirst = pbpb->BGBPB_RootDirStrtClus;
RewindStream(pstmRoot, INVALID_POS);
pvol->v_csecUsed = pvol->v_secEndAllFATs;
// Compute block bias for cluster 0. The first data cluster is 2.
pvol->v_blkClusBias = (pvol->v_csecUsed << pvol->v_log2cblkSec) -
(DATA_CLUSTER << pvol->v_log2cblkClus);
// Set the maximum cluster # supported for this volume; it is the
// smaller of 1) total clusters on the media and 2) total cluster entries
// the FAT can contain.
cmaxClus = pstmFAT->s_size/sizeof(DWORD) - DATA_CLUSTER;
pvol->v_clusMax = ((pvol->v_csecTotal - pvol->v_csecUsed) >> pvol->v_log2csecClus);
if (pvol->v_clusMax > cmaxClus) {
DEBUGMSGBREAK(ZONE_INIT || ZONE_ERRORS,
(DBGTEXT("FATFS!InitVolume: total clusters (%d) exceeds FAT32 size (%d), reducing...\n"), pvol->v_clusMax, cmaxClus));
pvol->v_clusMax = cmaxClus;
}
pvol->v_clusMax++; // now convert total clusters to max cluster #
pvol->v_unpack = Unpack32;
pvol->v_pack = Pack32;
pvol->v_clusEOF = FAT32_EOF_MIN;
} else
#endif // FAT32
{
// 16-bit or 12-bit FAT volume
PBOOTSEC pbs = (PBOOTSEC)pbgbs;
pvol->v_serialID = pbs->bsVolumeID;
memcpy(pvol->v_label, pbs->bsVolumeLabel, sizeof(pbs->bsVolumeLabel));
pvol->v_csecFAT = pbpb->oldBPB.BPB_SectorsPerFAT;
// Set up the FAT DSTREAM structure; always assume that the first FAT
// is the active one
pvol->v_secEndFAT = pbpb->oldBPB.BPB_SectorsPerFAT;
pvol->v_secEndAllFATs = pbpb->oldBPB.BPB_SectorsPerFAT * pbpb->oldBPB.BPB_NumberOfFATs;
pstmFAT->s_size = pbpb->oldBPB.BPB_SectorsPerFAT << pvol->v_log2cbSec;
ASSERT(pstmFAT->s_run.r_start == 0);
pstmFAT->s_run.r_end = pstmFAT->s_size;
pstmFAT->s_run.r_blk = 0;
// Set up the root directory DSTREAM structure
pstmRoot->s_size = pbpb->oldBPB.BPB_RootEntries * sizeof(DIRENTRY);
pstmRoot->s_clusFirst = ROOT_PSEUDO_CLUSTER;
pstmRoot->s_run.r_start = 0;
pstmRoot->s_run.r_end = pstmRoot->s_size;
pstmRoot->s_run.r_blk = pvol->v_secEndAllFATs << pvol->v_log2cblkSec;
pvol->v_csecUsed = pvol->v_secEndAllFATs + ((pstmRoot->s_size + pbpb->oldBPB.BPB_BytesPerSector-1) >> pvol->v_log2cbSec);
// Compute block bias for cluster 0. The first data cluster is 2.
pvol->v_blkClusBias = (pvol->v_csecUsed << pvol->v_log2cblkSec) -
(DATA_CLUSTER << pvol->v_log2cblkClus);
// clusMax is temporarily the total # of clusters, and cmaxClus is
// temporarily the total number of BITS contained in the FAT (we'll divide
// that by 12 or 16 as appropriate, and then use it to make sure clusMax is valid).
pvol->v_clusMax = (pvol->v_csecTotal - pvol->v_csecUsed) >> pvol->v_log2csecClus;
cmaxClus = pvol->v_csecFAT << (pvol->v_log2cbSec+3); // add 3 to get # bits instead of # bytes
if (pvol->v_clusMax >= FAT1216_THRESHOLD) {
cmaxClus /= 16;
pvol->v_flags |= VOLF_16BIT_FAT;
pvol->v_unpack = Unpack16;
pvol->v_pack = Pack16;
pvol->v_clusEOF = FAT16_EOF_MIN;
} else {
cmaxClus /= 12;
pvol->v_flags |= VOLF_12BIT_FAT;
pvol->v_unpack = Unpack12;
pvol->v_pack = Pack12;
pvol->v_clusEOF = (pvol->v_clusMax < FAT12_EOF_SPECIAL-1)? FAT12_EOF_SPECIAL : FAT12_EOF_MIN;
}
// Set the maximum cluster # supported for this volume; it is the
// smaller of 1) total clusters on the media and 2) total cluster entries
// the FAT can contain.
cmaxClus -= DATA_CLUSTER;
if (pvol->v_clusMax > cmaxClus) {
DEBUGMSGBREAK(ZONE_INIT || ZONE_ERRORS,
(DBGTEXT("FATFS!InitVolume: total clusters (%d) exceeds FAT size (%d), reducing...\n"), pvol->v_clusMax, cmaxClus));
pvol->v_clusMax = cmaxClus;
}
pvol->v_clusMax++; // now convert total clusters to max cluster #
}
exit:
pvol->v_clusAlloc = pvol->v_cclusFree = UNKNOWN_CLUSTER;
// If the FORMATTING bit is set and the volume is valid, then we assume that the volume
// has just been reformatted, and therefore that the number of free clusters is the same
// as total clusters.
if ((pvol->v_flags & (VOLF_INVALID|VOLF_FORMATTING)) == VOLF_FORMATTING)
pvol->v_cclusFree = pvol->v_clusMax-1;
CloseStream(pstmRoot);
CloseStream(pstmFAT);
#ifdef DISK_CACHING
pvol->v_CacheSize = 0;
pvol->v_pFATCacheBuffer = NULL;
pvol->v_pFATCacheLookup = NULL;
SetupDiskCache(pvol);
#endif
return pstmFAT && pstmRoot;
}
/* ValidateFATSector - Verify FAT sector has valid media ID
*
* ENTRY
* pvol - pointer to VOLUME
* pvSector - pointer to memory containing FAT sector
*
* EXIT
* TRUE if given FAT sector appears to be valid, FALSE if not
*/
BOOL ValidateFATSector(PVOLUME pvol, PVOID pvSector)
{
DWORD dwMask;
dwMask = 0xff0;
if (pvol->v_bMediaDesc == MEDIA_HD)
dwMask = 0xff8;
if (pvol->v_flags & VOLF_16BIT_FAT)
dwMask |= 0xfff0;
#ifdef FAT32
else if (pvol->v_flags & VOLF_32BIT_FAT)
dwMask |= 0x0ffffff0;
#endif
else
ASSERT(pvol->v_flags & VOLF_12BIT_FAT);
if ((*(PDWORD)pvSector & dwMask) < dwMask)
return FALSE;
return TRUE;
}
PVOLUME FindVolume(PDSK pdsk, PBIGFATBOOTSEC pbgbs)
{
PBIGFATBPB pbpb = &pbgbs->bgbsBPB;
PVOLUME pvol = pdsk->pVol;
ASSERT(OWNCRITICALSECTION(&csFATFS));
if (!pvol) {
pvol = (PVOLUME)LocalAlloc(LPTR, sizeof(VOLUME));
} else {
pvol->v_flags |= VOLF_REMOUNTED;
return pvol;
}
if (!pvol)
DEBUGMSG(ZONE_INIT || ZONE_ERRORS,(DBGTEXT("FATFS!FindVolume: out of memory!\n")));
else {
DEBUGALLOC(sizeof(VOLUME));
InitializeCriticalSection(&pvol->v_cs);
DEBUGALLOC(DEBUGALLOC_CS);
InitializeCriticalSection(&pvol->v_csStms);
DEBUGALLOC(DEBUGALLOC_CS);
#ifdef PATH_CACHING
InitList((PDLINK)&pvol->v_dlCaches);
InitializeCriticalSection(&pvol->v_csCaches);
DEBUGALLOC(DEBUGALLOC_CS);
#endif
InitList((PDLINK)&pvol->v_dlOpenStreams);
pvol->v_pdsk = pdsk;
pvol->v_volID = INVALID_AFS;
}
return pvol;
}
/* ProbeVolume - Test for the (continued) existence of a VOLUME
*
* ENTRY
* pvol - pointer to VOLUME
*
* EXIT
* Sets the volume's VOLF_RETAIN flag as appropriate. When set,
* the RETAIN flag causes the PC Card volume to persist across a
* power on/off sequence; otherwise, if the user was browsing the
* PC Card folder, the shell could close the browser window unexpectedly.
*/
void ProbeVolume(PVOLUME pvol)
{
pvol->v_flags |= VOLF_RETAIN;
#ifdef LATER
PBYTE pbSector;
__try {
pbSector = _alloca(pvol->v_pdsk->d_diActive.di_bytes_per_sect);
// Perform a trial read of the first sector (sector 0) now.
if (pbSector) {
if (ReadWriteDisk(pvol,
pvol->v_pdsk->d_hdsk,
DISK_IOCTL_READ,
&pvol->v_pdsk->d_diActive,
pvol->v_secVolBias + 0,
1,
pbSector) == ERROR_SUCCESS) {
pvol->v_flags |= VOLF_RETAIN;
}
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
;
}
DEBUGMSGW(ZONE_INIT,(DBGTEXTW("FATFS!ProbeVolume: %sretaining volume 0x%08x\n"), pvol->v_flags & VOLF_RETAIN? TEXTW("") : TEXTW("NOT "), pvol));
#endif
}
/* TestVolume - Test a VOLUME's validity
*
* ENTRY
* pvol - pointer to VOLUME
* ppbgbs - pointer to address of PBR (partition boot record) for volume
*
* EXIT
* ERROR_SUCCESS, else VOLUME's INVALID bit set if any errors encountered
*/
DWORD TestVolume(PVOLUME pvol, PBIGFATBOOTSEC *ppbgbs)
{
DWORD cbSecOrig;
DWORD dwError = ERROR_SUCCESS;
PDSK pdsk = pvol->v_pdsk;
PBIGFATBOOTSEC pbgbs = *ppbgbs;
if (pvol->v_flags & VOLF_INVALID)
return dwError;
// Make sure other key BPB values are in sync with the driver (ie, sector
// size), assuming driver info was provided.
cbSecOrig = pdsk->d_diActive.di_bytes_per_sect;
if (cbSecOrig != pbgbs->bgbsBPB.oldBPB.BPB_BytesPerSector) {
DEBUGMSG(ZONE_INIT || ZONE_ERRORS,
(DBGTEXT("FATFS!TestVolume: forcing driver sector size (%d) to match BPB (%d)\n"),
cbSecOrig, pbgbs->bgbsBPB.oldBPB.BPB_BytesPerSector));
pdsk->d_diActive.di_bytes_per_sect = pbgbs->bgbsBPB.oldBPB.BPB_BytesPerSector;
if (SetDiskInfo(pdsk->d_hdsk, &pdsk->d_diActive) == ERROR_SUCCESS) {
pvol->v_flags |= VOLF_MODDISKINFO;
if (pdsk->d_diActive.di_bytes_per_sect > cbSecOrig) {
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -