📄 nand.c
字号:
EdbgOutputDebugString("WARNING: NAND device doesn't exist - unable to store image.\r\n");
return(FALSE);
}
EdbgOutputDebugString("INFO: Prepare for writing DIO image to NAND.\r\n");
if (!FMD_GetInfo(&g_flashInfo))
{
EdbgOutputDebugString("ERROR: Unable to get NAND flash information.\r\n");
return(FALSE);
}
// Make sure DIO image length does not exceed reserved NAND size
if (dwLength > IMAGE_BOOT_DIOIMAGE_NAND_SIZE)
{
EdbgOutputDebugString("ERROR: DIO image size exceeds reserved NAND region (size = 0x%x)\r\n", dwLength);
return(FALSE);
}
// Force all blocks in XLDR(128KB), EBOOT(256KB) and IPL(256KB) to be reserved
startBlockID = 0;
endBlockID = (IMAGE_BOOT_DIOIMAGE_NAND_OFFSET / g_flashInfo.dwBytesPerBlock) - 1;
for (blockID = startBlockID; blockID < endBlockID; blockID++)
{
// Skip bad blocks
if (FMD_GetBlockStatus(blockID) == BLOCK_STATUS_BAD)
{
EdbgOutputDebugString("INFO: Found bad NAND flash block [0x%x].\r\n", blockID);
continue;
}
// Set reserved status
if ((FMD_GetBlockStatus(blockID) & BLOCK_STATUS_RESERVED) == 0)
{
EdbgOutputDebugString("INFO: Block [0x%x] not marked as bad or reserved. Force status to reserved.\r\n", blockID);
if (!FMD_SetBlockStatus(blockID, BLOCK_STATUS_RESERVED))
{
EdbgOutputDebugString("ERROR: Block [0x%x] force reserved status failed.\r\n", blockID);
return(FALSE);
}
}
}
// Calculate the physical block range for the DIO image
startBlockID = IMAGE_BOOT_DIOIMAGE_NAND_OFFSET / g_flashInfo.dwBytesPerBlock;
endBlockID = startBlockID + (IMAGE_BOOT_DIOIMAGE_NAND_SIZE / g_flashInfo.dwBytesPerBlock);
EdbgOutputDebugString("INFO: Erasing NAND flash blocks [0x%x - 0x%x].\r\n", startBlockID, endBlockID);
// Erase range of NAND blocks reserved for DIO image
for (blockID = startBlockID; blockID < endBlockID; blockID++)
{
// Skip bad blocks
if (FMD_GetBlockStatus(blockID) == BLOCK_STATUS_BAD)
{
EdbgOutputDebugString("INFO: Found bad NAND flash block [0x%x].\r\n", blockID);
continue;
}
// Erase the block...
if (!FMD_EraseBlock(blockID))
{
EdbgOutputDebugString("ERROR: Unable to erase NAND flash block [0x%x].\r\n", blockID);
return(FALSE);
}
percentComplete = 100 * (blockID - startBlockID + 1) / (endBlockID - startBlockID);
// If percentage complete has changed, show the progress
if (lastPercentComplete != percentComplete)
{
lastPercentComplete = percentComplete;
OEMWriteDebugByte('\r');
EdbgOutputDebugString("INFO: Erase is %d%% complete.", percentComplete);
}
}
EdbgOutputDebugString("\r\nINFO: Ready to write DIO image ... \r\n");
return(TRUE);
}
//------------------------------------------------------------------------------
//
// Function: NANDContinueWriteBinDIO
//
// N/A
//
// Parameters:
// None.
//
// Returns:
// TRUE indicates success. FALSE indicates failure.
//
//-----------------------------------------------------------------------------
BOOL NANDContinueWriteBinDIO(DWORD dwAddress, BYTE *pbData, DWORD dwSize)
{
BOOL bOK;
BLOCK_ID blockID;
SECTOR_ADDR sectorAddr;
SectorInfo *pSectorInfo;
UINT32 blockSize, sectorSize;
UINT32 dwCount;
static UINT32 nTimes = 0, dwBadBlock = 0;
// Check for NAND device availability
//
if (!g_bNandExist)
{
EdbgOutputDebugString("WARNING: NAND device doesn't exist - unable to store image.\r\n");
return(FALSE);
}
// First we need to calculate position where to write
sectorSize = g_flashInfo.wDataBytesPerSector + sizeof(SectorInfo);
blockSize = g_flashInfo.wSectorsPerBlock * sectorSize;
blockID = dwAddress / blockSize;
sectorAddr = (dwAddress - blockID * blockSize) / sectorSize;
// Shift block by DIO image region base
blockID += (IMAGE_BOOT_DIOIMAGE_NAND_OFFSET / g_flashInfo.dwBytesPerBlock);
// Skip the number of bad blocks
blockID += dwBadBlock;
// Write record
dwCount = 0;
while (dwCount < dwSize && blockID < g_flashInfo.dwNumBlocks)
{
// Skip bad blocks
if (FMD_GetBlockStatus(blockID) == BLOCK_STATUS_BAD)
{
EdbgOutputDebugString("INFO: Found bad NAND flash block [0x%x].\r\n", blockID);
blockID++;
dwBadBlock++;
continue;
}
// Write sectors
bOK = TRUE;
while (sectorAddr < g_flashInfo.wSectorsPerBlock && dwCount < dwSize)
{
// First we have to check for empty sectors
pSectorInfo = (SectorInfo *)(pbData + dwCount + g_flashInfo.wDataBytesPerSector);
// Don't write empty sector
if (IsSectorEmpty(pbData + dwCount, g_flashInfo.wDataBytesPerSector, pSectorInfo))
{
// EdbgOutputDebugString("INFO: Skipping empty sector [0x%x].\r\n", sectorAddr);
// Move to next sector
dwCount += sectorSize;
sectorAddr++;
continue;
}
// Clear reserved flag if set
pSectorInfo->bOEMReserved |= OEM_BLOCK_RESERVED;
// Never ever write sector with bad block
if (pSectorInfo->bBadBlock != 0xFF)
{
EdbgOutputDebugString("ERROR: Incorrect or corrupted DIO BIN file - bad block flag set.\r\n");
return(FALSE);
}
// Write sector
if (!(bOK = FMD_WriteSector(blockID * g_flashInfo.wSectorsPerBlock + sectorAddr,
pbData + dwCount, pSectorInfo, 1)))
{
EdbgOutputDebugString("ERROR: Writing sector [0x%x] failed.\r\n", sectorAddr);
break;
}
// Move to next sector
dwCount += sectorSize;
sectorAddr++;
}
// When sector write failed, mark block as bad and move back
if (!bOK)
{
EdbgOutputDebugString("WARN: Block [0x%x] / sector [0x%x] write failed, mark block as bad.\r\n", blockID, sectorAddr);
// First move back
dwCount -= sectorAddr * sectorSize;
// Mark block as bad
FMD_SetBlockStatus(blockID, BLOCK_STATUS_BAD);
blockID++;
continue;
}
// We are done with block
sectorAddr = 0;
blockID++;
}
// Progress
OEMWriteDebugByte('\r');
switch (nTimes++ % 4)
{
case 0:
OEMWriteDebugByte('\\');
break;
case 1:
OEMWriteDebugByte('|');
break;
case 2:
OEMWriteDebugByte('/');
break;
case 3:
OEMWriteDebugByte('-');
}
// Before we leave erase buffer
memset(pbData, 0xFF, dwSize);
// If we wrote all, we are succesfull
return (dwCount >= dwSize);
}
//------------------------------------------------------------------------------
//
// Function: NANDFinishWriteBinDIO
//
// N/A
//
// Parameters:
// None.
//
// Returns:
// TRUE indicates success. FALSE indicates failure.
//
//-----------------------------------------------------------------------------
BOOL NANDFinishWriteBinDIO()
{
if (!g_bNandExist)
{
EdbgOutputDebugString("\r\nINFO: No NAND present!\r\n");
return(FALSE);
}
// Nothing to do...
EdbgOutputDebugString("\r\nINFO: Update of DIO image completed successfully.\r\n");
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: NANDLoadIPL
//
// N/A
//
// Parameters:
// None.
//
// Returns:
// TRUE indicates success. FALSE indicates failure.
//
//-----------------------------------------------------------------------------
BOOL NANDLoadIPL(VOID)
{
FlashInfo flashInfo;
LPBYTE pSectorBuf;
SectorInfo sectorInfo;
BLOCK_ID blockID, startBlockID, endBlockID;
SECTOR_ADDR sectorAddr, startSectorAddr, endSectorAddr;
// Check for NAND device availability
//
if (!g_bNandExist)
{
EdbgOutputDebugString("WARNING: NAND device doesn't exist - unable to read image.\r\n");
return(FALSE);
}
EdbgOutputDebugString("INFO: Reading IPL image from NAND (please wait)...\r\n");
if (!FMD_GetInfo(&flashInfo))
{
EdbgOutputDebugString("ERROR: Unable to get NAND flash information.\r\n");
return(FALSE);
}
// Calculate the physical block range for the NK image
startBlockID = IMAGE_BOOT_IPLIMAGE_NAND_OFFSET / flashInfo.dwBytesPerBlock;
endBlockID = startBlockID + (IMAGE_BOOT_IPLIMAGE_NAND_SIZE / flashInfo.dwBytesPerBlock);
// Set image load address
pSectorBuf = (LPBYTE) OALPAtoUA(IMAGE_BOOT_IPLIMAGE_RAM_START);
EdbgOutputDebugString("INFO: Copying IPL image to RAM address 0x%x\r\n", pSectorBuf);
// Copy IPL from NAND flash to RAM
for (blockID = startBlockID; blockID < endBlockID ; blockID++)
{
// Skip bad blocks
if (FMD_GetBlockStatus(blockID) == BLOCK_STATUS_BAD)
{
EdbgOutputDebugString("INFO: Found bad NAND flash block [0x%x].\r\n", blockID);
continue;
}
// Compute sector address based on current physical block
startSectorAddr = blockID * flashInfo.wSectorsPerBlock;
endSectorAddr = startSectorAddr + flashInfo.wSectorsPerBlock;
for (sectorAddr = startSectorAddr; sectorAddr < endSectorAddr; sectorAddr++)
{
if (!FMD_ReadSector(sectorAddr, pSectorBuf, §orInfo, 1))
{
EdbgOutputDebugString("ERROR: Failed to update IPL.\r\n");
return(FALSE);
}
pSectorBuf += flashInfo.wDataBytesPerSector;
}
}
EdbgOutputDebugString("INFO: Copy of IPL completed successfully.\r\n");
return(TRUE);
}
//-----------------------------------------------------------------------------
//
// Function: NANDLoadNK
//
// This function loads an OS image from NAND flash memory into RAM for
// execution.
//
// Parameters:
// None.
//
// Returns:
// TRUE indicates success. FALSE indicates failure.
//
//-----------------------------------------------------------------------------
BOOL NANDLoadNK(VOID)
{
FlashInfo flashInfo;
LPBYTE pSectorBuf;
SectorInfo sectorInfo;
BLOCK_ID blockID, startBlockID, endBlockID;
SECTOR_ADDR sectorAddr, startSectorAddr, endSectorAddr;
UINT32 percentComplete, lastPercentComplete;
// Check for NAND device availability
//
if (!g_bNandExist)
{
EdbgOutputDebugString("WARNING: NAND device doesn't exist - unable to read image.\r\n");
return(FALSE);
}
EdbgOutputDebugString("INFO: Reading NK image to NAND (please wait)...\r\n");
if (!FMD_GetInfo(&flashInfo))
{
EdbgOutputDebugString("ERROR: Unable to get NAND flash information.\r\n");
return(FALSE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -