Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1520 lines
50 KiB

  1. /*******************************************************************************
  2. * *
  3. * M-Systems Confidential *
  4. * Copyright (C) M-Systems Flash Disk Pioneers Ltd. 1995-2001 *
  5. * All Rights Reserved *
  6. * *
  7. *******************************************************************************
  8. * *
  9. * NOTICE OF M-SYSTEMS OEM *
  10. * SOFTWARE LICENSE AGREEMENT *
  11. * *
  12. * THE USE OF THIS SOFTWARE IS GOVERNED BY A SEPARATE LICENSE AGREEMENT *
  13. * BETWEEN THE OEM AND M-SYSTEMS. REFER TO THAT AGREEMENT FOR THE SPECIFIC *
  14. * TERMS AND CONDITIONS OF USE, OR CONTACT M-SYSTEMS FOR LICENSE *
  15. * ASSISTANCE: *
  16. * E-MAIL = info@m-sys.com *
  17. * *
  18. *******************************************************************************
  19. * *
  20. * *
  21. * Module: FATFILT *
  22. * *
  23. * This module implements installable FAT12/16 filters. It supports up to *
  24. * SOCKETS sockets, with up to MAX_TL_PARTITIONS disks per socket. *
  25. * Each disk can contain up to FL_MAX_PARTS_PER_DISK partitions on it, with *
  26. * maximum depth of partition nesting in extended partitions equal to *
  27. * MAX_PARTITION_DEPTH. *
  28. * *
  29. * In order for this module to work, disks must be abs.mounted rather then *
  30. * mounted. In latter case, this module won't detect any of disk's *
  31. * partitions, and won't install FAT filters. *
  32. * *
  33. * This module uses more then 512 bytes of stack space in case if MALLOC is *
  34. * not enabled. *
  35. * *
  36. *******************************************************************************/
  37. /*
  38. * $Log: V:/Flite/archives/TrueFFS5/Src/FATFILT.C_V $
  39. *
  40. * Rev 1.10 Jan 17 2002 23:00:14 oris
  41. * Changed debug print added \r.
  42. *
  43. * Rev 1.9 Sep 15 2001 23:45:50 oris
  44. * Changed BIG_ENDIAN to FL_BIG_ENDIAN
  45. *
  46. * Rev 1.8 Jun 17 2001 16:39:10 oris
  47. * Improved documentation and remove warnings.
  48. *
  49. * Rev 1.7 May 16 2001 21:17:18 oris
  50. * Added the FL_ prefix to the following defines: MALLOC and FREE.
  51. *
  52. * Rev 1.6 May 01 2001 14:21:02 oris
  53. * Remove warnings.
  54. *
  55. * Rev 1.5 Apr 30 2001 18:00:10 oris
  56. * Added casting to remove warrnings.
  57. *
  58. * Rev 1.4 Apr 24 2001 17:07:32 oris
  59. * Missing casting of MALLOC calls.
  60. *
  61. * Rev 1.3 Apr 10 2001 23:54:24 oris
  62. * FL_MAX_DISKS_PER_SOCKET changed to MAX_TL_PARTITIONS.
  63. *
  64. * Rev 1.2 Apr 09 2001 15:00:42 oris
  65. * Change static allocation to dynamic allocations.
  66. * Renamed flffCheck back to ffCheckBeforeWrite to be backwards compatible with OSAK 4.2.
  67. *
  68. * Rev 1.1 Apr 01 2001 07:51:16 oris
  69. * New implementation of fat filter.
  70. *
  71. * Rev 1.0 19 Feb 2001 21:14:14 andreyk
  72. * Initial revision.
  73. */
  74. /*
  75. * Includes
  76. */
  77. #include "fatfilt.h"
  78. #include "blockdev.h"
  79. #include "flflash.h"
  80. #include "bddefs.h"
  81. #if defined(ABS_READ_WRITE) && !defined(FL_READ_ONLY)
  82. /*
  83. * Module configuration
  84. */
  85. #define FL_INCLUDE_FAT_MONITOR /* undefine it to remove FAT filter code */
  86. /*
  87. * Defines
  88. */
  89. /* extract pointer to user's buffer from IOreq */
  90. #ifdef SCATTER_GATHER
  91. #define FLBUF(ioreq,i) (*((char FAR1 **)((ioreq)->irData) + (int)(i)))
  92. #else
  93. #define FLBUF(ioreq,i) ((char FAR1 *)(ioreq->irData) + (SECTOR_SIZE * ((int)(i))))
  94. #endif
  95. /* extract socket# and disk# from TFFS handle */
  96. #define H2S(handle) (((int)(handle)) & 0xf)
  97. #define H2D(handle) ((((int)(handle)) >> 4) & 0xf)
  98. /* construct TFFS handle from socket# and disk# */
  99. #define SD2H(socNo,diskNo) ((int)((((diskNo) & 0xf) << 4) | ((socNo) & 0xf)))
  100. /* unformatted ("raw") disk partition */
  101. #define FL_RAW_PART (-1)
  102. /*
  103. * Local routines
  104. */
  105. static FLStatus reset (void);
  106. static FLStatus discardDisk (int handle);
  107. static FLStatus newDisk (int handle);
  108. static FLStatus parseDisk (int handle);
  109. static FLStatus discardDiskParts (FLffDisk *pd);
  110. static FLStatus addDiskPart (FLffDisk *pd, int partNo);
  111. static FLStatus addNewDiskPart (FLffDisk *pd);
  112. static FLBoolean isPartTableWrite (FLffDisk *pd, IOreq FAR2 *ioreq);
  113. static FLStatus isExtPartPresent (char FAR1 *buf, SectorNo *nextExtPartSec);
  114. #ifdef FL_INCLUDE_FAT_MONITOR
  115. static FLStatus partEnableFF (FLffVol* pv);
  116. static FLStatus partFreeDelClusters (FLffVol *pv, SectorNo secNo, char FAR1 *newFAT);
  117. #endif
  118. /*
  119. * Local data
  120. */
  121. /* module reset flag */
  122. static FLBoolean resetDone = FALSE;
  123. /* disks (BDTL partitions in OSAK terminology) */
  124. static FLffDisk* ffDisk[SOCKETS][MAX_TL_PARTITIONS] = { { NULL } };
  125. #ifndef FL_MALLOC
  126. /*
  127. * WARNING: Large static arrays !
  128. *
  129. * sizeof(ffAllDisks[x][y]) is 64 bytes.
  130. * sizeof(ffAllParts[x][y][z]) is 40 bytes.
  131. *
  132. */
  133. static FLffDisk ffAllDisks[SOCKETS][MAX_TL_PARTITIONS];
  134. static FLffVol ffAllParts[SOCKETS][MAX_TL_PARTITIONS][FL_MAX_PARTS_PER_DISK];
  135. #endif /* FL_MALLOC */
  136. static const char zeroes[SECTOR_SIZE] = {0};
  137. /* --------------------------------------------------------------------------- *
  138. * *
  139. * d i s c a r d D i s k P a r t s *
  140. * *
  141. * Discard all the partition info (if any) associated with particular disk. *
  142. * *
  143. * Parameters: *
  144. * pd : disk (BDTL volume) *
  145. * *
  146. * Returns: *
  147. * Always flOK. *
  148. * *
  149. * --------------------------------------------------------------------------- */
  150. static FLStatus discardDiskParts ( FLffDisk * pd )
  151. {
  152. register int i;
  153. if (pd != NULL) {
  154. for (i = 0; i < FL_MAX_PARTS_PER_DISK; i++) {
  155. #ifdef FL_MALLOC
  156. if (pd->part[i] != NULL)
  157. FL_FREE(pd->part[i]);
  158. #endif
  159. pd->part[i] = NULL;
  160. }
  161. pd->parts = 0;
  162. }
  163. return flOK;
  164. }
  165. /* --------------------------------------------------------------------------- *
  166. * *
  167. * a d d D i s k P a r t *
  168. * *
  169. * If there is partition record #partNo associated with the disk, discard *
  170. * this info. Attach new partition record #partNo. *
  171. * *
  172. * Parameters: *
  173. * pd : disk (BDTL volume) *
  174. * partNo : partition (0 ... FL_MAX_PARTS_PER_DISK-1) *
  175. * *
  176. * Returns: *
  177. * flOK if success, otherwise respective error code *
  178. * *
  179. * --------------------------------------------------------------------------- */
  180. static FLStatus addDiskPart ( FLffDisk * pd,
  181. int partNo )
  182. {
  183. FLffVol * pv;
  184. FLStatus status;
  185. int socNo, diskNo;
  186. /* arg. sanity check */
  187. if ((pd == NULL) || (partNo >= FL_MAX_PARTS_PER_DISK))
  188. return flBadDriveHandle;
  189. /* break TFFS handle into socket# and disk#, and do sanity check */
  190. socNo = H2S(pd->handle);
  191. diskNo = H2D(pd->handle);
  192. if ((socNo >= SOCKETS) || (diskNo >= MAX_TL_PARTITIONS))
  193. return flBadDriveHandle;
  194. status = flNotEnoughMemory;
  195. #ifdef FL_MALLOC
  196. pv = (FLffVol *)FL_MALLOC( sizeof(FLffVol) );
  197. #else
  198. pv = &ffAllParts[socNo][diskNo][partNo];
  199. #endif
  200. if (pv != NULL) {
  201. /* initialize fields in struct FLffDisk to safe values */
  202. pv->handle = pd->handle;
  203. pv->type = FL_RAW_PART;
  204. pv->flags = 0;
  205. pv->ffEnabled = FALSE; /* turn off FAT minitor */
  206. pv->sectors = (SectorNo) 0;
  207. pv->firstFATsecNo = (SectorNo) -1; /* none */
  208. pv->lastFATsecNo = pv->firstFATsecNo; /* none */
  209. pv->firstDataSecNo = (SectorNo) 0;
  210. pv->clusterSize = (unsigned) 0;
  211. #ifdef FL_MALLOC
  212. if( pd->part[partNo] != NULL )
  213. FL_FREE(pd->part[partNo]);
  214. #endif
  215. pd->part[partNo] = pv;
  216. status = flOK;
  217. }
  218. return status;
  219. }
  220. /* --------------------------------------------------------------------------- *
  221. * *
  222. * a d d N e w D i s k P a r t *
  223. * *
  224. * Add one more partition record to the disk. *
  225. * *
  226. * Parameters: *
  227. * pd : disk (BDTL volume) *
  228. * *
  229. * Returns: *
  230. * flOK if success, otherwise respective error code *
  231. * *
  232. * --------------------------------------------------------------------------- */
  233. static FLStatus addNewDiskPart ( FLffDisk * pd )
  234. {
  235. if (pd->parts < FL_MAX_PARTS_PER_DISK) {
  236. checkStatus( addDiskPart (pd, pd->parts) );
  237. pd->parts++;
  238. }
  239. return flOK;
  240. }
  241. /* --------------------------------------------------------------------------- *
  242. * *
  243. * d i s c a r d D i s k *
  244. * *
  245. * Remove disk record (with all the associated partition records). *
  246. * *
  247. * Parameters: *
  248. * handle : TFFS handle *
  249. * *
  250. * Returns: *
  251. * flOK if success, otherwise respective error code *
  252. * *
  253. * --------------------------------------------------------------------------- */
  254. static FLStatus discardDisk ( int handle )
  255. {
  256. int socNo, diskNo;
  257. /* break TFFS handle into socket# and disk#, and do sanity check */
  258. socNo = H2S(handle);
  259. diskNo = H2D(handle);
  260. if ((socNo >= SOCKETS) || (diskNo >= MAX_TL_PARTITIONS))
  261. return flBadDriveHandle;
  262. if( ffDisk[socNo][diskNo] != NULL ) {
  263. /* discard associated partition info */
  264. (void) discardDiskParts( ffDisk[socNo][diskNo] );
  265. #ifdef FL_MALLOC
  266. /* release disk's scratch buffer */
  267. if( (ffDisk[socNo][diskNo])->buf != NULL)
  268. FL_FREE( (ffDisk[socNo][diskNo])->buf );
  269. FL_FREE( ffDisk[socNo][diskNo] );
  270. #endif
  271. ffDisk[socNo][diskNo] = NULL;
  272. }
  273. return flOK;
  274. }
  275. /* --------------------------------------------------------------------------- *
  276. * *
  277. * n e w D i s k *
  278. * *
  279. * Discard existing disk record (if any), and create new one. *
  280. * *
  281. * Parameters: *
  282. * handle : TFFS handle *
  283. * *
  284. * Returns: *
  285. * flOK if success, otherwise respective error code *
  286. * *
  287. * --------------------------------------------------------------------------- */
  288. static FLStatus newDisk ( int handle )
  289. {
  290. int socNo, diskNo;
  291. int i;
  292. FLffDisk * pd;
  293. /* break TFFS handle into socket# and disk#, and do sanity check */
  294. socNo = H2S(handle);
  295. diskNo = H2D(handle);
  296. if ((socNo >= SOCKETS) || (diskNo >= MAX_TL_PARTITIONS))
  297. return flBadDriveHandle;
  298. /* discard current disk and associated partition info (if any) */
  299. checkStatus( discardDisk(handle) );
  300. #ifdef FL_MALLOC
  301. pd = (FLffDisk *) FL_MALLOC( sizeof(FLffDisk) );
  302. if (pd == NULL)
  303. return flNotEnoughMemory;
  304. /* allocate and attach disk's scratch buffer */
  305. pd->buf = (char *)FL_MALLOC( SECTOR_SIZE );
  306. if (pd->buf == NULL) {
  307. FL_FREE (pd);
  308. return flNotEnoughMemory;
  309. }
  310. #else /* !FL_MALLOC */
  311. pd = &ffAllDisks[socNo][diskNo];
  312. #endif /* FL_MALLOC */
  313. pd->handle = handle;
  314. pd->ffstate = flStateNotInitialized;
  315. /* don't know partition layout yet */
  316. pd->parts = 0;
  317. for (i = 0; i < FL_MAX_PARTS_PER_DISK; i++)
  318. pd->part[i] = NULL;
  319. /* watch Master Boot Record for update */
  320. pd->secToWatch = (SectorNo) 0;
  321. ffDisk[socNo][diskNo] = pd;
  322. return flOK;
  323. }
  324. /* --------------------------------------------------------------------------- *
  325. * *
  326. * i s P a r t T a b l e W r i t e *
  327. * *
  328. * Check if any of the sectors specified by 'ioreq' points to Master Boot *
  329. * Record or next extended partition in the extended partitions list. *
  330. * *
  331. * Parameters: *
  332. * pd : pointer to disk structure *
  333. * ioreq : standard I/O request *
  334. * *
  335. * Returns: *
  336. * TRUE if write to MBR or extended partition list is detected, otherwise *
  337. * FALSE *
  338. * *
  339. * --------------------------------------------------------------------------- */
  340. static FLBoolean isPartTableWrite ( FLffDisk * pd,
  341. IOreq FAR2 * ioreq )
  342. {
  343. register long i;
  344. if (pd != NULL) {
  345. for (i = (long)0; i < ioreq->irSectorCount; i++) {
  346. if( (ioreq->irSectorNo + i) == (long)pd->secToWatch )
  347. return TRUE;
  348. }
  349. }
  350. return FALSE;
  351. }
  352. /* --------------------------------------------------------------------------- *
  353. * *
  354. * i s E x t P a r t P r e s e n t *
  355. * *
  356. * Check if extended partition persent in the partition table. If it is, *
  357. * calculate the sector # where next partition table will be written to. *
  358. * *
  359. * Parameters: *
  360. * buf : partition table *
  361. * nextExtPartSec : sector where next partition table will be written to *
  362. * *
  363. * Returns: *
  364. * flOK on success, otherwise error code *
  365. * *
  366. * --------------------------------------------------------------------------- */
  367. static FLStatus isExtPartPresent ( char FAR1 * buf,
  368. SectorNo * nextExtPartSec )
  369. {
  370. Partition FAR1 * p;
  371. register int i;
  372. /* does it look like partition table ? */
  373. if (LE2(((PartitionTable FAR1 *) buf)->signature) != PARTITION_SIGNATURE)
  374. return flBadFormat;
  375. /* if extended. part. present, get sector# that will contain next part. in list */
  376. p = &( ((PartitionTable FAR1 *) buf)->ptEntry[0] );
  377. for (i = 0; i < FL_PART_TBL_ENTRIES; i++, p++) {
  378. if (p->type == EX_PARTIT) {
  379. *nextExtPartSec = (SectorNo) UNAL4( (void *) p[i].startingSectorOfPartition );
  380. return flOK;
  381. }
  382. }
  383. /* no extended partition found */
  384. return flFileNotFound;
  385. }
  386. /* --------------------------------------------------------------------------- *
  387. * *
  388. * r e s e t *
  389. * *
  390. * Resets this software module to it's initial state upon boot. *
  391. * *
  392. * Parameters: *
  393. * none *
  394. * *
  395. * Returns: *
  396. * flOK in case of success, otherwise respective error code *
  397. * *
  398. * --------------------------------------------------------------------------- */
  399. static FLStatus reset (void)
  400. {
  401. int iSoc, iDisk;
  402. for (iSoc = 0; iSoc < SOCKETS; iSoc++) {
  403. /* discard existing disk structures for that socket */
  404. for (iDisk = 0; iDisk < MAX_TL_PARTITIONS; iDisk++)
  405. (void) discardDisk( SD2H(iSoc, iDisk) );
  406. /* pre-allocate disk structure for first disk of every socket */
  407. checkStatus( newDisk(SD2H(iSoc, 0)) );
  408. }
  409. resetDone = TRUE;
  410. return flOK;
  411. }
  412. /* --------------------------------------------------------------------------- *
  413. * *
  414. * p a r s e D i s k *
  415. * *
  416. * Read partition table(s), install and enable FAT filters on all FAT12/16 *
  417. * partitions. *
  418. * *
  419. * Parameters: *
  420. * handle : TFFS handle *
  421. * *
  422. * Returns: *
  423. * flOK on success, otherwise error code *
  424. * *
  425. * NOTE: This routine uses disk's scratch buffer. *
  426. * *
  427. * --------------------------------------------------------------------------- */
  428. static FLStatus parseDisk ( int handle )
  429. {
  430. int socNo, diskNo;
  431. SectorNo extPartStartSec, sec;
  432. int i, depth;
  433. int type;
  434. FLffDisk * pd;
  435. FLffVol * pv;
  436. Partition * pp;
  437. IOreq ioreq;
  438. #ifdef FL_MALLOC
  439. char * buf;
  440. #else
  441. char buf[SECTOR_SIZE];
  442. #endif
  443. /* break TFFS handle into socket# and disk#, and do sanity check */
  444. socNo = H2S(handle);
  445. diskNo = H2D(handle);
  446. if ((socNo >= ((int) noOfSockets)) || (diskNo >= MAX_TL_PARTITIONS))
  447. return flBadDriveHandle;
  448. /* if disk structure hasn't been allocated yet, do it now */
  449. if (ffDisk[socNo][diskNo] == NULL)
  450. checkStatus( newDisk(handle) );
  451. pd = ffDisk[socNo][diskNo];
  452. #ifdef FL_MALLOC
  453. /* make sure scratch buffer is available */
  454. if (pd->buf == NULL)
  455. return flBufferingError;
  456. buf = pd->buf;
  457. #endif /* FL_MALLOC */
  458. /* discard obsolete disk's partition info */
  459. (void) discardDiskParts (pd);
  460. /* read Master Boot Record */
  461. ioreq.irHandle = handle;
  462. ioreq.irSectorNo = (SectorNo) 0;
  463. ioreq.irSectorCount = (SectorNo) 1;
  464. ioreq.irData = (void FAR1 *) buf;
  465. checkStatus( flAbsRead(&ioreq) );
  466. /* is it MBR indeed ? */
  467. if (LE2(((PartitionTable *) buf)->signature) != PARTITION_SIGNATURE)
  468. return flPartitionNotFound;
  469. /* do primary partitions only (we will do extended partitions later) */
  470. pp = &( ((PartitionTable *) buf)->ptEntry[0] );
  471. for (i = 0; i < FL_PART_TBL_ENTRIES; i++, pp++) {
  472. if( pp->type == ((char)0) ) /* skip empty slot */
  473. continue;
  474. if( pp->type == ((char)EX_PARTIT) ) /* skip extended partition */
  475. continue;
  476. /* primary partition found (not necessarily FAT12/16) */
  477. if( addNewDiskPart(pd) != flOK )
  478. break;
  479. pv = pd->part[pd->parts - 1];
  480. /* remember partition's type, and where it starts */
  481. pv->type = (int) pp->type;
  482. pv->startSecNo = (SectorNo) UNAL4( (void *) pp->startingSectorOfPartition );
  483. }
  484. /* do extended partitions in depth */
  485. for (i = 0; i < FL_PART_TBL_ENTRIES; i++) {
  486. /* re-read Master Boot Record */
  487. ioreq.irHandle = handle;
  488. ioreq.irSectorNo = (SectorNo) 0;
  489. ioreq.irSectorCount = (SectorNo) 1;
  490. ioreq.irData = (void FAR1 *) buf;
  491. checkStatus( flAbsRead(&ioreq) );
  492. /* is it MBR indeed ? */
  493. if (LE2(((PartitionTable *) buf)->signature) != PARTITION_SIGNATURE)
  494. return flOK;
  495. /* pick up next extended partition in MBR */
  496. pp = &( ((PartitionTable *) buf)->ptEntry[i] );
  497. if( pp->type == ((char)EX_PARTIT) ) {
  498. /* remember where extended partition starts */
  499. extPartStartSec = (SectorNo) UNAL4( (void *) pp->startingSectorOfPartition );
  500. /* follow the list of partition tables */
  501. sec = extPartStartSec;
  502. for (depth = 0; depth < MAX_PARTITION_DEPTH; depth++) {
  503. /* read next partition table in the list */
  504. ioreq.irHandle = handle;
  505. ioreq.irSectorNo = sec;
  506. ioreq.irSectorCount = (SectorNo) 1;
  507. ioreq.irData = (void FAR1 *) buf;
  508. checkStatus( flAbsRead(&ioreq) );
  509. /* is it valid partition table ? */
  510. if (LE2(((PartitionTable *) buf)->signature) != PARTITION_SIGNATURE)
  511. break;
  512. /* if 1st entry is zero, it's the end of part. table list */
  513. pp = &( ((PartitionTable *) buf)->ptEntry[0] );
  514. if( pp->type == ((char)0) )
  515. break;
  516. /* Take this partition. Remember it's type, and where it starts */
  517. if( addNewDiskPart(pd) != flOK )
  518. break;
  519. pv = pd->part[pd->parts - 1];
  520. pv->type = (int) pp->type;
  521. pv->startSecNo =
  522. (SectorNo) UNAL4( (void *) pp->startingSectorOfPartition) + sec;
  523. /* 2nd entry must be extended partition */
  524. pp = &( ((PartitionTable *) buf)->ptEntry[1] );
  525. if( pp->type != ((char)EX_PARTIT) )
  526. break;
  527. /* sector where next part. table in the list resides */
  528. sec = extPartStartSec +
  529. (SectorNo) UNAL4( (void *) pp->startingSectorOfPartition );
  530. } /* for(depth) */
  531. }
  532. } /* for(i) */
  533. #ifdef FL_INCLUDE_FAT_MONITOR
  534. /* turn on FAT filters on FAT12/16 partition(s) */
  535. if (pd->parts > 0) {
  536. for (i = 0; i < pd->parts; i++) {
  537. pv = pd->part[i];
  538. type = pv->type;
  539. /*
  540. * WARNING : Routine partEnableFF() uses disk's scratch buffer !
  541. */
  542. if((type == FAT12_PARTIT) || (type == FAT16_PARTIT) || (type == DOS4_PARTIT))
  543. partEnableFF (pv);
  544. }
  545. }
  546. #endif /* FL_INCLUDE_FAT_MONITOR */
  547. /* watch for MBR (sector #0) update */
  548. pd->secToWatch = (SectorNo) 0;
  549. pd->ffstate = flStateInitialized;
  550. return flOK;
  551. }
  552. #ifdef FL_INCLUDE_FAT_MONITOR
  553. /* --------------------------------------------------------------------------- *
  554. * *
  555. * p a r t E n a b l e F F *
  556. * *
  557. * Installs and enables FAT filter on partition. *
  558. * *
  559. * Parameters: *
  560. * pv : disk partition (filesystem volume) *
  561. * *
  562. * Returns: *
  563. * flOK on success, otherwise error code *
  564. * *
  565. * NOTE: This routine uses disk's scratch buffer. *
  566. * *
  567. * --------------------------------------------------------------------------- */
  568. static FLStatus partEnableFF ( FLffVol * pv )
  569. {
  570. int socNo, diskNo;
  571. FLffDisk * pd;
  572. BPB * bpb;
  573. SectorNo sectors;
  574. SectorNo rootDirSecNo;
  575. SectorNo rootDirSectors;
  576. SectorNo sectorsPerFAT;
  577. unsigned maxCluster;
  578. int partNo;
  579. IOreq ioreq;
  580. #ifdef FL_MALLOC
  581. char * buf;
  582. #else
  583. char buf[SECTOR_SIZE];
  584. #endif
  585. /* arg. sanity check */
  586. if (pv == NULL)
  587. return flBadDriveHandle;
  588. /* break TFFS handle into socket# and disk#, and do sanity check */
  589. socNo = H2S(pv->handle);
  590. diskNo = H2D(pv->handle);
  591. if ((socNo >= ((int) noOfSockets)) || (diskNo >= MAX_TL_PARTITIONS))
  592. return flBadDriveHandle;
  593. /* check if 'pv' belongs to this disk */
  594. pd = ffDisk[socNo][diskNo];
  595. if (pd == NULL)
  596. return flBadDriveHandle;
  597. for (partNo = 0; partNo < pd->parts; partNo++) {
  598. if (pd->part[partNo] == pv)
  599. break;
  600. }
  601. if (partNo >= pd->parts)
  602. return flBadDriveHandle;
  603. #ifdef FL_MALLOC
  604. /* make sure scratch buffer is available */
  605. if (pd->buf == NULL)
  606. return flBufferingError;
  607. buf = pd->buf;
  608. #endif /* FL_MALLOC */
  609. /* make sure FAT filter is off on this partition */
  610. pv->ffEnabled = FALSE;
  611. pv->firstFATsecNo = (SectorNo) -1;
  612. pv->lastFATsecNo = pv->firstFATsecNo;
  613. pv->clusterSize = (unsigned) 0;
  614. /* read the BPB */
  615. ioreq.irHandle = pv->handle;
  616. ioreq.irSectorNo = pv->startSecNo;
  617. ioreq.irSectorCount = (SectorNo) 1;
  618. ioreq.irData = (void FAR1 *) buf;
  619. checkStatus( flAbsRead(&ioreq) );
  620. /* Does it look like DOS bootsector ? */
  621. bpb = &( ((DOSBootSector *) buf)->bpb );
  622. if( !((bpb->jumpInstruction[0] == 0xe9)
  623. ||
  624. ((bpb->jumpInstruction[0] == 0xeb) && (bpb->jumpInstruction[2] == 0x90)))) {
  625. return flNonFATformat;
  626. }
  627. /* Do we handle this sector size ? */
  628. if (UNAL2(bpb->bytesPerSector) != SECTOR_SIZE)
  629. return flFormatNotSupported;
  630. /*
  631. * Is it a bogus BPB (leftover from previous disk partitioning) ?
  632. * Check that there is no overlap with next partition (if one exists).
  633. */
  634. sectors = UNAL2(bpb->totalSectorsInVolumeDOS3);
  635. if (sectors == (SectorNo)0)
  636. sectors = (SectorNo) LE4(bpb->totalSectorsInVolume);
  637. if ((partNo+1 < pd->parts) && (pd->part[partNo+1] != NULL)) {
  638. if( sectors > (pd->part[partNo+1])->startSecNo - pv->startSecNo )
  639. return flNonFATformat;
  640. }
  641. /* number of sectors in partition as reported by BPB */
  642. pv->sectors = sectors;
  643. /* valid BPB; get the rest of partition info from it */
  644. pv->firstFATsecNo = pv->startSecNo + (SectorNo)( LE2(bpb->reservedSectors) );
  645. sectorsPerFAT = (SectorNo) LE2(bpb->sectorsPerFAT);
  646. pv->lastFATsecNo = pv->firstFATsecNo + sectorsPerFAT - (SectorNo)1;
  647. rootDirSecNo = pv->firstFATsecNo + (sectorsPerFAT * bpb->noOfFATS);
  648. rootDirSectors = (SectorNo)1 + (SectorNo)
  649. (((UNAL2(bpb->rootDirectoryEntries) * DIRECTORY_ENTRY_SIZE) - 1) / SECTOR_SIZE);
  650. pv->firstDataSecNo = rootDirSecNo + rootDirSectors;
  651. pv->clusterSize = bpb->sectorsPerCluster;
  652. /* decide which type of FAT is it */
  653. maxCluster = (unsigned)1 + (unsigned)
  654. ((pv->sectors - (pv->firstDataSecNo - pv->startSecNo)) / pv->clusterSize);
  655. if (maxCluster < 4085) {
  656. pv->flags |= VOLUME_12BIT_FAT; /* 12-bit FAT */
  657. #ifndef FAT_12BIT
  658. DEBUG_PRINT(("Debug: FAT_12BIT must be defined.\r\n"));
  659. return flFormatNotSupported;
  660. #endif
  661. }
  662. /* turn on FAT filter on this partition */
  663. pv->ffEnabled = TRUE;
  664. return flOK;
  665. }
  666. /* --------------------------------------------------------------------------- *
  667. * *
  668. * p a r t F r e e D e l C l u s t e r s *
  669. * *
  670. * Compare the new contents of the specified FAT sector against the old *
  671. * one on the disk. If any freed clusters are found, issue 'sector delete' *
  672. * calls for all sectors that are occupied by these freed clusters. *
  673. * *
  674. * Parameters: *
  675. * pv : disk partition (filesystem volume) *
  676. * secNo : abs. sector # of the FAT sector *
  677. * newFAT : new contents of this FAT sector *
  678. * *
  679. * Returns: *
  680. * flOK on success, otherwise error code *
  681. * *
  682. * NOTE: This routine uses disk's scratch buffer. *
  683. * *
  684. * --------------------------------------------------------------------------- */
  685. static FLStatus partFreeDelClusters ( FLffVol * pv,
  686. SectorNo secNo,
  687. char FAR1 * newFAT)
  688. {
  689. FLffDisk * pd;
  690. int socNo, diskNo;
  691. unsigned short oldFATentry, newFATentry;
  692. SectorNo iSec;
  693. unsigned firstCluster;
  694. IOreq ioreq;
  695. int offset;
  696. int iPart;
  697. #ifdef FAT_12BIT
  698. int halfBytes;
  699. #endif
  700. #ifdef FL_MALLOC
  701. char * oldFAT;
  702. #else
  703. char oldFAT[SECTOR_SIZE];
  704. #endif
  705. /* arg. sanity check */
  706. if (pv == NULL)
  707. return flBadDriveHandle;
  708. /* break TFFS handle into socket# and disk#, and do sanity check */
  709. socNo = H2S(pv->handle);
  710. diskNo = H2D(pv->handle);
  711. if ((socNo >= ((int) noOfSockets)) || (diskNo >= MAX_TL_PARTITIONS))
  712. return flBadDriveHandle;
  713. /* check if 'pv' belongs to this disk */
  714. pd = ffDisk[socNo][diskNo];
  715. if (pd == NULL)
  716. return flBadDriveHandle;
  717. for (iPart = 0; iPart < pd->parts; iPart++) {
  718. if (pd->part[iPart] == pv)
  719. break;
  720. }
  721. if (iPart >= pd->parts)
  722. return flBadDriveHandle;
  723. #ifdef FL_MALLOC
  724. /* make sure scratch buffer is available */
  725. if (pd->buf == NULL)
  726. return flBufferingError;
  727. oldFAT = pd->buf;
  728. #endif /* FL_MALLOC */
  729. /* read in the FAT sector from the disk */
  730. ioreq.irHandle = pv->handle;
  731. ioreq.irSectorNo = secNo;
  732. ioreq.irSectorCount = 1;
  733. ioreq.irData = (void FAR1 *) oldFAT;
  734. checkStatus( flAbsRead(&ioreq) );
  735. #ifdef FAT_12BIT
  736. /* size of FAT entry in half-bytes */
  737. halfBytes = ((pv->flags & VOLUME_12BIT_FAT) ? 3 : 4);
  738. /* starting cluster */
  739. if (halfBytes == 3) {
  740. firstCluster =
  741. ((((unsigned)(secNo - pv->firstFATsecNo)) * (2 * SECTOR_SIZE)) + 2) / 3;
  742. }
  743. else {
  744. firstCluster = ((unsigned)(secNo - pv->firstFATsecNo)) * (SECTOR_SIZE / 2);
  745. }
  746. /* staring data sector */
  747. iSec = (((SectorNo)firstCluster - 2) * pv->clusterSize) + pv->firstDataSecNo;
  748. offset = (firstCluster * ((unsigned) halfBytes)) & ((2 * SECTOR_SIZE) - 1);
  749. /*
  750. * Find if any clusters were logically deleted, and if so, delete them.
  751. *
  752. * NOTE: We are skipping over 12-bit FAT entries which span more than
  753. * one sector.
  754. */
  755. for (; offset < ((2 * SECTOR_SIZE) - 2);
  756. offset += halfBytes, iSec += pv->clusterSize) {
  757. #ifdef FL_BIG_ENDIAN
  758. oldFATentry = LE2( *(LEushort FAR0 *)(oldFAT + (offset / 2)) );
  759. newFATentry = LE2( *(LEushort FAR1 *)(newFAT + (offset / 2)) );
  760. #else
  761. oldFATentry = UNAL2( *(Unaligned FAR0 *)(oldFAT + (offset / 2)) );
  762. newFATentry = UNAL2( *(Unaligned FAR1 *)(newFAT + (offset / 2)) );
  763. #endif /* FL_BIG_ENDIAN */
  764. if (offset & 1) {
  765. oldFATentry >>= 4;
  766. newFATentry >>= 4;
  767. }
  768. else {
  769. if (halfBytes == 3) {
  770. oldFATentry &= 0xfff;
  771. newFATentry &= 0xfff;
  772. }
  773. }
  774. #else /* !FAT_12BIT */
  775. firstCluster = ((unsigned) (secNo - pv->firstFATsecNo) * (SECTOR_SIZE / 2));
  776. iSec = pv->firstDataSecNo +
  777. (((SectorNo)(firstCluster - (unsigned)2)) * pv->clusterSize);
  778. /* Find if any clusters were logically deleted, and if so, delete them */
  779. for (offset = 0; offset < SECTOR_SIZE; offset += 2, iSec += pv->clusterSize) {
  780. oldFATentry = LE2( *(LEushort FAR0 *)(oldFAT + offset) );
  781. newFATentry = LE2( *(LEushort FAR1 *)(newFAT + offset) );
  782. #endif /* FAT_12BIT */
  783. if ((oldFATentry != FAT_FREE) && (newFATentry == FAT_FREE)) {
  784. ioreq.irHandle = pv->handle;
  785. ioreq.irSectorNo = iSec;
  786. ioreq.irSectorCount = pv->clusterSize;
  787. checkStatus( flAbsDelete(&ioreq) );
  788. }
  789. }
  790. return flOK;
  791. }
  792. #endif /* FL_INCLUDE_FAT_MONITOR */
  793. /* --------------------------------------------------------------------------- *
  794. * *
  795. * f f C h e c k B e f o r e W r i t e *
  796. * *
  797. * Catch all the FAT updates. Detect disk partitioning operation, track it *
  798. * to completion, re-read partition tables, and re-install FAT filters on *
  799. * all FAT12/16 partitions. *
  800. * *
  801. * Parameters: *
  802. * ioreq : standard I/O request to be checked *
  803. * *
  804. * Returns: *
  805. * flOK on success, otherwise error code *
  806. * *
  807. * --------------------------------------------------------------------------- */
  808. FLStatus ffCheckBeforeWrite ( IOreq FAR2 * ioreq )
  809. {
  810. int socNo, diskNo;
  811. FLffDisk * pd;
  812. FLffVol * pv;
  813. long iSec;
  814. int iPart;
  815. IOreq ioreq2;
  816. char FAR1 * usrBuf;
  817. /* if module hasn't been reset yet, do it now */
  818. if (resetDone == FALSE)
  819. (void) reset();
  820. /* break TFFS handle into socket# and disk#, and do sanity check */
  821. socNo = H2S(ioreq->irHandle);
  822. diskNo = H2D(ioreq->irHandle);
  823. if ((socNo >= ((int) noOfSockets)) || (diskNo >= MAX_TL_PARTITIONS))
  824. return flBadDriveHandle;
  825. /* if disk structure hasn't been allocated yet, do it now */
  826. if (ffDisk[socNo][diskNo] == NULL)
  827. checkStatus( newDisk((int)ioreq->irHandle) );
  828. pd = ffDisk[socNo][diskNo];
  829. /* read partition table(s) and install FAT filters is needed */
  830. if (pd->ffstate == flStateNotInitialized)
  831. checkStatus( parseDisk((int)ioreq->irHandle) );
  832. /* catch writes to MBR, and track the whole disk partitioning operations */
  833. while( isPartTableWrite(pd, ioreq) == TRUE ) {
  834. /* disk re-partitioning is in progress */
  835. if( pd->secToWatch == (SectorNo)0 ) {
  836. /* it's write to MBR, so trash BPBs in all disk's partitions */
  837. if (pd->parts > 0) {
  838. for (iPart = 0; iPart < pd->parts; iPart++) {
  839. ioreq2.irHandle = ioreq->irHandle;
  840. ioreq2.irSectorNo = (pd->part[iPart])->startSecNo;
  841. ioreq2.irSectorCount = (SectorNo) 1;
  842. ioreq2.irData = (void FAR1 *) zeroes;
  843. (void) flAbsWrite(&ioreq2);
  844. }
  845. }
  846. }
  847. /* keep FAT filters disabled while disk partitioning is in progress */
  848. pd->ffstate = flStateInitInProgress;
  849. /* partition table which is about to be written to disk */
  850. usrBuf = FLBUF( ioreq, (pd->secToWatch - ioreq->irSectorNo) );
  851. switch( isExtPartPresent(usrBuf, &(pd->secToWatch)) ) {
  852. case flOK:
  853. /*
  854. * Found valid partition table with extended partition.
  855. * The pd->secToWatch has been updated to point to the
  856. * sector where next partition table will be written to.
  857. */
  858. continue;
  859. case flFileNotFound:
  860. /*
  861. * Valid partition table, but no extended partition in it.
  862. * Partitioning has been completed. Set pd->ffstate to
  863. * 'flStateNotInitialized' to initiate parsing of partition
  864. * table(s) and FAT filter installation next time this routine
  865. * is called.
  866. */
  867. pd->ffstate = flStateNotInitialized;
  868. break;
  869. case flBadFormat:
  870. default:
  871. /* No valid partition table. */
  872. break;
  873. }
  874. return flOK;
  875. }
  876. #ifdef FL_INCLUDE_FAT_MONITOR
  877. /* check for FAT update */
  878. if (pd->ffstate == flStateInitialized) {
  879. /* NOTE: We can handle 'write' request that spans disk partition boundaries */
  880. for (iSec = ioreq->irSectorNo;
  881. iSec < (ioreq->irSectorNo + ioreq->irSectorCount); iSec++) {
  882. for (iPart = 0; iPart < pd->parts; iPart++) {
  883. pv = pd->part[iPart];
  884. /* we monitor only FAT12/16 partitions */
  885. if ((pv->type != FAT12_PARTIT) && (pv->type != FAT16_PARTIT) &&
  886. (pv->type != DOS4_PARTIT))
  887. continue;
  888. /* FAT filters can be disabled on individual partitions */
  889. if (pv->ffEnabled != TRUE)
  890. continue;
  891. if ((iSec >= (long)pv->firstFATsecNo) && (iSec <= (long)pv->lastFATsecNo)) {
  892. /* compare new and old contents of FAT sectors(s) */
  893. usrBuf = FLBUF( ioreq, (iSec - ioreq->irSectorNo) );
  894. checkStatus( partFreeDelClusters(pv, iSec, usrBuf) );
  895. }
  896. }
  897. }
  898. }
  899. #endif /* FL_INCLUDE_FAT_MONITOR */
  900. return flOK;
  901. }
  902. /* --------------------------------------------------------------------------- *
  903. * *
  904. * f l f f C o n t r o l *
  905. * *
  906. * Enable/disable/install FAT filters. See comments inside the routine for *
  907. * the list of supported operations. *
  908. * *
  909. * Parameters: *
  910. * handle : TFFS handle *
  911. * partNo : partition # (0 .. FL_MAX_PARTS_PER_DISK) *
  912. * state : see list of supported operations below *
  913. * *
  914. * Returns: *
  915. * flOK on success, otherwise error code *
  916. * *
  917. * --------------------------------------------------------------------------- *
  918. * *
  919. * The following FAT monitor control requests are supported: *
  920. * *
  921. * state : flStateNotInitialized *
  922. * partNo : [0 ... pd->parts-1] *
  923. * action : turn off FAT monitor on specified partition *
  924. * *
  925. * state : flStateNotInitialized *
  926. * partNo : < 0 *
  927. * action : turn off FAT monitor on all partitions *
  928. * *
  929. * state : flStateInitialized *
  930. * partNo : [0 ... pd->parts-1] *
  931. * action : if FAT monitor has been installed on specified partition, *
  932. * turn it on *
  933. * *
  934. * state : flStateInitInProgress *
  935. * partNo : ignored *
  936. * action : re-read partition table(s), and install FAT filters on all *
  937. * partitions *
  938. * *
  939. * --------------------------------------------------------------------------- */
  940. FLStatus flffControl ( int handle,
  941. int partNo,
  942. FLState state )
  943. {
  944. int socNo, diskNo;
  945. FLffDisk * pd;
  946. int i;
  947. FLStatus status;
  948. /* if module hasn't been reset yet, do it now */
  949. if (resetDone == FALSE)
  950. (void) reset();
  951. /* break TFFS handle into socket# and disk#, and do sanity check */
  952. socNo = H2S(handle);
  953. diskNo = H2D(handle);
  954. if ((socNo >= ((int) noOfSockets)) || (diskNo >= MAX_TL_PARTITIONS))
  955. return flBadDriveHandle;
  956. /* if disk structure hasn't been allocated yet, do it now */
  957. if (ffDisk[socNo][diskNo] == NULL)
  958. checkStatus( newDisk(handle) );
  959. pd = ffDisk[socNo][diskNo];
  960. /* abort if disk re-partitioning is in progress */
  961. if (pd->ffstate == flStateInitInProgress)
  962. return flDriveNotReady;
  963. /* read partition table(s) and install FAT filters is needed */
  964. if (pd->ffstate == flStateNotInitialized) {
  965. if (state == flStateNotInitialized)
  966. return flOK;
  967. checkStatus( parseDisk(handle) );
  968. }
  969. /* check 'partNo' arguement for sanity */
  970. if ((partNo >= pd->parts) || (partNo >= FL_MAX_PARTS_PER_DISK))
  971. return flBadDriveHandle;
  972. /* do requested operation */
  973. status = flBadParameter;
  974. switch (state) {
  975. case flStateInitInProgress:
  976. /* read partition table(s), install FAT filters on all partitions */
  977. pd->ffstate = flStateNotInitialized;
  978. status = parseDisk(handle);
  979. break;
  980. case flStateNotInitialized:
  981. /* turn off FAT monitor */
  982. if (partNo < 0) { /* all partitions */
  983. for (i = 0; i < FL_MAX_PARTS_PER_DISK; i++) {
  984. if (pd->part[i] != NULL)
  985. (pd->part[i])->ffEnabled = FALSE;
  986. }
  987. }
  988. else { /* specified partition */
  989. if (pd->part[partNo] != NULL)
  990. (pd->part[partNo])->ffEnabled = FALSE;
  991. }
  992. status = flOK;
  993. break;
  994. #ifdef FL_INCLUDE_FAT_MONITOR
  995. case flStateInitialized:
  996. /* turn on FAT monitor */
  997. if ((pd->ffstate == flStateInitialized) && (partNo >= 0)) {
  998. if (pd->part[partNo] != NULL) {
  999. switch( (pd->part[partNo])->type ) {
  1000. case FAT12_PARTIT:
  1001. case FAT16_PARTIT:
  1002. case DOS4_PARTIT:
  1003. (pd->part[partNo])->ffEnabled = TRUE;
  1004. status = flOK;
  1005. break;
  1006. case FL_RAW_PART:
  1007. DEBUG_PRINT(("Debug: can't ctrl non-existent partition.\r\n"));
  1008. break;
  1009. default:
  1010. DEBUG_PRINT(("Debug: can't ctrl non-FAT12/16 partition.\r\n"));
  1011. break;
  1012. }
  1013. }
  1014. }
  1015. break;
  1016. #endif /* FL_INCLUDE_FAT_MONITOR */
  1017. } /* switch(state) */
  1018. return status;
  1019. }
  1020. /* --------------------------------------------------------------------------- *
  1021. * *
  1022. * f l f f I n f o *
  1023. * *
  1024. * Obtain complete partition info for specified disk. *
  1025. * *
  1026. * Parameters: *
  1027. * handle : TFFS handle *
  1028. * *
  1029. * Returns: *
  1030. * NULL if error, otherwise pointer to partitioning info *
  1031. * *
  1032. * --------------------------------------------------------------------------- */
  1033. FLffDisk * flffInfo ( int handle )
  1034. {
  1035. int socNo, diskNo;
  1036. FLffDisk * pd;
  1037. /* if module hasn't been reset yet, do it now */
  1038. if (resetDone == FALSE)
  1039. (void) reset();
  1040. /* break TFFS handle into socket# and disk#, and do sanity check */
  1041. socNo = H2S(handle);
  1042. diskNo = H2D(handle);
  1043. if ((socNo >= ((int) noOfSockets)) || (diskNo >= MAX_TL_PARTITIONS))
  1044. return NULL;
  1045. /* if disk structure hasn't been allocated yet, do it now */
  1046. if (ffDisk[socNo][diskNo] == NULL) {
  1047. if( newDisk(handle) != flOK )
  1048. return NULL;
  1049. }
  1050. pd = ffDisk[socNo][diskNo];
  1051. /* read partition table(s) and install FAT filters is needed */
  1052. if (pd->ffstate == flStateNotInitialized) {
  1053. if( parseDisk(handle) != flOK )
  1054. return NULL;
  1055. }
  1056. return pd;
  1057. }
  1058. #endif /* ABS_READ_WRITE && FL_READ_ONLY */