⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nand.c

📁 Freescale ARM9系列CPU MX27的WINCE 5.0下的BSP
💻 C
📖 第 1 页 / 共 4 页
字号:
//			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 + -