📄 fmd.cpp
字号:
break;
}
case IOCTL_FMD_SET_REGION_TABLE:
{
DWORD dwTableSize = g_dwNumRegions * sizeof(FlashRegion);
// Temp
RETAILMSG(1, (L"IOCTL_FMD_SET_REGION_TABLE enter.\r\n"));
// Set the reserved table.
if (!pInBuf || nInBufSize != dwTableSize)
{
// If no buffer is provided or wrong size, fail.
if (pBytesReturned)
*pBytesReturned = 0;
return FALSE;
}
if (pBytesReturned)
*pBytesReturned = dwTableSize;
if (g_pRegionTable)
memcpy (g_pRegionTable, pInBuf, dwTableSize);
// Temp
for (DWORD iRegion = 0; iRegion < g_dwNumRegions; iRegion++) {
RETAILMSG(1, (L"Type=%d, Start=0x%x, Num=0x%x, Sec/Blk=0x%x, B/Blk=0x%x, Compact=%d.\r\n",
g_pRegionTable[iRegion].regionType,
g_pRegionTable[iRegion].dwStartPhysBlock,
g_pRegionTable[iRegion].dwNumBlocks,
g_pRegionTable[iRegion].dwSectorsPerBlock,
g_pRegionTable[iRegion].dwBytesPerBlock,
g_pRegionTable[iRegion].dwCompactBlocks));
}
if (g_dwFLSBlock)
{
// Read the block containing the FLS
if (!ReadBlock(g_dwFLSBlock, g_pFLSBuffer, g_pSectorInfo)) {
return FALSE;
}
PFlashLayoutSector pFLS = (PFlashLayoutSector)(g_pFLSBuffer + g_flashInfo.wDataBytesPerSector);
// FlashRegion table starts after the ReservedEntry table.
PFlashRegion pRegion = (PFlashRegion)((LPBYTE)pFLS + sizeof(FlashLayoutSector) + pFLS->cbReservedEntries);
memcpy (pRegion, pInBuf, dwTableSize);
if (!FMD_EraseBlock (g_dwFLSBlock)) {
return FALSE;
}
// Write new FLS
if (!WriteBlock (g_dwFLSBlock, g_pFLSBuffer, g_pSectorInfo)) {
return FALSE;
}
}
return TRUE;
}
#endif
default:
DEBUGMSG(1, (TEXT("FMD_OEMIoControl: unrecognized IOCTL (0x%x).\r\n"), dwIoControlCode));
return(FALSE);
}
return TRUE;
}
BOOL FMD_Deinit(PVOID hFMD)
{
return(TRUE);
}
/*
@func BOOL | FMD_GetInfo | Provides information on the NAND flash.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
BOOL FMD_GetInfo(PFlashInfo pFlashInfo)
{
if (!pFlashInfo)
return(FALSE);
pFlashInfo->flashType = NAND;
pFlashInfo->wDataBytesPerSector = NAND_PAGE_SIZE;
pFlashInfo->dwNumBlocks = NAND_BLOCK_CNT;
pFlashInfo->wSectorsPerBlock = NAND_PAGE_CNT;
pFlashInfo->dwBytesPerBlock = (pFlashInfo->wSectorsPerBlock * pFlashInfo->wDataBytesPerSector);
return(TRUE);
}
BOOL FMD_GetInfoEx(PFlashInfoEx pFlashInfo, PDWORD pdwNumRegions)
{
// Temp
RETAILMSG(1, (L"FMD_GetInfoEx enter.\r\n"));
if (!pdwNumRegions)
{
return FALSE;
}
if (!pFlashInfo)
{
// Return required buffer size to caller
*pdwNumRegions = g_dwNumRegions;
return TRUE;
}
if (*pdwNumRegions < g_dwNumRegions)
{
*pdwNumRegions = g_dwNumRegions;
DEBUGMSG (1, (TEXT("FMD_GetInfoEx: Insufficient buffer for number of regions")));
return FALSE;
}
memcpy (pFlashInfo->region, g_pRegionTable, g_dwNumRegions * sizeof(FlashRegion));
// Temp
for (DWORD iRegion = 0; iRegion < g_dwNumRegions; iRegion++) {
RETAILMSG(1, (L"Type=%d, StartP=0x%x, NumP=0x%x, NumL=0x%x, Sec/Blk=0x%x, B/Blk=0x%x, Compact=%d.\r\n",
g_pRegionTable[iRegion].regionType,
g_pRegionTable[iRegion].dwStartPhysBlock,
g_pRegionTable[iRegion].dwNumPhysBlocks,
g_pRegionTable[iRegion].dwNumLogicalBlocks,
g_pRegionTable[iRegion].dwSectorsPerBlock,
g_pRegionTable[iRegion].dwBytesPerBlock,
g_pRegionTable[iRegion].dwCompactBlocks));
}
*pdwNumRegions = g_dwNumRegions;
pFlashInfo->cbSize = sizeof(FlashInfoEx);
pFlashInfo->flashType = NAND;
pFlashInfo->dwNumBlocks = NAND_BLOCK_CNT;
pFlashInfo->dwDataBytesPerSector = NAND_PAGE_SIZE;
pFlashInfo->dwNumRegions = g_dwNumRegions;
return(TRUE);
}
static BOOL IsBlockBad(BLOCK_ID blockID)
{
BYTE Data;
SECTOR_ADDR blockPage = (blockID * NAND_PAGE_CNT);
NF_nFCE_L(); // Select the flash chip.
NF_CMD(CMD_RESET); // Send reset command.
NF_WAITRB(); // Wait for flash to complete command.
NF_CMD(CMD_READ2); // Send read confirm command.
NF_ADDR(0); // Column = 0.
NF_ADDR(blockPage & 0xff); /* The mark of bad block is in 0 page */
NF_ADDR((blockPage >> 8) & 0xff); /* For block number A[24:17] */
NF_ADDR((blockPage >> 16) & 0xff); /* For block number A[25] */
NF_WAITRB(); // Wait for flash to complete command.
// TODO
Data = NF_RDDATA(); // Read command status.
Data = NF_RDDATA(); // Read command status.
Data = NF_RDDATA(); // Read command status.
Data = NF_RDDATA(); // Read command status.
Data = NF_RDDATA(); // Read command status.
Data = NF_RDDATA(); // Read command status.
if(0xff != Data)
{
return(TRUE);
}
NF_nFCE_H(); // Deassert the flash chip.
return(FALSE);
}
/*
@func DWORD | FMD_GetBlockStatus | Returns the status of the specified block.
@rdesc Block status (see fmd.h).
@comm
@xref
*/
DWORD FMD_GetBlockStatus(BLOCK_ID blockID)
{
SECTOR_ADDR Sector = (blockID * NAND_PAGE_CNT);
SectorInfo SI;
DWORD dwResult = 0;
if (IsBlockBad(blockID))
return BLOCK_STATUS_BAD;
if (!FMD_ReadSector(Sector, NULL, &SI, 1))
return BLOCK_STATUS_UNKNOWN;
if (!(SI.bOEMReserved & OEM_BLOCK_READONLY))
dwResult |= BLOCK_STATUS_READONLY;
if (!(SI.bOEMReserved & OEM_BLOCK_RESERVED))
dwResult |= BLOCK_STATUS_RESERVED;
return(dwResult);
}
/*
@func BOOL | MarkBlockBad | Marks the specified block as bad.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
static BOOL MarkBlockBad(BLOCK_ID blockID)
{
BYTE Status;
ULONG blockPage = (blockID * NAND_PAGE_CNT); // Convert block address to page address.
NF_nFCE_L(); // Select the flash chip.
NF_CMD(CMD_RESET); // Send reset command.
NF_WAITRB(); // Wait for flash to complete command.
NF_CMD(CMD_READ2); // Send read confirm command.
NF_CMD(CMD_WRITE); // Send write command.
NF_ADDR(0); // Column = 0.
NF_ADDR(blockPage & 0xff); /* The mark of bad block is in 0 page */
NF_ADDR((blockPage >> 8) & 0xff); /* For block number A[24:17] */
NF_ADDR((blockPage >> 16) & 0xff); /* For block number A[25] */
// TODO
NF_WRDATA(0xFF); // Write bad block marker.
NF_WRDATA(0xFF); // Write bad block marker.
NF_WRDATA(0xFF); // Write bad block marker.
NF_WRDATA(0xFF); // Write bad block marker.
NF_WRDATA(0xFF); // Write bad block marker.
NF_WRDATA(0); // Write bad block marker.
NF_CMD(CMD_WRITE2); // Send write confirm command.
NF_WAITRB(); // Wait for flash to complete command.
Status = NF_RDDATA(); // Read command status.
NF_nFCE_H(); // Deassert the flash chip.
return((Status & 1) ? FALSE : TRUE);
}
/*
@func BOOL | FMD_SetBlockStatus | Marks the block with the specified block status.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
BOOL FMD_SetBlockStatus(BLOCK_ID blockID, DWORD dwStatus)
{
if (dwStatus & BLOCK_STATUS_BAD)
{
if (!MarkBlockBad(blockID))
return(FALSE);
}
if (dwStatus & (BLOCK_STATUS_READONLY | BLOCK_STATUS_RESERVED)) {
SECTOR_ADDR Sector = blockID * NAND_PAGE_CNT;
SectorInfo SI;
if (!FMD_ReadSector(Sector, NULL, &SI, 1)) {
return FALSE;
}
if (dwStatus & BLOCK_STATUS_READONLY) {
SI.bOEMReserved &= ~OEM_BLOCK_READONLY;
}
if (dwStatus & BLOCK_STATUS_RESERVED) {
SI.bOEMReserved &= ~OEM_BLOCK_RESERVED;
}
if (!FMD_WriteSector (Sector, NULL, &SI, 1)) {
return FALSE;
}
}
return(TRUE);
}
static BOOL DefineLayout()
{
PFlashRegion pRegion = NULL;
DWORD dwBlock = 0;
if (!FMD_GetInfo (&g_flashInfo)) {
return FALSE;
}
// Find the MBR to determine if there is a flash layout sector
g_dwNumRegions = 0;
// Find the first usuable block
while (dwBlock < g_flashInfo.dwNumBlocks) {
if (!(FMD_GetBlockStatus(dwBlock) & (BLOCK_STATUS_BAD | BLOCK_STATUS_RESERVED))) {
break;
}
dwBlock++;
}
DWORD dwSector = dwBlock * g_flashInfo.wSectorsPerBlock;
if (!FMD_ReadSector (dwSector, g_pFLSBuffer, NULL, 1)) {
return FALSE;
}
// compare the signatures
if (IS_VALID_BOOTSEC(g_pFLSBuffer))
{
if (!FMD_ReadSector (dwSector+1, g_pFLSBuffer, NULL, 1)) {
return FALSE;
}
if (IS_VALID_FLS(g_pFLSBuffer))
{
PFlashLayoutSector pFLS = (PFlashLayoutSector)(g_pFLSBuffer);
// Cache the flash layout sector information
g_dwNumRegions = pFLS->cbRegionEntries / sizeof(FlashRegion);
// FlashRegion table starts after the ReservedEntry table.
if (g_dwNumRegions)
{
pRegion = (PFlashRegion)((LPBYTE)pFLS + sizeof(FlashLayoutSector) + pFLS->cbReservedEntries);
}
}
}
if (!g_dwNumRegions)
{
g_dwNumRegions = 1;
}
//#ifdef UNDER_BOOTLOADER
// Not enough room in the statically allocated buffer to store region table.
if (g_dwNumRegions > MAX_REGIONS)
return FALSE;
//#else
// g_pRegionTable = (PFlashRegion)LocalAlloc (0, g_dwNumRegions * sizeof(FlashRegion));
// if (!g_pRegionTable)
// return FALSE;
//#endif
if (pRegion)
{
memcpy (g_pRegionTable, pRegion, g_dwNumRegions * sizeof(FlashRegion));
}
else
{
g_pRegionTable[0].dwStartPhysBlock = 0;
g_pRegionTable[0].dwNumPhysBlocks = g_flashInfo.dwNumBlocks;
g_pRegionTable[0].dwNumLogicalBlocks = FIELD_NOT_IN_USE;
g_pRegionTable[0].dwBytesPerBlock = g_flashInfo.dwBytesPerBlock;
g_pRegionTable[0].regionType = FILESYS;
g_pRegionTable[0].dwSectorsPerBlock = g_flashInfo.wSectorsPerBlock;
g_pRegionTable[0].dwCompactBlocks = DEFAULT_COMPACTION_BLOCKS;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -