Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

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