📄 fmd.cpp
字号:
//-----------------------------------------------------------------------------
//
// 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
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
// File: fmd.cpp
//
// Provides the implementation of the NOR block driver FMD layer.
//
// IMPORTANT!:
// The Microsoft block driver is not designed for NOR driver XIP. Thus, this
// driver can be used XIP in flash ONLY WHEN the NOR flash part used supports
// SIMULTANEOUS READ/WRITE/ERASE. Since most flash parts support this only
// when operating on different banks. Care must be taken in choosing the FMD
// storage area to ensure that it occupies a DIFFERENT BANK from the OS image.
//
//-----------------------------------------------------------------------------
#include <windows.h>
#include <ddkreg.h>
#include <psapi.h>
#include <fmd.h>
#include "debug.h"
#include "nor.h"
//------------------------------------------------------------------------------
// External Variables
//------------------------------------------------------------------------------
// Defines
#define MAX(a, b) ( ((a) > (b))? (a) : (b) )
#define MIN(a, b) ( ((a) < (b))? (a) : (b) )
#define SECTOR_SIZE 512 // Number of data bytes in a sector
#ifndef KERNEL_MODE
#define READ_FROM_REGISTRY 1
#endif
#define INITIAL_MMAP_SIZE 0x02000000
//------------------------------------------------------------------------------
// Types
typedef struct _NOR_FMD_FLASH_INFO {
ULONG BaseAddress; // Base address of flash part
ULONG FlashLength; // Flash size
ULONG FMDBaseOffset; // Offset of FMD region from flash base
ULONG FMDLength; // size of FMD region
ULONG SectorInfoOffset; // Offset of sector meta info from block start
WORD BytesPerSector; // Logical sector size
WORD SectorsPerBlock; // Num of logical sector+meta info per block
DWORD NumBlocks; // Number of blocks used by FMD driver
ULONG EraseBlockSize; // Physical erase block size
BOOL bIsPairedFlash;
ULONG ulDeviceWidth;
} NOR_FMD_FLASH_INFO, *PNOR_FMD_FLASH_INFO;
//------------------------------------------------------------------------------
// Global Variables
//------------------------------------------------------------------------------
// Local Variables
static NOR_FMD_FLASH_INFO g_FMDInfo;
static BOOL g_bXIPMode = FALSE;
static ULONG *g_pNORFlashBase = NULL;
static BYTE *g_pAlignBuf = NULL;
//------------------------------------------------------------------------------
// Local Functions
static BOOL DefineLayout(BOOL bIsPairedFlash, CFI_FLASH_GEOMETRY_INFO *pGeomtry, NOR_FMD_FLASH_INFO *pInfo);
static void GetPhysicalSectorAddress(DWORD dwSector, PSECTOR_ADDR pStartSectorAddr, PSECTOR_ADDR pStartSectorInfoAddr);
static void GetMappedSectorAddress(DWORD dwSector, PSECTOR_ADDR pStartSectorAddr, PSECTOR_ADDR pStartSectorInfoAddr);
static BOOL SetBlockLock(BLOCK_ID blockID, ULONG NumBlocks, BOOL bLock);
//-----------------------------------------------------------------------------
// EXPORTED FUNCTIONS
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
// Function: FMD_Init
//
// Function Initializes the flash memory of a device.
//
// Parameters:
// lpActiveReg
// [in] Ptr to the active registry string to find device info from
// registry. Set to NULL if not needed.
//
// pRegIn
// [in] Ptr to a PCI_REG_INFO structure. Used to find flash on PCI
// hardware. Set to NULL if not needed.
//
// pRegOut
// [in/out] Ptr to a PCI_REG_INFO structure. Used to return flash
// information. Set to NULL if not needed.
//
// Returns:
// 0 on failure
//
//-----------------------------------------------------------------------------
PVOID FMD_Init(LPCTSTR lpActiveReg, PPCI_REG_INFO pRegIn, PPCI_REG_INFO pRegOut)
{
ULONG BaseAddress;
ULONG FlashLength;
ULONG FMDLength;
CFI_FLASH_GEOMETRY_INFO Geometry;
BOOL bLastMode;
#ifdef DEBUG
extern DBGPARAM dpCurSettings;
dpCurSettings.ulZoneMask |= (ZONEMASK_INFO | ZONEMASK_ERROR);
#endif
DEBUGMSG(ZONE_FUNCTION, (TEXT("FMD_Init+\r\n")));
bLastMode = SetKMode(TRUE);
#if READ_FROM_REGISTRY
if(lpActiveReg != NULL)
{
DDKWINDOWINFO dwi;
HKEY hConfig;
// Get flash information from the registry.
hConfig = OpenDeviceKey((LPCTSTR)lpActiveReg);
if(hConfig == NULL)
{
ERRORMSG(ZONE_ERROR, (TEXT("ERROR: FMD_Init: OpenDeviceKey failed.\r\n")));
goto _errExit;
}
dwi.cbSize = sizeof(dwi);
if(DDKReg_GetWindowInfo(hConfig, &dwi) != ERROR_SUCCESS)
{
ERRORMSG(ZONE_ERROR, (TEXT("ERROR: FMD_Init: DDKReg_GetWindowInfo() failed.\r\n")));
goto _errExit;
}
if(dwi.dwNumIoWindows == 1)
{
// The IO window contains the flash physical base address and
// size of FMD storage area.
// NOTE: FMD storage area is defined to be at the end of flash.
// ie. FMD area start = flash end - FMD length
BaseAddress = (ULONG)(dwi.ioWindows[0].dwBase);
FMDLength = (ULONG)(dwi.ioWindows[0].dwLen);
}
else
{
ERRORMSG(ZONE_ERROR, (TEXT("ERROR: FMD_Init: Invalid memory windows information.\r\n")));
goto _errExit;
}
}
#else
// Get flash base address and length from caller.
if(!pRegIn || !pRegIn->IoBase.Num || !pRegIn->IoLen.Num)
{
ERRORMSG(ZONE_ERROR, (TEXT("ERROR: FMD_Init: invalid flash memory base and/or length specified by caller.\r\n")));
goto _errExit;
}
else
{
// The IO window contains the flash physical base address and
// size of FMD storage area.
// NOTE: FMD storage area is defined to be at the end of flash.
// ie. FMD area start = flash end - FMD length
BaseAddress = (ULONG)pRegIn->IoBase.Reg[0];
FMDLength = (ULONG)pRegIn->IoLen.Reg[0];
}
#endif // READ_FROM_REGISTRY.
// Sanity check
if(BaseAddress == 0 || FMDLength == 0)
{
ERRORMSG(ZONE_ERROR, (TEXT("ERROR: FMD_Init: invalid flash values: base 0x%08X FMD length 0x%08X\r\n"),
BaseAddress, FMDLength));
goto _errExit;
}
else
{
g_FMDInfo.BaseAddress = BaseAddress;
g_FMDInfo.FMDLength = FMDLength;
}
DEBUGMSG(ZONE_INFO, (TEXT("INFO: Flash base: 0x%08X FMD length: 0x%08X\r\n"), BaseAddress, FMDLength));
#ifndef KERNEL_MODE
// Memmap flash for access
PHYSICAL_ADDRESS phyAddr;
phyAddr.QuadPart = BaseAddress;
// TODO: Investigate why unable to map 64Mb.
// Possible: Because of current RAM == 64Mb only or some other reason.
g_pNORFlashBase = (ULONG *)MmMapIoSpace(phyAddr, INITIAL_MMAP_SIZE, FALSE);
if(!g_pNORFlashBase)
{
ERRORMSG(ZONE_ERROR, (TEXT("FMD_Init: MmMapIoSpace NOR mem failed %d\r\n"), GetLastError()));
goto _errExit;
}
#else
g_pNORFlashBase = (ULONG *)OALPAtoUA(BaseAddress);
#endif
DEBUGMSG(ZONE_INFO, (TEXT("INFO: Mapped Flash Base 0x%08X\r\n"), g_pNORFlashBase));
// Initialize flash
DEBUGMSG(ZONE_FUNCTION, (TEXT("Initializing NOR flash library (base 0x%08X)"), g_pNORFlashBase));
if(!NORLibInit((ULONG)g_pNORFlashBase, 0, 0))
{
ERRORMSG(ZONE_ERROR, (TEXT("\r\nERROR: Failed NOR flash driver init!\r\n")));
goto _errExit;
}
else
DEBUGMSG(ZONE_FUNCTION, (TEXT("Success.\r\n")));
// Get flash geometry info.
if(!NORGetGeometry(&Geometry))
{
ERRORMSG(ZONE_ERROR, (TEXT("FMD_Init: Unable to get NOR geometry information!\r\n")));
goto _errExit;
}
// Get Flash device and bus width information
if(!NORGetDeviceWidth(&g_FMDInfo.bIsPairedFlash, &g_FMDInfo.ulDeviceWidth))
{
ERRORMSG(ZONE_ERROR, (TEXT("FMD_Init: Unable to get NOR device and bus width information!S\r\n")));
goto _errExit;
}
FlashLength = g_FMDInfo.bIsPairedFlash? 2 * (1 << Geometry.DevSize) : (1 << Geometry.DevSize);
DEBUGMSG(ZONE_INFO, (TEXT("Detected flash length 0x%08X FMD size 0x%08X!\r\n"), FlashLength, FMDLength));
// Sanity check
if(FlashLength == 0 || FlashLength < FMDLength)
{
ERRORMSG(ZONE_ERROR, (TEXT("FMD_Init: invalid flash length and/or FMD base offset!\r\n")));
ERRORMSG(ZONE_ERROR, (TEXT("Flash base: 0x%08X Flash length: 0x%08X\r\n"), BaseAddress, FlashLength));
goto _errExit;
}
else
{
g_FMDInfo.FlashLength = FlashLength;
g_FMDInfo.FMDBaseOffset = FlashLength - FMDLength;
DEBUGMSG(ZONE_INFO, (TEXT("INFO: Flash length: 0x%08X FMDBaseOffset 0x%08X\r\n"),
FlashLength, g_FMDInfo.FMDBaseOffset));
}
#ifndef KERNEL_MODE
if(FlashLength != INITIAL_MMAP_SIZE)
{
MmUnmapIoSpace(g_pNORFlashBase, 0);
// TODO: Check why MmMapIoSpace fails for 64MB size.
// Remap whole flash for access
phyAddr.QuadPart = BaseAddress;
g_pNORFlashBase = (ULONG *)MmMapIoSpace(phyAddr, FlashLength, FALSE);
if(!g_pNORFlashBase)
{
ERRORMSG(ZONE_ERROR, (TEXT("FMD_Init: 2nd MmMapIoSpace NOR mem failed %d\r\n"), GetLastError()));
goto _errExit;
}
// Need to reinit the NOR lib again
// Initialize flash
DEBUGMSG(ZONE_FUNCTION, (TEXT("2nd initialize NOR flash library (base 0x%08X)"), g_pNORFlashBase));
if(!NORLibInit((ULONG)g_pNORFlashBase, 0, 0))
{
ERRORMSG(ZONE_ERROR, (TEXT("\r\nERROR: Failed NOR flash driver init!\r\n")));
goto _errExit;
}
else
DEBUGMSG(ZONE_FUNCTION, (TEXT("Success.\r\n")));
}
#endif
// Define logical flash layout
if(!DefineLayout(g_FMDInfo.bIsPairedFlash, &Geometry, &g_FMDInfo))
{
ERRORMSG(ZONE_ERROR, (TEXT("ERROR: FMD_Init: Defining logical flash layout failed!\r\n")));
goto _errExit;
}
// Allocate alignment buffer
g_pAlignBuf = (BYTE *)LocalAlloc(LMEM_FIXED, g_FMDInfo.BytesPerSector);
if(!g_pAlignBuf)
{
ERRORMSG(ZONE_ERROR, (TEXT("FMD_Init failed alignment buffer allocation\r\n")));
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("FMD_Init- 0x%08X\r\n"), g_pNORFlashBase));
SetKMode(bLastMode);
return g_pNORFlashBase;
_errExit:
if(g_pNORFlashBase)
MmUnmapIoSpace(g_pNORFlashBase, 0);
if(g_pAlignBuf)
LocalFree(g_pAlignBuf);
SetKMode(bLastMode);
return NULL;
}
//-----------------------------------------------------------------------------
//
// Function: FMD_Deinit
//
// Function De-initializes the flash driver.
//
// Parameters:
// hFMD
// [in] handle returned by FMD_Init.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -