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

📄 fat.cxx

📁 EFI(Extensible Firmware Interface)是下一代BIOS
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c) 1991-1999 Microsoft Corporation

Module Name:

    fat.cxx

--*/

#include <pch.cxx>

#define _NTAPI_ULIB_
#define _UFAT_MEMBER_

#include "ulib.hxx"
#include "ufat.hxx"

#include "bitvect.hxx"
#include "error.hxx"
#include "fat.hxx"


DEFINE_CONSTRUCTOR( FAT, SECRUN );


FAT::~FAT(
    )
/*++

Routine Description:

    Destructor for FAT.

Arguments:

    None.

Return Value:

    None.

--*/
{
    Destroy();
}

extern VOID DoInsufMemory(VOID);

VOID
FAT::Construct (
    )
/*++

Routine Description:

    Constructor for FAT.

Arguments:

    None.

Return Value:

    None.

--*/
{
    _fat = NULL;
    _num_entries = 0;
    _fat_bits = 0;
    _low_end_of_chain = 0;
    _end_of_chain = 0;
    _bad_cluster = 0;
    _low_reserved = 0;
    _high_reserved = 0;
    _AllocatedClusters = 0xFFFFFFFF;
}


VOID
FAT::Destroy(
    )
/*++

Routine Description:

    This routine returns a FAT object to its initial state.

Arguments:

    None.

Return Value:

    None.

--*/
{
    _fat = NULL;
    _num_entries = 0;
    _fat_bits = 0;
    _low_end_of_chain = 0;
    _end_of_chain = 0;
    _bad_cluster = 0;
    _low_reserved = 0;
    _high_reserved = 0;
    _AllocatedClusters = 0xFFFFFFFF;
}


BOOLEAN
FAT::Initialize(
    IN OUT  PSECRUN     Srun,
    IN OUT  PMEM                Mem,
    IN OUT  PLOG_IO_DP_DRIVE    Drive,
    IN      LBN                 StartSector,
    IN      ULONG               NumOfEntries,
    IN      ULONG               NumSectors
    )
/*++

Routine Description:

    This routine initialize a FAT object.

Arguments:

    Mem             - Supplies the memory for the run of sectors.
    Drive           - Supplies the drive to read and write from.
    StartSector     - Supplies the start of the fat.
    NumberOfEntries - Supplies the number of entries in the FAT
                      which should be the total number of clusters
                      plus two reserved entries at the beginning.
    NumSectors      - Supplies the number of sectors allocated for
                      the fat.  If this parameter is not supplied
                      then this routine will compute this value
                      from the given number of entries.

Return Value:

    FALSE   - Failure.
    TRUE    - Success.

Notes:

    The 'NumSectors' parameter is added to this function
    DOS FORMAT does not always make the FAT large enough for
    the volume.  If this parameter is supported then the
    number of entries supported by this FAT will be the lesser
    or the actual number passed in that the maximum number that
    the given FAT size will support.

--*/
{
    SECTORCOUNT n;
    ULONG       sector_size;
    ULONG       max_num_entries;

    DebugAssert(Mem);
    DebugAssert(Drive);

    Destroy();

    if (!(sector_size = Drive->QuerySectorSize())) {
        Destroy();
        return FALSE;
    }

    _num_entries = NumOfEntries;

    if (_num_entries < FirstDiskCluster + MaxNumClusForSmallFat) {
       _fat_bits = fFat12;
    } else if (_num_entries < FirstDiskCluster + MinNumClusForFat32) {
       _fat_bits = fFat16;
    } else {
       _fat_bits = fFat32;
    }

    if (fFat32 == _fat_bits) {
        _low_end_of_chain = 0x0FFFFFF8;
        _end_of_chain = 0x0FFFFFFF;
        _bad_cluster = 0x0FFFFFF7;
        _low_reserved = 0x0FFFFFF0;
        _high_reserved = 0x0FFFFFF6;
        n = (_num_entries*4 - 1)/sector_size + 1;
    }
    else if (fFat16 == _fat_bits) {
        // COMMON CODE for FAT 12 and FAT 16
        // FAT 16
        _low_end_of_chain = 0xFFF8;
        _end_of_chain = 0xFFFF;
        _bad_cluster = 0xFFF7;
        _low_reserved = 0xFFF0;
        _high_reserved = 0xFFF6;

        n = (_num_entries*2 - 1)/sector_size + 1;

    }
    else {      // FAT 12
        _low_end_of_chain = 0x0FF8;
        _end_of_chain = 0x0FFF;
        _bad_cluster = 0x0FF7;
        _low_reserved = 0x0FF0;
        _high_reserved = 0x0FF6;

        n = (_num_entries*3 - 1)/2/sector_size + 1;
    }

    if (NumSectors) {
        n = NumSectors;
        if (fFat32 == _fat_bits) {
           max_num_entries = (n*sector_size/4);
        } else if (fFat16 == _fat_bits) {
           // COMMON CODE for FAT 12 and FAT 16
           max_num_entries = (n*sector_size/2);
        } else {
            max_num_entries = (n*sector_size*2/3);
        }
        _num_entries = min(_num_entries, max_num_entries);
    }
    _AllocatedClusters = 0xFFFFFFFF;

    if (!Srun->Initialize(Mem, Drive, StartSector, n)) {
    DoInsufMemory();
        Destroy();
        return FALSE;
    }

    _fat = Srun->GetBuf();
    return TRUE;
}



BOOLEAN
FAT::Initialize(
    IN OUT  PMEM                Mem,
    IN OUT  PLOG_IO_DP_DRIVE    Drive,
    IN      LBN                 StartSector,
    IN      ULONG               NumOfEntries,
    IN      ULONG               NumSectors
    )
/*++

Routine Description:

    This routine initialize a FAT object.

Arguments:

    Mem             - Supplies the memory for the run of sectors.
    Drive           - Supplies the drive to read and write from.
    StartSector     - Supplies the start of the fat.
    NumberOfEntries - Supplies the number of entries in the FAT
                      which should be the total number of clusters
                      plus two reserved entries at the beginning.
    NumSectors      - Supplies the number of sectors allocated for
                      the fat.  If this parameter is not supplied
                      then this routine will compute this value
                      from the given number of entries.

Return Value:

    FALSE   - Failure.
    TRUE    - Success.

Notes:

    The 'NumSectors' parameter is added to this function
    DOS FORMAT does not always make the FAT large enough for
    the volume.  If this parameter is supported then the
    number of entries supported by this FAT will be the lesser
    or the actual number passed in that the maximum number that
    the given FAT size will support.

--*/
{
    SECTORCOUNT n;
    ULONG       sector_size;
    ULONG       max_num_entries;

    DebugAssert(Mem);
    DebugAssert(Drive);

    Destroy();

    if (!(sector_size = Drive->QuerySectorSize())) {
        Destroy();
        return FALSE;
    }

    _num_entries = NumOfEntries;

    if (_num_entries < FirstDiskCluster + MaxNumClusForSmallFat) {
       _fat_bits = fFat12;
    } else if (_num_entries < FirstDiskCluster + MinNumClusForFat32) {
       _fat_bits = fFat16;
    } else {
       _fat_bits = fFat32;
    }

    if (fFat32 == _fat_bits) {
        _low_end_of_chain = 0x0FFFFFF8;
        _end_of_chain = 0x0FFFFFFF;
        _bad_cluster = 0x0FFFFFF7;
        _low_reserved = 0x0FFFFFF0;
        _high_reserved = 0x0FFFFFF6;
    n = ((_num_entries * 4) + (sector_size - 1)) / sector_size;
    }
    else if (fFat16 == _fat_bits) {
        // COMMON CODE for FAT 12 and FAT 16
        // FAT 16
        _low_end_of_chain = 0xFFF8;
        _end_of_chain = 0xFFFF;
        _bad_cluster = 0xFFF7;
        _low_reserved = 0xFFF0;
        _high_reserved = 0xFFF6;

    n = ((_num_entries * 2) + (sector_size - 1)) / sector_size;

    }
    else {      // FAT 12
        _low_end_of_chain = 0x0FF8;
        _end_of_chain = 0x0FFF;
        _bad_cluster = 0x0FF7;
        _low_reserved = 0x0FF0;
        _high_reserved = 0x0FF6;

    // NOTE: the "+ (2 - 1)) / 2)" below is doing a round up divide by 2
    //   it is left this way because it is clearer what it is doing....

    n = ((((_num_entries * 3) + (2 - 1)) / 2) + (sector_size - 1)) / sector_size;
    }

    if (NumSectors) {
        n = NumSectors;
        if (fFat32 == _fat_bits) {
           max_num_entries = (n*sector_size/4);
        } else if (fFat16 == _fat_bits) {
           // COMMON CODE for FAT 12 and FAT 16
           max_num_entries = (n*sector_size/2);
        } else {
            max_num_entries = (n*sector_size*2/3);
        }
        _num_entries = min(_num_entries, max_num_entries);
    }
    _AllocatedClusters = 0xFFFFFFFF;

    if (!SECRUN::Initialize(Mem, Drive, StartSector, n)) {
    DoInsufMemory();
        Destroy();
        return FALSE;
    }

    _fat = GetBuf();
    return TRUE;
}


UFAT_EXPORT
ULONG
FAT::Index12(
    IN  ULONG    ClusterNumber
    ) CONST
/*++

Routine Description:

    This routine indexes the FAT as 12 bit little endian entries.

Arguments:

    ClusterNumber   - Supplies the FAT entry desired.

Return Value:

    The value of the FAT entry at ClusterNumber.

--*/
{
    ULONG   n;
    PUCHAR  p;

    p = (PUCHAR) _fat;

    DebugAssert(p);

    n = ClusterNumber*3;
    if (n%2) {
        return (p[n/2]>>4) | (p[n/2 + 1]<<4);
    } else {
        return p[n/2] | ((p[n/2 + 1]&0x0F)<<8);
    }
}


UFAT_EXPORT
VOID
FAT::Set12(
    IN  ULONG    ClusterNumber,
    IN  ULONG    Value
    )
/*++

Routine Description:

    This routine sets the ClusterNumber'th 12 bit FAT entry to Value.

Arguments:

    ClusterNumber   - Supplies the FAT entry to set.
    Value           - Supplies the value to set the FAT entry to.

Return Value:

    None.

--*/
{
    ULONG   n;
    PUCHAR  p;

    p = (PUCHAR) _fat;

    DebugAssert(p);

    n = ClusterNumber*3;
    if (n%2) {
        p[n/2] = (p[n/2]&0x0F) | (((UCHAR)Value&0x000F)<<4);
        p[n/2 + 1] = (UCHAR)((Value&0x0FF0)>>4);
    } else {
        p[n/2] = (UCHAR)Value&0x00FF;
        p[n/2 + 1] = (p[n/2 + 1]&0xF0) | (UCHAR)((Value&0x0F00)>>8);
    }
    _AllocatedClusters = 0xFFFFFFFF;
}

ULONG
FAT::QueryFreeClusters(
    ) CONST
/*++

Routine Description:

    This routine computes the number of free clusters on the disk by
    scanning the FAT and counting the number of empty entries.

Arguments:

    None.

Return Value:

    The number of free clusters on the disk.

--*/
{
    ULONG    i;
    ULONG    r;

    r = 0;
    for (i = FirstDiskCluster; IsInRange(i); i++) {
        if (IsClusterFree(i)) {

            r++;
        }
    }

    return r;
}


ULONG
FAT::QueryBadClusters(
    ) CONST
/*++

Routine Description:

    This routine computes the number of bad clusters on the disk by
    scanning the FAT and counting the number of entries marked bad.

Arguments:

    None.

Return Value:

    The number of bad clusters on the disk.

--*/
{
    ULONG    i;
    ULONG    r;

    r = 0;
    for (i = FirstDiskCluster; IsInRange(i); i++) {
        if (IsClusterBad(i)) {
            r++;
        }
    }

    return r;
}


ULONG
FAT::QueryReservedClusters(
    ) CONST
/*++

Routine Description:

    This routine computes the number of reserved clusters on the disk by
    scanning the FAT and counting the number of entries marked reserved.

Arguments:

    None.

Return Value:

    The number of reserved clusters on the disk.

--*/
{
    ULONG    i;
    ULONG    r;

    r = 0;
    for (i = FirstDiskCluster; IsInRange(i); i++) {
        if (IsClusterReserved(i)) {
            r++;
        }
    }

    return r;
}

ULONG
FAT::QueryAllocatedClusters(
    ) CONST
/*++

Routine Description:

    This routine computes the number of allocated clusters on the
    disk by scanning the FAT and counting the entries marked allocated.

Arguments:

    None.

Return Value:

    The number of allocated clusters on the disk.

--*/
{
    ULONG    i;
    ULONG    r;

    r = 0;
    for (i = FirstDiskCluster; IsInRange(i); i++) {
        if (!IsClusterReserved(i) && !IsClusterBad(i) && !IsClusterFree(i)) {
            r++;
        }
    }

    return r;
}


UFAT_EXPORT
ULONG
FAT::QueryNthCluster(
    IN  ULONG    StartingCluster,
    IN  ULONG    Index
    ) CONST
/*++

Routine Description:

    This routine returns the cluster number of the cluster that is in the
    'Index'th position in the cluster chain beginning at 'StartingCluster'.
    The clusters in a chain are numbered beginning at zero.

Arguments:

    StartingCluster - Supplies the first cluster of a cluster chain.
    Index           - Supplies the number of the cluster in the chain
                        requested.

⌨️ 快捷键说明

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