📄 fmd.cpp
字号:
}
ASSERT(0);
return;
}
virtual BOOL DefineLayout()
{
PFlashRegion pRegion = NULL;
ASSERT(m_cbSector);
// Find the MBR to determine if there is a flash layout sector
LPBYTE pFlashAddress = (LPBYTE)m_dwBaseAddr;
m_cRegions = 0;
// Don't read FLS if g_bXIPEntire is set.
if (!m_fXIPEntire)
{
for (UINT i = 0; i < m_cBlocks; i++)
{
// compare the signatures
if (IS_VALID_BOOTSEC(pFlashAddress))
{
pFlashAddress += m_cbSector;
if (IS_VALID_FLS(pFlashAddress))
{
// Cache the flash layout sector information
PFlashLayoutSector pFLS = (PFlashLayoutSector)pFlashAddress;
m_cReserved = pFLS->cbReservedEntries / sizeof(ReservedEntry);
m_cRegions = pFLS->cbRegionEntries / sizeof(FlashRegion);
// ReservedEntry table starts at the end of the PFlashLayoutSector struct.
PReservedEntry pEntry = (PReservedEntry)(pFLS+1);
if (m_cReserved)
{
#ifdef UNDER_BOOTLOADER
// Not enough room in the statically allocated buffer to store reserved table.
if (m_cReserved > MAX_RESERVES)
return FALSE;
#else
m_pReservedTable = (PReservedEntry)LocalAlloc (0, m_cReserved * sizeof(ReservedEntry));
if (!m_pReservedTable)
return FALSE;
#endif
memcpy (m_pReservedTable, pEntry, m_cReserved * sizeof(ReservedEntry));
}
// FlashRegion table starts after the ReservedEntry table.
if (m_cRegions)
{
pRegion = (PFlashRegion)((LPBYTE)pEntry + pFLS->cbReservedEntries);
}
}
break;
}
pFlashAddress += m_cbBlock;
}
}
if (!m_cRegions)
{
m_cRegions = 1;
}
#ifdef UNDER_BOOTLOADER
// Not enough room in the statically allocated buffer to store region table.
if (m_cRegions > MAX_REGIONS)
return FALSE;
#else
m_pRegionTable = (PFlashRegion)LocalAlloc (0, m_cRegions * sizeof(FlashRegion));
m_pStartSectorTable = (PDWORD)LocalAlloc (0, m_cRegions * sizeof(DWORD));
if (!m_pRegionTable || !m_pStartSectorTable)
return FALSE;
#endif
if (pRegion)
{
memcpy (m_pRegionTable, pRegion, m_cRegions * sizeof(FlashRegion));
}
else
{
m_pRegionTable[0].dwStartPhysBlock = 0;
m_pRegionTable[0].dwNumPhysBlocks = m_cBlocks;
m_pRegionTable[0].dwBytesPerBlock = m_cbBlock;
m_pRegionTable[0].dwNumLogicalBlocks = FIELD_NOT_IN_USE;
if (m_fXIPEntire)
{
m_pRegionTable[0].regionType = XIP;
m_pRegionTable[0].dwSectorsPerBlock = m_cbBlock / m_cbSector;
m_pRegionTable[0].dwCompactBlocks = 0;
}
else
{
m_pRegionTable[0].regionType = FILESYS;
m_pRegionTable[0].dwSectorsPerBlock = m_cbBlock / (m_cbSector + sizeof(SectorInfo));
m_pRegionTable[0].dwCompactBlocks = DEFAULT_COMPACTION_BLOCKS;
}
}
DWORD dwStartSector = 0;
for (DWORD iRegion = 0; iRegion < m_cRegions; iRegion++)
{
m_pStartSectorTable[iRegion] = dwStartSector;
dwStartSector += m_pRegionTable[iRegion].dwNumPhysBlocks * m_pRegionTable[iRegion].dwSectorsPerBlock;
}
return TRUE;
}
virtual BOOLEAN SetBlockLock(BLOCK_ID blockID, ULONG NumBlocks, BOOL fLock) {
return FALSE;
}
virtual BOOL ReadWriteReserved (PReservedReq pReq, BOOL fRead)
{
PCSTR szName = pReq->szName;
LPBYTE pBuffer = pReq->pBuffer;
for (DWORD i = 0; i < m_cReserved; i++)
{
if (_strnicmp(szName, m_pReservedTable[i].szName, RESERVED_NAME_LEN) == 0)
{
//
// Found a region name match
//
// Verify the request is in the valid range
DWORD dwRegionSize = m_pReservedTable[i].dwNumBlocks * m_cbBlock;
if ((pReq->dwStart >= dwRegionSize) || (pReq->dwStart + pReq->dwLen > dwRegionSize))
{
DEBUGMSG(ZONE_ERROR, (TEXT("ReadWriteReserved: Invalid request. Start: 0x%x. Len: 0x%x\r\n"), pReq->dwStart, pReq->dwLen));
goto Error;
}
if (fRead)
{
PVOID pStartAddress = (PVOID)(m_dwBaseAddr + m_pReservedTable[i].dwStartBlock * m_cbBlock + pReq->dwStart);
memcpy (pBuffer, pStartAddress, pReq->dwLen);
}
else
{
//
// Write flash case
//
if (pReq->dwStart % m_cbSector)
{
DEBUGMSG(ZONE_ERROR, (TEXT("ReadWriteReserved: Invalid write request. Start: 0x%x is not sector aligned.\r\n"), pReq->dwStart));
goto Error;
}
DWORD dwStartBlock = pReq->dwStart / m_cbBlock + m_pReservedTable[i].dwStartBlock;
DWORD dwEndBlock = (pReq->dwStart + pReq->dwLen - 1) / m_cbBlock + m_pReservedTable[i].dwStartBlock;
DWORD dwWriteRemain = pReq->dwLen;
for (DWORD iBlock = dwStartBlock; iBlock <= dwEndBlock; iBlock++)
{
DWORD dwBlockWriteLen = MIN (m_cbBlock, dwWriteRemain);
DWORD dwBlockOffset = 0;
// If this is the first block, then start at the appropriate offset within the block
if (iBlock == dwStartBlock)
{
dwBlockOffset = pReq->dwStart % m_cbBlock;
dwBlockWriteLen = MIN (dwBlockWriteLen, m_cbBlock - dwBlockOffset);
}
if (!EraseBlock(iBlock)) {
DEBUGMSG(ZONE_ERROR, (TEXT("ReadWriteReserved: EraseBlock failed (0x%x).\r\n"), iBlock));
goto Error;
}
if (!WriteBlock (iBlock, pBuffer, dwBlockOffset, dwBlockWriteLen))
{
DEBUGMSG(ZONE_ERROR, (TEXT("ReadWriteReserved: WriteBlock failed (0x%x).\r\n"), iBlock));
goto Error;
}
pBuffer += dwBlockWriteLen;
dwWriteRemain -= dwBlockWriteLen;
}
}
return TRUE;
}
}
Error:
return FALSE;
}
BOOL RawWriteBlocks (PRawWriteBlocksReq pReq)
{
DWORD dwEndBlock = pReq->dwStartBlock + pReq->dwNumBlocks - 1;
LPBYTE pBuffer = pReq->pBuffer;
BOOL fRet = FALSE;
if (pReq->dwStartBlock >= m_cBlocks ||
dwEndBlock >= m_cBlocks ||
dwEndBlock < pReq->dwStartBlock)
{
DEBUGMSG(ZONE_ERROR, (TEXT("RawWriteBlocks: Invalid request: (0x%x, 0x%x)\r\n"), pReq->dwStartBlock, pReq->dwNumBlocks));
goto Error;
}
if (pReq->cbBuffer < (pReq->dwNumBlocks * m_cbBlock))
{
DEBUGMSG(ZONE_ERROR, (TEXT("RawWriteBlocks: Insufficient buffer: (0x%x)\r\n"), pReq->cbBuffer));
goto Error;
}
for (DWORD dwBlock = pReq->dwStartBlock; dwBlock <= dwEndBlock; dwBlock++)
{
if (!WriteBlock (dwBlock, pBuffer, 0, m_cbBlock))
{
DEBUGMSG(ZONE_ERROR, (TEXT("RawWriteBlocks: WriteBlock failed (0x%x).\r\n"), dwBlock));
goto Error;
}
PREFAST_SUPPRESS (12008, "pReq->dwNumBlocks is validated above");
pBuffer += m_cbBlock;
}
fRet = TRUE;
Error:
return fRet;
}
static DWORD BLOCK_SIG_LOC(DWORD dwBlockStart, DWORD cbBlock)
{
return dwBlockStart + cbBlock - sizeof(m_rgdwBlockSig);
}
BOOL VerifySignatures()
{
if (m_fXIPEntire)
return TRUE;
ULONG iRetVal;
ULONG ulBlockStart;
for (UINT iRegion = 0; iRegion < m_cRegions; iRegion++)
{
if (m_pRegionTable[iRegion].regionType == XIP)
continue;
ulBlockStart = m_dwBaseAddr + (m_pRegionTable[iRegion].dwStartPhysBlock * m_cbBlock);
for (UINT iBlock = m_pRegionTable[iRegion].dwStartPhysBlock; iBlock < m_pRegionTable[iRegion].dwStartPhysBlock + m_pRegionTable[iRegion].dwNumPhysBlocks; iBlock++)
{
if (!(FMD_GetBlockStatus(iBlock) & BLOCK_STATUS_RESERVED))
{
// compare the signatures
iRetVal = memcmp((void *) BLOCK_SIG_LOC(ulBlockStart, m_cbBlock),
m_rgdwBlockSig,
sizeof(m_rgdwBlockSig));
if (iRetVal != 0)
{
DEBUGMSG(ZONE_ERROR, (TEXT("VerifySignatures: invalid block detected, calling FMD_EraseBlock\r\n")));
if (!FMD_EraseBlock(iBlock))
{
DEBUGMSG(ZONE_ERROR, (TEXT("VerifySignatures: error in FMD_EraseBlock, bailing\r\n")));
return FALSE;
}
}
}
// increment to the next block
ulBlockStart += m_cbBlock;
}
}
return TRUE;
}
virtual BOOL WriteBlock (DWORD dwBlock, LPBYTE pBuffer, DWORD dwStartByteOffset, DWORD dwByteLen) = 0;
static const DWORD m_rgdwBlockSig[8];
DWORD m_dwBaseAddr;
DWORD m_dwLength;
DWORD m_cbSector;
DWORD m_cbBlock;
DWORD m_cBlocks;
DWORD m_cRegions;
DWORD m_cReserved;
BOOL m_fXIPEntire;
BOOL m_fUpdateMode;
#ifdef UNDER_BOOTLOADER
ReservedEntry m_pReservedTable[MAX_RESERVES];
FlashRegion m_pRegionTable[MAX_REGIONS];
DWORD m_pStartSectorTable[MAX_REGIONS];
#else
// Dynamically allocate this under the OS
PReservedEntry m_pReservedTable;
PFlashRegion m_pRegionTable;
PDWORD m_pStartSectorTable;
#endif
};
// We sign the last 32 bytes of each flash block so we can verify that the block
// is valid at boot time. OEMs should feel free to modify gc_dwBlockSig
const DWORD CNorFmd::m_rgdwBlockSig[8] = {0xC1552106, 0xDF9C29D5, 0xBAB8EAB8, 0x82D3F9F3,
0x3B438A47, 0xA9D92AE6, 0x09396731, 0x12BF6753};
#define CB_USABLE_FLASH_OFFSET IMAGE_IPL_SIZE
#define CB_USABLE_FLASH (AMD_FLASH_SIZE - CB_USABLE_FLASH_OFFSET)
#define CB_BLOCK 0x10000
#define CB_SECTOR 0x1000
#define BLOCK_COUNT (CB_USABLE_FLASH / CB_BLOCK)
class CAmdNorFmd : public CNorFmd {
public:
CAmdNorFmd() : CNorFmd() {}
virtual ~CAmdNorFmd() {}
virtual PVOID Init(LPCTSTR lpActiveReg, PPCI_REG_INFO pRegIn, PPCI_REG_INFO pRegOut) {
PVOID pvRet = NULL;
DEBUGMSG(ZONE_INIT, (TEXT("FMD_Init(0x%x, 0x%x, 0x%x)\r\n"), lpActiveReg, pRegIn, pRegOut));
#ifdef UNDER_BOOTLOADER
// Get flash base address and length from caller.
if (!pRegIn || !pRegIn->MemBase.Num || !pRegIn->MemLen.Num) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -