fmd_tyax.cpp
来自「该BSP是基于PXA270+WINCE的BSP」· C++ 代码 · 共 1,678 行 · 第 1/5 页
CPP
1,678 行
PVOID FMD_Init(LPCTSTR lpActiveReg, PPCI_REG_INFO pRegIn, PPCI_REG_INFO pRegOut)
{
ULONG* pBaseAddress = NULL;
ULONG FlashLength = 0;
#ifndef UNDER_BOOTLOADER
BOOL bLastMode;
#endif
DWORD dwLen = sizeof(DWORD);
struct FMDHAL_CmdStruct CurrCmd;
DBGMSG(1, (TEXT("FMD_Init@ 0x%x:\r\n"), FMD_Init));
#ifdef READ_FROM_REGISTRY
if (lpActiveReg != NULL)
{
DDKWINDOWINFO dwi;
HKEY hConfig;
// Get flash information from the registry.
hConfig = OpenDeviceKey((LPCTSTR)lpActiveReg);
if (hConfig == NULL)
{
LOGMSG(1, (TEXT("ERROR: FMD_Init: OpenDeviceKey failed.\r\n")));
return(NULL);
}
dwi.cbSize = sizeof(dwi);
if (DDKReg_GetWindowInfo(hConfig, &dwi) != ERROR_SUCCESS)
{
LOGMSG(1, (TEXT("ERROR: FMD_Init: DDKReg_GetWindowInfo() failed.\r\n")));
return(NULL);
}
// The first memory window contains the base address and length of our flash part.
if (dwi.dwNumMemWindows)
{
pBaseAddress = (ULONG*)(dwi.memWindows[0].dwBase);
FlashLength = (ULONG)(dwi.memWindows[0].dwLen);
}
HINSTANCE hCoreDll = LoadLibrary (TEXT("coredll.dll"));
if (hCoreDll)
{
pRegQueryValueEx fnRegQueryValueEx = (pRegQueryValueEx)GetProcAddress(hCoreDll, TEXT("RegQueryValueExW"));
if (fnRegQueryValueEx)
{
fnRegQueryValueEx(hConfig, L"XIPEntireFlash", 0, NULL, (LPBYTE)&g_bXIPEntire, &dwLen);
fnRegQueryValueEx(hConfig, L"UpdateMode", 0, NULL, (LPBYTE)&g_bUpdateMode, &dwLen);
fnRegQueryValueEx(hConfig, L"BlockSize", 0, NULL, (LPBYTE)&g_FMDInfo.BlockSize, &dwLen);
fnRegQueryValueEx(hConfig, L"WriteBufferSize", 0, NULL, (LPBYTE)&g_dwWriteBufferSize, &dwLen);
// new
fnRegQueryValueEx(hConfig, L"ActualFlashBase", 0, NULL, (LPBYTE)&g_FMDInfo.ActualFlashBase, &dwLen);
if (fnRegQueryValueEx(hConfig, L"IsPairedFlash", 0, NULL, (LPBYTE)&g_bPairedFlash, &dwLen) != ERROR_SUCCESS)
{
LOGMSG(1, (TEXT("FMD_Init: Warning, IsPairedFlash not specified in registry. Using value of 0.\r\n")));
}
if (fnRegQueryValueEx(hConfig, L"SectorSize", 0, NULL, (LPBYTE)&g_FMDInfo.SectorSize, &dwLen) != ERROR_SUCCESS)
{
SYSTEM_INFO SystemInfo;
GetSystemInfo (&SystemInfo);
g_FMDInfo.SectorSize = SystemInfo.dwPageSize;
}
}
FreeLibrary (hCoreDll);
}
}
#else
// Get flash base address and length from caller.
DBGMSG(1, (TEXT("FMD_Init: pMemBaseNum = %x MemLenNum = %x \r\n"), pRegIn->MemBase.Num, pRegIn->MemLen.Num));
DBGMSG(1, (TEXT("FMD_Init: pMemBaseREG = %x MemLenNum = %x \r\n"), pRegIn->MemBase.Reg[0], pRegIn->MemLen.Num));
//if (!pRegIn || !pRegIn->MemLen.Num) // Use this line for Eboot FMD testing - MemLen.Num is arriving as 0 in eboot
if (!pRegIn || !pRegIn->MemBase.Num || !pRegIn->MemLen.Num)
{
LOGMSG(1, (TEXT("ERROR: FMD_Init: invalid flash memory base and/or length specified by caller.\r\n")));
return(NULL);
} else
{
pBaseAddress = (ULONG*)pRegIn->MemBase.Reg[0];
FlashLength = pRegIn->MemLen.Reg[0];
g_FMDInfo.ActualFlashBase = pRegIn->IoBase.Reg[0]; // the KVA of the base address of Flash
DBGMSG(1, (TEXT("FMD_Init: pBaseAddress = %x IO = %x \r\n"), pBaseAddress ,g_FMDInfo.ActualFlashBase));
// Temporary work-arounds for the bootloader
if (!g_FMDInfo.SectorSize)
{
g_FMDInfo.SectorSize = 4 * 1024;
}
}
#endif // READ_FROM_REGISTRY.
#ifndef UNDER_BOOTLOADER
DBGMSG(1,(TEXT("FMD_Init: ->SetKMode\r\n")));
// Run in kernel mode.
bLastMode = SetKMode(TRUE);
/* // Make a RAM copy of the flash init code in case this driver is executing directly from the flash part
//
DWORD codeSize = (DWORD)UserKInfo[KINX_PAGESIZE]; // Copy 1 page of code, should be sufficient to contain InitializeFlash() funciton
BOOL (*pfnInitializeFlash)(volatile ULONG*, ULONG) = (BOOL (*)(volatile ULONG*, ULONG))VirtualAlloc(NULL, 0, MEM_COMMIT, PAGE_READWRITE);
if (!pfnInitializeFlash)
{
DEBUGMSG(1, (TEXT("ERROR: FMD_Init: Failed VirtualAlloc for InitializeFlash\r\n")));
return(NULL);
}
NKDbgPrintfW(TEXT("FMD_Init: About to set copy code to pfn\r\n"));
// Copy the init function to RAM
memcpy(pfnInitializeFlash, InitializeFlash, codeSize);
// Change protection to allow execute from the RAM copy of the init function
DWORD oldProtect;
if (!VirtualProtect(pfnInitializeFlash, codeSize, PAGE_EXECUTE_READ, &oldProtect))
{
DEBUGMSG(1, (TEXT("ERROR: FMD_Init: Failed VirtualProtect for InitializeFlash\r\n")));
return(NULL);
}
#else
// Directly call the init function
BOOL (*pfnInitializeFlash)(volatile ULONG*, ULONG) = (BOOL (*)(volatile ULONG*, ULONG))InitializeFlash;
*/
#endif
#ifdef FMD_FLASH_GLOBAL_MUTEX
/* Initialize flash mutex */
ghFlashMutex = CreateMutex(NULL, FALSE, TEXT("_RAMDISK_STRATAFMD_MUTEX_"));
if (NULL == ghFlashMutex)
{
LOGMSG(1, (TEXT("CreateMutex failed (x%08x)\r\n"), GetLastError()));
return(NULL);
}
else
{
DBGMSG(1, (TEXT("FMD_Init: CreateMutex OK\r\n")));
}
#endif
// Identify the flash part and collect device information.
//
CurrCmd.pTargetAddress = pBaseAddress;
CurrCmd.uCmd = FMDHAL_CMD_INIT;
if (!FMD_OEMIoControl(IOCTL_FMDHAL_FLASH_CMD,(PBYTE) &CurrCmd, sizeof(FMD_FLASH_INFO),
(PBYTE) &g_FMDInfo, sizeof(FMD_FLASH_INFO), NULL))
{
LOGMSG(1, (TEXT("FMD_Init: IOCTL_FMDHAL_FLASH_CMD:FMDHAL_CMD_INIT failed\r\n")));
#ifndef UNDER_BOOTLOADER
SetKMode(bLastMode);
#endif
return(NULL);
}
else
{
DBGMSG(1, (TEXT("FMD_Init: InitializeFlash OK\r\n")));
}
g_FMDInfo.FlashLength = FlashLength;
g_FMDInfo.SectorSize = 4096;
g_FMDInfo.BaseAddress = (ULONG)pBaseAddress;
g_FMDInfo.TotalFlashBlocks = (FlashLength / g_FMDInfo.BlockSize);
g_dwWriteBufferSize = g_bPairedFlash ? (1 << g_FMDInfo.Geometry.WriteBuffSize) * 2 : (1 << g_FMDInfo.Geometry.WriteBuffSize);
#ifdef DEBUG
DumpFlashInfo();
DumpGeometry();
#endif
if (!DefineLayout())
{
LOGMSG(1, (TEXT("FMD_Init:DefineLayOut Failed\r\n")));
#ifndef UNDER_BOOTLOADER
SetKMode(bLastMode);
#endif
return(NULL);
}
#ifndef UNDER_BOOTLOADER
// Free the RAM copy of the initialization function
// VirtualFree(pfnInitializeFlash, 0, MEM_RELEASE);
{
ULONG unlock_ret;
unlock_ret = UnlockFILESYSRegions();
DBGMSG(1, (TEXT("FMD_Init: %u blocks in %u regions unlocked\r\n"), unlock_ret & 0xffff, unlock_ret >> 16));
}
// Verify that the block signatures are all intact
if (!VerifySignatures())
{
LOGMSG(1, (TEXT("ERROR: FMD_Init: VerifySignatures failed\r\n")));
}
#endif
LOGMSG(1, (TEXT("FMD:FMD_Init: Flash Address=0x%x, Length=0x%x.\r\n"), (ULONG)pBaseAddress, FlashLength));
#ifndef UNDER_BOOTLOADER
SetKMode(bLastMode);
#endif
//return((PVOID) pBaseAddress);
return((PVOID) TRUE);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: FMD_Deinit()
Description: De-initializes the Flash memory device.
Returns: Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL FMD_Deinit(PVOID pBaseAddress)
{
DBGMSG(1, (TEXT("FMD_Deinit:\r\n")));
#ifdef FMD_FLASH_GLOBAL_MUTEX
/* Destroy the Mutex created for the FMD */
if ( !CloseHandle(ghFlashMutex) )
{
LOGMSG(1, (TEXT("FMD_Deinit: CloseHandle on FlashMutex Failed.\r\n")));
}
#endif
return(TRUE);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: FMD_GetInfo()
Description: Determines the size characteristics for the Flash memory device.
Notes: Notice that although each byte of a NOR Flash block is individually
addressable, the media is still logically broken up into sectors.
To compute the number of sectors per block, you have to divide the
total Flash block size by the number of bytes per sector and the number
bytes for the sector metadata.
Returns: Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL FMD_GetInfo(PFlashInfo pFlashInfo)
{
DBGMSG(1, (TEXT("FMD_GetInfo:\r\n")));
pFlashInfo->flashType = NOR;
pFlashInfo->dwNumBlocks = g_FMDInfo.TotalFlashBlocks;
pFlashInfo->dwBytesPerBlock = g_FMDInfo.BlockSize;
pFlashInfo->wDataBytesPerSector = (WORD)g_FMDInfo.SectorSize;
pFlashInfo->wSectorsPerBlock = (WORD)g_pRegionTable[0].dwSectorsPerBlock;
return(TRUE);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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)
{
DBGMSG(1, (TEXT("FMD_GetInfoEx:\r\n")));
#ifdef UNDER_BOOTLOADER
if (g_dwNumRegions > MAX_REGIONS)
{
return(FALSE);
}
#endif
if (!pdwNumRegions)
{
return(FALSE);
}
if (!pFlashInfo)
{
// Return required buffer size to caller
*pdwNumRegions = g_dwNumRegions;
return(TRUE);
}
if (*pdwNumRegions < g_dwNumRegions)
{
*pdwNumRegions = g_dwNumRegions;
LOGMSG (1, (TEXT("FMD_GetInfoEx: Insufficient buffer for number of regions")));
return(FALSE);
}
memcpy (pFlashInfo->region, g_pRegionTable, g_dwNumRegions * sizeof(FlashRegion));
*pdwNumRegions = g_dwNumRegions;
pFlashInfo->cbSize = sizeof(FlashInfoEx);
pFlashInfo->flashType = NOR;
pFlashInfo->dwNumBlocks = g_FMDInfo.TotalFlashBlocks;
pFlashInfo->dwDataBytesPerSector = (WORD)g_FMDInfo.SectorSize;
pFlashInfo->dwNumRegions = g_dwNumRegions;
return(TRUE);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: FMD_GetPhysSectorAddr()
Description: Returns the physical address for the physical sector passed in.
Returns: None
------------------------------------------------------------------------------*/
VOID FMD_GetPhysSectorAddr (DWORD dwSector, PSECTOR_ADDR pStartSectorAddr)
{
GetPhysicalSectorAddress (dwSector, pStartSectorAddr, NULL, NULL);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: FMD_ReadSector()
Description: Reads the requested sector data and/or sector metadata from the
Flash media.
Notes: Notice that although each byte of a NOR Flash block is individually
addressable, the media is still logically broken up into sectors.
Thus, for each sector request, we must determine where this data
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?