📄 bootconfig.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(§or[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 + -