⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdfat.c

📁 Windows CE 6.0 BSP for VOIP sample phone. Intel PXA270 platform.
💻 C
📖 第 1 页 / 共 4 页
字号:
//
// 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 + -