FatPartition.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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/FsCache.h"
  36. #include "../common/FsStructs.h"
  37. /** Type for FAT12 partition */
  38. const uint8_t FAT_TYPE_FAT12 = 12;
  39. /** Type for FAT12 partition */
  40. const uint8_t FAT_TYPE_FAT16 = 16;
  41. /** Type for FAT12 partition */
  42. const uint8_t FAT_TYPE_FAT32 = 32;
  43. //------------------------------------------------------------------------------
  44. /**
  45. * \brief Cache type for a sector.
  46. */
  47. union cache_t {
  48. /** Used to access cached file data sectors. */
  49. uint8_t data[512];
  50. /** Used to access cached FAT16 entries. */
  51. uint16_t fat16[256];
  52. /** Used to access cached FAT32 entries. */
  53. uint32_t fat32[128];
  54. /** Used to access cached directory entries. */
  55. DirFat_t dir[16];
  56. };
  57. //==============================================================================
  58. /**
  59. * \class FatPartition
  60. * \brief Access FAT16 and FAT32 partitions on raw file devices.
  61. */
  62. class FatPartition {
  63. public:
  64. /** Create an instance of FatPartition
  65. */
  66. FatPartition() {}
  67. /** \return The shift count required to multiply by bytesPerCluster. */
  68. uint8_t bytesPerClusterShift() const {
  69. return m_sectorsPerClusterShift + m_bytesPerSectorShift;
  70. }
  71. /** \return Number of bytes in a cluster. */
  72. uint16_t bytesPerCluster() const {
  73. return m_bytesPerSector << m_sectorsPerClusterShift;
  74. }
  75. /** \return Number of bytes per sector. */
  76. uint16_t bytesPerSector() const {
  77. return m_bytesPerSector;
  78. }
  79. /** \return The shift count required to multiply by bytesPerCluster. */
  80. uint8_t bytesPerSectorShift() const {
  81. return m_bytesPerSectorShift;
  82. }
  83. /** \return Mask for sector offset. */
  84. uint16_t sectorMask() const {
  85. return m_sectorMask;
  86. }
  87. /** \return The volume's cluster size in sectors. */
  88. uint8_t sectorsPerCluster() const {
  89. return m_sectorsPerCluster;
  90. }
  91. #ifndef DOXYGEN_SHOULD_SKIP_THIS
  92. // Use sectorsPerCluster(). blocksPerCluster() will be removed in the future.
  93. uint8_t blocksPerCluster() __attribute__ ((deprecated)) {return sectorsPerCluster();} //NOLINT
  94. #endif // DOXYGEN_SHOULD_SKIP_THIS
  95. /** \return The number of sectors in one FAT. */
  96. uint32_t sectorsPerFat() const {
  97. return m_sectorsPerFat;
  98. }
  99. /** Clear the cache and returns a pointer to the cache. Not for normal apps.
  100. * \return A pointer to the cache buffer or zero if an error occurs.
  101. */
  102. uint8_t* cacheClear() {
  103. return m_cache.clear();
  104. }
  105. /** \return The total number of clusters in the volume. */
  106. uint32_t clusterCount() const {
  107. return m_lastCluster - 1;
  108. }
  109. /** \return The shift count required to multiply by sectorsPerCluster. */
  110. uint8_t sectorsPerClusterShift() const {
  111. return m_sectorsPerClusterShift;
  112. }
  113. /** \return The logical sector number for the start of file data. */
  114. uint32_t dataStartSector() const {
  115. return m_dataStartSector;
  116. }
  117. /** \return The number of File Allocation Tables. */
  118. uint8_t fatCount() const {
  119. return 2;
  120. }
  121. /** \return The logical sector number for the start of the first FAT. */
  122. uint32_t fatStartSector() const {
  123. return m_fatStartSector;
  124. }
  125. /** \return The FAT type of the volume. Values are 12, 16 or 32. */
  126. uint8_t fatType() const {
  127. return m_fatType;
  128. }
  129. /** Volume free space in clusters.
  130. *
  131. * \return Count of free clusters for success or -1 if an error occurs.
  132. */
  133. int32_t freeClusterCount();
  134. /** Initialize a FAT partition.
  135. *
  136. * \param[in] dev BlockDevice for this partition.
  137. * \param[in] part The partition to be used. Legal values for \a part are
  138. * 1-4 to use the corresponding partition on a device formatted with
  139. * a MBR, Master Boot Record, or zero if the device is formatted as
  140. * a super floppy with the FAT boot sector in sector zero.
  141. *
  142. * \return true for success or false for failure.
  143. */
  144. bool init(BlockDevice* dev, uint8_t part = 1);
  145. /** \return The number of entries in the root directory for FAT16 volumes. */
  146. uint16_t rootDirEntryCount() const {
  147. return m_rootDirEntryCount;
  148. }
  149. /** \return The logical sector number for the start of the root directory
  150. on FAT16 volumes or the first cluster number on FAT32 volumes. */
  151. uint32_t rootDirStart() const {
  152. return m_rootDirStart;
  153. }
  154. /** \return The number of sectors in the volume */
  155. uint32_t volumeSectorCount() const {
  156. return sectorsPerCluster()*clusterCount();
  157. }
  158. /** Debug access to FAT table
  159. *
  160. * \param[in] n cluster number.
  161. * \param[out] v value of entry
  162. * \return -1 error, 0 EOC, else 1.
  163. */
  164. int8_t dbgFat(uint32_t n, uint32_t* v) {
  165. return fatGet(n, v);
  166. }
  167. /**
  168. * Check for BlockDevice busy.
  169. *
  170. * \return true if busy else false.
  171. */
  172. bool isBusy() {return m_blockDev->isBusy();}
  173. //----------------------------------------------------------------------------
  174. #ifndef DOXYGEN_SHOULD_SKIP_THIS
  175. void dmpDirSector(print_t* pr, uint32_t sector);
  176. void dmpFat(print_t* pr, uint32_t start, uint32_t count);
  177. void dmpRootDir(print_t* pr);
  178. void dmpSector(print_t* pr, uint32_t sector, uint8_t bits = 8);
  179. #endif // DOXYGEN_SHOULD_SKIP_THIS
  180. //----------------------------------------------------------------------------
  181. private:
  182. /** FatFile allowed access to private members. */
  183. friend class FatFile;
  184. //----------------------------------------------------------------------------
  185. static const uint8_t m_bytesPerSectorShift = 9;
  186. static const uint16_t m_bytesPerSector = 512;
  187. static const uint16_t m_sectorMask = 0x1FF;
  188. //----------------------------------------------------------------------------
  189. BlockDevice* m_blockDev; // sector device
  190. uint8_t m_sectorsPerCluster; // Cluster size in sectors.
  191. uint8_t m_clusterSectorMask; // Mask to extract sector of cluster.
  192. uint8_t m_sectorsPerClusterShift; // Cluster count to sector count shift.
  193. uint8_t m_fatType = 0; // Volume type (12, 16, OR 32).
  194. uint16_t m_rootDirEntryCount; // Number of entries in FAT16 root dir.
  195. uint32_t m_allocSearchStart; // Start cluster for alloc search.
  196. uint32_t m_sectorsPerFat; // FAT size in sectors
  197. uint32_t m_dataStartSector; // First data sector number.
  198. uint32_t m_fatStartSector; // Start sector for first FAT.
  199. uint32_t m_lastCluster; // Last cluster number in FAT.
  200. uint32_t m_rootDirStart; // Start sector FAT16, cluster FAT32.
  201. //----------------------------------------------------------------------------
  202. // sector I/O functions.
  203. bool cacheSafeRead(uint32_t sector, uint8_t* dst) {
  204. return m_cache.cacheSafeRead(sector, dst);
  205. }
  206. bool cacheSafeRead(uint32_t sector, uint8_t* dst, size_t count) {
  207. return m_cache.cacheSafeRead(sector, dst, count);
  208. }
  209. bool cacheSafeWrite(uint32_t sector, const uint8_t* dst) {
  210. return m_cache.cacheSafeWrite(sector, dst);
  211. }
  212. bool cacheSafeWrite(uint32_t sector, const uint8_t* dst, size_t count) {
  213. return m_cache.cacheSafeWrite(sector, dst, count);
  214. }
  215. bool readSector(uint32_t sector, uint8_t* dst) {
  216. return m_blockDev->readSector(sector, dst);
  217. }
  218. bool syncDevice() {
  219. return m_blockDev->syncDevice();
  220. }
  221. bool writeSector(uint32_t sector, const uint8_t* src) {
  222. return m_blockDev->writeSector(sector, src);
  223. }
  224. #if MAINTAIN_FREE_CLUSTER_COUNT
  225. int32_t m_freeClusterCount; // Count of free clusters in volume.
  226. void setFreeClusterCount(int32_t value) {
  227. m_freeClusterCount = value;
  228. }
  229. void updateFreeClusterCount(int32_t change) {
  230. if (m_freeClusterCount >= 0) {
  231. m_freeClusterCount += change;
  232. }
  233. }
  234. #else // MAINTAIN_FREE_CLUSTER_COUNT
  235. void setFreeClusterCount(int32_t value) {
  236. (void)value;
  237. }
  238. void updateFreeClusterCount(int32_t change) {
  239. (void)change;
  240. }
  241. #endif // MAINTAIN_FREE_CLUSTER_COUNT
  242. // sector caches
  243. FsCache m_cache;
  244. #if USE_SEPARATE_FAT_CACHE
  245. FsCache m_fatCache;
  246. cache_t* cacheFetchFat(uint32_t sector, uint8_t options) {
  247. options |= FsCache::CACHE_STATUS_MIRROR_FAT;
  248. return reinterpret_cast<cache_t*>(m_fatCache.get(sector, options));
  249. }
  250. bool cacheSync() {
  251. return m_cache.sync() && m_fatCache.sync() && syncDevice();
  252. }
  253. #else // USE_SEPARATE_FAT_CACHE
  254. cache_t* cacheFetchFat(uint32_t sector, uint8_t options) {
  255. options |= FsCache::CACHE_STATUS_MIRROR_FAT;
  256. return cacheFetchData(sector, options);
  257. }
  258. bool cacheSync() {
  259. return m_cache.sync() && syncDevice();
  260. }
  261. #endif // USE_SEPARATE_FAT_CACHE
  262. cache_t* cacheFetchData(uint32_t sector, uint8_t options) {
  263. return reinterpret_cast<cache_t*>(m_cache.get(sector, options));
  264. }
  265. void cacheInvalidate() {
  266. m_cache.invalidate();
  267. }
  268. bool cacheSyncData() {
  269. return m_cache.sync();
  270. }
  271. cache_t* cacheAddress() {
  272. return reinterpret_cast<cache_t*>(m_cache.cacheBuffer());
  273. }
  274. uint32_t cacheSectorNumber() {
  275. return m_cache.sector();
  276. }
  277. void cacheDirty() {
  278. m_cache.dirty();
  279. }
  280. //----------------------------------------------------------------------------
  281. bool allocateCluster(uint32_t current, uint32_t* next);
  282. bool allocContiguous(uint32_t count, uint32_t* firstCluster);
  283. uint8_t sectorOfCluster(uint32_t position) const {
  284. return (position >> 9) & m_clusterSectorMask;
  285. }
  286. uint32_t clusterStartSector(uint32_t cluster) const {
  287. return m_dataStartSector + ((cluster - 2) << m_sectorsPerClusterShift);
  288. }
  289. int8_t fatGet(uint32_t cluster, uint32_t* value);
  290. bool fatPut(uint32_t cluster, uint32_t value);
  291. bool fatPutEOC(uint32_t cluster) {
  292. return fatPut(cluster, 0x0FFFFFFF);
  293. }
  294. bool freeChain(uint32_t cluster);
  295. bool isEOC(uint32_t cluster) const {
  296. return cluster > m_lastCluster;
  297. }
  298. };
  299. #endif // FatPartition