FsStructs.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. /**
  2. * Copyright (c) 2011-2022 Bill Greiman
  3. * This file is part of the SdFat library for SD memory cards.
  4. *
  5. * MIT License
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a
  8. * copy of this software and associated documentation files (the "Software"),
  9. * to deal in the Software without restriction, including without limitation
  10. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. * and/or sell copies of the Software, and to permit persons to whom the
  12. * Software is furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included
  15. * in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. * DEALINGS IN THE SOFTWARE.
  24. */
  25. #ifndef FsStructs_h
  26. #define FsStructs_h
  27. #include <stddef.h>
  28. #include <stdint.h>
  29. //------------------------------------------------------------------------------
  30. void lbaToMbrChs(uint8_t* chs, uint32_t capacityMB, uint32_t lba);
  31. //------------------------------------------------------------------------------
  32. #if !defined(USE_SIMPLE_LITTLE_ENDIAN) || USE_SIMPLE_LITTLE_ENDIAN
  33. // assumes CPU is little-endian and handles alignment issues.
  34. inline uint16_t getLe16(const uint8_t* src) {
  35. return *reinterpret_cast<const uint16_t*>(src);
  36. }
  37. inline uint32_t getLe32(const uint8_t* src) {
  38. return *reinterpret_cast<const uint32_t*>(src);
  39. }
  40. inline uint64_t getLe64(const uint8_t* src) {
  41. return *reinterpret_cast<const uint64_t*>(src);
  42. }
  43. inline void setLe16(uint8_t* dst, uint16_t src) {
  44. *reinterpret_cast<uint16_t*>(dst) = src;
  45. }
  46. inline void setLe32(uint8_t* dst, uint32_t src) {
  47. *reinterpret_cast<uint32_t*>(dst) = src;
  48. }
  49. inline void setLe64(uint8_t* dst, uint64_t src) {
  50. *reinterpret_cast<uint64_t*>(dst) = src;
  51. }
  52. #else // USE_SIMPLE_LITTLE_ENDIAN
  53. inline uint16_t getLe16(const uint8_t* src) {
  54. return (uint16_t)src[0] << 0 |
  55. (uint16_t)src[1] << 8;
  56. }
  57. inline uint32_t getLe32(const uint8_t* src) {
  58. return (uint32_t)src[0] << 0 |
  59. (uint32_t)src[1] << 8 |
  60. (uint32_t)src[2] << 16 |
  61. (uint32_t)src[3] << 24;
  62. }
  63. inline uint64_t getLe64(const uint8_t* src) {
  64. return (uint64_t)src[0] << 0 |
  65. (uint64_t)src[1] << 8 |
  66. (uint64_t)src[2] << 16 |
  67. (uint64_t)src[3] << 24 |
  68. (uint64_t)src[4] << 32 |
  69. (uint64_t)src[5] << 40 |
  70. (uint64_t)src[6] << 48 |
  71. (uint64_t)src[7] << 56;
  72. }
  73. inline void setLe16(uint8_t* dst, uint16_t src) {
  74. dst[0] = src >> 0;
  75. dst[1] = src >> 8;
  76. }
  77. inline void setLe32(uint8_t* dst, uint32_t src) {
  78. dst[0] = src >> 0;
  79. dst[1] = src >> 8;
  80. dst[2] = src >> 16;
  81. dst[3] = src >> 24;
  82. }
  83. inline void setLe64(uint8_t* dst, uint64_t src) {
  84. dst[0] = src >> 0;
  85. dst[1] = src >> 8;
  86. dst[2] = src >> 16;
  87. dst[3] = src >> 24;
  88. dst[4] = src >> 32;
  89. dst[5] = src >> 40;
  90. dst[6] = src >> 48;
  91. dst[7] = src >> 56;
  92. }
  93. #endif // USE_SIMPLE_LITTLE_ENDIAN
  94. //------------------------------------------------------------------------------
  95. // Size of FAT and exFAT directory structures.
  96. const size_t FS_DIR_SIZE = 32;
  97. //------------------------------------------------------------------------------
  98. // Reserved characters for exFAT names and FAT LFN.
  99. inline bool lfnReservedChar(uint8_t c) {
  100. return c < 0X20 || c == '"' || c == '*' || c == '/' || c == ':'
  101. || c == '<' || c == '>' || c == '?' || c == '\\'|| c == '|';
  102. }
  103. //------------------------------------------------------------------------------
  104. // Reserved characters for FAT short 8.3 names.
  105. inline bool sfnReservedChar(uint8_t c) {
  106. if (c == '"' || c == '|' || c == '[' || c == '\\' || c == ']') {
  107. return true;
  108. }
  109. // *+,./ or :;<=>?
  110. if ((0X2A <= c && c <= 0X2F && c != 0X2D) || (0X3A <= c && c <= 0X3F)) {
  111. return true;
  112. }
  113. // Reserved if not in range (0X20, 0X7F).
  114. return !(0X20 < c && c < 0X7F);
  115. }
  116. //------------------------------------------------------------------------------
  117. const uint16_t MBR_SIGNATURE = 0xAA55;
  118. const uint16_t PBR_SIGNATURE = 0xAA55;
  119. typedef struct mbrPartition {
  120. uint8_t boot;
  121. uint8_t beginCHS[3];
  122. uint8_t type;
  123. uint8_t endCHS[3];
  124. uint8_t relativeSectors[4];
  125. uint8_t totalSectors[4];
  126. } MbrPart_t;
  127. //------------------------------------------------------------------------------
  128. typedef struct masterBootRecordSector {
  129. uint8_t bootCode[446];
  130. MbrPart_t part[4];
  131. uint8_t signature[2];
  132. } MbrSector_t;
  133. //------------------------------------------------------------------------------
  134. typedef struct partitionBootSector {
  135. uint8_t jmpInstruction[3];
  136. char oemName[8];
  137. uint8_t bpb[109];
  138. uint8_t bootCode[390];
  139. uint8_t signature[2];
  140. } pbs_t;
  141. //------------------------------------------------------------------------------
  142. typedef struct {
  143. uint8_t type;
  144. uint8_t data[31];
  145. } DirGeneric_t;
  146. //==============================================================================
  147. typedef struct {
  148. uint64_t position;
  149. uint32_t cluster;
  150. } fspos_t;
  151. //==============================================================================
  152. const uint8_t EXTENDED_BOOT_SIGNATURE = 0X29;
  153. typedef struct biosParameterBlockFat16 {
  154. uint8_t bytesPerSector[2];
  155. uint8_t sectorsPerCluster;
  156. uint8_t reservedSectorCount[2];
  157. uint8_t fatCount;
  158. uint8_t rootDirEntryCount[2];
  159. uint8_t totalSectors16[2];
  160. uint8_t mediaType;
  161. uint8_t sectorsPerFat16[2];
  162. uint8_t sectorsPerTrtack[2];
  163. uint8_t headCount[2];
  164. uint8_t hidddenSectors[4];
  165. uint8_t totalSectors32[4];
  166. uint8_t physicalDriveNumber;
  167. uint8_t extReserved;
  168. uint8_t extSignature;
  169. uint8_t volumeSerialNumber[4];
  170. uint8_t volumeLabel[11];
  171. uint8_t volumeType[8];
  172. } BpbFat16_t;
  173. //------------------------------------------------------------------------------
  174. typedef struct biosParameterBlockFat32 {
  175. uint8_t bytesPerSector[2];
  176. uint8_t sectorsPerCluster;
  177. uint8_t reservedSectorCount[2];
  178. uint8_t fatCount;
  179. uint8_t rootDirEntryCount[2];
  180. uint8_t totalSectors16[2];
  181. uint8_t mediaType;
  182. uint8_t sectorsPerFat16[2];
  183. uint8_t sectorsPerTrtack[2];
  184. uint8_t headCount[2];
  185. uint8_t hidddenSectors[4];
  186. uint8_t totalSectors32[4];
  187. uint8_t sectorsPerFat32[4];
  188. uint8_t fat32Flags[2];
  189. uint8_t fat32Version[2];
  190. uint8_t fat32RootCluster[4];
  191. uint8_t fat32FSInfoSector[2];
  192. uint8_t fat32BackBootSector[2];
  193. uint8_t fat32Reserved[12];
  194. uint8_t physicalDriveNumber;
  195. uint8_t extReserved;
  196. uint8_t extSignature;
  197. uint8_t volumeSerialNumber[4];
  198. uint8_t volumeLabel[11];
  199. uint8_t volumeType[8];
  200. } BpbFat32_t;
  201. //------------------------------------------------------------------------------
  202. typedef struct partitionBootSectorFat {
  203. uint8_t jmpInstruction[3];
  204. char oemName[8];
  205. union {
  206. uint8_t bpb[109];
  207. BpbFat16_t bpb16;
  208. BpbFat32_t bpb32;
  209. } bpb;
  210. uint8_t bootCode[390];
  211. uint8_t signature[2];
  212. } PbsFat_t;
  213. //------------------------------------------------------------------------------
  214. const uint32_t FSINFO_LEAD_SIGNATURE = 0X41615252;
  215. const uint32_t FSINFO_STRUCT_SIGNATURE = 0x61417272;
  216. const uint32_t FSINFO_TRAIL_SIGNATURE = 0xAA550000;
  217. typedef struct FsInfoSector {
  218. uint8_t leadSignature[4];
  219. uint8_t reserved1[480];
  220. uint8_t structSignature[4];
  221. uint8_t freeCount[4];
  222. uint8_t nextFree[4];
  223. uint8_t reserved2[12];
  224. uint8_t trailSignature[4];
  225. } FsInfo_t;
  226. //==============================================================================
  227. /** Attributes common to FAT and exFAT */
  228. const uint8_t FS_ATTRIB_READ_ONLY = 0x01;
  229. const uint8_t FS_ATTRIB_HIDDEN = 0x02;
  230. const uint8_t FS_ATTRIB_SYSTEM = 0x04;
  231. const uint8_t FS_ATTRIB_DIRECTORY = 0x10;
  232. const uint8_t FS_ATTRIB_ARCHIVE = 0x20;
  233. // Attributes that users can change.
  234. const uint8_t FS_ATTRIB_USER_SETTABLE = FS_ATTRIB_READ_ONLY |
  235. FS_ATTRIB_HIDDEN | FS_ATTRIB_SYSTEM | FS_ATTRIB_ARCHIVE;
  236. // Attributes to copy when a file is opened.
  237. const uint8_t FS_ATTRIB_COPY = FS_ATTRIB_USER_SETTABLE | FS_ATTRIB_DIRECTORY;
  238. //==============================================================================
  239. /** name[0] value for entry that is free and no allocated entries follow */
  240. const uint8_t FAT_NAME_FREE = 0X00;
  241. /** name[0] value for entry that is free after being "deleted" */
  242. const uint8_t FAT_NAME_DELETED = 0XE5;
  243. // Directiry attribute of volume label.
  244. const uint8_t FAT_ATTRIB_LABEL = 0x08;
  245. const uint8_t FAT_ATTRIB_LONG_NAME = 0X0F;
  246. /** Filename base-name is all lower case */
  247. const uint8_t FAT_CASE_LC_BASE = 0X08;
  248. /** Filename extension is all lower case.*/
  249. const uint8_t FAT_CASE_LC_EXT = 0X10;
  250. typedef struct {
  251. uint8_t name[11];
  252. uint8_t attributes;
  253. uint8_t caseFlags;
  254. uint8_t createTimeMs;
  255. uint8_t createTime[2];
  256. uint8_t createDate[2];
  257. uint8_t accessDate[2];
  258. uint8_t firstClusterHigh[2];
  259. uint8_t modifyTime[2];
  260. uint8_t modifyDate[2];
  261. uint8_t firstClusterLow[2];
  262. uint8_t fileSize[4];
  263. } DirFat_t;
  264. static inline bool isFatFile(const DirFat_t* dir) {
  265. return (dir->attributes & (FS_ATTRIB_DIRECTORY | FAT_ATTRIB_LABEL)) == 0;
  266. }
  267. static inline bool isFatFileOrSubdir(const DirFat_t* dir) {
  268. return (dir->attributes & FAT_ATTRIB_LABEL) == 0;
  269. }
  270. static inline uint8_t isFatLongName(const DirFat_t* dir) {
  271. return dir->attributes == FAT_ATTRIB_LONG_NAME;
  272. }
  273. static inline bool isFatSubdir(const DirFat_t* dir) {
  274. return (dir->attributes & (FS_ATTRIB_DIRECTORY | FAT_ATTRIB_LABEL))
  275. == FS_ATTRIB_DIRECTORY;
  276. }
  277. //------------------------------------------------------------------------------
  278. /**
  279. * Order mask that indicates the entry is the last long dir entry in a
  280. * set of long dir entries. All valid sets of long dir entries must
  281. * begin with an entry having this mask.
  282. */
  283. const uint8_t FAT_ORDER_LAST_LONG_ENTRY = 0X40;
  284. /** Max long file name length */
  285. const uint8_t FAT_MAX_LFN_LENGTH = 255;
  286. typedef struct {
  287. uint8_t order;
  288. uint8_t unicode1[10];
  289. uint8_t attributes;
  290. uint8_t mustBeZero1;
  291. uint8_t checksum;
  292. uint8_t unicode2[12];
  293. uint8_t mustBeZero2[2];
  294. uint8_t unicode3[4];
  295. } DirLfn_t;
  296. //==============================================================================
  297. inline uint32_t exFatChecksum(uint32_t sum, uint8_t data) {
  298. return (sum << 31) + (sum >> 1) + data;
  299. }
  300. //------------------------------------------------------------------------------
  301. typedef struct biosParameterBlockExFat {
  302. uint8_t mustBeZero[53];
  303. uint8_t partitionOffset[8];
  304. uint8_t volumeLength[8];
  305. uint8_t fatOffset[4];
  306. uint8_t fatLength[4];
  307. uint8_t clusterHeapOffset[4];
  308. uint8_t clusterCount[4];
  309. uint8_t rootDirectoryCluster[4];
  310. uint8_t volumeSerialNumber[4];
  311. uint8_t fileSystemRevision[2];
  312. uint8_t volumeFlags[2];
  313. uint8_t bytesPerSectorShift;
  314. uint8_t sectorsPerClusterShift;
  315. uint8_t numberOfFats;
  316. uint8_t driveSelect;
  317. uint8_t percentInUse;
  318. uint8_t reserved[7];
  319. } BpbExFat_t;
  320. //------------------------------------------------------------------------------
  321. typedef struct ExFatBootSector {
  322. uint8_t jmpInstruction[3];
  323. char oemName[8];
  324. BpbExFat_t bpb;
  325. uint8_t bootCode[390];
  326. uint8_t signature[2];
  327. } ExFatPbs_t;
  328. //------------------------------------------------------------------------------
  329. const uint32_t EXFAT_EOC = 0XFFFFFFFF;
  330. const uint8_t EXFAT_TYPE_BITMAP = 0X81;
  331. typedef struct {
  332. uint8_t type;
  333. uint8_t flags;
  334. uint8_t reserved[18];
  335. uint8_t firstCluster[4];
  336. uint8_t size[8];
  337. } DirBitmap_t;
  338. //------------------------------------------------------------------------------
  339. const uint8_t EXFAT_TYPE_UPCASE = 0X82;
  340. typedef struct {
  341. uint8_t type;
  342. uint8_t reserved1[3];
  343. uint8_t checksum[4];
  344. uint8_t reserved2[12];
  345. uint8_t firstCluster[4];
  346. uint8_t size[8];
  347. } DirUpcase_t;
  348. //------------------------------------------------------------------------------
  349. const uint8_t EXFAT_TYPE_LABEL = 0X83;
  350. typedef struct {
  351. uint8_t type;
  352. uint8_t labelLength;
  353. uint8_t unicode[22];
  354. uint8_t reserved[8];
  355. } DirLabel_t;
  356. //------------------------------------------------------------------------------
  357. // Last entry in directory.
  358. const uint8_t EXFAT_TYPE_END_DIR = 0X00;
  359. // Entry is used if bit is set.
  360. const uint8_t EXFAT_TYPE_USED = 0X80;
  361. const uint8_t EXFAT_TYPE_FILE = 0X85;
  362. // File attribute reserved since used for FAT volume label.
  363. const uint8_t EXFAT_ATTRIB_RESERVED = 0x08;
  364. typedef struct {
  365. uint8_t type;
  366. uint8_t setCount;
  367. uint8_t setChecksum[2];
  368. uint8_t attributes[2];
  369. uint8_t reserved1[2];
  370. uint8_t createTime[2];
  371. uint8_t createDate[2];
  372. uint8_t modifyTime[2];
  373. uint8_t modifyDate[2];
  374. uint8_t accessTime[2];
  375. uint8_t accessDate[2];
  376. uint8_t createTimeMs;
  377. uint8_t modifyTimeMs;
  378. uint8_t createTimezone;
  379. uint8_t modifyTimezone;
  380. uint8_t accessTimezone;
  381. uint8_t reserved2[7];
  382. } DirFile_t;
  383. const uint8_t EXFAT_TYPE_STREAM = 0XC0;
  384. const uint8_t EXFAT_FLAG_ALWAYS1 = 0x01;
  385. const uint8_t EXFAT_FLAG_CONTIGUOUS = 0x02;
  386. typedef struct {
  387. uint8_t type;
  388. uint8_t flags;
  389. uint8_t reserved1;
  390. uint8_t nameLength;
  391. uint8_t nameHash[2];
  392. uint8_t reserved2[2];
  393. uint8_t validLength[8];
  394. uint8_t reserved3[4];
  395. uint8_t firstCluster[4];
  396. uint8_t dataLength[8];
  397. } DirStream_t;
  398. const uint8_t EXFAT_TYPE_NAME = 0XC1;
  399. const uint8_t EXFAT_MAX_NAME_LENGTH = 255;
  400. typedef struct {
  401. uint8_t type;
  402. uint8_t mustBeZero;
  403. uint8_t unicode[30];
  404. } DirName_t;
  405. #endif // FsStructs_h