FatPartition.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /**
  2. * Copyright (c) 2011-2020 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 FatPartition_h
  26. #define FatPartition_h
  27. /**
  28. * \file
  29. * \brief FatPartition class
  30. */
  31. #include <stddef.h>
  32. #include "FatLibConfig.h"
  33. #include "../common/SysCall.h"
  34. #include "../common/BlockDevice.h"
  35. #include "../common/FsStructs.h"
  36. /** Type for FAT12 partition */
  37. const uint8_t FAT_TYPE_FAT12 = 12;
  38. /** Type for FAT12 partition */
  39. const uint8_t FAT_TYPE_FAT16 = 16;
  40. /** Type for FAT12 partition */
  41. const uint8_t FAT_TYPE_FAT32 = 32;
  42. //------------------------------------------------------------------------------
  43. // Forward declaration of FatPartition.
  44. class FatPartition;
  45. //------------------------------------------------------------------------------
  46. /**
  47. * \brief Cache for an raw data sector.
  48. */
  49. union cache_t {
  50. /** Used to access cached file data sectors. */
  51. uint8_t data[512];
  52. /** Used to access cached FAT16 entries. */
  53. uint16_t fat16[256];
  54. /** Used to access cached FAT32 entries. */
  55. uint32_t fat32[128];
  56. /** Used to access cached directory entries. */
  57. DirFat_t dir[16];
  58. };
  59. //==============================================================================
  60. /**
  61. * \class FatCache
  62. * \brief Sector cache.
  63. */
  64. class FatCache {
  65. public:
  66. /** Cached sector is dirty */
  67. static const uint8_t CACHE_STATUS_DIRTY = 1;
  68. /** Cashed sector is FAT entry and must be mirrored in second FAT. */
  69. static const uint8_t CACHE_STATUS_MIRROR_FAT = 2;
  70. /** Cache sector status bits */
  71. static const uint8_t CACHE_STATUS_MASK
  72. = CACHE_STATUS_DIRTY | CACHE_STATUS_MIRROR_FAT;
  73. /** Sync existing sector but do not read new sector. */
  74. static const uint8_t CACHE_OPTION_NO_READ = 4;
  75. /** Cache sector for read. */
  76. static const uint8_t CACHE_FOR_READ = 0;
  77. /** Cache sector for write. */
  78. static const uint8_t CACHE_FOR_WRITE = CACHE_STATUS_DIRTY;
  79. /** Reserve cache sector for write - do not read from sector device. */
  80. static const uint8_t CACHE_RESERVE_FOR_WRITE
  81. = CACHE_STATUS_DIRTY | CACHE_OPTION_NO_READ;
  82. /** \return Cache sector address. */
  83. cache_t* buffer() {
  84. return &m_buffer;
  85. }
  86. /** Set current sector dirty. */
  87. void dirty() {
  88. m_status |= CACHE_STATUS_DIRTY;
  89. }
  90. /** Initialize the cache.
  91. * \param[in] vol FatPartition that owns this FatCache.
  92. */
  93. void init(FatPartition *vol) {
  94. m_part = vol;
  95. invalidate();
  96. }
  97. /** Invalidate current cache sector. */
  98. void invalidate() {
  99. m_status = 0;
  100. m_lbn = 0XFFFFFFFF;
  101. }
  102. /** \return dirty status */
  103. bool isDirty() {
  104. return m_status & CACHE_STATUS_DIRTY;
  105. }
  106. /** \return Logical sector number for cached sector. */
  107. uint32_t sector() {
  108. return m_lbn;
  109. }
  110. /** Read a sector into the cache.
  111. * \param[in] sector Sector to read.
  112. * \param[in] option mode for cached sector.
  113. * \return Address of cached sector. */
  114. cache_t* read(uint32_t sector, uint8_t option);
  115. /** Write current sector if dirty.
  116. * \return true for success or false for failure.
  117. */
  118. bool sync();
  119. private:
  120. uint8_t m_status;
  121. FatPartition* m_part;
  122. uint32_t m_lbn;
  123. cache_t m_buffer;
  124. };
  125. //==============================================================================
  126. /**
  127. * \class FatPartition
  128. * \brief Access FAT16 and FAT32 partitions on raw file devices.
  129. */
  130. class FatPartition {
  131. public:
  132. /** Create an instance of FatPartition
  133. */
  134. FatPartition() : m_fatType(0) {}
  135. /** \return The shift count required to multiply by bytesPerCluster. */
  136. uint8_t bytesPerClusterShift() {
  137. return m_sectorsPerClusterShift + m_bytesPerSectorShift;
  138. }
  139. /** \return Number of bytes in a cluster. */
  140. uint16_t bytesPerCluster() {
  141. return m_bytesPerSector << m_sectorsPerClusterShift;
  142. }
  143. /** \return Number of bytes per sector. */
  144. uint16_t bytesPerSector() {
  145. return m_bytesPerSector;
  146. }
  147. /** \return The shift count required to multiply by bytesPerCluster. */
  148. uint8_t bytesPerSectorShift() {
  149. return m_bytesPerSectorShift;
  150. }
  151. /** \return Mask for sector offset. */
  152. uint16_t sectorMask() {
  153. return m_sectorMask;
  154. }
  155. /** \return The volume's cluster size in sectors. */
  156. uint8_t sectorsPerCluster() const {
  157. return m_sectorsPerCluster;
  158. }
  159. #ifndef DOXYGEN_SHOULD_SKIP_THIS
  160. // Use sectorsPerCluster(). blocksPerCluster() will be removed in the future.
  161. uint8_t blocksPerCluster() __attribute__ ((deprecated)) {return sectorsPerCluster();} //NOLINT
  162. #endif // DOXYGEN_SHOULD_SKIP_THIS
  163. /** \return The number of sectors in one FAT. */
  164. uint32_t sectorsPerFat() const {
  165. return m_sectorsPerFat;
  166. }
  167. /** Clear the cache and returns a pointer to the cache. Not for normal apps.
  168. * \return A pointer to the cache buffer or zero if an error occurs.
  169. */
  170. cache_t* cacheClear() {
  171. if (!cacheSync()) {
  172. return nullptr;
  173. }
  174. m_cache.invalidate();
  175. return m_cache.buffer();
  176. }
  177. /** \return The total number of clusters in the volume. */
  178. uint32_t clusterCount() const {
  179. return m_lastCluster - 1;
  180. }
  181. /** \return The shift count required to multiply by sectorsPerCluster. */
  182. uint8_t sectorsPerClusterShift() const {
  183. return m_sectorsPerClusterShift;
  184. }
  185. /** \return The logical sector number for the start of file data. */
  186. uint32_t dataStartSector() const {
  187. return m_dataStartSector;
  188. }
  189. /** \return The number of File Allocation Tables. */
  190. uint8_t fatCount() {
  191. return 2;
  192. }
  193. /** \return The logical sector number for the start of the first FAT. */
  194. uint32_t fatStartSector() const {
  195. return m_fatStartSector;
  196. }
  197. /** \return The FAT type of the volume. Values are 12, 16 or 32. */
  198. uint8_t fatType() const {
  199. return m_fatType;
  200. }
  201. /** Volume free space in clusters.
  202. *
  203. * \return Count of free clusters for success or -1 if an error occurs.
  204. */
  205. int32_t freeClusterCount();
  206. /** Initialize a FAT partition.
  207. *
  208. * \param[in] dev BlockDevice for this partition.
  209. * \param[in] part The partition to be used. Legal values for \a part are
  210. * 1-4 to use the corresponding partition on a device formatted with
  211. * a MBR, Master Boot Record, or zero if the device is formatted as
  212. * a super floppy with the FAT boot sector in sector zero.
  213. *
  214. * \return true for success or false for failure.
  215. */
  216. bool init(BlockDevice* dev, uint8_t part = 1);
  217. /** \return The number of entries in the root directory for FAT16 volumes. */
  218. uint16_t rootDirEntryCount() const {
  219. return m_rootDirEntryCount;
  220. }
  221. /** \return The logical sector number for the start of the root directory
  222. on FAT16 volumes or the first cluster number on FAT32 volumes. */
  223. uint32_t rootDirStart() const {
  224. return m_rootDirStart;
  225. }
  226. /** \return The number of sectors in the volume */
  227. uint32_t volumeSectorCount() const {
  228. return sectorsPerCluster()*clusterCount();
  229. }
  230. /** Debug access to FAT table
  231. *
  232. * \param[in] n cluster number.
  233. * \param[out] v value of entry
  234. * \return -1 error, 0 EOC, else 1.
  235. */
  236. int8_t dbgFat(uint32_t n, uint32_t* v) {
  237. return fatGet(n, v);
  238. }
  239. //----------------------------------------------------------------------------
  240. #ifndef DOXYGEN_SHOULD_SKIP_THIS
  241. void dmpDirSector(print_t* pr, uint32_t sector);
  242. void dmpFat(print_t* pr, uint32_t start, uint32_t count);
  243. void dmpRootDir(print_t* pr);
  244. void dmpSector(print_t* pr, uint32_t sector, uint8_t bits = 8);
  245. #endif // DOXYGEN_SHOULD_SKIP_THIS
  246. //----------------------------------------------------------------------------
  247. private:
  248. /** FatCache allowed access to private members. */
  249. friend class FatCache;
  250. /** FatFile allowed access to private members. */
  251. friend class FatFile;
  252. //----------------------------------------------------------------------------
  253. static const uint8_t m_bytesPerSectorShift = 9;
  254. static const uint16_t m_bytesPerSector = 512;
  255. static const uint16_t m_sectorMask = 0x1FF;
  256. //----------------------------------------------------------------------------
  257. BlockDevice* m_blockDev; // sector device
  258. uint8_t m_sectorsPerCluster; // Cluster size in sectors.
  259. uint8_t m_clusterSectorMask; // Mask to extract sector of cluster.
  260. uint8_t m_sectorsPerClusterShift; // Cluster count to sector count shift.
  261. uint8_t m_fatType; // Volume type (12, 16, OR 32).
  262. uint16_t m_rootDirEntryCount; // Number of entries in FAT16 root dir.
  263. uint32_t m_allocSearchStart; // Start cluster for alloc search.
  264. uint32_t m_sectorsPerFat; // FAT size in sectors
  265. uint32_t m_dataStartSector; // First data sector number.
  266. uint32_t m_fatStartSector; // Start sector for first FAT.
  267. uint32_t m_lastCluster; // Last cluster number in FAT.
  268. uint32_t m_rootDirStart; // Start sector FAT16, cluster FAT32.
  269. //----------------------------------------------------------------------------
  270. // sector I/O functions.
  271. bool readSector(uint32_t sector, uint8_t* dst) {
  272. return m_blockDev->readSector(sector, dst);
  273. }
  274. bool syncDevice() {
  275. return m_blockDev->syncDevice();
  276. }
  277. bool writeSector(uint32_t sector, const uint8_t* src) {
  278. return m_blockDev->writeSector(sector, src);
  279. }
  280. #if USE_MULTI_SECTOR_IO
  281. bool readSectors(uint32_t sector, uint8_t* dst, size_t ns) {
  282. return m_blockDev->readSectors(sector, dst, ns);
  283. }
  284. bool writeSectors(uint32_t sector, const uint8_t* src, size_t ns) {
  285. return m_blockDev->writeSectors(sector, src, ns);
  286. }
  287. #endif // USE_MULTI_SECTOR_IO
  288. #if MAINTAIN_FREE_CLUSTER_COUNT
  289. int32_t m_freeClusterCount; // Count of free clusters in volume.
  290. void setFreeClusterCount(int32_t value) {
  291. m_freeClusterCount = value;
  292. }
  293. void updateFreeClusterCount(int32_t change) {
  294. if (m_freeClusterCount >= 0) {
  295. m_freeClusterCount += change;
  296. }
  297. }
  298. #else // MAINTAIN_FREE_CLUSTER_COUNT
  299. void setFreeClusterCount(int32_t value) {
  300. (void)value;
  301. }
  302. void updateFreeClusterCount(int32_t change) {
  303. (void)change;
  304. }
  305. #endif // MAINTAIN_FREE_CLUSTER_COUNT
  306. // sector caches
  307. FatCache m_cache;
  308. #if USE_SEPARATE_FAT_CACHE
  309. FatCache m_fatCache;
  310. cache_t* cacheFetchFat(uint32_t sector, uint8_t options) {
  311. return m_fatCache.read(sector,
  312. options | FatCache::CACHE_STATUS_MIRROR_FAT);
  313. }
  314. bool cacheSync() {
  315. return m_cache.sync() && m_fatCache.sync() && syncDevice();
  316. }
  317. #else // USE_SEPARATE_FAT_CACHE
  318. cache_t* cacheFetchFat(uint32_t sector, uint8_t options) {
  319. return cacheFetchData(sector,
  320. options | FatCache::CACHE_STATUS_MIRROR_FAT);
  321. }
  322. bool cacheSync() {
  323. return m_cache.sync() && syncDevice();
  324. }
  325. #endif // USE_SEPARATE_FAT_CACHE
  326. cache_t* cacheFetchData(uint32_t sector, uint8_t options) {
  327. return m_cache.read(sector, options);
  328. }
  329. void cacheInvalidate() {
  330. m_cache.invalidate();
  331. }
  332. bool cacheSyncData() {
  333. return m_cache.sync();
  334. }
  335. cache_t* cacheAddress() {
  336. return m_cache.buffer();
  337. }
  338. uint32_t cacheSectorNumber() {
  339. return m_cache.sector();
  340. }
  341. void cacheDirty() {
  342. m_cache.dirty();
  343. }
  344. //----------------------------------------------------------------------------
  345. bool allocateCluster(uint32_t current, uint32_t* next);
  346. bool allocContiguous(uint32_t count, uint32_t* firstCluster);
  347. uint8_t sectorOfCluster(uint32_t position) const {
  348. return (position >> 9) & m_clusterSectorMask;
  349. }
  350. uint32_t clusterStartSector(uint32_t cluster) const;
  351. int8_t fatGet(uint32_t cluster, uint32_t* value);
  352. bool fatPut(uint32_t cluster, uint32_t value);
  353. bool fatPutEOC(uint32_t cluster) {
  354. return fatPut(cluster, 0x0FFFFFFF);
  355. }
  356. bool freeChain(uint32_t cluster);
  357. bool isEOC(uint32_t cluster) const {
  358. return cluster > m_lastCluster;
  359. }
  360. };
  361. #endif // FatPartition