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

📄 bootconfig.c

📁 freescale i.mx31 BSP CE5.0全部源码
💻 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, 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:  bootconfig.c
//
//  BOOT configuration access routines.
//
//-----------------------------------------------------------------------------

#ifndef PLAT_PMC

#include <windows.h>

#include "bsp.h"

#if (BOOTCFG_STORAGE == BOOTCFG_STORAGE_NAND)
#include <fmd.h>
#include "nandfmd.h"
#endif
//------------------------------------------------------------------------------
// External Variables

//------------------------------------------------------------------------------
// Defines

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

//------------------------------------------------------------------------------
// Global Variables

//------------------------------------------------------------------------------
// Local Variables
#if (BOOTCFG_STORAGE == BOOTCFG_STORAGE_NAND)
static DWORD g_dwBootConfigBlock = -1;
#endif
//------------------------------------------------------------------------------
// Local Functions
static DWORD inet_addr( char *pszDottedD );

//------------------------------------------------------------------------------
//
//  Function:        OALReadBootCFG
//
//  This function is used to load the stored bootloader configuration from
//    permanent storage. It also checks if the configuration values are valid,
//    if not, resets to default values.
//
//  Parameters:
//            pBootCFG
//                [out] ptr to boot configuration data store
//
//  Returns:
//            TRUE if boot configuration read successfully. FALSE otherwise.
//
//------------------------------------------------------------------------------
#if (BOOTCFG_STORAGE == BOOTCFG_STORAGE_NAND)
BOOL OALReadBootCFG(BOOT_CFG *pBootCFG)
{
    FlashInfo flashInfo;
    BYTE sector[512];   // hardcode cos EBOOT no malloc service
    DWORD dwCount, dwStartSectorAddr, i, j, k;
    PVOID handle = NULL;
    BOOL success = TRUE;
    DWORD dwStatus;

    OALMSG(OAL_FUNC, (TEXT("INFO: Reading boot configuration from NAND.\r\n")));

    handle = FMD_Init(NULL, NULL, NULL);
    if(handle == NULL)
    {
        OALMSG(OAL_ERROR, (TEXT("ERROR: OALReadBootCFG: FMD_Init failed.\r\n")));
        success = FALSE;
        goto _done;
    }    
    if(!FMD_GetInfo(&flashInfo))
    {
        OALMSG(OAL_ERROR, (TEXT("ERROR: Unable to get NAND flash info.\r\n")));
        success = FALSE;
        goto _done;
    }
    dwCount = NAND_IMAGE_NUM_SECTOR(sizeof(BOOT_CFG), flashInfo.wDataBytesPerSector);
    if(dwCount > flashInfo.dwNumBlocks)
    {
        OALMSG(OAL_ERROR, (TEXT("ERROR: Boot config size exceeded max.\r\n")));
        success = FALSE;
        goto _done;
    } 
    // Read NAND block to get boot configuration.
    // Boot configuration is stored in sector 0 of last good block.
    if(g_dwBootConfigBlock == -1)
    {
        for(i = flashInfo.dwNumBlocks - 1; i >= 0; i--)
        {
            DWORD dwStatus;
            dwStatus = FMD_GetBlockStatus(i);
            if((dwStatus & BLOCK_STATUS_BAD) == 0)
            {
                g_dwBootConfigBlock = i;
                OALMSG(OAL_FUNC, (TEXT("INFO: last good block found: %d status 0x%x\r\n"), 
                    g_dwBootConfigBlock, dwStatus));
                break;
            }
        }
        if(g_dwBootConfigBlock == -1 || g_dwBootConfigBlock == 0)
        {
            OALMSG(OAL_ERROR, (TEXT("ERROR: Invalid boot configuration storage block %d!\r\n"),
                g_dwBootConfigBlock));
            success = FALSE;
            goto _done;
        }
    }
    dwStatus = FMD_GetBlockStatus(g_dwBootConfigBlock);
    OALMSG(OAL_FUNC, (TEXT("INFO: block %d status 0x%08x\r\n"), g_dwBootConfigBlock, dwStatus));
    if( (dwStatus ^ (BLOCK_STATUS_RESERVED | BLOCK_STATUS_READONLY)) != 0)
    {
        if(!FMD_SetBlockStatus(g_dwBootConfigBlock, (BLOCK_STATUS_RESERVED | BLOCK_STATUS_READONLY)) )
        {
            OALMSG(OAL_ERROR, (TEXT("ERROR: cannot reserve block %d for boot config!\r\n"),
                    g_dwBootConfigBlock));
            success = FALSE;
            goto _done;
        }
        else
            OALMSG(OAL_INFO, (TEXT("INFO: block %d is reserved for boot configuration\r\n"),
                    g_dwBootConfigBlock));
    }
    OALMSG(OAL_FUNC, (TEXT("INFO: Boot configuration block: %d\r\n"), g_dwBootConfigBlock));
    OALMSG(OAL_FUNC, (TEXT("INFO: Boot configuration sectors: %d\r\n"), dwCount));
    dwStartSectorAddr = g_dwBootConfigBlock * flashInfo.wSectorsPerBlock;
    for(i = 0, j = 0; i < dwCount; i++, j += flashInfo.wDataBytesPerSector)
    {
        if(FMD_ReadSector((SECTOR_ADDR)dwStartSectorAddr, sector, NULL, 1))
        {
            k = ((sizeof(BOOT_CFG) - j) < flashInfo.wDataBytesPerSector)? (sizeof(BOOT_CFG) - j) : flashInfo.wDataBytesPerSector;
            memcpy(&pBootCFG[j], sector, k);
            dwStartSectorAddr++;
        }
        else
        {
            OALMSG(OAL_ERROR, (TEXT("ERROR: Unable to read boot configuration from sector %d.\r\n"), i));
            success = FALSE;
            goto _done;
        }
    }

_done:
    // Make sure that signature is valid. Otherwise reset to default factory settings
    if (pBootCFG->Signature != CONFIG_SIGNATURE ||
        pBootCFG->VerMajor != CONFIG_VERSION_MAJOR ||
        pBootCFG->VerMinor != CONFIG_VERSION_MINOR)
    {
        OALResetBootCFG(pBootCFG);
        // Store default BOOT configuration
        OALWriteBootCFG(pBootCFG);
    }

    if(handle)
        FMD_Deinit(handle);
    return success;
}

#elif (BOOTCFG_STORAGE == BOOTCFG_STORAGE_EEPROM)
BOOL OALReadBootCFG(BOOT_CFG *pBootCFG)
{
    OALMSG(OAL_FUNC, (TEXT("OALReadBootCFG+\r\n")));

    // Init EEPROM to get boot configuration
    if(BSPEEPROMInit((PBYTE)BSP_BASE_REG_PA_CS8900A_IOBASE) == TRUE)
        BSPEEPROMReadUserData(0, (UINT16 *)pBootCFG, sizeof(BOOT_CFG) / 2);
    else
        OALMSG(OAL_ERROR, (TEXT("INFO: OALReadBootCFG: BSPEEPROMInit failed.\r\n")));

    OALMSG(OAL_INFO, (TEXT("OALReadBootCFG:  pBootCFG->Signature = 0x%x\r\n"), pBootCFG->Signature));
    OALMSG(OAL_INFO, (TEXT("OALReadBootCFG:  pBootCFG->VerMajor = 0x%x\r\n"), pBootCFG->VerMajor));
    OALMSG(OAL_INFO, (TEXT("OALReadBootCFG:  pBootCFG->VerMinor = 0x%x\r\n"), pBootCFG->VerMinor));
    
    // Make sure that signature is valid. Otherwise reset to default factory settings
    if (pBootCFG->Signature != CONFIG_SIGNATURE ||
        pBootCFG->VerMajor != CONFIG_VERSION_MAJOR ||
        pBootCFG->VerMinor != CONFIG_VERSION_MINOR)
    {
        OALResetBootCFG(pBootCFG);
        // Store default BOOT configuration
        OALWriteBootCFG(pBootCFG);
        return FALSE;
    }

    OALMSG(OAL_FUNC, (TEXT("OALReadBootCFG-\r\n")));

    return TRUE;
}

#else
BOOL OALReadBootCFG(BOOT_CFG *pBootCFG)
{
    // Make sure that signature is valid. Otherwise reset to default factory settings
    if (pBootCFG->Signature != CONFIG_SIGNATURE ||
        pBootCFG->VerMajor != CONFIG_VERSION_MAJOR ||
        pBootCFG->VerMinor != CONFIG_VERSION_MINOR)
    {
        OALResetBootCFG(pBootCFG);
        // Store default BOOT configuration
        OALWriteBootCFG(pBootCFG);
        return FALSE;
    }
    return TRUE;
}
#endif

//------------------------------------------------------------------------------
//
//  Function:        OALWriteBootCFG
//
//  This function is used to store bootloader configuration into permanent
//    storage.
//
//  Parameters:
//            pBootCFG
//                [in] ptr to boot configuration data to be written
//
//  Returns:
//             TRUE if write succeeds
//------------------------------------------------------------------------------
#if (BOOTCFG_STORAGE == BOOTCFG_STORAGE_NAND)
BOOL OALWriteBootCFG(BOOT_CFG *pBootCFG)
{
    FlashInfo flashInfo;
    BYTE sector[512];   // hardcode cos EBOOT no malloc service
    DWORD dwCount, dwStartSectorAddr, i, j, k;
    PVOID handle;
    BOOL success = TRUE;

    OALMSG(OAL_FUNC, (TEXT("INFO: Writing boot configuration to NAND.\r\n")));

    handle = FMD_Init(NULL, NULL, NULL);
    if(!handle)
    {
        OALMSG(OAL_ERROR, (TEXT("ERROR: OALReadBootCFG: FMD_Init failed.\r\n")));
        return FALSE;
    }    
    if(!FMD_GetInfo(&flashInfo))
    {
        OALMSG(OAL_ERROR, (TEXT("ERROR: Unable to get NAND flash info.\r\n")));
        success = FALSE;
        goto _done;
    }
    dwCount = NAND_IMAGE_NUM_SECTOR(sizeof(BOOT_CFG), flashInfo.wDataBytesPerSector);
    if(dwCount > flashInfo.dwNumBlocks)
    {
        OALMSG(OAL_ERROR, (TEXT("ERROR: Boot config size exceeded max.\r\n")));
        success = FALSE;
        goto _done;
    } 
    // Boot configuration is stored in sector 0 onwards of last good block.
    if(g_dwBootConfigBlock == -1)
    {
        for(i = flashInfo.dwNumBlocks - 1; i >= 0; i--)
        {
            if((FMD_GetBlockStatus(i) & BLOCK_STATUS_BAD) == 0)
            {
                g_dwBootConfigBlock = i;
                OALMSG(OAL_FUNC, (TEXT("INFO: last good block found: %d\r\n"), g_dwBootConfigBlock));
                break;
            }
        }
    }
    OALMSG(OAL_FUNC, (TEXT("INFO: Boot configuration block: %d\r\n"), g_dwBootConfigBlock));
    OALMSG(OAL_FUNC, (TEXT("INFO: Boot configuration sectors: %d\r\n"), dwCount));
    if(!FMD_EraseBlock(g_dwBootConfigBlock))
    {    
           OALMSG(OAL_ERROR, (TEXT("ERROR: Unable to erase NAND block %d.\r\n"), g_dwBootConfigBlock));
        success = FALSE;
        goto _done;
    }
    // Make block readonly & reserved.
    if(!FMD_SetBlockStatus(g_dwBootConfigBlock, (BLOCK_STATUS_RESERVED | BLOCK_STATUS_READONLY)) )
    {
        OALMSG(OAL_ERROR, (TEXT("ERROR: cannot reserve block %d for boot config!\r\n"),
                g_dwBootConfigBlock));
        success = FALSE;
        goto _done;
    }
    else
        OALMSG(OAL_FUNC, (TEXT("INFO: block %d is reserved for boot configuration\r\n"),
                g_dwBootConfigBlock));

    dwStartSectorAddr = g_dwBootConfigBlock  * flashInfo.wSectorsPerBlock;
    for(i = 0, j = 0; i < dwCount; i++, j += flashInfo.wDataBytesPerSector)
    {
        k = ((sizeof(BOOT_CFG) - j) < flashInfo.wDataBytesPerSector)? (sizeof(BOOT_CFG) - j) : flashInfo.wDataBytesPerSector;
        memcpy(sector, &pBootCFG[j], k);
        memset(&sector[k], 0xFF, flashInfo.wDataBytesPerSector - k);
        if(!FMD_WriteSector((SECTOR_ADDR)dwStartSectorAddr, sector, NULL, 1))
        {
            OALMSG(OAL_ERROR, (TEXT("ERROR: Unable to write configuration to sector %d.\r\n"),
                    dwStartSectorAddr));
            success = FALSE;
            goto _done;
        }
        else
            dwStartSectorAddr++;
    }
_done:
    FMD_Deinit(handle);
    return success;
}

#elif (BOOTCFG_STORAGE == BOOTCFG_STORAGE_EEPROM)
BOOL OALWriteBootCFG(BOOT_CFG *pBootCFG)
{
    if(!BSPEEPROMWriteUserData(0, (UINT16 *)pBootCFG, sizeof(BOOT_CFG) / 2))
    {
        OALMSG(OAL_ERROR, (TEXT("ERROR: OALWriteBootCFG: failed to write configuration.\r\n")));
        return FALSE;
    }
    return TRUE;
}

#else
BOOL OALWriteBootCFG(BOOT_CFG *pBootCFG)
{
    return FALSE;
}
#endif

//------------------------------------------------------------------------------
//
//  Function:        OALResetBootCFG
//
//  This function is used to reset the bootloader configuration structure
//    to default values.
//
//  Parameters:
//            pBootCFG
//                [in/out] ptr to boot configuration data
//
//  Returns:
//
//------------------------------------------------------------------------------
void OALResetBootCFG(BOOT_CFG *pBootCFG)
{
    OALMSG(OAL_INFO, (TEXT("\r\nResetting factory default configuration ... \r\n")));

    pBootCFG->Signature        = CONFIG_SIGNATURE;
    pBootCFG->VerMajor         = CONFIG_VERSION_MAJOR;
    pBootCFG->VerMinor         = CONFIG_VERSION_MINOR;
    pBootCFG->ConfigFlags      = CONFIG_FLAGS_DHCP;
    pBootCFG->IPAddr           = inet_addr(CONFIG_DEFAULT_IPADDR);
    pBootCFG->SubnetMask       = inet_addr(CONFIG_DEFAULT_SUBNET_MASK);
    pBootCFG->BootDevice       = CONFIG_AUTOBOOT_DEVICE_NOR;
    pBootCFG->KitlTransport    = 0;
    pBootCFG->CS8900MAC[0] = (BSP_ARGS_DEFAULT_MAC_BYTE1 << 8) | BSP_ARGS_DEFAULT_MAC_BYTE0;
    pBootCFG->CS8900MAC[1] = (BSP_ARGS_DEFAULT_MAC_BYTE3 << 8) | BSP_ARGS_DEFAULT_MAC_BYTE2;
    pBootCFG->CS8900MAC[2] = (BSP_ARGS_DEFAULT_MAC_BYTE5 << 8) | BSP_ARGS_DEFAULT_MAC_BYTE4;
    pBootCFG->LaunchAddress = IMAGE_WINCE_CODE_RAM_CA_START;

}

// This routine will take a dotted decimal IP address as represent here and return a binary version of it
static DWORD inet_addr( char *pszDottedD )
{

    DWORD dwIP = 0;
    DWORD cBytes;
    char *pszLastNum;
    int atoi (const char *s);

    // Replace the dots with NULL terminators
    pszLastNum = pszDottedD;
    for( cBytes = 0; cBytes < 4; cBytes++ ) {
        while(*pszDottedD != '.' && *pszDottedD != '\0')
            pszDottedD++;
        if (pszDottedD == '\0' && cBytes != 3)
            return 0;
        *pszDottedD = '\0';
        dwIP |= (atoi(pszLastNum) & 0xFF) << (8*cBytes);
        pszLastNum = ++pszDottedD;
    }

    return dwIP;

} // inet_addr()

#endif // PLAT_PMC

⌨️ 快捷键说明

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