📄 perreg.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.
//
//------------------------------------------------------------------------------
//
// File: PerReg.c
//
// This file implements persistent registry module for NOR flash memory.
//
#include <windows.h>
#include <oal_log.h>
#include <oal_memory.h>
#include <oal_flash.h>
#include <oal_perreg.h>
//------------------------------------------------------------------------------
//
// External: pWriteRegistryToOEM/pReadRegistryFromOEM
//
// This function pointers are expored by kernel as support for optional
// persistent registry functionality.
//
extern BOOL (*pWriteRegistryToOEM)(UINT32 flags, UINT8 *pData, UINT32 size);
extern UINT32 (*pReadRegistryFromOEM)(UINT32 flags, UINT8 *pData, UINT32 size);
//------------------------------------------------------------------------------
//
// Define: OAL_PERREG_MAX_REGIONS
//
// This constant defines maximal supported number of regions. It is solved
// in this way to avoid memory allocation which isn't supported at time
// when OALPerRegInit is usally called.
//
#define OAL_PERREG_MAX_REGIONS 8
//------------------------------------------------------------------------------
//
// Define: OAL_PERREG_SIGN
//
// This constant is used as persistent registry signature in registry storage
// header.
//
#define OAL_PERREG_SIGN 'PREG'
//------------------------------------------------------------------------------
//
// Type: OAL_PERREG_HEADER
//
// This type defines registry storage header. Its size must be 32-bit word
// allignment and it must be smaller than buffer size in OAL_PERREG_STATE
// structure.
//
typedef struct {
UINT32 signature;
UINT32 size;
UINT32 checkSum;
} OAL_PERREG_HEADER;
//------------------------------------------------------------------------------
//
// Type: OAL_PERREG_STATE
//
// The type encapsulating implementation internal status variables.
//
typedef struct {
UINT32 regions;
OAL_PERREG_REGION region[OAL_PERREG_MAX_REGIONS];
UINT32 size;
UINT32 checkSum;
UINT32 regionIdx;
UINT32 regionPos;
UINT8 buffer[1024];
UINT32 bufferPos;
} OAL_PERREG_STATE;
//------------------------------------------------------------------------------
//
// Static: g_perRegState
//
// Persistent registry implementation internal state.
//
static OAL_PERREG_STATE g_perRegState;
//------------------------------------------------------------------------------
// Local Functions
static UINT32 CheckSum(VOID *pStart, UINT32 size);
static BOOL WriteBufferToFlash(BOOL skipHeader);
static BOOL ReadBufferFromFlash();
static BOOL EraseFlash();
static VOID ResetBuffer(BOOL write);
static BOOL CopyFromBuffer(VOID *pBuffer, UINT32 count);
static BOOL CopyToBuffer(VOID *pBuffer, UINT32 count);
static BOOL FlushBuffer(BOOL skipHeader);
//------------------------------------------------------------------------------
//
// Function: OALPerRegInit
//
// This function should be called from OAL to initalize persistent registry
// functionality. When clean flag is set it also erase all regions. Function
// make all regions flash memory block alignment.
//
BOOL OALPerRegInit(BOOL clean, OAL_PERREG_REGION aRegions[])
{
UINT32 rc = FALSE;
OAL_PERREG_REGION *pRegion;
UINT32 i = 0;
UINT32 offset; //, blockStart, blockSize;
OALMSG(OAL_FLASH&&OAL_FUNC, (L"+OALPerRegInit(0x%08x)\r\n", aRegions));
// Copy regions info to state variable
g_perRegState.regions = 0;
pRegion = &g_perRegState.region[0];
while (aRegions[i].base != 0) {
#if 0
// Verify, that there is flash memory
if (!OALFlashBlockInfo(
aRegions[i].pBase, aRegions[i].pStart, &blockStart, &blockSize
)) {
OALMSG(OAL_ERROR, (
L"ERROR: There isn't flash memory at 0x%08x\r\n",
aRegions[i].pBase
));
i++;
continue;
}
// Get region offset in block
offset = OALVAtoPA(aRegions[i].pStart) - blockStart;
if (offset >= pRegion->size) {
OALMSG(OAL_WARN, (
L"WARN: Region %08x - %08x - %08x too small, ignored\r\n",
aRegions[i].pBase, aRegions[i].pStart, aRegions[i].size
));
i++;
continue;
}
#else
offset = 0;
#endif
// Save region to state variable
pRegion->base = aRegions[i].base;
pRegion->start = aRegions[i].start + offset;
pRegion->size = aRegions[i].size - offset;
pRegion++;
if (++g_perRegState.regions >= OAL_PERREG_MAX_REGIONS) break;
i++;
}
// We was succesfull when at least one region was verified
if (rc = (g_perRegState.regions > 0)) {
pWriteRegistryToOEM = OALPerRegWrite;
if (!clean) pReadRegistryFromOEM = OALPerRegRead;
}
OALMSG(OAL_FLASH&&OAL_FUNC, (L"-OALPerRegInit(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: OALPerRegWrite
//
// This function implements pWriteRegistryToOEM write function.
//
BOOL OALPerRegWrite(UINT32 flags, UINT8 *pData, UINT32 size)
{
BOOL rc = FALSE;
OAL_PERREG_HEADER header;
OALMSG(OAL_FLASH&&OAL_FUNC, (
L"+OALPerRegWrite(0x%08x, 0x%08x, 0x%08x)\r\n", flags, pData, size
));
// Check if it is write start
if ((flags & REG_WRITE_BYTES_START) != 0) {
// First check if there are regions defined
if (g_perRegState.regions <= 0) {
OALMSG(OAL_ERROR, (
L"ERROR: OALPerRegWrite: No valid flash regions defined\r\n"
));
goto cleanUp;
}
RETAILMSG(TRUE, (L"INFO: OALPerRegWrite: Registry write start\r\n"));
// Erase flash memory
if (!EraseFlash()) goto cleanUp;
// Initialize local state variables
g_perRegState.size = 0;
g_perRegState.checkSum = 0;
memset(&header, 0xFF, sizeof(header));
// Reset buffer & write temporary header
ResetBuffer(TRUE);
CopyToBuffer(&header, sizeof(header));
}
// While there are some data && place where to write
if (size > 0) {
if (!CopyToBuffer(pData, size)) {
OALMSG(OAL_ERROR, (
L"ERROR: OALPerRegWrite: CopyToBuffer failed\r\n"
));
goto cleanUp;
}
g_perRegState.size += size;
} else {
// Flush buffer
FlushBuffer(TRUE);
// Prepare and write header
header.signature = OAL_PERREG_SIGN;
header.size = g_perRegState.size;
header.checkSum = g_perRegState.checkSum;
ResetBuffer(TRUE);
CopyToBuffer(&header, sizeof(header));
FlushBuffer(FALSE);
RETAILMSG(TRUE, (L"INFO: OALPerRegWrite: Registry write done\r\n"));
}
rc = TRUE;
cleanUp:
OALMSG(OAL_FLASH&&OAL_FUNC, (L"-OALPerRegWrite(rc = %d)", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: OALPerRegRead
//
// This function implements pReadRegistryFromOEM read function.
//
UINT32 OALPerRegRead(UINT32 flags, UINT8 *pData, UINT32 dataSize)
{
UINT32 rc = 0;
OAL_PERREG_HEADER header;
UINT32 count, checkSum, chunk, buffer[32];
UINT8 *pBase = pData;
OALMSG(OAL_FLASH&&OAL_FUNC, (
L"+OALPerRegRead(0x%08x, 0x%08x, 0x%08x)\r\n", flags, pData, dataSize
));
if (flags & REG_READ_BYTES_START) {
if (g_perRegState.regions <= 0) {
OALMSG(OAL_ERROR, (
L"ERROR: OALPerRegRead: No valid flash regions defined\r\n"
));
rc = -1;
goto cleanUp;
}
RETAILMSG(TRUE, (L"INFO: OALPerRegRead: Registry read start\r\n"));
// Reset buffer and read header
ResetBuffer(FALSE);
CopyFromBuffer(&header, sizeof(header));
if (header.signature != OAL_PERREG_SIGN) {
OALMSG(OAL_WARN, (L"WARN: ReadRegistryFromOEM: Bad signature\r\n"));
rc = -1;
goto cleanUp;
}
// Calculate checksum
count = (header.size + 3) & ~0x3;
checkSum = 0;
while (count > 0) {
chunk = sizeof(buffer) < count ? sizeof(buffer) : count;
CopyFromBuffer(buffer, chunk);
checkSum += CheckSum(buffer, chunk);
count -= chunk;
}
if (header.checkSum != checkSum) {
OALMSG(OAL_WARN, (
L"WARN: ReadRegistryFromOEM: Invalid checksum\r\n"
));
rc = -1;
goto cleanUp;
}
// Reset buffer and read header
ResetBuffer(FALSE);
CopyFromBuffer(&header, sizeof(header));
g_perRegState.size = header.size;
}
if (g_perRegState.size >= dataSize) {
CopyFromBuffer(pData, dataSize);
g_perRegState.size -= dataSize;
rc = dataSize;
}
RETAILMSG(rc == 0, (
L"INFO: OALPerRegRead: Registry read done (%d)\r\n", g_perRegState.size
));
cleanUp:
OALMSG(OAL_FLASH&&OAL_FUNC, (L"-OALPerRegRead(rc = %d)", rc));
return rc;
}
//------------------------------------------------------------------------------
static UINT32 CheckSum(VOID *pStart, UINT32 size)
{
UINT32 sum = 0;
UINT32 *p;
for (p = pStart; size > sizeof(UINT32) - 1; size -= sizeof(UINT32)) {
sum += *p++;
}
return sum;
}
//------------------------------------------------------------------------------
static BOOL EraseFlash()
{
BOOL rc = FALSE;
OAL_PERREG_REGION *pRegion;
UINT32 i;
// Erase all regions...
RETAILMSG(TRUE, (L"INFO: OALPerRegWrite: Registry store erase start\r\n"));
pRegion = g_perRegState.region;
for (i = 0; i < g_perRegState.regions; i++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -