?? nand.c
字號:
//-----------------------------------------------------------------------------
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on
// your install media.
//
//-----------------------------------------------------------------------------
//
// Copyright (C) 2004-2007, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//-----------------------------------------------------------------------------
//
// File: nand.c
//
// Contains BOOT NAND flash support functions.
//
//-----------------------------------------------------------------------------
#include "bsp.h"
#include "loader.h"
#pragma warning(push)
#pragma warning(disable: 4115)
#include <fmd.h>
#pragma warning(pop)
//-----------------------------------------------------------------------------
// External Functions
//-----------------------------------------------------------------------------
// External Variables
extern BOOL g_bNandExist;
//-----------------------------------------------------------------------------
// Defines
#define NANDFC_BOOT_SIZE (2*1024)
//-----------------------------------------------------------------------------
// Types
//-----------------------------------------------------------------------------
// Global Variables
BYTE sectorBuf[NANDFC_BOOT_SIZE];
static FlashInfo g_flashInfo;
//-----------------------------------------------------------------------------
// Local Variables
//-----------------------------------------------------------------------------
// Local Functions
//-----------------------------------------------------------------------------
//
// Function: NANDWriteXldr
//
// This function writes to NAND flash memory the XLDR image stored
// in the RAM file cache area.
//
// Parameters:
// dwStartAddr
// [in] Address in flash memory where the start of the downloaded
// XLDR image is to be written.
//
// dwLength
// [in] Length of the XLDR image, in bytes, to be written to flash
// memory.
//
// Returns:
// TRUE indicates success. FALSE indicates failure.
//
//-----------------------------------------------------------------------------
BOOL NANDWriteXldr(DWORD dwStartAddr, DWORD dwLength)
{
FlashInfo flashInfo;
LPBYTE pSectorBuf, pImage;
SectorInfo sectorInfo;
SECTOR_ADDR sectorAddr, endSectorAddr;
// Check for NAND device availability
//
if (!g_bNandExist)
{
EdbgOutputDebugString("WARNING: NAND device doesn't exist - unable to store image.\r\n");
return(FALSE);
}
EdbgOutputDebugString("INFO: Writing XLDR image to NAND (please wait)...\r\n");
if (!FMD_GetInfo(&flashInfo))
{
EdbgOutputDebugString("ERROR: Unable to get NAND flash information.\r\n");
return(FALSE);
}
// XLDR is placed in block #0 of the NAND device.
// Block #0 is always good, so just erase it
if (!FMD_EraseBlock(0))
{
EdbgOutputDebugString("ERROR: Unable to erase NAND flash block #0\r\n");
return(FALSE);
}
// Get cached image location
pImage = OEMMapMemAddr(dwStartAddr, dwStartAddr);
// If image is larger than 4K, this must be xldr.bin produced by
// ROMIMAGE
if (dwLength > 0x1000)
{
// ROMIMAGE adds 4K page at the beginning of the image.
// We will flash the first 2K bytes that appear after this 4K page.
//
pImage += 0x1000;
dwLength -= 0x1000;
}
// Make sure XLDR length does not exceed size that can be supported by NANDFC (2KB)
if (dwLength > NANDFC_BOOT_SIZE)
{
EdbgOutputDebugString("ERROR: XLDR exceeds 2KByte\r\n");
return(FALSE);
}
// Fill unused space with 0xFF
memset(pImage + dwLength, 0xFF, (NANDFC_BOOT_SIZE) - dwLength);
EdbgOutputDebugString("INFO: Using XLDR image from flash cache address 0x%x, size = %d\r\n", pImage, dwLength);
sectorInfo.dwReserved1 = 0xFFFFFFFF;
sectorInfo.bOEMReserved = 0x00;
sectorInfo.bBadBlock = 0xFF;
sectorInfo.wReserved2 = 0xFFFF;
endSectorAddr = (NANDFC_BOOT_SIZE / flashInfo.wDataBytesPerSector);
// Write XLDR to NAND flash
pSectorBuf = pImage;
for (sectorAddr = 0; sectorAddr < endSectorAddr; sectorAddr++)
{
if (!FMD_WriteSector(sectorAddr, pSectorBuf, §orInfo, 1))
{
EdbgOutputDebugString("ERROR: Failed to update XLDR.\r\n");
return(FALSE);
}
pSectorBuf += flashInfo.wDataBytesPerSector;
}
// Read XLDR from NAND flash to verify contents
pSectorBuf = pImage + NANDFC_BOOT_SIZE;
for (sectorAddr = 0; sectorAddr < endSectorAddr; sectorAddr++)
{
if (!FMD_ReadSector(sectorAddr, pSectorBuf, §orInfo, 1))
{
EdbgOutputDebugString("ERROR: Failed to verify XLDR.\r\n");
return(FALSE);
}
pSectorBuf += flashInfo.wDataBytesPerSector;
}
if (memcmp(pImage, pImage + NANDFC_BOOT_SIZE, NANDFC_BOOT_SIZE) != 0)
{
EdbgOutputDebugString("ERROR: Failed to verify XLDR.\r\n");
}
EdbgOutputDebugString("INFO: Update of XLDR completed successfully.\r\n");
return(TRUE);
}
//-----------------------------------------------------------------------------
//
// Function: NANDWriteBoot
//
// This function writes to NAND flash memory the Boot image stored
// in the RAM file cache area.
//
// Parameters:
// dwStartAddr
// [in] Address in flash memory where the start of the downloaded
// Boot image is to be written.
//
// dwLength
// [in] Length of the Boot image, in bytes, to be written to flash
// memory.
//
// Returns:
// TRUE indicates success. FALSE indicates failure.
//
//-----------------------------------------------------------------------------
BOOL NANDWriteBoot(DWORD dwStartAddr, DWORD dwLength)
{
FlashInfo flashInfo;
LPBYTE pSectorBuf, pImage;
SectorInfo sectorInfo;
BLOCK_ID blockID, startBlockID, endBlockID;
SECTOR_ADDR sectorAddr, startSectorAddr, endSectorAddr;
// Check for NAND device availability
//
if (!g_bNandExist)
{
EdbgOutputDebugString("WARNING: NAND device doesn't exist - unable to store image.\r\n");
return(FALSE);
}
EdbgOutputDebugString("INFO: Writing Boot image to NAND (please wait)...\r\n");
if (!FMD_GetInfo(&flashInfo))
{
EdbgOutputDebugString("ERROR: Unable to get NAND flash information.\r\n");
return(FALSE);
}
// Make sure Boot length does not exceed reserved NAND size
if (dwLength > IMAGE_BOOT_BOOTIMAGE_NAND_SIZE)
{
EdbgOutputDebugString("ERROR: Boot size exceeds reserved NAND region (size = 0x%x)\r\n", dwLength);
return(FALSE);
}
// Calculate the physical block range for the EBOOT image
startBlockID = IMAGE_BOOT_BOOTIMAGE_NAND_OFFSET / flashInfo.dwBytesPerBlock;
endBlockID = startBlockID + (IMAGE_BOOT_BOOTIMAGE_NAND_SIZE / flashInfo.dwBytesPerBlock);
EdbgOutputDebugString("INFO: Erasing NAND flash blocks [0x%x - 0x%x].\r\n", startBlockID, endBlockID);
// Erase range of NAND blocks reserved for EBOOT
for (blockID = startBlockID; blockID < endBlockID; blockID++)
{
// Skip bad blocks
if (FMD_GetBlockStatus(blockID) == BLOCK_STATUS_BAD)
{
EdbgOutputDebugString("INFO: Found bad NAND flash block [0x%x].\r\n", blockID);
continue;
}
// Erase the block...
if (!FMD_EraseBlock(blockID))
{
EdbgOutputDebugString("ERROR: Unable to erase NAND flash block [0x%x].\r\n", blockID);
return(FALSE);
}
}
// Get cached image location
pImage = OEMMapMemAddr(dwStartAddr, dwStartAddr);
// Fill unused space with 0xFF
memset(pImage + dwLength, 0xFF, (IMAGE_BOOT_BOOTIMAGE_NAND_SIZE) - dwLength);
EdbgOutputDebugString("INFO: Programming EBOOT/SBOOT image from flash cache address 0x%x, size = %d\r\n", pImage, dwLength);
sectorInfo.dwReserved1 = 0xFFFFFFFF;
sectorInfo.bOEMReserved = 0x00;
sectorInfo.bBadBlock = 0xFF;
sectorInfo.wReserved2 = 0xFFFF;
// Write EBOOT to NAND flash
pSectorBuf = pImage;
for (blockID = startBlockID; blockID < endBlockID; blockID++)
{
// Skip bad blocks
if (FMD_GetBlockStatus(blockID) == BLOCK_STATUS_BAD)
{
EdbgOutputDebugString("INFO: Found bad NAND flash block [0x%x].\r\n", blockID);
continue;
}
// Compute sector address based on current physical block
startSectorAddr = blockID * flashInfo.wSectorsPerBlock;
endSectorAddr = startSectorAddr + flashInfo.wSectorsPerBlock;
for (sectorAddr = startSectorAddr; sectorAddr < endSectorAddr; sectorAddr++)
{
if (!FMD_WriteSector(sectorAddr, pSectorBuf, §orInfo, 1))
{
EdbgOutputDebugString("ERROR: Failed to update EBOOT/SBOOT.\r\n");
return(FALSE);
}
pSectorBuf += flashInfo.wDataBytesPerSector;
}
}
// Read EBOOT from NAND flash to verify contents
pSectorBuf = pImage + IMAGE_BOOT_BOOTIMAGE_NAND_SIZE;
for (blockID = startBlockID; blockID < endBlockID ; blockID++)
{
// Skip bad blocks
if (FMD_GetBlockStatus(blockID) == BLOCK_STATUS_BAD)
{
EdbgOutputDebugString("INFO: Found bad NAND flash block [0x%x].\r\n", blockID);
continue;
}
// Compute sector address based on current physical block
startSectorAddr = blockID * flashInfo.wSectorsPerBlock;
endSectorAddr = startSectorAddr + flashInfo.wSectorsPerBlock;
for (sectorAddr = startSectorAddr; sectorAddr < endSectorAddr; sectorAddr++)
{
if (!FMD_ReadSector(sectorAddr, pSectorBuf, §orInfo, 1))
{
EdbgOutputDebugString("ERROR: Failed to update EBOOT/SBOOT.\r\n");
return(FALSE);
}
pSectorBuf += flashInfo.wDataBytesPerSector;
}
}
EdbgOutputDebugString("INFO: Verifying image.\r\n");
if (memcmp(pImage, pImage + IMAGE_BOOT_BOOTIMAGE_NAND_SIZE, IMAGE_BOOT_BOOTIMAGE_NAND_SIZE) != 0)
{
EdbgOutputDebugString("ERROR: Failed to verify EBOOT/SBOOT.\r\n");
}
EdbgOutputDebugString("INFO: Update of EBOOT/SBOOT completed successfully.\r\n");
return(TRUE);
}
//------------------------------------------------------------------------------
//
// Function: NANDWriteIPL
//
// N/A
//
// Parameters:
// None.
//
// Returns:
// TRUE indicates success. FALSE indicates failure.
//
//-----------------------------------------------------------------------------
BOOL NANDWriteIPL(DWORD dwStartAddr, DWORD dwLength)
{
FlashInfo flashInfo;
LPBYTE pSectorBuf, pImage;
SectorInfo sectorInfo;
BLOCK_ID blockID, startBlockID, endBlockID;
SECTOR_ADDR sectorAddr, startSectorAddr, endSectorAddr;
// Check for NAND device availability
//
if (!g_bNandExist)
{
EdbgOutputDebugString("WARNING: NAND device doesn't exist - unable to store image.\r\n");
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -