📄 nand.cpp
字号:
// 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);
OALMSG(OAL_INFO, (TEXT("INFO: OEMLaunch: Found chain extenstion: '%s' @ 0x%x\r\n"), pExt->name, dwBaseAddr));
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_INFO, (TEXT("INFO: OEMLaunch: Found 'chain information' (pChainInfo=0x%x Extensions=0x%x).\r\n"), (DWORD)pChainInfo, dwNumExts));
break;
}
pExt = (EXTENSION *)pExt->pNextExt;
}
}
else {
// Search for Chain region. Chain region doesn't have the ROMSIGNATURE set
DWORD dwRegionStart = g_BINRegionInfo.Region[nCount].dwRegionStart;
DWORD dwSig = *(LPDWORD) OEMMapMemAddr(dwRegionStart, dwRegionStart + ROM_SIGNATURE_OFFSET);
if ( dwSig != ROM_SIGNATURE) {
// It is the chain
dwChainStart = dwRegionStart;
dwChainLength = g_BINRegionInfo.Region[nCount].dwRegionLength;
OALMSG(TRUE, (TEXT("Found the Chain region: StartAddress: 0x%X; Length: 0x%X\n"), dwChainStart, dwChainLength));
}
}
}
// Determine how big the Total BINFS partition needs to be to store all of this.
//
if (pChainInfo && dwNumExts == g_BINRegionInfo.dwNumRegions) // We're downloading all the regions in a multi-region image...
{
DWORD i;
OALMSG(TRUE, (TEXT("Writing multi-regions\r\n")));
for (nCount = 0, dwBINFSPartLength = 0 ; nCount < dwNumExts ; nCount++)
{
dwBINFSPartLength += (pChainInfo + nCount)->dwMaxLength;
OALMSG(OAL_ERROR, (TEXT("BINFSPartMaxLength[%u]: 0x%x, TtlBINFSPartLength: 0x%x \r\n"),
nCount, (pChainInfo + nCount)->dwMaxLength, dwBINFSPartLength));
// MultiBINInfo does not store each Regions MAX length, and pChainInfo is not in any particular order.
// So, walk our MultiBINInfo matching up pChainInfo to find each regions MAX Length
for (i = 0; i < dwNumExts; i++) {
if ( g_BINRegionInfo.Region[i].dwRegionStart == (DWORD)((pChainInfo + nCount)->pvAddr) ) {
dwMaxRegionLength[i] = (pChainInfo + nCount)->dwMaxLength;
OALMSG(TRUE, (TEXT("dwMaxRegionLength[%u]: 0x%x \r\n"), i, dwMaxRegionLength[i]));
break;
}
}
}
}
else // A single BIN file or potentially a multi-region update (but the partition's already been created in this latter case).
{
dwBINFSPartLength = g_BINRegionInfo.Region[0].dwRegionLength;
OALMSG(TRUE, (TEXT("Writing single region/multi-region update, dwBINFSPartLength: %u \r\n"), dwBINFSPartLength));
}
// Open/Create the BINFS partition where images are stored. This partition starts immediately after the MBR on the Boot Media and its length is
// determined by the maximum image size (or sum of all maximum sizes in a multi-region design).
// Parameters are LOGICAL sectors.
//
hPart = BP_OpenPartition( (IMAGE_START_BLOCK+1)*PAGES_PER_BLOCK, // next block of MBR
SECTOR_TO_BLOCK_SIZE(FILE_TO_SECTOR_SIZE(dwBINFSPartLength))*PAGES_PER_BLOCK, // align to block
PART_BINFS,
TRUE,
PART_OPEN_ALWAYS);
if (hPart == INVALID_HANDLE_VALUE )
{
OALMSG(OAL_ERROR, (TEXT("ERROR: WriteOSImageToBootMedia: Failed to open/create partition.\r\n")));
return(FALSE);
}
// Are there multiple BIN files in RAM (we may just be updating one in a multi-BIN solution)?
//
for (nCount = 0, dwStoreOffset = 0; nCount < g_BINRegionInfo.dwNumRegions ; nCount++)
{
DWORD dwRegionStart = (DWORD)OEMMapMemAddr(0, g_BINRegionInfo.Region[nCount].dwRegionStart);
DWORD dwRegionLength = g_BINRegionInfo.Region[nCount].dwRegionLength;
// Media byte offset where image region is stored.
dwStoreOffset += nCount ? dwMaxRegionLength[nCount-1] : 0;
// Set the file pointer (byte indexing) to the correct offset for this particular region.
//
if ( !BP_SetDataPointer(hPart, dwStoreOffset) )
{
OALMSG(OAL_ERROR, (TEXT("ERROR: StoreImageToBootMedia: Failed to set data pointer in partition (offset=0x%x).\r\n"), dwStoreOffset));
return(FALSE);
}
// Write the region to the BINFS partition.
//
if ( !BP_WriteData(hPart, (LPBYTE)dwRegionStart, dwRegionLength) )
{
EdbgOutputDebugString("ERROR: StoreImageToBootMedia: Failed to write region to BINFS partition (start=0x%x, length=0x%x).\r\n", dwRegionStart, dwRegionLength);
return(FALSE);
}
// update our TOC?
//
if ((g_pTOC->id[g_dwTocEntry].dwLoadAddress == g_BINRegionInfo.Region[nCount].dwRegionStart) &&
g_pTOC->id[g_dwTocEntry].dwTtlSectors == FILE_TO_SECTOR_SIZE(dwRegionLength) )
{
g_pTOC->id[g_dwTocEntry].dwStoreOffset = dwStoreOffset;
g_pTOC->id[g_dwTocEntry].dwJumpAddress = 0; // Filled upon return to OEMLaunch
g_pTOC->id[g_dwTocEntry].dwImageType = g_ImageType;
g_pTOC->id[g_dwTocEntry].sgList[0].dwSector = FILE_TO_SECTOR_SIZE(g_dwLastWrittenLoc);
g_pTOC->id[g_dwTocEntry].sgList[0].dwLength = g_pTOC->id[g_dwTocEntry].dwTtlSectors;
// copy Kernel Region to SDRAM for jump
memcpy((void*)g_pTOC->id[g_dwTocEntry].dwLoadAddress, (void*)dwRegionStart, dwRegionLength);
OALMSG(TRUE, (TEXT("Updateded TOC!\r\n")));
}
else if( (dwChainStart == g_BINRegionInfo.Region[nCount].dwRegionStart) &&
(dwChainLength == g_BINRegionInfo.Region[nCount].dwRegionLength))
{
// Update our TOC for Chain region
g_pTOC->chainInfo.dwLoadAddress = dwChainStart;
g_pTOC->chainInfo.dwFlashAddress = FILE_TO_SECTOR_SIZE(g_dwLastWrittenLoc);
g_pTOC->chainInfo.dwLength = FILE_TO_SECTOR_SIZE(dwMaxRegionLength[nCount]);
OALMSG(TRUE, (TEXT("Written Chain Region to the Flash\n")));
OALMSG(TRUE, (TEXT("LoadAddress = 0x%X; FlashAddress = 0x%X; Length = 0x%X\n"),
g_pTOC->chainInfo.dwLoadAddress,
g_pTOC->chainInfo.dwFlashAddress,
g_pTOC->chainInfo.dwLength));
// Now copy it to the SDRAM
memcpy((void *)g_pTOC->chainInfo.dwLoadAddress, (void *)dwRegionStart, dwRegionLength);
}
}
// create extended partition in whatever is left
//
hPartEx = BP_OpenPartition( NEXT_FREE_LOC,
USE_REMAINING_SPACE,
PART_DOS32,
TRUE,
PART_OPEN_ALWAYS);
if (hPartEx == INVALID_HANDLE_VALUE )
{
OALMSG(OAL_WARN, (TEXT("*** WARN: StoreImageToBootMedia: Failed to open/create Extended partition ***\r\n")));
}
OALMSG(OAL_FUNC, (TEXT("-WriteOSImageToBootMedia\r\n")));
return(TRUE);
}
/*
@func BOOL | ReadKernelRegionFromBootMedia |
BinFS support. Reads the kernel region from Boot Media into RAM. The kernel region is fixed up
to run from RAM and this is done just before jumping to the kernel entry point.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
BOOL ReadOSImageFromBootMedia()
{
HANDLE hPart;
SectorInfo si;
DWORD chainaddr, flashaddr;
DWORD i;
OALMSG(OAL_FUNC, (TEXT("+ReadOSImageFromBootMedia\r\n")));
if (!g_bBootMediaExist)
{
OALMSG(OAL_ERROR, (TEXT("ERROR: WriteRawImageToBootMedia: device doesn't exist.\r\n")));
return(FALSE);
}
if ( !VALID_TOC(g_pTOC) )
{
OALMSG(OAL_ERROR, (TEXT("ERROR: ReadOSImageFromBootMedia: INVALID_TOC\r\n")));
return(FALSE);
}
if ( !VALID_IMAGE_DESCRIPTOR(&g_pTOC->id[g_dwTocEntry]) )
{
OALMSG(OAL_ERROR, (TEXT("ReadOSImageFromBootMedia: ERROR_INVALID_IMAGE_DESCRIPTOR: 0x%x\r\n"),
g_pTOC->id[g_dwTocEntry].dwSignature));
return FALSE;
}
if ( !OEMVerifyMemory(g_pTOC->id[g_dwTocEntry].dwLoadAddress, sizeof(DWORD)) ||
!OEMVerifyMemory(g_pTOC->id[g_dwTocEntry].dwJumpAddress, sizeof(DWORD)) ||
!g_pTOC->id[g_dwTocEntry].dwTtlSectors )
{
OALMSG(OAL_ERROR, (TEXT("ReadOSImageFromBootMedia: ERROR_INVALID_ADDRESS: (address=0x%x, sectors=0x%x, launch address=0x%x)...\r\n"),
g_pTOC->id[g_dwTocEntry].dwLoadAddress, g_pTOC->id[g_dwTocEntry].dwTtlSectors, g_pTOC->id[g_dwTocEntry].dwJumpAddress));
return FALSE;
}
// Open the BINFS partition (it must exist).
//
hPart = BP_OpenPartition( NEXT_FREE_LOC,
USE_REMAINING_SPACE,
PART_BINFS,
TRUE,
PART_OPEN_EXISTING);
if (hPart == INVALID_HANDLE_VALUE )
{
OALMSG(OAL_ERROR, (TEXT("ERROR: ReadOSImageFromBootMedia: Failed to open existing partition.\r\n")));
return(FALSE);
}
// Set the partition file pointer to the correct offset for the kernel region.
//
if ( !BP_SetDataPointer(hPart, g_pTOC->id[g_dwTocEntry].dwStoreOffset) )
{
OALMSG(OAL_ERROR, (TEXT("ERROR: ReadOSImageFromBootMedia: Failed to set data pointer in partition (offset=0x%x).\r\n"),
g_pTOC->id[g_dwTocEntry].dwStoreOffset));
return(FALSE);
}
// Read the kernel region from the Boot Media into RAM.
//
if ( !BP_ReadData( hPart,
(LPBYTE)(g_pTOC->id[g_dwTocEntry].dwLoadAddress),
SECTOR_TO_FILE_SIZE(g_pTOC->id[g_dwTocEntry].dwTtlSectors)) )
{
OALMSG(OAL_ERROR, (TEXT("ERROR: ReadOSImageFromBootMedia: Failed to read kernel region from partition.\r\n")));
return(FALSE);
}
if (!g_pTOC->chainInfo.dwLoadAddress)
{
chainaddr = g_pTOC->chainInfo.dwLoadAddress;
flashaddr = g_pTOC->chainInfo.dwFlashAddress;
for ( i = 0; i < (g_pTOC->chainInfo.dwLength); i++ )
{
OALMSG(TRUE, (TEXT("chainaddr=0x%x, flashaddr=0x%x\r\n"), chainaddr, flashaddr+i));
if ( !FMD_ReadSector(flashaddr+i, (PUCHAR)(chainaddr), &si, 1) ) {
OALMSG(OAL_ERROR, (TEXT("TOC_Write ERROR: Unable to read/verify TOC\r\n")));
return FALSE;
}
chainaddr += 512;
}
}
OALMSG(OAL_FUNC, (TEXT("_ReadOSImageFromBootMedia\r\n")));
return(TRUE);
}
BOOL ReadBlock(DWORD dwBlock, LPBYTE pbBlock, PSectorInfo pSectorInfoTable)
{
for (int iSector = 0; iSector < g_FlashInfo.wSectorsPerBlock; iSector++) {
if (!FMD_ReadSector(dwBlock * g_FlashInfo.wSectorsPerBlock + iSector, pbBlock, pSectorInfoTable, 1))
return FALSE;
if (pbBlock)
pbBlock += g_FlashInfo.wDataBytesPerSector;
if (pSectorInfoTable)
pSectorInfoTable++;
}
return TRUE;
}
BOOL WriteBlock(DWORD dwBlock, LPBYTE pbBlock, PSectorInfo pSectorInfoTable)
{
for (int iSector = 0; iSector < g_FlashInfo.wSectorsPerBlock; iSector++) {
if (!FMD_WriteSector(dwBlock * g_FlashInfo.wSectorsPerBlock + iSector, pbBlock, pSectorInfoTable, 1))
return FALSE;
if (pbBlock)
pbBlock += g_FlashInfo.wDataBytesPerSector;
if (pSectorInfoTable)
pSectorInfoTable++;
}
return TRUE;
}
BOOL WriteRawImageToBootMedia(DWORD dwImageStart, DWORD dwImageLength, DWORD dwLaunchAddr)
{
DWORD dwBlock,dwNumBlocks;
LPBYTE pbBuffer;
SectorInfo si;
OALMSG(OAL_FUNC, (TEXT("+WriteRawImageToBootMedia\r\n")));
if ( !g_bBootMediaExist )
{
OALMSG(OAL_ERROR, (TEXT("ERROR: WriteRawImageToBootMedia: device doesn't exist.\r\n")));
return(FALSE);
}
if (g_ImageType == IMAGE_TYPE_LOADER)
{
dwBlock = EBOOT_BLOCK;
if ( !VALID_TOC(g_pTOC) )
{
OALMSG(OAL_WARN, (TEXT("WARN: WriteRawImageToBootMedia: INVALID_TOC\r\n")));
if ( !TOC_Init(g_dwTocEntry, g_ImageType, dwImageStart, dwImageLength, dwLaunchAddr) )
{
OALMSG(OAL_ERROR, (TEXT("ERROR: INVALID_TOC\r\n")));
return(FALSE);
}
}
}
else if (g_ImageType == IMAGE_TYPE_STEPLDR)
{
dwBlock = NBOOT_BLOCK;
dwImageStart += dwLaunchAddr;
dwImageLength = 0x1000; //step loader can support 4k bytes only.
}
pbBuffer = OEMMapMemAddr(dwImageStart, dwImageStart);
// Compute number of blocks.
dwNumBlocks = (dwImageLength / 0x4000) + 1;
while (dwNumBlocks--)
{
// If the block is marked bad, skip to next block. Note that the assumption in our error checking
// is that any truely bad block will be marked either by the factory during production or will be marked
// during the erase and write verification phases. If anything other than a bad block fails ECC correction
// in this routine, it's fatal.
FMD_ReadSector(dwBlock*32, NULL, &si, 1);
// Stepldr & Eboot image in nand flash
// block mark as BLOCK_STATUS_RESERVED & BLOCK_STATUS_READONLY & BLOCK_STATUS_BAD
if ((si.bBadBlock == 0x0) && (si.bOEMReserved !=3 ))
{
++dwBlock;
++dwNumBlocks; // Compensate for fact that we didn't write any blocks.
continue;
}
if (!ReadBlock(dwBlock, NULL, g_pSectorInfoBuf))
{
OALMSG(OAL_ERROR, (TEXT("WriteData: failed to read block (0x%x).\r\n"), dwBlock));
return(FALSE);
}
if (!FMD_EraseBlock(dwBlock))
{
OALMSG(OAL_ERROR, (TEXT("WriteData: failed to erase block (0x%x).\r\n"), dwBlock));
return FALSE;
}
if (!WriteBlock(dwBlock, pbBuffer, g_pSectorInfoBuf))
{
OALMSG(OAL_ERROR, (TEXT("WriteData: failed to write block (0x%x).\r\n"), dwBlock));
return(FALSE);
}
++dwBlock;
pbBuffer += 0x4000;
}
if (g_ImageType == IMAGE_TYPE_LOADER)
{
g_pTOC->id[0].dwLoadAddress = dwImageStart;
g_pTOC->id[0].dwJumpAddress = 0;
g_pTOC->id[0].dwTtlSectors = FILE_TO_SECTOR_SIZE(dwImageLength);
g_pTOC->id[0].sgList[0].dwSector = BLOCK_TO_SECTOR(EBOOT_BLOCK);
g_pTOC->id[0].sgList[0].dwLength = g_pTOC->id[0].dwTtlSectors;
}
OALMSG(OAL_FUNC, (TEXT("_WriteRawImageToBootMedia\r\n")));
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -