📄 nor.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// 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-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: nor.c
//
// Provides the implementation of the NOR flash library interface layer.
//
// IMPORTANT!
// ==========
//
// 1. The flash library is not meant to be run XIP in flash. If not already
// residing out of flash, the library user should allocate some buffer
// (use NORGetRelocateCodeSize() to get max required buffer size) and pass
// address of this buffer in NORLibInit() to relocate the flash functions.
// This may not be needed for flash parts that support simultaneous
// read/write/erase.
//
// 2. WinCE linker orders functions randomly, the following line must
// be added in the sources file of the exe or dll using the libraty to force
// function ordering for relocation. Eg. see eboot/sources
//
// LDEFINES=$(LDEFINES) /ORDER:@$(_TARGETPLATROOT)\SRC\DRIVERS\BLOCK\NORFMD\NORFLASHLIB\linkorder.txt
//
// 3. If relocation is required, no msg printout is allowed. ie DEBUG MODE
// MUST BE OFF! To debug the flash libraries, run it in RAM.
//
// 4. The flash library can make use of OS wait services in order to reduce
// use of polling if USE_OS_SERVICES is defined. However, in this case
// RELOCATION CANNOT be USED since the flash programming codes will no longer
// be self contained!
//
//-----------------------------------------------------------------------------
#include <windows.h>
#include "nor.h"
#include "amd.h"
#include "strata.h"
//------------------------------------------------------------------------------
// External Variables
//------------------------------------------------------------------------------
// Defines
#define MAX_SUPPORTED_FLASH_DRIVERS \
(sizeof(g_LowLevelDrivers) / sizeof(NOR_FLASH_DRIVER))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
// Global Variables
//------------------------------------------------------------------------------
// Local Variables
// Table of supported lower level flash drivers.
static const NOR_FLASH_DRIVER g_LowLevelDrivers[] = {
{
AMDx16_RelocateBegin,
AMDx16_IsFlashSupported,
AMDx16_Program,
AMDx16_EraseSector,
AMDx16_EraseChip,
AMDx16_RelocateEnd,
AMDx16_LockSector,
AMDx16_UnlockSector,
AMDx16_IsSectorLocked,
L"AMD/Spansion x16 Flash Driver",
},
{
StrataX16_RelocateBegin,
StrataX16_IsFlashSupported,
StrataX16_Program,
StrataX16_EraseSector,
NULL,
StrataX16_RelocateEnd,
StrataX16_LockSector,
StrataX16_UnlockSector,
NULL,
L"Intel Strata x16 Flash Driver",
},
// Add more low level flash drivers here
};
static NOR_FLASH_DRIVER g_FlashDriver;
static DWORD g_dwFlashDriverID = -1;
static NOR_FLASH_DESC g_FlashDesc;
static BOOL g_bShowProgress = FALSE;
static ULONG g_ulBytePerStep = 0;
//------------------------------------------------------------------------------
// Local Functions
static void PrintCFIData(NOR_FLASH_DESC *pFlashDesc);
static void PrintFlashID(NOR_FLASH_DESC *pFlashDesc);
static BOOL NORFindSector(ULONG *pulFlashAddr, ULONG *pulSectorSize);
//-----------------------------------------------------------------------------
// EXPORTED FUNCTIONS
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
// Function: NORLibInit
//
// Function NOR library initialization.
//
// Parameters:
// ulFlashBase
// [in] flash base address
//
// ulRelocateBase
// [in] address of buffer to relocate codes. codes will be relocated
// if this parameter is non zero.
// NOTE: This must be an address to uncached memory!
//
// ulRelocSize
// [in] size of buffer to relocate codes.
//
// Returns:
// FALSE on failure
//
//-----------------------------------------------------------------------------
BOOL NORLibInit(ULONG ulFlashBase, ULONG ulRelocateBase, ULONG ulRelocSize)
{
ULONG i;
ULONG ulRelocLen;
BOOL bSuccess;
BOOL (*pIsFlashSupported)(NOR_FLASH_DESC *pFlashDesc);
DEBUGMSG(ZONE_FUNCTION, (TEXT("NORLibInit+0x%x 0x%x\r\n"), ulFlashBase, ulRelocateBase));
if (ulRelocateBase != 0 && ulRelocSize < NORGetRelocateCodeSize()) {
ERRORMSG(ZONE_ERROR, (TEXT("ERROR: Insufficient relocation size! Expected 0x%x\r\n"),
NORGetRelocateCodeSize()));
return FALSE;
} else {
DEBUGMSG(ZONE_FUNCTION, (TEXT("Init relocate base 0x%x 0x%x\r\n"), ulRelocateBase, ulRelocSize));
memset((void *)ulRelocateBase, 0, ulRelocSize);
DEBUGMSG(ZONE_FUNCTION, (TEXT("done relocate base 0x%x 0x%x\r\n"), ulRelocateBase, ulRelocSize));
}
memset(&g_FlashDesc, 0, sizeof(NOR_FLASH_DESC));
g_dwFlashDriverID = -1;
for (i = 0; i < MAX_SUPPORTED_FLASH_DRIVERS; i++) {
pIsFlashSupported = g_LowLevelDrivers[i].IsFlashSupported;
if (ulRelocateBase != 0) {
// Relocate flash detection codes cos flash will not be accessible then.
ulRelocLen = (ULONG)g_LowLevelDrivers[i].RelocateEnd - (ULONG)g_LowLevelDrivers[i].RelocateBegin;
DEBUGMSG(ZONE_FUNCTION, (TEXT("INFO: Relocate 0x%x to 0x%x.\r\n"),
*(ULONG *)&g_LowLevelDrivers[i].RelocateBegin, ulRelocateBase));
DEBUGMSG(ZONE_FUNCTION, (TEXT("%s detection code size 0x%x\r\n"),
g_LowLevelDrivers[i].lpszName, ulRelocLen));
memcpy((BYTE *)ulRelocateBase, (BYTE *)g_LowLevelDrivers[i].RelocateBegin, ulRelocLen);
*(ULONG *)&pIsFlashSupported = ((ULONG)g_LowLevelDrivers[i].IsFlashSupported -
(ULONG)g_LowLevelDrivers[i].RelocateBegin + (ULONG)ulRelocateBase);
DEBUGMSG(ZONE_FUNCTION, (TEXT("pIsFlashSupported 0x%x\r\n"), pIsFlashSupported));
}
g_FlashDesc.FlashBase = ulFlashBase;
bSuccess = pIsFlashSupported(&g_FlashDesc);
DEBUGMSG(ZONE_FUNCTION, (TEXT("pIsFlashSupported %c\r\n"), bSuccess? 'T':'F'));
if (bSuccess == TRUE) {
memcpy(&g_FlashDriver, &g_LowLevelDrivers[i], sizeof(NOR_FLASH_DRIVER));
g_dwFlashDriverID = i;
break;
}
}
if (g_dwFlashDriverID == -1 || g_dwFlashDriverID >= MAX_SUPPORTED_FLASH_DRIVERS ||
g_FlashDriver.Program == NULL || g_FlashDriver.EraseSector == NULL) {
ERRORMSG(ZONE_ERROR, (TEXT("ERROR: No supported NOR flash found!\r\n")));
return FALSE;
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("ll driver index: %d\r\n"), i));
if (ulRelocateBase != 0 && bSuccess == TRUE) {
ulRelocLen = (ULONG)g_LowLevelDrivers[i].RelocateEnd - (ULONG)g_LowLevelDrivers[i].RelocateBegin;
memcpy((BYTE *)ulRelocateBase, (BYTE *)g_LowLevelDrivers[i].RelocateBegin, ulRelocLen);
DEBUGMSG(ZONE_FUNCTION, (TEXT("INFO: Relocate 0x%x to 0x%x.\r\n"), *(ULONG *)&g_LowLevelDrivers[i].RelocateBegin, ulRelocateBase));
DEBUGMSG(ZONE_FUNCTION, (TEXT("%s relocate code size 0x%x\r\n"), g_LowLevelDrivers[i].lpszName, ulRelocLen));
// Overwrite function pointer to point to relocated codes
*(ULONG *)&g_FlashDriver.IsFlashSupported = (ulRelocateBase + (ULONG)g_FlashDriver.IsFlashSupported - (ULONG)g_FlashDriver.RelocateBegin);
*(ULONG *)&g_FlashDriver.Program = (ulRelocateBase + (ULONG)g_FlashDriver.Program - (ULONG)g_FlashDriver.RelocateBegin);
*(ULONG *)&g_FlashDriver.EraseSector = (ulRelocateBase + (ULONG)g_FlashDriver.EraseSector - (ULONG)g_FlashDriver.RelocateBegin);
if (g_FlashDriver.EraseChip != NULL)
*(ULONG *)&g_FlashDriver.EraseChip = (ulRelocateBase + (ULONG)g_FlashDriver.EraseChip - (ULONG)g_FlashDriver.RelocateBegin);
DEBUGMSG(ZONE_FUNCTION, (TEXT("Relocated IsFlashSupported: 0x%x\r\n"), (ULONG)g_FlashDriver.IsFlashSupported));
DEBUGMSG(ZONE_FUNCTION, (TEXT("Relocated Program: 0x%x\r\n"), (ULONG)g_FlashDriver.Program));
DEBUGMSG(ZONE_FUNCTION, (TEXT("Relocated EraseSector: 0x%x\r\n"), (ULONG)g_FlashDriver.EraseSector));
DEBUGMSG(ZONE_FUNCTION, (TEXT("Relocated EraseChip: 0x%x\r\n"), (ULONG)g_FlashDriver.EraseChip));
}
PrintCFIData(&g_FlashDesc);
PrintFlashID(&g_FlashDesc);
DEBUGMSG(ZONE_FUNCTION, (TEXT("NORLibInit-\r\n")));
return bSuccess;
}
//-----------------------------------------------------------------------------
//
// Function: NORProgram
//
// Program the flash starting from the given address.
//
// Parameters:
// ulStartAddress
// [in] address to start writing from
//
// pData
// [in] ptr to data buffer to write
//
// ulSize
// [in] size of data to program
//
// bIgnore0to1
// [in] ignores programming 0 to 1 errors if TRUE
//
// Returns:
// FALSE on failure
//
//-----------------------------------------------------------------------------
BOOL NORProgram(ULONG ulStartAddress, UCHAR *pData, ULONG ulSize, BOOL bIgnore0to1)
{
BOOL bSuccess;
BOOL bIsPaired;
DWORD dwBusWidth;
ULONG ulprogSize;
DEBUGMSG(ZONE_FUNCTION, (TEXT("NORProgram+ 0x%x 0x%x 0x%x\r\n"),
ulStartAddress, pData, ulSize));
bIsPaired = g_FlashDesc.PairedFlash;
dwBusWidth = bIsPaired? g_FlashDesc.DeviceWidth >> 2 : g_FlashDesc.DeviceWidth >> 3;
// Check address is bus width aligned
if ((ulStartAddress % dwBusWidth) != 0) {
DEBUGMSG(ZONE_ERROR, (TEXT("ERROR: Unaligned start address for program: 0x%x buswith: %d\r\n"),
ulStartAddress, dwBusWidth));
return FALSE;
}
// Check data size aligned wrt buswidth
if ((ulSize % dwBusWidth) != 0) {
DEBUGMSG(ZONE_ERROR, (TEXT("ERROR: Unaligned data size for program: 0x%x buswith: %d\r\n"),
ulSize, dwBusWidth));
return FALSE;
}
if (g_bShowProgress) {
while (ulSize) {
ulprogSize = MIN(ulSize, g_ulBytePerStep);
DEBUGMSG(ZONE_FUNCTION, (TEXT("ulprogSize 0x%x ulSize 0x%x\r\n"), ulprogSize, ulSize));
bSuccess = g_FlashDriver.Program(&g_FlashDesc, ulStartAddress, pData, ulprogSize, bIgnore0to1);
if (bSuccess) {
PROGRESSMSG(g_bShowProgress, (TEXT("P")));
ulSize -= ulprogSize;
ulStartAddress += ulprogSize;
pData += ulprogSize;
}
else
break;
}
}
else
bSuccess = g_FlashDriver.Program(&g_FlashDesc, ulStartAddress, pData, ulSize, bIgnore0to1);
PROGRESSMSG(g_bShowProgress, (TEXT("\r\n")));
DEBUGMSG(ZONE_FUNCTION, (TEXT("NORProgram- %c \r\n"), bSuccess? 'T' : 'F'));
return bSuccess;
}
//-----------------------------------------------------------------------------
//
// Function: NORErase
//
// Erases the flash starting from the given address.
//
// Note:
// All sectors overlapping the desired region is erased.
//
// Parameters:
// ulStartAddress
// [in] address to start erase
//
// ulLen
// [in] size of region to erase
//
// Returns:
// actual erase size on success or 0 on failure
//
//-----------------------------------------------------------------------------
ULONG NORErase(ULONG ulStartAddress, ULONG ulLen)
{
ULONG ulFlashBase;
BOOL bIsPaired;
ULONG i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -