📄 nand.c
字号:
// dwRegionLength - size of region
//
// RETURNS:
// Pointer to kernel's extension area. NULL if failure.
//-----------------------------------------------------------------------------
static PVOID GetNandLoaderFilePointer(DWORD dwRegionStart, DWORD dwRegionLength)
{
DWORD dwCacheAddress = 0;
ROMHDR *pROMHeader;
DWORD dwNumFiles = 0;
TOCentry *pTOC;
FILESentry *pFILES;
OALMSG(OAL_FUNC, (TEXT("GetNandLoaderFilePointer+\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);
OALMSG(OAL_FUNC, (TEXT("dwCacheAddress:%X dwRegionStart:%X :%X\r\n"), dwCacheAddress, dwRegionStart, dwRegionStart + ROM_SIGNATURE_OFFSET + sizeof(ULONG)));
OALMSG(OAL_FUNC, (TEXT("pROMHeader:%X\r\n"), pROMHeader));
OALMSG(OAL_FUNC, (TEXT("\n")));
OALMSG(OAL_FUNC, (TEXT("ROMHDR ----------------------------------------\r\n")));
OALMSG(OAL_FUNC, (TEXT(" DLL First : 0x%X \r\n"), pROMHeader->dllfirst));
OALMSG(OAL_FUNC, (TEXT(" DLL Last : 0x%X \r\n"), pROMHeader->dlllast));
OALMSG(OAL_FUNC, (TEXT(" Physical First : 0x%X \r\n"), pROMHeader->physfirst));
OALMSG(OAL_FUNC, (TEXT(" Physical Last : 0x%X \r\n"), pROMHeader->physlast));
OALMSG(OAL_FUNC, (TEXT(" RAM Start : 0x%X \r\n"), pROMHeader->ulRAMStart));
OALMSG(OAL_FUNC, (TEXT(" RAM Free : 0x%X \r\n"), pROMHeader->ulRAMFree));
OALMSG(OAL_FUNC, (TEXT(" RAM End : 0x%X \r\n"), pROMHeader->ulRAMEnd));
OALMSG(OAL_FUNC, (TEXT(" Kernel flags : 0x%X \r\n"), pROMHeader->ulKernelFlags));
OALMSG(OAL_FUNC, (TEXT(" Prof Symbol Offset : 0x%X \r\n"), pROMHeader->ulProfileOffset));
OALMSG(OAL_FUNC, (TEXT(" Num Copy Entries : %d \r\n"), pROMHeader->ulCopyEntries));
OALMSG(OAL_FUNC, (TEXT(" Copy Entries Offset : 0x%X \r\n"), pROMHeader->ulCopyOffset));
OALMSG(OAL_FUNC, (TEXT(" Num Modules : %d \r\n"), pROMHeader->nummods));
OALMSG(OAL_FUNC, (TEXT(" Num Files : %d \r\n"), pROMHeader->numfiles));
// Make sure sure are some modules in the table of contents.
//
if(pROMHeader->nummods == 0)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: No modules in ROM header!\r\n")));
return NULL;
}
// Make sure sure are some files in the table of contents.
//
if((dwNumFiles = pROMHeader->numfiles) == 0)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: No files in ROM header! %d\r\n"), dwNumFiles));
return NULL;
}
// Locate the table of contents and search for the nandloader binary.
//
pTOC = (TOCentry *)(pROMHeader + 1);
pFILES = (FILESentry *)(pTOC + pROMHeader->nummods);
while(dwNumFiles--) {
LPBYTE pFileName = OEMMapMemAddr(dwRegionStart, (DWORD)pFILES->lpszFileName);
switch(g_FlashWidth)
{
case 8:
if (!strcmp((const char *)pFileName, "nandloader_8bit.nb0")) {
OALMSG(OAL_FUNC, (TEXT("Nandloader 8bit file found.\r\n")));
return ((PVOID)(pFILES));
}
break;
case 16:
if (!strcmp((const char *)pFileName, "nandloader_16bit.nb0")) {
OALMSG(OAL_FUNC, (TEXT("Nandloader 16bit file found.\r\n")));
return ((PVOID)(pFILES));
}
break;
default:
return NULL;
}
++pFILES;
}
OALMSG(OAL_FUNC, (TEXT("GetNandLoaderFilePointer-\r\n")));
return NULL;
}
//-----------------------------------------------------------------------------
//
// FUNCTION: GetRequiredNumBlocks
//
// DESCRIPTION: Gets the number of blocks required for EBOOT
// region including bad blocks in region. Also checks
// for a valid start block of the region.
//
// PARAMETERS:
// pBootCfg - Ptr to EBOOT configuration structure.
// Ignored.
//
// RETURNS: TRUE for success. FALSE for failure.
//
//-----------------------------------------------------------------------------
static DWORD FindFirstGoodBlock(DWORD dwStartBlock)
{
DWORD dwBlockStatus;
DWORD dwBlock;
OALMSG(OAL_FUNC, (TEXT("FindFirstGoodBlock+\r\n")));
for(dwBlock = dwStartBlock; dwBlock < g_FlashInfo.dwNumBlocks; dwBlock++)
{
dwBlockStatus = FMD_GetBlockStatus(dwBlock);
if(!(dwBlockStatus & (BLOCK_STATUS_UNKNOWN | BLOCK_STATUS_BAD)))
break;
}
OALMSG(OAL_FUNC, (TEXT("FindFirstGoodBlock-: dwBlock: %d\r\n"), dwBlock));
return dwBlock;
}
//-----------------------------------------------------------------------------
//
// FUNCTION: WriteRegionsToNand
//
// DESCRIPTION: Writes bin regions to NAND.
//
// PARAMETERS:
// pBootCfg - Ptr to EBOOT configuration structure
//
// RETURNS: TRUE for success. FALSE for failure.
//
//-----------------------------------------------------------------------------
static BOOL WriteOSRegionsToNand(BOOT_CFG *pBootCfg)
{
extern MultiBINInfo g_BINRegionInfo;
EBOOT_NANDCFG nandParams;
PXIPCHAIN_SUMMARY pChainInfo = NULL;
PPARTENTRY pPartEntry;
HANDLE hPart;
HANDLE hBootPart;
DWORD dwNumExts;
DWORD dwPartitionLength = 0;
DWORD dwNumSectors = 0;
BYTE nCount;
UINT32 xip_chain_addr = 0;
OALMSG(OAL_FUNC, (TEXT("WriteOSRegionsToNand+\r\n")));
if(!pBootCfg)
{
OALMSG(OAL_ERROR, (TEXT("WriteOSRegionsToNand: Invalid input Parameter!\r\n")));
return FALSE;
}
if(g_fNandExists != TRUE)
{
OALMSG(OAL_INFO, (TEXT("INFO: NAND device doesn't exist - unable to write image.\r\n")));
return FALSE;
}
// Look in the kernel regions extension area for a multi-BIN
// extension descriptor. This region, if found, details the
// number, start, and size of each XIP region.
for (nCount = 0, dwNumExts = 0 ; (nCount < g_BINRegionInfo.dwNumRegions) && !pChainInfo ; nCount++)
{
EXTENSION *pExt = NULL;
// Does this region contain nk.exe and an extension pointer?
if ((pExt = (EXTENSION *)GetKernelExtPointer(g_BINRegionInfo.Region[nCount].dwRegionStart, g_BINRegionInfo.Region[nCount].dwRegionLength)) != NULL)
{
// If there is an extension pointer region, walk it until the end.
while (pExt)
{
DWORD dwBaseAddr = g_BINRegionInfo.Region[nCount].dwRegionStart;
pExt = (EXTENSION *)OEMMapMemAddr(dwBaseAddr, (DWORD)pExt);
if ((pExt->type == 0) && !strcmp(pExt->name, "chain information"))
{
pChainInfo = (PXIPCHAIN_SUMMARY)OEMMapMemAddr(dwBaseAddr, (DWORD)pExt->pdata);
dwNumExts = (pExt->length / sizeof(XIPCHAIN_SUMMARY));
OALMSG(OAL_FUNC, (TEXT("Found chain information (pChainInfo=0x%x Extensions=0x%x).\r\n"), (DWORD)pChainInfo, dwNumExts));
OALMSG(OAL_FUNC, (TEXT("pvAddr:0x%X dwMaxLength:0x%X usOrder:0x%x usFlags:0x%X\r\n"),
pChainInfo->pvAddr, pChainInfo->dwMaxLength, pChainInfo->usOrder, pChainInfo->usFlags));
// Store chain region info for booting use
nandParams.dwChainStart = (DWORD)pChainInfo->pvAddr;
nandParams.dwChainLength= pChainInfo->dwMaxLength;
nandParams.dwChainOffset = 0xffffffff;
// Remember the chain idx
xip_chain_addr = nandParams.dwChainStart;
break;
}
pExt = (EXTENSION *)pExt->pNextExt;
}
}
}
// If we're downloading all the files in a multi-region image,
// first format the flash and write out logical sector numbers.
if(pChainInfo && dwNumExts == g_BINRegionInfo.dwNumRegions)
{
// Skip the first entry - this is the chain file.
for(nCount = 0, dwPartitionLength = 0; nCount < dwNumExts; nCount++)
{
// Handle both cases where the image is built for flash or for RAM.
dwPartitionLength += (pChainInfo + nCount)->dwMaxLength;
OALMSG(OAL_FUNC, (TEXT("dwPartitionLength:0x%X dwMaxLength:0x%X\r\n"),
dwPartitionLength, (pChainInfo + nCount)->dwMaxLength));
}
// Calculate the Chain offset - Locate after all the images
nandParams.dwChainOffset = dwPartitionLength - nandParams.dwChainLength;
}
else
{
// If downloading a single image that contains the kernel
// then format the flash and write logical sector numbers.
// Note that we don't want to format flash when downloading
// a single image of a multi-image build.
dwPartitionLength = g_BINRegionInfo.Region[0].dwRegionLength;
nandParams.dwChainStart = 0;
nandParams.dwChainLength= 0;
nandParams.dwChainOffset = 0;
}
dwNumSectors = ((dwPartitionLength + g_FlashInfo.wDataBytesPerSector - 1) / g_FlashInfo.wDataBytesPerSector);
OALMSG(OAL_FUNC, (TEXT("dwPartitionLength:%X dwNumSectors:%d\r\n"),
dwPartitionLength, dwNumSectors));
// NOTE: Do not allow the partition manager to format the flash part if it can't
// find a valid MBR because default FORMAT_SKIP_RESERVED is not set by default.
// This will result in OEM reserved blocks being erased.
OALMSG(OAL_INFO, (TEXT("INFO: Creating/opening OS flash partition (this may take a few minutes if flash needs to be formatted).\r\n")));
// Create/open a partition to store the image.
#if 1
hPart = BP_OpenPartition(NEXT_FREE_LOC, dwNumSectors,
PART_BINFS, TRUE, PART_OPEN_EXISTING);
if(hPart == INVALID_HANDLE_VALUE)
{
DWORD dwCurMSec;
BOOL bFormat = FALSE;
BYTE selection;
OALMSG(OAL_INFO, (TEXT("INFO: Cannot find existing BinFS partition.\r\n")));
// No existing partition, do a low level format if user agrees.
OALMSG(1, (TEXT("Press 'F' within 3 seconds to do a low level format.\r\n")));
dwCurMSec = OEMEthGetSecs();
while(OEMEthGetSecs() < (dwCurMSec + 3))
{
selection = OEMReadDebugByte();
if((selection == 'f' || selection == 'F'))
{
bFormat = TRUE;
break;
}
}
if(bFormat == FALSE)
return FALSE;
OALMSG(OAL_INFO, (TEXT("INFO: Performing low level format on NAND...\r\n")));
if(BP_LowLevelFormat(0, -1, FORMAT_SKIP_RESERVED) != TRUE)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: Failed to low-level format NAND.\r\n")));
return FALSE;
}
else
OALMSG(OAL_INFO, (TEXT("INFO: Successfully formatted NAND.\r\n")));
OALMSG(OAL_INFO, (TEXT("INFO: Creating new BinFS partition.\r\n")));
hPart = BP_OpenPartition(NEXT_FREE_LOC, dwNumSectors,
PART_BINFS, TRUE, PART_OPEN_ALWAYS);
if(hPart == INVALID_HANDLE_VALUE)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: Cannot create BinFS partition!\r\n")));
return FALSE;
}
else
OALMSG(OAL_INFO, (TEXT("INFO: Successfully created BinFS partition.\r\n")));
}
else
OALMSG(OAL_INFO, (TEXT("INFO: Successfully opened BinFS partition.\r\n")));
#else
hPart = BP_OpenPartition(NEXT_FREE_LOC, dwNumSectors,
PART_BINFS, TRUE, PART_OPEN_ALWAYS);
if(hPart == INVALID_HANDLE_VALUE)
{
EdbgOutputDebugString("ERROR: Cannot create BinFS partition!\r\n");
return FALSE;
}
else
EdbgOutputDebugString("INFO: Successfully opened BinFS partition.\r\n");
#endif
// Check partition size
pPartEntry = BP_GetPartitionInfo(hPart);
if(!pPartEntry)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: Cannot get BINFS partition info.\r\n")));
return FALSE;
}
if(pPartEntry->Part_TotalSectors < dwNumSectors)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: Existing BINFS partition too small to store image. Please perform a low level format first!\r\n")));
return FALSE;
}
else
OALMSG(OAL_INFO, (TEXT("INFO: Existing partition size: 0x%X!\r\n"), pPartEntry->Part_TotalSectors * g_FlashInfo.wDataBytesPerSector));
OALMSG(OAL_INFO, (TEXT("INFO: Writing OS RAM image to flash partition:\r\n")));
// Create/open a bootsection partition to nand params.
hBootPart = BP_OpenPartition(NEXT_FREE_LOC,
NAND_IMAGE_NUM_SECTOR(sizeof(EBOOT_NANDCFG), g_FlashInfo.wDataBytesPerSector),
PART_BOOTSECTION, FALSE, PART_OPEN_ALWAYS);
if(hBootPart == INVALID_HANDLE_VALUE)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: failed to create/open BOOTSECTION partition.\r\n")));
return FALSE;
}
else
{
nandParams.ConfigMagicNumber = EbootCFGMagicNumber;
}
// Are there multiple BIN files in RAM (we may just be updating
// one in a multi-BIN solution)?
for(nCount = 0; nCount < g_BINRegionInfo.dwNumRegions; nCount++)
{
DWORD dwRegionStart = g_BINRegionInfo.Region[nCount].dwRegionStart;
DWORD dwRegionLength = g_BINRegionInfo.Region[nCount].dwRegionLength;
DWORD dwImageOffset;
if(OEMIsFlashAddr(dwRegionStart))
{
EdbgOutputDebugString("WARNING: Image built for FLASH. Skipping NAND program.\r\n");
break;
}
// Get offset of region into image.
if (xip_chain_addr == dwRegionStart)
dwImageOffset = nandParams.dwChainOffset;
else
dwImageOffset = dwRegionStart - OS_RAM_IMAGE_START;
OALMSG(OAL_FUNC, (TEXT("dwRegionStart: %X dwImageOffset:%X\r\n"),
dwRegionStart, dwImageOffset));
// Set the offset into the BINFS partition and write the image.
if(!BP_SetDataPointer(hPart, dwImageOffset))
{
OALMSG(OAL_ERROR, (TEXT("ERROR: failed to set data pointer in BINFS partition (address=0x%x).\r\n"), dwImageOffset));
return FALSE;
}
if(!BP_WriteData(hPart, (LPBYTE)dwRegionStart, dwRegionLength))
{
OALMSG(OAL_ERROR, (TEXT("ERROR: failed to write BINFS data (start=0x%x, length=0x%x).\r\n"), dwRegionStart, dwRegionLength));
return FALSE;
}
// Check if region is kernel region by checking if launch address
// is in current region.
// If so, save the region's information in the bootloader
// settings partition for use later when retrieving the region.
if(pBootCfg->LaunchAddress >= dwRegionStart &&
pBootCfg->LaunchAddress < (dwRegionStart + dwRegionLength))
{
nandParams.dwLaunchAddr = pBootCfg->LaunchAddress;
nandParams.dwRegionStart = dwRegionStart;
nandParams.dwImageOffset = dwImageOffset;
}
}
// Set the length to be total length less the lenght of the XIP Chain
// as that gets read out separately
nandParams.dwRegionLength= dwPartitionLength - nandParams.dwChainLength;
OALMSG(OAL_FUNC, (TEXT("launch (0x%x), start (0x%x), len (0x%x), offset (0x%x)\n"),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -