您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

351 行
12KB

  1. /* FatLib Library
  2. * Copyright (C) 2013 by William Greiman
  3. *
  4. * This file is part of the FatLib Library
  5. *
  6. * This Library is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This Library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with the FatLib Library. If not, see
  18. * <http://www.gnu.org/licenses/>.
  19. */
  20. #ifndef FatVolume_h
  21. #define FatVolume_h
  22. /**
  23. * \file
  24. * \brief FatVolume class
  25. */
  26. #include <stddef.h>
  27. #include "SystemInclude.h"
  28. #include "FatLibConfig.h"
  29. #include "FatStructs.h"
  30. //------------------------------------------------------------------------------
  31. #ifndef DOXYGEN_SHOULD_SKIP_THIS
  32. /** Macro for debug. */
  33. #define DEBUG_MODE 0
  34. #if DEBUG_MODE
  35. #define DBG_FAIL_MACRO Serial.print(F(__FILE__)); Serial.println(__LINE__)
  36. #define DBG_PRINT_IF(b) if (b) {Serial.println(F(#b)); DBG_FAIL_MACRO;}
  37. #define DBG_HALT_IF(b) if (b) {Serial.println(F(#b));\
  38. DBG_FAIL_MACRO; while (1);}
  39. #else // DEBUG_MODE
  40. #define DBG_FAIL_MACRO
  41. #define DBG_PRINT_IF(b)
  42. #define DBG_HALT_IF(b)
  43. #endif // DEBUG_MODE
  44. #endif // DOXYGEN_SHOULD_SKIP_THIS
  45. //------------------------------------------------------------------------------
  46. #if ENABLE_ARDUINO_FEATURES
  47. /** Use Print for Arduino */
  48. typedef Print print_t;
  49. #else // ENABLE_ARDUINO_FEATURES
  50. /**
  51. * \class CharWriter
  52. * \brief Character output - often serial port.
  53. */
  54. class CharWriter {
  55. public:
  56. virtual size_t write(char c) = 0;
  57. virtual size_t write(const char* s) = 0;
  58. };
  59. typedef CharWriter print_t;
  60. #endif // ENABLE_ARDUINO_FEATURES
  61. //------------------------------------------------------------------------------
  62. // Forward declaration of FatVolume.
  63. class FatVolume;
  64. //------------------------------------------------------------------------------
  65. /**
  66. * \brief Cache for an raw data block.
  67. */
  68. union cache_t {
  69. /** Used to access cached file data blocks. */
  70. uint8_t data[512];
  71. /** Used to access cached FAT16 entries. */
  72. uint16_t fat16[256];
  73. /** Used to access cached FAT32 entries. */
  74. uint32_t fat32[128];
  75. /** Used to access cached directory entries. */
  76. dir_t dir[16];
  77. /** Used to access a cached Master Boot Record. */
  78. mbr_t mbr;
  79. /** Used to access to a cached FAT boot sector. */
  80. fat_boot_t fbs;
  81. /** Used to access to a cached FAT32 boot sector. */
  82. fat32_boot_t fbs32;
  83. /** Used to access to a cached FAT32 FSINFO sector. */
  84. fat32_fsinfo_t fsinfo;
  85. };
  86. //==============================================================================
  87. /**
  88. * \class FatCache
  89. * \brief Block cache.
  90. */
  91. class FatCache {
  92. public:
  93. /** Cached block is dirty */
  94. static const uint8_t CACHE_STATUS_DIRTY = 1;
  95. /** Cashed block is FAT entry and must be mirrored in second FAT. */
  96. static const uint8_t CACHE_STATUS_MIRROR_FAT = 2;
  97. /** Cache block status bits */
  98. static const uint8_t CACHE_STATUS_MASK
  99. = CACHE_STATUS_DIRTY | CACHE_STATUS_MIRROR_FAT;
  100. /** Sync existing block but do not read new block. */
  101. static const uint8_t CACHE_OPTION_NO_READ = 4;
  102. /** Cache block for read. */
  103. static uint8_t const CACHE_FOR_READ = 0;
  104. /** Cache block for write. */
  105. static uint8_t const CACHE_FOR_WRITE = CACHE_STATUS_DIRTY;
  106. /** Reserve cache block for write - do not read from block device. */
  107. static uint8_t const CACHE_RESERVE_FOR_WRITE
  108. = CACHE_STATUS_DIRTY | CACHE_OPTION_NO_READ;
  109. /** \return Cache block address. */
  110. cache_t* block() {
  111. return &m_block;
  112. }
  113. /** Set current block dirty. */
  114. void dirty() {
  115. m_status |= CACHE_STATUS_DIRTY;
  116. }
  117. /** Initialize the cache.
  118. * \param[in] vol FatVolume that owns this FatCache.
  119. */
  120. void init(FatVolume *vol) {
  121. m_vol = vol;
  122. invalidate();
  123. }
  124. /** Invalidate current cache block. */
  125. void invalidate() {
  126. m_status = 0;
  127. m_lbn = 0XFFFFFFFF;
  128. }
  129. /** \return Logical block number for cached block. */
  130. uint32_t lbn() {
  131. return m_lbn;
  132. }
  133. /** Read a block into the cache.
  134. * \param[in] lbn Block to read.
  135. * \param[in] option mode for cached block.
  136. * \return Address of cached block. */
  137. cache_t* read(uint32_t lbn, uint8_t option);
  138. /** Write current block if dirty.
  139. * \return true for success else false.
  140. */
  141. bool sync();
  142. private:
  143. uint8_t m_status;
  144. FatVolume* m_vol;
  145. uint32_t m_lbn;
  146. cache_t m_block;
  147. };
  148. //==============================================================================
  149. /**
  150. * \class FatVolume
  151. * \brief Access FAT16 and FAT32 volumes on raw file devices.
  152. */
  153. class FatVolume {
  154. public:
  155. /** Create an instance of FatVolume
  156. */
  157. FatVolume() : m_fatType(0) {}
  158. /** \return The volume's cluster size in blocks. */
  159. uint8_t blocksPerCluster() const {
  160. return m_blocksPerCluster;
  161. }
  162. /** \return The number of blocks in one FAT. */
  163. uint32_t blocksPerFat() const {
  164. return m_blocksPerFat;
  165. }
  166. /** Clear the cache and returns a pointer to the cache. Not for normal apps.
  167. * \return A pointer to the cache buffer or zero if an error occurs.
  168. */
  169. cache_t* cacheClear() {
  170. if (!cacheSync()) {
  171. return 0;
  172. }
  173. m_cache.invalidate();
  174. return m_cache.block();
  175. }
  176. /** \return The total number of clusters in the volume. */
  177. uint32_t clusterCount() const {
  178. return m_lastCluster - 1;
  179. }
  180. /** \return The shift count required to multiply by blocksPerCluster. */
  181. uint8_t clusterSizeShift() const {
  182. return m_clusterSizeShift;
  183. }
  184. /** \return The logical block number for the start of file data. */
  185. uint32_t dataStartBlock() const {
  186. return m_dataStartBlock;
  187. }
  188. /** \return The number of File Allocation Tables. */
  189. uint8_t fatCount() {
  190. return 2;
  191. }
  192. /** \return The logical block number for the start of the first FAT. */
  193. uint32_t fatStartBlock() const {
  194. return m_fatStartBlock;
  195. }
  196. /** \return The FAT type of the volume. Values are 12, 16 or 32. */
  197. uint8_t fatType() const {
  198. return m_fatType;
  199. }
  200. /** Volume free space in clusters.
  201. *
  202. * \return Count of free clusters for success or -1 if an error occurs.
  203. */
  204. int32_t freeClusterCount();
  205. /** Initialize a FAT volume. Try partition one first then try super
  206. * floppy format.
  207. *
  208. * \return The value true is returned for success and
  209. * the value false is returned for failure.
  210. */
  211. bool init() {
  212. return init(1) || init(0);
  213. }
  214. /** Initialize a FAT volume.
  215. * \param[in] part The partition to be used. Legal values for \a part are
  216. * 1-4 to use the corresponding partition on a device formatted with
  217. * a MBR, Master Boot Record, or zero if the device is formatted as
  218. * a super floppy with the FAT boot sector in block zero.
  219. *
  220. * \return The value true is returned for success and
  221. * the value false is returned for failure.
  222. */
  223. bool init(uint8_t part);
  224. /** \return The number of entries in the root directory for FAT16 volumes. */
  225. uint16_t rootDirEntryCount() const {
  226. return m_rootDirEntryCount;
  227. }
  228. /** \return The logical block number for the start of the root directory
  229. on FAT16 volumes or the first cluster number on FAT32 volumes. */
  230. uint32_t rootDirStart() const {
  231. return m_rootDirStart;
  232. }
  233. /** \return The number of blocks in the volume */
  234. uint32_t volumeBlockCount() const {
  235. return blocksPerCluster()*clusterCount();
  236. }
  237. /** Wipe all data from the volume.
  238. * \param[in] pr print stream for status dots.
  239. * \return true for success else false.
  240. */
  241. bool wipe(print_t* pr = 0);
  242. /** Debug access to FAT table
  243. *
  244. * \param[in] n cluster number.
  245. * \param[out] v value of entry
  246. * \return true for success or false for failure
  247. */
  248. int8_t dbgFat(uint32_t n, uint32_t* v) {
  249. return fatGet(n, v);
  250. }
  251. //------------------------------------------------------------------------------
  252. private:
  253. // Allow FatFile and FatCache access to FatVolume private functions.
  254. friend class FatCache;
  255. friend class FatFile;
  256. //------------------------------------------------------------------------------
  257. uint8_t m_blocksPerCluster; // Cluster size in blocks.
  258. uint8_t m_clusterBlockMask; // Mask to extract block of cluster.
  259. uint8_t m_clusterSizeShift; // Cluster count to block count shift.
  260. uint8_t m_fatType; // Volume type (12, 16, OR 32).
  261. uint16_t m_rootDirEntryCount; // Number of entries in FAT16 root dir.
  262. uint32_t m_allocSearchStart; // Start cluster for alloc search.
  263. uint32_t m_blocksPerFat; // FAT size in blocks
  264. uint32_t m_dataStartBlock; // First data block number.
  265. uint32_t m_fatStartBlock; // Start block for first FAT.
  266. uint32_t m_lastCluster; // Last cluster number in FAT.
  267. uint32_t m_rootDirStart; // Start block for FAT16, cluster for FAT32.
  268. //------------------------------------------------------------------------------
  269. #if MAINTAIN_FREE_CLUSTER_COUNT
  270. int32_t m_freeClusterCount; // Count of free clusters in volume.
  271. void setFreeClusterCount(int32_t value) {
  272. m_freeClusterCount = value;
  273. }
  274. void updateFreeClusterCount(int32_t change) {
  275. if (m_freeClusterCount >= 0) {
  276. m_freeClusterCount += change;
  277. }
  278. }
  279. #else // MAINTAIN_FREE_CLUSTER_COUNT
  280. void setFreeClusterCount(int32_t value) {}
  281. void updateFreeClusterCount(int32_t change) {}
  282. #endif // MAINTAIN_FREE_CLUSTER_COUNT
  283. // block caches
  284. FatCache m_cache;
  285. #if USE_SEPARATE_FAT_CACHE
  286. FatCache m_fatCache;
  287. cache_t* cacheFetchFat(uint32_t blockNumber, uint8_t options) {
  288. return m_fatCache.read(blockNumber,
  289. options | FatCache::CACHE_STATUS_MIRROR_FAT);
  290. }
  291. bool cacheSync() {
  292. return m_cache.sync() && m_fatCache.sync();
  293. }
  294. #else //
  295. cache_t* cacheFetchFat(uint32_t blockNumber, uint8_t options) {
  296. return cacheFetchData(blockNumber,
  297. options | FatCache::CACHE_STATUS_MIRROR_FAT);
  298. }
  299. bool cacheSync() {
  300. return m_cache.sync();
  301. }
  302. #endif // USE_SEPARATE_FAT_CACHE
  303. cache_t* cacheFetchData(uint32_t blockNumber, uint8_t options) {
  304. return m_cache.read(blockNumber, options);
  305. }
  306. void cacheInvalidate() {
  307. m_cache.invalidate();
  308. }
  309. bool cacheSyncData() {
  310. return m_cache.sync();
  311. }
  312. cache_t *cacheAddress() {
  313. return m_cache.block();
  314. }
  315. uint32_t cacheBlockNumber() {
  316. return m_cache.lbn();
  317. }
  318. void cacheDirty() {
  319. m_cache.dirty();
  320. }
  321. //------------------------------------------------------------------------------
  322. bool allocateCluster(uint32_t current, uint32_t* next);
  323. bool allocContiguous(uint32_t count, uint32_t* firstCluster);
  324. uint8_t blockOfCluster(uint32_t position) const {
  325. return (position >> 9) & m_clusterBlockMask;
  326. }
  327. uint32_t clusterStartBlock(uint32_t cluster) const;
  328. int8_t fatGet(uint32_t cluster, uint32_t* value);
  329. bool fatPut(uint32_t cluster, uint32_t value);
  330. bool fatPutEOC(uint32_t cluster) {
  331. return fatPut(cluster, 0x0FFFFFFF);
  332. }
  333. bool freeChain(uint32_t cluster);
  334. bool isEOC(uint32_t cluster) const {
  335. return cluster > m_lastCluster;
  336. }
  337. //----------------------------------------------------------------------------
  338. // Virtual block I/O functions.
  339. virtual bool readBlock(uint32_t block, uint8_t* dst) = 0;
  340. virtual bool writeBlock(uint32_t block, const uint8_t* src) = 0;
  341. #if USE_MULTI_BLOCK_IO
  342. virtual bool readBlocks(uint32_t block, uint8_t* dst, size_t nb) = 0;
  343. virtual bool writeBlocks(uint32_t block, const uint8_t* src, size_t nb) = 0;
  344. #endif // USE_MULTI_BLOCK_IO
  345. };
  346. #endif // FatVolume