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

📄 nand.c

📁 freescale i.mx31 BSP CE5.0全部源码
💻 C
📖 第 1 页 / 共 5 页
字号:
//-----------------------------------------------------------------------------
//
//  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, Motorola Inc. All Rights Reserved
//
//-----------------------------------------------------------------------------
//
//  Copyright (C) 2004, Freescale Semiconductor, Inc. All Rights Reserved
//  THIS SOURCE CODE IS CONFIDENTIAL AND PROPRIETARY AND MAY NOT
//  BE USED OR DISTRIBUTED WITHOUT THE WRITTEN PERMISSION OF
//  FREESCALE SEMICONDUCTOR, INC.
//
//-----------------------------------------------------------------------------
//
//  File:  nand.c
//
//  EBOOT Nand flash routines
//
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// INCLUDE FILES
//-----------------------------------------------------------------------------
#include <windows.h>
#include <blcommon.h>
#include <bootpart.h>
#include <fmd.h>

#include "bsp.h"

#include "loader.h"
#include "nand.h"
#include "nandfmd.h"
//-----------------------------------------------------------------------------
// GLOBAL DEFINITIONS
//-----------------------------------------------------------------------------
#if DEBUG
#define LE32(x32)    \
    (((x32 & 0x000000FF) << 24) |     \
    ((x32 & 0x0000FF00) << 8) |     \
    ((x32 & 0x00FF0000) >> 8) |     \
    ((x32 & 0xFF000000) >> 24))

#endif

// Only enable this for testing
#define IGNORE_OEM_RESERVED_BAD_BLOCKS 0
//-----------------------------------------------------------------------------
// GLOBAL OR STATIC VARIABLES
//-----------------------------------------------------------------------------
static BOOL g_fNandExists;
static BOOL g_fBlock0Erased;
static FlashInfo g_FlashInfo;
static DWORD g_FlashWidth;

//-----------------------------------------------------------------------------
// STATIC FUNCTION PROTOTYPES
//-----------------------------------------------------------------------------
static PVOID GetKernelExtPointer(DWORD dwRegionStart, DWORD dwRegionLength);
static PVOID GetNandLoaderFilePointer(DWORD dwRegionStart, DWORD dwRegionLength);
static DWORD FindFirstGoodBlock(DWORD dwStartBlock);
static BOOL WriteOSRegionsToNand(BOOT_CFG *pBootCfg);
static BOOL WriteEBootRegionToNand(BOOT_CFG *pBootCfg);
static BOOL WriteNandLoaderRegionToNand(BOOT_CFG *pBootCfg);

#ifdef DEBUG
static DWORD GetBlockNumberInput(void);
static void DisplayMem(UINT32 start, UINT32 size, UINT32 displaySize);
#endif
//-----------------------------------------------------------------------------
// EXPORTED FUNCTIONS
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
//  FUNCTION:        InitPartitionMgr
//
//  DESCRIPTION:    Initialises the Boot partition manager for
//                    Nand flash interface.
//
//  PARAMETERS:        None
//
//  RETURNS:        TRUE for success. FALSE for failure.
//
//-----------------------------------------------------------------------------
BOOL InitPartitionMgr(void)
{
    DWORD dwBlock;
    DWORD dwReservedBlocks;
    DWORD dwBlockStatus;

    OALMSG(OAL_FUNC, (TEXT("InitPartitionMgr+\r\n")));
    g_fNandExists = FALSE;
    g_fBlock0Erased = FALSE;

    // Initialize the FMD flash interface and get flash information.
    if(!BP_Init((LPBYTE)EBOOT_NANDCACHE_START, EBOOT_NANDCACHE_SIZE, NULL, NULL, NULL))
    {
        OALMSG(OAL_ERROR, (TEXT("ERROR: BP_Init failed. Check if NAND is present.\r\n")));
        return FALSE;
    }

    // Get NAND flash info
    if(!FMD_GetInfo(&g_FlashInfo))
    {
        EdbgOutputDebugString("ERROR: Unable to get flash info.\r\n");
        return FALSE;
    }

    g_FlashWidth = NAND_BUS_WIDTH;
    
    OALMSG(OAL_FUNC, (TEXT("flash type: %s\r\n"), g_FlashInfo.flashType == NAND? L"NAND":L"NOR"));
    OALMSG(OAL_FUNC, (TEXT("dwNumBlocks: %d\r\n"), g_FlashInfo.dwNumBlocks));
    OALMSG(OAL_FUNC, (TEXT("wSectorsPerBlock: %d\r\n"), g_FlashInfo.wSectorsPerBlock));
    OALMSG(OAL_FUNC, (TEXT("wDataBytesPerSector: %d\r\n"), g_FlashInfo.wDataBytesPerSector));
    OALMSG(OAL_FUNC, (TEXT("dwBytesPerBlock: 0x%x\r\n"), g_FlashInfo.dwBytesPerBlock));
    OALMSG(OAL_FUNC, (TEXT("width: %d\r\n"), g_FlashWidth));


    // Sanity check    for first good block after block 0.
    OALMSG(OAL_FUNC, (TEXT("start block: %d\r\n"), FindFirstGoodBlock(1)));

    // Check that NANDLoader and EBOOT blocks are marked as readonly and
    // oem reserved.
    for(dwBlock = 0, dwReservedBlocks = 0;
        dwReservedBlocks < NAND_IMAGE_NUM_BLOCK(NAND_EBOOT_IMAGE_SIZE, g_FlashInfo.dwBytesPerBlock) + 1;
        dwBlock++)
    {
        dwBlockStatus = FMD_GetBlockStatus(dwBlock);
        if((dwBlockStatus & BLOCK_STATUS_UNKNOWN))
        {
            OALMSG(OAL_ERROR, (TEXT("ERROR: Checking OEM reserved block %d status failed.\r\n"), dwBlock));
            return FALSE;
        }
        if(dwBlockStatus & BLOCK_STATUS_BAD)
        {
            OALMSG(OAL_INFO, (TEXT("OEM reserved block %d status Bad.\r\n"), dwBlock));
            continue;
        }
        // Set blocks as OEM_RESERVED and READONLY
        if((dwBlockStatus & (BLOCK_STATUS_READONLY | BLOCK_STATUS_RESERVED)) !=
            (BLOCK_STATUS_READONLY | BLOCK_STATUS_RESERVED))
        {
            OALMSG(OAL_INFO, (TEXT("INFO: Setting block %d status as OEM reserved/read only.\r\n"), dwBlock));
            if(FMD_SetBlockStatus(dwBlock, (BLOCK_STATUS_READONLY | BLOCK_STATUS_RESERVED)) != TRUE)
            {
                OALMSG(OAL_ERROR, (TEXT("ERROR: Setting OEM reserved block %d status failed.\r\n"), dwBlock));
                return FALSE;
            }
            else
                dwReservedBlocks++;
        }
        else
            dwReservedBlocks++;
    }
    OALMSG(OAL_FUNC, (TEXT("last oem block: %d\r\n"), dwBlock - 1));

    g_fNandExists = TRUE;
    OALMSG(OAL_FUNC, (TEXT("InitPartitionMgr-: Nand %c\r\n"),
        g_fNandExists? 'T':'F'));
    return TRUE;
}

//-----------------------------------------------------------------------------
//
//  FUNCTION:        DeinitPartitionMgr
//
//  DESCRIPTION:    Deinitializes Nand flash interface.
//
//  PARAMETERS:        None
//
//  RETURNS:        None
//
//-----------------------------------------------------------------------------
void DeinitPartitionMgr(void)
{
    // Deinitialize the NFC hardware
    FMD_Deinit("FMOK");
}

//-----------------------------------------------------------------------------
//
//  FUNCTION:        WriteRegionsToNand
//
//  DESCRIPTION:    Writes bin regions to NAND.
//
//  PARAMETERS:
//                    pBootCfg - Ptr to EBOOT configuration structure
//
//  RETURNS:        TRUE for success. FALSE for failure.
//
//-----------------------------------------------------------------------------
BOOL WriteRegionsToNand(BOOT_CFG *pBootCfg)
{
    extern MultiBINInfo g_BINRegionInfo;
    DWORD dwImageStart = 0;
    BOOL result;
    DWORD dwCurMSec;
    CHAR selection;

    OALMSG(OAL_INFO, (TEXT("WriteRegionsToNand+\r\n")));
    if(!pBootCfg)
    {
        OALMSG(OAL_ERROR, (TEXT("WriteRegionsToNand: Invalid input Parameter!\r\n")));
        return FALSE;
    }

    if(g_fNandExists != TRUE)
    {
        EdbgOutputDebugString("WARNING: NAND device doesn't exist - unable to write image.\r\n");
        return FALSE;
    }

    /*
    * I don't like this at all. It'll be nicer to be able to identify 
    * bins via the .exe names in pTOC. Unfortunately WinCE tools are all 
    * keyed off to work with the magic "nk.exe". Too bad, 
    * we sort by launch/download address (offset from start of flash 
    * cache area.)
    *
    * Note: These addresses will change if the respective .bib files 
    * RAMIMAGE and ROMOFFSET entries change.
    * 
    * This is how it goes:
    * 0x00000000            - NK ram OS image
    * 0x00040000/0x00044000    - EBoot ram OS image
    */    
    dwImageStart = pBootCfg->LaunchAddress - 0x1000;
    if(dwImageStart == EBOOT_RAM_IMAGE_START)
    {
        BOOL err = FALSE;

        OALMSG(OAL_INFO, (TEXT("WriteRegionsToNand: writing EBoot region!\r\n")));

        EdbgOutputDebugString("Press 'N' within 3 seconds to update NANDLoader image.\r\n");
        dwCurMSec = OEMEthGetSecs();
        while(OEMEthGetSecs() < (dwCurMSec + 3))
        {
            selection = OEMReadDebugByte();
            if((selection == 'n' || selection == 'N'))
            {
                OALMSG(OAL_INFO, (TEXT("WriteRegionsToNand: writing NandLoader!\r\n")));
                 result = WriteNandLoaderRegionToNand(pBootCfg);
                if(result == FALSE)
                {
                    EdbgOutputDebugString("ERROR: Write NandLoader failed.\r\n");
                    err = TRUE;
                }
                break;
            }
        }
        EdbgOutputDebugString("Press 'E' within 3 seconds to update NAND EBOOT image.\r\n");
        dwCurMSec = OEMEthGetSecs();
        while(OEMEthGetSecs() < (dwCurMSec + 3))
        {
            selection = OEMReadDebugByte();
            if((selection == 'e' || selection == 'E'))
            {
                OALMSG(OAL_INFO, (TEXT("WriteRegionsToNand: writing EBOOT!\r\n")));
                result = WriteEBootRegionToNand(pBootCfg);
                if(result == FALSE)
                {
                    EdbgOutputDebugString("ERROR: Write EBOOT failed.\r\n");
                    err = TRUE;
                }
                break;
            }
        }

        if(err == TRUE)
            result = FALSE;
    }
    else if(dwImageStart == OS_RAM_IMAGE_START)
    {
        OALMSG(OAL_INFO, (TEXT("WriteRegionsToNand: writing OS region!\r\n")));
        result = WriteOSRegionsToNand(pBootCfg);
    }
    else
    {
        OALMSG(OAL_INFO, (TEXT("WriteRegionsToNand: dwImageStart: %X\r\n"), dwImageStart));
        OALMSG(OAL_INFO, (TEXT("WriteRegionsToNand: OS_RAM_IMAGE_START: %X\r\n"), OS_RAM_IMAGE_START));
        OALMSG(OAL_INFO, (TEXT("WriteRegionsToNand: EBOOT_RAM_IMAGE_START: %X\r\n"), EBOOT_RAM_IMAGE_START));
        result = FALSE;
    }
    return result;
}

//-----------------------------------------------------------------------------
//
//  FUNCTION:        ReadKernelRegionFromNand
//
//  DESCRIPTION:    Reads kernel region from NAND to RAM.
//
//  PARAMETERS:        
//                    pBootCfg - Ptr to EBOOT configuration structure
//                    
//  RETURNS:        TRUE for success. FALSE for failure.
//
//-----------------------------------------------------------------------------
BOOL ReadKernelRegionFromNand(BOOT_CFG *pBootCfg)
{
    HANDLE hPart;
    EBOOT_NANDCFG nandParams;

    OALMSG(OAL_INFO, (TEXT("ReadKernelRegionFromNand+\r\n")));

    if(!pBootCfg)
    {
        OALMSG(1, (TEXT("ReadRegionsFromNand: Invalid input Parameter!\r\n")));

⌨️ 快捷键说明

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