📄 nand.c
字号:
nandParams.dwLaunchAddr, nandParams.dwRegionStart, nandParams.dwRegionLength, nandParams.dwImageOffset));
// Store Boot partition
if(!BP_WriteData(hBootPart, (LPBYTE)&nandParams, sizeof(EBOOT_NANDCFG)))
{
OALMSG(OAL_ERROR, (TEXT("ERROR: failed to write BOOTSECTION data\r\n")));
return FALSE;
}
// Create an extended partition to use rest of flash to mount a filesystem.
hPart = BP_OpenPartition(NEXT_FREE_LOC, USE_REMAINING_SPACE,
PART_EXTENDED, TRUE, PART_OPEN_ALWAYS);
if(hPart == INVALID_HANDLE_VALUE)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: failed to create/open extended partition.\r\n")));
return FALSE;
}
OALMSG(OAL_INFO, (TEXT("INFO: Programming OS to NAND complete.\r\n")));
OALMSG(OAL_FUNC, (TEXT("WriteOSRegionsToNand-\r\n")));
return TRUE;
}
//-----------------------------------------------------------------------------
//
// FUNCTION: WriteEBootRegionToNand
//
// DESCRIPTION: Writes EBoot bin region to NAND.
// Note: This assumes that the blocks to be occupied
// by EBOOT is valid and good.
//
// PARAMETERS:
// pBootCfg - Ptr to EBOOT configuration structure.
// Ignored.
//
// RETURNS: TRUE for success. FALSE for failure.
//
//-----------------------------------------------------------------------------
static BOOL WriteEBootRegionToNand(BOOT_CFG *pBootCfg)
{
extern MultiBINInfo g_BINRegionInfo;
DWORD dwRegionStart = g_BINRegionInfo.Region[0].dwRegionStart;
DWORD dwRegionLength = g_BINRegionInfo.Region[0].dwRegionLength;
DWORD dwBlockStatus;
DWORD dwStartSectorAddr;
DWORD nSectors;
DWORD dwNumSectors;
DWORD dwImageStart;
DWORD dwBlock;
OALMSG(OAL_FUNC, (TEXT("WriteEBootRegionToNand+\r\n")));
if(g_fNandExists != TRUE)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: NAND device doesn't exist - unable to write image.\r\n")));
return FALSE;
}
if(g_BINRegionInfo.dwNumRegions > 1)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: Multi BIN regions(%d) in EBoot image unsupported. Skipping NAND program.\r\n"), g_BINRegionInfo.dwNumRegions));
return FALSE;
}
if(OEMIsFlashAddr(dwRegionStart))
{
OALMSG(OAL_ERROR, (TEXT("ERROR: Image built for FLASH(%X). Skipping NAND program.\r\n"), dwRegionStart));
return FALSE;
}
if(dwRegionLength > NAND_EBOOT_IMAGE_SIZE)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: EBOOT Image size(0x%X) greater than reserved. Skipping NAND program.\r\n"), dwRegionLength));
return FALSE;
}
OALMSG(OAL_INFO, (TEXT("INFO: Writing EBOOT image to NAND:\r\n")));
dwImageStart = (DWORD)OEMMapMemAddr(dwRegionStart, dwRegionStart);
dwNumSectors = NAND_IMAGE_NUM_SECTOR(dwRegionLength, g_FlashInfo.wDataBytesPerSector);
dwBlock = FindFirstGoodBlock(1);
OALMSG(OAL_FUNC, (TEXT("dwRegionStart:%X dwRegionLength:%X dwImageStart:%X dwNumSectors: %d dwBlock %d\r\n"),
dwRegionStart, dwRegionLength, dwImageStart, dwNumSectors, dwBlock));
for(; dwNumSectors > 0; dwBlock++)
{
if(dwBlock >= g_FlashInfo.dwNumBlocks)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: No available blocks left! Unwritten sectors: %d \r\n"), dwNumSectors));
return FALSE;
}
dwBlockStatus = FMD_GetBlockStatus(dwBlock);
// Skip bad blocks
if((dwBlockStatus & BLOCK_STATUS_BAD) || (dwBlockStatus & BLOCK_STATUS_UNKNOWN))
{
OALMSG(OAL_INFO, (TEXT("INFO: block %d bad! Skipping block.\r\n"), dwBlock));
continue;
}
// Prepare block
if( FMD_EraseBlock(dwBlock) != TRUE ||
FMD_SetBlockStatus(dwBlock, (BLOCK_STATUS_READONLY | BLOCK_STATUS_RESERVED)) != TRUE)
{
OALMSG(OAL_ERROR, (TEXT("Prepare block %d status failed or un-erasable! Skip block.\r\n"), dwBlock));
if(FMD_SetBlockStatus(dwBlock, BLOCK_STATUS_BAD) != TRUE)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: Unable to set block %d status! Skipping NAND program.\r\n"), dwBlock));
return FALSE;
}
continue;
}
// Write image to block
dwStartSectorAddr = dwBlock * g_FlashInfo.wSectorsPerBlock;
nSectors = (dwNumSectors > g_FlashInfo.wSectorsPerBlock)? g_FlashInfo.wSectorsPerBlock : dwNumSectors;
OALMSG(1|OAL_FUNC, (TEXT("Writing block %d sector 0x%X numSectors %d!\r\n"),
dwBlock, dwStartSectorAddr, nSectors));
if(FMD_WriteSector(dwStartSectorAddr, (LPBYTE)dwImageStart, NULL, nSectors) != TRUE)
{
OALMSG(OAL_ERROR, (TEXT("Writing to block %d failed!\r\n"), dwBlock));
if(FMD_SetBlockStatus(dwBlock, BLOCK_STATUS_BAD) != TRUE)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: Unable to set block %d status! Skipping NAND program.\r\n"), dwBlock));
return FALSE;
}
continue;
}
else
{
dwNumSectors -= nSectors;
dwImageStart += nSectors * g_FlashInfo.wDataBytesPerSector;
}
}
OALMSG(OAL_INFO, (TEXT("INFO: Programming EBOOT to NAND cmplete.\r\n")));
OALMSG(OAL_FUNC, (TEXT("WriteEBootRegionToNand-\r\n")));
return TRUE;
}
//-----------------------------------------------------------------------------
//
// FUNCTION: WriteNandLoaderRegionToNand
//
// DESCRIPTION: Writes Nand Loader binary region to NAND.
// Note: This assumes that the block0 to be valid and good.
//
// PARAMETERS:
// pBootCfg - Ptr to EBOOT configuration structure.
// Ignored.
//
// RETURNS: TRUE for success. FALSE for failure.
//
//-----------------------------------------------------------------------------
static BOOL WriteNandLoaderRegionToNand(BOOT_CFG *pBootCfg)
{
extern MultiBINInfo g_BINRegionInfo;
FILESentry *pFILES;
DWORD blockStatus;
DWORD dwImageSize;
DWORD dwImageStart;
DWORD dwNumSectors;
BYTE nCount;
OALMSG(OAL_FUNC, (TEXT("WriteNandLoaderRegionToNand+\r\n")));
if(g_fNandExists != TRUE)
{
OALMSG(OAL_ERROR, (TEXT("WARNING: NAND device doesn't exist - unable to write image.\r\n")));
return FALSE;
}
// Check for presence of nandloader file
for(nCount = 0; nCount < g_BINRegionInfo.dwNumRegions; nCount++)
{
if((pFILES = (FILESentry *)GetNandLoaderFilePointer(g_BINRegionInfo.Region[nCount].dwRegionStart, g_BINRegionInfo.Region[nCount].dwRegionLength)) == NULL)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: No NANDLoader image file found! Skipping NAND program.\r\n")));
return FALSE;
}
}
if(OEMIsFlashAddr(g_BINRegionInfo.Region[nCount].dwRegionStart))
{
OALMSG(OAL_ERROR, (TEXT("ERROR: Image built for FLASH. Skipping NAND program.\r\n")));
return FALSE;
}
dwImageStart = (DWORD)OEMMapMemAddr(g_BINRegionInfo.Region[nCount].dwRegionStart, pFILES->ulLoadOffset);
// Check nandloader image file size
if(pFILES->nCompFileSize != pFILES->nRealFileSize)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: NandLoader Image should not be compressed! Skipping NAND program.\r\n")));
return FALSE;
}
if((dwImageSize = pFILES->nRealFileSize) > NAND_LOADER_IMAGE_SIZE)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: Image size(0x%X) greater than reserved(%x). Skipping NAND program.\r\n"),
pFILES->nRealFileSize, NAND_LOADER_IMAGE_SIZE));
return FALSE;
}
dwNumSectors = NAND_IMAGE_NUM_SECTOR(dwImageSize, g_FlashInfo.wDataBytesPerSector);
// first erase the flash and set block info.
OALMSG(OAL_INFO, (TEXT("INFO: Erasing NandLoader NAND flash region...\r\n")));
if(FMD_EraseBlock(0) != TRUE)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: WriteNandLoaderRegionToNand: cannot erase block 0!\r\n")));
return FALSE;
}
g_fBlock0Erased = TRUE;
blockStatus = FMD_GetBlockStatus(0);
if((blockStatus & BLOCK_STATUS_UNKNOWN))
{
OALMSG(OAL_ERROR, (TEXT("ERROR: Cannot get block 0 status! Skipping NAND program.\r\n")));
return FALSE;
}
if((blockStatus & BLOCK_STATUS_BAD))
{
#if !IGNORE_OEM_RESERVED_BAD_BLOCKS
OALMSG(OAL_ERROR, (TEXT("ERROR: Block 0 BAD! Skipping NAND program.\r\n")));
return FALSE;
#endif
}
// Set block as OEM_RESERVED and READONLY
if(FMD_SetBlockStatus(0, (BLOCK_STATUS_READONLY | BLOCK_STATUS_RESERVED)) != TRUE)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: Unable to set block 0 status! Skipping NAND program.\r\n")));
return FALSE;
}
OALMSG(OAL_FUNC, (TEXT("INFO: Writing NandLoader image to flash:\r\n")));
OALMSG(OAL_FUNC, (TEXT("imageStart:%X imageSize:%X numSectors: %d\r\n"),
dwImageStart, dwImageSize, dwNumSectors));
if(FMD_WriteSector(0, (LPBYTE)(dwImageStart), NULL, dwNumSectors ) != TRUE)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: failed to write NandLoader image (start=0x%x, length=0x%x).\r\n"), dwImageStart, dwImageSize));
return FALSE;
}
#if DEBUG
if(FMD_ReadSector(0, (LPBYTE)(EBOOT_FCACHE_START + 0x00100000), NULL, dwNumSectors ) != TRUE)
{
OALMSG(OAL_INFO, (TEXT("ERROR: failed to read NandLoader image.\r\n")));
return FALSE;
}
if(memcmp((PVOID)dwImageStart, (PVOID)(EBOOT_FCACHE_START + 0x00100000), dwImageSize) != 0)
OALMSG(OAL_INFO, (TEXT("ERROR: NandLoader image compare failed.\r\n")));
else
OALMSG(OAL_INFO, (TEXT("INFO: NandLoader image compare passed.\r\n")));
DisplayMem(dwImageStart, dwImageSize, 0x100);
#endif
EdbgOutputDebugString("INFO: Programming NandLoader to NAND complete.\r\n");
OALMSG(OAL_FUNC, (TEXT("WriteNandLoaderRegionToNand-\r\n")));
return TRUE;
}
#ifdef DEBUG
//-----------------------------------------------------------------------------
//
// FUNCTION: GetBlockNumberInput
//
// DESCRIPTION: Loops to get a valid block number from user
// input. Breaks if user presses enter only.
//
// PARAMETERS:
// None
//
// RETURNS:
// -1 for no block number entered
// entered block number otherwise
//
//-----------------------------------------------------------------------------
static DWORD GetBlockNumberInput(void)
{
DWORD dwBlock;
CHAR number;
BYTE nNumChar;
dwBlock = 0;
nNumChar= 0;
while(1)
{
number = OEMReadDebugByte();
if(number == OEM_DEBUG_READ_NODATA)
continue;
if(number == 0x08)
{
// backspace
if(nNumChar > 0)
{
nNumChar--;
OEMWriteDebugByte(number);
OEMWriteDebugByte(0xFF);
OEMWriteDebugByte(number);
dwBlock /= 10;
}
}
if(number >= '0' && number <= '9')
{
nNumChar++;
OEMWriteDebugByte(number);
dwBlock *= 10;
dwBlock += number - '0';
}
if(number == '\n' || number == '\r')
{
if(dwBlock >= 0 && dwBlock < g_FlashInfo.dwNumBlocks)
break;
else
{
OALMSG(1, (TEXT("ERROR: Invalid block %d.\r\n"), dwBlock));
dwBlock = 0;
nNumChar = 0;
}
}
}
OALMSG(1, (TEXT("\r\n")));
if(nNumChar == 0)
return -1;
else
return dwBlock;
}
/*********************************************************************
*
* FUNCTION: DisplayMem
*
* DESCRIPTION: Display mem contents in hex
*
* PARAMETERS:
* start - mem start
* size - mem end
* displaySize - size of mem to display at a go
*
* RETURNS:
* None
*
********************************************************************/
static void DisplayMem(UINT32 start, UINT32 size, UINT32 displaySize)
{
UINT32 *pImage;
UINT32 dwSize;
BOOL bStopDisplay;
char selection;
pImage = (UINT32 *)start;
bStopDisplay = FALSE;
dwSize = 0;
while(size > 0 && bStopDisplay == FALSE)
{
OALMSG(1, (TEXT("0x%08X: %08X %08X %08X %08X\r\n"), pImage,
LE32(*pImage), LE32(*(pImage+1)), LE32(*(pImage+2)), LE32(*(pImage+3)) ));
pImage += 4;
dwSize += 4 * sizeof(DWORD);
size -= 4 * sizeof(DWORD);
if(dwSize >= displaySize && dwSize % displaySize == 0)
{
OALMSG(1, (TEXT("Press Enter to continue or 'b' to break.\r\n")));
while(1)
{
selection = OEMReadDebugByte();
if(selection == 0x0d || selection == 0x20)
break;
if(selection == 'b' || selection == 'B')
{
bStopDisplay = TRUE;
break;
}
};
}
}
}
#endif
//-----------------------------------------------------------------------------
// END OF FILE
//-----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -