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

📄 nand.c

📁 Freescale ARM11系列CPU MX31的WINCE 5.0下的BSP
💻 C
📖 第 1 页 / 共 4 页
字号:
//-----------------------------------------------------------------------------
//
//  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-2006, 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 EBOOT NAND flash support functions.
//
//-----------------------------------------------------------------------------
#include <windows.h>
#include <blcommon.h>
#include "loader.h"
#include <fmd.h>
#include "bsp.h"

//-----------------------------------------------------------------------------
// External Functions


//-----------------------------------------------------------------------------
// External Variables
extern BOOL g_bNandExist;


//-----------------------------------------------------------------------------
// Defines
#define     NANDFC_BOOT_SIZE        (2*1024)


//-----------------------------------------------------------------------------
// Types


//-----------------------------------------------------------------------------
// Global Variables
BYTE sectorBuf[2048];
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, &sectorInfo, 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, &sectorInfo, 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:  NANDWriteEboot
//
//  This function writes to NAND flash memory the EBOOT image stored 
//  in the RAM file cache area.
//
//  Parameters:
//      dwStartAddr 
//          [in] Address in flash memory where the start of the downloaded 
//          EBOOT image is to be written.
//
//      dwLength 
//          [in] Length of the EBOOT image, in bytes, to be written to flash
//          memory.            
//
//  Returns:
//      TRUE indicates success. FALSE indicates failure.
//
//-----------------------------------------------------------------------------
BOOL NANDWriteEboot(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 EBOOT 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 EBOOT length does not exceed reserved NAND size
    if (dwLength > IMAGE_BOOT_EBOOTIMAGE_NAND_SIZE)
    {
        EdbgOutputDebugString("ERROR: EBOOT 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_EBOOTIMAGE_NAND_OFFSET / flashInfo.dwBytesPerBlock;
    endBlockID = startBlockID + (IMAGE_BOOT_EBOOTIMAGE_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_EBOOTIMAGE_NAND_SIZE) - dwLength);

    EdbgOutputDebugString("INFO: Programming EBOOT 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, &sectorInfo, 1))
            {
                EdbgOutputDebugString("ERROR: Failed to update EBOOT.\r\n");
                return(FALSE);
            }

            pSectorBuf += flashInfo.wDataBytesPerSector;
        }
    }
    
    // Read EBOOT from NAND flash to verify contents
    pSectorBuf = pImage + IMAGE_BOOT_EBOOTIMAGE_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, &sectorInfo, 1))
            {
                EdbgOutputDebugString("ERROR: Failed to update EBOOT.\r\n");
                return(FALSE);
            }

            pSectorBuf += flashInfo.wDataBytesPerSector;
        }
    }

    EdbgOutputDebugString("INFO: Verifying image.\r\n");

    if (memcmp(pImage, pImage + IMAGE_BOOT_EBOOTIMAGE_NAND_SIZE, IMAGE_BOOT_EBOOTIMAGE_NAND_SIZE) != 0)
    {
        EdbgOutputDebugString("ERROR: Failed to verify EBOOT.\r\n");
    }
    

    EdbgOutputDebugString("INFO: Update of EBOOT 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)
    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -