此為轉貼資料
http://depos.patching.net/showart.asp?art_id=72&cat_id=2
讀取FAT12,16根源程式<1> //
//檔案名稱: fat.c
//版本: 00.00.01
//
//FAT文件系統.
// 蔡軍生
// 20021218 --- 20021222
//
#include <_krnl.h> //bool定義.
#include // 調試巨集定義.
#include //硬碟
#include // FAT文件系統.
#include /* memcpy(), memsetw() */
//來自: MM.C
void* kmalloc(size_t size);
//
//邏輯驅器鏈表.
//
static CDosDriver g_DosDriver;
//
//邏輯磁區到物理磁區轉換(C,H,S).
//
// C柱面號 = 邏輯磁區號 /( 每磁軌磁區數 * 磁頭數)
// H磁頭號 = (邏輯磁區號 / 每磁軌磁區數) % 磁頭數
// S磁軌記憶體磁區號 = 邏輯磁區號 % 每磁軌磁區數 1
void FAT_RelSecToCHS(int nSec,int* pCylinder,int* pHead,int* pSect);
//
//讀取C盤分區.
//
void FAT_ReadDiskC(void);
//
//識別FAT12,FAT16,FAT32.
//
int IsFatType(unsigned char* pBuf);
//
//讀取FAT到記憶體.
//
void FAT_ReadFatToBuf(void);
//
//取得根目錄表.
//
void FAT_ReadRootDirToBuf(void);
//
//格式化目錄項輸出
//
void FAT_FormatRootEnt(CRootEnt* pRootEnt,char* pBuf);
//
//格式化目錄項日期和時間字串.
//
char* FAT_FormatDatetime(CRootEnt* pRootEnt);
///////////////////////////////////////////////////////////////////////////
//
//初始化文件系統.
//
void FAT_Init(void)
{
//取得硬碟分區表.
HD_PartTableFour* pPartTable = HD_GetPartTable();
KTRACE("BootID = 0xX\n",pPartTable->ptTable1.byteBootID);
//
FAT_ReadDiskC();
}
//
//讀取WINDOWS分區表.可以從MicroSoft的文件文檔得到.
//
//讀取C:分區.
//
void FAT_ReadDiskC(void)
{
unsigned char nBuf[512];//C:分區第一個引導磁區.
//取得主驅動器參數.
HD_Info* pIDE0 = HD_GetIDE0();
//取得硬碟分區表.
HD_PartTableFour* pPartTable = HD_GetPartTable();
//設置C:分區資訊.
g_DosDriver.nSizeSelf = sizeof(CDosDriver);
memcpy(g_DosDriver.cName,"C:",3);
g_DosDriver.nStartSec = pPartTable->ptTable1.byteSectorStart;//開始磁區
g_DosDriver.nStartHead = pPartTable->ptTable1.byteHeadStart;//開始磁頭
g_DosDriver.nStartCylinder = (pPartTable->ptTable1.byteSectorStart & 0xC0) << 2 |
pPartTable->ptTable1.byteCylinderStart;//開始柱面.
//保存本驅動器參數.
g_DosDriver.nHead = pIDE0->wHead;//磁頭數.
g_DosDriver.nSecPerTrk = pIDE0->wSectPerTrack;//每道多少磁區數.
KTRACE("pIDE0->wSectPerTrack=%d\t",pIDE0->wSectPerTrack);
//讀C:分區第一個引導磁區.其中包含有Boot sector和
//BPB結構.
HD_ReadWrite(
CMD_READ,//讀取命令.
0,//0,主硬碟驅動器,
1,//讀取一個磁區.
g_DosDriver.nStartSec,//開始磁區
g_DosDriver.nStartHead,//開始磁頭
g_DosDriver.nStartCylinder,//開始柱面.
nBuf);//保存讀取的資料.
//
g_DosDriver.iFatType = IsFatType(nBuf);
KTRACE("FAT%d\n",g_DosDriver.iFatType);
//邏輯磁區開始位置.
//邏輯磁區號 = (物理磁區號-1) 物理磁頭號*每道磁區數 物理磁頭號*每道磁區數*磁頭數.
g_DosDriver.nStartSecRel = (g_DosDriver.nStartSec -1)
g_DosDriver.nStartHead*g_DosDriver.nSecPerTrk
g_DosDriver.nStartCylinder*g_DosDriver.nSecPerTrk*g_DosDriver.nHead;
KTRACE("g_DosDriver.nStartSecRel=%d\n",g_DosDriver.nStartSecRel);
//讀FAT.
FAT_ReadFatToBuf();
//讀取根目錄.
FAT_ReadRootDirToBuf();
// while(1);//for test.
}
//
//識別FAT12,FAT16,FAT32.
//
int IsFatType(unsigned char* pBuf)
{
DWORD dwRootDirSectors;//根目錄所占磁區數.
DWORD dwFatsz;//
DWORD dwTotSec;//總磁區.
DWORD dwCountOfClusters;//資料區有多少簇.
CBootSecBPB1216* pBs = (CBootSecBPB1216*) pBuf;
CBootSecBPB32* pBs32 = (CBootSecBPB32*) pBuf;
//計算根目錄佔用的磁區數.
dwRootDirSectors = ( *((WORD*)pBs->bpb.BPB_RootEntCnt) * 32
*((WORD*)pBs->bpb.BPB_BytePerSec)-1 )/ *((WORD*)pBs->bpb.BPB_BytePerSec);
KTRACE("RootDirSectors:%d\n",dwRootDirSectors);
//取得每個FAT磁區數
if( *((WORD*)pBs->bpb.BPB_FatSz16) != 0)//FAT12,FAT16
{
dwFatsz = *((WORD*)pBs->bpb.BPB_FatSz16);
}
else//FAT32
{
dwFatsz = *((DWORD*)pBs32->bs.BPB_FATSz32);
}
//取得總共磁區數.
if( *((WORD*)pBs->bpb.BPB_TotSec16) != 0)//FAT12,FAT16
{
dwTotSec = *((WORD*)pBs->bpb.BPB_TotSec16);
}
else//FAT32
{
dwTotSec = *((DWORD*)pBs32->bpb.BPB_TotSec32);
}
//保存FAT
g_DosDriver.nFatSize = dwFatsz;
g_DosDriver.nFatStartSec = *((WORD*)pBs->bpb.BPB_RsvdSecCnt);
//保存根目錄.
g_DosDriver.nRootEntCnt = *((WORD*)pBs->bpb.BPB_RootEntCnt);
g_DosDriver.nRootDirSize = dwRootDirSectors;
g_DosDriver.nRootDirStartSec = g_DosDriver.nFatStartSec pBs->bpb.BPB_NumFATs * dwFatsz;
//保存文件資料區.
g_DosDriver.nFileStartSec = g_DosDriver.nRootDirStartSec dwRootDirSectors;
//資料區佔用的磁區數.
g_DosDriver.nFileSize = dwTotSec - ( *((WORD*)pBs->bpb.BPB_RsvdSecCnt)
pBs->bpb.BPB_NumFATs * dwFatsz dwRootDirSectors);
KTRACE("dwFatsz:%d\n",dwFatsz);
//計算有多少簇.
dwCountOfClusters = g_DosDriver.nFileSize/pBs->bpb.BPB_SecPerClus;
KTRACE("dwCountOfClusters:%d\n",dwCountOfClusters);
//
g_DosDriver.nSecPerTrk = *((WORD*)pBs->bpb.BPB_SecPerTrk);
//
if(dwCountOfClusters < 4085)//FAT12
{
return FAT12;
}
else if(dwCountOfClusters < 65525)//FAT16
{
return FAT16;
}
else //FAT32
{
return FAT32;
}//end
}
//
//讀取FAT到記憶體.
//
void FAT_ReadFatToBuf(void)
{
int i;
//物理磁區開始.
int nFatSec = g_DosDriver.nFatStartSec g_DosDriver.nStartSecRel;
KTRACE("nFatSec =%d\t",nFatSec);
//分配保存FAT的記憶體.
g_DosDriver.pFatStart = kmalloc(g_DosDriver.nFatSize * 512);
KTRACE("nFatSize=%d\n",g_DosDriver.nFatSize * 512);
//讀取所有FAT資料磁區.
for(i = 0; i < g_DosDriver.nFatSize; i )
{
FAT_ReadOneRelSec(nFatSec i,(g_DosDriver.pFatStart i*512));
}
//
KTRACE("i=%d\n",i);
}
//
//用邏輯磁區號讀取一個磁區.
//
bool FAT_ReadOneRelSec(int nRelSec,char* pBuf)
{
int nCylinder;
int nHead;
int nSect;
//邏輯磁區到物理磁區轉換(C,H,S).
FAT_RelSecToCHS(nRelSec,&nCylinder,&nHead,&nSect);
HD_ReadWrite(
CMD_READ,//讀取命令.
0,//0,主硬碟驅動器,
1,//讀取一個磁區.
nSect,//開始磁區
nHead,//開始磁頭
nCylinder,//開始柱面.
pBuf);//保存讀取的資料.
}
//
//邏輯磁區到物理磁區轉換,nSec->(C,H,S).
//
// C柱面號 = 邏輯磁區號 /( 每磁軌磁區數 * 磁頭數)
// H磁頭號 = (邏輯磁區號 / 每磁軌磁區數) % 磁頭數
// S磁軌記憶體磁區號 = 邏輯磁區號 % 每磁軌磁區數 1
void FAT_RelSecToCHS(int nSec,int* pCylinder,int* pHead,int* pSect)
{
*pCylinder = nSec/( g_DosDriver.nSecPerTrk * g_DosDriver.nHead );
*pHead = ( nSec/g_DosDriver.nSecPerTrk ) % g_DosDriver.nHead;
*pSect = nSec % g_DosDriver.nSecPerTrk 1;
}
//
//取得根目錄表.
//
void FAT_ReadRootDirToBuf(void)
{
int i;
char TempBuf[1024];
CRootEnt* pRootEnt = (CRootEnt* ) g_DosDriver.pRootDirStart;
char* pCharRootEnt = (char*) g_DosDriver.pRootDirStart;
//磁區開始.
int nFatSec = g_DosDriver.nRootDirStartSec g_DosDriver.nStartSecRel;
KTRACE("nFatSec =%d\t",nFatSec);
//分配保存Root DIR的記憶體.
g_DosDriver.pFatStart = kmalloc(g_DosDriver.nRootDirSize * 512);
KTRACE("nRootDirSize=%d\n",g_DosDriver.nRootDirSize * 512);
//讀取所有Root DIR資料磁區.
for(i = 0; i < g_DosDriver.nRootDirSize; i )
{
FAT_ReadOneRelSec(nFatSec i,(g_DosDriver.pRootDirStart i*512));
}
//顯示根目錄.
for(i=0; i < g_DosDriver.nRootEntCnt; i )
{
if(*pCharRootEnt == 0x00 || *pCharRootEnt == 0xE5 ||
*pCharRootEnt == 0x05 || *pCharRootEnt == 0x2E )
{
continue;
}
//
FAT_FormatRootEnt(pRootEnt,TempBuf);
pCharRootEnt = sizeof(CRootEnt);
pRootEnt = (CRootEnt*) pCharRootEnt;
}
//
}
//
//格式化目錄項輸出
//
void FAT_FormatRootEnt(CRootEnt* pRootEnt,char* pBuf)
{
int i;
char* pTemp = pBuf;
//格式化時間. //
for(i=0; i<8; i )
{
if(pRootEnt->Name == )
break;
pBuf = pRootEnt->Name;
}
memcpy(pBuf i,".",1);
memcpy(pBuf i 1,pRootEnt->Exte,3);
*(pBuf i 4) = \0;
//
FAT_FormatDatetime(pRootEnt);
if( pRootEnt->Attr & 0x10 )
{
KTRACE(" d ",pRootEnt->Length);
}
else
{
KTRACE(" d ",pRootEnt->Length);
}
//
KTRACE("%s\n",pBuf);
}
//
//格式化目錄項日期和時間字串.
//
char* FAT_FormatDatetime(CRootEnt* pRootEnt)
{
int nYear = 1980;
int nMonth = 1;
int nDate = 1;
int nHour = 0;
int nMinute = 0;
//
nDate = 0x1F & pRootEnt->Date;
nMonth = 0xF & (pRootEnt->Date >> 5);
nYear = 0x7F & (pRootEnt->Date >> 9);
KTRACE("d-d-d ",nYear,nMonth,nDate);
nHour = pRootEnt->Time >> 12 & 0x1F;
nMinute = pRootEnt->Time >> 5 & 0x3F;
KTRACE("d:d ",nHour,nMinute);
} -------------------------------------------------------------------------------- *********************************************************
哈哈&兵燹
最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好 Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知
K.表Knowlege 知識,就是本站的標語:Open our mind to make knowledge together!
希望能大家敞開心胸,將知識寶庫結合一起
------
**********************************************************
哈哈&兵燹
最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好
Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知
K.表Knowlege 知識,就是本站的標語:Open our mind