📄 fmd.cpp
字号:
DEBUGMSG(ZONE_ERROR, (TEXT("ERROR: FMD_Init: invalid flash memory base and/or length specified by caller.\r\n")));
goto EXIT;
}
else {
m_dwBaseAddr = pRegIn->MemBase.Reg[0];
m_dwLength = pRegIn->MemLen.Reg[0];
}
#else
{
// Get info from the registry
HKEY hkDevice = OpenDeviceKey(lpActiveReg);
CReg regDevice(hkDevice, TEXT(""));
if (hkDevice == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("ERROR: FMD_Init: OpenDeviceKey(%s) failed.\r\n"), lpActiveReg));
goto EXIT;
}
RegCloseKey(hkDevice);
DDKWINDOWINFO dwi;
dwi.cbSize = sizeof(dwi);
if (DDKReg_GetWindowInfo(regDevice, &dwi) != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ERROR, (TEXT("ERROR: FMD_Init: DDKReg_GetWindowInfo() failed.\r\n")));
goto EXIT;
}
// The first memory window contains the base address and length of our flash part.
if (dwi.dwNumMemWindows == 0) {
DEBUGMSG(ZONE_ERROR, (TEXT("ERROR: FMD_Init: DDKReg_GetWindowInfo() found no windows.\r\n")));
goto EXIT;
}
m_dwBaseAddr = dwi.memWindows[0].dwBase;
m_dwLength = dwi.memWindows[0].dwLen;
}
#endif
if (!AM29LV800_Init(m_dwBaseAddr - CB_USABLE_FLASH_OFFSET)) {
DEBUGMSG(ZONE_ERROR, (TEXT("ERROR: FMD_Init: AM29LV800_Init(0x%x) failed.\r\n"), m_dwBaseAddr));
goto EXIT;
}
m_cbSector = CB_SECTOR;
m_cbBlock = CB_BLOCK;
m_cBlocks = BLOCK_COUNT;
if (!DefineLayout()) {
DEBUGMSG(ZONE_ERROR, (TEXT("ERROR: FMD_Init: DefineLayout failed.\r\n")));
goto EXIT;
}
#ifndef UNDER_BOOTLOADER
// Verify that the block signatures are all intact
if (!VerifySignatures()) {
DEBUGMSG(ZONE_ERROR, (TEXT("ERROR: FMD_Init: Error while trying to verify block signatures.\r\n")));
goto EXIT;
}
#endif
pvRet = VALID_FMD_HANDLE;
EXIT:
return pvRet;
}
virtual BOOL EraseBlock(BLOCK_ID blockID) {
DEBUGMSG(ZONE_INIT, (TEXT("FMD_EraseBlock(0x%x)\r\n"), blockID));
return AM29LV800_EraseFlash((blockID * CB_BLOCK) + CB_USABLE_FLASH_OFFSET, CB_BLOCK);
}
virtual BOOL WriteSector (SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors) {
DEBUGMSG(ZONE_INIT, (TEXT("FMD_WriteSector(0x%x, 0x%x, 0x%x, 0x%x)\r\n"), startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors));
volatile SECTOR_ADDR physicalSectorAddr = 0;
volatile SECTOR_ADDR physicalSectorInfoAddr = 0;
BOOL fRet = FALSE;
//----- 1. Check the input parameters -----
// NOTE: The FAL insures that the starting sector address is in the allowable range.
if((dwNumSectors == 0) || ((pSectorBuff == NULL) && (pSectorInfoBuff == NULL)))
{
return(FALSE);
}
//----- 2. Process the write request(s)... -----
for(DWORD i = startSectorAddr; i < (startSectorAddr + dwNumSectors); i++)
{
//----- Compute the physical address for the requested -----
GetPhysicalSectorAddress(i, (PSECTOR_ADDR)&physicalSectorAddr, (PSECTOR_ADDR)&physicalSectorInfoAddr);
//----- Write the necessary sector data -----
if(pSectorBuff)
{
fRet = AM29LV800_WriteFlash(physicalSectorAddr, pSectorBuff, m_cbSector);
if (fRet == FALSE) {
goto exit;
}
pSectorBuff += m_cbSector;
}
//----- Write the necessary sector info data (metadata) -----
if (!m_fXIPEntire && pSectorInfoBuff)
{
fRet = AM29LV800_WriteFlash(physicalSectorInfoAddr, (PBYTE)pSectorInfoBuff, sizeof(SectorInfo));
if (fRet == FALSE) {
goto exit;
}
pSectorInfoBuff++;
}
}
fRet = TRUE;
exit:
return fRet;
}
protected:
BOOL WriteBlock (DWORD dwBlock, LPBYTE pBuffer, DWORD dwStartByteOffset, DWORD dwByteLen)
{
if (!EraseBlock(dwBlock))
{
DEBUGMSG(ZONE_ERROR, (TEXT("ReadWriteReserved: FMD_EraseBlock failed 0x%x.\r\n"), dwBlock));
return FALSE;
}
DWORD dwAddr = CB_USABLE_FLASH_OFFSET + (dwBlock * m_cbBlock) + dwStartByteOffset;
if (!AM29LV800_WriteFlash(dwAddr, pBuffer, dwByteLen)) {
return FALSE;
}
return TRUE;
}
};
#ifdef UNDER_BOOTLOADER
static BYTE s_rgbFmdBuffer[sizeof(CAmdNorFmd)];
static CFmd *s_pFmd = (CFmd*) s_rgbFmdBuffer;
#else
static CAmdNorFmd s_fmd;
CFmd *s_pFmd = &s_fmd;
#endif
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: FMD_Init()
Description: This function is called by the by the DLLMain and initializes
the flash memory bank.
Parameters: lpActiveReg [in]
Pointer to the active registry string used to find device
information from the registry. Set to NULL if not needed.
pRegIn [in]
Pointer to a PCI_REG_INFO structure. Used to find flash
hardware on PCI hardware. Set to NULL if not needed.
pRegOut [out]
Pointer to a PCI_REG_INFO structure. Used to return flash
information. Set to NULL if not needed.
Return Values: A handle that can be used in a call to FMD_Deinit. It is the
responsibility of the specific Flash Media Driver (FMD)
implementation to determine what this value represents.
A value of 0 represents failure.
-------------------------------------------------------------------------------*/
PVOID FMD_Init(LPCTSTR lpActiveReg, PPCI_REG_INFO pRegIn, PPCI_REG_INFO pRegOut)
{
PREFAST_ASSERT(s_pFmd);
#ifdef UNDER_BOOTLOADER
new (s_pFmd) CAmdNorFmd;
#endif
return s_pFmd->Init(lpActiveReg, pRegIn, pRegOut);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: FMD_Deinit()
Description: This function provides the code to clean-up any resources
the FMD may have acquired in the course of the operation.
Parameters: hFMD [in]
The handle returned from FMD_Init.
Return Values: A boolean indicating function result.
TRUE on success.
FALSE on failure.
Remarks: Always returns TRUE.
-------------------------------------------------------------------------------*/
BOOL FMD_Deinit(PVOID pv)
{
PREFAST_ASSERT(s_pFmd);
BOOL fRet = s_pFmd->Deinit(pv);
#ifdef UNDER_BOOTLOADER
s_pFmd->~CFmd();
#endif
return fRet;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: FMD_GetInfo()
Description: This function reports the characteristics for the
underlying flash memory.
Parameters: pFlashInfo [out]
A pointer to a structure that contains the size
characteristics for the flash memory device.
Return Values: A boolean indicating function result.
TRUE on success.
FALSE on failure.
Remarks: Even for NOR flash memory, the media must be logically divided
into sectors. It is the responsibility of the specific FMD
implementation to determine how this is accomplished.
To compute the number of sectors per block, divide the total
Flash block size by the number of bytes per sector and the
number bytes for the sector metadata.
-------------------------------------------------------------------------------*/
BOOL FMD_GetInfo(PFlashInfo pFlashInfo)
{
PREFAST_ASSERT(s_pFmd);
return s_pFmd->GetInfo(pFlashInfo);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: FMD_GetInfoEx()
Description: Determines the size characteristics for the Flash memory device.
Includes support for multiple regions.
Notes: If pFlashInfo is NULL, then this just returns the number of reserved regions.
Returns: Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL FMD_GetInfoEx(PFlashInfoEx pFlashInfo, PDWORD pdwNumRegions)
{
PREFAST_ASSERT(s_pFmd);
return s_pFmd->GetInfoEx(pFlashInfo, pdwNumRegions);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: FMD_GetPhysSectorAddr()
Description: Returns the physical address for the physical sector passed in.
Returns: None
------------------------------------------------------------------------------*/
VOID FMD_GetPhysSectorAddr (DWORD dwSector, PSECTOR_ADDR pStartSectorAddr)
{
PREFAST_ASSERT(s_pFmd);
return s_pFmd->GetPhysSectorAddr(dwSector, pStartSectorAddr);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: FMD_GetBlockStatus()
Description: This function returns the status of a block.
Returns the status of a block. For read-only blocks, checks
the sector info data for the first sector of the block. Block
is always good, so no need to check.
Parameters: blockID [in]
The block number used to check status.
Return Values: A double word value describing the status of the block. The
values defined are as follows:
Value Description
----- -----------
BLOCK_STATUS_UNKNOWN The status could not be determined
as a result of a read error.
BLOCK_STATUS_BAD The block is bad.
BLOCK_STATUS_READONLY The block is read-only.
BLOCK_STATUS_RESERVED The block is reserved.
Remarks: It is the responsibility of the caller of the FMD to check and
interpret the block status. If the FMD is used with the Flash
Abstraction Layer (FAL), then a read-only block will be mapped
to a logical sector but will not allow write access. A
reserved block will not be mapped to a logical sector and
therefore will not be used by the FAL. A bad block will be
ignored.
-------------------------------------------------------------------------------*/
DWORD FMD_GetBlockStatus(BLOCK_ID blockID)
{
PREFAST_ASSERT(s_pFmd);
return s_pFmd->GetBlockStatus(blockID);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: FMD_SetBlockStatus()
Description: This function sets the status of a block.
Parameters: blockID [in]
The block number used to set status.
dwStatus [in]
The status value to set. The values that can be used to
describe the status of the block are as follows:
Value Description
----- -----------
BLOCK_STATUS_BAD The block is bad.
BLOCK_STATUS_READONLY The block is read-only.
BLOCK_STATUS_RESERVED The block is reserved.
Return Values: A boolean indicating function result.
TRUE on success.
FALSE on failure.
------------------------------------------------------------------------------*/
BOOL FMD_SetBlockStatus(BLOCK_ID blockID, DWORD dwStatus)
{
PREFAST_ASSERT(s_pFmd);
return s_pFmd->SetBlockStatus(blockID, dwStatus);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -