You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

FatVolume.h 11KB

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