📄 cf.c
字号:
/*
**
** Compact Flash access routines
**
**
*/
#include "CF.h" // compact flash interface
#include "generic.h"
#include "fileio.h"
BYTE gblCFBuf [MEDIA_SECTOR_SIZE];
DISK glbDiskData;
// BPB FAT12
typedef struct __BPB_FAT12 {
SWORD BS_jmpBoot; // Jump Command
BYTE BS_OEMName[8]; // OEM name
WORD BPB_BytsPerSec; // BYTEs per sector
BYTE BPB_SecPerClus; // sectors per allocation unit
WORD BPB_RsvdSecCnt; // number of reserved sectors after start
BYTE BPB_NumFATs; // number of FATs
WORD BPB_RootEntCnt; // number of root directory entries
WORD BPB_TotSec16; // total number of sectors
BYTE BPB_Media; // media descriptor
WORD BPB_FATSz16; // number of sectors per FAT
WORD BPB_SecPerTrk; // sectors per track
WORD BPB_NumHeads; // number of heads
DWORD BPB_HiddSec; // number of hidden sectors
BYTE BS_Reserved0; // Nothing
BYTE BS_DrvNum; // Int 13 drive number
BYTE BS_Reserved1; // Nothing
BYTE BS_BootSig; // 0x29
BYTE BS_VolID[4]; // Volume Id
BYTE BS_VolLab[11]; // Volume Label
BYTE BS_FilSysType[8]; // File system type, not used for determination
}_BPB_FAT12;
typedef _BPB_FAT12 * BPB_FAT12;
// BPB FAT32
typedef struct __BPB_FAT32 {
SWORD BPB_jmpBoot; // Jump Command
BYTE BPB_OEMName[8]; // OEM name
WORD BPB_BytsPerSec; // BYTEs per sector
BYTE BPB_SecPerClus; // sectors per allocation unit
WORD BPB_RsvdSecCnt; // number of reserved sectors after start
BYTE BPB_NumFATs; // number of FATs
WORD BPB_RootEntCnt; // number of root directory entries
WORD BPB_TotSec16; // total number of sectors
BYTE BPB_Media; // media descriptor
WORD BPB_FATSz16; // number of sectors per FAT
WORD BPB_SecPerTrk; // sectors per track
WORD BPB_NumHeads; // number of heads
DWORD BPB_HiddSec; // number of hidden sectors
DWORD BPB_TotSec32; // New 32bit total sec count
DWORD BPB_FATSz32; // Sectors occupied by one FAT
WORD BPB_ExtFlags; // Presently active FAT as defined by bits 0-3 if bit 7 is 1
WORD BPB_FSVers; // FAT32 filesystem version, should be 0:0
DWORD BPB_RootClus; // start cluster of the root directory (should be 2)
WORD BPB_FSInfo; // filesystem info structure sector
WORD BPB_BkBootSec; // backup boot sector normally 6
BYTE BPB_Reserved[12]; // Reserved memory
BYTE BS_DrvNum; // Int 13 drive number
BYTE BS_Reserved1; // Nothing
BYTE BS_BootSig; // 0x29
BYTE BS_VolID[4]; // Volume Id
BYTE BS_VolLab[11]; // Volume Label
BYTE BS_FilSysType[8]; // File system type, not used for determination
}_BPB_FAT32;
typedef _BPB_FAT32 * BPB_FAT32;
// BPB FAT16
typedef struct __BPB_FAT16 {
SWORD BS_jmpBoot; // Jump Command
BYTE BS_OEMName[8]; // OEM name
WORD BPB_BytsPerSec; // BYTEs per sector
BYTE BPB_SecPerClus; // sectors per allocation unit
WORD BPB_RsvdSecCnt; // number of reserved sectors after start
BYTE BPB_NumFATs; // number of FATs
WORD BPB_RootEntCnt; // number of root directory entries
WORD BPB_TotSec16; // total number of sectors
BYTE BPB_Media; // media descriptor
WORD BPB_FATSz16; // number of sectors per FAT
WORD BPB_SecPerTrk; // sectors per track
WORD BPB_NumHeads; // number of heads
DWORD BPB_HiddSec; // number of hidden sectors
DWORD BPB_TotSec32; // New 32bit total sec count
BYTE BS_DrvNum; // Int 13 drive number
BYTE BS_Reserved1; // Nothing
BYTE BS_BootSig; // 0x29
BYTE BS_VolID[4]; // Volume Id
BYTE BS_VolLab[11]; // Volume Label
BYTE BS_FilSysType[8]; // File system type, not used for determination
}_BPB_FAT16;
#define BSI_BOOTJMP 0
#define BSI_OEM_NAME 3
#define BSI_BytesPerSec 11
#define BSI_SecPerClus 13
#define BSI_RsvdSecCount 14
#define BSI_NumFATs 16
#define BSI_RootEntCnt 17
#define BSI_TotSec16 19
#define BSI_Media 21
#define BSI_FATSz16 22
#define BSI_SecPerTrk 24
#define BSI_NumHeads 26
#define BSI_HiddSec 28
#define BSI_TotSec32 32
#define BSI_DrvNum 36
#define BSI_Reserved1 37
#define BSI_BootSig 38
#define BSI_VolID 39
#define BSI_VolLab 43
#define BSI_FilSysType 54
typedef _BPB_FAT16 * BPB_FAT16;
// PTE_FAT - Partition Table Entry
typedef struct _PTE_FAT
{
BYTE PTE_BootDes; // Boot Descriptor, 0x80
SWORD PTE_FrstPartSect; // First Partion Sector
BYTE PTE_FSDesc; // File System Descriptor
SWORD PTE_LstPartSect; // Last Partion Sector
DWORD PTE_FrstSect; // First Sector Position
DWORD PTE_NumSect; // Number of Sectors in partion
}PTE_FAT;
// PT_FAT - Partition Table
typedef struct __PT_FAT
{
BYTE ConsChkRtn[446];
PTE_FAT Partition0;
PTE_FAT Partition1;
PTE_FAT Partition2;
PTE_FAT Partition3;
BYTE Signature0; // 0x55
BYTE Signature1; // 0xAA
}_PT_FAT;
typedef _PT_FAT * PT_FAT;
typedef struct __BS
{
union
{
_BPB_FAT32 FAT_32;
_BPB_FAT16 FAT_16;
_BPB_FAT12 FAT_12;
}FAT;
BYTE Reserved[MEDIA_SECTOR_SIZE-sizeof(_BPB_FAT32)-2];
BYTE Signature0; // 0x55
BYTE Signature1; // 0xAA
}_BS;
typedef _BS * BS;
// Master Boot Record offsets
#define FO_MBR 0L // master boot record sector LBA
#ifndef EOF
#define EOF (-1)
#endif
#define RAMread( a, f) *(a+f)
#define FAT_GOOD_SIGN_0 0x55
#define FAT_GOOD_SIGN_1 0xAA
#define BOOTABLE 0x80
#define NON_BOOTABLE 0x00
CETYPE StartupCard(DISK *dsk);
CETYPE DISKmount( DISK *dsk, BYTE* b);
CETYPE LoadMBR(DISK *dsk);
BYTE LoadBootSector(DISK *dsk);
void StopCard (DISK * dsk);
BYTE ReadByte( BYTE* pBuffer, WORD index );
WORD ReadWord( BYTE* pBuffer, WORD index );
DWORD ReadDWord( BYTE* pBuffer, WORD index );
CETYPE StartupCard(DISK *dsk)
{
CETYPE error;
BYTE * buffer = gblCFBuf;
if((error = DISKmount( dsk, buffer)) == CE_GOOD)
{
}
else
{
// there was an issue so turn off the card
StopCard(dsk);
}
return(error);
}
CETYPE DISKmount( DISK *dsk, BYTE* b)
{
BYTE i;
CETYPE error = CE_GOOD;
dsk->mount = FALSE; // default invalid
dsk->buffer = b; // assign buffer
// Load the Master Boot Record (partition)
if((error = LoadMBR(dsk)) == CE_GOOD)
{
// Now the boot sector
if((error = LoadBootSector(dsk)) == CE_GOOD)
dsk->mount = TRUE; // Mark that the DISK mounted successfully
}
return(error);
} // -- mount
CETYPE LoadMBR(DISK *dsk)
{
PT_FAT Partition;
CETYPE error = CE_GOOD;
BYTE type;
// Get the partition table from the MBR
if ( SECTORread( FO_MBR, dsk->buffer) != TRUE)
error = CE_BAD_SECTOR_READ;
else
{
// assign it the partition table strucutre
Partition = (PT_FAT)dsk->buffer;
// Ensure its good
if((Partition->Signature0 != FAT_GOOD_SIGN_0) || (Partition->Signature1 != FAT_GOOD_SIGN_1))
{
error = CE_BAD_PARTITION;
}
else
{
/* Valid Master Boot Record Loaded */
// Get the 32 bit offset to the first partition
dsk->firsts = Partition->Partition0.PTE_FrstSect;
// check if the partition type is acceptable
type = Partition->Partition0.PTE_FSDesc;
switch (type)
{
case 0x01:
dsk->type = FAT12;
error = CE_CARDFAT12;
break;
case 0x04:
case 0x06:
case 0x0E:
dsk->type = FAT16;
break;
case 0x0B:
case 0x0C:
dsk->type = FAT32; // and error out
error = CE_CARDFAT32;
break;
default:
error = CE_BAD_PARTITION;
} // switch
}
}
return(error);
}// -- LoadMBR
BYTE LoadBootSector(DISK *dsk)
{
WORD RootDirSectors;
DWORD TotSec,DataSec;
BYTE error = CE_GOOD;
BS BootSec; // boot sector, assume its FAT16 til we know better
BYTE * test1;
WORD * test2;
SWORD * test3;
DWORD * test4;
WORD BytesPerSec;
// Get the Boot sector
if ( SECTORread( dsk->firsts, dsk->buffer) != TRUE)
error = CE_BAD_SECTOR_READ;
else
{
// Assign the type
BootSec = (BS)dsk->buffer;
//Verify the Boot Sector is valid
if((BootSec->Signature0 != FAT_GOOD_SIGN_0) || (BootSec->Signature1 != FAT_GOOD_SIGN_1))
{
error = CE_NOT_FORMATTED;
}
else
{
// determine the number of sectors in one FAT (FATSz)
dsk->fatsize = ReadWord( dsk->buffer, BSI_FATSz16 );
// Figure out the total number of sectors
TotSec = ReadWord( dsk->buffer, BSI_TotSec16 );
if( TotSec == 0 )
TotSec = ReadDWord( dsk->buffer, BSI_TotSec32 );
// 6. get the full partition/drive layout
// 6.1 determine the size of a cluster
dsk->SecPerClus = ReadByte( dsk->buffer, BSI_SecPerClus );
// 6.2 determine fat, root and data lbas
// FAT = first sector in partition (boot record) + reserved records
dsk->fat = dsk->firsts + ReadWord( dsk->buffer, BSI_RsvdSecCount );
// 6.3 fatcopy is the number of FAT tables
dsk->fatcopy = ReadByte( dsk->buffer, BSI_NumFATs );
// 6.4 MAX ROOT is the maximum number of entries in the root directory
dsk->maxroot = ReadWord( dsk->buffer, BSI_RootEntCnt );
// "root" Is the sector location of the root directory
dsk->root = dsk->fat + (dsk->fatcopy * dsk->fatsize);
BytesPerSec = ReadWord( dsk->buffer, BSI_BytesPerSec );
if( BytesPerSec == 0 || (BytesPerSec & 1) == 1 ) //cannot be 0 or odd
return( CE_NOT_FORMATTED );
RootDirSectors = ((dsk->maxroot * 32) + (BytesPerSec - 1)) / BytesPerSec;
// figure out how many data sectors there is
DataSec = TotSec - (dsk->root + RootDirSectors);
dsk->maxcls = DataSec / dsk->SecPerClus;
// Straight out of MS FAT Hardware White Paper
if(dsk->maxcls < 4085)
{
/* Volume is FAT12 */
dsk->type = FAT12;
error = CE_CARDFAT12;
}
else
{
if(dsk->maxcls < 65525)
{
/* Volume is FAT16 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -