fat.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357
  1. /*
  2. * fat.c
  3. *
  4. * R/O (V)FAT 12/16/32 filesystem implementation by Marcus Sundberg
  5. *
  6. * 2002-07-28 - rjones@nexus-tech.net - ported to ppcboot v1.1.6
  7. * 2003-03-10 - kharris@nexus-tech.net - ported to uboot
  8. *
  9. * SPDX-License-Identifier: GPL-2.0+
  10. */
  11. #include <common.h>
  12. #include <blk.h>
  13. #include <config.h>
  14. #include <exports.h>
  15. #include <fat.h>
  16. #include <asm/byteorder.h>
  17. #include <part.h>
  18. #include <malloc.h>
  19. #include <memalign.h>
  20. #include <linux/compiler.h>
  21. #include <linux/ctype.h>
  22. #ifdef CONFIG_SUPPORT_VFAT
  23. static const int vfat_enabled = 1;
  24. #else
  25. static const int vfat_enabled = 0;
  26. #endif
  27. /*
  28. * Convert a string to lowercase.
  29. */
  30. static void downcase(char *str)
  31. {
  32. while (*str != '\0') {
  33. *str = tolower(*str);
  34. str++;
  35. }
  36. }
  37. static struct blk_desc *cur_dev;
  38. static disk_partition_t cur_part_info;
  39. #define DOS_BOOT_MAGIC_OFFSET 0x1fe
  40. #define DOS_FS_TYPE_OFFSET 0x36
  41. #define DOS_FS32_TYPE_OFFSET 0x52
  42. static int disk_read(__u32 block, __u32 nr_blocks, void *buf)
  43. {
  44. ulong ret;
  45. if (!cur_dev)
  46. return -1;
  47. ret = blk_dread(cur_dev, cur_part_info.start + block, nr_blocks, buf);
  48. if (nr_blocks && ret == 0)
  49. return -1;
  50. return ret;
  51. }
  52. int fat_set_blk_dev(struct blk_desc *dev_desc, disk_partition_t *info)
  53. {
  54. ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz);
  55. cur_dev = dev_desc;
  56. cur_part_info = *info;
  57. /* Make sure it has a valid FAT header */
  58. if (disk_read(0, 1, buffer) != 1) {
  59. cur_dev = NULL;
  60. return -1;
  61. }
  62. /* Check if it's actually a DOS volume */
  63. if (memcmp(buffer + DOS_BOOT_MAGIC_OFFSET, "\x55\xAA", 2)) {
  64. cur_dev = NULL;
  65. return -1;
  66. }
  67. /* Check for FAT12/FAT16/FAT32 filesystem */
  68. if (!memcmp(buffer + DOS_FS_TYPE_OFFSET, "FAT", 3))
  69. return 0;
  70. if (!memcmp(buffer + DOS_FS32_TYPE_OFFSET, "FAT32", 5))
  71. return 0;
  72. cur_dev = NULL;
  73. return -1;
  74. }
  75. int fat_register_device(struct blk_desc *dev_desc, int part_no)
  76. {
  77. disk_partition_t info;
  78. /* First close any currently found FAT filesystem */
  79. cur_dev = NULL;
  80. /* Read the partition table, if present */
  81. if (part_get_info(dev_desc, part_no, &info)) {
  82. if (part_no != 0) {
  83. printf("** Partition %d not valid on device %d **\n",
  84. part_no, dev_desc->devnum);
  85. return -1;
  86. }
  87. info.start = 0;
  88. info.size = dev_desc->lba;
  89. info.blksz = dev_desc->blksz;
  90. info.name[0] = 0;
  91. info.type[0] = 0;
  92. info.bootable = 0;
  93. #ifdef CONFIG_PARTITION_UUIDS
  94. info.uuid[0] = 0;
  95. #endif
  96. }
  97. return fat_set_blk_dev(dev_desc, &info);
  98. }
  99. /*
  100. * Get the first occurence of a directory delimiter ('/' or '\') in a string.
  101. * Return index into string if found, -1 otherwise.
  102. */
  103. static int dirdelim(char *str)
  104. {
  105. char *start = str;
  106. while (*str != '\0') {
  107. if (ISDIRDELIM(*str))
  108. return str - start;
  109. str++;
  110. }
  111. return -1;
  112. }
  113. /*
  114. * Extract zero terminated short name from a directory entry.
  115. */
  116. static void get_name(dir_entry *dirent, char *s_name)
  117. {
  118. char *ptr;
  119. memcpy(s_name, dirent->name, 8);
  120. s_name[8] = '\0';
  121. ptr = s_name;
  122. while (*ptr && *ptr != ' ')
  123. ptr++;
  124. if (dirent->ext[0] && dirent->ext[0] != ' ') {
  125. *ptr = '.';
  126. ptr++;
  127. memcpy(ptr, dirent->ext, 3);
  128. ptr[3] = '\0';
  129. while (*ptr && *ptr != ' ')
  130. ptr++;
  131. }
  132. *ptr = '\0';
  133. if (*s_name == DELETED_FLAG)
  134. *s_name = '\0';
  135. else if (*s_name == aRING)
  136. *s_name = DELETED_FLAG;
  137. downcase(s_name);
  138. }
  139. static int flush_dirty_fat_buffer(fsdata *mydata);
  140. #if !defined(CONFIG_FAT_WRITE)
  141. /* Stub for read only operation */
  142. int flush_dirty_fat_buffer(fsdata *mydata)
  143. {
  144. (void)(mydata);
  145. return 0;
  146. }
  147. #endif
  148. /*
  149. * Get the entry at index 'entry' in a FAT (12/16/32) table.
  150. * On failure 0x00 is returned.
  151. */
  152. static __u32 get_fatent(fsdata *mydata, __u32 entry)
  153. {
  154. __u32 bufnum;
  155. __u32 off16, offset;
  156. __u32 ret = 0x00;
  157. if (CHECK_CLUST(entry, mydata->fatsize)) {
  158. printf("Error: Invalid FAT entry: 0x%08x\n", entry);
  159. return ret;
  160. }
  161. switch (mydata->fatsize) {
  162. case 32:
  163. bufnum = entry / FAT32BUFSIZE;
  164. offset = entry - bufnum * FAT32BUFSIZE;
  165. break;
  166. case 16:
  167. bufnum = entry / FAT16BUFSIZE;
  168. offset = entry - bufnum * FAT16BUFSIZE;
  169. break;
  170. case 12:
  171. bufnum = entry / FAT12BUFSIZE;
  172. offset = entry - bufnum * FAT12BUFSIZE;
  173. break;
  174. default:
  175. /* Unsupported FAT size */
  176. return ret;
  177. }
  178. debug("FAT%d: entry: 0x%08x = %d, offset: 0x%04x = %d\n",
  179. mydata->fatsize, entry, entry, offset, offset);
  180. /* Read a new block of FAT entries into the cache. */
  181. if (bufnum != mydata->fatbufnum) {
  182. __u32 getsize = FATBUFBLOCKS;
  183. __u8 *bufptr = mydata->fatbuf;
  184. __u32 fatlength = mydata->fatlength;
  185. __u32 startblock = bufnum * FATBUFBLOCKS;
  186. /* Cap length if fatlength is not a multiple of FATBUFBLOCKS */
  187. if (startblock + getsize > fatlength)
  188. getsize = fatlength - startblock;
  189. startblock += mydata->fat_sect; /* Offset from start of disk */
  190. /* Write back the fatbuf to the disk */
  191. if (flush_dirty_fat_buffer(mydata) < 0)
  192. return -1;
  193. if (disk_read(startblock, getsize, bufptr) < 0) {
  194. debug("Error reading FAT blocks\n");
  195. return ret;
  196. }
  197. mydata->fatbufnum = bufnum;
  198. }
  199. /* Get the actual entry from the table */
  200. switch (mydata->fatsize) {
  201. case 32:
  202. ret = FAT2CPU32(((__u32 *) mydata->fatbuf)[offset]);
  203. break;
  204. case 16:
  205. ret = FAT2CPU16(((__u16 *) mydata->fatbuf)[offset]);
  206. break;
  207. case 12:
  208. off16 = (offset * 3) / 2;
  209. ret = FAT2CPU16(*(__u16 *)(mydata->fatbuf + off16));
  210. if (offset & 0x1)
  211. ret >>= 4;
  212. ret &= 0xfff;
  213. }
  214. debug("FAT%d: ret: 0x%08x, entry: 0x%08x, offset: 0x%04x\n",
  215. mydata->fatsize, ret, entry, offset);
  216. return ret;
  217. }
  218. /*
  219. * Read at most 'size' bytes from the specified cluster into 'buffer'.
  220. * Return 0 on success, -1 otherwise.
  221. */
  222. static int
  223. get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size)
  224. {
  225. __u32 idx = 0;
  226. __u32 startsect;
  227. int ret;
  228. if (clustnum > 0) {
  229. startsect = mydata->data_begin +
  230. clustnum * mydata->clust_size;
  231. } else {
  232. startsect = mydata->rootdir_sect;
  233. }
  234. debug("gc - clustnum: %d, startsect: %d\n", clustnum, startsect);
  235. if ((unsigned long)buffer & (ARCH_DMA_MINALIGN - 1)) {
  236. ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size);
  237. debug("FAT: misaligned buffer address (%p)\n", buffer);
  238. while (size >= mydata->sect_size) {
  239. ret = disk_read(startsect++, 1, tmpbuf);
  240. if (ret != 1) {
  241. debug("Error reading data (got %d)\n", ret);
  242. return -1;
  243. }
  244. memcpy(buffer, tmpbuf, mydata->sect_size);
  245. buffer += mydata->sect_size;
  246. size -= mydata->sect_size;
  247. }
  248. } else {
  249. idx = size / mydata->sect_size;
  250. ret = disk_read(startsect, idx, buffer);
  251. if (ret != idx) {
  252. debug("Error reading data (got %d)\n", ret);
  253. return -1;
  254. }
  255. startsect += idx;
  256. idx *= mydata->sect_size;
  257. buffer += idx;
  258. size -= idx;
  259. }
  260. if (size) {
  261. ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size);
  262. ret = disk_read(startsect, 1, tmpbuf);
  263. if (ret != 1) {
  264. debug("Error reading data (got %d)\n", ret);
  265. return -1;
  266. }
  267. memcpy(buffer, tmpbuf, size);
  268. }
  269. return 0;
  270. }
  271. /*
  272. * Read at most 'maxsize' bytes from 'pos' in the file associated with 'dentptr'
  273. * into 'buffer'.
  274. * Update the number of bytes read in *gotsize or return -1 on fatal errors.
  275. */
  276. __u8 get_contents_vfatname_block[MAX_CLUSTSIZE]
  277. __aligned(ARCH_DMA_MINALIGN);
  278. static int get_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos,
  279. __u8 *buffer, loff_t maxsize, loff_t *gotsize)
  280. {
  281. loff_t filesize = FAT2CPU32(dentptr->size);
  282. unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
  283. __u32 curclust = START(dentptr);
  284. __u32 endclust, newclust;
  285. loff_t actsize;
  286. *gotsize = 0;
  287. debug("Filesize: %llu bytes\n", filesize);
  288. if (pos >= filesize) {
  289. debug("Read position past EOF: %llu\n", pos);
  290. return 0;
  291. }
  292. if (maxsize > 0 && filesize > pos + maxsize)
  293. filesize = pos + maxsize;
  294. debug("%llu bytes\n", filesize);
  295. actsize = bytesperclust;
  296. /* go to cluster at pos */
  297. while (actsize <= pos) {
  298. curclust = get_fatent(mydata, curclust);
  299. if (CHECK_CLUST(curclust, mydata->fatsize)) {
  300. debug("curclust: 0x%x\n", curclust);
  301. debug("Invalid FAT entry\n");
  302. return 0;
  303. }
  304. actsize += bytesperclust;
  305. }
  306. /* actsize > pos */
  307. actsize -= bytesperclust;
  308. filesize -= actsize;
  309. pos -= actsize;
  310. /* align to beginning of next cluster if any */
  311. if (pos) {
  312. actsize = min(filesize, (loff_t)bytesperclust);
  313. if (get_cluster(mydata, curclust, get_contents_vfatname_block,
  314. (int)actsize) != 0) {
  315. printf("Error reading cluster\n");
  316. return -1;
  317. }
  318. filesize -= actsize;
  319. actsize -= pos;
  320. memcpy(buffer, get_contents_vfatname_block + pos, actsize);
  321. *gotsize += actsize;
  322. if (!filesize)
  323. return 0;
  324. buffer += actsize;
  325. curclust = get_fatent(mydata, curclust);
  326. if (CHECK_CLUST(curclust, mydata->fatsize)) {
  327. debug("curclust: 0x%x\n", curclust);
  328. debug("Invalid FAT entry\n");
  329. return 0;
  330. }
  331. }
  332. actsize = bytesperclust;
  333. endclust = curclust;
  334. do {
  335. /* search for consecutive clusters */
  336. while (actsize < filesize) {
  337. newclust = get_fatent(mydata, endclust);
  338. if ((newclust - 1) != endclust)
  339. goto getit;
  340. if (CHECK_CLUST(newclust, mydata->fatsize)) {
  341. debug("curclust: 0x%x\n", newclust);
  342. debug("Invalid FAT entry\n");
  343. return 0;
  344. }
  345. endclust = newclust;
  346. actsize += bytesperclust;
  347. }
  348. /* get remaining bytes */
  349. actsize = filesize;
  350. if (get_cluster(mydata, curclust, buffer, (int)actsize) != 0) {
  351. printf("Error reading cluster\n");
  352. return -1;
  353. }
  354. *gotsize += actsize;
  355. return 0;
  356. getit:
  357. if (get_cluster(mydata, curclust, buffer, (int)actsize) != 0) {
  358. printf("Error reading cluster\n");
  359. return -1;
  360. }
  361. *gotsize += (int)actsize;
  362. filesize -= actsize;
  363. buffer += actsize;
  364. curclust = get_fatent(mydata, endclust);
  365. if (CHECK_CLUST(curclust, mydata->fatsize)) {
  366. debug("curclust: 0x%x\n", curclust);
  367. printf("Invalid FAT entry\n");
  368. return 0;
  369. }
  370. actsize = bytesperclust;
  371. endclust = curclust;
  372. } while (1);
  373. }
  374. /*
  375. * Extract the file name information from 'slotptr' into 'l_name',
  376. * starting at l_name[*idx].
  377. * Return 1 if terminator (zero byte) is found, 0 otherwise.
  378. */
  379. static int slot2str(dir_slot *slotptr, char *l_name, int *idx)
  380. {
  381. int j;
  382. for (j = 0; j <= 8; j += 2) {
  383. l_name[*idx] = slotptr->name0_4[j];
  384. if (l_name[*idx] == 0x00)
  385. return 1;
  386. (*idx)++;
  387. }
  388. for (j = 0; j <= 10; j += 2) {
  389. l_name[*idx] = slotptr->name5_10[j];
  390. if (l_name[*idx] == 0x00)
  391. return 1;
  392. (*idx)++;
  393. }
  394. for (j = 0; j <= 2; j += 2) {
  395. l_name[*idx] = slotptr->name11_12[j];
  396. if (l_name[*idx] == 0x00)
  397. return 1;
  398. (*idx)++;
  399. }
  400. return 0;
  401. }
  402. /*
  403. * Extract the full long filename starting at 'retdent' (which is really
  404. * a slot) into 'l_name'. If successful also copy the real directory entry
  405. * into 'retdent'
  406. * Return 0 on success, -1 otherwise.
  407. */
  408. static int
  409. get_vfatname(fsdata *mydata, int curclust, __u8 *cluster,
  410. dir_entry *retdent, char *l_name)
  411. {
  412. dir_entry *realdent;
  413. dir_slot *slotptr = (dir_slot *)retdent;
  414. __u8 *buflimit = cluster + mydata->sect_size * ((curclust == 0) ?
  415. PREFETCH_BLOCKS :
  416. mydata->clust_size);
  417. __u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff;
  418. int idx = 0;
  419. if (counter > VFAT_MAXSEQ) {
  420. debug("Error: VFAT name is too long\n");
  421. return -1;
  422. }
  423. while ((__u8 *)slotptr < buflimit) {
  424. if (counter == 0)
  425. break;
  426. if (((slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff) != counter)
  427. return -1;
  428. slotptr++;
  429. counter--;
  430. }
  431. if ((__u8 *)slotptr >= buflimit) {
  432. dir_slot *slotptr2;
  433. if (curclust == 0)
  434. return -1;
  435. curclust = get_fatent(mydata, curclust);
  436. if (CHECK_CLUST(curclust, mydata->fatsize)) {
  437. debug("curclust: 0x%x\n", curclust);
  438. printf("Invalid FAT entry\n");
  439. return -1;
  440. }
  441. if (get_cluster(mydata, curclust, get_contents_vfatname_block,
  442. mydata->clust_size * mydata->sect_size) != 0) {
  443. debug("Error: reading directory block\n");
  444. return -1;
  445. }
  446. slotptr2 = (dir_slot *)get_contents_vfatname_block;
  447. while (counter > 0) {
  448. if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK)
  449. & 0xff) != counter)
  450. return -1;
  451. slotptr2++;
  452. counter--;
  453. }
  454. /* Save the real directory entry */
  455. realdent = (dir_entry *)slotptr2;
  456. while ((__u8 *)slotptr2 > get_contents_vfatname_block) {
  457. slotptr2--;
  458. slot2str(slotptr2, l_name, &idx);
  459. }
  460. } else {
  461. /* Save the real directory entry */
  462. realdent = (dir_entry *)slotptr;
  463. }
  464. do {
  465. slotptr--;
  466. if (slot2str(slotptr, l_name, &idx))
  467. break;
  468. } while (!(slotptr->id & LAST_LONG_ENTRY_MASK));
  469. l_name[idx] = '\0';
  470. if (*l_name == DELETED_FLAG)
  471. *l_name = '\0';
  472. else if (*l_name == aRING)
  473. *l_name = DELETED_FLAG;
  474. downcase(l_name);
  475. /* Return the real directory entry */
  476. memcpy(retdent, realdent, sizeof(dir_entry));
  477. return 0;
  478. }
  479. /* Calculate short name checksum */
  480. static __u8 mkcksum(const char name[8], const char ext[3])
  481. {
  482. int i;
  483. __u8 ret = 0;
  484. for (i = 0; i < 8; i++)
  485. ret = (((ret & 1) << 7) | ((ret & 0xfe) >> 1)) + name[i];
  486. for (i = 0; i < 3; i++)
  487. ret = (((ret & 1) << 7) | ((ret & 0xfe) >> 1)) + ext[i];
  488. return ret;
  489. }
  490. /*
  491. * Get the directory entry associated with 'filename' from the directory
  492. * starting at 'startsect'
  493. */
  494. __u8 get_dentfromdir_block[MAX_CLUSTSIZE]
  495. __aligned(ARCH_DMA_MINALIGN);
  496. static dir_entry *get_dentfromdir(fsdata *mydata, int startsect,
  497. char *filename, dir_entry *retdent,
  498. int dols)
  499. {
  500. __u16 prevcksum = 0xffff;
  501. __u32 curclust = START(retdent);
  502. int files = 0, dirs = 0;
  503. debug("get_dentfromdir: %s\n", filename);
  504. while (1) {
  505. dir_entry *dentptr;
  506. int i;
  507. if (get_cluster(mydata, curclust, get_dentfromdir_block,
  508. mydata->clust_size * mydata->sect_size) != 0) {
  509. debug("Error: reading directory block\n");
  510. return NULL;
  511. }
  512. dentptr = (dir_entry *)get_dentfromdir_block;
  513. for (i = 0; i < DIRENTSPERCLUST; i++) {
  514. char s_name[14], l_name[VFAT_MAXLEN_BYTES];
  515. l_name[0] = '\0';
  516. if (dentptr->name[0] == DELETED_FLAG) {
  517. dentptr++;
  518. continue;
  519. }
  520. if ((dentptr->attr & ATTR_VOLUME)) {
  521. if (vfat_enabled &&
  522. (dentptr->attr & ATTR_VFAT) == ATTR_VFAT &&
  523. (dentptr->name[0] & LAST_LONG_ENTRY_MASK)) {
  524. prevcksum = ((dir_slot *)dentptr)->alias_checksum;
  525. get_vfatname(mydata, curclust,
  526. get_dentfromdir_block,
  527. dentptr, l_name);
  528. if (dols) {
  529. int isdir;
  530. char dirc;
  531. int doit = 0;
  532. isdir = (dentptr->attr & ATTR_DIR);
  533. if (isdir) {
  534. dirs++;
  535. dirc = '/';
  536. doit = 1;
  537. } else {
  538. dirc = ' ';
  539. if (l_name[0] != 0) {
  540. files++;
  541. doit = 1;
  542. }
  543. }
  544. if (doit) {
  545. if (dirc == ' ') {
  546. printf(" %8u %s%c\n",
  547. FAT2CPU32(dentptr->size),
  548. l_name,
  549. dirc);
  550. } else {
  551. printf(" %s%c\n",
  552. l_name,
  553. dirc);
  554. }
  555. }
  556. dentptr++;
  557. continue;
  558. }
  559. debug("vfatname: |%s|\n", l_name);
  560. } else {
  561. /* Volume label or VFAT entry */
  562. dentptr++;
  563. continue;
  564. }
  565. }
  566. if (dentptr->name[0] == 0) {
  567. if (dols) {
  568. printf("\n%d file(s), %d dir(s)\n\n",
  569. files, dirs);
  570. }
  571. debug("Dentname == NULL - %d\n", i);
  572. return NULL;
  573. }
  574. if (vfat_enabled) {
  575. __u8 csum = mkcksum(dentptr->name, dentptr->ext);
  576. if (dols && csum == prevcksum) {
  577. prevcksum = 0xffff;
  578. dentptr++;
  579. continue;
  580. }
  581. }
  582. get_name(dentptr, s_name);
  583. if (dols) {
  584. int isdir = (dentptr->attr & ATTR_DIR);
  585. char dirc;
  586. int doit = 0;
  587. if (isdir) {
  588. dirs++;
  589. dirc = '/';
  590. doit = 1;
  591. } else {
  592. dirc = ' ';
  593. if (s_name[0] != 0) {
  594. files++;
  595. doit = 1;
  596. }
  597. }
  598. if (doit) {
  599. if (dirc == ' ') {
  600. printf(" %8u %s%c\n",
  601. FAT2CPU32(dentptr->size),
  602. s_name, dirc);
  603. } else {
  604. printf(" %s%c\n",
  605. s_name, dirc);
  606. }
  607. }
  608. dentptr++;
  609. continue;
  610. }
  611. if (strcmp(filename, s_name)
  612. && strcmp(filename, l_name)) {
  613. debug("Mismatch: |%s|%s|\n", s_name, l_name);
  614. dentptr++;
  615. continue;
  616. }
  617. memcpy(retdent, dentptr, sizeof(dir_entry));
  618. debug("DentName: %s", s_name);
  619. debug(", start: 0x%x", START(dentptr));
  620. debug(", size: 0x%x %s\n",
  621. FAT2CPU32(dentptr->size),
  622. (dentptr->attr & ATTR_DIR) ? "(DIR)" : "");
  623. return retdent;
  624. }
  625. curclust = get_fatent(mydata, curclust);
  626. if (CHECK_CLUST(curclust, mydata->fatsize)) {
  627. debug("curclust: 0x%x\n", curclust);
  628. printf("Invalid FAT entry\n");
  629. return NULL;
  630. }
  631. }
  632. return NULL;
  633. }
  634. /*
  635. * Read boot sector and volume info from a FAT filesystem
  636. */
  637. static int
  638. read_bootsectandvi(boot_sector *bs, volume_info *volinfo, int *fatsize)
  639. {
  640. __u8 *block;
  641. volume_info *vistart;
  642. int ret = 0;
  643. if (cur_dev == NULL) {
  644. debug("Error: no device selected\n");
  645. return -1;
  646. }
  647. block = memalign(ARCH_DMA_MINALIGN, cur_dev->blksz);
  648. if (block == NULL) {
  649. debug("Error: allocating block\n");
  650. return -1;
  651. }
  652. if (disk_read(0, 1, block) < 0) {
  653. debug("Error: reading block\n");
  654. goto fail;
  655. }
  656. memcpy(bs, block, sizeof(boot_sector));
  657. bs->reserved = FAT2CPU16(bs->reserved);
  658. bs->fat_length = FAT2CPU16(bs->fat_length);
  659. bs->secs_track = FAT2CPU16(bs->secs_track);
  660. bs->heads = FAT2CPU16(bs->heads);
  661. bs->total_sect = FAT2CPU32(bs->total_sect);
  662. /* FAT32 entries */
  663. if (bs->fat_length == 0) {
  664. /* Assume FAT32 */
  665. bs->fat32_length = FAT2CPU32(bs->fat32_length);
  666. bs->flags = FAT2CPU16(bs->flags);
  667. bs->root_cluster = FAT2CPU32(bs->root_cluster);
  668. bs->info_sector = FAT2CPU16(bs->info_sector);
  669. bs->backup_boot = FAT2CPU16(bs->backup_boot);
  670. vistart = (volume_info *)(block + sizeof(boot_sector));
  671. *fatsize = 32;
  672. } else {
  673. vistart = (volume_info *)&(bs->fat32_length);
  674. *fatsize = 0;
  675. }
  676. memcpy(volinfo, vistart, sizeof(volume_info));
  677. if (*fatsize == 32) {
  678. if (strncmp(FAT32_SIGN, vistart->fs_type, SIGNLEN) == 0)
  679. goto exit;
  680. } else {
  681. if (strncmp(FAT12_SIGN, vistart->fs_type, SIGNLEN) == 0) {
  682. *fatsize = 12;
  683. goto exit;
  684. }
  685. if (strncmp(FAT16_SIGN, vistart->fs_type, SIGNLEN) == 0) {
  686. *fatsize = 16;
  687. goto exit;
  688. }
  689. }
  690. debug("Error: broken fs_type sign\n");
  691. fail:
  692. ret = -1;
  693. exit:
  694. free(block);
  695. return ret;
  696. }
  697. __u8 do_fat_read_at_block[MAX_CLUSTSIZE]
  698. __aligned(ARCH_DMA_MINALIGN);
  699. int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
  700. loff_t maxsize, int dols, int dogetsize, loff_t *size)
  701. {
  702. char fnamecopy[2048];
  703. boot_sector bs;
  704. volume_info volinfo;
  705. fsdata datablock;
  706. fsdata *mydata = &datablock;
  707. dir_entry *dentptr = NULL;
  708. __u16 prevcksum = 0xffff;
  709. char *subname = "";
  710. __u32 cursect;
  711. int idx, isdir = 0;
  712. int files = 0, dirs = 0;
  713. int ret = -1;
  714. int firsttime;
  715. __u32 root_cluster = 0;
  716. __u32 read_blk;
  717. int rootdir_size = 0;
  718. int buffer_blk_cnt;
  719. int do_read;
  720. __u8 *dir_ptr;
  721. if (read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) {
  722. debug("Error: reading boot sector\n");
  723. return -1;
  724. }
  725. if (mydata->fatsize == 32) {
  726. root_cluster = bs.root_cluster;
  727. mydata->fatlength = bs.fat32_length;
  728. } else {
  729. mydata->fatlength = bs.fat_length;
  730. }
  731. mydata->fat_sect = bs.reserved;
  732. cursect = mydata->rootdir_sect
  733. = mydata->fat_sect + mydata->fatlength * bs.fats;
  734. mydata->sect_size = (bs.sector_size[1] << 8) + bs.sector_size[0];
  735. mydata->clust_size = bs.cluster_size;
  736. if (mydata->sect_size != cur_part_info.blksz) {
  737. printf("Error: FAT sector size mismatch (fs=%hu, dev=%lu)\n",
  738. mydata->sect_size, cur_part_info.blksz);
  739. return -1;
  740. }
  741. if (mydata->fatsize == 32) {
  742. mydata->data_begin = mydata->rootdir_sect -
  743. (mydata->clust_size * 2);
  744. } else {
  745. rootdir_size = ((bs.dir_entries[1] * (int)256 +
  746. bs.dir_entries[0]) *
  747. sizeof(dir_entry)) /
  748. mydata->sect_size;
  749. mydata->data_begin = mydata->rootdir_sect +
  750. rootdir_size -
  751. (mydata->clust_size * 2);
  752. }
  753. mydata->fatbufnum = -1;
  754. mydata->fat_dirty = 0;
  755. mydata->fatbuf = memalign(ARCH_DMA_MINALIGN, FATBUFSIZE);
  756. if (mydata->fatbuf == NULL) {
  757. debug("Error: allocating memory\n");
  758. return -1;
  759. }
  760. if (vfat_enabled)
  761. debug("VFAT Support enabled\n");
  762. debug("FAT%d, fat_sect: %d, fatlength: %d\n",
  763. mydata->fatsize, mydata->fat_sect, mydata->fatlength);
  764. debug("Rootdir begins at cluster: %d, sector: %d, offset: %x\n"
  765. "Data begins at: %d\n",
  766. root_cluster,
  767. mydata->rootdir_sect,
  768. mydata->rootdir_sect * mydata->sect_size, mydata->data_begin);
  769. debug("Sector size: %d, cluster size: %d\n", mydata->sect_size,
  770. mydata->clust_size);
  771. /* "cwd" is always the root... */
  772. while (ISDIRDELIM(*filename))
  773. filename++;
  774. /* Make a copy of the filename and convert it to lowercase */
  775. strcpy(fnamecopy, filename);
  776. downcase(fnamecopy);
  777. root_reparse:
  778. if (*fnamecopy == '\0') {
  779. if (!dols)
  780. goto exit;
  781. dols = LS_ROOT;
  782. } else if ((idx = dirdelim(fnamecopy)) >= 0) {
  783. isdir = 1;
  784. fnamecopy[idx] = '\0';
  785. subname = fnamecopy + idx + 1;
  786. /* Handle multiple delimiters */
  787. while (ISDIRDELIM(*subname))
  788. subname++;
  789. } else if (dols) {
  790. isdir = 1;
  791. }
  792. buffer_blk_cnt = 0;
  793. firsttime = 1;
  794. while (1) {
  795. int i;
  796. if (mydata->fatsize == 32 || firsttime) {
  797. dir_ptr = do_fat_read_at_block;
  798. firsttime = 0;
  799. } else {
  800. /**
  801. * FAT16 sector buffer modification:
  802. * Each loop, the second buffered block is moved to
  803. * the buffer begin, and two next sectors are read
  804. * next to the previously moved one. So the sector
  805. * buffer keeps always 3 sectors for fat16.
  806. * And the current sector is the buffer second sector
  807. * beside the "firsttime" read, when it is the first one.
  808. *
  809. * PREFETCH_BLOCKS is 2 for FAT16 == loop[0:1]
  810. * n = computed root dir sector
  811. * loop | cursect-1 | cursect | cursect+1 |
  812. * 0 | sector n+0 | sector n+1 | none |
  813. * 1 | none | sector n+0 | sector n+1 |
  814. * 0 | sector n+1 | sector n+2 | sector n+3 |
  815. * 1 | sector n+3 | ...
  816. */
  817. dir_ptr = (do_fat_read_at_block + mydata->sect_size);
  818. memcpy(do_fat_read_at_block, dir_ptr, mydata->sect_size);
  819. }
  820. do_read = 1;
  821. if (mydata->fatsize == 32 && buffer_blk_cnt)
  822. do_read = 0;
  823. if (do_read) {
  824. read_blk = (mydata->fatsize == 32) ?
  825. mydata->clust_size : PREFETCH_BLOCKS;
  826. debug("FAT read(sect=%d, cnt:%d), clust_size=%d, DIRENTSPERBLOCK=%zd\n",
  827. cursect, read_blk, mydata->clust_size, DIRENTSPERBLOCK);
  828. if (disk_read(cursect, read_blk, dir_ptr) < 0) {
  829. debug("Error: reading rootdir block\n");
  830. goto exit;
  831. }
  832. dentptr = (dir_entry *)dir_ptr;
  833. }
  834. for (i = 0; i < DIRENTSPERBLOCK; i++) {
  835. char s_name[14], l_name[VFAT_MAXLEN_BYTES];
  836. __u8 csum;
  837. l_name[0] = '\0';
  838. if (dentptr->name[0] == DELETED_FLAG) {
  839. dentptr++;
  840. continue;
  841. }
  842. if (vfat_enabled)
  843. csum = mkcksum(dentptr->name, dentptr->ext);
  844. if (dentptr->attr & ATTR_VOLUME) {
  845. if (vfat_enabled &&
  846. (dentptr->attr & ATTR_VFAT) == ATTR_VFAT &&
  847. (dentptr->name[0] & LAST_LONG_ENTRY_MASK)) {
  848. prevcksum =
  849. ((dir_slot *)dentptr)->alias_checksum;
  850. get_vfatname(mydata,
  851. root_cluster,
  852. dir_ptr,
  853. dentptr, l_name);
  854. if (dols == LS_ROOT) {
  855. char dirc;
  856. int doit = 0;
  857. int isdir =
  858. (dentptr->attr & ATTR_DIR);
  859. if (isdir) {
  860. dirs++;
  861. dirc = '/';
  862. doit = 1;
  863. } else {
  864. dirc = ' ';
  865. if (l_name[0] != 0) {
  866. files++;
  867. doit = 1;
  868. }
  869. }
  870. if (doit) {
  871. if (dirc == ' ') {
  872. printf(" %8u %s%c\n",
  873. FAT2CPU32(dentptr->size),
  874. l_name,
  875. dirc);
  876. } else {
  877. printf(" %s%c\n",
  878. l_name,
  879. dirc);
  880. }
  881. }
  882. dentptr++;
  883. continue;
  884. }
  885. debug("Rootvfatname: |%s|\n",
  886. l_name);
  887. } else {
  888. /* Volume label or VFAT entry */
  889. dentptr++;
  890. continue;
  891. }
  892. } else if (dentptr->name[0] == 0) {
  893. debug("RootDentname == NULL - %d\n", i);
  894. if (dols == LS_ROOT) {
  895. printf("\n%d file(s), %d dir(s)\n\n",
  896. files, dirs);
  897. ret = 0;
  898. }
  899. goto exit;
  900. }
  901. else if (vfat_enabled &&
  902. dols == LS_ROOT && csum == prevcksum) {
  903. prevcksum = 0xffff;
  904. dentptr++;
  905. continue;
  906. }
  907. get_name(dentptr, s_name);
  908. if (dols == LS_ROOT) {
  909. int isdir = (dentptr->attr & ATTR_DIR);
  910. char dirc;
  911. int doit = 0;
  912. if (isdir) {
  913. dirc = '/';
  914. if (s_name[0] != 0) {
  915. dirs++;
  916. doit = 1;
  917. }
  918. } else {
  919. dirc = ' ';
  920. if (s_name[0] != 0) {
  921. files++;
  922. doit = 1;
  923. }
  924. }
  925. if (doit) {
  926. if (dirc == ' ') {
  927. printf(" %8u %s%c\n",
  928. FAT2CPU32(dentptr->size),
  929. s_name, dirc);
  930. } else {
  931. printf(" %s%c\n",
  932. s_name, dirc);
  933. }
  934. }
  935. dentptr++;
  936. continue;
  937. }
  938. if (strcmp(fnamecopy, s_name)
  939. && strcmp(fnamecopy, l_name)) {
  940. debug("RootMismatch: |%s|%s|\n", s_name,
  941. l_name);
  942. dentptr++;
  943. continue;
  944. }
  945. if (isdir && !(dentptr->attr & ATTR_DIR))
  946. goto exit;
  947. debug("RootName: %s", s_name);
  948. debug(", start: 0x%x", START(dentptr));
  949. debug(", size: 0x%x %s\n",
  950. FAT2CPU32(dentptr->size),
  951. isdir ? "(DIR)" : "");
  952. goto rootdir_done; /* We got a match */
  953. }
  954. debug("END LOOP: buffer_blk_cnt=%d clust_size=%d\n", buffer_blk_cnt,
  955. mydata->clust_size);
  956. /*
  957. * On FAT32 we must fetch the FAT entries for the next
  958. * root directory clusters when a cluster has been
  959. * completely processed.
  960. */
  961. ++buffer_blk_cnt;
  962. int rootdir_end = 0;
  963. if (mydata->fatsize == 32) {
  964. if (buffer_blk_cnt == mydata->clust_size) {
  965. int nxtsect = 0;
  966. int nxt_clust = 0;
  967. nxt_clust = get_fatent(mydata, root_cluster);
  968. rootdir_end = CHECK_CLUST(nxt_clust, 32);
  969. nxtsect = mydata->data_begin +
  970. (nxt_clust * mydata->clust_size);
  971. root_cluster = nxt_clust;
  972. cursect = nxtsect;
  973. buffer_blk_cnt = 0;
  974. }
  975. } else {
  976. if (buffer_blk_cnt == PREFETCH_BLOCKS)
  977. buffer_blk_cnt = 0;
  978. rootdir_end = (++cursect - mydata->rootdir_sect >=
  979. rootdir_size);
  980. }
  981. /* If end of rootdir reached */
  982. if (rootdir_end) {
  983. if (dols == LS_ROOT) {
  984. printf("\n%d file(s), %d dir(s)\n\n",
  985. files, dirs);
  986. *size = 0;
  987. }
  988. goto exit;
  989. }
  990. }
  991. rootdir_done:
  992. firsttime = 1;
  993. while (isdir) {
  994. int startsect = mydata->data_begin
  995. + START(dentptr) * mydata->clust_size;
  996. dir_entry dent;
  997. char *nextname = NULL;
  998. dent = *dentptr;
  999. dentptr = &dent;
  1000. idx = dirdelim(subname);
  1001. if (idx >= 0) {
  1002. subname[idx] = '\0';
  1003. nextname = subname + idx + 1;
  1004. /* Handle multiple delimiters */
  1005. while (ISDIRDELIM(*nextname))
  1006. nextname++;
  1007. if (dols && *nextname == '\0')
  1008. firsttime = 0;
  1009. } else {
  1010. if (dols && firsttime) {
  1011. firsttime = 0;
  1012. } else {
  1013. isdir = 0;
  1014. }
  1015. }
  1016. if (get_dentfromdir(mydata, startsect, subname, dentptr,
  1017. isdir ? 0 : dols) == NULL) {
  1018. if (dols && !isdir)
  1019. *size = 0;
  1020. goto exit;
  1021. }
  1022. if (isdir && !(dentptr->attr & ATTR_DIR))
  1023. goto exit;
  1024. /*
  1025. * If we are looking for a directory, and found a directory
  1026. * type entry, and the entry is for the root directory (as
  1027. * denoted by a cluster number of 0), jump back to the start
  1028. * of the function, since at least on FAT12/16, the root dir
  1029. * lives in a hard-coded location and needs special handling
  1030. * to parse, rather than simply following the cluster linked
  1031. * list in the FAT, like other directories.
  1032. */
  1033. if (isdir && (dentptr->attr & ATTR_DIR) && !START(dentptr)) {
  1034. /*
  1035. * Modify the filename to remove the prefix that gets
  1036. * back to the root directory, so the initial root dir
  1037. * parsing code can continue from where we are without
  1038. * confusion.
  1039. */
  1040. strcpy(fnamecopy, nextname ?: "");
  1041. /*
  1042. * Set up state the same way as the function does when
  1043. * first started. This is required for the root dir
  1044. * parsing code operates in its expected environment.
  1045. */
  1046. subname = "";
  1047. cursect = mydata->rootdir_sect;
  1048. isdir = 0;
  1049. goto root_reparse;
  1050. }
  1051. if (idx >= 0)
  1052. subname = nextname;
  1053. }
  1054. if (dogetsize) {
  1055. *size = FAT2CPU32(dentptr->size);
  1056. ret = 0;
  1057. } else {
  1058. ret = get_contents(mydata, dentptr, pos, buffer, maxsize, size);
  1059. }
  1060. debug("Size: %u, got: %llu\n", FAT2CPU32(dentptr->size), *size);
  1061. exit:
  1062. free(mydata->fatbuf);
  1063. return ret;
  1064. }
  1065. int do_fat_read(const char *filename, void *buffer, loff_t maxsize, int dols,
  1066. loff_t *actread)
  1067. {
  1068. return do_fat_read_at(filename, 0, buffer, maxsize, dols, 0, actread);
  1069. }
  1070. int file_fat_detectfs(void)
  1071. {
  1072. boot_sector bs;
  1073. volume_info volinfo;
  1074. int fatsize;
  1075. char vol_label[12];
  1076. if (cur_dev == NULL) {
  1077. printf("No current device\n");
  1078. return 1;
  1079. }
  1080. #if defined(CONFIG_CMD_IDE) || \
  1081. defined(CONFIG_CMD_SATA) || \
  1082. defined(CONFIG_SCSI) || \
  1083. defined(CONFIG_CMD_USB) || \
  1084. defined(CONFIG_MMC)
  1085. printf("Interface: ");
  1086. switch (cur_dev->if_type) {
  1087. case IF_TYPE_IDE:
  1088. printf("IDE");
  1089. break;
  1090. case IF_TYPE_SATA:
  1091. printf("SATA");
  1092. break;
  1093. case IF_TYPE_SCSI:
  1094. printf("SCSI");
  1095. break;
  1096. case IF_TYPE_ATAPI:
  1097. printf("ATAPI");
  1098. break;
  1099. case IF_TYPE_USB:
  1100. printf("USB");
  1101. break;
  1102. case IF_TYPE_DOC:
  1103. printf("DOC");
  1104. break;
  1105. case IF_TYPE_MMC:
  1106. printf("MMC");
  1107. break;
  1108. default:
  1109. printf("Unknown");
  1110. }
  1111. printf("\n Device %d: ", cur_dev->devnum);
  1112. dev_print(cur_dev);
  1113. #endif
  1114. if (read_bootsectandvi(&bs, &volinfo, &fatsize)) {
  1115. printf("\nNo valid FAT fs found\n");
  1116. return 1;
  1117. }
  1118. memcpy(vol_label, volinfo.volume_label, 11);
  1119. vol_label[11] = '\0';
  1120. volinfo.fs_type[5] = '\0';
  1121. printf("Filesystem: %s \"%s\"\n", volinfo.fs_type, vol_label);
  1122. return 0;
  1123. }
  1124. int file_fat_ls(const char *dir)
  1125. {
  1126. loff_t size;
  1127. return do_fat_read(dir, NULL, 0, LS_YES, &size);
  1128. }
  1129. int fat_exists(const char *filename)
  1130. {
  1131. int ret;
  1132. loff_t size;
  1133. ret = do_fat_read_at(filename, 0, NULL, 0, LS_NO, 1, &size);
  1134. return ret == 0;
  1135. }
  1136. int fat_size(const char *filename, loff_t *size)
  1137. {
  1138. return do_fat_read_at(filename, 0, NULL, 0, LS_NO, 1, size);
  1139. }
  1140. int file_fat_read_at(const char *filename, loff_t pos, void *buffer,
  1141. loff_t maxsize, loff_t *actread)
  1142. {
  1143. printf("reading %s\n", filename);
  1144. return do_fat_read_at(filename, pos, buffer, maxsize, LS_NO, 0,
  1145. actread);
  1146. }
  1147. int file_fat_read(const char *filename, void *buffer, int maxsize)
  1148. {
  1149. loff_t actread;
  1150. int ret;
  1151. ret = file_fat_read_at(filename, 0, buffer, maxsize, &actread);
  1152. if (ret)
  1153. return ret;
  1154. else
  1155. return actread;
  1156. }
  1157. int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len,
  1158. loff_t *actread)
  1159. {
  1160. int ret;
  1161. ret = file_fat_read_at(filename, offset, buf, len, actread);
  1162. if (ret)
  1163. printf("** Unable to read file %s **\n", filename);
  1164. return ret;
  1165. }
  1166. void fat_close(void)
  1167. {
  1168. }