FatDbg.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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. #include "FatVolume.h"
  26. #include "FatFile.h"
  27. #ifndef DOXYGEN_SHOULD_SKIP_THIS
  28. //------------------------------------------------------------------------------
  29. static uint16_t getLfnChar(DirLfn_t* ldir, uint8_t i) {
  30. if (i < 5) {
  31. return getLe16(ldir->unicode1 + 2*i);
  32. } else if (i < 11) {
  33. return getLe16(ldir->unicode2 + 2*i - 10);
  34. } else if (i < 13) {
  35. return getLe16(ldir->unicode3 + 2*i - 22);
  36. }
  37. return 0;
  38. }
  39. //------------------------------------------------------------------------------
  40. static void printHex(print_t* pr, uint8_t h) {
  41. if (h < 16) {
  42. pr->write('0');
  43. }
  44. pr->print(h, HEX);
  45. }
  46. //------------------------------------------------------------------------------
  47. static void printHex(print_t* pr, uint16_t val) {
  48. bool space = true;
  49. for (uint8_t i = 0; i < 4; i++) {
  50. uint8_t h = (val >> (12 - 4*i)) & 15;
  51. if (h || i == 3) {
  52. space = false;
  53. }
  54. if (space) {
  55. pr->write(' ');
  56. } else {
  57. pr->print(h, HEX);
  58. }
  59. }
  60. }
  61. //------------------------------------------------------------------------------
  62. static void printHex(print_t* pr, uint32_t val) {
  63. bool space = true;
  64. for (uint8_t i = 0; i < 8; i++) {
  65. uint8_t h = (val >> (28 - 4*i)) & 15;
  66. if (h || i == 7) {
  67. space = false;
  68. }
  69. if (space) {
  70. pr->write(' ');
  71. } else {
  72. pr->print(h, HEX);
  73. }
  74. }
  75. }
  76. //------------------------------------------------------------------------------
  77. template<typename Uint>
  78. static void printHexLn(print_t* pr, Uint val) {
  79. printHex(pr, val);
  80. pr->println();
  81. }
  82. //------------------------------------------------------------------------------
  83. bool printFatDir(print_t* pr, DirFat_t* dir) {
  84. DirLfn_t* ldir = reinterpret_cast<DirLfn_t*>(dir);
  85. if (!dir->name[0]) {
  86. pr->println(F("Unused"));
  87. return false;
  88. } else if (dir->name[0] == FAT_NAME_DELETED) {
  89. pr->println(F("Deleted"));
  90. } else if (isFileOrSubdir(dir)) {
  91. pr->print(F("SFN: "));
  92. for (uint8_t i = 0; i < 11; i++) {
  93. printHex(pr, dir->name[i]);
  94. pr->write(' ');
  95. }
  96. pr->write(' ');
  97. pr->write(dir->name, 11);
  98. pr->println();
  99. pr->print(F("attributes: 0X"));
  100. printHexLn(pr, dir->attributes);
  101. pr->print(F("caseFlags: 0X"));
  102. printHexLn(pr, dir->caseFlags);
  103. uint32_t fc = ((uint32_t)getLe16(dir->firstClusterHigh) << 16)
  104. | getLe16(dir->firstClusterLow);
  105. pr->print(F("firstCluster: "));
  106. pr->println(fc, HEX);
  107. pr->print(F("fileSize: "));
  108. pr->println(getLe32(dir->fileSize));
  109. } else if (isLongName(dir)) {
  110. pr->print(F("LFN: "));
  111. for (uint8_t i = 0; i < 13; i++) {
  112. uint16_t c = getLfnChar(ldir, i);
  113. if (15 < c && c < 128) {
  114. pr->print(static_cast<char>(c));
  115. } else {
  116. pr->print("0X");
  117. pr->print(c, HEX);
  118. }
  119. pr->print(' ');
  120. }
  121. pr->println();
  122. pr->print(F("order: 0X"));
  123. pr->println(ldir->order, HEX);
  124. pr->print(F("attributes: 0X"));
  125. pr->println(ldir->attributes, HEX);
  126. pr->print(F("checksum: 0X"));
  127. pr->println(ldir->checksum, HEX);
  128. } else {
  129. pr->println(F("Other"));
  130. }
  131. pr->println();
  132. return true;
  133. }
  134. //------------------------------------------------------------------------------
  135. bool FatPartition::dmpDirSector(print_t* pr, uint32_t sector) {
  136. DirFat_t dir[16];
  137. if (!readSector(sector, reinterpret_cast<uint8_t*>(dir))) {
  138. pr->println(F("dmpDir failed"));
  139. return false;
  140. }
  141. for (uint8_t i = 0; i < 16; i++) {
  142. if (!printFatDir(pr, dir + i)) {
  143. return false;
  144. }
  145. }
  146. return true;
  147. }
  148. //------------------------------------------------------------------------------
  149. bool FatPartition::dmpRootDir(print_t* pr, uint32_t n) {
  150. uint32_t sector;
  151. if (fatType() == 16) {
  152. sector = rootDirStart();
  153. } else if (fatType() == 32) {
  154. sector = clusterStartSector(rootDirStart());
  155. } else {
  156. pr->println(F("dmpRootDir failed"));
  157. return false;
  158. }
  159. return dmpDirSector(pr, sector + n);
  160. }
  161. //------------------------------------------------------------------------------
  162. void FatPartition::dmpSector(print_t* pr, uint32_t sector, uint8_t bits) {
  163. uint8_t data[512];
  164. if (!readSector(sector, data)) {
  165. pr->println(F("dmpSector failed"));
  166. return;
  167. }
  168. for (uint16_t i = 0; i < 512;) {
  169. if (i%32 == 0) {
  170. if (i) {
  171. pr->println();
  172. }
  173. printHex(pr, i);
  174. }
  175. pr->write(' ');
  176. if (bits == 32) {
  177. printHex(pr, *reinterpret_cast<uint32_t*>(data + i));
  178. i += 4;
  179. } else if (bits == 16) {
  180. printHex(pr, *reinterpret_cast<uint16_t*>(data + i));
  181. i += 2;
  182. } else {
  183. printHex(pr, data[i++]);
  184. }
  185. }
  186. pr->println();
  187. }
  188. //------------------------------------------------------------------------------
  189. void FatPartition::dmpFat(print_t* pr, uint32_t start, uint32_t count) {
  190. uint16_t nf = fatType() == 16 ? 256 : fatType() == 32 ? 128 : 0;
  191. if (nf == 0) {
  192. pr->println(F("Invalid fatType"));
  193. return;
  194. }
  195. pr->println(F("FAT:"));
  196. uint32_t sector = m_fatStartSector + start;
  197. uint32_t cluster = nf*start;
  198. for (uint32_t i = 0; i < count; i++) {
  199. cache_t* pc = cacheFetchFat(sector + i, FsCache::CACHE_FOR_READ);
  200. if (!pc) {
  201. pr->println(F("cache read failed"));
  202. return;
  203. }
  204. for (size_t k = 0; k < nf; k++) {
  205. if (0 == cluster%8) {
  206. if (k) {
  207. pr->println();
  208. }
  209. printHex(pr, cluster);
  210. }
  211. cluster++;
  212. pr->write(' ');
  213. uint32_t v = fatType() == 32 ? pc->fat32[k] : pc->fat16[k];
  214. printHex(pr, v);
  215. }
  216. pr->println();
  217. }
  218. }
  219. #endif // DOXYGEN_SHOULD_SKIP_THIS