fat.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * fat.c
  4. *
  5. * R/O (V)FAT 12/16/32 filesystem implementation by Marcus Sundberg
  6. *
  7. * 2002-07-28 - rjones@nexus-tech.net - ported to ppcboot v1.1.6
  8. * 2003-03-10 - kharris@nexus-tech.net - ported to uboot
  9. */
  10. #include <common.h>
  11. #include <blk.h>
  12. #include <config.h>
  13. #include <exports.h>
  14. #include <fat.h>
  15. #include <fs.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. /*
  23. * Convert a string to lowercase. Converts at most 'len' characters,
  24. * 'len' may be larger than the length of 'str' if 'str' is NULL
  25. * terminated.
  26. */
  27. static void downcase(char *str, size_t len)
  28. {
  29. while (*str != '\0' && len--) {
  30. *str = tolower(*str);
  31. str++;
  32. }
  33. }
  34. static struct blk_desc *cur_dev;
  35. static disk_partition_t cur_part_info;
  36. #define DOS_BOOT_MAGIC_OFFSET 0x1fe
  37. #define DOS_FS_TYPE_OFFSET 0x36
  38. #define DOS_FS32_TYPE_OFFSET 0x52
  39. static int disk_read(__u32 block, __u32 nr_blocks, void *buf)
  40. {
  41. ulong ret;
  42. if (!cur_dev)
  43. return -1;
  44. ret = blk_dread(cur_dev, cur_part_info.start + block, nr_blocks, buf);
  45. if (ret != nr_blocks)
  46. return -1;
  47. return ret;
  48. }
  49. int fat_set_blk_dev(struct blk_desc *dev_desc, disk_partition_t *info)
  50. {
  51. ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz);
  52. cur_dev = dev_desc;
  53. cur_part_info = *info;
  54. /* Make sure it has a valid FAT header */
  55. if (disk_read(0, 1, buffer) != 1) {
  56. cur_dev = NULL;
  57. return -1;
  58. }
  59. /* Check if it's actually a DOS volume */
  60. if (memcmp(buffer + DOS_BOOT_MAGIC_OFFSET, "\x55\xAA", 2)) {
  61. cur_dev = NULL;
  62. return -1;
  63. }
  64. /* Check for FAT12/FAT16/FAT32 filesystem */
  65. if (!memcmp(buffer + DOS_FS_TYPE_OFFSET, "FAT", 3))
  66. return 0;
  67. if (!memcmp(buffer + DOS_FS32_TYPE_OFFSET, "FAT32", 5))
  68. return 0;
  69. cur_dev = NULL;
  70. return -1;
  71. }
  72. int fat_register_device(struct blk_desc *dev_desc, int part_no)
  73. {
  74. disk_partition_t info;
  75. /* First close any currently found FAT filesystem */
  76. cur_dev = NULL;
  77. /* Read the partition table, if present */
  78. if (part_get_info(dev_desc, part_no, &info)) {
  79. if (part_no != 0) {
  80. printf("** Partition %d not valid on device %d **\n",
  81. part_no, dev_desc->devnum);
  82. return -1;
  83. }
  84. info.start = 0;
  85. info.size = dev_desc->lba;
  86. info.blksz = dev_desc->blksz;
  87. info.name[0] = 0;
  88. info.type[0] = 0;
  89. info.bootable = 0;
  90. #if CONFIG_IS_ENABLED(PARTITION_UUIDS)
  91. info.uuid[0] = 0;
  92. #endif
  93. }
  94. return fat_set_blk_dev(dev_desc, &info);
  95. }
  96. /*
  97. * Extract zero terminated short name from a directory entry.
  98. */
  99. static void get_name(dir_entry *dirent, char *s_name)
  100. {
  101. char *ptr;
  102. memcpy(s_name, dirent->name, 8);
  103. s_name[8] = '\0';
  104. ptr = s_name;
  105. while (*ptr && *ptr != ' ')
  106. ptr++;
  107. if (dirent->lcase & CASE_LOWER_BASE)
  108. downcase(s_name, (unsigned)(ptr - s_name));
  109. if (dirent->ext[0] && dirent->ext[0] != ' ') {
  110. *ptr++ = '.';
  111. memcpy(ptr, dirent->ext, 3);
  112. if (dirent->lcase & CASE_LOWER_EXT)
  113. downcase(ptr, 3);
  114. ptr[3] = '\0';
  115. while (*ptr && *ptr != ' ')
  116. ptr++;
  117. }
  118. *ptr = '\0';
  119. if (*s_name == DELETED_FLAG)
  120. *s_name = '\0';
  121. else if (*s_name == aRING)
  122. *s_name = DELETED_FLAG;
  123. }
  124. static int flush_dirty_fat_buffer(fsdata *mydata);
  125. #if !defined(CONFIG_FAT_WRITE)
  126. /* Stub for read only operation */
  127. int flush_dirty_fat_buffer(fsdata *mydata)
  128. {
  129. (void)(mydata);
  130. return 0;
  131. }
  132. #endif
  133. /*
  134. * Get the entry at index 'entry' in a FAT (12/16/32) table.
  135. * On failure 0x00 is returned.
  136. */
  137. static __u32 get_fatent(fsdata *mydata, __u32 entry)
  138. {
  139. __u32 bufnum;
  140. __u32 offset, off8;
  141. __u32 ret = 0x00;
  142. if (CHECK_CLUST(entry, mydata->fatsize)) {
  143. printf("Error: Invalid FAT entry: 0x%08x\n", entry);
  144. return ret;
  145. }
  146. switch (mydata->fatsize) {
  147. case 32:
  148. bufnum = entry / FAT32BUFSIZE;
  149. offset = entry - bufnum * FAT32BUFSIZE;
  150. break;
  151. case 16:
  152. bufnum = entry / FAT16BUFSIZE;
  153. offset = entry - bufnum * FAT16BUFSIZE;
  154. break;
  155. case 12:
  156. bufnum = entry / FAT12BUFSIZE;
  157. offset = entry - bufnum * FAT12BUFSIZE;
  158. break;
  159. default:
  160. /* Unsupported FAT size */
  161. return ret;
  162. }
  163. debug("FAT%d: entry: 0x%08x = %d, offset: 0x%04x = %d\n",
  164. mydata->fatsize, entry, entry, offset, offset);
  165. /* Read a new block of FAT entries into the cache. */
  166. if (bufnum != mydata->fatbufnum) {
  167. __u32 getsize = FATBUFBLOCKS;
  168. __u8 *bufptr = mydata->fatbuf;
  169. __u32 fatlength = mydata->fatlength;
  170. __u32 startblock = bufnum * FATBUFBLOCKS;
  171. /* Cap length if fatlength is not a multiple of FATBUFBLOCKS */
  172. if (startblock + getsize > fatlength)
  173. getsize = fatlength - startblock;
  174. startblock += mydata->fat_sect; /* Offset from start of disk */
  175. /* Write back the fatbuf to the disk */
  176. if (flush_dirty_fat_buffer(mydata) < 0)
  177. return -1;
  178. if (disk_read(startblock, getsize, bufptr) < 0) {
  179. debug("Error reading FAT blocks\n");
  180. return ret;
  181. }
  182. mydata->fatbufnum = bufnum;
  183. }
  184. /* Get the actual entry from the table */
  185. switch (mydata->fatsize) {
  186. case 32:
  187. ret = FAT2CPU32(((__u32 *) mydata->fatbuf)[offset]);
  188. break;
  189. case 16:
  190. ret = FAT2CPU16(((__u16 *) mydata->fatbuf)[offset]);
  191. break;
  192. case 12:
  193. off8 = (offset * 3) / 2;
  194. /* fatbut + off8 may be unaligned, read in byte granularity */
  195. ret = mydata->fatbuf[off8] + (mydata->fatbuf[off8 + 1] << 8);
  196. if (offset & 0x1)
  197. ret >>= 4;
  198. ret &= 0xfff;
  199. }
  200. debug("FAT%d: ret: 0x%08x, entry: 0x%08x, offset: 0x%04x\n",
  201. mydata->fatsize, ret, entry, offset);
  202. return ret;
  203. }
  204. /*
  205. * Read at most 'size' bytes from the specified cluster into 'buffer'.
  206. * Return 0 on success, -1 otherwise.
  207. */
  208. static int
  209. get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size)
  210. {
  211. __u32 idx = 0;
  212. __u32 startsect;
  213. int ret;
  214. if (clustnum > 0) {
  215. startsect = clust_to_sect(mydata, clustnum);
  216. } else {
  217. startsect = mydata->rootdir_sect;
  218. }
  219. debug("gc - clustnum: %d, startsect: %d\n", clustnum, startsect);
  220. if ((unsigned long)buffer & (ARCH_DMA_MINALIGN - 1)) {
  221. ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size);
  222. debug("FAT: Misaligned buffer address (%p)\n", buffer);
  223. while (size >= mydata->sect_size) {
  224. ret = disk_read(startsect++, 1, tmpbuf);
  225. if (ret != 1) {
  226. debug("Error reading data (got %d)\n", ret);
  227. return -1;
  228. }
  229. memcpy(buffer, tmpbuf, mydata->sect_size);
  230. buffer += mydata->sect_size;
  231. size -= mydata->sect_size;
  232. }
  233. } else {
  234. idx = size / mydata->sect_size;
  235. ret = disk_read(startsect, idx, buffer);
  236. if (ret != idx) {
  237. debug("Error reading data (got %d)\n", ret);
  238. return -1;
  239. }
  240. startsect += idx;
  241. idx *= mydata->sect_size;
  242. buffer += idx;
  243. size -= idx;
  244. }
  245. if (size) {
  246. ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size);
  247. ret = disk_read(startsect, 1, tmpbuf);
  248. if (ret != 1) {
  249. debug("Error reading data (got %d)\n", ret);
  250. return -1;
  251. }
  252. memcpy(buffer, tmpbuf, size);
  253. }
  254. return 0;
  255. }
  256. /*
  257. * Read at most 'maxsize' bytes from 'pos' in the file associated with 'dentptr'
  258. * into 'buffer'.
  259. * Update the number of bytes read in *gotsize or return -1 on fatal errors.
  260. */
  261. __u8 get_contents_vfatname_block[MAX_CLUSTSIZE]
  262. __aligned(ARCH_DMA_MINALIGN);
  263. static int get_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos,
  264. __u8 *buffer, loff_t maxsize, loff_t *gotsize)
  265. {
  266. loff_t filesize = FAT2CPU32(dentptr->size);
  267. unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
  268. __u32 curclust = START(dentptr);
  269. __u32 endclust, newclust;
  270. loff_t actsize;
  271. *gotsize = 0;
  272. debug("Filesize: %llu bytes\n", filesize);
  273. if (pos >= filesize) {
  274. debug("Read position past EOF: %llu\n", pos);
  275. return 0;
  276. }
  277. if (maxsize > 0 && filesize > pos + maxsize)
  278. filesize = pos + maxsize;
  279. debug("%llu bytes\n", filesize);
  280. actsize = bytesperclust;
  281. /* go to cluster at pos */
  282. while (actsize <= pos) {
  283. curclust = get_fatent(mydata, curclust);
  284. if (CHECK_CLUST(curclust, mydata->fatsize)) {
  285. debug("curclust: 0x%x\n", curclust);
  286. debug("Invalid FAT entry\n");
  287. return 0;
  288. }
  289. actsize += bytesperclust;
  290. }
  291. /* actsize > pos */
  292. actsize -= bytesperclust;
  293. filesize -= actsize;
  294. pos -= actsize;
  295. /* align to beginning of next cluster if any */
  296. if (pos) {
  297. actsize = min(filesize, (loff_t)bytesperclust);
  298. if (get_cluster(mydata, curclust, get_contents_vfatname_block,
  299. (int)actsize) != 0) {
  300. printf("Error reading cluster\n");
  301. return -1;
  302. }
  303. filesize -= actsize;
  304. actsize -= pos;
  305. memcpy(buffer, get_contents_vfatname_block + pos, actsize);
  306. *gotsize += actsize;
  307. if (!filesize)
  308. return 0;
  309. buffer += actsize;
  310. curclust = get_fatent(mydata, curclust);
  311. if (CHECK_CLUST(curclust, mydata->fatsize)) {
  312. debug("curclust: 0x%x\n", curclust);
  313. debug("Invalid FAT entry\n");
  314. return 0;
  315. }
  316. }
  317. actsize = bytesperclust;
  318. endclust = curclust;
  319. do {
  320. /* search for consecutive clusters */
  321. while (actsize < filesize) {
  322. newclust = get_fatent(mydata, endclust);
  323. if ((newclust - 1) != endclust)
  324. goto getit;
  325. if (CHECK_CLUST(newclust, mydata->fatsize)) {
  326. debug("curclust: 0x%x\n", newclust);
  327. debug("Invalid FAT entry\n");
  328. return 0;
  329. }
  330. endclust = newclust;
  331. actsize += bytesperclust;
  332. }
  333. /* get remaining bytes */
  334. actsize = filesize;
  335. if (get_cluster(mydata, curclust, buffer, (int)actsize) != 0) {
  336. printf("Error reading cluster\n");
  337. return -1;
  338. }
  339. *gotsize += actsize;
  340. return 0;
  341. getit:
  342. if (get_cluster(mydata, curclust, buffer, (int)actsize) != 0) {
  343. printf("Error reading cluster\n");
  344. return -1;
  345. }
  346. *gotsize += (int)actsize;
  347. filesize -= actsize;
  348. buffer += actsize;
  349. curclust = get_fatent(mydata, endclust);
  350. if (CHECK_CLUST(curclust, mydata->fatsize)) {
  351. debug("curclust: 0x%x\n", curclust);
  352. printf("Invalid FAT entry\n");
  353. return 0;
  354. }
  355. actsize = bytesperclust;
  356. endclust = curclust;
  357. } while (1);
  358. }
  359. /*
  360. * Extract the file name information from 'slotptr' into 'l_name',
  361. * starting at l_name[*idx].
  362. * Return 1 if terminator (zero byte) is found, 0 otherwise.
  363. */
  364. static int slot2str(dir_slot *slotptr, char *l_name, int *idx)
  365. {
  366. int j;
  367. for (j = 0; j <= 8; j += 2) {
  368. l_name[*idx] = slotptr->name0_4[j];
  369. if (l_name[*idx] == 0x00)
  370. return 1;
  371. (*idx)++;
  372. }
  373. for (j = 0; j <= 10; j += 2) {
  374. l_name[*idx] = slotptr->name5_10[j];
  375. if (l_name[*idx] == 0x00)
  376. return 1;
  377. (*idx)++;
  378. }
  379. for (j = 0; j <= 2; j += 2) {
  380. l_name[*idx] = slotptr->name11_12[j];
  381. if (l_name[*idx] == 0x00)
  382. return 1;
  383. (*idx)++;
  384. }
  385. return 0;
  386. }
  387. /* Calculate short name checksum */
  388. static __u8 mkcksum(const char name[8], const char ext[3])
  389. {
  390. int i;
  391. __u8 ret = 0;
  392. for (i = 0; i < 8; i++)
  393. ret = (((ret & 1) << 7) | ((ret & 0xfe) >> 1)) + name[i];
  394. for (i = 0; i < 3; i++)
  395. ret = (((ret & 1) << 7) | ((ret & 0xfe) >> 1)) + ext[i];
  396. return ret;
  397. }
  398. /*
  399. * Read boot sector and volume info from a FAT filesystem
  400. */
  401. static int
  402. read_bootsectandvi(boot_sector *bs, volume_info *volinfo, int *fatsize)
  403. {
  404. __u8 *block;
  405. volume_info *vistart;
  406. int ret = 0;
  407. if (cur_dev == NULL) {
  408. debug("Error: no device selected\n");
  409. return -1;
  410. }
  411. block = malloc_cache_aligned(cur_dev->blksz);
  412. if (block == NULL) {
  413. debug("Error: allocating block\n");
  414. return -1;
  415. }
  416. if (disk_read(0, 1, block) < 0) {
  417. debug("Error: reading block\n");
  418. goto fail;
  419. }
  420. memcpy(bs, block, sizeof(boot_sector));
  421. bs->reserved = FAT2CPU16(bs->reserved);
  422. bs->fat_length = FAT2CPU16(bs->fat_length);
  423. bs->secs_track = FAT2CPU16(bs->secs_track);
  424. bs->heads = FAT2CPU16(bs->heads);
  425. bs->total_sect = FAT2CPU32(bs->total_sect);
  426. /* FAT32 entries */
  427. if (bs->fat_length == 0) {
  428. /* Assume FAT32 */
  429. bs->fat32_length = FAT2CPU32(bs->fat32_length);
  430. bs->flags = FAT2CPU16(bs->flags);
  431. bs->root_cluster = FAT2CPU32(bs->root_cluster);
  432. bs->info_sector = FAT2CPU16(bs->info_sector);
  433. bs->backup_boot = FAT2CPU16(bs->backup_boot);
  434. vistart = (volume_info *)(block + sizeof(boot_sector));
  435. *fatsize = 32;
  436. } else {
  437. vistart = (volume_info *)&(bs->fat32_length);
  438. *fatsize = 0;
  439. }
  440. memcpy(volinfo, vistart, sizeof(volume_info));
  441. if (*fatsize == 32) {
  442. if (strncmp(FAT32_SIGN, vistart->fs_type, SIGNLEN) == 0)
  443. goto exit;
  444. } else {
  445. if (strncmp(FAT12_SIGN, vistart->fs_type, SIGNLEN) == 0) {
  446. *fatsize = 12;
  447. goto exit;
  448. }
  449. if (strncmp(FAT16_SIGN, vistart->fs_type, SIGNLEN) == 0) {
  450. *fatsize = 16;
  451. goto exit;
  452. }
  453. }
  454. debug("Error: broken fs_type sign\n");
  455. fail:
  456. ret = -1;
  457. exit:
  458. free(block);
  459. return ret;
  460. }
  461. static int get_fs_info(fsdata *mydata)
  462. {
  463. boot_sector bs;
  464. volume_info volinfo;
  465. int ret;
  466. ret = read_bootsectandvi(&bs, &volinfo, &mydata->fatsize);
  467. if (ret) {
  468. debug("Error: reading boot sector\n");
  469. return ret;
  470. }
  471. if (mydata->fatsize == 32) {
  472. mydata->fatlength = bs.fat32_length;
  473. mydata->total_sect = bs.total_sect;
  474. } else {
  475. mydata->fatlength = bs.fat_length;
  476. mydata->total_sect = (bs.sectors[1] << 8) + bs.sectors[0];
  477. if (!mydata->total_sect)
  478. mydata->total_sect = bs.total_sect;
  479. }
  480. if (!mydata->total_sect) /* unlikely */
  481. mydata->total_sect = (u32)cur_part_info.size;
  482. mydata->fats = bs.fats;
  483. mydata->fat_sect = bs.reserved;
  484. mydata->rootdir_sect = mydata->fat_sect + mydata->fatlength * bs.fats;
  485. mydata->sect_size = (bs.sector_size[1] << 8) + bs.sector_size[0];
  486. mydata->clust_size = bs.cluster_size;
  487. if (mydata->sect_size != cur_part_info.blksz) {
  488. printf("Error: FAT sector size mismatch (fs=%hu, dev=%lu)\n",
  489. mydata->sect_size, cur_part_info.blksz);
  490. return -1;
  491. }
  492. if (mydata->fatsize == 32) {
  493. mydata->data_begin = mydata->rootdir_sect -
  494. (mydata->clust_size * 2);
  495. mydata->root_cluster = bs.root_cluster;
  496. } else {
  497. mydata->rootdir_size = ((bs.dir_entries[1] * (int)256 +
  498. bs.dir_entries[0]) *
  499. sizeof(dir_entry)) /
  500. mydata->sect_size;
  501. mydata->data_begin = mydata->rootdir_sect +
  502. mydata->rootdir_size -
  503. (mydata->clust_size * 2);
  504. mydata->root_cluster =
  505. sect_to_clust(mydata, mydata->rootdir_sect);
  506. }
  507. mydata->fatbufnum = -1;
  508. mydata->fat_dirty = 0;
  509. mydata->fatbuf = malloc_cache_aligned(FATBUFSIZE);
  510. if (mydata->fatbuf == NULL) {
  511. debug("Error: allocating memory\n");
  512. return -1;
  513. }
  514. debug("FAT%d, fat_sect: %d, fatlength: %d\n",
  515. mydata->fatsize, mydata->fat_sect, mydata->fatlength);
  516. debug("Rootdir begins at cluster: %d, sector: %d, offset: %x\n"
  517. "Data begins at: %d\n",
  518. mydata->root_cluster,
  519. mydata->rootdir_sect,
  520. mydata->rootdir_sect * mydata->sect_size, mydata->data_begin);
  521. debug("Sector size: %d, cluster size: %d\n", mydata->sect_size,
  522. mydata->clust_size);
  523. return 0;
  524. }
  525. /*
  526. * Directory iterator, to simplify filesystem traversal
  527. *
  528. * Implements an iterator pattern to traverse directory tables,
  529. * transparently handling directory tables split across multiple
  530. * clusters, and the difference between FAT12/FAT16 root directory
  531. * (contiguous) and subdirectories + FAT32 root (chained).
  532. *
  533. * Rough usage:
  534. *
  535. * for (fat_itr_root(&itr, fsdata); fat_itr_next(&itr); ) {
  536. * // to traverse down to a subdirectory pointed to by
  537. * // current iterator position:
  538. * fat_itr_child(&itr, &itr);
  539. * }
  540. *
  541. * For more complete example, see fat_itr_resolve()
  542. */
  543. typedef struct {
  544. fsdata *fsdata; /* filesystem parameters */
  545. unsigned start_clust; /* first cluster */
  546. unsigned clust; /* current cluster */
  547. unsigned next_clust; /* next cluster if remaining == 0 */
  548. int last_cluster; /* set once we've read last cluster */
  549. int is_root; /* is iterator at root directory */
  550. int remaining; /* remaining dent's in current cluster */
  551. /* current iterator position values: */
  552. dir_entry *dent; /* current directory entry */
  553. char l_name[VFAT_MAXLEN_BYTES]; /* long (vfat) name */
  554. char s_name[14]; /* short 8.3 name */
  555. char *name; /* l_name if there is one, else s_name */
  556. /* storage for current cluster in memory: */
  557. u8 block[MAX_CLUSTSIZE] __aligned(ARCH_DMA_MINALIGN);
  558. } fat_itr;
  559. static int fat_itr_isdir(fat_itr *itr);
  560. /**
  561. * fat_itr_root() - initialize an iterator to start at the root
  562. * directory
  563. *
  564. * @itr: iterator to initialize
  565. * @fsdata: filesystem data for the partition
  566. * @return 0 on success, else -errno
  567. */
  568. static int fat_itr_root(fat_itr *itr, fsdata *fsdata)
  569. {
  570. if (get_fs_info(fsdata))
  571. return -ENXIO;
  572. itr->fsdata = fsdata;
  573. itr->start_clust = 0;
  574. itr->clust = fsdata->root_cluster;
  575. itr->next_clust = fsdata->root_cluster;
  576. itr->dent = NULL;
  577. itr->remaining = 0;
  578. itr->last_cluster = 0;
  579. itr->is_root = 1;
  580. return 0;
  581. }
  582. /**
  583. * fat_itr_child() - initialize an iterator to descend into a sub-
  584. * directory
  585. *
  586. * Initializes 'itr' to iterate the contents of the directory at
  587. * the current cursor position of 'parent'. It is an error to
  588. * call this if the current cursor of 'parent' is pointing at a
  589. * regular file.
  590. *
  591. * Note that 'itr' and 'parent' can be the same pointer if you do
  592. * not need to preserve 'parent' after this call, which is useful
  593. * for traversing directory structure to resolve a file/directory.
  594. *
  595. * @itr: iterator to initialize
  596. * @parent: the iterator pointing at a directory entry in the
  597. * parent directory of the directory to iterate
  598. */
  599. static void fat_itr_child(fat_itr *itr, fat_itr *parent)
  600. {
  601. fsdata *mydata = parent->fsdata; /* for silly macros */
  602. unsigned clustnum = START(parent->dent);
  603. assert(fat_itr_isdir(parent));
  604. itr->fsdata = parent->fsdata;
  605. itr->start_clust = clustnum;
  606. if (clustnum > 0) {
  607. itr->clust = clustnum;
  608. itr->next_clust = clustnum;
  609. itr->is_root = 0;
  610. } else {
  611. itr->clust = parent->fsdata->root_cluster;
  612. itr->next_clust = parent->fsdata->root_cluster;
  613. itr->is_root = 1;
  614. }
  615. itr->dent = NULL;
  616. itr->remaining = 0;
  617. itr->last_cluster = 0;
  618. }
  619. static void *next_cluster(fat_itr *itr)
  620. {
  621. fsdata *mydata = itr->fsdata; /* for silly macros */
  622. int ret;
  623. u32 sect;
  624. /* have we reached the end? */
  625. if (itr->last_cluster)
  626. return NULL;
  627. if (itr->fsdata->fatsize != 32 && itr->is_root)
  628. sect = mydata->rootdir_sect;
  629. else
  630. sect = clust_to_sect(itr->fsdata, itr->next_clust);
  631. debug("FAT read(sect=%d), clust_size=%d, DIRENTSPERBLOCK=%zd\n",
  632. sect, itr->fsdata->clust_size, DIRENTSPERBLOCK);
  633. /*
  634. * NOTE: do_fat_read_at() had complicated logic to deal w/
  635. * vfat names that span multiple clusters in the fat16 case,
  636. * which get_dentfromdir() probably also needed (and was
  637. * missing). And not entirely sure what fat32 didn't have
  638. * the same issue.. We solve that by only caring about one
  639. * dent at a time and iteratively constructing the vfat long
  640. * name.
  641. */
  642. ret = disk_read(sect, itr->fsdata->clust_size,
  643. itr->block);
  644. if (ret < 0) {
  645. debug("Error: reading block\n");
  646. return NULL;
  647. }
  648. itr->clust = itr->next_clust;
  649. if (itr->is_root && itr->fsdata->fatsize != 32) {
  650. itr->next_clust++;
  651. sect = clust_to_sect(itr->fsdata, itr->next_clust);
  652. if (sect - itr->fsdata->rootdir_sect >=
  653. itr->fsdata->rootdir_size) {
  654. debug("nextclust: 0x%x\n", itr->next_clust);
  655. itr->last_cluster = 1;
  656. }
  657. } else {
  658. itr->next_clust = get_fatent(itr->fsdata, itr->next_clust);
  659. if (CHECK_CLUST(itr->next_clust, itr->fsdata->fatsize)) {
  660. debug("nextclust: 0x%x\n", itr->next_clust);
  661. itr->last_cluster = 1;
  662. }
  663. }
  664. return itr->block;
  665. }
  666. static dir_entry *next_dent(fat_itr *itr)
  667. {
  668. if (itr->remaining == 0) {
  669. struct dir_entry *dent = next_cluster(itr);
  670. unsigned nbytes = itr->fsdata->sect_size *
  671. itr->fsdata->clust_size;
  672. /* have we reached the last cluster? */
  673. if (!dent) {
  674. /* a sign for no more entries left */
  675. itr->dent = NULL;
  676. return NULL;
  677. }
  678. itr->remaining = nbytes / sizeof(dir_entry) - 1;
  679. itr->dent = dent;
  680. } else {
  681. itr->remaining--;
  682. itr->dent++;
  683. }
  684. /* have we reached the last valid entry? */
  685. if (itr->dent->name[0] == 0)
  686. return NULL;
  687. return itr->dent;
  688. }
  689. static dir_entry *extract_vfat_name(fat_itr *itr)
  690. {
  691. struct dir_entry *dent = itr->dent;
  692. int seqn = itr->dent->name[0] & ~LAST_LONG_ENTRY_MASK;
  693. u8 chksum, alias_checksum = ((dir_slot *)dent)->alias_checksum;
  694. int n = 0;
  695. while (seqn--) {
  696. char buf[13];
  697. int idx = 0;
  698. slot2str((dir_slot *)dent, buf, &idx);
  699. /* shift accumulated long-name up and copy new part in: */
  700. memmove(itr->l_name + idx, itr->l_name, n);
  701. memcpy(itr->l_name, buf, idx);
  702. n += idx;
  703. dent = next_dent(itr);
  704. if (!dent)
  705. return NULL;
  706. }
  707. itr->l_name[n] = '\0';
  708. chksum = mkcksum(dent->name, dent->ext);
  709. /* checksum mismatch could mean deleted file, etc.. skip it: */
  710. if (chksum != alias_checksum) {
  711. debug("** chksum=%x, alias_checksum=%x, l_name=%s, s_name=%8s.%3s\n",
  712. chksum, alias_checksum, itr->l_name, dent->name, dent->ext);
  713. return NULL;
  714. }
  715. return dent;
  716. }
  717. /**
  718. * fat_itr_next() - step to the next entry in a directory
  719. *
  720. * Must be called once on a new iterator before the cursor is valid.
  721. *
  722. * @itr: the iterator to iterate
  723. * @return boolean, 1 if success or 0 if no more entries in the
  724. * current directory
  725. */
  726. static int fat_itr_next(fat_itr *itr)
  727. {
  728. dir_entry *dent;
  729. itr->name = NULL;
  730. while (1) {
  731. dent = next_dent(itr);
  732. if (!dent)
  733. return 0;
  734. if (dent->name[0] == DELETED_FLAG ||
  735. dent->name[0] == aRING)
  736. continue;
  737. if (dent->attr & ATTR_VOLUME) {
  738. if ((dent->attr & ATTR_VFAT) == ATTR_VFAT &&
  739. (dent->name[0] & LAST_LONG_ENTRY_MASK)) {
  740. dent = extract_vfat_name(itr);
  741. if (!dent)
  742. continue;
  743. itr->name = itr->l_name;
  744. break;
  745. } else {
  746. /* Volume label or VFAT entry, skip */
  747. continue;
  748. }
  749. }
  750. break;
  751. }
  752. get_name(dent, itr->s_name);
  753. if (!itr->name)
  754. itr->name = itr->s_name;
  755. return 1;
  756. }
  757. /**
  758. * fat_itr_isdir() - is current cursor position pointing to a directory
  759. *
  760. * @itr: the iterator
  761. * @return true if cursor is at a directory
  762. */
  763. static int fat_itr_isdir(fat_itr *itr)
  764. {
  765. return !!(itr->dent->attr & ATTR_DIR);
  766. }
  767. /*
  768. * Helpers:
  769. */
  770. #define TYPE_FILE 0x1
  771. #define TYPE_DIR 0x2
  772. #define TYPE_ANY (TYPE_FILE | TYPE_DIR)
  773. /**
  774. * fat_itr_resolve() - traverse directory structure to resolve the
  775. * requested path.
  776. *
  777. * Traverse directory structure to the requested path. If the specified
  778. * path is to a directory, this will descend into the directory and
  779. * leave it iterator at the start of the directory. If the path is to a
  780. * file, it will leave the iterator in the parent directory with current
  781. * cursor at file's entry in the directory.
  782. *
  783. * @itr: iterator initialized to root
  784. * @path: the requested path
  785. * @type: bitmask of allowable file types
  786. * @return 0 on success or -errno
  787. */
  788. static int fat_itr_resolve(fat_itr *itr, const char *path, unsigned type)
  789. {
  790. const char *next;
  791. /* chomp any extra leading slashes: */
  792. while (path[0] && ISDIRDELIM(path[0]))
  793. path++;
  794. /* are we at the end? */
  795. if (strlen(path) == 0) {
  796. if (!(type & TYPE_DIR))
  797. return -ENOENT;
  798. return 0;
  799. }
  800. /* find length of next path entry: */
  801. next = path;
  802. while (next[0] && !ISDIRDELIM(next[0]))
  803. next++;
  804. if (itr->is_root) {
  805. /* root dir doesn't have "." nor ".." */
  806. if ((((next - path) == 1) && !strncmp(path, ".", 1)) ||
  807. (((next - path) == 2) && !strncmp(path, "..", 2))) {
  808. /* point back to itself */
  809. itr->clust = itr->fsdata->root_cluster;
  810. itr->next_clust = itr->fsdata->root_cluster;
  811. itr->dent = NULL;
  812. itr->remaining = 0;
  813. itr->last_cluster = 0;
  814. if (next[0] == 0) {
  815. if (type & TYPE_DIR)
  816. return 0;
  817. else
  818. return -ENOENT;
  819. }
  820. return fat_itr_resolve(itr, next, type);
  821. }
  822. }
  823. while (fat_itr_next(itr)) {
  824. int match = 0;
  825. unsigned n = max(strlen(itr->name), (size_t)(next - path));
  826. /* check both long and short name: */
  827. if (!strncasecmp(path, itr->name, n))
  828. match = 1;
  829. else if (itr->name != itr->s_name &&
  830. !strncasecmp(path, itr->s_name, n))
  831. match = 1;
  832. if (!match)
  833. continue;
  834. if (fat_itr_isdir(itr)) {
  835. /* recurse into directory: */
  836. fat_itr_child(itr, itr);
  837. return fat_itr_resolve(itr, next, type);
  838. } else if (next[0]) {
  839. /*
  840. * If next is not empty then we have a case
  841. * like: /path/to/realfile/nonsense
  842. */
  843. debug("bad trailing path: %s\n", next);
  844. return -ENOENT;
  845. } else if (!(type & TYPE_FILE)) {
  846. return -ENOTDIR;
  847. } else {
  848. return 0;
  849. }
  850. }
  851. return -ENOENT;
  852. }
  853. int file_fat_detectfs(void)
  854. {
  855. boot_sector bs;
  856. volume_info volinfo;
  857. int fatsize;
  858. char vol_label[12];
  859. if (cur_dev == NULL) {
  860. printf("No current device\n");
  861. return 1;
  862. }
  863. #if defined(CONFIG_IDE) || \
  864. defined(CONFIG_SATA) || \
  865. defined(CONFIG_SCSI) || \
  866. defined(CONFIG_CMD_USB) || \
  867. defined(CONFIG_MMC)
  868. printf("Interface: ");
  869. switch (cur_dev->if_type) {
  870. case IF_TYPE_IDE:
  871. printf("IDE");
  872. break;
  873. case IF_TYPE_SATA:
  874. printf("SATA");
  875. break;
  876. case IF_TYPE_SCSI:
  877. printf("SCSI");
  878. break;
  879. case IF_TYPE_ATAPI:
  880. printf("ATAPI");
  881. break;
  882. case IF_TYPE_USB:
  883. printf("USB");
  884. break;
  885. case IF_TYPE_DOC:
  886. printf("DOC");
  887. break;
  888. case IF_TYPE_MMC:
  889. printf("MMC");
  890. break;
  891. default:
  892. printf("Unknown");
  893. }
  894. printf("\n Device %d: ", cur_dev->devnum);
  895. dev_print(cur_dev);
  896. #endif
  897. if (read_bootsectandvi(&bs, &volinfo, &fatsize)) {
  898. printf("\nNo valid FAT fs found\n");
  899. return 1;
  900. }
  901. memcpy(vol_label, volinfo.volume_label, 11);
  902. vol_label[11] = '\0';
  903. volinfo.fs_type[5] = '\0';
  904. printf("Filesystem: %s \"%s\"\n", volinfo.fs_type, vol_label);
  905. return 0;
  906. }
  907. int fat_exists(const char *filename)
  908. {
  909. fsdata fsdata;
  910. fat_itr *itr;
  911. int ret;
  912. itr = malloc_cache_aligned(sizeof(fat_itr));
  913. if (!itr)
  914. return 0;
  915. ret = fat_itr_root(itr, &fsdata);
  916. if (ret)
  917. goto out;
  918. ret = fat_itr_resolve(itr, filename, TYPE_ANY);
  919. free(fsdata.fatbuf);
  920. out:
  921. free(itr);
  922. return ret == 0;
  923. }
  924. int fat_size(const char *filename, loff_t *size)
  925. {
  926. fsdata fsdata;
  927. fat_itr *itr;
  928. int ret;
  929. itr = malloc_cache_aligned(sizeof(fat_itr));
  930. if (!itr)
  931. return -ENOMEM;
  932. ret = fat_itr_root(itr, &fsdata);
  933. if (ret)
  934. goto out_free_itr;
  935. ret = fat_itr_resolve(itr, filename, TYPE_FILE);
  936. if (ret) {
  937. /*
  938. * Directories don't have size, but fs_size() is not
  939. * expected to fail if passed a directory path:
  940. */
  941. free(fsdata.fatbuf);
  942. fat_itr_root(itr, &fsdata);
  943. if (!fat_itr_resolve(itr, filename, TYPE_DIR)) {
  944. *size = 0;
  945. ret = 0;
  946. }
  947. goto out_free_both;
  948. }
  949. *size = FAT2CPU32(itr->dent->size);
  950. out_free_both:
  951. free(fsdata.fatbuf);
  952. out_free_itr:
  953. free(itr);
  954. return ret;
  955. }
  956. int file_fat_read_at(const char *filename, loff_t pos, void *buffer,
  957. loff_t maxsize, loff_t *actread)
  958. {
  959. fsdata fsdata;
  960. fat_itr *itr;
  961. int ret;
  962. itr = malloc_cache_aligned(sizeof(fat_itr));
  963. if (!itr)
  964. return -ENOMEM;
  965. ret = fat_itr_root(itr, &fsdata);
  966. if (ret)
  967. goto out_free_itr;
  968. ret = fat_itr_resolve(itr, filename, TYPE_FILE);
  969. if (ret)
  970. goto out_free_both;
  971. debug("reading %s at pos %llu\n", filename, pos);
  972. ret = get_contents(&fsdata, itr->dent, pos, buffer, maxsize, actread);
  973. out_free_both:
  974. free(fsdata.fatbuf);
  975. out_free_itr:
  976. free(itr);
  977. return ret;
  978. }
  979. int file_fat_read(const char *filename, void *buffer, int maxsize)
  980. {
  981. loff_t actread;
  982. int ret;
  983. ret = file_fat_read_at(filename, 0, buffer, maxsize, &actread);
  984. if (ret)
  985. return ret;
  986. else
  987. return actread;
  988. }
  989. int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len,
  990. loff_t *actread)
  991. {
  992. int ret;
  993. ret = file_fat_read_at(filename, offset, buf, len, actread);
  994. if (ret)
  995. printf("** Unable to read file %s **\n", filename);
  996. return ret;
  997. }
  998. typedef struct {
  999. struct fs_dir_stream parent;
  1000. struct fs_dirent dirent;
  1001. fsdata fsdata;
  1002. fat_itr itr;
  1003. } fat_dir;
  1004. int fat_opendir(const char *filename, struct fs_dir_stream **dirsp)
  1005. {
  1006. fat_dir *dir;
  1007. int ret;
  1008. dir = malloc_cache_aligned(sizeof(*dir));
  1009. if (!dir)
  1010. return -ENOMEM;
  1011. memset(dir, 0, sizeof(*dir));
  1012. ret = fat_itr_root(&dir->itr, &dir->fsdata);
  1013. if (ret)
  1014. goto fail_free_dir;
  1015. ret = fat_itr_resolve(&dir->itr, filename, TYPE_DIR);
  1016. if (ret)
  1017. goto fail_free_both;
  1018. *dirsp = (struct fs_dir_stream *)dir;
  1019. return 0;
  1020. fail_free_both:
  1021. free(dir->fsdata.fatbuf);
  1022. fail_free_dir:
  1023. free(dir);
  1024. return ret;
  1025. }
  1026. int fat_readdir(struct fs_dir_stream *dirs, struct fs_dirent **dentp)
  1027. {
  1028. fat_dir *dir = (fat_dir *)dirs;
  1029. struct fs_dirent *dent = &dir->dirent;
  1030. if (!fat_itr_next(&dir->itr))
  1031. return -ENOENT;
  1032. memset(dent, 0, sizeof(*dent));
  1033. strcpy(dent->name, dir->itr.name);
  1034. if (fat_itr_isdir(&dir->itr)) {
  1035. dent->type = FS_DT_DIR;
  1036. } else {
  1037. dent->type = FS_DT_REG;
  1038. dent->size = FAT2CPU32(dir->itr.dent->size);
  1039. }
  1040. *dentp = dent;
  1041. return 0;
  1042. }
  1043. void fat_closedir(struct fs_dir_stream *dirs)
  1044. {
  1045. fat_dir *dir = (fat_dir *)dirs;
  1046. free(dir->fsdata.fatbuf);
  1047. free(dir);
  1048. }
  1049. void fat_close(void)
  1050. {
  1051. }