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

📄 fmd.cpp

📁 老外的一个开源项目
💻 CPP
📖 第 1 页 / 共 3 页
字号:

Returns:        None.
------------------------------------------------------------------------------*/
VOID  FMD_PowerUp(VOID)  
{  
    return; 
}


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_PowerDown()

Description:    Suspends power to the Flash memory device (if applicable).

Returns:        None.
------------------------------------------------------------------------------*/
VOID  FMD_PowerDown(VOID)
{  
    return; 
}


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_OEMIoControl()

Description:    Implements user-defined (a.k.a. application specific) commands 
                for the Flash memory device

Returns:        None.
------------------------------------------------------------------------------*/
BOOL  FMD_OEMIoControl(DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize, 
                       PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned)
{
    switch(dwIoControlCode)
    {
    case IOCTL_FMD_GET_INTERFACE:
    {
        if (!pOutBuf || nOutBufSize < sizeof(FMDInterface))
        {
            DEBUGMSG(1, (TEXT("FMD_OEMIoControl: IOCTL_FMD_GET_INTERFACE bad parameter(s).\r\n")));
            return(FALSE);
        }    

        PFMDInterface pInterface = (PFMDInterface)pOutBuf;
        pInterface->cbSize = sizeof(FMDInterface);
        pInterface->pInit = FMD_Init;
        pInterface->pDeInit = FMD_Deinit;
        pInterface->pGetInfo = FMD_GetInfo;        
        pInterface->pGetBlockStatus = FMD_GetBlockStatus;     
        pInterface->pSetBlockStatus = FMD_SetBlockStatus;
        pInterface->pReadSector = FMD_ReadSector;
        pInterface->pWriteSector = FMD_WriteSector;
        pInterface->pEraseBlock = FMD_EraseBlock;
        pInterface->pPowerUp = FMD_PowerUp;
        pInterface->pPowerDown = FMD_PowerDown;
        pInterface->pGetPhysSectorAddr = FMD_GetPhysSectorAddr;            

        break;
    }
    case IOCTL_FMD_SET_XIPMODE:
        // Select between XIP mode or non-XIP mode.  The difference from the FMD's standpoint is whether or not
        // sector information is stored along with each sector.  This should be called before FMD_Init.
        if (!pInBuf || nInBufSize < sizeof(BOOLEAN))
        {
            DEBUGMSG(1, (TEXT("FMD_OEMIoControl: IOCTL_FMD_SET_XIPMODE bad parameter(s).\r\n")));
            return(FALSE);
        }
        g_bXIPEntire = *(PBOOLEAN)pInBuf;      
        break;
    case IOCTL_FMD_GET_XIPMODE:

        if (!pOutBuf || nOutBufSize < sizeof(BOOLEAN))
        {
            DEBUGMSG(1, (TEXT("FMD_OEMIoControl: IOCTL_FMD_GET_XIPMODE bad parameter(s).\r\n")));
            return(FALSE);
        }
        *(PBOOLEAN)pOutBuf = g_bXIPEntire;      
        break;        
    case IOCTL_FMD_LOCK_BLOCKS:
        // Lock one of more blocks in a specified range.
        if (!pInBuf || nInBufSize < sizeof(BlockLockInfo))
        {
            DEBUGMSG(1, (TEXT("FMD_OEMIoControl: IOCTL_FMD_LOCK_BLOCKS bad parameter(s).\r\n")));
            return(FALSE);
        }
        if (!SetBlockLock(((PBlockLockInfo)pInBuf)->StartBlock, ((PBlockLockInfo)pInBuf)->NumBlocks, TRUE))
        {
            DEBUGMSG(1, (TEXT("FMD_OEMIoControl: IOCTL_FMD_LOCK_BLOCKS failed to lock blocks (start=0x%x, number=0x%x).\r\n"), ((PBlockLockInfo)pInBuf)->StartBlock, ((PBlockLockInfo)pInBuf)->NumBlocks));
            return(FALSE);
        }
        break;
    case IOCTL_FMD_UNLOCK_BLOCKS:
        // Unlock one of more blocks in a specified range.
        if (!pInBuf || nInBufSize < sizeof(BlockLockInfo))
        {
            DEBUGMSG(1, (TEXT("FMD_OEMIoControl: IOCTL_FMD_UNLOCK_BLOCKS bad parameter(s).\r\n")));
            return(FALSE);
        }
        if (!SetBlockLock(((PBlockLockInfo)pInBuf)->StartBlock, ((PBlockLockInfo)pInBuf)->NumBlocks, FALSE))
        {
            DEBUGMSG(1, (TEXT("FMD_OEMIoControl: IOCTL_FMD_UNLOCK_BLOCKS failed to unlock blocks (start=0x%x, number=0x%x).\r\n"), ((PBlockLockInfo)pInBuf)->StartBlock, ((PBlockLockInfo)pInBuf)->NumBlocks));
            return(FALSE);
        }
        break;

    default:
        DEBUGMSG(1, (TEXT("FMD_OEMIoControl: unrecognized IOCTL (0x%x).\r\n"), dwIoControlCode));
        return(FALSE);
    }

    return(TRUE);
}

VOID DefineLayout()
{
    if (!g_FMDInfo.SectorSize) 
        g_FMDInfo.SectorSize = SECTOR_SIZE;

    if (!g_bXIPEntire)    // Not XIP mode.
    {
        g_FMDInfo.SectorsPerBlock = g_FMDInfo.BlockSize / (g_FMDInfo.SectorSize + sizeof(SectorInfo));
        g_FMDInfo.SectorInfoOffset = g_FMDInfo.SectorsPerBlock * g_FMDInfo.SectorSize;

        // Assert there is enough room for a signiture gc_dwFlashSignature at the end 
        // of the block.  If not, the signiture should be modified by the OEM
        ASSERT (g_FMDInfo.BlockSize % (g_FMDInfo.SectorSize + sizeof(SectorInfo)) >= BLOCK_SIG_BYTES);
    }
    else                // XIP mode.
    {
        g_FMDInfo.SectorsPerBlock = g_FMDInfo.BlockSize / g_FMDInfo.SectorSize;
        g_FMDInfo.SectorInfoOffset = 0;
    }                
}

BOOLEAN InitializeFlash(volatile ULONG* pBaseAddress, ULONG FlashLength)
{
    UCHAR nCount = 0;

    ASSERT(pBaseAddress);
    ASSERT(FlashLength);

    if (!pBaseAddress || !FlashLength)
        return(FALSE);

    if (!g_dwWriteBufferSize || !g_FMDInfo.BlockSize)
    {

        // Assume the flash part is an Intel Strataflash - first check the manufacturer code.
        //
//dcv        g_bPairedFlash = TRUE;    // Assume flash is paired.
        WRITE_COMMAND(pBaseAddress, READ_IDENT_CMD);
        if (!CHECK_STATUS_INDEXED(pBaseAddress, QS_MFGCODE_OFFSET, MFGCODE_INTEL))
        {
            g_bPairedFlash = FALSE;        // Maybe it's not paired?
            WRITE_COMMAND(pBaseAddress, READ_IDENT_CMD);
            if (!CHECK_STATUS_INDEXED(pBaseAddress, QS_MFGCODE_OFFSET, MFGCODE_INTEL))
            {
                // This isn't an Intel flash part.
                DEBUGMSG(1, (TEXT("ERROR: InitializeFlash: invalid manufacturing code.\r\n")));
                return(FALSE);
            }
        }

        // Look for a Common Flash Interface (CFI).
        //
        WRITE_COMMAND(pBaseAddress, READ_QUERY_CMD);
        if (!CHECK_STATUS_INDEXED(pBaseAddress, QS_IDSTRING_OFFSET,  IDSTRING_Q) ||
            !CHECK_STATUS_INDEXED(pBaseAddress, QS_IDSTRING_OFFSET + 1, IDSTRING_R) ||
            !CHECK_STATUS_INDEXED(pBaseAddress, QS_IDSTRING_OFFSET + 2, IDSTRING_Y))
        {
            // This flash doesn't support CFI, so it's not a Strataflash.
            DEBUGMSG(1, (TEXT("ERROR: InitializeFlash: didn't find StrataFlash CFI.\r\n")));
            return(FALSE);
        }

        // We're pretty sure this is an Intel Strataflash part at this point - use the CFI to
        // collect information on it (we're still in query mode).  Also, we'll assume that both
        // high and low word flash parts are the same from here on out (if paired).
        //
        for (nCount = 0 ; nCount < sizeof(FLASH_SYSINTERFACE_INFO) ; nCount++)
        {
            *((PUCHAR)&g_FMDInfo.SysInt + nCount) = (UCHAR)(READ_FLASH_INDEXED(pBaseAddress, QS_SYSINTF_OFFSET + nCount) & 0xFF);
        }
        for (nCount = 0 ; nCount < sizeof(FLASH_GEOMETRY_INFO) ; nCount++)
        {
            *((PUCHAR)&g_FMDInfo.Geometry + nCount) = (UCHAR)(READ_FLASH_INDEXED(pBaseAddress, QS_DEVGEOM_OFFSET + nCount) & 0xFF);
        }

        // The block erase code assumes a single block per erase region - check for that here...
        //
        if (g_FMDInfo.Geometry.NumEraseBlocks != 1)
        {
            DEBUGMSG(1, (TEXT("ERROR: InitializeFlash: more than one block per erase region (%d).\r\n"), g_FMDInfo.Geometry.NumEraseBlocks));
            return(FALSE);
        }

        // Compute block size and the total number of blocks here.  Since we know an erase region contains
        // only one block, the erase region size is equal to the block size.

        // Note that the flash block size is 128KB, if paired, we have two of the 16-bit parts and the block size is effectively 256KB.
        g_FMDInfo.BlockSize = (g_FMDInfo.Geometry.EraseRegionSize * REGION_SIZE_MULT);
        if (g_bPairedFlash) 
        {
            g_FMDInfo.BlockSize *= 2;
        }

        g_dwWriteBufferSize = g_bPairedFlash ? (1 << g_FMDInfo.Geometry.WriteBuffSize) * 2 : (1 << g_FMDInfo.Geometry.WriteBuffSize);

        // Put the Flash into a known state (READ_ARRAY mode with WRITE-ENABLE disabled).
        //
        WRITE_COMMAND(pBaseAddress, READ_ARRAY_CMD);        
    }
    
        
    // In order for all the math to work out later, we require that the flash base address be block-aligned and that the flash length be 
    // an integral number of blocks.
    if (!IS_BLOCK_ALIGNED(pBaseAddress) || !IS_BLOCK_ALIGNED(FlashLength))
    {
        DEBUGMSG(1, (TEXT("ERROR: InitializeFlash: base address and length must be block-aligned (Base=0x%x, Length=0x%x).\r\n"), (ULONG)pBaseAddress, FlashLength));
        return(FALSE);
    }

    g_FMDInfo.BaseAddress = (ULONG)pBaseAddress;
    g_FMDInfo.FlashLength = (ULONG)FlashLength;
    
    // Note that we need to adjust the total available blocks if the caller specified a non-zero flash offset value.
    g_FMDInfo.TotalFlashBlocks    = (FlashLength / g_FMDInfo.BlockSize);

    DefineLayout();

    return TRUE;
}

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       CheckStatus()

Description:    Checks status of the operation. 

Parameters:     ulBlockAddress - The block address to write status command to
                       fLockCmd - TRUE if this is a Set/Clear Lock-Bit command.  

Returns:        None.
------------------------------------------------------------------------------*/

BOOL CheckStatus(ULONG ulBlockAddress, BOOL fLockCmd)
{
    ULONG ulStatus;
    ULONG ulCount = 0;
    while (!CHECK_STATUS(ulBlockAddress, STATUS_READY_MASK))
    {
        if ( ulCount++ == CHECK_STATUS_TIMEOUT )
        {
            DEBUGMSG(1, (TEXT("STRATA Error: Timed out checking status\r\n")));
            break;
        }
    }

    ulStatus = READ_FLASH(ulBlockAddress);

    if (ulStatus == (ULONG)CREATE_MASK(STATUS_READY_MASK))
    {
        // Success
        return TRUE;
    }

    //
    // Print appropriate error...
    //
    
    DWORD dwBlock = (ulBlockAddress - g_FMDInfo.BaseAddress) / g_FMDInfo.BlockSize;
    
    if ((ulStatus & STATUS_ERROR_VOLTAGE) == STATUS_ERROR_VOLTAGE)
        DEBUGMSG(1, (TEXT("STRATA Error: Voltage Range Error ... Lower flash.\r\n")));

    else if ((ulStatus & STATUS_ERROR_COMMAND) == STATUS_ERROR_COMMAND)
        DEBUGMSG(1, (TEXT("STRATA Error: Command Sequence Error ... Lower flash.\r\n")));

    else if ((ulStatus & STATUS_ERROR_LOCKED) == STATUS_ERROR_LOCKED)
        DEBUGMSG(1, (TEXT("STRATA Error: Block %d locked ... Lower flash.\r\n"), dwBlock));

    else if ((ulStatus & STATUS_ERROR_SR5) == STATUS_ERROR_SR5)
    {
        if (fLockCmd)
            DEBUGMSG(1, (TEXT("STRATA Error: Clear Lock Bits Error for Block %d ... Lower flash.\r\n"), dwBlock));
        else
            DEBUGMSG(1, (TEXT("STRATA Error: Erase Error for Block %d ... Lower flash.\r\n"), dwBlock));
    }

    else if ((ulStatus & STATUS_ERROR_SR4) == STATUS_ERROR_SR4)
    {
        if (fLockCmd)
            DEBUGMSG(1, (TEXT("STRATA Error: Set Lock Bits Error for Block %d ... Lower flash.\r\n"), dwBlock));
        else
            DEBUGMSG(1, (TEXT("STRATA Error: Programming Error for Block %d ... Lower flash.\r\n"), dwBlock));
    }

    if (g_bPairedFlash)
    {
        if ((ulStatus & UPPER(STATUS_ERROR_VOLTAGE)) == UPPER(STATUS_ERROR_VOLTAGE))
            DEBUGMSG(1, (TEXT("STRATA Error: Voltage Range Error ... Upper flash.\r\n")));
        
        else if ((ulStatus & UPPER(STATUS_ERROR_COMMAND)) == UPPER(STATUS_ERROR_COMMAND))
            DEBUGMSG(1, (TEXT("STRATA Error: Command Sequence Error ... Upper flash.\r\n")));
        
        else if ((ulStatus & UPPER(STATUS_ERROR_LOCKED)) == UPPER(STATUS_ERROR_LOCKED))
            DEBUGMSG(1, (TEXT("STRATA Error: Block %d locked ... Upper flash.\r\n"), dwBlock));
        
        else if ((ulStatus & UPPER(STATUS_ERROR_SR5)) == UPPER(STATUS_ERROR_SR5))
        {
            if (fLockCmd)
                DEBUGMSG(1, (TEXT("STRATA Error: Clear Lock Bits Error for Block %d ... Upper flash.\r\n"), dwBlock));
            else
                DEBUGMSG(1, (TEXT("STRATA Error: Erase Error for Block %d ... Upper flash.\r\n"), dwBlock));
        }

        else if ((ulStatus & UPPER(STATUS_ERROR_SR4)) == UPPER(STATUS_ERROR_SR4))
        {
            if (fLockCmd)
                DEBUGMSG(1, (TEXT("STRATA Error: Set Lock Bits Error for Block %d ... Upper flash.\r\n"), dwBlock));
            else
                DEBUGMSG(1, (TEXT("STRATA Error: Programming Error for Block %d ... Upper flash.\r\n"), dwBlock));
        }
    }

    // Clear the status register
    WRITE_COMMAND(ulBlockAddress, CLEAR_STATUS_CMD);

    return FALSE;

}

BOOL SignBlock(volatile ULONG ulBlockAddress, PUCHAR pusSignature)
{    
    if (g_bXIPEntire)
        return TRUE;
    
    SECTOR_ADDR ulSignatureStart = BLOCK_SIG_LOC(ulBlockAddress, g_FMDInfo.BlockSize);
    DWORD dwBytesWritten = 0;

    dwBytesWritten = DoBufferedWrite(ulBlockAddress, ulSignatureStart, pusSignature, BLOCK_SIG_BYTES);

    return (dwBytesWritten == BLOCK_SIG_BYTES);
}

BOOL VerifySignatures()
{
    if (g_bXIPEntire)
        return TRUE;
    
    int iRetVal;
    ULONG ulBlockStart = g_FMDInfo.BaseAddress;

    for (UINT i = 0; i < g_FMDInfo.TotalFlashBlocks; i++)
    {
        // compare the signatures
        iRetVal = memcmp((void *) BLOCK_SIG_LOC(ulBlockStart, g_FMDInfo.BlockSize),
        				 (void *) gc_dwBlockSig, 
        				 BLOCK_SIG_BYTES);

        if (iRetVal != 0)
        {
            DEBUGMSG(1, (TEXT("VerifySignatures: invalid block detected, calling FMD_EraseBlock\r\n")));
            if (!FMD_EraseBlock(i))
            {
                DEBUGMSG(1, (TEXT("VerifySignatures: error in FMD_EraseBlock, bailing\r\n")));
                return FALSE;
            }
        }

        // increment to the next block
        ulBlockStart += g_FMDInfo.BlockSize;
    }

    return TRUE;
}

⌨️ 快捷键说明

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