📄 sdfat.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
//------------------------------------------------------------------------------
//
// File: sdfat.c implements FAT parser
//
#include <sdfat.h>
#include <sdmdd.h>
#include <oal.h>
// file system struct must be one byte alignment
#pragma pack(push, 1)
// detailed info can reference:
// 1.The MultiMediaCard System Specification Version 3.31 Chapter 12
// 2.SD Memory Card Specifications Part 2 FILE SYSTEM SPECIFICATION Version 1.0
// 3.ISO/IEC 9293:1994 Volume and file structure of disk cartridges for information interchange
// 4 Microsoft Extensible Firmware Initiative FAT32 File System Specification
#define DEFAULT_SECTOR_SIZE 512
// partition table
#define PARTITION_NUMBER 4 // for MBR
#define PARTITION_NORMAL 0x00 // BootIndicator
#define PARTITION_SYSTEM 0x80
#define PARTITION_EMPTY 0x00 // SystemId
#define PARTITION_FAT12 0x01
#define PARTITION_FAT16 0x04
#define PARTITION_EXT 0x05
#define PARTITION_FAT16B 0x06
#define PARTITION_FAT32 0x0B
#define PARTITION_FAT32L 0x0C
#define PARTITION_FAT16L 0x0E
#define PARTITION_EXTL 0x0F
typedef __unaligned struct _PARTITION_TABLE{
UINT8 BootIndicator;
UINT8 StartingHead;
UINT16 StartingSector:6;
UINT16 StartingCylinder:10;
UINT8 SystemId;
UINT8 EndingHead;
UINT16 EndingSector:6;
UINT16 EndingCylinder:10;
UINT32 RelativeSector;
UINT32 TotalSector;
}PARTITION_TABLE, *PPARTITION_TABLE;
// master boot record(MBR)
#define MASTERBOOT_CODELEN 446
#define MASTERBOOT_SIGNATURE 0xAA55
typedef __unaligned struct _MASTERBOOT_RECORD{
UINT8 BootCode[MASTERBOOT_CODELEN];
PARTITION_TABLE Partition[PARTITION_NUMBER];
UINT16 Signature;
}MASTERBOOT_RECORD, *PMASTERBOOT_RECORD;
// partition boot sector
#define RAWPARTITION_JUMPCODELEN 3
#define RAWPARTITION_CREATORIDLEN 8
#define RAWPARTITION_VOLUMELABLELEN 11
#define RAWPARTITION_FILESYSTEMLEN 8
#define RAWPARTITION_RESERVED1LEN 12
#define RAWPARTITION_RESERVED2LEN 420
#define RAWPARTITION_SIGNATURE 0xAA55
#define RAWPARTITION_EFDCSIGNATURE 0x29
typedef __unaligned struct _RAWPARTITION{
UINT8 JumpCode[RAWPARTITION_JUMPCODELEN]; // FDC part
UINT8 CreatorID[RAWPARTITION_CREATORIDLEN];
UINT16 SectorSize;
UINT8 SectorPerCluster;
UINT16 ReservedSector;
UINT8 NumberOfFAT;
UINT16 NumberOfRootEntry;
UINT16 TotalSector;
UINT8 MediumId;
UINT16 SectorPerFAT;
UINT16 SectorPerTrack;
UINT16 NumberOfSide;
UINT32 NumberOfHiddenSector; // EFDC part
UINT32 TotalSector2; // when TotalSector==0, use this
union{
__unaligned struct{ // FAT12/FAT16
UINT8 PhysicalDiskNumber;
UINT8 Reserved;
UINT8 EFDCSignature;
UINT32 VolumeSerialNumber;
UINT8 VolumeLabel[RAWPARTITION_VOLUMELABLELEN];
UINT8 FileSystemType[RAWPARTITION_FILESYSTEMLEN];
};
__unaligned struct{ // FAT32
UINT32 SectorPerFAT;
UINT16 ExtentFlag;
UINT16 FileSystemVersion;
UINT32 RootEntryCluster;
UINT16 FileSystemInfomation;
UINT16 BackupBootSector;
UINT8 Reserved1[RAWPARTITION_RESERVED1LEN];
UINT8 PhysicalDiskNumber;
UINT8 Reserved;
UINT8 EFDCSignature;
UINT32 VolumeSerialNumber;
UINT8 VolumeLabel[RAWPARTITION_VOLUMELABLELEN];
UINT8 FileSystemType[RAWPARTITION_FILESYSTEMLEN];
}FAT32;
};
UINT8 Reserved2[RAWPARTITION_RESERVED2LEN];
UINT16 Signature;
}RAWPARTITION, *PRAWPARTITION;
// FAT12 entry
#define FAT12_BITS 12
#define FAT12_BYTES2ENTRIES(Bytes) ((8*(Bytes))/FAT12_BITS)
#define FAT12_ENTRIES2BYTES(Entries) ((FAT12_BITS*(Entries))/8)
#define FAT12_FREE 0x000
#define FAT12_ALLOC 0x002 // to FATEntryNumber-1
#define FAT12_DEFECT 0xFF7
#define FAT12_END 0xFF8 // to 0xFFF
#define FAT12_ISFREE(Cluster) ((Cluster)==FAT12_FREE)
#define FAT12_ISALLOC(Cluster, Number) ((Cluster)>=FAT12_ALLOC&&(Cluster)<(Number))
#define FAT12_ISDEFECT(Cluster) ((Cluster)==FAT12_DEFECT)
#define FAT12_ISEND(Cluster) ((Cluster)>=FAT12_END&&(Cluster)<=0xFFF)
// help macro to implement FAT12_GETENTRY, don't call them directly
#define FAT12_ISEVENENTRY(Cluster) (Cluster%2==0)
#define FAT12_GETEVENENTRY(FatTable, Offset) (((FatTable[Offset+1]&0x0F)<<8)|FatTable[Offset])
#define FAT12_GETODDENTRY(FatTable, Offset) ((FatTable[Offset+1]<<4)|(FatTable[Offset]>>4))
#define FAT12_GETENTRY(FatTable, Start, Cluster) \
(FAT12_ISEVENENTRY((Cluster)) \
?FAT12_GETEVENENTRY(((UINT8*)(FatTable)), (FAT12_ENTRIES2BYTES(Cluster)-FAT12_ENTRIES2BYTES(Start))) \
:FAT12_GETODDENTRY(((UINT8*)(FatTable)), (FAT12_ENTRIES2BYTES(Cluster)-FAT12_ENTRIES2BYTES(Start))))
// FAT16 entry
#define FAT16_BITS 16
#define FAT16_BYTES2ENTRIES(Bytes) ((8*(Bytes))/FAT16_BITS)
#define FAT16_ENTRIES2BYTES(Entries) ((FAT16_BITS*(Entries))/8)
#define FAT16_FREE 0x0000
#define FAT16_ALLOC 0x0002 // to FATEntryNumber-1
#define FAT16_DEFECT 0xFFF7
#define FAT16_END 0xFFF8 // to 0xFFFF
#define FAT16_ISFREE(Cluster) ((Cluster)==FAT16_FREE)
#define FAT16_ISALLOC(Cluster, Number) ((Cluster)>=FAT16_ALLOC&&(Cluster)<(Number))
#define FAT16_ISDEFECT(Cluster) ((Cluster)==FAT16_DEFECT)
#define FAT16_ISEND(Cluster) ((Cluster)>=FAT16_END&&(Cluster)<=0xFFFF)
#define FAT16_GETENTRY(FatTable, Start, Cluster) \
(*(UINT16*)(((UINT8*)(FatTable))+(FAT16_ENTRIES2BYTES(Cluster)-FAT16_ENTRIES2BYTES(Start))))
// FAT32 entry
#define FAT32_BITS 32
#define FAT32_BYTES2ENTRIES(Bytes) ((8*(Bytes))/FAT32_BITS)
#define FAT32_ENTRIES2BYTES(Entries) ((FAT32_BITS*(Entries))/8)
#define FAT32_FREE 0x00000000
#define FAT32_ALLOC 0x00000002 // to FATEntryNumber-1
#define FAT32_DEFECT 0x0FFFFFF7
#define FAT32_END 0x0FFFFFF8 // to 0x0FFFFFFF
#define FAT32_ISFREE(Cluster) ((Cluster)==FAT32_FREE)
#define FAT32_ISALLOC(Cluster, Number) ((Cluster)>=FAT32_ALLOC&&(Cluster)<(Number))
#define FAT32_ISDEFECT(Cluster) ((Cluster)==FAT32_DEFECT)
#define FAT32_ISEND(Cluster) ((Cluster)>=FAT32_END&&(Cluster)<=0x0FFFFFFF)
#define FAT32_GETENTRY(FatTable, Start, Cluster) \
((*(UINT32*)(((UINT8*)(FatTable))+(FAT32_ENTRIES2BYTES(Cluster)-FAT32_ENTRIES2BYTES(Start))))&0x0FFFFFFF)
// FAT(shared by FAT12/FAT16/FAT32)
#define FAT_ROOTCLUSTER 0 // pseudo for FAT12/FAT16 root
#define FAT_STARTCLUSTER 2
// directory entry
#define DIRENTRY_NAMELEN 8 // short name
#define DIRENTRY_EXTENSIONLEN 3
#define DIRENTRY_NAMELEN1 5 // long name support
#define DIRENTRY_NAMELEN2 6
#define DIRENTRY_NAMELEN3 2
#define DIRENTRY_MAXCOMP 20
#define DIRENTRY_LASTCOMP 0x40
#define DIRENTRY_COMPMASK 0xBF
#define DIRENTRY_ENDCHAR ' ' // special character for name
#define DIRENTRY_DELETED 0xE5
#define DIRENTRY_NEVERUSED 0x00
#define DIRENTRY_KANJI 0x05
#define DIRENTRY_PADDING 0xFFFF
#define DIRENTRY_READONLY 0x01 // Attribute
#define DIRENTRY_HIDDEN 0x02
#define DIRENTRY_SYSTEM 0x04
#define DIRENTRY_VOLUMELABEL 0x08
#define DIRENTRY_SUBDIR 0x10
#define DIRENTRY_ARCHIVE 0x20
#define DIRENTRY_LONGNAME 0x0f
#define DIRENTRY_HOUR(Time) ((Time)/2048) // Time
#define DIRENTRY_MINUTE(Time) (((Time)/32)&0x3f)
#define DIRENTRY_SECOND(Time) (((Time)&0x1f)*2)
#define DIRENTRY_SECONDEX(Time, TimeTenth) (DIRENTRY_SECOND(Time)+(TimeTenth)/100)
#define DIRENTRY_MILLISECOND(TimeTenth) (10*((TimeTenth)%100))
#define DIRENTRY_YEAR(Date) (1980+((Date)/512)) // Date
#define DIRENTRY_MONTH(Date) (((Date)/32)&0x0f)
#define DIRENTRY_DAY(Date) ((Date)&0x1f)
typedef union _RAWDIRENTRY{
__unaligned struct{ // short name
UINT8 Name[DIRENTRY_NAMELEN];
UINT8 Extension[DIRENTRY_EXTENSIONLEN];
UINT8 Attribute;
UINT8 Reserved;
UINT8 CreatedTimeTenth;
UINT16 CreatedTime;
UINT16 CreatedDate;
UINT16 AccessedDate;
UINT16 StartingClusterHi;
UINT16 ModifiedTime;
UINT16 ModifiedDate;
UINT16 StartingCluster;
UINT32 FileLength;
};
__unaligned struct{ // long name
UINT8 Ordinal;
UINT16 Name1[DIRENTRY_NAMELEN1];
UINT8 Reserved1;
UINT8 Type; // always zero
UINT8 CheckSum;
UINT16 Name2[DIRENTRY_NAMELEN2];
UINT16 Reserved2;
UINT16 Name3[DIRENTRY_NAMELEN3];
};
}RAWDIRENTRY, *PRAWDIRENTRY;
#pragma pack(pop)
// file system struct internal representation
#define PART_UNKNOWN 0
#define PART_FAT12 1
#define PART_FAT16 2
#define PART_FAT32 3
typedef struct _PARTITION{
BOOL Bootable;
DWORD FileSystem;
DWORD StartingPartition; // partition
DWORD PartitionLength;
DWORD StartingFATEntry; // FAT
DWORD FATEntryNumber;
DWORD StartingRootEntry; // root
DWORD RootEntryLength;
DWORD StartingCluster; // cluster
DWORD LengthPerCluster;
// cache for speed up
BYTE CacheFATEntry[DEFAULT_SECTOR_SIZE];
DWORD CacheFATEntryBegin;
DWORD CacheFATEntryEnd;
}PARTITION, *PPARTITION;
typedef struct _DIRENTRY{
CHAR FileName[MAX_PATH+1];
DWORD Attribute;
DWORD CheckSum;
DWORD Ordinal;
SYSTEMTIME Created;
SYSTEMTIME Accessed;
SYSTEMTIME Modified;
DWORD StartingCluster;
DWORD FileLength;
}DIRENTRY, *PDIRENTRY;
// global state variable
#define MAX_PARTITION 26
static DWORD MasterBootRecordNumber;
static MASTERBOOT_RECORD MasterBootRecord[MAX_PARTITION];
static DWORD PartitionNumber;
static RAWPARTITION RawPartition[MAX_PARTITION];
static PARTITION Partition[MAX_PARTITION];
// help routine for FAT entry
static DWORD GetFATEntryBits(DWORD dwPartNo){
DWORD dwBits = FAT_ERROR;
switch(Partition[dwPartNo].FileSystem){
case PART_FAT12:
dwBits = FAT12_BITS;
break;
case PART_FAT16:
dwBits = FAT16_BITS;
break;
case PART_FAT32:
dwBits = FAT32_BITS;
break;
}
return dwBits;
}
static DWORD GetFATEntryBytes(DWORD dwPartNo){
DWORD dwBits = GetFATEntryBits(dwPartNo);
if(dwBits != FAT_ERROR){
dwBits = (dwBits+7)/8;
}
return dwBits;
}
static DWORD ConvertBytesToFATEntries(DWORD dwPartNo, DWORD dwBytes){
DWORD dwEntries = FAT_ERROR;
switch(Partition[dwPartNo].FileSystem){
case PART_FAT12:
dwEntries = FAT12_BYTES2ENTRIES(dwBytes);
break;
case PART_FAT16:
dwEntries = FAT16_BYTES2ENTRIES(dwBytes);
break;
case PART_FAT32:
dwEntries = FAT32_BYTES2ENTRIES(dwBytes);
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -