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

📄 fat.c

📁 CIRRUS 公司EP93XX系列CPU的WINCE下的BSP
💻 C
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//------------------------------------------------------------------------------
//
//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//  PARTICULAR PURPOSE.
//
//------------------------------------------------------------------------------
#include <windows.h>
#include <memorymap.h>
#include <halether.h>
#include "eboot.h"
#include "fat.h"

#define SERPRINT        EdbgOutputDebugString
#define TO_UPPER(a)     (a >= 0x61 ? a - 0x20 : a)
#define MIN(a, b)       (a < b ? a : b)


extern ULONG DataStartLBA;

BOOLEAN ReadSectors(UCHAR Drive, ULONG LBA, USHORT nSectors, PUCHAR pBuffer);
static BOOL InitReadBuffer(ULONG pStartAddress, ULONG Length);

#if defined( NDEF_DWF_USE_OLD_READ )        
int read_sector(ULONG lba, unsigned char *pbuf);
#endif  // ( NDEF_DWF_USE_OLD_READ )        

PUCHAR g_pReadBuffStart = 0;
ULONG  g_ReadBuffLenInClusters = 0;

//
// File information
//
FILEINFO g_FileInfo;

// This data supplements the BPB information - used to save time.
t_FAT_PARMS g_FATParms;

#define SET_MEM( buffer, byteValue )  memset( &buffer[0], byteValue, sizeof( buffer ) )

#define NDEF_DWF_WRITE_TEST

#if !defined( NDEF_DWF_WRITE_TEST )

#include "ide.h"

#define IDE_WRITE_SECTOR_CMD    0x30


int write_sector( ULONG lba, unsigned char *pbuf )
{
    USHORT i = 0;

    if (!pbuf)
        return(-1);

    // Program the IDE controller
    WAIT_IDE_BUSY;
    WRITE_IDE_UCHAR(IDE_SECTCNT_REG, 1);

    // LBA access...
    //
    WRITE_IDE_UCHAR(IDE_SECTNUM_REG, (UCHAR)(lba & 0xff));
    WRITE_IDE_UCHAR(IDE_CYLL_REG, (UCHAR)((lba >> 8) & 0xff));
    WRITE_IDE_UCHAR(IDE_CYLH_REG, (UCHAR)((lba >> 16) & 0xff));
    // TODO - future drive num compensate.
    WRITE_IDE_UCHAR(IDE_DRVHD_REG, (UCHAR)(((lba >> 24) & 0xff) | IDE_HEAD_DRIVE_1 | IDE_HEAD_LBA_MODE));

    //
    // Make sure interrupt enable bit is off (we'll poll)
    //
    WRITE_IDE_UCHAR(IDE_ALT_CTRL_REG, 0xA0);    
    
    WAIT_IDE_NOT_DRDY;

    WRITE_IDE_UCHAR( IDE_CMD_REG, IDE_WRITE_SECTOR_CMD );

    WAIT_IDE_BUSY; 
    if (IS_IDE_ERROR)
    {
        printf( "write_sector: write of IDE_WRITE_SECTOR_CMD to cmd register failed!\n" );
        return(-1);
    }
    WAIT_IDE_NOT_DRQ;

    // Copy write buffer contents to IDE controller data register
    for(i=0 ; i < (SECTOR_SIZE / sizeof(USHORT)) ; i++)
    {
        WRITE_IDE_USHORT( IDE_DATA_REG, *(USHORT*)(pbuf + 1) );
    }

    return(0);
}

void WriteAndRead( void )
{
    USHORT i;
    USHORT cnt = 20;
    UCHAR  byte = 0xFF;
    
    UCHAR writeSector[SECTOR_SIZE];
    UCHAR readSector[SECTOR_SIZE];

    for (i = 0; i < cnt; ++i)
    {
        // initialize the buffers...
        SET_MEM( writeSector, byte );
        SET_MEM( readSector, i );
        
        SERPRINT( "WriteAndRead: write 1 sector to LBA 0x%X\r\n", i );
        if (0 != write_sector( i, writeSector ) )
        {
            SERPRINT( "WriteAndRead: write_sector of LBA 0x%X failed!\n", i );
        }
        SERPRINT( "WriteAndRead: read 1 sector to LBA 0x%X\r\n", i );
        if (0 != read_sector( i, readSector ) )
        {
            SERPRINT( "WriteAndRead: read_sector of LBA 0x%X failed!\n", i );
            continue;
        }
        if ( 0 != memcmp( &writeSector[0], &readSector[0], sizeof( writeSector ) ) )
        {
            SERPRINT( "WriteAndRead: read does not match write of LBA 0x%X\n", i );
        }
    }
}

#endif  // ( NDEF_DWF_WRITE_TEST )


static ULONG Cluster2LBA(ULONG Cluster)
{
    return(g_FATParms.DataStartLBA + (Cluster - 2) * g_FATParms.SectsPerClust);
}


static BOOL IsDataCluster(ULONG Cluster)
{
    switch(g_FATParms.FATType)
    {
      case FAT_12:
        if (Cluster >= 0x002 && Cluster <= 0xfef)
            return(TRUE);
        break;
      case FAT_32:
        Cluster &= 0x0fffffff;
        if (Cluster >= 0x00000002 && Cluster <= 0x0fffffef)
            return(TRUE);
        break;
      case FAT_16:
      default:
        if (Cluster >= 0x0002 && Cluster <= 0xffef)
            return(TRUE);
    }

    return(FALSE);
}


static BOOL IsRsvdCluster(ULONG Cluster)
{
    switch(g_FATParms.FATType)
    {
      case FAT_12:
        if (Cluster >= 0xff0 && Cluster <= 0xff6)
            return(TRUE);
        break;
      case FAT_32:
        Cluster &= 0x0fffffff;
        if (Cluster >= 0x0ffffff0 && Cluster <= 0x0ffffff6)
            return(TRUE);
        break;
      case FAT_16:
      default:
        if (Cluster >= 0xfff0 && Cluster <= 0xfff6)
            return(TRUE);
    }

    return(FALSE);
}


static BOOL IsEOFCluster(ULONG Cluster)
{
    switch(g_FATParms.FATType)
    {
      case FAT_12:
        if (Cluster >= 0xff8 && Cluster <= 0xfff)
            return(TRUE);
        break;
      case FAT_32:
        Cluster &= 0x0fffffff;
        if (Cluster >= 0x0ffffff8 && Cluster <= 0x0fffffff)
            return(TRUE);
        break;
      case FAT_16:
      default:
        if (Cluster >= 0xfff8 && Cluster <= 0xffff)
            return(TRUE);
    }

    return(FALSE);
}


static BOOL IsBadCluster(ULONG Cluster)
{
    switch(g_FATParms.FATType)
    {
      case FAT_12:
        if (Cluster == 0xff7)
            return(TRUE);
        break;
      case FAT_32:
        Cluster &= 0x0fffffff;
        if (Cluster == 0x0ffffff7)
            return(TRUE);
        break;
      case FAT_16:
      default:
        if (Cluster == 0xfff7)
            return(TRUE);
    }

    return(FALSE);
}


ULONG GetNextCluster(ULONG Cluster)
{
    ULONG Sector = 0;
    ULONG ByteOffset = 0;
    PUCHAR pSectorCache = (PUCHAR)SECTOR_CACHE_START;   // Sector cache is where the sector used to read the FAT cluster chains lives.
    static ULONG CurrentSector = 0;
    ULONG NextCluster = 0;
#if !defined( NDEF_DWF_NEW_FAT_12_CODE )
    USHORT  uShort1, uShort2;
#endif  //  ( NDEF_DWF_NEW_FAT_12_CODE )


    // If we're passed an EOF cluster, return it.
    //
    if (IsEOFCluster(Cluster))
        return(Cluster);

    // Is caller giving us a valid cluster?
    //
    if (!IsDataCluster(Cluster))
    {
        SERPRINT("ERROR: GetNextCluster - bad cluster number.\r\n");
        return(0);  // 0 isn't a valid cluster number (at least for our purposes).
    }

    // Compute sector where our FAT entry lives.
    //
    switch(g_FATParms.FATType)
    {
      case FAT_12:
        Sector = (Cluster * 3) / 2;     // Every FAT12 cluster is 1.5 bytes.
        ByteOffset = Sector % g_FATParms.BytesPerSect;
        Sector /= g_FATParms.BytesPerSect;
        Sector += g_FATParms.FATLBA;
        break;
      case FAT_32:
        Sector = Cluster * sizeof(ULONG);
        ByteOffset = Sector % g_FATParms.BytesPerSect;
        Sector /= g_FATParms.BytesPerSect;
        Sector += g_FATParms.FATLBA;
        break;
      case FAT_16:
      default:
        Sector = Cluster * sizeof(USHORT);
        ByteOffset = Sector % g_FATParms.BytesPerSect;
        Sector /= g_FATParms.BytesPerSect;
        Sector += g_FATParms.FATLBA;
        break;
    }

    // If the sector we're interested in isn't in our cache, get it.
    //
    if (CurrentSector != Sector)
    {
        if (!ReadSectors(g_FATParms.DriveId, Sector, 1, pSectorCache))
        {
            SERPRINT("ERROR: GetNextCluster - unable to read sector.\r\n");
        }

        CurrentSector = Sector;
    }

    // Locate next cluster number...
    //
    switch(g_FATParms.FATType)
    {
    case FAT_12:
#if !defined( NDEF_DWF_NEW_FAT_12_CODE )
        // Every FAT-12 entry requires 3 bytes, so we must watch
        // for sector boundry crossings and access the correct
        // bytes...
        uShort1 = *((PUCHAR) (pSectorCache + ByteOffset));
        // Need to worry about cluster number crossing a sector boundary.
        if (ByteOffset == ((ULONG)g_FATParms.BytesPerSect - 1))
        {
            // We must read the next sector to get the 2nd byte of the
            // FAT entry for this cluster!
            ++Sector;
            if (!ReadSectors(g_FATParms.DriveId, Sector, 1, pSectorCache))
            {
                SERPRINT("ERROR: GetNextCluster - unable to read sector.\r\n");
            }
            CurrentSector = Sector;
            uShort2 = *((PUCHAR) pSectorCache); // get the 1st byte of sector...
        }
        else
        {
            uShort2 = *((PUCHAR) (pSectorCache + ByteOffset + 1));
        }
        // decide which parts of the FAT info to use...
        if (Cluster & 0x01)
        {
            // how odd, an odd cluster number!
            uShort1 = (uShort1 >> 4);
            uShort2 = (uShort2 << 4);
        }
        else
        {
            // must be an even cluster, uShort1 does not change...
            uShort2 = (uShort2 & 0x0F);
            uShort2 = (uShort2 << 8);
        }
        NextCluster = uShort1 | uShort2;
        
#else   // ( NDEF_DWF_NEW_FAT_12_CODE )

        // Need to worry about cluster number crossing a sector boundary.
        if (ByteOffset == ((ULONG)g_FATParms.BytesPerSect - 1))
        {
            NextCluster = (ULONG)(*(PUCHAR)(pSectorCache + ByteOffset));

            // Now we need to read the next sector.
            //
            ++Sector;
            if (!ReadSectors(g_FATParms.DriveId, Sector, 1, pSectorCache))
            {
                SERPRINT("ERROR: GetNextCluster - unable to read sector.\r\n");
            }
            CurrentSector = Sector;

            NextCluster |= (ULONG)((*(PUCHAR)pSectorCache) << 8);
        }
        else
            NextCluster = (ULONG)(*(PUSHORT)(pSectorCache + ByteOffset));

        // Since every FAT12 entry is 1.5 bytes, we either need to shift or mask based
        // on whether the previous cluster number was odd or even.
        //
        if (Cluster & 0x1)
            NextCluster = NextCluster >> 4;
        else
            NextCluster = NextCluster & 0xfff;
            
#endif  // ( NDEF_DWF_NEW_FAT_12_CODE )
        break;
    case FAT_32:
        // FAT32 is easy - no worries about sector boundaries...
        NextCluster = (ULONG)(*(PULONG)(pSectorCache + ByteOffset));
        break;
    case FAT_16:
    default:
        // FAT16 is easy - no worries about sector boundaries...
        NextCluster = (ULONG)(*(PUSHORT)(pSectorCache + ByteOffset));
    }

#if 0
    SERPRINT("INFO: GetNextCluster - cluster=0x%x  next cluster=0x%x.\r\n", Cluster, NextCluster);
#endif
    
    // Return the next cluster value.
    //
    return(NextCluster);
}

#if defined( DUMP_ROOT_DIR )

void DumpRootDir( void )
{
    int       i;
    int       sector;
    int       numEntriesPerSector = g_FATParms.BytesPerSect/sizeof( DIRENTRY );
    DIRENTRY *pDirEntry;
    UCHAR     fName[ 12 ];
    BOOL      bEndOfDir = FALSE;
    BOOL      bDumpRootDir = FALSE;

    if ( !bDumpRootDir )
    {
        SERPRINT( "\r\nINFO: Dump Root Directory is currently disabled\r\n" );
        return;
    }
    
    fName[ 11 ] = 0x00;

⌨️ 快捷键说明

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