1521 lines
50 KiB
C
1521 lines
50 KiB
C
|
|
||
|
/*******************************************************************************
|
||
|
* *
|
||
|
* M-Systems Confidential *
|
||
|
* Copyright (C) M-Systems Flash Disk Pioneers Ltd. 1995-2001 *
|
||
|
* All Rights Reserved *
|
||
|
* *
|
||
|
*******************************************************************************
|
||
|
* *
|
||
|
* NOTICE OF M-SYSTEMS OEM *
|
||
|
* SOFTWARE LICENSE AGREEMENT *
|
||
|
* *
|
||
|
* THE USE OF THIS SOFTWARE IS GOVERNED BY A SEPARATE LICENSE AGREEMENT *
|
||
|
* BETWEEN THE OEM AND M-SYSTEMS. REFER TO THAT AGREEMENT FOR THE SPECIFIC *
|
||
|
* TERMS AND CONDITIONS OF USE, OR CONTACT M-SYSTEMS FOR LICENSE *
|
||
|
* ASSISTANCE: *
|
||
|
* E-MAIL = info@m-sys.com *
|
||
|
* *
|
||
|
*******************************************************************************
|
||
|
* *
|
||
|
* *
|
||
|
* Module: FATFILT *
|
||
|
* *
|
||
|
* This module implements installable FAT12/16 filters. It supports up to *
|
||
|
* SOCKETS sockets, with up to MAX_TL_PARTITIONS disks per socket. *
|
||
|
* Each disk can contain up to FL_MAX_PARTS_PER_DISK partitions on it, with *
|
||
|
* maximum depth of partition nesting in extended partitions equal to *
|
||
|
* MAX_PARTITION_DEPTH. *
|
||
|
* *
|
||
|
* In order for this module to work, disks must be abs.mounted rather then *
|
||
|
* mounted. In latter case, this module won't detect any of disk's *
|
||
|
* partitions, and won't install FAT filters. *
|
||
|
* *
|
||
|
* This module uses more then 512 bytes of stack space in case if MALLOC is *
|
||
|
* not enabled. *
|
||
|
* *
|
||
|
*******************************************************************************/
|
||
|
|
||
|
/*
|
||
|
* $Log: V:/Flite/archives/TrueFFS5/Src/FATFILT.C_V $
|
||
|
*
|
||
|
* Rev 1.10 Jan 17 2002 23:00:14 oris
|
||
|
* Changed debug print added \r.
|
||
|
*
|
||
|
* Rev 1.9 Sep 15 2001 23:45:50 oris
|
||
|
* Changed BIG_ENDIAN to FL_BIG_ENDIAN
|
||
|
*
|
||
|
* Rev 1.8 Jun 17 2001 16:39:10 oris
|
||
|
* Improved documentation and remove warnings.
|
||
|
*
|
||
|
* Rev 1.7 May 16 2001 21:17:18 oris
|
||
|
* Added the FL_ prefix to the following defines: MALLOC and FREE.
|
||
|
*
|
||
|
* Rev 1.6 May 01 2001 14:21:02 oris
|
||
|
* Remove warnings.
|
||
|
*
|
||
|
* Rev 1.5 Apr 30 2001 18:00:10 oris
|
||
|
* Added casting to remove warrnings.
|
||
|
*
|
||
|
* Rev 1.4 Apr 24 2001 17:07:32 oris
|
||
|
* Missing casting of MALLOC calls.
|
||
|
*
|
||
|
* Rev 1.3 Apr 10 2001 23:54:24 oris
|
||
|
* FL_MAX_DISKS_PER_SOCKET changed to MAX_TL_PARTITIONS.
|
||
|
*
|
||
|
* Rev 1.2 Apr 09 2001 15:00:42 oris
|
||
|
* Change static allocation to dynamic allocations.
|
||
|
* Renamed flffCheck back to ffCheckBeforeWrite to be backwards compatible with OSAK 4.2.
|
||
|
*
|
||
|
* Rev 1.1 Apr 01 2001 07:51:16 oris
|
||
|
* New implementation of fat filter.
|
||
|
*
|
||
|
* Rev 1.0 19 Feb 2001 21:14:14 andreyk
|
||
|
* Initial revision.
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Includes
|
||
|
*/
|
||
|
|
||
|
#include "fatfilt.h"
|
||
|
#include "blockdev.h"
|
||
|
#include "flflash.h"
|
||
|
#include "bddefs.h"
|
||
|
|
||
|
|
||
|
#if defined(ABS_READ_WRITE) && !defined(FL_READ_ONLY)
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Module configuration
|
||
|
*/
|
||
|
|
||
|
#define FL_INCLUDE_FAT_MONITOR /* undefine it to remove FAT filter code */
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Defines
|
||
|
*/
|
||
|
|
||
|
/* extract pointer to user's buffer from IOreq */
|
||
|
|
||
|
#ifdef SCATTER_GATHER
|
||
|
#define FLBUF(ioreq,i) (*((char FAR1 **)((ioreq)->irData) + (int)(i)))
|
||
|
#else
|
||
|
#define FLBUF(ioreq,i) ((char FAR1 *)(ioreq->irData) + (SECTOR_SIZE * ((int)(i))))
|
||
|
#endif
|
||
|
|
||
|
/* extract socket# and disk# from TFFS handle */
|
||
|
|
||
|
#define H2S(handle) (((int)(handle)) & 0xf)
|
||
|
#define H2D(handle) ((((int)(handle)) >> 4) & 0xf)
|
||
|
|
||
|
/* construct TFFS handle from socket# and disk# */
|
||
|
|
||
|
#define SD2H(socNo,diskNo) ((int)((((diskNo) & 0xf) << 4) | ((socNo) & 0xf)))
|
||
|
|
||
|
/* unformatted ("raw") disk partition */
|
||
|
|
||
|
#define FL_RAW_PART (-1)
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Local routines
|
||
|
*/
|
||
|
|
||
|
static FLStatus reset (void);
|
||
|
static FLStatus discardDisk (int handle);
|
||
|
static FLStatus newDisk (int handle);
|
||
|
static FLStatus parseDisk (int handle);
|
||
|
static FLStatus discardDiskParts (FLffDisk *pd);
|
||
|
static FLStatus addDiskPart (FLffDisk *pd, int partNo);
|
||
|
static FLStatus addNewDiskPart (FLffDisk *pd);
|
||
|
static FLBoolean isPartTableWrite (FLffDisk *pd, IOreq FAR2 *ioreq);
|
||
|
static FLStatus isExtPartPresent (char FAR1 *buf, SectorNo *nextExtPartSec);
|
||
|
|
||
|
|
||
|
#ifdef FL_INCLUDE_FAT_MONITOR
|
||
|
|
||
|
static FLStatus partEnableFF (FLffVol* pv);
|
||
|
static FLStatus partFreeDelClusters (FLffVol *pv, SectorNo secNo, char FAR1 *newFAT);
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Local data
|
||
|
*/
|
||
|
|
||
|
/* module reset flag */
|
||
|
|
||
|
static FLBoolean resetDone = FALSE;
|
||
|
|
||
|
/* disks (BDTL partitions in OSAK terminology) */
|
||
|
|
||
|
static FLffDisk* ffDisk[SOCKETS][MAX_TL_PARTITIONS] = { { NULL } };
|
||
|
|
||
|
|
||
|
#ifndef FL_MALLOC
|
||
|
|
||
|
/*
|
||
|
* WARNING: Large static arrays !
|
||
|
*
|
||
|
* sizeof(ffAllDisks[x][y]) is 64 bytes.
|
||
|
* sizeof(ffAllParts[x][y][z]) is 40 bytes.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
static FLffDisk ffAllDisks[SOCKETS][MAX_TL_PARTITIONS];
|
||
|
static FLffVol ffAllParts[SOCKETS][MAX_TL_PARTITIONS][FL_MAX_PARTS_PER_DISK];
|
||
|
|
||
|
#endif /* FL_MALLOC */
|
||
|
|
||
|
static const char zeroes[SECTOR_SIZE] = {0};
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* --------------------------------------------------------------------------- *
|
||
|
* *
|
||
|
* d i s c a r d D i s k P a r t s *
|
||
|
* *
|
||
|
* Discard all the partition info (if any) associated with particular disk. *
|
||
|
* *
|
||
|
* Parameters: *
|
||
|
* pd : disk (BDTL volume) *
|
||
|
* *
|
||
|
* Returns: *
|
||
|
* Always flOK. *
|
||
|
* *
|
||
|
* --------------------------------------------------------------------------- */
|
||
|
|
||
|
static FLStatus discardDiskParts ( FLffDisk * pd )
|
||
|
{
|
||
|
register int i;
|
||
|
|
||
|
if (pd != NULL) {
|
||
|
|
||
|
for (i = 0; i < FL_MAX_PARTS_PER_DISK; i++) {
|
||
|
|
||
|
#ifdef FL_MALLOC
|
||
|
if (pd->part[i] != NULL)
|
||
|
FL_FREE(pd->part[i]);
|
||
|
#endif
|
||
|
|
||
|
pd->part[i] = NULL;
|
||
|
}
|
||
|
|
||
|
pd->parts = 0;
|
||
|
}
|
||
|
|
||
|
return flOK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* --------------------------------------------------------------------------- *
|
||
|
* *
|
||
|
* a d d D i s k P a r t *
|
||
|
* *
|
||
|
* If there is partition record #partNo associated with the disk, discard *
|
||
|
* this info. Attach new partition record #partNo. *
|
||
|
* *
|
||
|
* Parameters: *
|
||
|
* pd : disk (BDTL volume) *
|
||
|
* partNo : partition (0 ... FL_MAX_PARTS_PER_DISK-1) *
|
||
|
* *
|
||
|
* Returns: *
|
||
|
* flOK if success, otherwise respective error code *
|
||
|
* *
|
||
|
* --------------------------------------------------------------------------- */
|
||
|
|
||
|
static FLStatus addDiskPart ( FLffDisk * pd,
|
||
|
int partNo )
|
||
|
{
|
||
|
FLffVol * pv;
|
||
|
FLStatus status;
|
||
|
int socNo, diskNo;
|
||
|
|
||
|
/* arg. sanity check */
|
||
|
|
||
|
if ((pd == NULL) || (partNo >= FL_MAX_PARTS_PER_DISK))
|
||
|
return flBadDriveHandle;
|
||
|
|
||
|
/* break TFFS handle into socket# and disk#, and do sanity check */
|
||
|
|
||
|
socNo = H2S(pd->handle);
|
||
|
diskNo = H2D(pd->handle);
|
||
|
|
||
|
if ((socNo >= SOCKETS) || (diskNo >= MAX_TL_PARTITIONS))
|
||
|
return flBadDriveHandle;
|
||
|
|
||
|
status = flNotEnoughMemory;
|
||
|
|
||
|
#ifdef FL_MALLOC
|
||
|
pv = (FLffVol *)FL_MALLOC( sizeof(FLffVol) );
|
||
|
#else
|
||
|
pv = &ffAllParts[socNo][diskNo][partNo];
|
||
|
#endif
|
||
|
|
||
|
if (pv != NULL) {
|
||
|
|
||
|
/* initialize fields in struct FLffDisk to safe values */
|
||
|
|
||
|
pv->handle = pd->handle;
|
||
|
pv->type = FL_RAW_PART;
|
||
|
pv->flags = 0;
|
||
|
pv->ffEnabled = FALSE; /* turn off FAT minitor */
|
||
|
pv->sectors = (SectorNo) 0;
|
||
|
pv->firstFATsecNo = (SectorNo) -1; /* none */
|
||
|
pv->lastFATsecNo = pv->firstFATsecNo; /* none */
|
||
|
pv->firstDataSecNo = (SectorNo) 0;
|
||
|
pv->clusterSize = (unsigned) 0;
|
||
|
|
||
|
#ifdef FL_MALLOC
|
||
|
if( pd->part[partNo] != NULL )
|
||
|
FL_FREE(pd->part[partNo]);
|
||
|
#endif
|
||
|
|
||
|
pd->part[partNo] = pv;
|
||
|
|
||
|
status = flOK;
|
||
|
}
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* --------------------------------------------------------------------------- *
|
||
|
* *
|
||
|
* a d d N e w D i s k P a r t *
|
||
|
* *
|
||
|
* Add one more partition record to the disk. *
|
||
|
* *
|
||
|
* Parameters: *
|
||
|
* pd : disk (BDTL volume) *
|
||
|
* *
|
||
|
* Returns: *
|
||
|
* flOK if success, otherwise respective error code *
|
||
|
* *
|
||
|
* --------------------------------------------------------------------------- */
|
||
|
|
||
|
static FLStatus addNewDiskPart ( FLffDisk * pd )
|
||
|
{
|
||
|
if (pd->parts < FL_MAX_PARTS_PER_DISK) {
|
||
|
|
||
|
checkStatus( addDiskPart (pd, pd->parts) );
|
||
|
pd->parts++;
|
||
|
}
|
||
|
|
||
|
return flOK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* --------------------------------------------------------------------------- *
|
||
|
* *
|
||
|
* d i s c a r d D i s k *
|
||
|
* *
|
||
|
* Remove disk record (with all the associated partition records). *
|
||
|
* *
|
||
|
* Parameters: *
|
||
|
* handle : TFFS handle *
|
||
|
* *
|
||
|
* Returns: *
|
||
|
* flOK if success, otherwise respective error code *
|
||
|
* *
|
||
|
* --------------------------------------------------------------------------- */
|
||
|
|
||
|
static FLStatus discardDisk ( int handle )
|
||
|
{
|
||
|
int socNo, diskNo;
|
||
|
|
||
|
/* break TFFS handle into socket# and disk#, and do sanity check */
|
||
|
|
||
|
socNo = H2S(handle);
|
||
|
diskNo = H2D(handle);
|
||
|
|
||
|
if ((socNo >= SOCKETS) || (diskNo >= MAX_TL_PARTITIONS))
|
||
|
return flBadDriveHandle;
|
||
|
|
||
|
if( ffDisk[socNo][diskNo] != NULL ) {
|
||
|
|
||
|
/* discard associated partition info */
|
||
|
|
||
|
(void) discardDiskParts( ffDisk[socNo][diskNo] );
|
||
|
|
||
|
#ifdef FL_MALLOC
|
||
|
|
||
|
/* release disk's scratch buffer */
|
||
|
|
||
|
if( (ffDisk[socNo][diskNo])->buf != NULL)
|
||
|
FL_FREE( (ffDisk[socNo][diskNo])->buf );
|
||
|
|
||
|
FL_FREE( ffDisk[socNo][diskNo] );
|
||
|
|
||
|
#endif
|
||
|
|
||
|
ffDisk[socNo][diskNo] = NULL;
|
||
|
}
|
||
|
|
||
|
return flOK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* --------------------------------------------------------------------------- *
|
||
|
* *
|
||
|
* n e w D i s k *
|
||
|
* *
|
||
|
* Discard existing disk record (if any), and create new one. *
|
||
|
* *
|
||
|
* Parameters: *
|
||
|
* handle : TFFS handle *
|
||
|
* *
|
||
|
* Returns: *
|
||
|
* flOK if success, otherwise respective error code *
|
||
|
* *
|
||
|
* --------------------------------------------------------------------------- */
|
||
|
|
||
|
static FLStatus newDisk ( int handle )
|
||
|
{
|
||
|
int socNo, diskNo;
|
||
|
int i;
|
||
|
FLffDisk * pd;
|
||
|
|
||
|
/* break TFFS handle into socket# and disk#, and do sanity check */
|
||
|
|
||
|
socNo = H2S(handle);
|
||
|
diskNo = H2D(handle);
|
||
|
|
||
|
if ((socNo >= SOCKETS) || (diskNo >= MAX_TL_PARTITIONS))
|
||
|
return flBadDriveHandle;
|
||
|
|
||
|
/* discard current disk and associated partition info (if any) */
|
||
|
|
||
|
checkStatus( discardDisk(handle) );
|
||
|
|
||
|
#ifdef FL_MALLOC
|
||
|
|
||
|
pd = (FLffDisk *) FL_MALLOC( sizeof(FLffDisk) );
|
||
|
|
||
|
if (pd == NULL)
|
||
|
return flNotEnoughMemory;
|
||
|
|
||
|
/* allocate and attach disk's scratch buffer */
|
||
|
|
||
|
pd->buf = (char *)FL_MALLOC( SECTOR_SIZE );
|
||
|
|
||
|
if (pd->buf == NULL) {
|
||
|
|
||
|
FL_FREE (pd);
|
||
|
return flNotEnoughMemory;
|
||
|
}
|
||
|
|
||
|
#else /* !FL_MALLOC */
|
||
|
|
||
|
pd = &ffAllDisks[socNo][diskNo];
|
||
|
|
||
|
#endif /* FL_MALLOC */
|
||
|
|
||
|
|
||
|
pd->handle = handle;
|
||
|
pd->ffstate = flStateNotInitialized;
|
||
|
|
||
|
/* don't know partition layout yet */
|
||
|
|
||
|
pd->parts = 0;
|
||
|
for (i = 0; i < FL_MAX_PARTS_PER_DISK; i++)
|
||
|
pd->part[i] = NULL;
|
||
|
|
||
|
/* watch Master Boot Record for update */
|
||
|
|
||
|
pd->secToWatch = (SectorNo) 0;
|
||
|
|
||
|
ffDisk[socNo][diskNo] = pd;
|
||
|
|
||
|
return flOK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* --------------------------------------------------------------------------- *
|
||
|
* *
|
||
|
* i s P a r t T a b l e W r i t e *
|
||
|
* *
|
||
|
* Check if any of the sectors specified by 'ioreq' points to Master Boot *
|
||
|
* Record or next extended partition in the extended partitions list. *
|
||
|
* *
|
||
|
* Parameters: *
|
||
|
* pd : pointer to disk structure *
|
||
|
* ioreq : standard I/O request *
|
||
|
* *
|
||
|
* Returns: *
|
||
|
* TRUE if write to MBR or extended partition list is detected, otherwise *
|
||
|
* FALSE *
|
||
|
* *
|
||
|
* --------------------------------------------------------------------------- */
|
||
|
|
||
|
static FLBoolean isPartTableWrite ( FLffDisk * pd,
|
||
|
IOreq FAR2 * ioreq )
|
||
|
{
|
||
|
register long i;
|
||
|
|
||
|
if (pd != NULL) {
|
||
|
|
||
|
for (i = (long)0; i < ioreq->irSectorCount; i++) {
|
||
|
|
||
|
if( (ioreq->irSectorNo + i) == (long)pd->secToWatch )
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* --------------------------------------------------------------------------- *
|
||
|
* *
|
||
|
* i s E x t P a r t P r e s e n t *
|
||
|
* *
|
||
|
* Check if extended partition persent in the partition table. If it is, *
|
||
|
* calculate the sector # where next partition table will be written to. *
|
||
|
* *
|
||
|
* Parameters: *
|
||
|
* buf : partition table *
|
||
|
* nextExtPartSec : sector where next partition table will be written to *
|
||
|
* *
|
||
|
* Returns: *
|
||
|
* flOK on success, otherwise error code *
|
||
|
* *
|
||
|
* --------------------------------------------------------------------------- */
|
||
|
|
||
|
static FLStatus isExtPartPresent ( char FAR1 * buf,
|
||
|
SectorNo * nextExtPartSec )
|
||
|
{
|
||
|
Partition FAR1 * p;
|
||
|
register int i;
|
||
|
|
||
|
/* does it look like partition table ? */
|
||
|
|
||
|
if (LE2(((PartitionTable FAR1 *) buf)->signature) != PARTITION_SIGNATURE)
|
||
|
return flBadFormat;
|
||
|
|
||
|
/* if extended. part. present, get sector# that will contain next part. in list */
|
||
|
|
||
|
p = &( ((PartitionTable FAR1 *) buf)->ptEntry[0] );
|
||
|
|
||
|
for (i = 0; i < FL_PART_TBL_ENTRIES; i++, p++) {
|
||
|
|
||
|
if (p->type == EX_PARTIT) {
|
||
|
|
||
|
*nextExtPartSec = (SectorNo) UNAL4( (void *) p[i].startingSectorOfPartition );
|
||
|
return flOK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* no extended partition found */
|
||
|
|
||
|
return flFileNotFound;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* --------------------------------------------------------------------------- *
|
||
|
* *
|
||
|
* r e s e t *
|
||
|
* *
|
||
|
* Resets this software module to it's initial state upon boot. *
|
||
|
* *
|
||
|
* Parameters: *
|
||
|
* none *
|
||
|
* *
|
||
|
* Returns: *
|
||
|
* flOK in case of success, otherwise respective error code *
|
||
|
* *
|
||
|
* --------------------------------------------------------------------------- */
|
||
|
|
||
|
static FLStatus reset (void)
|
||
|
{
|
||
|
int iSoc, iDisk;
|
||
|
|
||
|
for (iSoc = 0; iSoc < SOCKETS; iSoc++) {
|
||
|
|
||
|
/* discard existing disk structures for that socket */
|
||
|
|
||
|
for (iDisk = 0; iDisk < MAX_TL_PARTITIONS; iDisk++)
|
||
|
(void) discardDisk( SD2H(iSoc, iDisk) );
|
||
|
|
||
|
/* pre-allocate disk structure for first disk of every socket */
|
||
|
|
||
|
checkStatus( newDisk(SD2H(iSoc, 0)) );
|
||
|
}
|
||
|
|
||
|
resetDone = TRUE;
|
||
|
|
||
|
return flOK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* --------------------------------------------------------------------------- *
|
||
|
* *
|
||
|
* p a r s e D i s k *
|
||
|
* *
|
||
|
* Read partition table(s), install and enable FAT filters on all FAT12/16 *
|
||
|
* partitions. *
|
||
|
* *
|
||
|
* Parameters: *
|
||
|
* handle : TFFS handle *
|
||
|
* *
|
||
|
* Returns: *
|
||
|
* flOK on success, otherwise error code *
|
||
|
* *
|
||
|
* NOTE: This routine uses disk's scratch buffer. *
|
||
|
* *
|
||
|
* --------------------------------------------------------------------------- */
|
||
|
|
||
|
static FLStatus parseDisk ( int handle )
|
||
|
{
|
||
|
int socNo, diskNo;
|
||
|
SectorNo extPartStartSec, sec;
|
||
|
int i, depth;
|
||
|
int type;
|
||
|
FLffDisk * pd;
|
||
|
FLffVol * pv;
|
||
|
Partition * pp;
|
||
|
IOreq ioreq;
|
||
|
|
||
|
#ifdef FL_MALLOC
|
||
|
char * buf;
|
||
|
#else
|
||
|
char buf[SECTOR_SIZE];
|
||
|
#endif
|
||
|
|
||
|
/* break TFFS handle into socket# and disk#, and do sanity check */
|
||
|
|
||
|
socNo = H2S(handle);
|
||
|
diskNo = H2D(handle);
|
||
|
|
||
|
if ((socNo >= ((int) noOfSockets)) || (diskNo >= MAX_TL_PARTITIONS))
|
||
|
return flBadDriveHandle;
|
||
|
|
||
|
/* if disk structure hasn't been allocated yet, do it now */
|
||
|
|
||
|
if (ffDisk[socNo][diskNo] == NULL)
|
||
|
checkStatus( newDisk(handle) );
|
||
|
|
||
|
pd = ffDisk[socNo][diskNo];
|
||
|
|
||
|
#ifdef FL_MALLOC
|
||
|
|
||
|
/* make sure scratch buffer is available */
|
||
|
|
||
|
if (pd->buf == NULL)
|
||
|
return flBufferingError;
|
||
|
|
||
|
buf = pd->buf;
|
||
|
|
||
|
#endif /* FL_MALLOC */
|
||
|
|
||
|
/* discard obsolete disk's partition info */
|
||
|
|
||
|
(void) discardDiskParts (pd);
|
||
|
|
||
|
/* read Master Boot Record */
|
||
|
|
||
|
ioreq.irHandle = handle;
|
||
|
ioreq.irSectorNo = (SectorNo) 0;
|
||
|
ioreq.irSectorCount = (SectorNo) 1;
|
||
|
ioreq.irData = (void FAR1 *) buf;
|
||
|
checkStatus( flAbsRead(&ioreq) );
|
||
|
|
||
|
/* is it MBR indeed ? */
|
||
|
|
||
|
if (LE2(((PartitionTable *) buf)->signature) != PARTITION_SIGNATURE)
|
||
|
return flPartitionNotFound;
|
||
|
|
||
|
/* do primary partitions only (we will do extended partitions later) */
|
||
|
|
||
|
pp = &( ((PartitionTable *) buf)->ptEntry[0] );
|
||
|
|
||
|
for (i = 0; i < FL_PART_TBL_ENTRIES; i++, pp++) {
|
||
|
|
||
|
if( pp->type == ((char)0) ) /* skip empty slot */
|
||
|
continue;
|
||
|
|
||
|
if( pp->type == ((char)EX_PARTIT) ) /* skip extended partition */
|
||
|
continue;
|
||
|
|
||
|
/* primary partition found (not necessarily FAT12/16) */
|
||
|
|
||
|
if( addNewDiskPart(pd) != flOK )
|
||
|
break;
|
||
|
|
||
|
pv = pd->part[pd->parts - 1];
|
||
|
|
||
|
/* remember partition's type, and where it starts */
|
||
|
|
||
|
pv->type = (int) pp->type;
|
||
|
pv->startSecNo = (SectorNo) UNAL4( (void *) pp->startingSectorOfPartition );
|
||
|
}
|
||
|
|
||
|
/* do extended partitions in depth */
|
||
|
|
||
|
for (i = 0; i < FL_PART_TBL_ENTRIES; i++) {
|
||
|
|
||
|
/* re-read Master Boot Record */
|
||
|
|
||
|
ioreq.irHandle = handle;
|
||
|
ioreq.irSectorNo = (SectorNo) 0;
|
||
|
ioreq.irSectorCount = (SectorNo) 1;
|
||
|
ioreq.irData = (void FAR1 *) buf;
|
||
|
checkStatus( flAbsRead(&ioreq) );
|
||
|
|
||
|
/* is it MBR indeed ? */
|
||
|
|
||
|
if (LE2(((PartitionTable *) buf)->signature) != PARTITION_SIGNATURE)
|
||
|
return flOK;
|
||
|
|
||
|
/* pick up next extended partition in MBR */
|
||
|
|
||
|
pp = &( ((PartitionTable *) buf)->ptEntry[i] );
|
||
|
|
||
|
if( pp->type == ((char)EX_PARTIT) ) {
|
||
|
|
||
|
/* remember where extended partition starts */
|
||
|
|
||
|
extPartStartSec = (SectorNo) UNAL4( (void *) pp->startingSectorOfPartition );
|
||
|
|
||
|
/* follow the list of partition tables */
|
||
|
|
||
|
sec = extPartStartSec;
|
||
|
|
||
|
for (depth = 0; depth < MAX_PARTITION_DEPTH; depth++) {
|
||
|
|
||
|
/* read next partition table in the list */
|
||
|
|
||
|
ioreq.irHandle = handle;
|
||
|
ioreq.irSectorNo = sec;
|
||
|
ioreq.irSectorCount = (SectorNo) 1;
|
||
|
ioreq.irData = (void FAR1 *) buf;
|
||
|
checkStatus( flAbsRead(&ioreq) );
|
||
|
|
||
|
/* is it valid partition table ? */
|
||
|
|
||
|
if (LE2(((PartitionTable *) buf)->signature) != PARTITION_SIGNATURE)
|
||
|
break;
|
||
|
|
||
|
/* if 1st entry is zero, it's the end of part. table list */
|
||
|
|
||
|
pp = &( ((PartitionTable *) buf)->ptEntry[0] );
|
||
|
if( pp->type == ((char)0) )
|
||
|
break;
|
||
|
|
||
|
/* Take this partition. Remember it's type, and where it starts */
|
||
|
|
||
|
if( addNewDiskPart(pd) != flOK )
|
||
|
break;
|
||
|
|
||
|
pv = pd->part[pd->parts - 1];
|
||
|
|
||
|
pv->type = (int) pp->type;
|
||
|
pv->startSecNo =
|
||
|
(SectorNo) UNAL4( (void *) pp->startingSectorOfPartition) + sec;
|
||
|
|
||
|
/* 2nd entry must be extended partition */
|
||
|
|
||
|
pp = &( ((PartitionTable *) buf)->ptEntry[1] );
|
||
|
if( pp->type != ((char)EX_PARTIT) )
|
||
|
break;
|
||
|
|
||
|
/* sector where next part. table in the list resides */
|
||
|
|
||
|
sec = extPartStartSec +
|
||
|
(SectorNo) UNAL4( (void *) pp->startingSectorOfPartition );
|
||
|
|
||
|
} /* for(depth) */
|
||
|
}
|
||
|
} /* for(i) */
|
||
|
|
||
|
#ifdef FL_INCLUDE_FAT_MONITOR
|
||
|
|
||
|
/* turn on FAT filters on FAT12/16 partition(s) */
|
||
|
|
||
|
if (pd->parts > 0) {
|
||
|
|
||
|
for (i = 0; i < pd->parts; i++) {
|
||
|
|
||
|
pv = pd->part[i];
|
||
|
type = pv->type;
|
||
|
|
||
|
/*
|
||
|
* WARNING : Routine partEnableFF() uses disk's scratch buffer !
|
||
|
*/
|
||
|
|
||
|
if((type == FAT12_PARTIT) || (type == FAT16_PARTIT) || (type == DOS4_PARTIT))
|
||
|
partEnableFF (pv);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif /* FL_INCLUDE_FAT_MONITOR */
|
||
|
|
||
|
/* watch for MBR (sector #0) update */
|
||
|
|
||
|
pd->secToWatch = (SectorNo) 0;
|
||
|
|
||
|
pd->ffstate = flStateInitialized;
|
||
|
|
||
|
return flOK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef FL_INCLUDE_FAT_MONITOR
|
||
|
|
||
|
/* --------------------------------------------------------------------------- *
|
||
|
* *
|
||
|
* p a r t E n a b l e F F *
|
||
|
* *
|
||
|
* Installs and enables FAT filter on partition. *
|
||
|
* *
|
||
|
* Parameters: *
|
||
|
* pv : disk partition (filesystem volume) *
|
||
|
* *
|
||
|
* Returns: *
|
||
|
* flOK on success, otherwise error code *
|
||
|
* *
|
||
|
* NOTE: This routine uses disk's scratch buffer. *
|
||
|
* *
|
||
|
* --------------------------------------------------------------------------- */
|
||
|
|
||
|
static FLStatus partEnableFF ( FLffVol * pv )
|
||
|
{
|
||
|
int socNo, diskNo;
|
||
|
FLffDisk * pd;
|
||
|
BPB * bpb;
|
||
|
SectorNo sectors;
|
||
|
SectorNo rootDirSecNo;
|
||
|
SectorNo rootDirSectors;
|
||
|
SectorNo sectorsPerFAT;
|
||
|
unsigned maxCluster;
|
||
|
int partNo;
|
||
|
IOreq ioreq;
|
||
|
|
||
|
#ifdef FL_MALLOC
|
||
|
char * buf;
|
||
|
#else
|
||
|
char buf[SECTOR_SIZE];
|
||
|
#endif
|
||
|
|
||
|
/* arg. sanity check */
|
||
|
|
||
|
if (pv == NULL)
|
||
|
return flBadDriveHandle;
|
||
|
|
||
|
/* break TFFS handle into socket# and disk#, and do sanity check */
|
||
|
|
||
|
socNo = H2S(pv->handle);
|
||
|
diskNo = H2D(pv->handle);
|
||
|
|
||
|
if ((socNo >= ((int) noOfSockets)) || (diskNo >= MAX_TL_PARTITIONS))
|
||
|
return flBadDriveHandle;
|
||
|
|
||
|
/* check if 'pv' belongs to this disk */
|
||
|
|
||
|
pd = ffDisk[socNo][diskNo];
|
||
|
|
||
|
if (pd == NULL)
|
||
|
return flBadDriveHandle;
|
||
|
|
||
|
for (partNo = 0; partNo < pd->parts; partNo++) {
|
||
|
|
||
|
if (pd->part[partNo] == pv)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (partNo >= pd->parts)
|
||
|
return flBadDriveHandle;
|
||
|
|
||
|
#ifdef FL_MALLOC
|
||
|
|
||
|
/* make sure scratch buffer is available */
|
||
|
|
||
|
if (pd->buf == NULL)
|
||
|
return flBufferingError;
|
||
|
|
||
|
buf = pd->buf;
|
||
|
|
||
|
#endif /* FL_MALLOC */
|
||
|
|
||
|
/* make sure FAT filter is off on this partition */
|
||
|
|
||
|
pv->ffEnabled = FALSE;
|
||
|
|
||
|
pv->firstFATsecNo = (SectorNo) -1;
|
||
|
pv->lastFATsecNo = pv->firstFATsecNo;
|
||
|
pv->clusterSize = (unsigned) 0;
|
||
|
|
||
|
/* read the BPB */
|
||
|
|
||
|
ioreq.irHandle = pv->handle;
|
||
|
ioreq.irSectorNo = pv->startSecNo;
|
||
|
ioreq.irSectorCount = (SectorNo) 1;
|
||
|
ioreq.irData = (void FAR1 *) buf;
|
||
|
checkStatus( flAbsRead(&ioreq) );
|
||
|
|
||
|
/* Does it look like DOS bootsector ? */
|
||
|
|
||
|
bpb = &( ((DOSBootSector *) buf)->bpb );
|
||
|
|
||
|
if( !((bpb->jumpInstruction[0] == 0xe9)
|
||
|
||
|
||
|
((bpb->jumpInstruction[0] == 0xeb) && (bpb->jumpInstruction[2] == 0x90)))) {
|
||
|
|
||
|
return flNonFATformat;
|
||
|
}
|
||
|
|
||
|
/* Do we handle this sector size ? */
|
||
|
|
||
|
if (UNAL2(bpb->bytesPerSector) != SECTOR_SIZE)
|
||
|
return flFormatNotSupported;
|
||
|
|
||
|
/*
|
||
|
* Is it a bogus BPB (leftover from previous disk partitioning) ?
|
||
|
* Check that there is no overlap with next partition (if one exists).
|
||
|
*/
|
||
|
|
||
|
sectors = UNAL2(bpb->totalSectorsInVolumeDOS3);
|
||
|
if (sectors == (SectorNo)0)
|
||
|
sectors = (SectorNo) LE4(bpb->totalSectorsInVolume);
|
||
|
|
||
|
if ((partNo+1 < pd->parts) && (pd->part[partNo+1] != NULL)) {
|
||
|
|
||
|
if( sectors > (pd->part[partNo+1])->startSecNo - pv->startSecNo )
|
||
|
return flNonFATformat;
|
||
|
}
|
||
|
|
||
|
/* number of sectors in partition as reported by BPB */
|
||
|
|
||
|
pv->sectors = sectors;
|
||
|
|
||
|
/* valid BPB; get the rest of partition info from it */
|
||
|
|
||
|
pv->firstFATsecNo = pv->startSecNo + (SectorNo)( LE2(bpb->reservedSectors) );
|
||
|
sectorsPerFAT = (SectorNo) LE2(bpb->sectorsPerFAT);
|
||
|
pv->lastFATsecNo = pv->firstFATsecNo + sectorsPerFAT - (SectorNo)1;
|
||
|
rootDirSecNo = pv->firstFATsecNo + (sectorsPerFAT * bpb->noOfFATS);
|
||
|
rootDirSectors = (SectorNo)1 + (SectorNo)
|
||
|
(((UNAL2(bpb->rootDirectoryEntries) * DIRECTORY_ENTRY_SIZE) - 1) / SECTOR_SIZE);
|
||
|
pv->firstDataSecNo = rootDirSecNo + rootDirSectors;
|
||
|
|
||
|
pv->clusterSize = bpb->sectorsPerCluster;
|
||
|
|
||
|
/* decide which type of FAT is it */
|
||
|
|
||
|
maxCluster = (unsigned)1 + (unsigned)
|
||
|
((pv->sectors - (pv->firstDataSecNo - pv->startSecNo)) / pv->clusterSize);
|
||
|
|
||
|
if (maxCluster < 4085) {
|
||
|
pv->flags |= VOLUME_12BIT_FAT; /* 12-bit FAT */
|
||
|
|
||
|
#ifndef FAT_12BIT
|
||
|
DEBUG_PRINT(("Debug: FAT_12BIT must be defined.\r\n"));
|
||
|
return flFormatNotSupported;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/* turn on FAT filter on this partition */
|
||
|
|
||
|
pv->ffEnabled = TRUE;
|
||
|
|
||
|
return flOK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* --------------------------------------------------------------------------- *
|
||
|
* *
|
||
|
* p a r t F r e e D e l C l u s t e r s *
|
||
|
* *
|
||
|
* Compare the new contents of the specified FAT sector against the old *
|
||
|
* one on the disk. If any freed clusters are found, issue 'sector delete' *
|
||
|
* calls for all sectors that are occupied by these freed clusters. *
|
||
|
* *
|
||
|
* Parameters: *
|
||
|
* pv : disk partition (filesystem volume) *
|
||
|
* secNo : abs. sector # of the FAT sector *
|
||
|
* newFAT : new contents of this FAT sector *
|
||
|
* *
|
||
|
* Returns: *
|
||
|
* flOK on success, otherwise error code *
|
||
|
* *
|
||
|
* NOTE: This routine uses disk's scratch buffer. *
|
||
|
* *
|
||
|
* --------------------------------------------------------------------------- */
|
||
|
|
||
|
static FLStatus partFreeDelClusters ( FLffVol * pv,
|
||
|
SectorNo secNo,
|
||
|
char FAR1 * newFAT)
|
||
|
{
|
||
|
FLffDisk * pd;
|
||
|
int socNo, diskNo;
|
||
|
unsigned short oldFATentry, newFATentry;
|
||
|
SectorNo iSec;
|
||
|
unsigned firstCluster;
|
||
|
IOreq ioreq;
|
||
|
int offset;
|
||
|
int iPart;
|
||
|
|
||
|
#ifdef FAT_12BIT
|
||
|
int halfBytes;
|
||
|
#endif
|
||
|
|
||
|
#ifdef FL_MALLOC
|
||
|
char * oldFAT;
|
||
|
#else
|
||
|
char oldFAT[SECTOR_SIZE];
|
||
|
#endif
|
||
|
|
||
|
/* arg. sanity check */
|
||
|
|
||
|
if (pv == NULL)
|
||
|
return flBadDriveHandle;
|
||
|
|
||
|
/* break TFFS handle into socket# and disk#, and do sanity check */
|
||
|
|
||
|
socNo = H2S(pv->handle);
|
||
|
diskNo = H2D(pv->handle);
|
||
|
|
||
|
if ((socNo >= ((int) noOfSockets)) || (diskNo >= MAX_TL_PARTITIONS))
|
||
|
return flBadDriveHandle;
|
||
|
|
||
|
/* check if 'pv' belongs to this disk */
|
||
|
|
||
|
pd = ffDisk[socNo][diskNo];
|
||
|
|
||
|
if (pd == NULL)
|
||
|
return flBadDriveHandle;
|
||
|
|
||
|
for (iPart = 0; iPart < pd->parts; iPart++) {
|
||
|
|
||
|
if (pd->part[iPart] == pv)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (iPart >= pd->parts)
|
||
|
return flBadDriveHandle;
|
||
|
|
||
|
#ifdef FL_MALLOC
|
||
|
|
||
|
/* make sure scratch buffer is available */
|
||
|
|
||
|
if (pd->buf == NULL)
|
||
|
return flBufferingError;
|
||
|
|
||
|
oldFAT = pd->buf;
|
||
|
|
||
|
#endif /* FL_MALLOC */
|
||
|
|
||
|
/* read in the FAT sector from the disk */
|
||
|
|
||
|
ioreq.irHandle = pv->handle;
|
||
|
ioreq.irSectorNo = secNo;
|
||
|
ioreq.irSectorCount = 1;
|
||
|
ioreq.irData = (void FAR1 *) oldFAT;
|
||
|
checkStatus( flAbsRead(&ioreq) );
|
||
|
|
||
|
#ifdef FAT_12BIT
|
||
|
|
||
|
/* size of FAT entry in half-bytes */
|
||
|
|
||
|
halfBytes = ((pv->flags & VOLUME_12BIT_FAT) ? 3 : 4);
|
||
|
|
||
|
/* starting cluster */
|
||
|
|
||
|
if (halfBytes == 3) {
|
||
|
|
||
|
firstCluster =
|
||
|
((((unsigned)(secNo - pv->firstFATsecNo)) * (2 * SECTOR_SIZE)) + 2) / 3;
|
||
|
}
|
||
|
else {
|
||
|
firstCluster = ((unsigned)(secNo - pv->firstFATsecNo)) * (SECTOR_SIZE / 2);
|
||
|
}
|
||
|
|
||
|
/* staring data sector */
|
||
|
|
||
|
iSec = (((SectorNo)firstCluster - 2) * pv->clusterSize) + pv->firstDataSecNo;
|
||
|
|
||
|
offset = (firstCluster * ((unsigned) halfBytes)) & ((2 * SECTOR_SIZE) - 1);
|
||
|
|
||
|
/*
|
||
|
* Find if any clusters were logically deleted, and if so, delete them.
|
||
|
*
|
||
|
* NOTE: We are skipping over 12-bit FAT entries which span more than
|
||
|
* one sector.
|
||
|
*/
|
||
|
|
||
|
for (; offset < ((2 * SECTOR_SIZE) - 2);
|
||
|
offset += halfBytes, iSec += pv->clusterSize) {
|
||
|
|
||
|
#ifdef FL_BIG_ENDIAN
|
||
|
oldFATentry = LE2( *(LEushort FAR0 *)(oldFAT + (offset / 2)) );
|
||
|
newFATentry = LE2( *(LEushort FAR1 *)(newFAT + (offset / 2)) );
|
||
|
#else
|
||
|
oldFATentry = UNAL2( *(Unaligned FAR0 *)(oldFAT + (offset / 2)) );
|
||
|
newFATentry = UNAL2( *(Unaligned FAR1 *)(newFAT + (offset / 2)) );
|
||
|
#endif /* FL_BIG_ENDIAN */
|
||
|
|
||
|
if (offset & 1) {
|
||
|
oldFATentry >>= 4;
|
||
|
newFATentry >>= 4;
|
||
|
}
|
||
|
else {
|
||
|
if (halfBytes == 3) {
|
||
|
oldFATentry &= 0xfff;
|
||
|
newFATentry &= 0xfff;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#else /* !FAT_12BIT */
|
||
|
|
||
|
firstCluster = ((unsigned) (secNo - pv->firstFATsecNo) * (SECTOR_SIZE / 2));
|
||
|
iSec = pv->firstDataSecNo +
|
||
|
(((SectorNo)(firstCluster - (unsigned)2)) * pv->clusterSize);
|
||
|
|
||
|
/* Find if any clusters were logically deleted, and if so, delete them */
|
||
|
|
||
|
for (offset = 0; offset < SECTOR_SIZE; offset += 2, iSec += pv->clusterSize) {
|
||
|
|
||
|
oldFATentry = LE2( *(LEushort FAR0 *)(oldFAT + offset) );
|
||
|
newFATentry = LE2( *(LEushort FAR1 *)(newFAT + offset) );
|
||
|
|
||
|
#endif /* FAT_12BIT */
|
||
|
|
||
|
if ((oldFATentry != FAT_FREE) && (newFATentry == FAT_FREE)) {
|
||
|
|
||
|
ioreq.irHandle = pv->handle;
|
||
|
ioreq.irSectorNo = iSec;
|
||
|
ioreq.irSectorCount = pv->clusterSize;
|
||
|
checkStatus( flAbsDelete(&ioreq) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return flOK;
|
||
|
}
|
||
|
|
||
|
#endif /* FL_INCLUDE_FAT_MONITOR */
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* --------------------------------------------------------------------------- *
|
||
|
* *
|
||
|
* f f C h e c k B e f o r e W r i t e *
|
||
|
* *
|
||
|
* Catch all the FAT updates. Detect disk partitioning operation, track it *
|
||
|
* to completion, re-read partition tables, and re-install FAT filters on *
|
||
|
* all FAT12/16 partitions. *
|
||
|
* *
|
||
|
* Parameters: *
|
||
|
* ioreq : standard I/O request to be checked *
|
||
|
* *
|
||
|
* Returns: *
|
||
|
* flOK on success, otherwise error code *
|
||
|
* *
|
||
|
* --------------------------------------------------------------------------- */
|
||
|
|
||
|
FLStatus ffCheckBeforeWrite ( IOreq FAR2 * ioreq )
|
||
|
{
|
||
|
int socNo, diskNo;
|
||
|
FLffDisk * pd;
|
||
|
FLffVol * pv;
|
||
|
long iSec;
|
||
|
int iPart;
|
||
|
IOreq ioreq2;
|
||
|
char FAR1 * usrBuf;
|
||
|
|
||
|
/* if module hasn't been reset yet, do it now */
|
||
|
|
||
|
if (resetDone == FALSE)
|
||
|
(void) reset();
|
||
|
|
||
|
/* break TFFS handle into socket# and disk#, and do sanity check */
|
||
|
|
||
|
socNo = H2S(ioreq->irHandle);
|
||
|
diskNo = H2D(ioreq->irHandle);
|
||
|
|
||
|
if ((socNo >= ((int) noOfSockets)) || (diskNo >= MAX_TL_PARTITIONS))
|
||
|
return flBadDriveHandle;
|
||
|
|
||
|
/* if disk structure hasn't been allocated yet, do it now */
|
||
|
|
||
|
if (ffDisk[socNo][diskNo] == NULL)
|
||
|
checkStatus( newDisk((int)ioreq->irHandle) );
|
||
|
|
||
|
pd = ffDisk[socNo][diskNo];
|
||
|
|
||
|
/* read partition table(s) and install FAT filters is needed */
|
||
|
|
||
|
if (pd->ffstate == flStateNotInitialized)
|
||
|
checkStatus( parseDisk((int)ioreq->irHandle) );
|
||
|
|
||
|
/* catch writes to MBR, and track the whole disk partitioning operations */
|
||
|
|
||
|
while( isPartTableWrite(pd, ioreq) == TRUE ) {
|
||
|
|
||
|
/* disk re-partitioning is in progress */
|
||
|
|
||
|
if( pd->secToWatch == (SectorNo)0 ) {
|
||
|
|
||
|
/* it's write to MBR, so trash BPBs in all disk's partitions */
|
||
|
|
||
|
if (pd->parts > 0) {
|
||
|
|
||
|
for (iPart = 0; iPart < pd->parts; iPart++) {
|
||
|
|
||
|
ioreq2.irHandle = ioreq->irHandle;
|
||
|
ioreq2.irSectorNo = (pd->part[iPart])->startSecNo;
|
||
|
ioreq2.irSectorCount = (SectorNo) 1;
|
||
|
ioreq2.irData = (void FAR1 *) zeroes;
|
||
|
(void) flAbsWrite(&ioreq2);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* keep FAT filters disabled while disk partitioning is in progress */
|
||
|
|
||
|
pd->ffstate = flStateInitInProgress;
|
||
|
|
||
|
/* partition table which is about to be written to disk */
|
||
|
|
||
|
usrBuf = FLBUF( ioreq, (pd->secToWatch - ioreq->irSectorNo) );
|
||
|
|
||
|
switch( isExtPartPresent(usrBuf, &(pd->secToWatch)) ) {
|
||
|
|
||
|
case flOK:
|
||
|
|
||
|
/*
|
||
|
* Found valid partition table with extended partition.
|
||
|
* The pd->secToWatch has been updated to point to the
|
||
|
* sector where next partition table will be written to.
|
||
|
*/
|
||
|
continue;
|
||
|
|
||
|
case flFileNotFound:
|
||
|
|
||
|
/*
|
||
|
* Valid partition table, but no extended partition in it.
|
||
|
* Partitioning has been completed. Set pd->ffstate to
|
||
|
* 'flStateNotInitialized' to initiate parsing of partition
|
||
|
* table(s) and FAT filter installation next time this routine
|
||
|
* is called.
|
||
|
*/
|
||
|
|
||
|
pd->ffstate = flStateNotInitialized;
|
||
|
break;
|
||
|
|
||
|
case flBadFormat:
|
||
|
default:
|
||
|
|
||
|
/* No valid partition table. */
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return flOK;
|
||
|
}
|
||
|
|
||
|
#ifdef FL_INCLUDE_FAT_MONITOR
|
||
|
|
||
|
/* check for FAT update */
|
||
|
|
||
|
if (pd->ffstate == flStateInitialized) {
|
||
|
|
||
|
/* NOTE: We can handle 'write' request that spans disk partition boundaries */
|
||
|
|
||
|
for (iSec = ioreq->irSectorNo;
|
||
|
iSec < (ioreq->irSectorNo + ioreq->irSectorCount); iSec++) {
|
||
|
|
||
|
for (iPart = 0; iPart < pd->parts; iPart++) {
|
||
|
|
||
|
pv = pd->part[iPart];
|
||
|
|
||
|
/* we monitor only FAT12/16 partitions */
|
||
|
|
||
|
if ((pv->type != FAT12_PARTIT) && (pv->type != FAT16_PARTIT) &&
|
||
|
(pv->type != DOS4_PARTIT))
|
||
|
continue;
|
||
|
|
||
|
/* FAT filters can be disabled on individual partitions */
|
||
|
|
||
|
if (pv->ffEnabled != TRUE)
|
||
|
continue;
|
||
|
|
||
|
if ((iSec >= (long)pv->firstFATsecNo) && (iSec <= (long)pv->lastFATsecNo)) {
|
||
|
|
||
|
/* compare new and old contents of FAT sectors(s) */
|
||
|
|
||
|
usrBuf = FLBUF( ioreq, (iSec - ioreq->irSectorNo) );
|
||
|
|
||
|
checkStatus( partFreeDelClusters(pv, iSec, usrBuf) );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif /* FL_INCLUDE_FAT_MONITOR */
|
||
|
|
||
|
return flOK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* --------------------------------------------------------------------------- *
|
||
|
* *
|
||
|
* f l f f C o n t r o l *
|
||
|
* *
|
||
|
* Enable/disable/install FAT filters. See comments inside the routine for *
|
||
|
* the list of supported operations. *
|
||
|
* *
|
||
|
* Parameters: *
|
||
|
* handle : TFFS handle *
|
||
|
* partNo : partition # (0 .. FL_MAX_PARTS_PER_DISK) *
|
||
|
* state : see list of supported operations below *
|
||
|
* *
|
||
|
* Returns: *
|
||
|
* flOK on success, otherwise error code *
|
||
|
* *
|
||
|
* --------------------------------------------------------------------------- *
|
||
|
* *
|
||
|
* The following FAT monitor control requests are supported: *
|
||
|
* *
|
||
|
* state : flStateNotInitialized *
|
||
|
* partNo : [0 ... pd->parts-1] *
|
||
|
* action : turn off FAT monitor on specified partition *
|
||
|
* *
|
||
|
* state : flStateNotInitialized *
|
||
|
* partNo : < 0 *
|
||
|
* action : turn off FAT monitor on all partitions *
|
||
|
* *
|
||
|
* state : flStateInitialized *
|
||
|
* partNo : [0 ... pd->parts-1] *
|
||
|
* action : if FAT monitor has been installed on specified partition, *
|
||
|
* turn it on *
|
||
|
* *
|
||
|
* state : flStateInitInProgress *
|
||
|
* partNo : ignored *
|
||
|
* action : re-read partition table(s), and install FAT filters on all *
|
||
|
* partitions *
|
||
|
* *
|
||
|
* --------------------------------------------------------------------------- */
|
||
|
|
||
|
FLStatus flffControl ( int handle,
|
||
|
int partNo,
|
||
|
FLState state )
|
||
|
{
|
||
|
int socNo, diskNo;
|
||
|
FLffDisk * pd;
|
||
|
int i;
|
||
|
FLStatus status;
|
||
|
|
||
|
/* if module hasn't been reset yet, do it now */
|
||
|
|
||
|
if (resetDone == FALSE)
|
||
|
(void) reset();
|
||
|
|
||
|
/* break TFFS handle into socket# and disk#, and do sanity check */
|
||
|
|
||
|
socNo = H2S(handle);
|
||
|
diskNo = H2D(handle);
|
||
|
|
||
|
if ((socNo >= ((int) noOfSockets)) || (diskNo >= MAX_TL_PARTITIONS))
|
||
|
return flBadDriveHandle;
|
||
|
|
||
|
/* if disk structure hasn't been allocated yet, do it now */
|
||
|
|
||
|
if (ffDisk[socNo][diskNo] == NULL)
|
||
|
checkStatus( newDisk(handle) );
|
||
|
|
||
|
pd = ffDisk[socNo][diskNo];
|
||
|
|
||
|
/* abort if disk re-partitioning is in progress */
|
||
|
|
||
|
if (pd->ffstate == flStateInitInProgress)
|
||
|
return flDriveNotReady;
|
||
|
|
||
|
/* read partition table(s) and install FAT filters is needed */
|
||
|
|
||
|
if (pd->ffstate == flStateNotInitialized) {
|
||
|
|
||
|
if (state == flStateNotInitialized)
|
||
|
return flOK;
|
||
|
|
||
|
checkStatus( parseDisk(handle) );
|
||
|
}
|
||
|
|
||
|
/* check 'partNo' arguement for sanity */
|
||
|
|
||
|
if ((partNo >= pd->parts) || (partNo >= FL_MAX_PARTS_PER_DISK))
|
||
|
return flBadDriveHandle;
|
||
|
|
||
|
/* do requested operation */
|
||
|
|
||
|
status = flBadParameter;
|
||
|
|
||
|
switch (state) {
|
||
|
|
||
|
case flStateInitInProgress:
|
||
|
|
||
|
/* read partition table(s), install FAT filters on all partitions */
|
||
|
|
||
|
pd->ffstate = flStateNotInitialized;
|
||
|
status = parseDisk(handle);
|
||
|
break;
|
||
|
|
||
|
case flStateNotInitialized:
|
||
|
|
||
|
/* turn off FAT monitor */
|
||
|
|
||
|
if (partNo < 0) { /* all partitions */
|
||
|
|
||
|
for (i = 0; i < FL_MAX_PARTS_PER_DISK; i++) {
|
||
|
|
||
|
if (pd->part[i] != NULL)
|
||
|
(pd->part[i])->ffEnabled = FALSE;
|
||
|
}
|
||
|
}
|
||
|
else { /* specified partition */
|
||
|
|
||
|
if (pd->part[partNo] != NULL)
|
||
|
(pd->part[partNo])->ffEnabled = FALSE;
|
||
|
}
|
||
|
status = flOK;
|
||
|
break;
|
||
|
|
||
|
#ifdef FL_INCLUDE_FAT_MONITOR
|
||
|
|
||
|
case flStateInitialized:
|
||
|
|
||
|
/* turn on FAT monitor */
|
||
|
|
||
|
if ((pd->ffstate == flStateInitialized) && (partNo >= 0)) {
|
||
|
|
||
|
if (pd->part[partNo] != NULL) {
|
||
|
|
||
|
switch( (pd->part[partNo])->type ) {
|
||
|
|
||
|
case FAT12_PARTIT:
|
||
|
case FAT16_PARTIT:
|
||
|
case DOS4_PARTIT:
|
||
|
(pd->part[partNo])->ffEnabled = TRUE;
|
||
|
status = flOK;
|
||
|
break;
|
||
|
|
||
|
case FL_RAW_PART:
|
||
|
DEBUG_PRINT(("Debug: can't ctrl non-existent partition.\r\n"));
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
DEBUG_PRINT(("Debug: can't ctrl non-FAT12/16 partition.\r\n"));
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
#endif /* FL_INCLUDE_FAT_MONITOR */
|
||
|
|
||
|
} /* switch(state) */
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* --------------------------------------------------------------------------- *
|
||
|
* *
|
||
|
* f l f f I n f o *
|
||
|
* *
|
||
|
* Obtain complete partition info for specified disk. *
|
||
|
* *
|
||
|
* Parameters: *
|
||
|
* handle : TFFS handle *
|
||
|
* *
|
||
|
* Returns: *
|
||
|
* NULL if error, otherwise pointer to partitioning info *
|
||
|
* *
|
||
|
* --------------------------------------------------------------------------- */
|
||
|
|
||
|
FLffDisk * flffInfo ( int handle )
|
||
|
{
|
||
|
int socNo, diskNo;
|
||
|
FLffDisk * pd;
|
||
|
|
||
|
/* if module hasn't been reset yet, do it now */
|
||
|
|
||
|
if (resetDone == FALSE)
|
||
|
(void) reset();
|
||
|
|
||
|
/* break TFFS handle into socket# and disk#, and do sanity check */
|
||
|
|
||
|
socNo = H2S(handle);
|
||
|
diskNo = H2D(handle);
|
||
|
|
||
|
if ((socNo >= ((int) noOfSockets)) || (diskNo >= MAX_TL_PARTITIONS))
|
||
|
return NULL;
|
||
|
|
||
|
/* if disk structure hasn't been allocated yet, do it now */
|
||
|
|
||
|
if (ffDisk[socNo][diskNo] == NULL) {
|
||
|
|
||
|
if( newDisk(handle) != flOK )
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
pd = ffDisk[socNo][diskNo];
|
||
|
|
||
|
/* read partition table(s) and install FAT filters is needed */
|
||
|
|
||
|
if (pd->ffstate == flStateNotInitialized) {
|
||
|
|
||
|
if( parseDisk(handle) != flOK )
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return pd;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#endif /* ABS_READ_WRITE && FL_READ_ONLY */
|
||
|
|
||
|
|