⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rfatsa.cxx

📁 EFI(Extensible Firmware Interface)是下一代BIOS
💻 CXX
📖 第 1 页 / 共 5 页
字号:
    _ft           = INVALID_FATTYPE;
    _StartDataLbn = 0;
    _ClusterCount = 0;
    _sysid        = SYSID_NONE;
    _data_aligned = FALSE;
    _AdditionalReservedSectors = MAXULONG;
}


UFAT_EXPORT
REAL_FAT_SA::~REAL_FAT_SA(
    )
/*++

Routine Description:

    Destructor for REAL_FAT_SA.

Arguments:

    None.

Return Value:

    None.

--*/
{
    Destroy();
}

UFAT_EXPORT
BOOLEAN
REAL_FAT_SA::Initialize(
    IN OUT  PLOG_IO_DP_DRIVE    Drive,
    IN OUT  PMESSAGE            Message,
    IN      BOOLEAN             Formatted
    )
/*++

Routine Description:

    This routine initializes the FAT super area to an initial state.  It
    does so by first reading in the boot sector and verifying it with
    the methods of REAL_FAT_SA.  Upon computing the super area's actual size,
    the underlying SECRUN will be set to the correct size.

    If the caller needs to format this volume, then this method should
    be called with the Formatted parameter set to FALSE.

Arguments:

    Drive       - Supplies the drive where the super area resides.
    Message     - Supplies an outlet for messages
    Formatted   - Supplies a boolean which indicates whether or not
                    the volume is formatted.

Return Value:

    FALSE   - Failure.
    TRUE    - Success.

--*/
{

    BIG_INT     data_offset;

    //
    //  Reset the state of the REAL_FAT_SA object.
    //

    Destroy();

    //
    //  Make sure that the boot sector(s) is(are) at least 512 bytes
    //  in size. Note that the boot area for a FAT32 volume is of size at least
    //  32 * 512 bytes but that adjustment will be made later. The first
    //  512 bytes of a FAT volume should contain the whole Bpb and that is all we
    //  care for the moment.
    //

    _sec_per_boot = max(1, BYTES_PER_BOOT_SECTOR/Drive->QuerySectorSize());

    if (!Formatted) {
        return _mem.Initialize() &&
               DosSaInit(&_mem, Drive, _sec_per_boot, Message);
    }

    //
    //  Do some quick parameter checking, initialize the underlying
    //  SUPERAREA and SECRUN structure, and read in the Bpb.
    //

    if (!Drive ||
        !(Drive->QuerySectorSize()) ||
        !_mem.Initialize() ||
        !DosSaInit(&_mem, Drive, _sec_per_boot, Message) ||
        !SECRUN::Read()) {

        Message->Set(MSG_CANT_READ_BOOT_SECTOR);
        Message->Display("");
        Destroy();
        return FALSE;

    }

    //
    //  Unpack the bpb in the SECRUN buffer into the _sector_zero
    //  member for easier access to the fields within the bpb.
    //

    UnpackExtendedBios(&_sector_zero,
        (PPACKED_EXTENDED_BIOS_PARAMETER_BLOCK)SECRUN::GetBuf());

    //
    //  Have a really quick check on the unpacked Bpb.
    //

    if (!VerifyBootSector() || !_sector_zero.Bpb.Fats) {
        Destroy();
        return FALSE;
    }

    //
    //  Determine the FAT type and the number of clusters on the volume
    //  depending on the
    //

    _ClusterCount = DetermineClusterCountAndFatType ( &_StartDataLbn,
                                                      &_ft );

    //
    // figured out if the data clusters are aligned
    //
    data_offset = QuerySectorsPerFat()*QueryFats()+QueryReservedSectors();
    data_offset = data_offset * Drive->QuerySectorSize();
    data_offset += QueryRootEntries()*BytesPerDirent;
    DebugAssert(FAT_FIRST_DATA_CLUSTER_ALIGNMENT <= MAXULONG);
    _data_aligned = ((data_offset.GetLowPart() & (FAT_FIRST_DATA_CLUSTER_ALIGNMENT - 1)) == 0);

    //
    //  Determine the partition id.
    //

    if (_ft == SMALL) {
        _sysid = SYSID_FAT12BIT;
    } else if (QueryVirtualSectors() < CSEC_FAT32MEG) {
        _sysid = SYSID_FAT16BIT;
    } else if (_ft == LARGE32) {
        _sysid = SYSID_FAT32BIT;
    } else {
        _sysid = SYSID_FAT32MEG;
    }

    //
    //  Adjust the _sector_per_boot member if the volume
    //  is a FAT32 volume and also in the case of a FAT32 drive
    //  only set up the super area to include memory for one FAT.
    //  On FAT32 drives the FAT can be much larger than on a FAT16 drive
    //  and we do not want to carry around the second FAT in memory as
    //  extra baggage.
    //

    if ( _ft == LARGE32 ) {
    //
    // FAT32 drives have a variable reserved area size so we do not want this
    // number hard wired at 32 unless it is not set yet (BPB value is 0 or 1)
    //
    if(_sector_zero.Bpb.ReservedSectors > 1) {
        _sec_per_boot = _sector_zero.Bpb.ReservedSectors;
    } else {
        _sec_per_boot = max((32 * 512)/_drive->QuerySectorSize(), 32);
    }
    if(!_mem.Initialize() || !DosSaInit(&_mem, Drive,
                        _sector_zero.Bpb.ReservedSectors + _sector_zero.Bpb.BigSectorsPerFat,
                        Message)) {
        Message->Set(MSG_FMT_NO_MEMORY);
        Message->Display("");
        Destroy();
        return FALSE;
    }
    } else {
    //
    //  The main idea behind the following code segment is to allocate
    //  memory for the whole super area including the boot area, all copies
    //  of the FAT, and the root directory for FAT12/16 volume and to initialize
    //  the underlying SECRUn object to cover the whole superarea on the
    //  disk.
    //
    if(!_mem.Initialize() || !DosSaInit(&_mem, Drive, _StartDataLbn, Message)) {
        Message->Set(MSG_FMT_NO_MEMORY);
        Message->Display("");
        Destroy();
        return FALSE;
    }
    }
    //
    //  Initialize the root directory of the volume.
    //

    if (!(InitializeRootDirectory(Message))) {
        return FALSE;
    }

    return TRUE;
}

UFAT_EXPORT
BOOLEAN
REAL_FAT_SA::InitFATChkDirty(
    IN OUT  PLOG_IO_DP_DRIVE    Drive,
    IN OUT  PMESSAGE        Message
    )
/*++

Routine Description:

    This routine initializes the _fat pointer in the FAT super area
    to point to the first sector of one of the FATs so that the dirty bits in the FAT[1]
    entry can be looked at.

Arguments:

    Drive   - Supplies the drive.
    Message     - Supplies an outlet for messages

Return Value:

    FALSE   - Failure.
    TRUE    - Success.

--*/
{
    UINT    StartSec;


    UnpackExtendedBios(&_sector_zero,
               (PPACKED_EXTENDED_BIOS_PARAMETER_BLOCK)SECRUN::GetBuf());

    if (!VerifyBootSector() || !_sector_zero.Bpb.Fats) {
        return FALSE;
    }

    _ClusterCount = DetermineClusterCountAndFatType ( &_StartDataLbn,
                                                      &_ft );

    StartSec =  _sector_zero.Bpb.ReservedSectors;

    if(!_mem2.Initialize()) {
    return FALSE;
    }

    DELETE(_fat);
    if (!(_fat = NEW FAT)) {
    return FALSE;
    }

    if (!_fat->Initialize(&_secrun2, &_mem2, Drive, StartSec, _ClusterCount, 1)) {
    DELETE(_fat);
    return FALSE;
    }

    if(!_secrun2.Read()) {
    if(_sector_zero.Bpb.SectorsPerFat == 0) {
        StartSec += _sector_zero.Bpb.BigSectorsPerFat;
    } else {
        StartSec += (UINT)_sector_zero.Bpb.SectorsPerFat;
    }
    if (!_fat->Initialize(&_secrun2, &_mem2, Drive, StartSec, _ClusterCount, 1)) {
        DELETE(_fat);
        return FALSE;
    }
    if(!_secrun2.Read()) {
        DELETE(_fat);
        return FALSE;
    }
    }

    return TRUE;
}

ULONG
REAL_FAT_SA::DetermineClusterCountAndFatType (
    IN OUT  PULONG      StartingDataLbn,
    IN OUT  FATTYPE     *FatType
    )
/*++

Routine Description:

    This routine computes the number of clusters and fat type of a volume
    based on the total number of sectors on the volume and data in the Bpb.

    Note that this method assumes that the _sector_zero member has beeen
    initialized properly.

Arguments:

    StartingDataLbn - Supplies the address at which the starting data
        Lbn should be returned to the caller.

    FatType  - Supplies the address at which the Fat type should be
        returned to the caller.

Return Values:

    Number of clusters on the volume. Note that this number includes the
    first two entries.

--*/
{
    ULONG   cluster_count;      //  Number of clusters on the volume
    ULONG   sectors;            //  Number of sectors on the volume.
    ULONG   starting_data_lbn;  //  The first data sector on the FAT volume.
    FATTYPE fat_type;           //  FAT type.
    ULONG   sector_size;        //  Sector size.

    sectors = QueryVirtualSectors();
    starting_data_lbn = ComputeStartDataLbn();
    sector_size = _drive->QuerySectorSize();

    //
    //  Use the naive formula to compute a preliminary cluster count
    //  on the volume.
    //

    cluster_count = (sectors - starting_data_lbn) / (ULONG)QuerySectorsPerCluster() +
                    FirstDiskCluster;

    //
    //  We can determine the fat type now, note that we are assuming
    //  that subsequent adjustment to the cluster count will not affect the
    //  fat type which is fairly reasonable.
    //

    fat_type = cluster_count > MAX_CLUS_ENT_SMALL ? LARGE16 : SMALL;

    //
    //  It is possible to have a FAT16 volume that doesn't use up all
    //  the space on the disk so we should check whether _sector_zero.Bpb
    //  .SectorsPerfat == 0 in order to make sure that the volume is really
    //  a FAT32 volume.
    //

    if (cluster_count > MAX_CLUS_ENT_BIG) {
        if ( _sector_zero.Bpb.SectorsPerFat == 0 ) {
            fat_type = LARGE32;
        } else {
            cluster_count = MAX_CLUS_ENT_BIG;
        }
    }

    //
    // Check to make sure the FAT size in the BPB is actually big enough to hold this
    //  many clusters, adjust the cluster_count down if it is not.
    //

    switch(fat_type) {
    case SMALL:
        if (RoundUpDiv(cluster_count * 12, sector_size * 8) > _sector_zero.Bpb.SectorsPerFat ) {
        cluster_count = (_sector_zero.Bpb.SectorsPerFat * sector_size * 8) / 12;
        }
        break;
    case LARGE16:
        if (RoundUpDiv(cluster_count * 2, sector_size) > _sector_zero.Bpb.SectorsPerFat ) {
        cluster_count = (_sector_zero.Bpb.SectorsPerFat * sector_size) / 2;
        }
        break;
    case LARGE32:
        if (RoundUpDiv(cluster_count * 4, sector_size) > _sector_zero.Bpb.BigSectorsPerFat ) {
        cluster_count = (_sector_zero.Bpb.BigSectorsPerFat * sector_size) / 4;
        }
        break;
    default:
        DebugPrintTrace(("Bad FAT type.\n"));
    }

    //
    //  Make sure that the caller gets what it wants.
    //

    *FatType = fat_type;
    *StartingDataLbn = starting_data_lbn;
    return cluster_count;

}

BOOLEAN
REAL_FAT_SA::InitializeRootDirectory (
    IN  PMESSAGE    Message
    )
/*++

Routine Description:

    This routine initializes the root directory structure in the
    FAT super area object after the boot sector has been read from the
    disk.

Arguments:

    Message - Supplies an outlet for messages.

Return Values:

    TRUE  - The opreation is completed successfully.
    FALSE - This routine fails to complete the intended operation.

--*/
{

    //
    //  Note that the root directory for a FAT32 volume is a cluster
    //  chain while the FAT16/12 root directory is a fixed size area
    //  that comes right after the FATs.
    //

    if ( _ft == LARGE32 ) {

        if (!(_dirF32 = NEW FILEDIR)) {
            Destroy();
            Message->Set(MSG_FMT_NO_MEMORY);
            Message->Display("");
            return FALSE;
        }

        //
        //  Complete initialization of _dirF32 is deffered until
        //  REAL_FAT_SA::read is called because the FAT
        //  is needed.
        //

    } else {

        CONT_MEM    cmem;           //  This CONT_MEM object piggybacks onto the
                                    //  the root directory section of the

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -