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

📄 nand.c

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