PageRenderTime 30ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/usb/usbhdfsd/fat_driver.c

https://bitbucket.org/ifcaro/open-ps2-loader/
C | 1033 lines | 794 code | 123 blank | 116 comment | 227 complexity | bbb5f05d103a53aa58a274a42de4744d MD5 | raw file
Possible License(s): CC-BY-SA-3.0, MPL-2.0-no-copyleft-exception, GPL-2.0
  1. //---------------------------------------------------------------------------
  2. //File name: fat_driver.c
  3. //---------------------------------------------------------------------------
  4. #include <stdio.h>
  5. #include <errno.h>
  6. #ifdef WIN32
  7. #include <malloc.h>
  8. #include <memory.h>
  9. #include <string.h>
  10. #else
  11. #include <sysclib.h>
  12. //#include <sys/stat.h>
  13. #include <thbase.h>
  14. #include <sysmem.h>
  15. #endif
  16. #include <usbhdfsd.h>
  17. #include "usbhd_common.h"
  18. #include "scache.h"
  19. #include "fat_driver.h"
  20. #include "fat.h"
  21. #include "mass_stor.h"
  22. //#define DEBUG //comment out this line when not debugging
  23. #include "mass_debug.h"
  24. #define READ_SECTOR(d, a, b) scache_readSector((d)->cache, (a), (void **)&b)
  25. #define NUM_DRIVES 10
  26. static fat_driver* g_fatd[NUM_DRIVES];
  27. //---------------------------------------------------------------------------
  28. int InitFAT(void)
  29. {
  30. int i;
  31. int ret = 0;
  32. for (i = 0; i < NUM_DRIVES; ++i)
  33. g_fatd[i] = NULL;
  34. return ret;
  35. }
  36. //---------------------------------------------------------------------------
  37. int strEqual(const unsigned char *s1, const unsigned char* s2) {
  38. unsigned char u1, u2;
  39. for (;;) {
  40. u1 = *s1++;
  41. u2 = *s2++;
  42. if (u1 >64 && u1 < 91) u1+=32;
  43. if (u2 >64 && u2 < 91) u2+=32;
  44. if (u1 != u2) {
  45. return -1;
  46. }
  47. if (u1 == '\0') {
  48. return 0;
  49. }
  50. }
  51. }
  52. /*
  53. 0x321, 0xABC
  54. byte| byte| byte|
  55. +--+--+--+--+--+--+
  56. |2 |1 |C |3 |A |B |
  57. +--+--+--+--+--+--+
  58. */
  59. //---------------------------------------------------------------------------
  60. unsigned int fat_getClusterRecord12(unsigned char* buf, int type) {
  61. if (type) { //1
  62. return ((buf[1]<< 4) + (buf[0] >>4));
  63. } else { // 0
  64. return (((buf[1] & 0x0F) << 8) + buf[0]);
  65. }
  66. }
  67. //---------------------------------------------------------------------------
  68. // Get Cluster chain into <buf> buffer
  69. // returns:
  70. // 0 :if buf is full (bufSize entries) and more chain entries exist
  71. // 1-n :number of filled entries of the buf
  72. // -1 :error
  73. //---------------------------------------------------------------------------
  74. //for fat12
  75. /* fat12 cluster records can overlap the edge of the sector so we need to detect and maintain
  76. these cases
  77. */
  78. static int fat_getClusterChain12(fat_driver* fatd, unsigned int cluster, unsigned int* buf, unsigned int bufSize, int startFlag) {
  79. int ret;
  80. unsigned int i, recordOffset, fatSector, lastFatSector;
  81. unsigned char xbuf[4], sectorSpan, cont;
  82. unsigned char* sbuf = NULL; //sector buffer
  83. cont = 1;
  84. lastFatSector = -1;
  85. i = 0;
  86. if (startFlag) {
  87. buf[i] = cluster; //store first cluster
  88. i++;
  89. }
  90. while(i < bufSize && cont) {
  91. recordOffset = (cluster * 3) / 2; //offset of the cluster record (in bytes) from the FAT start
  92. fatSector = recordOffset / fatd->partBpb.sectorSize;
  93. sectorSpan = 0;
  94. if ((recordOffset % fatd->partBpb.sectorSize) == (fatd->partBpb.sectorSize - 1)) {
  95. sectorSpan = 1;
  96. }
  97. if (lastFatSector != fatSector || sectorSpan) {
  98. ret = READ_SECTOR(fatd->dev, fatd->partBpb.partStart + fatd->partBpb.resSectors + fatSector, sbuf);
  99. if (ret < 0) {
  100. XPRINTF("USBHDFSD: Read fat12 sector failed! sector=%u! \n", fatd->partBpb.partStart + fatd->partBpb.resSectors + fatSector );
  101. return -EIO;
  102. }
  103. lastFatSector = fatSector;
  104. if (sectorSpan) {
  105. xbuf[0] = sbuf[fatd->partBpb.sectorSize - 2];
  106. xbuf[1] = sbuf[fatd->partBpb.sectorSize - 1];
  107. ret = READ_SECTOR(fatd->dev, fatd->partBpb.partStart + fatd->partBpb.resSectors + fatSector + 1, sbuf);
  108. if (ret < 0) {
  109. XPRINTF("USBHDFSD: Read fat12 sector failed sector=%u! \n", fatd->partBpb.partStart + fatd->partBpb.resSectors + fatSector + 1);
  110. return -EIO;
  111. }
  112. xbuf[2] = sbuf[0];
  113. xbuf[3] = sbuf[1];
  114. }
  115. }
  116. if (sectorSpan) { // use xbuf as source buffer
  117. cluster = fat_getClusterRecord12(xbuf + (recordOffset % fatd->partBpb.sectorSize) - (fatd->partBpb.sectorSize-2), cluster % 2);
  118. } else { // use sector buffer as source buffer
  119. cluster = fat_getClusterRecord12(sbuf + (recordOffset % fatd->partBpb.sectorSize), cluster % 2);
  120. }
  121. if ((cluster & 0xFFF) >= 0xFF8) {
  122. cont = 0; //continue = false
  123. } else {
  124. buf[i] = cluster & 0xFFF;
  125. i++;
  126. }
  127. }
  128. return i;
  129. }
  130. //---------------------------------------------------------------------------
  131. //for fat16
  132. static int fat_getClusterChain16(fat_driver* fatd, unsigned int cluster, unsigned int* buf, unsigned int bufSize, int startFlag) {
  133. int ret;
  134. unsigned int i, indexCount, fatSector, lastFatSector;
  135. unsigned char cont;
  136. unsigned char* sbuf = NULL; //sector buffer
  137. cont = 1;
  138. indexCount = fatd->partBpb.sectorSize / 2; //FAT16->2, FAT32->4
  139. lastFatSector = -1;
  140. i = 0;
  141. if (startFlag) {
  142. buf[i] = cluster; //store first cluster
  143. i++;
  144. }
  145. while(i < bufSize && cont) {
  146. fatSector = cluster / indexCount;
  147. if (lastFatSector != fatSector) {
  148. ret = READ_SECTOR(fatd->dev, fatd->partBpb.partStart + fatd->partBpb.resSectors + fatSector, sbuf);
  149. if (ret < 0) {
  150. XPRINTF("USBHDFSD: Read fat16 sector failed! sector=%u! \n", fatd->partBpb.partStart + fatd->partBpb.resSectors + fatSector );
  151. return -EIO;
  152. }
  153. lastFatSector = fatSector;
  154. }
  155. cluster = getI16(sbuf + ((cluster % indexCount) * 2));
  156. if ((cluster & 0xFFFF) >= 0xFFF8) {
  157. cont = 0; //continue = false
  158. } else {
  159. buf[i] = cluster & 0xFFFF;
  160. i++;
  161. }
  162. }
  163. return i;
  164. }
  165. //---------------------------------------------------------------------------
  166. //for fat32
  167. static int fat_getClusterChain32(fat_driver* fatd, unsigned int cluster, unsigned int* buf, unsigned int bufSize, int startFlag) {
  168. int ret;
  169. unsigned int i, indexCount, fatSector, lastFatSector;
  170. unsigned char cont;
  171. unsigned char* sbuf = NULL; //sector buffer
  172. cont = 1;
  173. indexCount = fatd->partBpb.sectorSize / 4; //FAT16->2, FAT32->4
  174. lastFatSector = -1;
  175. i = 0;
  176. if (startFlag) {
  177. buf[i] = cluster; //store first cluster
  178. i++;
  179. }
  180. while(i < bufSize && cont) {
  181. fatSector = cluster / indexCount;
  182. if (lastFatSector != fatSector) {
  183. ret = READ_SECTOR(fatd->dev, fatd->partBpb.partStart + fatd->partBpb.resSectors + fatSector, sbuf);
  184. if (ret < 0) {
  185. XPRINTF("USBHDFSD: Read fat32 sector failed sector=%u! \n", fatd->partBpb.partStart + fatd->partBpb.resSectors + fatSector );
  186. return -EIO;
  187. }
  188. lastFatSector = fatSector;
  189. }
  190. cluster = getI32(sbuf + ((cluster % indexCount) * 4));
  191. if ((cluster & 0xFFFFFFF) >= 0xFFFFFF8) {
  192. cont = 0; //continue = false
  193. } else {
  194. buf[i] = cluster & 0xFFFFFFF;
  195. i++;
  196. }
  197. }
  198. return i;
  199. }
  200. //---------------------------------------------------------------------------
  201. int fat_getClusterChain(fat_driver* fatd, unsigned int cluster, unsigned int* buf, unsigned int bufSize, int startFlag) {
  202. if (cluster == fatd->lastChainCluster) {
  203. return fatd->lastChainResult;
  204. }
  205. switch (fatd->partBpb.fatType) {
  206. case FAT12: fatd->lastChainResult = fat_getClusterChain12(fatd, cluster, buf, bufSize, startFlag); break;
  207. case FAT16: fatd->lastChainResult = fat_getClusterChain16(fatd, cluster, buf, bufSize, startFlag); break;
  208. case FAT32: fatd->lastChainResult = fat_getClusterChain32(fatd, cluster, buf, bufSize, startFlag); break;
  209. }
  210. fatd->lastChainCluster = cluster;
  211. return fatd->lastChainResult;
  212. }
  213. //---------------------------------------------------------------------------
  214. void fat_invalidateLastChainResult(fat_driver* fatd)
  215. {
  216. fatd->lastChainCluster = 0;
  217. }
  218. //---------------------------------------------------------------------------
  219. static void fat_determineFatType(fat_bpb* partBpb) {
  220. unsigned int sector, clusterCount;
  221. //get sector of cluster 0
  222. sector = fat_cluster2sector(partBpb, 0);
  223. //remove partition start sector to get BR+FAT+ROOT_DIR sector count
  224. sector -= partBpb->partStart;
  225. sector = partBpb->sectorCount - sector;
  226. clusterCount = sector / partBpb->clusterSize;
  227. //XPRINTF("USBHDFSD: Data cluster count = %u \n", clusterCount);
  228. if (clusterCount < 4085) {
  229. partBpb->fatType = FAT12;
  230. } else
  231. if (clusterCount < 65525) {
  232. partBpb->fatType = FAT16;
  233. } else {
  234. partBpb->fatType = FAT32;
  235. }
  236. }
  237. //---------------------------------------------------------------------------
  238. static int fat_getPartitionBootSector(mass_dev* dev, unsigned int sector, fat_bpb* partBpb) {
  239. fat_raw_bpb* bpb_raw; //fat16, fat12
  240. fat32_raw_bpb* bpb32_raw; //fat32
  241. int ret;
  242. unsigned char* sbuf = NULL; //sector buffer
  243. ret = READ_SECTOR(dev, sector, sbuf); //read partition boot sector (first sector on partition)
  244. if (ret < 0) {
  245. XPRINTF("USBHDFSD: Read partition boot sector failed sector=%u! \n", sector);
  246. return -EIO;
  247. }
  248. bpb_raw = (fat_raw_bpb*) sbuf;
  249. bpb32_raw = (fat32_raw_bpb*) sbuf;
  250. //set fat common properties
  251. partBpb->sectorSize = getI16(bpb_raw->sectorSize);
  252. partBpb->clusterSize = bpb_raw->clusterSize;
  253. partBpb->resSectors = getI16(bpb_raw->resSectors);
  254. partBpb->fatCount = bpb_raw->fatCount;
  255. partBpb->rootSize = getI16(bpb_raw->rootSize);
  256. partBpb->fatSize = getI16(bpb_raw->fatSize);
  257. partBpb->trackSize = getI16(bpb_raw->trackSize);
  258. partBpb->headCount = getI16(bpb_raw->headCount);
  259. partBpb->sectorCount = getI16(bpb_raw->sectorCountO);
  260. if (partBpb->sectorCount == 0) {
  261. partBpb->sectorCount = getI32(bpb_raw->sectorCount); // large partition
  262. }
  263. partBpb->partStart = sector;
  264. partBpb->rootDirStart = partBpb->partStart + (partBpb->fatCount * partBpb->fatSize) + partBpb->resSectors;
  265. for (ret = 0; ret < 8; ret++) {
  266. partBpb->fatId[ret] = bpb_raw->fatId[ret];
  267. }
  268. partBpb->fatId[ret] = 0;
  269. partBpb->rootDirCluster = 0;
  270. partBpb->dataStart = partBpb->rootDirStart + (partBpb->rootSize / (partBpb->sectorSize >> 5));
  271. fat_determineFatType(partBpb);
  272. //fat32 specific info
  273. if (partBpb->fatType == FAT32 && partBpb->fatSize == 0) {
  274. partBpb->fatSize = getI32(bpb32_raw->fatSize32);
  275. partBpb->activeFat = getI16(bpb32_raw->fatStatus);
  276. if (partBpb->activeFat & 0x80) { //fat not synced
  277. partBpb->activeFat = (partBpb->activeFat & 0xF);
  278. } else {
  279. partBpb->activeFat = 0;
  280. }
  281. partBpb->rootDirStart = partBpb->partStart + (partBpb->fatCount * partBpb->fatSize) + partBpb->resSectors;
  282. partBpb->rootDirCluster = getI32(bpb32_raw->rootDirCluster);
  283. for (ret = 0; ret < 8; ret++) {
  284. partBpb->fatId[ret] = bpb32_raw->fatId[ret];
  285. }
  286. partBpb->fatId[ret] = 0;
  287. partBpb->dataStart = partBpb->rootDirStart;
  288. }
  289. printf("USBHDFSD: Fat type %u Id %s \n", partBpb->fatType, partBpb->fatId);
  290. return 1;
  291. }
  292. //---------------------------------------------------------------------------
  293. /*
  294. returns:
  295. 0 - no more dir entries
  296. 1 - short name dir entry found
  297. 2 - long name dir entry found
  298. 3 - deleted dir entry found
  299. */
  300. int fat_getDirentry(unsigned char fatType, fat_direntry* dir_entry, fat_direntry_summary* dir ) {
  301. int i, j;
  302. unsigned int offset;
  303. unsigned char cont;
  304. u16 character;
  305. //detect last entry - all zeros (slight modification by radad)
  306. if (dir_entry->sfn.name[0] == 0) {
  307. return 0;
  308. }
  309. //detect deleted entry - it will be ignored
  310. if (dir_entry->sfn.name[0] == 0xE5) {
  311. return 3;
  312. }
  313. //detect long filename
  314. if (dir_entry->lfn.rshv == 0x0F && dir_entry->lfn.reserved1 == 0x00 && dir_entry->lfn.reserved2[0] == 0x00) {
  315. //long filename - almost whole direntry is unicode string - extract it
  316. offset = dir_entry->lfn.entrySeq & 0x3f;
  317. offset--;
  318. offset = offset * 13;
  319. //name - 1st part
  320. cont = 1;
  321. for (i = 0; i < 10 && cont; i+=2) {
  322. character = dir_entry->lfn.name1[i] | (dir_entry->lfn.name1[i+1] << 8);
  323. if (character == 0 || offset >= FAT_MAX_NAME) {
  324. dir->name[offset] = 0; //terminate
  325. cont = 0; //stop
  326. } else {
  327. // Handle non-ASCII characters
  328. dir->name[offset] = character < 128 ? dir_entry->lfn.name1[i] : '?';
  329. offset++;
  330. }
  331. }
  332. //name - 2nd part
  333. for (i = 0; i < 12 && cont; i+=2) {
  334. character = dir_entry->lfn.name2[i] | (dir_entry->lfn.name2[i+1] << 8);
  335. if (character == 0 || offset >= FAT_MAX_NAME) {
  336. dir->name[offset] = 0; //terminate
  337. cont = 0; //stop
  338. } else {
  339. // Handle non-ASCII characters
  340. dir->name[offset] = character < 128 ? dir_entry->lfn.name2[i] : '?';
  341. offset++;
  342. }
  343. }
  344. //name - 3rd part
  345. for (i = 0; i < 4 && cont; i+=2) {
  346. character = dir_entry->lfn.name3[i] | (dir_entry->lfn.name3[i+1] << 8);
  347. if (character == 0 || offset >= FAT_MAX_NAME) {
  348. dir->name[offset] = 0; //terminate
  349. cont = 0; //stop
  350. } else {
  351. // Handle non-ASCII characters
  352. dir->name[offset] = character < 128 ? dir_entry->lfn.name3[i] : '?';
  353. offset++;
  354. }
  355. }
  356. if ((dir_entry->lfn.entrySeq & 0x40)) { //terminate string flag
  357. dir->name[offset] = 0;
  358. }
  359. return 2;
  360. } else {
  361. //short filename
  362. //copy name
  363. for (i = 0; i < 8 && dir_entry->sfn.name[i]!= ' '; i++) {
  364. dir->sname[i] = dir_entry->sfn.name[i];
  365. // NT—adaption for LaunchELF
  366. if (dir_entry->sfn.reservedNT & 0x08 &&
  367. dir->sname[i] >= 'A' && dir->sname[i] <= 'Z') {
  368. dir->sname[i] += 0x20; //Force standard letters in name to lower case
  369. }
  370. }
  371. for (j=0; j < 3 && dir_entry->sfn.ext[j] != ' '; j++) {
  372. if (j == 0) {
  373. dir->sname[i] = '.';
  374. i++;
  375. }
  376. dir->sname[i+j] = dir_entry->sfn.ext[j];
  377. // NT—adaption for LaunchELF
  378. if (dir_entry->sfn.reservedNT & 0x10 &&
  379. dir->sname[i+j] >= 'A' && dir->sname[i+j] <= 'Z') {
  380. dir->sname[i+j] += 0x20; //Force standard letters in ext to lower case
  381. }
  382. }
  383. dir->sname[i+j] = 0; //terminate
  384. if (dir->name[0] == 0) { //long name desn't exit
  385. for (i =0 ; dir->sname[i] !=0; i++) dir->name[i] = dir->sname[i];
  386. dir->name[i] = 0;
  387. }
  388. dir->attr = dir_entry->sfn.attr;
  389. dir->size = getI32(dir_entry->sfn.size);
  390. dir->cluster = (fatType == FAT32) ? getI32_2(dir_entry->sfn.clusterL, dir_entry->sfn.clusterH) : getI16(dir_entry->sfn.clusterL);
  391. return 1;
  392. }
  393. }
  394. //---------------------------------------------------------------------------
  395. //Set chain info (cluster/offset) cache
  396. void fat_setFatDirChain(fat_driver* fatd, fat_dir* fatDir) {
  397. int i,j;
  398. unsigned int index, clusterChainStart, fileCluster, fileSize, blockSize;
  399. unsigned char nextChain;
  400. int chainSize;
  401. XPRINTF("USBHDFSD: reading cluster chain \n");
  402. fileCluster = fatDir->chain[0].cluster;
  403. if (fileCluster < 2) {
  404. XPRINTF("USBHDFSD: early exit... \n");
  405. return;
  406. }
  407. fileSize = fatDir->size;
  408. blockSize = fileSize / DIR_CHAIN_SIZE;
  409. nextChain = 1;
  410. clusterChainStart = 0;
  411. j = 1;
  412. fileSize = 0;
  413. index = 0;
  414. while (nextChain) {
  415. if((chainSize = fat_getClusterChain(fatd, fileCluster, fatd->cbuf, MAX_DIR_CLUSTER, 1)) >=0){
  416. if (chainSize >= MAX_DIR_CLUSTER) { //the chain is full, but more chain parts exist
  417. fileCluster = fatd->cbuf[MAX_DIR_CLUSTER - 1];
  418. }else { //chain fits in the chain buffer completely - no next chain exist
  419. nextChain = 0;
  420. }
  421. }else{
  422. XPRINTF("USBHDFSD: fat_setFatDirChain(): fat_getClusterChain() failed: %d\n", chainSize);
  423. return;
  424. }
  425. //process the cluster chain (fatd->cbuf)
  426. for (i = clusterChainStart; i < chainSize; i++) {
  427. fileSize += (fatd->partBpb.clusterSize * fatd->partBpb.sectorSize);
  428. while (fileSize >= (j * blockSize) && j < DIR_CHAIN_SIZE) {
  429. fatDir->chain[j].cluster = fatd->cbuf[i];
  430. fatDir->chain[j].index = index;
  431. j++;
  432. }//ends "while"
  433. index++;
  434. }//ends "for"
  435. clusterChainStart = 1;
  436. }//ends "while"
  437. fatDir->lastCluster = fatd->cbuf[i-1];
  438. #ifdef DEBUG_EXTREME //dlanor: I patched this because this bloat hid important stuff
  439. //debug
  440. XPRINTF("USBHDFSD: SEEK CLUSTER CHAIN CACHE fileSize=%u blockSize=%u \n", fatDir->size, blockSize);
  441. for (i = 0; i < DIR_CHAIN_SIZE; i++) {
  442. XPRINTF("USBHDFSD: index=%u cluster=%u offset= %u - %u start=%u \n",
  443. fatDir->chain[i].index, fatDir->chain[i].cluster,
  444. fatDir->chain[i].index * fatd->partBpb.clusterSize * fatd->partBpb.sectorSize,
  445. (fatDir->chain[i].index+1) * fatd->partBpb.clusterSize * fatd->partBpb.sectorSize,
  446. i * blockSize);
  447. }
  448. #endif /* debug */
  449. XPRINTF("USBHDFSD: read cluster chain done!\n");
  450. }
  451. //---------------------------------------------------------------------------
  452. /* Set base attributes of direntry */
  453. static void fat_setFatDir(fat_driver* fatd, fat_dir* fatDir, unsigned int parentDirCluster, fat_direntry_sfn* dsfn, fat_direntry_summary* dir, int getClusterInfo ) {
  454. unsigned int i;
  455. unsigned char* srcName;
  456. XPRINTF("USBHDFSD: setting fat dir...\n");
  457. srcName = dir->sname;
  458. if (dir->name[0] != 0) { //long filename not empty
  459. srcName = dir->name;
  460. }
  461. //copy name
  462. for (i = 0; srcName[i] != 0; i++) fatDir->name[i] = srcName[i];
  463. fatDir->name[i] = 0; //terminate
  464. fatDir->attr = dir->attr;
  465. fatDir->size = dir->size;
  466. //created Date: Day, Month, Year-low, Year-high
  467. fatDir->cdate[0] = (dsfn->dateCreate[0] & 0x1F);
  468. fatDir->cdate[1] = (dsfn->dateCreate[0] >> 5) + ((dsfn->dateCreate[1] & 0x01) << 3 );
  469. i = 1980 + (dsfn->dateCreate[1] >> 1);
  470. fatDir->cdate[2] = (i & 0xFF);
  471. fatDir->cdate[3] = ((i & 0xFF00)>> 8);
  472. //created Time: Hours, Minutes, Seconds
  473. fatDir->ctime[0] = ((dsfn->timeCreate[1] & 0xF8) >> 3);
  474. fatDir->ctime[1] = ((dsfn->timeCreate[1] & 0x07) << 3) + ((dsfn->timeCreate[0] & 0xE0) >> 5);
  475. fatDir->ctime[6] = ((dsfn->timeCreate[0] & 0x1F) << 1);
  476. //accessed Date: Day, Month, Year-low, Year-high
  477. fatDir->adate[0] = (dsfn->dateAccess[0] & 0x1F);
  478. fatDir->adate[1] = (dsfn->dateAccess[0] >> 5) + ((dsfn->dateAccess[1] & 0x01) << 3 );
  479. i = 1980 + (dsfn->dateAccess[1] >> 1);
  480. fatDir->adate[2] = (i & 0xFF);
  481. fatDir->adate[3] = ((i & 0xFF00)>> 8);
  482. //modified Date: Day, Month, Year-low, Year-high
  483. fatDir->mdate[0] = (dsfn->dateWrite[0] & 0x1F);
  484. fatDir->mdate[1] = (dsfn->dateWrite[0] >> 5) + ((dsfn->dateWrite[1] & 0x01) << 3 );
  485. i = 1980 + (dsfn->dateWrite[1] >> 1);
  486. fatDir->mdate[2] = (i & 0xFF);
  487. fatDir->mdate[3] = ((i & 0xFF00)>> 8);
  488. //modified Time: Hours, Minutes, Seconds
  489. fatDir->mtime[0] = ((dsfn->timeWrite[1] & 0xF8) >> 3);
  490. fatDir->mtime[1] = ((dsfn->timeWrite[1] & 0x07) << 3) + ((dsfn->timeWrite[0] & 0xE0) >> 5);
  491. fatDir->mtime[2] = ((dsfn->timeWrite[0] & 0x1F) << 1);
  492. fatDir->chain[0].cluster = dir->cluster;
  493. fatDir->chain[0].index = 0;
  494. if (getClusterInfo) {
  495. fat_setFatDirChain(fatd, fatDir);
  496. }
  497. fatDir->parentDirCluster = parentDirCluster;
  498. fatDir->startCluster = dir->cluster;
  499. }
  500. //---------------------------------------------------------------------------
  501. int fat_getDirentrySectorData(fat_driver* fatd, unsigned int* startCluster, unsigned int* startSector, unsigned int* dirSector) {
  502. unsigned int chainSize;
  503. if (*startCluster == 0 && fatd->partBpb.fatType < FAT32) { //Root directory
  504. *startSector = fatd->partBpb.rootDirStart;
  505. *dirSector = fatd->partBpb.rootSize / (fatd->partBpb.sectorSize / 32);
  506. return 0;
  507. }
  508. //other directory or fat 32
  509. if (*startCluster == 0 && fatd->partBpb.fatType == FAT32) {
  510. *startCluster = fatd->partBpb.rootDirCluster;
  511. }
  512. *startSector = fat_cluster2sector(&fatd->partBpb, *startCluster);
  513. chainSize = fat_getClusterChain(fatd, *startCluster, fatd->cbuf, MAX_DIR_CLUSTER, 1);
  514. if (chainSize >= MAX_DIR_CLUSTER) {
  515. XPRINTF("USBHDFSD: Chain too large\n");
  516. return -EFAULT;
  517. } else if (chainSize > 0) {
  518. *dirSector = chainSize * fatd->partBpb.clusterSize;
  519. } else {
  520. XPRINTF("USBHDFSD: Error getting cluster chain! startCluster=%u \n", *startCluster);
  521. return -EFAULT;
  522. }
  523. return chainSize;
  524. }
  525. //---------------------------------------------------------------------------
  526. static int fat_getDirentryStartCluster(fat_driver* fatd, unsigned char* dirName, unsigned int* startCluster, fat_dir* fatDir) {
  527. fat_direntry_summary dir;
  528. unsigned int i, dirSector, startSector, dirPos;
  529. unsigned char cont;
  530. int ret;
  531. #ifdef DEBUG
  532. mass_dev* mass_device = fatd->dev;
  533. #endif
  534. cont = 1;
  535. XPRINTF("USBHDFSD: getting cluster for dir entry: %s \n", dirName);
  536. //clear name strings
  537. dir.sname[0] = 0;
  538. dir.name[0] = 0;
  539. ret = fat_getDirentrySectorData(fatd, startCluster, &startSector, &dirSector);
  540. if (ret < 0)
  541. return ret;
  542. XPRINTF("USBHDFSD: dirCluster=%u startSector=%u (%u) dirSector=%u \n", *startCluster, startSector, startSector * mass_device->sectorSize, dirSector);
  543. //go through first directory sector till the max number of directory sectors
  544. //or stop when no more direntries detected
  545. for (i = 0; i < dirSector && cont; i++) {
  546. unsigned char* sbuf = NULL; //sector buffer
  547. //At cluster borders, get correct sector from cluster chain buffer
  548. if ((*startCluster != 0) && (i % fatd->partBpb.clusterSize == 0)) {
  549. startSector = fat_cluster2sector(&fatd->partBpb, fatd->cbuf[(i / fatd->partBpb.clusterSize)]) -i;
  550. }
  551. ret = READ_SECTOR(fatd->dev, startSector + i, sbuf);
  552. if (ret < 0) {
  553. XPRINTF("USBHDFSD: read directory sector failed ! sector=%u\n", startSector + i);
  554. return -EIO;
  555. }
  556. XPRINTF("USBHDFSD: read sector ok, scanning sector for direntries...\n");
  557. dirPos = 0;
  558. // go through start of the sector till the end of sector
  559. while (cont && dirPos < fatd->partBpb.sectorSize) {
  560. fat_direntry* dir_entry = (fat_direntry*) (sbuf + dirPos);
  561. cont = fat_getDirentry(fatd->partBpb.fatType, dir_entry, &dir); //get single directory entry from sector buffer
  562. if (cont == 1) { //when short file name entry detected
  563. if (!(dir.attr & FAT_ATTR_VOLUME_LABEL)) { //not volume label
  564. if ((strEqual(dir.sname, dirName) == 0) ||
  565. (strEqual(dir.name, dirName) == 0) ) {
  566. XPRINTF("USBHDFSD: found! %s\n", dir.name);
  567. if (fatDir != NULL) { //fill the directory properties
  568. fat_setFatDir(fatd, fatDir, *startCluster, &dir_entry->sfn, &dir, 1);
  569. }
  570. *startCluster = dir.cluster;
  571. XPRINTF("USBHDFSD: direntry %s found at cluster: %u \n", dirName, dir.cluster);
  572. return dir.attr; //returns file or directory attr
  573. }
  574. }//ends "if(!(dir.attr & FAT_ATTR_VOLUME_LABEL))"
  575. //clear name strings
  576. dir.sname[0] = 0;
  577. dir.name[0] = 0;
  578. }//ends "if (cont == 1)"
  579. dirPos += sizeof(fat_direntry);
  580. }//ends "while"
  581. }//ends "for"
  582. XPRINTF("USBHDFSD: direntry %s not found! \n", dirName);
  583. return -ENOENT;
  584. }
  585. //---------------------------------------------------------------------------
  586. // start cluster should be 0 - if we want to search from root directory
  587. // otherwise the start cluster should be correct cluster of directory
  588. // to search directory - set fatDir as NULL
  589. int fat_getFileStartCluster(fat_driver* fatd, const unsigned char* fname, unsigned int* startCluster, fat_dir* fatDir) {
  590. unsigned char tmpName[FAT_MAX_NAME+1];
  591. unsigned int i, offset;
  592. unsigned char cont;
  593. int ret;
  594. XPRINTF("USBHDFSD: Entering fat_getFileStartCluster\n");
  595. cont = 1;
  596. offset = 0;
  597. i=0;
  598. *startCluster = 0;
  599. if (fatDir != NULL) {
  600. memset(fatDir, 0, sizeof(fat_dir));
  601. fatDir->attr = FAT_ATTR_DIRECTORY;
  602. }
  603. if (fname[i] == '/') {
  604. i++;
  605. }
  606. for ( ; fname[i] !=0; i++) {
  607. if (fname[i] == '/') { //directory separator
  608. tmpName[offset] = 0; //terminate string
  609. ret = fat_getDirentryStartCluster(fatd, tmpName, startCluster, fatDir);
  610. if (ret < 0) {
  611. return -ENOENT;
  612. }
  613. offset = 0;
  614. } else{
  615. tmpName[offset] = fname[i];
  616. offset++;
  617. }
  618. }//ends "for"
  619. //and the final file
  620. tmpName[offset] = 0; //terminate string
  621. XPRINTF("USBHDFSD: Ready to get cluster for file \"%s\"\n", tmpName);
  622. if (fatDir != NULL) {
  623. //if the last char of the name was slash - the name was already found -exit
  624. if (offset == 0) {
  625. XPRINTF("USBHDFSD: Exiting from fat_getFileStartCluster with a folder\n");
  626. return 2;
  627. }
  628. ret = fat_getDirentryStartCluster(fatd, tmpName, startCluster, fatDir);
  629. if (ret < 0) {
  630. XPRINTF("USBHDFSD: Exiting from fat_getFileStartCluster with error %i\n", ret);
  631. return ret;
  632. }
  633. XPRINTF("USBHDFSD: file's startCluster found. Name=%s, cluster=%u \n", fname, *startCluster);
  634. }
  635. XPRINTF("USBHDFSD: Exiting from fat_getFileStartCluster with no error.\n");
  636. return 1;
  637. }
  638. //---------------------------------------------------------------------------
  639. void fat_getClusterAtFilePos(fat_driver* fatd, fat_dir* fatDir, unsigned int filePos, unsigned int* cluster, unsigned int* clusterPos) {
  640. unsigned int i, j, blockSize;
  641. blockSize = fatd->partBpb.clusterSize * fatd->partBpb.sectorSize;
  642. for (i = 0, j = (DIR_CHAIN_SIZE-1); i < (DIR_CHAIN_SIZE-1); i++) {
  643. if (fatDir->chain[i].index * blockSize <= filePos &&
  644. fatDir->chain[i+1].index * blockSize > filePos) {
  645. j = i;
  646. break;
  647. }
  648. }
  649. *cluster = fatDir->chain[j].cluster;
  650. *clusterPos = (fatDir->chain[j].index * blockSize);
  651. }
  652. //---------------------------------------------------------------------------
  653. int fat_readFile(fat_driver* fatd, fat_dir* fatDir, unsigned int filePos, unsigned char* buffer, unsigned int size) {
  654. int ret, chainSize;
  655. unsigned int i, j, startSector, clusterChainStart, bufSize, sectorSkip, clusterSkip, dataSkip;
  656. unsigned char nextChain;
  657. mass_dev* mass_device = fatd->dev;
  658. unsigned int bufferPos, fileCluster, clusterPos;
  659. fat_getClusterAtFilePos(fatd, fatDir, filePos, &fileCluster, &clusterPos);
  660. sectorSkip = (filePos - clusterPos) / fatd->partBpb.sectorSize;
  661. clusterSkip = sectorSkip / fatd->partBpb.clusterSize;
  662. sectorSkip %= fatd->partBpb.clusterSize;
  663. dataSkip = filePos % fatd->partBpb.sectorSize;
  664. bufferPos = 0;
  665. XPRINTF("USBHDFSD: fileCluster = %u, clusterPos= %u clusterSkip=%u, sectorSkip=%u dataSkip=%u \n",
  666. fileCluster, clusterPos, clusterSkip, sectorSkip, dataSkip);
  667. if (fileCluster < 2) {
  668. return 0;
  669. }
  670. bufSize = mass_device->sectorSize;
  671. nextChain = 1;
  672. clusterChainStart = 1;
  673. while (nextChain && size > 0 ) {
  674. if((chainSize = fat_getClusterChain(fatd, fileCluster, fatd->cbuf, MAX_DIR_CLUSTER, clusterChainStart))<0){
  675. return chainSize;
  676. }
  677. clusterChainStart = 0;
  678. if (chainSize >= MAX_DIR_CLUSTER) { //the chain is full, but more chain parts exist
  679. fileCluster = fatd->cbuf[MAX_DIR_CLUSTER - 1];
  680. }else { //chain fits in the chain buffer completely - no next chain needed
  681. nextChain = 0;
  682. }
  683. while (clusterSkip >= MAX_DIR_CLUSTER) {
  684. chainSize = fat_getClusterChain(fatd, fileCluster, fatd->cbuf, MAX_DIR_CLUSTER, clusterChainStart);
  685. clusterChainStart = 0;
  686. if (chainSize >= MAX_DIR_CLUSTER) { //the chain is full, but more chain parts exist
  687. fileCluster = fatd->cbuf[MAX_DIR_CLUSTER - 1];
  688. }else { //chain fits in the chain buffer completely - no next chain needed
  689. nextChain = 0;
  690. }
  691. clusterSkip -= MAX_DIR_CLUSTER;
  692. }
  693. //process the cluster chain (fatd->cbuf) and skip leading clusters if needed
  694. for (i = 0 + clusterSkip; i < chainSize && size > 0; i++) {
  695. //read cluster and save cluster content
  696. startSector = fat_cluster2sector(&fatd->partBpb, fatd->cbuf[i]);
  697. //process all sectors of the cluster (and skip leading sectors if needed)
  698. for (j = 0 + sectorSkip; j < fatd->partBpb.clusterSize && size > 0; j++) {
  699. unsigned char* sbuf = NULL; //sector buffer
  700. ret = READ_SECTOR(fatd->dev, startSector + j, sbuf);
  701. if (ret < 0) {
  702. XPRINTF("USBHDFSD: Read sector failed ! sector=%u\n", startSector + j);
  703. return bufferPos;
  704. }
  705. //compute exact size of transfered bytes
  706. if (size < bufSize) {
  707. bufSize = size + dataSkip;
  708. }
  709. if (bufSize > mass_device->sectorSize) {
  710. bufSize = mass_device->sectorSize;
  711. }
  712. XPRINTF("USBHDFSD: memcopy dst=%u, src=%u, size=%u bufSize=%u \n", bufferPos, dataSkip, bufSize-dataSkip, bufSize);
  713. memcpy(buffer+bufferPos, sbuf + dataSkip, bufSize - dataSkip);
  714. size-= (bufSize - dataSkip);
  715. bufferPos += (bufSize - dataSkip);
  716. dataSkip = 0;
  717. bufSize = mass_device->sectorSize;
  718. }
  719. sectorSkip = 0;
  720. }
  721. clusterSkip = 0;
  722. }
  723. return bufferPos;
  724. }
  725. //---------------------------------------------------------------------------
  726. int fat_getNextDirentry(fat_driver* fatd, fat_dir_list* fatdlist, fat_dir* fatDir) {
  727. fat_direntry_summary dir;
  728. int i, ret;
  729. unsigned int startSector, dirSector, dirPos, dirCluster;
  730. unsigned char cont, new_entry;
  731. #ifdef DEBUG
  732. mass_dev* mass_device = fatd->dev;
  733. #endif
  734. //the getFirst function was not called
  735. if (fatdlist->direntryCluster == 0xFFFFFFFF || fatDir == NULL) {
  736. return -EFAULT;
  737. }
  738. dirCluster = fatdlist->direntryCluster;
  739. //clear name strings
  740. dir.sname[0] = 0;
  741. dir.name[0] = 0;
  742. ret = fat_getDirentrySectorData(fatd, &dirCluster, &startSector, &dirSector);
  743. if (ret < 0)
  744. return ret;
  745. XPRINTF("USBHDFSD: dirCluster=%u startSector=%u (%u) dirSector=%u \n", dirCluster, startSector, startSector * mass_device->sectorSize, dirSector);
  746. //go through first directory sector till the max number of directory sectors
  747. //or stop when no more direntries detected
  748. //dlanor: but avoid rescanning same areas redundantly (if possible)
  749. cont = 1;
  750. new_entry = 1;
  751. dirPos = (fatdlist->direntryIndex*32) % fatd->partBpb.sectorSize;
  752. for (i = ((fatdlist->direntryIndex*32) / fatd->partBpb.sectorSize); (i < dirSector) && cont; i++) {
  753. unsigned char* sbuf = NULL; //sector buffer
  754. //At cluster borders, get correct sector from cluster chain buffer
  755. if ((dirCluster != 0) && (new_entry || (i % fatd->partBpb.clusterSize == 0))) {
  756. startSector = fat_cluster2sector(&fatd->partBpb, fatd->cbuf[(i / fatd->partBpb.clusterSize)])
  757. -i + (i % fatd->partBpb.clusterSize);
  758. new_entry = 0;
  759. }
  760. ret = READ_SECTOR(fatd->dev, startSector + i, sbuf);
  761. if (ret < 0) {
  762. XPRINTF("USBHDFSD: Read directory sector failed ! sector=%u\n", startSector + i);
  763. return -EIO;
  764. }
  765. // go through sector from current pos till its end
  766. while (cont && (dirPos < fatd->partBpb.sectorSize)) {
  767. fat_direntry* dir_entry = (fat_direntry*) (sbuf + dirPos);
  768. cont = fat_getDirentry(fatd->partBpb.fatType, dir_entry, &dir); //get a directory entry from sector
  769. fatdlist->direntryIndex++; //Note current entry processed
  770. if (cont == 1) { //when short file name entry detected
  771. fat_setFatDir(fatd, fatDir, dirCluster, &dir_entry->sfn, &dir, 0);
  772. #if 0
  773. XPRINTF("USBHDFSD: fat_getNextDirentry %c%c%c%c%c%c %x %s %s\n",
  774. (dir.attr & FAT_ATTR_VOLUME_LABEL) ? 'v' : '-',
  775. (dir.attr & FAT_ATTR_DIRECTORY) ? 'd' : '-',
  776. (dir.attr & FAT_ATTR_READONLY) ? 'r' : '-',
  777. (dir.attr & FAT_ATTR_ARCHIVE) ? 'a' : '-',
  778. (dir.attr & FAT_ATTR_SYSTEM) ? 's' : '-',
  779. (dir.attr & FAT_ATTR_HIDDEN) ? 'h' : '-',
  780. dir.attr,
  781. dir.sname,
  782. dir.name);
  783. #endif
  784. return 1;
  785. }
  786. dirPos += sizeof(fat_direntry);
  787. }//ends "while"
  788. dirPos = 0;
  789. }//ends "for"
  790. // when we get this far - reset the direntry cluster
  791. fatdlist->direntryCluster = 0xFFFFFFFF; //no more files
  792. return 0; //indicate that no direntry is avalable
  793. }
  794. //---------------------------------------------------------------------------
  795. int fat_getFirstDirentry(fat_driver* fatd, const unsigned char* dirName, fat_dir_list* fatdlist, fat_dir *fatDir_host, fat_dir* fatDir) {
  796. int ret;
  797. unsigned int startCluster = 0;
  798. ret = fat_getFileStartCluster(fatd, dirName, &startCluster, fatDir_host);
  799. if (ret < 0) { //dir name not found
  800. return -ENOENT;
  801. }
  802. //check that direntry is directory
  803. if (!(fatDir_host->attr & FAT_ATTR_DIRECTORY)) {
  804. return -ENOTDIR; //it's a file - exit
  805. }
  806. fatdlist->direntryCluster = startCluster;
  807. fatdlist->direntryIndex = 0;
  808. return fat_getNextDirentry(fatd, fatdlist, fatDir);
  809. }
  810. //---------------------------------------------------------------------------
  811. int fat_CheckChain(fat_driver* fatd, fat_dir* fatDir){
  812. int i;
  813. int chainSize;
  814. int nextChain;
  815. unsigned int fileCluster;
  816. unsigned int clusterPos;
  817. int clusterChainStart;
  818. fat_getClusterAtFilePos(fatd, fatDir, 0, &fileCluster, &clusterPos);
  819. if (fileCluster < 2) return 1;
  820. nextChain = 1;
  821. clusterChainStart = 1;
  822. while (nextChain) {
  823. chainSize = fat_getClusterChain(fatd, fileCluster, fatd->cbuf, MAX_DIR_CLUSTER, clusterChainStart);
  824. clusterChainStart = 0;
  825. if (chainSize >= MAX_DIR_CLUSTER) { //the chain is full, but more chain parts exist
  826. fileCluster = fatd->cbuf[MAX_DIR_CLUSTER - 1];
  827. }else { //chain fits in the chain buffer completely - no next chain needed
  828. nextChain = 0;
  829. }
  830. //process the cluster chain (fatd->cbuf) and skip leading clusters if needed
  831. for (i = 0; i < (chainSize-1); i++) {
  832. if((fatd->cbuf[i]+1)!=fatd->cbuf[i+1]) return 0;
  833. }
  834. }
  835. return 1;
  836. }
  837. //---------------------------------------------------------------------------
  838. int fat_mount(mass_dev* dev, unsigned int start, unsigned int count)
  839. {
  840. fat_driver* fatd = NULL;
  841. unsigned int i;
  842. for (i = 0; i < NUM_DRIVES && fatd == NULL; ++i)
  843. {
  844. if (g_fatd[i] == NULL)
  845. {
  846. XPRINTF("USBHDFSD: usb fat: allocate fat_driver %d!\n", sizeof(fat_driver));
  847. g_fatd[i] = malloc(sizeof(fat_driver));
  848. if (g_fatd[i] != NULL)
  849. {
  850. g_fatd[i]->dev = NULL;
  851. }
  852. fatd = g_fatd[i];
  853. }
  854. else if(g_fatd[i]->dev == NULL)
  855. {
  856. fatd = g_fatd[i];
  857. }
  858. }
  859. if (fatd == NULL)
  860. {
  861. printf("USBHDFSD: usb fat: unable to allocate drive!\n");
  862. return -1;
  863. }
  864. if (fatd->dev != NULL)
  865. {
  866. printf("USBHDFSD: usb fat: mount ERROR: alread mounted\n");
  867. fat_forceUnmount(fatd->dev);
  868. }
  869. if (fat_getPartitionBootSector(dev, start, &fatd->partBpb) < 0)
  870. return -1;
  871. fatd->dev = dev;
  872. fatd->deIdx = 0;
  873. fatd->clStackIndex = 0;
  874. fatd->clStackLast = 0;
  875. fatd->lastChainCluster = 0xFFFFFFFF;
  876. fatd->lastChainResult = -1;
  877. return 0;
  878. }
  879. //---------------------------------------------------------------------------
  880. void fat_forceUnmount(mass_dev* dev)
  881. {
  882. unsigned int i;
  883. XPRINTF("USBHDFSD: usb fat: forceUnmount devId %i \n", dev->devId);
  884. for (i = 0; i < NUM_DRIVES; ++i)
  885. {
  886. if (g_fatd[i] != NULL && g_fatd[i]->dev == dev)
  887. g_fatd[i] = NULL;
  888. }
  889. }
  890. //---------------------------------------------------------------------------
  891. fat_driver * fat_getData(int device)
  892. {
  893. if (device >= NUM_DRIVES)
  894. return NULL;
  895. while (g_fatd[device] == NULL || g_fatd[device]->dev == NULL)
  896. {
  897. if (mass_stor_configureNextDevice() <= 0)
  898. break;
  899. }
  900. if (g_fatd[device] == NULL || g_fatd[device]->dev == NULL)
  901. return NULL;
  902. else
  903. return g_fatd[device];
  904. }
  905. //---------------------------------------------------------------------------
  906. //End of file: fat_driver.c
  907. //---------------------------------------------------------------------------