📄 nand.c
字号:
pBootCfg->LaunchAddress = nandParams.dwLaunchAddr;
OALMSG(OAL_INFO, (TEXT("NAND LaunchAddress:%X"), pBootCfg->LaunchAddress));
return TRUE;
}
//-----------------------------------------------------------------------------
//
// FUNCTION: ShowNandFlashMenu
//
// DESCRIPTION: Nand Flash menu for bootloader.
//
// PARAMETERS:
// pBootCfg - Ptr to EBOOT configuration structure
// CFGChanged - flag TRUE if EBOOT configuration
// changed.
//
// RETURNS:
// TRUE if OS images needs to be downloaded.
// FALSE otherwise. ie. OS image already in RAM.
//
//-----------------------------------------------------------------------------
BOOL IsNandDevicePresent(void)
{
return g_fNandExists;
}
//-----------------------------------------------------------------------------
//
// FUNCTION: ShowNandFlashMenu
//
// DESCRIPTION: Nand Flash menu for bootloader.
//
// PARAMETERS:
// pBootCfg - Ptr to EBOOT configuration structure
// CFGChanged - flag TRUE if EBOOT configuration
// changed.
//
// RETURNS:
// TRUE if OS image is read to ram.
// FALSE otherwise.
//
//-----------------------------------------------------------------------------
BOOL NandFlashMenu(BOOT_CFG *pBootCfg, BOOL *CFGChanged)
{
BOOL bExitMenu;
BOOL bImageExists;
CHAR selection;
bExitMenu = FALSE;
bImageExists = FALSE;
selection = OEM_DEBUG_READ_NODATA;
do
{
// Nand Flash Menu
EdbgOutputDebugString("\r\nNAND Flash Menu\r\n");
EdbgOutputDebugString("NAND flash %s.\r\n", g_fNandExists? "present.":"not found!");
EdbgOutputDebugString("1) Low-level format. (WARNING: This will destroy any existing OS data!)\r\n");
EdbgOutputDebugString("2) Write ram image BIN to Flash.(%s)\r\n",
(pBootCfg->ConfigFlags & CONFIG_FLAGS_SAVETOFLASH)? "Enabled":"Disabled");
EdbgOutputDebugString("3) Launch existing OS image from NAND Flash.\r\n");
#if DEBUG
EdbgOutputDebugString("4) Erase EBOOT region from NAND Flash.\r\n");
EdbgOutputDebugString("5) Erase NANDLoader region from NAND Flash.\r\n");
EdbgOutputDebugString("6) Display EBOOT image from NAND Flash.\r\n");
EdbgOutputDebugString("7) Display NANDLoader image from NAND Flash.\r\n");
EdbgOutputDebugString("8) Set a block as bad.\r\n");
EdbgOutputDebugString("9) Erase block range.\r\n");
#endif
EdbgOutputDebugString("B) Return To Main Menu.\r\n");
EdbgOutputDebugString("Enter your selection: ");
while(1)
{
selection = OEMReadDebugByte();
#if DEBUG
if((selection >= '1' && selection <= '9') ||
#else
if((selection >= '1' && selection <= '3') ||
#endif
selection == 'B' || selection == 'b')
break;
}
EdbgOutputDebugString ("%c\r\n\r\n", selection);
switch(selection)
{
case '1':
if(g_fNandExists == TRUE)
{
// Note: We do not want to format the Eboot and Nandloader
// regions which are marked as oem reserved.
OALMSG(OAL_INFO, (TEXT("INFO: Performing NAND low level format.\r\n")));
if(BP_LowLevelFormat(0, -1, FORMAT_SKIP_RESERVED) != TRUE)
OALMSG(OAL_ERROR, (TEXT("ERROR: Failed to low-level format NAND.\r\n")));
else
OALMSG(OAL_INFO, (TEXT("INFO: Successfully formatted NAND.\r\n")));
}
else
OALMSG(OAL_INFO, (TEXT("INFO: NAND device non existent.\r\n")));
break;
case '2':
if(g_fNandExists == TRUE)
{
if((pBootCfg->ConfigFlags & CONFIG_FLAGS_SAVETOFLASH) == 0)
pBootCfg->ConfigFlags |= CONFIG_FLAGS_SAVETOFLASH;
else
pBootCfg->ConfigFlags &= ~CONFIG_FLAGS_SAVETOFLASH;
*CFGChanged = TRUE;
}
else
OALMSG(OAL_INFO, (TEXT("INFO: NAND device non existent.\r\n")));
break;
case '3':
if(g_fNandExists == TRUE)
{
if(ReadKernelRegionFromNand(pBootCfg) == FALSE)
OALMSG(OAL_ERROR, (TEXT("ERROR: Failed to load kernel region.\r\n")));
else
{
bImageExists = TRUE;
bExitMenu = TRUE;
}
}
else
OALMSG(OAL_INFO, (TEXT("INFO: NAND device non existent.\r\n")));
break;
#if DEBUG
case '4':
if(g_fNandExists == TRUE)
{
DWORD dwBlock = FindFirstGoodBlock(1);
DWORD dwNumBlock;
OALMSG(OAL_INFO, (TEXT("Erasing %d blocks starting at %d.\r\n"),
NAND_IMAGE_NUM_BLOCK(NAND_EBOOT_IMAGE_SIZE, g_FlashInfo.dwBytesPerBlock), dwBlock));
for(dwNumBlock = 0; dwNumBlock < NAND_IMAGE_NUM_BLOCK(NAND_EBOOT_IMAGE_SIZE, g_FlashInfo.dwBytesPerBlock); dwBlock++)
{
if(FMD_EraseBlock(dwBlock) != TRUE)
OALMSG(OAL_ERROR, (TEXT("ERROR: Failed to erase EBOOT block %d.\r\n"), dwBlock));
else
dwNumBlock++;
}
}
else
OALMSG(OAL_INFO, (TEXT("INFO: NAND device non existent.\r\n")));
break;
case '5':
if(g_fNandExists == TRUE)
{
OALMSG(OAL_INFO, (TEXT("Erasing block 0.\r\n")));
if(FMD_EraseBlock(0) != TRUE)
OALMSG(OAL_ERROR, (TEXT("ERROR: Failed to erase block 0.\r\n")));
}
else
OALMSG(OAL_INFO, (TEXT("INFO: NAND device non existent.\r\n")));
break;
case '6':
if(g_fNandExists == TRUE)
{
DWORD dwBlockStatus;
DWORD dwBlock = FindFirstGoodBlock(1);
DWORD dwNumSectors = NAND_IMAGE_NUM_SECTOR(NAND_EBOOT_IMAGE_SIZE, g_FlashInfo.wDataBytesPerSector);
DWORD dwStartSectorAddr;
DWORD dwDestAddress;
DWORD dwCount;
BOOL fErr;
fErr = FALSE;
dwDestAddress = EBOOT_FCACHE_START;
while(TRUE)
{
dwBlockStatus = FMD_GetBlockStatus(dwBlock);
if(!(dwBlockStatus & BLOCK_STATUS_UNKNOWN) && !(dwBlockStatus & BLOCK_STATUS_BAD))
{
dwStartSectorAddr = dwBlock * g_FlashInfo.wSectorsPerBlock;
dwCount = dwNumSectors > g_FlashInfo.wSectorsPerBlock? g_FlashInfo.wSectorsPerBlock : dwNumSectors;
if(FMD_ReadSector((SECTOR_ADDR)dwStartSectorAddr,
(LPBYTE)dwDestAddress, NULL,
dwCount) != TRUE)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: Failed to read EBOOT image.\r\n")));
fErr = TRUE;
break;
}
else
{
dwNumSectors -= dwCount;
dwDestAddress += dwCount * g_FlashInfo.wDataBytesPerSector;
if(dwNumSectors == 0)
break;
}
}
else
OALMSG(OAL_INFO, (TEXT("block %d bad.\r\n"), dwBlock));
dwBlock++;
};
if(fErr == FALSE)
{
OALMSG(OAL_INFO, (TEXT("INFO: EBOOT image at %X.\r\n"), EBOOT_FCACHE_START));
DisplayMem(EBOOT_FCACHE_START, NAND_EBOOT_IMAGE_SIZE, 0x100);
}
}
else
OALMSG(OAL_INFO, (TEXT("INFO: NAND device non existent.\r\n")));
break;
case '7':
if(g_fNandExists == TRUE)
{
if(FMD_ReadSector((SECTOR_ADDR)0,
(LPBYTE)EBOOT_FCACHE_START, NULL,
NAND_IMAGE_NUM_SECTOR(NAND_LOADER_IMAGE_SIZE, g_FlashInfo.wDataBytesPerSector)) != TRUE)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: Failed to read NAND Loader image.\r\n")));
}
else
{
OALMSG(OAL_INFO, (TEXT("INFO: NAND Loader image at %X.\r\n"), EBOOT_FCACHE_START));
DisplayMem(EBOOT_FCACHE_START, NAND_LOADER_IMAGE_SIZE, 0x100);
}
}
else
OALMSG(OAL_INFO, (TEXT("INFO: NAND device non existent.\r\n")));
break;
case '8':
if(g_fNandExists == TRUE)
{
DWORD dwBlock;
do
{
OALMSG(1, (TEXT("Enter bad block number(1-%d): "), (g_FlashInfo.dwNumBlocks - 1)));
dwBlock = GetBlockNumberInput();
if(dwBlock >= 1 && dwBlock < g_FlashInfo.dwNumBlocks)
{
if(FMD_SetBlockStatus(dwBlock, BLOCK_STATUS_BAD) != TRUE)
OALMSG(OAL_ERROR, (TEXT("ERROR: Failed to set block %d bad.\r\n"), dwBlock));
else
OALMSG(OAL_INFO, (TEXT("INFO: block %d set as bad.\r\n"), dwBlock));
}
} while(dwBlock != -1);
}
else
OALMSG(OAL_INFO, (TEXT("INFO: NAND device non existent.\r\n")));
break;
case '9':
if(g_fNandExists == TRUE)
{
DWORD dwBlock;
DWORD dwStartBlock;
DWORD dwEndBlock;
while(1)
{
OALMSG(1, (TEXT("Enter erase start block number(0-%d): "), (g_FlashInfo.dwNumBlocks - 1)));
dwBlock = GetBlockNumberInput();
if(dwBlock != -1 && dwBlock >= 0 && dwBlock < g_FlashInfo.dwNumBlocks)
{
dwStartBlock = dwBlock;
break;
}
};
while(1)
{
OALMSG(1, (TEXT("Enter erase end block number(%d-%d): "), dwStartBlock, (g_FlashInfo.dwNumBlocks - 1)));
dwBlock = GetBlockNumberInput();
if(dwBlock < 0 || dwBlock > g_FlashInfo.dwNumBlocks || dwBlock < dwStartBlock)
{
OALMSG(1, (TEXT("Invalid block number %d\r\n"), dwBlock));
continue;
}
else
{
dwEndBlock = dwBlock;
break;
}
};
while(dwStartBlock <= dwEndBlock)
{
if(FMD_EraseBlock(dwStartBlock) != TRUE)
OALMSG(OAL_ERROR, (TEXT("ERROR: Failed to erase block %d.\r\n"), dwStartBlock));
else
OALMSG(1, (TEXT("INFO: block %d erased.\r\n"), dwStartBlock));
dwStartBlock++;
}
}
else
OALMSG(OAL_INFO, (TEXT("INFO: NAND device non existent.\r\n")));
break;
#endif
case 'b':
case 'B':
// Return To Main Menu.
bExitMenu = TRUE;
break;
default:
break;
}
} while(bExitMenu == FALSE);
return bImageExists;
}
//-----------------------------------------------------------------------------
// PRIVATE FUNCTIONS
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------**
//
// FUNCTION: GetKernelExtPointer
//
// DESCRIPTION: Used to locate the kernel region's extension area.
//
// PARAMETERS:
// dwRegionStart - start of region
// dwRegionLength - size of region
//
// RETURNS:
// Pointer to kernel's extension area. NULL if failure.
//-----------------------------------------------------------------------------
static PVOID GetKernelExtPointer(DWORD dwRegionStart, DWORD dwRegionLength)
{
DWORD dwCacheAddress = 0;
ROMHDR *pROMHeader;
DWORD dwNumModules = 0;
TOCentry *pTOC;
OALMSG(OAL_FUNC, (TEXT("GetKernelExtPointer+\r\n")));
if (dwRegionStart == 0 || dwRegionLength == 0)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: dwRegionStart:%X dwRegionLength:%X\r\n"),
dwRegionStart, dwRegionLength));
return(NULL);
}
if (*(LPDWORD)OEMMapMemAddr(dwRegionStart, dwRegionStart + ROM_SIGNATURE_OFFSET) != ROM_SIGNATURE)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: Non ROM_SIGNATURE! start:%X length:%X offset:%X\r\n"),
dwRegionStart, dwRegionLength, ROM_SIGNATURE_OFFSET));
return NULL;
}
// A pointer to the ROMHDR structure lives just past the ROM_SIGNATURE (which is a longword value). Note that
// this pointer is remapped since it might be a flash address (image destined for flash), but is actually cached
// in RAM.
//
dwCacheAddress = *(LPDWORD) OEMMapMemAddr (dwRegionStart, dwRegionStart + ROM_SIGNATURE_OFFSET + sizeof(ULONG));
pROMHeader = (ROMHDR *) OEMMapMemAddr (dwRegionStart, dwCacheAddress);
// Make sure sure are some modules in the table of contents.
//
if((dwNumModules = pROMHeader->nummods) == 0)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: No modules in ROM header!\r\n")));
return NULL;
}
// Locate the table of contents and search for the kernel executable and the TOC immediately follows the ROMHDR.
//
pTOC = (TOCentry *)(pROMHeader + 1);
while(dwNumModules--) {
LPBYTE pFileName = OEMMapMemAddr(dwRegionStart, (DWORD)pTOC->lpszFileName);
if (!strcmp((const char *)pFileName, "nk.exe")) {
OALMSG(OAL_INFO, (TEXT("INFO: Kernel region found.\r\n")));
return ((PVOID)(pROMHeader->pExtensions));
}
++pTOC;
}
OALMSG(OAL_FUNC, (TEXT("GetKernelExtPointer-\r\n")));
return NULL;
}
//-----------------------------------------------------------------------------**
//
// FUNCTION: GetNandLoaderFilePointer
//
// DESCRIPTION: Used to locate the nand loader binary file area.
//
// PARAMETERS:
// dwRegionStart - start of region
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -