Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

602 Zeilen
14KB

  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. #include <string.h>
  21. #include "FatVolume.h"
  22. //------------------------------------------------------------------------------
  23. cache_t* FatCache::read(uint32_t lbn, uint8_t option) {
  24. if (m_lbn != lbn) {
  25. if (!sync()) {
  26. DBG_FAIL_MACRO;
  27. goto fail;
  28. }
  29. if (!(option & CACHE_OPTION_NO_READ)) {
  30. if (!m_vol->readBlock(lbn, m_block.data)) {
  31. DBG_FAIL_MACRO;
  32. goto fail;
  33. }
  34. }
  35. m_status = 0;
  36. m_lbn = lbn;
  37. }
  38. m_status |= option & CACHE_STATUS_MASK;
  39. return &m_block;
  40. fail:
  41. return 0;
  42. }
  43. //------------------------------------------------------------------------------
  44. bool FatCache::sync() {
  45. if (m_status & CACHE_STATUS_DIRTY) {
  46. if (!m_vol->writeBlock(m_lbn, m_block.data)) {
  47. DBG_FAIL_MACRO;
  48. goto fail;
  49. }
  50. // mirror second FAT
  51. if (m_status & CACHE_STATUS_MIRROR_FAT) {
  52. uint32_t lbn = m_lbn + m_vol->blocksPerFat();
  53. if (!m_vol->writeBlock(lbn, m_block.data)) {
  54. DBG_FAIL_MACRO;
  55. goto fail;
  56. }
  57. }
  58. m_status &= ~CACHE_STATUS_DIRTY;
  59. }
  60. return true;
  61. fail:
  62. return false;
  63. }
  64. //------------------------------------------------------------------------------
  65. bool FatVolume::allocateCluster(uint32_t current, uint32_t* next) {
  66. uint32_t find = current ? current : m_allocSearchStart;
  67. uint32_t start = find;
  68. while (1) {
  69. find++;
  70. // If at end of FAT go to beginning of FAT.
  71. if (find > m_lastCluster) {
  72. find = 2;
  73. }
  74. uint32_t f;
  75. int8_t fg = fatGet(find, &f);
  76. if (fg < 0) {
  77. DBG_FAIL_MACRO;
  78. goto fail;
  79. }
  80. if (fg && f == 0) {
  81. break;
  82. }
  83. if (find == start) {
  84. // Can't find space checked all clusters.
  85. DBG_FAIL_MACRO;
  86. goto fail;
  87. }
  88. }
  89. // mark end of chain
  90. if (!fatPutEOC(find)) {
  91. DBG_FAIL_MACRO;
  92. goto fail;
  93. }
  94. if (current) {
  95. // link clusters
  96. if (!fatPut(current, find)) {
  97. DBG_FAIL_MACRO;
  98. goto fail;
  99. }
  100. } else {
  101. // Remember place for search start.
  102. m_allocSearchStart = find;
  103. }
  104. updateFreeClusterCount(-1);
  105. *next = find;
  106. return true;
  107. fail:
  108. return false;
  109. }
  110. //------------------------------------------------------------------------------
  111. // find a contiguous group of clusters
  112. bool FatVolume::allocContiguous(uint32_t count, uint32_t* firstCluster) {
  113. // flag to save place to start next search
  114. bool setStart = true;
  115. // start of group
  116. uint32_t bgnCluster;
  117. // end of group
  118. uint32_t endCluster;
  119. // Start at cluster after last allocated cluster.
  120. uint32_t startCluster = m_allocSearchStart;
  121. endCluster = bgnCluster = startCluster + 1;
  122. // search the FAT for free clusters
  123. while (1) {
  124. // If past end - start from beginning of FAT.
  125. if (endCluster > m_lastCluster) {
  126. bgnCluster = endCluster = 2;
  127. }
  128. uint32_t f;
  129. int8_t fg = fatGet(endCluster, &f);
  130. if (fg < 0) {
  131. DBG_FAIL_MACRO;
  132. goto fail;
  133. }
  134. if (f || fg == 0) {
  135. // cluster in use try next cluster as bgnCluster
  136. bgnCluster = endCluster + 1;
  137. // don't update search start if unallocated clusters before endCluster.
  138. if (bgnCluster != endCluster) {
  139. setStart = false;
  140. }
  141. } else if ((endCluster - bgnCluster + 1) == count) {
  142. // done - found space
  143. break;
  144. }
  145. // Can't find space if all clusters checked.
  146. if (startCluster == endCluster) {
  147. DBG_FAIL_MACRO;
  148. goto fail;
  149. }
  150. endCluster++;
  151. }
  152. // remember possible next free cluster
  153. if (setStart) {
  154. m_allocSearchStart = endCluster + 1;
  155. }
  156. // mark end of chain
  157. if (!fatPutEOC(endCluster)) {
  158. DBG_FAIL_MACRO;
  159. goto fail;
  160. }
  161. // link clusters
  162. while (endCluster > bgnCluster) {
  163. if (!fatPut(endCluster - 1, endCluster)) {
  164. DBG_FAIL_MACRO;
  165. goto fail;
  166. }
  167. endCluster--;
  168. }
  169. // Maintain count of free clusters.
  170. updateFreeClusterCount(-count);
  171. // return first cluster number to caller
  172. *firstCluster = bgnCluster;
  173. return true;
  174. fail:
  175. return false;
  176. }
  177. //------------------------------------------------------------------------------
  178. uint32_t FatVolume::clusterStartBlock(uint32_t cluster) const {
  179. return m_dataStartBlock + ((cluster - 2) << m_clusterSizeShift);
  180. }
  181. //------------------------------------------------------------------------------
  182. // Fetch a FAT entry - return -1 error, 0 EOC, else 1.
  183. int8_t FatVolume::fatGet(uint32_t cluster, uint32_t* value) {
  184. uint32_t lba;
  185. uint32_t next;
  186. cache_t* pc;
  187. // error if reserved cluster of beyond FAT
  188. DBG_HALT_IF(cluster < 2 || cluster > m_lastCluster);
  189. if (m_fatType == 32) {
  190. lba = m_fatStartBlock + (cluster >> 7);
  191. pc = cacheFetchFat(lba, FatCache::CACHE_FOR_READ);
  192. if (!pc) {
  193. DBG_FAIL_MACRO;
  194. goto fail;
  195. }
  196. next = pc->fat32[cluster & 0X7F] & FAT32MASK;
  197. goto done;
  198. }
  199. if (m_fatType == 16) {
  200. lba = m_fatStartBlock + ((cluster >> 8) & 0XFF);
  201. pc = cacheFetchFat(lba, FatCache::CACHE_FOR_READ);
  202. if (!pc) {
  203. DBG_FAIL_MACRO;
  204. goto fail;
  205. }
  206. next = pc->fat16[cluster & 0XFF];
  207. goto done;
  208. }
  209. if (FAT12_SUPPORT && m_fatType == 12) {
  210. uint16_t index = cluster;
  211. index += index >> 1;
  212. lba = m_fatStartBlock + (index >> 9);
  213. pc = cacheFetchFat(lba, FatCache::CACHE_FOR_READ);
  214. if (!pc) {
  215. DBG_FAIL_MACRO;
  216. goto fail;
  217. }
  218. index &= 0X1FF;
  219. uint16_t tmp = pc->data[index];
  220. index++;
  221. if (index == 512) {
  222. pc = cacheFetchFat(lba + 1, FatCache::CACHE_FOR_READ);
  223. if (!pc) {
  224. DBG_FAIL_MACRO;
  225. goto fail;
  226. }
  227. index = 0;
  228. }
  229. tmp |= pc->data[index] << 8;
  230. next = cluster & 1 ? tmp >> 4 : tmp & 0XFFF;
  231. goto done;
  232. } else {
  233. DBG_FAIL_MACRO;
  234. goto fail;
  235. }
  236. done:
  237. if (isEOC(next)) {
  238. return 0;
  239. }
  240. *value = next;
  241. return 1;
  242. fail:
  243. return -1;
  244. }
  245. //------------------------------------------------------------------------------
  246. // Store a FAT entry
  247. bool FatVolume::fatPut(uint32_t cluster, uint32_t value) {
  248. uint32_t lba;
  249. cache_t* pc;
  250. // error if reserved cluster of beyond FAT
  251. DBG_HALT_IF(cluster < 2 || cluster > m_lastCluster);
  252. if (m_fatType == 32) {
  253. lba = m_fatStartBlock + (cluster >> 7);
  254. pc = cacheFetchFat(lba, FatCache::CACHE_FOR_WRITE);
  255. if (!pc) {
  256. DBG_FAIL_MACRO;
  257. goto fail;
  258. }
  259. pc->fat32[cluster & 0X7F] = value;
  260. return true;
  261. }
  262. if (m_fatType == 16) {
  263. lba = m_fatStartBlock + ((cluster >> 8) & 0XFF);
  264. pc = cacheFetchFat(lba, FatCache::CACHE_FOR_WRITE);
  265. if (!pc) {
  266. DBG_FAIL_MACRO;
  267. goto fail;
  268. }
  269. pc->fat16[cluster & 0XFF] = value;
  270. return true;
  271. }
  272. if (FAT12_SUPPORT && m_fatType == 12) {
  273. uint16_t index = cluster;
  274. index += index >> 1;
  275. lba = m_fatStartBlock + (index >> 9);
  276. pc = cacheFetchFat(lba, FatCache::CACHE_FOR_WRITE);
  277. if (!pc) {
  278. DBG_FAIL_MACRO;
  279. goto fail;
  280. }
  281. index &= 0X1FF;
  282. uint8_t tmp = value;
  283. if (cluster & 1) {
  284. tmp = (pc->data[index] & 0XF) | tmp << 4;
  285. }
  286. pc->data[index] = tmp;
  287. index++;
  288. if (index == 512) {
  289. lba++;
  290. index = 0;
  291. pc = cacheFetchFat(lba, FatCache::CACHE_FOR_WRITE);
  292. if (!pc) {
  293. DBG_FAIL_MACRO;
  294. goto fail;
  295. }
  296. }
  297. tmp = value >> 4;
  298. if (!(cluster & 1)) {
  299. tmp = ((pc->data[index] & 0XF0)) | tmp >> 4;
  300. }
  301. pc->data[index] = tmp;
  302. return true;
  303. } else {
  304. DBG_FAIL_MACRO;
  305. goto fail;
  306. }
  307. fail:
  308. return false;
  309. }
  310. //------------------------------------------------------------------------------
  311. // free a cluster chain
  312. bool FatVolume::freeChain(uint32_t cluster) {
  313. uint32_t next;
  314. int8_t fg;
  315. do {
  316. fg = fatGet(cluster, &next);
  317. if (fg < 0) {
  318. DBG_FAIL_MACRO;
  319. goto fail;
  320. }
  321. // free cluster
  322. if (!fatPut(cluster, 0)) {
  323. DBG_FAIL_MACRO;
  324. goto fail;
  325. }
  326. // Add one to count of free clusters.
  327. updateFreeClusterCount(1);
  328. if (cluster < m_allocSearchStart) {
  329. m_allocSearchStart = cluster;
  330. }
  331. cluster = next;
  332. } while (fg);
  333. return true;
  334. fail:
  335. return false;
  336. }
  337. //------------------------------------------------------------------------------
  338. int32_t FatVolume::freeClusterCount() {
  339. #if MAINTAIN_FREE_CLUSTER_COUNT
  340. if (m_freeClusterCount >= 0) {
  341. return m_freeClusterCount;
  342. }
  343. #endif // MAINTAIN_FREE_CLUSTER_COUNT
  344. uint32_t free = 0;
  345. uint32_t lba;
  346. uint32_t todo = m_lastCluster + 1;
  347. uint16_t n;
  348. if (FAT12_SUPPORT && m_fatType == 12) {
  349. for (unsigned i = 2; i < todo; i++) {
  350. uint32_t c;
  351. int8_t fg = fatGet(i, &c);
  352. if (fg < 0) {
  353. DBG_FAIL_MACRO;
  354. goto fail;
  355. }
  356. if (fg && c == 0) {
  357. free++;
  358. }
  359. }
  360. } else if (m_fatType == 16 || m_fatType == 32) {
  361. lba = m_fatStartBlock;
  362. while (todo) {
  363. cache_t* pc = cacheFetchFat(lba++, FatCache::CACHE_FOR_READ);
  364. if (!pc) {
  365. DBG_FAIL_MACRO;
  366. goto fail;
  367. }
  368. n = m_fatType == 16 ? 256 : 128;
  369. if (todo < n) {
  370. n = todo;
  371. }
  372. if (m_fatType == 16) {
  373. for (uint16_t i = 0; i < n; i++) {
  374. if (pc->fat16[i] == 0) {
  375. free++;
  376. }
  377. }
  378. } else {
  379. for (uint16_t i = 0; i < n; i++) {
  380. if (pc->fat32[i] == 0) {
  381. free++;
  382. }
  383. }
  384. }
  385. todo -= n;
  386. }
  387. } else {
  388. // invalid FAT type
  389. DBG_FAIL_MACRO;
  390. goto fail;
  391. }
  392. setFreeClusterCount(free);
  393. return free;
  394. fail:
  395. return -1;
  396. }
  397. //------------------------------------------------------------------------------
  398. bool FatVolume::init(uint8_t part) {
  399. uint32_t clusterCount;
  400. uint32_t totalBlocks;
  401. uint32_t volumeStartBlock = 0;
  402. fat32_boot_t* fbs;
  403. cache_t* pc;
  404. uint8_t tmp;
  405. m_fatType = 0;
  406. m_allocSearchStart = 1;
  407. m_cache.init(this);
  408. #if USE_SEPARATE_FAT_CACHE
  409. m_fatCache.init(this);
  410. #endif // USE_SEPARATE_FAT_CACHE
  411. // if part == 0 assume super floppy with FAT boot sector in block zero
  412. // if part > 0 assume mbr volume with partition table
  413. if (part) {
  414. if (part > 4) {
  415. DBG_FAIL_MACRO;
  416. goto fail;
  417. }
  418. pc = cacheFetchData(0, FatCache::CACHE_FOR_READ);
  419. if (!pc) {
  420. DBG_FAIL_MACRO;
  421. goto fail;
  422. }
  423. part_t* p = &pc->mbr.part[part - 1];
  424. if ((p->boot & 0X7F) != 0 || p->firstSector == 0) {
  425. // not a valid partition
  426. DBG_FAIL_MACRO;
  427. goto fail;
  428. }
  429. volumeStartBlock = p->firstSector;
  430. }
  431. pc = cacheFetchData(volumeStartBlock, FatCache::CACHE_FOR_READ);
  432. if (!pc) {
  433. DBG_FAIL_MACRO;
  434. goto fail;
  435. }
  436. fbs = &(pc->fbs32);
  437. if (fbs->bytesPerSector != 512 ||
  438. fbs->fatCount != 2 ||
  439. fbs->reservedSectorCount == 0) {
  440. // not valid FAT volume
  441. DBG_FAIL_MACRO;
  442. goto fail;
  443. }
  444. m_blocksPerCluster = fbs->sectorsPerCluster;
  445. m_clusterBlockMask = m_blocksPerCluster - 1;
  446. // determine shift that is same as multiply by m_blocksPerCluster
  447. m_clusterSizeShift = 0;
  448. for (tmp = 1; m_blocksPerCluster != tmp; tmp <<= 1, m_clusterSizeShift++) {
  449. if (tmp == 0) {
  450. DBG_FAIL_MACRO;
  451. goto fail;
  452. }
  453. }
  454. m_blocksPerFat = fbs->sectorsPerFat16 ?
  455. fbs->sectorsPerFat16 : fbs->sectorsPerFat32;
  456. m_fatStartBlock = volumeStartBlock + fbs->reservedSectorCount;
  457. // count for FAT16 zero for FAT32
  458. m_rootDirEntryCount = fbs->rootDirEntryCount;
  459. // directory start for FAT16 dataStart for FAT32
  460. m_rootDirStart = m_fatStartBlock + 2 * m_blocksPerFat;
  461. // data start for FAT16 and FAT32
  462. m_dataStartBlock = m_rootDirStart + ((32 * fbs->rootDirEntryCount + 511)/512);
  463. // total blocks for FAT16 or FAT32
  464. totalBlocks = fbs->totalSectors16 ?
  465. fbs->totalSectors16 : fbs->totalSectors32;
  466. // total data blocks
  467. clusterCount = totalBlocks - (m_dataStartBlock - volumeStartBlock);
  468. // divide by cluster size to get cluster count
  469. clusterCount >>= m_clusterSizeShift;
  470. m_lastCluster = clusterCount + 1;
  471. // Indicate unknown number of free clusters.
  472. setFreeClusterCount(-1);
  473. // FAT type is determined by cluster count
  474. if (clusterCount < 4085) {
  475. m_fatType = 12;
  476. if (!FAT12_SUPPORT) {
  477. DBG_FAIL_MACRO;
  478. goto fail;
  479. }
  480. } else if (clusterCount < 65525) {
  481. m_fatType = 16;
  482. } else {
  483. m_rootDirStart = fbs->fat32RootCluster;
  484. m_fatType = 32;
  485. }
  486. return true;
  487. fail:
  488. return false;
  489. }
  490. //------------------------------------------------------------------------------
  491. bool FatVolume::wipe(print_t* pr) {
  492. cache_t* cache;
  493. uint16_t count;
  494. uint32_t lbn;
  495. if (!m_fatType) {
  496. DBG_FAIL_MACRO;
  497. goto fail;
  498. }
  499. cache = cacheClear();
  500. if (!cache) {
  501. DBG_FAIL_MACRO;
  502. goto fail;
  503. }
  504. memset(cache->data, 0, 512);
  505. // Zero root.
  506. if (m_fatType == 32) {
  507. lbn = clusterStartBlock(m_rootDirStart);
  508. count = m_blocksPerCluster;
  509. } else {
  510. lbn = m_rootDirStart;
  511. count = m_rootDirEntryCount/16;
  512. }
  513. for (uint32_t n = 0; n < count; n++) {
  514. if (!writeBlock(lbn + n, cache->data)) {
  515. DBG_FAIL_MACRO;
  516. goto fail;
  517. }
  518. }
  519. // Clear FATs.
  520. count = 2*m_blocksPerFat;
  521. lbn = m_fatStartBlock;
  522. for (uint32_t nb = 0; nb < count; nb++) {
  523. if (pr && (nb & 0XFF) == 0) {
  524. pr->write('.');
  525. }
  526. if (!writeBlock(lbn + nb, cache->data)) {
  527. DBG_FAIL_MACRO;
  528. goto fail;
  529. }
  530. }
  531. // Reserve first two clusters.
  532. if (m_fatType == 32) {
  533. cache->fat32[0] = 0x0FFFFFF8;
  534. cache->fat32[1] = 0x0FFFFFFF;
  535. } else if (m_fatType == 16) {
  536. cache->fat16[0] = 0XFFF8;
  537. cache->fat16[1] = 0XFFFF;
  538. } else if (FAT12_SUPPORT && m_fatType == 12) {
  539. cache->fat32[0] = 0XFFFFF8;
  540. } else {
  541. DBG_FAIL_MACRO;
  542. goto fail;
  543. }
  544. if (!writeBlock(m_fatStartBlock, cache->data) ||
  545. !writeBlock(m_fatStartBlock + m_blocksPerFat, cache->data)) {
  546. DBG_FAIL_MACRO;
  547. goto fail;
  548. }
  549. if (m_fatType == 32) {
  550. // Reserve root cluster.
  551. if (!fatPutEOC(m_rootDirStart) || !cacheSync()) {
  552. DBG_FAIL_MACRO;
  553. goto fail;
  554. }
  555. }
  556. if (pr) {
  557. pr->write('\r');
  558. pr->write('\n');
  559. }
  560. m_fatType = 0;
  561. return true;
  562. fail:
  563. m_fatType = 0;
  564. return false;
  565. }