FatDbg.cpp 7.8 KB

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