ExFatFormatter.cpp 11 KB

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