ExFatFormatter.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  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. #define DBG_FILE "ExFatFormatter.cpp"
  26. #include "../common/DebugMacros.h"
  27. #include "ExFatFormatter.h"
  28. //------------------------------------------------------------------------------
  29. // Formatter assumes 512 byte sectors.
  30. const uint32_t BOOT_BACKUP_OFFSET = 12;
  31. const uint16_t BYTES_PER_SECTOR = 512;
  32. const uint16_t SECTOR_MASK = BYTES_PER_SECTOR - 1;
  33. const uint8_t BYTES_PER_SECTOR_SHIFT = 9;
  34. const uint16_t MINIMUM_UPCASE_SKIP = 512;
  35. const uint32_t BITMAP_CLUSTER = 2;
  36. const uint32_t UPCASE_CLUSTER = 3;
  37. const uint32_t ROOT_CLUSTER = 4;
  38. //------------------------------------------------------------------------------
  39. #define PRINT_FORMAT_PROGRESS 1
  40. #if !PRINT_FORMAT_PROGRESS
  41. #define writeMsg(pr, str)
  42. #elif defined(__AVR__)
  43. #define writeMsg(pr, str) if (pr) pr->print(F(str))
  44. #else // PRINT_FORMAT_PROGRESS
  45. #define writeMsg(pr, str) if (pr) pr->write(str)
  46. #endif // PRINT_FORMAT_PROGRESS
  47. //------------------------------------------------------------------------------
  48. bool ExFatFormatter::format(BlockDevice* dev, uint8_t* secBuf, print_t* pr) {
  49. #if !PRINT_FORMAT_PROGRESS
  50. (void)pr;
  51. #endif // !PRINT_FORMAT_PROGRESS
  52. MbrSector_t* mbr;
  53. ExFatPbs_t* pbs;
  54. DirUpcase_t* dup;
  55. DirBitmap_t* dbm;
  56. DirLabel_t* label;
  57. uint32_t bitmapSize;
  58. uint32_t checksum = 0;
  59. uint32_t clusterCount;
  60. uint32_t clusterHeapOffset;
  61. uint32_t fatLength;
  62. uint32_t fatOffset;
  63. uint32_t m;
  64. uint32_t ns;
  65. uint32_t partitionOffset;
  66. uint32_t sector;
  67. uint32_t sectorsPerCluster;
  68. uint32_t volumeLength;
  69. uint32_t sectorCount;
  70. uint8_t sectorsPerClusterShift;
  71. uint8_t vs;
  72. m_dev = dev;
  73. m_secBuf = secBuf;
  74. sectorCount = dev->sectorCount();
  75. // Min size is 512 MB
  76. if (sectorCount < 0X100000) {
  77. writeMsg(pr, "Device is too small\r\n");
  78. DBG_FAIL_MACRO;
  79. goto fail;
  80. }
  81. // Determine partition layout.
  82. for (m = 1, vs = 0; m && sectorCount > m; m <<= 1, vs++) {}
  83. sectorsPerClusterShift = vs < 29 ? 8 : (vs - 11)/2;
  84. sectorsPerCluster = 1UL << sectorsPerClusterShift;
  85. fatLength = 1UL << (vs < 27 ? 13 : (vs + 1)/2);
  86. fatOffset = fatLength;
  87. partitionOffset = 2*fatLength;
  88. clusterHeapOffset = 2*fatLength;
  89. clusterCount = (sectorCount - 4*fatLength) >> sectorsPerClusterShift;
  90. volumeLength = clusterHeapOffset + (clusterCount << sectorsPerClusterShift);
  91. // make Master Boot Record. Use fake CHS.
  92. memset(secBuf, 0, BYTES_PER_SECTOR);
  93. mbr = reinterpret_cast<MbrSector_t*>(secBuf);
  94. mbr->part->beginCHS[0] = 1;
  95. mbr->part->beginCHS[1] = 1;
  96. mbr->part->beginCHS[2] = 0;
  97. mbr->part->type = 7;
  98. mbr->part->endCHS[0] = 0XFE;
  99. mbr->part->endCHS[1] = 0XFF;
  100. mbr->part->endCHS[2] = 0XFF;
  101. setLe32(mbr->part->relativeSectors, partitionOffset);
  102. setLe32(mbr->part->totalSectors, volumeLength);
  103. setLe16(mbr->signature, MBR_SIGNATURE);
  104. if (!dev->writeSector(0, secBuf)) {
  105. DBG_FAIL_MACRO;
  106. goto fail;
  107. }
  108. // Partition Boot sector.
  109. memset(secBuf, 0, BYTES_PER_SECTOR);
  110. pbs = reinterpret_cast<ExFatPbs_t*>(secBuf);
  111. pbs->jmpInstruction[0] = 0XEB;
  112. pbs->jmpInstruction[1] = 0X76;
  113. pbs->jmpInstruction[2] = 0X90;
  114. pbs->oemName[0] = 'E';
  115. pbs->oemName[1] = 'X';
  116. pbs->oemName[2] = 'F';
  117. pbs->oemName[3] = 'A';
  118. pbs->oemName[4] = 'T';
  119. pbs->oemName[5] = ' ';
  120. pbs->oemName[6] = ' ';
  121. pbs->oemName[7] = ' ';
  122. setLe64(pbs->bpb.partitionOffset, partitionOffset);
  123. setLe64(pbs->bpb.volumeLength, volumeLength);
  124. setLe32(pbs->bpb.fatOffset, fatOffset);
  125. setLe32(pbs->bpb.fatLength, fatLength);
  126. setLe32(pbs->bpb.clusterHeapOffset, clusterHeapOffset);
  127. setLe32(pbs->bpb.clusterCount, clusterCount);
  128. setLe32(pbs->bpb.rootDirectoryCluster, ROOT_CLUSTER);
  129. setLe32(pbs->bpb.volumeSerialNumber, sectorCount);
  130. setLe16(pbs->bpb.fileSystemRevision, 0X100);
  131. setLe16(pbs->bpb.volumeFlags, 0);
  132. pbs->bpb.bytesPerSectorShift = BYTES_PER_SECTOR_SHIFT;
  133. pbs->bpb.sectorsPerClusterShift = sectorsPerClusterShift;
  134. pbs->bpb.numberOfFats = 1;
  135. pbs->bpb.driveSelect = 0X80;
  136. pbs->bpb.percentInUse = 0;
  137. // Fill boot code like official SDFormatter.
  138. for (size_t i = 0; i < sizeof(pbs->bootCode); i++) {
  139. pbs->bootCode[i] = 0XF4;
  140. }
  141. setLe16(pbs->signature, PBR_SIGNATURE);
  142. for (size_t i = 0; i < BYTES_PER_SECTOR; i++) {
  143. if (i == offsetof(ExFatPbs_t, bpb.volumeFlags[0]) ||
  144. i == offsetof(ExFatPbs_t, bpb.volumeFlags[1]) ||
  145. i == offsetof(ExFatPbs_t, bpb.percentInUse)) {
  146. continue;
  147. }
  148. checksum = exFatChecksum(checksum, secBuf[i]);
  149. }
  150. sector = partitionOffset;
  151. if (!dev->writeSector(sector, secBuf) ||
  152. !dev->writeSector(sector + BOOT_BACKUP_OFFSET , secBuf)) {
  153. DBG_FAIL_MACRO;
  154. goto fail;
  155. }
  156. sector++;
  157. // Write eight Extended Boot Sectors.
  158. memset(secBuf, 0, BYTES_PER_SECTOR);
  159. setLe16(pbs->signature, PBR_SIGNATURE);
  160. for (int j = 0; j < 8; j++) {
  161. for (size_t i = 0; i < BYTES_PER_SECTOR; i++) {
  162. checksum = exFatChecksum(checksum, secBuf[i]);
  163. }
  164. if (!dev->writeSector(sector, secBuf) ||
  165. !dev->writeSector(sector + BOOT_BACKUP_OFFSET , secBuf)) {
  166. DBG_FAIL_MACRO;
  167. goto fail;
  168. }
  169. sector++;
  170. }
  171. // Write OEM Parameter Sector and reserved sector.
  172. memset(secBuf, 0, BYTES_PER_SECTOR);
  173. for (int j = 0; j < 2; j++) {
  174. for (size_t i = 0; i < BYTES_PER_SECTOR; i++) {
  175. checksum = exFatChecksum(checksum, secBuf[i]);
  176. }
  177. if (!dev->writeSector(sector, secBuf) ||
  178. !dev->writeSector(sector + BOOT_BACKUP_OFFSET , secBuf)) {
  179. DBG_FAIL_MACRO;
  180. goto fail;
  181. }
  182. sector++;
  183. }
  184. // Write Boot CheckSum Sector.
  185. for (size_t i = 0; i < BYTES_PER_SECTOR; i += 4) {
  186. setLe32(secBuf + i, checksum);
  187. }
  188. if (!dev->writeSector(sector, secBuf) ||
  189. !dev->writeSector(sector + BOOT_BACKUP_OFFSET , secBuf)) {
  190. DBG_FAIL_MACRO;
  191. goto fail;
  192. }
  193. // Initialize FAT.
  194. writeMsg(pr, "Writing FAT ");
  195. sector = partitionOffset + fatOffset;
  196. ns = ((clusterCount + 2)*4 + BYTES_PER_SECTOR - 1)/BYTES_PER_SECTOR;
  197. memset(secBuf, 0, BYTES_PER_SECTOR);
  198. // Allocate two reserved clusters, bitmap, upcase, and root clusters.
  199. secBuf[0] = 0XF8;
  200. for (size_t i = 1; i < 20; i++) {
  201. secBuf[i] = 0XFF;
  202. }
  203. for (uint32_t i = 0; i < ns; i++) {
  204. if (i%(ns/32) == 0) {
  205. writeMsg(pr, ".");
  206. }
  207. if (!dev->writeSector(sector + i, secBuf)) {
  208. DBG_FAIL_MACRO;
  209. goto fail;
  210. }
  211. if (i == 0) {
  212. memset(secBuf, 0, BYTES_PER_SECTOR);
  213. }
  214. }
  215. writeMsg(pr, "\r\n");
  216. // Write cluster two, bitmap.
  217. sector = partitionOffset + clusterHeapOffset;
  218. bitmapSize = (clusterCount + 7)/8;
  219. ns = (bitmapSize + BYTES_PER_SECTOR - 1)/BYTES_PER_SECTOR;
  220. if (ns > sectorsPerCluster) {
  221. DBG_FAIL_MACRO;
  222. goto fail;
  223. }
  224. memset(secBuf, 0, BYTES_PER_SECTOR);
  225. // Allocate clusters for bitmap, upcase, and root.
  226. secBuf[0] = 0X7;
  227. for (uint32_t i = 0; i < ns; i++) {
  228. if (!dev->writeSector(sector + i, secBuf)) {
  229. DBG_FAIL_MACRO;
  230. goto fail;
  231. }
  232. if (i == 0) {
  233. secBuf[0] = 0;
  234. }
  235. }
  236. // Write cluster three, upcase table.
  237. writeMsg(pr, "Writing upcase table\r\n");
  238. if (!writeUpcase(partitionOffset + clusterHeapOffset + sectorsPerCluster)) {
  239. DBG_FAIL_MACRO;
  240. goto fail;
  241. }
  242. if (m_upcaseSize > BYTES_PER_SECTOR*sectorsPerCluster) {
  243. DBG_FAIL_MACRO;
  244. goto fail;
  245. }
  246. // Initialize first sector of root.
  247. writeMsg(pr, "Writing root\r\n");
  248. ns = sectorsPerCluster;
  249. sector = partitionOffset + clusterHeapOffset + 2*sectorsPerCluster;
  250. memset(secBuf, 0, BYTES_PER_SECTOR);
  251. // Unused Label entry.
  252. label = reinterpret_cast<DirLabel_t*>(secBuf);
  253. label->type = EXFAT_TYPE_LABEL & 0X7F;
  254. // bitmap directory entry.
  255. dbm = reinterpret_cast<DirBitmap_t*>(secBuf + 32);
  256. dbm->type = EXFAT_TYPE_BITMAP;
  257. setLe32(dbm->firstCluster, BITMAP_CLUSTER);
  258. setLe64(dbm->size, bitmapSize);
  259. // upcase directory entry.
  260. dup = reinterpret_cast<DirUpcase_t*>(secBuf +64);
  261. dup->type = EXFAT_TYPE_UPCASE;
  262. setLe32(dup->checksum, m_upcaseChecksum);
  263. setLe32(dup->firstCluster, UPCASE_CLUSTER);
  264. setLe64(dup->size, m_upcaseSize);
  265. // Write root, cluster four.
  266. for (uint32_t i = 0; i < ns; i++) {
  267. if (!dev->writeSector(sector + i, secBuf)) {
  268. DBG_FAIL_MACRO;
  269. goto fail;
  270. }
  271. if (i == 0) {
  272. memset(secBuf, 0, BYTES_PER_SECTOR);
  273. }
  274. }
  275. writeMsg(pr, "Format done\r\n");
  276. return true;
  277. fail:
  278. writeMsg(pr, "Format failed\r\n");
  279. return false;
  280. }
  281. //------------------------------------------------------------------------------
  282. bool ExFatFormatter::syncUpcase() {
  283. uint16_t index = m_upcaseSize & SECTOR_MASK;
  284. if (!index) {
  285. return true;
  286. }
  287. for (size_t i = index; i < BYTES_PER_SECTOR; i++) {
  288. m_secBuf[i] = 0;
  289. }
  290. return m_dev->writeSector(m_upcaseSector, m_secBuf);
  291. }
  292. //------------------------------------------------------------------------------
  293. bool ExFatFormatter::writeUpcaseByte(uint8_t b) {
  294. uint16_t index = m_upcaseSize & SECTOR_MASK;
  295. m_secBuf[index] = b;
  296. m_upcaseChecksum = exFatChecksum(m_upcaseChecksum, b);
  297. m_upcaseSize++;
  298. if (index == SECTOR_MASK) {
  299. return m_dev->writeSector(m_upcaseSector++, m_secBuf);
  300. }
  301. return true;
  302. }
  303. //------------------------------------------------------------------------------
  304. bool ExFatFormatter::writeUpcaseUnicode(uint16_t unicode) {
  305. return writeUpcaseByte(unicode) && writeUpcaseByte(unicode >> 8);
  306. }
  307. //------------------------------------------------------------------------------
  308. bool ExFatFormatter::writeUpcase(uint32_t sector) {
  309. uint32_t n;
  310. uint32_t ns;
  311. uint32_t ch = 0;
  312. uint16_t uc;
  313. m_upcaseSize = 0;
  314. m_upcaseChecksum = 0;
  315. m_upcaseSector = sector;
  316. while (ch < 0X10000) {
  317. uc = toUpcase(ch);
  318. if (uc != ch) {
  319. if (!writeUpcaseUnicode(uc)) {
  320. DBG_FAIL_MACRO;
  321. goto fail;
  322. }
  323. ch++;
  324. } else {
  325. for (n = ch + 1; n < 0X10000 && n == toUpcase(n); n++) {}
  326. ns = n - ch;
  327. if (ns >= MINIMUM_UPCASE_SKIP) {
  328. if (!writeUpcaseUnicode(0XFFFF) || !writeUpcaseUnicode(ns)) {
  329. DBG_FAIL_MACRO;
  330. goto fail;
  331. }
  332. ch = n;
  333. } else {
  334. while (ch < n) {
  335. if (!writeUpcaseUnicode(ch++)) {
  336. DBG_FAIL_MACRO;
  337. goto fail;
  338. }
  339. }
  340. }
  341. }
  342. }
  343. if (!syncUpcase()) {
  344. DBG_FAIL_MACRO;
  345. goto fail;
  346. }
  347. return true;
  348. fail:
  349. return false;
  350. }