📄 flsnand.cpp
字号:
if (IS_VALID_BOOTSEC(g_pFLSBuffer))
{
if (!g_hookInterface.pReadSector (dwSector+1, g_pFLSBuffer, NULL, 1)) {
return FALSE;
}
if (IS_VALID_FLS(g_pFLSBuffer))
{
// Cache the flash layout sector information
PFlashLayoutSector pFLS = (PFlashLayoutSector)(g_pFLSBuffer);
g_dwNumReserved = pFLS->cbReservedEntries / sizeof(ReservedEntry);
g_dwNumRegions = pFLS->cbRegionEntries / sizeof(FlashRegion);
// ReservedEntry table starts at the end of the PFlashLayoutSector struct.
PReservedEntry pEntry = (PReservedEntry)(pFLS+1);
if (g_dwNumReserved)
{
// Not enough room in the statically allocated buffer to store reserved table.
if (g_dwNumReserved > MAX_RESERVES)
return FALSE;
memcpy (g_pLogicalReservedTable, pEntry, g_dwNumReserved * sizeof(ReservedEntry));
}
// FlashRegion table starts after the ReservedEntry table.
if (g_dwNumRegions)
{
pRegion = (PFlashRegion)((LPBYTE)pEntry + pFLS->cbReservedEntries);
}
}
break;
}
}
if (!g_dwNumRegions)
{
g_dwNumRegions = 1;
}
// Not enough room in the statically allocated buffer to store region table.
if (g_dwNumRegions > MAX_REGIONS)
return FALSE;
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;
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// Reserved regions in the FLS are specified as number of logical blocks
// for that region. We need to translate that to physical start and length
// ranges, accounting for bad blocks and skipping any blocks that are marked
// reserved through the SectorInfo. All reserved regions in the FLS are put
// at the beginning of flash
//
static BOOL DefineReserveRegions()
{
DWORD dwStartPhysBlock = 0;
DWORD dwCurPhysBlock = 0;
// Find the starting physical block. Blocks marked reserved through the SectorInfo
// may preceed reserved regions, and are not part of the region.
while ((dwStartPhysBlock < g_flashInfo.dwNumBlocks) &&
g_hookInterface.pGetBlockStatus(dwStartPhysBlock) & (BLOCK_STATUS_RESERVED | BLOCK_STATUS_BAD))
{
dwStartPhysBlock++;
}
dwCurPhysBlock = dwStartPhysBlock;
for (DWORD i = 0; i < g_dwNumReserved; i++)
{
DWORD dwNumLogBlocks = g_pLogicalReservedTable[i].dwNumBlocks;
while (dwNumLogBlocks--)
{
// Determine the physical range of the region, skipping bad blocks
// Blocks marked reserved through the SectorInfo that are inside
// the reserved region will be treated as part of the region.
while ((dwCurPhysBlock < g_flashInfo.dwNumBlocks) &&
g_hookInterface.pGetBlockStatus(dwCurPhysBlock) & BLOCK_STATUS_BAD)
{
dwCurPhysBlock++;
}
dwCurPhysBlock++;
}
// Store the physical start and num blocks
g_pPhysReservedTable[i].dwStartBlock = dwStartPhysBlock;
g_pPhysReservedTable[i].dwNumBlocks = dwCurPhysBlock - dwStartPhysBlock;
dwStartPhysBlock = dwCurPhysBlock;
}
g_dwStartNonResBlock = dwCurPhysBlock;
return TRUE;
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
static BOOL ReadWriteReserved (PReservedReq pReq, BOOL fRead)
{
PCSTR szName = pReq->szName;
LPBYTE pBuffer = pReq->pBuffer;
if ((pBuffer = (LPBYTE)MapCallerPtr((LPVOID)(pReq->pBuffer), pReq->dwLen)) == NULL)
{
DEBUGMSG(1, (TEXT("ReadWriteReserved() - MapCallerPtr() failed, couldn't obtain pointer to buffer.\r\n")));
goto Error;
}
for (DWORD i = 0; i < g_dwNumReserved; i++)
{
if (_strnicmp(szName, g_pLogicalReservedTable[i].szName, RESERVED_NAME_LEN) == 0)
{
//
// Found a region name match
//
// Verify the request is in the valid range. pReq->dwStart is the starting byte offset into
// the region to start reading/writing and pReq->dwLen is number of bytes. Verify that
// both are within the size in bytes of the region
DWORD dwRegionSize = g_pLogicalReservedTable[i].dwNumBlocks * g_flashInfo.dwBytesPerBlock;
if ((pReq->dwStart >= dwRegionSize) || (pReq->dwStart + pReq->dwLen > dwRegionSize))
{
DEBUGMSG(1, (TEXT("ReadWriteReserved: Invalid request. Start: 0x%x. Len: 0x%x\r\n"), pReq->dwStart, pReq->dwLen));
goto Error;
}
if (pReq->dwStart % g_flashInfo.wDataBytesPerSector)
{
DEBUGMSG(1, (TEXT("ReadWriteReserved: Invalid request. Start: 0x%x is not sector aligned.\r\n"), pReq->dwStart));
goto Error;
}
if ((DWORD)pBuffer & (sizeof(DWORD) - 1))
{
DEBUGMSG(1, (TEXT("ReadWriteReserved: Unaligned pointer 0x%x.\r\n"), pBuffer));
goto Error;
}
DWORD dwStartBlockOffset = pReq->dwStart / g_flashInfo.dwBytesPerBlock;
DWORD dwPhysBlock = g_pPhysReservedTable[i].dwStartBlock;
DWORD dwRemain = pReq->dwLen;
DWORD dwNumValidBlocks = 0;
// Find the starting physical block to read/write
while (dwRemain && dwPhysBlock < g_flashInfo.dwNumBlocks)
{
DWORD dwSectorOffset = 0;
if (IsBlockBad(dwPhysBlock))
{
dwPhysBlock++;
continue;
}
if (dwNumValidBlocks < dwStartBlockOffset)
{
dwPhysBlock++;
dwNumValidBlocks++;
continue;
}
if (!fRead)
{
if (!g_hookInterface.pEraseBlock(dwPhysBlock))
{
DEBUGMSG(1, (TEXT("ReadWriteReserved: FMD_EraseBlock failed 0x%x.\r\n"), dwPhysBlock));
goto Error;
}
}
// If this is the starting block, determine the sector offset
// into the block to start.
if (dwNumValidBlocks == dwStartBlockOffset)
{
dwSectorOffset = (pReq->dwStart % g_flashInfo.dwBytesPerBlock) / g_flashInfo.wDataBytesPerSector;
}
while (dwSectorOffset < g_flashInfo.wSectorsPerBlock && dwRemain)
{
BYTE abTmpBuffer[MAX_PAGE_SIZE];
LPBYTE pTmpBuffer = pBuffer;
DWORD dwBytes = g_flashInfo.wDataBytesPerSector;
DWORD dwSector = dwPhysBlock * g_flashInfo.wSectorsPerBlock + dwSectorOffset;
// Double buffer if the remaining bytes do not make up an entire sector
if (dwRemain < g_flashInfo.wDataBytesPerSector)
{
if (!fRead)
{
memset (abTmpBuffer, 0xff, g_flashInfo.wDataBytesPerSector);
memcpy (abTmpBuffer, pBuffer, dwRemain);
}
pTmpBuffer = abTmpBuffer;
dwBytes = dwRemain;
}
if (fRead)
{
if (!g_hookInterface.pReadSector (dwSector, pTmpBuffer, NULL, 1))
{
DEBUGMSG(1, (TEXT("ReadWriteReserved: FMD_ReadSector failed 0x%x.\r\n"), dwSector));
goto Error;
}
if (dwRemain < g_flashInfo.wDataBytesPerSector)
{
memcpy (pBuffer, abTmpBuffer, dwBytes);
}
}
else
{
if (!g_hookInterface.pWriteSector (dwSector, pTmpBuffer, NULL, 1))
{
DEBUGMSG(1, (TEXT("ReadWriteReserved: FMD_WriteSector failed 0x%x.\r\n"), dwSector));
goto Error;
}
}
dwRemain -= dwBytes;
pBuffer += dwBytes;
dwSectorOffset++;
}
dwPhysBlock++;
dwNumValidBlocks++;
}
return TRUE;
}
}
Error:
return FALSE;
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
static BOOL RawWriteBlocks (PRawWriteBlocksReq pReq)
{
DWORD dwEndBlock = pReq->dwStartBlock + pReq->dwNumBlocks - 1;
LPBYTE pBuffer = pReq->pBuffer;
if (pReq->dwStartBlock >= g_flashInfo.dwNumBlocks||
dwEndBlock >= g_flashInfo.dwNumBlocks ||
dwEndBlock < pReq->dwStartBlock)
{
DEBUGMSG(1, (TEXT("RawWriteBlocks: Invalid request: (0x%x, 0x%x)\r\n"), pReq->dwStartBlock, pReq->dwNumBlocks));
return FALSE;
}
// Size of the buffer must include SectorInfo
if (pReq->cbBuffer < (pReq->dwNumBlocks * g_flashInfo.wSectorsPerBlock *
(g_flashInfo.wDataBytesPerSector + sizeof(SectorInfo))))
{
DEBUGMSG(1, (TEXT("RawWriteBlocks: Insufficient buffer: (0x%x)\r\n"), pReq->cbBuffer));
return FALSE;
}
DWORD dwStartPhysBlock = 0;
DWORD dwNumLogBlocks = 0;
static DWORD dwLastLogicalBlock = INVALID_BLOCK_ID;
static DWORD dwLastPhysicalBlock = INVALID_BLOCK_ID;
if (dwLastLogicalBlock == pReq->dwStartBlock) {
// Use the cached last block if caller is writing to sequential blocks
//
dwStartPhysBlock = dwLastPhysicalBlock;
} else {
// Find the starting physical block by skipping any bad blocks
//
while (dwNumLogBlocks < pReq->dwStartBlock)
{
if (dwStartPhysBlock >= g_flashInfo.dwNumBlocks)
{
DEBUGMSG(1, (TEXT("RawWriteBlocks: Not enough good blocks to complete request: (0x%x, 0x%x)\r\n"), pReq->dwStartBlock, pReq->dwNumBlocks));
return FALSE;
}
if (!(g_hookInterface.pGetBlockStatus(dwStartPhysBlock) & BLOCK_STATUS_BAD))
{
dwNumLogBlocks++;
}
dwStartPhysBlock++;
}
}
DWORD dwPhysBlock = dwStartPhysBlock;
dwNumLogBlocks = pReq->dwNumBlocks;
// Write out the requested blocks sequentially, skipping any bad blocks.
//
while (dwNumLogBlocks)
{
if (dwStartPhysBlock >= g_flashInfo.dwNumBlocks)
{
DEBUGMSG(1, (TEXT("RawWriteBlocks: Not enough good blocks to complete request: (0x%x, 0x%x)\r\n"), pReq->dwStartBlock, pReq->dwNumBlocks));
return FALSE;
}
if (g_hookInterface.pGetBlockStatus(dwPhysBlock) & BLOCK_STATUS_BAD)
{
dwPhysBlock++;
continue;
}
if (!WriteBlock (dwPhysBlock, pBuffer))
{
DEBUGMSG(1, (TEXT("RawWriteBlocks: WriteBlock failed (0x%x).\r\n"), dwPhysBlock));
return FALSE;
}
pBuffer += (g_flashInfo.dwBytesPerBlock + g_flashInfo.wSectorsPerBlock * sizeof(SectorInfo));
dwPhysBlock++;
dwNumLogBlocks--;
}
dwLastPhysicalBlock = dwPhysBlock;
dwLastLogicalBlock = pReq->dwStartBlock + pReq->dwNumBlocks;
return TRUE;
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
static BOOL WriteBlock (DWORD dwBlock, LPBYTE pBuffer)
{
DWORD dwStartSector;
if (!g_hookInterface.pGetInfo(&g_flashInfo)) {
return FALSE;
}
dwStartSector = dwBlock * g_flashInfo.wSectorsPerBlock;
if (!g_hookInterface.pEraseBlock (dwBlock))
{
DEBUGMSG(1, (TEXT("WriteBlock: FMD_EraseBlock failed (0x%x).\r\n"), dwBlock));
return FALSE;
}
if (!pBuffer)
{
// No buffer to write, simply return success after erasing
return TRUE;
}
// Write out each sector one at a time. The buffer contains the sector data followed by the
// SectorInfo for the particular sector.
for (DWORD iSector = dwStartSector; iSector < dwStartSector + g_flashInfo.wSectorsPerBlock; iSector++)
{
if (!g_hookInterface.pWriteSector (iSector, pBuffer, (PSectorInfo)(pBuffer + g_flashInfo.wDataBytesPerSector), 1))
{
DEBUGMSG(1, (TEXT("WriteBlock: FMD_WriteSector failed (0x%x).\r\n"), iSector));
return FALSE;
}
pBuffer += (g_flashInfo.wDataBytesPerSector + sizeof(SectorInfo));
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -