utility

Dependents:   SD

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FatStructs.h Source File

FatStructs.h

Go to the documentation of this file.
00001 /* Arduino SdFat Library
00002  * Copyright (C) 2009 by William Greiman
00003  *
00004  * This file is part of the Arduino SdFat Library
00005  *
00006  * This Library is free software: you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation, either version 3 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This Library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with the Arduino SdFat Library.  If not, see
00018  * <http://www.gnu.org/licenses/>.
00019  */
00020 #ifndef FatStructs_h
00021 #define FatStructs_h
00022 /**
00023  * \file
00024  * FAT file structures
00025  */
00026 /*
00027  * mostly from Microsoft document fatgen103.doc
00028  * http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx
00029  */
00030 //------------------------------------------------------------------------------
00031 /** Value for byte 510 of boot block or MBR */
00032 uint8_t const BOOTSIG0 = 0X55;
00033 /** Value for byte 511 of boot block or MBR */
00034 uint8_t const BOOTSIG1 = 0XAA;
00035 //------------------------------------------------------------------------------
00036 /**
00037  * \struct partitionTable
00038  * \brief MBR partition table entry
00039  *
00040  * A partition table entry for a MBR formatted storage device.
00041  * The MBR partition table has four entries.
00042  */
00043 struct partitionTable {
00044           /**
00045            * Boot Indicator . Indicates whether the volume is the active
00046            * partition.  Legal values include: 0X00. Do not use for booting.
00047            * 0X80 Active partition.
00048            */
00049   uint8_t  boot;
00050           /**
00051             * Head part of Cylinder-head-sector address of the first block in
00052             * the partition. Legal values are 0-255. Only used in old PC BIOS.
00053             */
00054   uint8_t  beginHead;
00055           /**
00056            * Sector part of Cylinder-head-sector address of the first block in
00057            * the partition. Legal values are 1-63. Only used in old PC BIOS.
00058            */
00059   unsigned beginSector : 6;
00060            /** High bits cylinder for first block in partition. */
00061   unsigned beginCylinderHigh : 2;
00062           /**
00063            * Combine beginCylinderLow with beginCylinderHigh. Legal values
00064            * are 0-1023.  Only used in old PC BIOS.
00065            */
00066   uint8_t  beginCylinderLow;
00067           /**
00068            * Partition type. See defines that begin with PART_TYPE_ for
00069            * some Microsoft partition types.
00070            */
00071   uint8_t  type;
00072           /**
00073            * head part of cylinder-head-sector address of the last sector in the
00074            * partition.  Legal values are 0-255. Only used in old PC BIOS.
00075            */
00076   uint8_t  endHead;
00077           /**
00078            * Sector part of cylinder-head-sector address of the last sector in
00079            * the partition.  Legal values are 1-63. Only used in old PC BIOS.
00080            */
00081   unsigned endSector : 6;
00082            /** High bits of end cylinder */
00083   unsigned endCylinderHigh : 2;
00084           /**
00085            * Combine endCylinderLow with endCylinderHigh. Legal values
00086            * are 0-1023.  Only used in old PC BIOS.
00087            */
00088   uint8_t  endCylinderLow;
00089            /** Logical block address of the first block in the partition. */
00090   uint32_t firstSector;
00091            /** Length of the partition, in blocks. */
00092   uint32_t totalSectors;
00093 };
00094 /** Type name for partitionTable */
00095 typedef struct partitionTable part_t;
00096 //------------------------------------------------------------------------------
00097 /**
00098  * \struct masterBootRecord
00099  *
00100  * \brief Master Boot Record
00101  *
00102  * The first block of a storage device that is formatted with a MBR.
00103  */
00104 struct masterBootRecord {
00105            /** Code Area for master boot program. */
00106   uint8_t  codeArea[440];
00107            /** Optional WindowsNT disk signature. May contain more boot code. */
00108   uint32_t diskSignature;
00109            /** Usually zero but may be more boot code. */
00110   uint16_t usuallyZero;
00111            /** Partition tables. */
00112   part_t   part[4];
00113            /** First MBR signature byte. Must be 0X55 */
00114   uint8_t  mbrSig0;
00115            /** Second MBR signature byte. Must be 0XAA */
00116   uint8_t  mbrSig1;
00117 };
00118 /** Type name for masterBootRecord */
00119 typedef struct masterBootRecord mbr_t;
00120 //------------------------------------------------------------------------------
00121 /** 
00122  * \struct biosParmBlock
00123  *
00124  * \brief BIOS parameter block
00125  * 
00126  *  The BIOS parameter block describes the physical layout of a FAT volume.
00127  */
00128 struct biosParmBlock {
00129           /**
00130            * Count of bytes per sector. This value may take on only the
00131            * following values: 512, 1024, 2048 or 4096
00132            */
00133   uint16_t bytesPerSector;
00134           /**
00135            * Number of sectors per allocation unit. This value must be a
00136            * power of 2 that is greater than 0. The legal values are
00137            * 1, 2, 4, 8, 16, 32, 64, and 128.
00138            */
00139   uint8_t  sectorsPerCluster;
00140           /**
00141            * Number of sectors before the first FAT.
00142            * This value must not be zero.
00143            */
00144   uint16_t reservedSectorCount;
00145           /** The count of FAT data structures on the volume. This field should
00146            *  always contain the value 2 for any FAT volume of any type.
00147            */
00148   uint8_t  fatCount;
00149           /**
00150           * For FAT12 and FAT16 volumes, this field contains the count of
00151           * 32-byte directory entries in the root directory. For FAT32 volumes,
00152           * this field must be set to 0. For FAT12 and FAT16 volumes, this
00153           * value should always specify a count that when multiplied by 32
00154           * results in a multiple of bytesPerSector.  FAT16 volumes should
00155           * use the value 512.
00156           */
00157   uint16_t rootDirEntryCount;
00158           /**
00159            * This field is the old 16-bit total count of sectors on the volume.
00160            * This count includes the count of all sectors in all four regions
00161            * of the volume. This field can be 0; if it is 0, then totalSectors32
00162            * must be non-zero.  For FAT32 volumes, this field must be 0. For
00163            * FAT12 and FAT16 volumes, this field contains the sector count, and
00164            * totalSectors32 is 0 if the total sector count fits
00165            * (is less than 0x10000).
00166            */
00167   uint16_t totalSectors16;
00168           /**
00169            * This dates back to the old MS-DOS 1.x media determination and is
00170            * no longer usually used for anything.  0xF8 is the standard value
00171            * for fixed (non-removable) media. For removable media, 0xF0 is
00172            * frequently used. Legal values are 0xF0 or 0xF8-0xFF.
00173            */
00174   uint8_t  mediaType;
00175           /**
00176            * Count of sectors occupied by one FAT on FAT12/FAT16 volumes.
00177            * On FAT32 volumes this field must be 0, and sectorsPerFat32
00178            * contains the FAT size count.
00179            */
00180   uint16_t sectorsPerFat16;
00181            /** Sectors per track for interrupt 0x13. Not used otherwise. */
00182   uint16_t sectorsPerTrtack;
00183            /** Number of heads for interrupt 0x13.  Not used otherwise. */
00184   uint16_t headCount;
00185           /**
00186            * Count of hidden sectors preceding the partition that contains this
00187            * FAT volume. This field is generally only relevant for media
00188            *  visible on interrupt 0x13.
00189            */
00190   uint32_t hidddenSectors;
00191           /**
00192            * This field is the new 32-bit total count of sectors on the volume.
00193            * This count includes the count of all sectors in all four regions
00194            * of the volume.  This field can be 0; if it is 0, then
00195            * totalSectors16 must be non-zero.
00196            */
00197   uint32_t totalSectors32;
00198           /**
00199            * Count of sectors occupied by one FAT on FAT32 volumes.
00200            */
00201   uint32_t sectorsPerFat32;
00202           /**
00203            * This field is only defined for FAT32 media and does not exist on
00204            * FAT12 and FAT16 media.
00205            * Bits 0-3 -- Zero-based number of active FAT.
00206            *             Only valid if mirroring is disabled.
00207            * Bits 4-6 -- Reserved.
00208            * Bit 7  -- 0 means the FAT is mirrored at runtime into all FATs.
00209              *        -- 1 means only one FAT is active; it is the one referenced in bits 0-3.
00210            * Bits 8-15  -- Reserved.
00211            */
00212   uint16_t fat32Flags;
00213           /**
00214            * FAT32 version. High byte is major revision number.
00215            * Low byte is minor revision number. Only 0.0 define.
00216            */
00217   uint16_t fat32Version;
00218           /**
00219            * Cluster number of the first cluster of the root directory for FAT32.
00220            * This usually 2 but not required to be 2.
00221            */
00222   uint32_t fat32RootCluster;
00223           /**
00224            * Sector number of FSINFO structure in the reserved area of the
00225            * FAT32 volume. Usually 1.
00226            */
00227   uint16_t fat32FSInfo;
00228           /**
00229            * If non-zero, indicates the sector number in the reserved area
00230            * of the volume of a copy of the boot record. Usually 6.
00231            * No value other than 6 is recommended.
00232            */
00233   uint16_t fat32BackBootBlock;
00234           /**
00235            * Reserved for future expansion. Code that formats FAT32 volumes
00236            * should always set all of the bytes of this field to 0.
00237            */
00238   uint8_t  fat32Reserved[12];
00239 };
00240 /** Type name for biosParmBlock */
00241 typedef struct biosParmBlock bpb_t;
00242 //------------------------------------------------------------------------------
00243 /**
00244  * \struct fat32BootSector
00245  *
00246  * \brief Boot sector for a FAT16 or FAT32 volume.
00247  * 
00248  */  
00249 struct fat32BootSector {
00250            /** X86 jmp to boot program */
00251   uint8_t  jmpToBootCode[3];
00252            /** informational only - don't depend on it */
00253   char     oemName[8];
00254            /** BIOS Parameter Block */
00255   bpb_t    bpb;
00256            /** for int0x13 use value 0X80 for hard drive */
00257   uint8_t  driveNumber;
00258            /** used by Windows NT - should be zero for FAT */
00259   uint8_t  reserved1;
00260            /** 0X29 if next three fields are valid */
00261   uint8_t  bootSignature;
00262            /** usually generated by combining date and time */
00263   uint32_t volumeSerialNumber;
00264            /** should match volume label in root dir */
00265   char     volumeLabel[11];
00266            /** informational only - don't depend on it */
00267   char     fileSystemType[8];
00268            /** X86 boot code */
00269   uint8_t  bootCode[420];
00270            /** must be 0X55 */
00271   uint8_t  bootSectorSig0;
00272            /** must be 0XAA */
00273   uint8_t  bootSectorSig1;
00274 };
00275 //------------------------------------------------------------------------------
00276 // End Of Chain values for FAT entries
00277 /** FAT16 end of chain value used by Microsoft. */
00278 uint16_t const FAT16EOC = 0XFFFF;
00279 /** Minimum value for FAT16 EOC.  Use to test for EOC. */
00280 uint16_t const FAT16EOC_MIN = 0XFFF8;
00281 /** FAT32 end of chain value used by Microsoft. */
00282 uint32_t const FAT32EOC = 0X0FFFFFFF;
00283 /** Minimum value for FAT32 EOC.  Use to test for EOC. */
00284 uint32_t const FAT32EOC_MIN = 0X0FFFFFF8;
00285 /** Mask a for FAT32 entry. Entries are 28 bits. */
00286 uint32_t const FAT32MASK = 0X0FFFFFFF;
00287 
00288 /** Type name for fat32BootSector */
00289 typedef struct fat32BootSector fbs_t;
00290 //------------------------------------------------------------------------------
00291 /**
00292  * \struct directoryEntry
00293  * \brief FAT short directory entry
00294  *
00295  * Short means short 8.3 name, not the entry size.
00296  *  
00297  * Date Format. A FAT directory entry date stamp is a 16-bit field that is 
00298  * basically a date relative to the MS-DOS epoch of 01/01/1980. Here is the
00299  * format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the 
00300  * 16-bit word):
00301  *   
00302  * Bits 9-15: Count of years from 1980, valid value range 0-127 
00303  * inclusive (1980-2107).
00304  *   
00305  * Bits 5-8: Month of year, 1 = January, valid value range 1-12 inclusive.
00306  *
00307  * Bits 0-4: Day of month, valid value range 1-31 inclusive.
00308  *
00309  * Time Format. A FAT directory entry time stamp is a 16-bit field that has
00310  * a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the 
00311  * 16-bit word, bit 15 is the MSB of the 16-bit word).
00312  *   
00313  * Bits 11-15: Hours, valid value range 0-23 inclusive.
00314  * 
00315  * Bits 5-10: Minutes, valid value range 0-59 inclusive.
00316  *      
00317  * Bits 0-4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds).
00318  *   
00319  * The valid time range is from Midnight 00:00:00 to 23:59:58.
00320  */
00321 struct directoryEntry {
00322            /**
00323             * Short 8.3 name.
00324             * The first eight bytes contain the file name with blank fill.
00325             * The last three bytes contain the file extension with blank fill.
00326             */
00327   uint8_t  name[11];
00328           /** Entry attributes.
00329            *
00330            * The upper two bits of the attribute byte are reserved and should
00331            * always be set to 0 when a file is created and never modified or
00332            * looked at after that.  See defines that begin with DIR_ATT_.
00333            */
00334   uint8_t  attributes;
00335           /**
00336            * Reserved for use by Windows NT. Set value to 0 when a file is
00337            * created and never modify or look at it after that.
00338            */
00339   uint8_t  reservedNT;
00340           /**
00341            * The granularity of the seconds part of creationTime is 2 seconds
00342            * so this field is a count of tenths of a second and its valid
00343            * value range is 0-199 inclusive. (WHG note - seems to be hundredths)
00344            */
00345   uint8_t  creationTimeTenths;
00346            /** Time file was created. */
00347   uint16_t creationTime;
00348            /** Date file was created. */
00349   uint16_t creationDate;
00350           /**
00351            * Last access date. Note that there is no last access time, only
00352            * a date.  This is the date of last read or write. In the case of
00353            * a write, this should be set to the same date as lastWriteDate.
00354            */
00355   uint16_t lastAccessDate;
00356           /**
00357            * High word of this entry's first cluster number (always 0 for a
00358            * FAT12 or FAT16 volume).
00359            */
00360   uint16_t firstClusterHigh;
00361            /** Time of last write. File creation is considered a write. */
00362   uint16_t lastWriteTime;
00363            /** Date of last write. File creation is considered a write. */
00364   uint16_t lastWriteDate;
00365            /** Low word of this entry's first cluster number. */
00366   uint16_t firstClusterLow;
00367            /** 32-bit unsigned holding this file's size in bytes. */
00368   uint32_t fileSize;
00369 };
00370 //------------------------------------------------------------------------------
00371 // Definitions for directory entries
00372 //
00373 /** Type name for directoryEntry */
00374 typedef struct directoryEntry dir_t;
00375 /** escape for name[0] = 0XE5 */
00376 uint8_t const DIR_NAME_0XE5 = 0X05;
00377 /** name[0] value for entry that is free after being "deleted" */
00378 uint8_t const DIR_NAME_DELETED = 0XE5;
00379 /** name[0] value for entry that is free and no allocated entries follow */
00380 uint8_t const DIR_NAME_FREE = 0X00;
00381 /** file is read-only */
00382 uint8_t const DIR_ATT_READ_ONLY = 0X01;
00383 /** File should hidden in directory listings */
00384 uint8_t const DIR_ATT_HIDDEN = 0X02;
00385 /** Entry is for a system file */
00386 uint8_t const DIR_ATT_SYSTEM = 0X04;
00387 /** Directory entry contains the volume label */
00388 uint8_t const DIR_ATT_VOLUME_ID = 0X08;
00389 /** Entry is for a directory */
00390 uint8_t const DIR_ATT_DIRECTORY = 0X10;
00391 /** Old DOS archive bit for backup support */
00392 uint8_t const DIR_ATT_ARCHIVE = 0X20;
00393 /** Test value for long name entry.  Test is
00394   (d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. */
00395 uint8_t const DIR_ATT_LONG_NAME = 0X0F;
00396 /** Test mask for long name entry */
00397 uint8_t const DIR_ATT_LONG_NAME_MASK = 0X3F;
00398 /** defined attribute bits */
00399 uint8_t const DIR_ATT_DEFINED_BITS = 0X3F;
00400 /** Directory entry is part of a long name */
00401 static inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir) {
00402   return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME;
00403 }
00404 /** Mask for file/subdirectory tests */
00405 uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY);
00406 /** Directory entry is for a file */
00407 static inline uint8_t DIR_IS_FILE(const dir_t* dir) {
00408   return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0;
00409 }
00410 /** Directory entry is for a subdirectory */
00411 static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) {
00412   return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY;
00413 }
00414 /** Directory entry is for a file or subdirectory */
00415 static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) {
00416   return (dir->attributes & DIR_ATT_VOLUME_ID) == 0;
00417 }
00418 #endif  // FatStructs_h