parent
665323e5af
commit
91d4df401a
183
Config.cpp
183
Config.cpp
|
@ -1,30 +1,37 @@
|
|||
#include "Config.h"
|
||||
#include "Flash.h"
|
||||
#include "Security\Crc.h"
|
||||
|
||||
Storage* ConfigBlock::Device = NULL;
|
||||
uint ConfigBlock::BaseAddress = NULL;
|
||||
Config* Config::Current = NULL;
|
||||
|
||||
bool ConfigBlock::IsGoodBlock() const
|
||||
// 配置块。名称、长度、头部校验,数据部分不做校验,方便外部修改
|
||||
class ConfigBlock
|
||||
{
|
||||
if(Signature != c_Version || HeaderCRC == 0) return false;
|
||||
public:
|
||||
ushort HeaderCRC;
|
||||
ushort Size;
|
||||
char Name[4];
|
||||
|
||||
bool Valid() const;
|
||||
|
||||
const ConfigBlock* Next() const;
|
||||
const void* Data() const;
|
||||
|
||||
bool Init(const char* name, const ByteArray& bs);
|
||||
bool Write(Storage* storage, uint addr, const ByteArray& bs);
|
||||
};
|
||||
|
||||
bool ConfigBlock::Valid() const
|
||||
{
|
||||
// 计算头部 CRC。从数据CRC开始,包括大小和名称
|
||||
ushort crc = Crc::Hash16(&DataCRC, sizeof(*this) - offsetof(ConfigBlock, DataCRC));
|
||||
ushort crc = Crc::Hash16(&Size, sizeof(*this) - offsetof(ConfigBlock, Size));
|
||||
|
||||
return crc == HeaderCRC;
|
||||
}
|
||||
|
||||
bool ConfigBlock::IsGoodData() const
|
||||
{
|
||||
// 计算数据块CRC
|
||||
ushort crc = Crc::Hash16(Data(), Size);
|
||||
|
||||
return crc == DataCRC;
|
||||
}
|
||||
|
||||
const ConfigBlock* ConfigBlock::Next() const
|
||||
{
|
||||
if(!IsGoodBlock()) return NULL;
|
||||
if(!Valid()) return NULL;
|
||||
|
||||
// 确保数据部分2字节对齐,便于Flash操作
|
||||
uint s = (Size + 1) & ~1;
|
||||
|
@ -38,8 +45,6 @@ const void* ConfigBlock::Data() const
|
|||
return (const void*)&this[1];
|
||||
}
|
||||
|
||||
//--//
|
||||
|
||||
// 构造一个新的配置块
|
||||
bool ConfigBlock::Init(const char* name, const ByteArray& bs)
|
||||
{
|
||||
|
@ -47,59 +52,18 @@ bool ConfigBlock::Init(const char* name, const ByteArray& bs)
|
|||
uint slen = strlen(name);
|
||||
if(slen > sizeof(Name)) return false;
|
||||
|
||||
//memset(this, 0, sizeof(*this));
|
||||
Size = bs.Length();
|
||||
|
||||
// 数据长度为0,表明是置为无效
|
||||
if(bs.Length() > 0)
|
||||
DataCRC = Crc::Hash16(bs.GetBuffer(), bs.Length());
|
||||
else
|
||||
DataCRC = 0;
|
||||
|
||||
/*// 只有首次允许设置名字和大小,避免后面随意扩张引起越界覆盖
|
||||
if(IsGoodBlock())
|
||||
{
|
||||
if(bs.Length() > Size) return false;
|
||||
}
|
||||
else*/
|
||||
{
|
||||
Signature = c_Version;
|
||||
Size = bs.Length();
|
||||
|
||||
if(slen > ArrayLength(Name)) slen = ArrayLength(Name);
|
||||
memset(Name, 0, ArrayLength(Name));
|
||||
memcpy(Name, name, slen);
|
||||
}
|
||||
if(slen > ArrayLength(Name)) slen = ArrayLength(Name);
|
||||
memset(Name, 0, ArrayLength(Name));
|
||||
memcpy(Name, name, slen);
|
||||
|
||||
// 计算头部CRC。包括数据CRC、大小、名称
|
||||
HeaderCRC = Crc::Hash16(&DataCRC, sizeof(*this) - offsetof(ConfigBlock, DataCRC));
|
||||
HeaderCRC = Crc::Hash16(&Size, sizeof(*this) - offsetof(ConfigBlock, Size));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--//
|
||||
|
||||
// 循环查找配置块
|
||||
const ConfigBlock* ConfigBlock::Find(const char* name, uint addr, bool fAppend)
|
||||
{
|
||||
const ConfigBlock* cfg = (const ConfigBlock*)addr;
|
||||
uint slen = strlen(name);
|
||||
assert_param2(slen <= sizeof(cfg->Name), "配置段名称最大4个字符");
|
||||
|
||||
// 遍历链表,找到同名块
|
||||
while(cfg->IsGoodBlock())
|
||||
{
|
||||
if(cfg->IsGoodData() && name && memcmp(name, cfg->Name, slen) == 0)
|
||||
{
|
||||
return cfg;
|
||||
}
|
||||
|
||||
cfg = cfg->Next();
|
||||
}
|
||||
|
||||
// 如果需要添加,返回最后一个非法块的地址
|
||||
return fAppend ? cfg : NULL;
|
||||
}
|
||||
|
||||
// 更新块
|
||||
bool ConfigBlock::Write(Storage* storage, uint addr, const ByteArray& bs)
|
||||
{
|
||||
|
@ -108,41 +72,71 @@ bool ConfigBlock::Write(Storage* storage, uint addr, const ByteArray& bs)
|
|||
bool rs = true;
|
||||
|
||||
// 先写入头部,然后写入数据
|
||||
uint len = sizeof(ConfigBlock) - offsetof(ConfigBlock, Signature);
|
||||
rs &= storage->Write(addr, ByteArray((byte*)&Signature, len));
|
||||
uint len = sizeof(ConfigBlock) - offsetof(ConfigBlock, HeaderCRC);
|
||||
if(!storage->Write(addr, ByteArray(&HeaderCRC, len))) return false;
|
||||
if(bs.Length() > 0)
|
||||
{
|
||||
uint offset = len;
|
||||
len = bs.Length();
|
||||
if(len > Size) len = Size;
|
||||
rs &= storage->Write(addr + offset, ByteArray(bs.GetBuffer(), len));
|
||||
uint len2 = bs.Length();
|
||||
if(len2 > Size) len2 = Size;
|
||||
if(!storage->Write(addr + len, ByteArray(bs.GetBuffer(), len2))) return false;
|
||||
}
|
||||
|
||||
return rs;
|
||||
}
|
||||
|
||||
// 废弃
|
||||
bool ConfigBlock::Invalid(const char* name, uint addr, Storage* storage)
|
||||
//--//
|
||||
|
||||
// 循环查找配置块
|
||||
const void* Config::Find(const char* name, bool fAppend)
|
||||
{
|
||||
return Set(name, ByteArray(0), addr, storage);
|
||||
assert_param2(name, "配置段名称不能为空");
|
||||
|
||||
uint addr = Address;
|
||||
// 检查签名,如果不存在则写入
|
||||
if(*(uint*)addr != c_Version)
|
||||
{
|
||||
if(!fAppend) return NULL;
|
||||
|
||||
Device->Write(addr, ByteArray(&c_Version, sizeof(c_Version)));
|
||||
}
|
||||
|
||||
addr += sizeof(c_Version);
|
||||
const ConfigBlock* cfg = (const ConfigBlock*)addr;
|
||||
uint slen = strlen(name);
|
||||
assert_param2(slen <= sizeof(cfg->Name), "配置段名称最大4个字符");
|
||||
|
||||
// 遍历链表,找到同名块
|
||||
while(cfg->Valid())
|
||||
{
|
||||
if(cfg->Name[0] && memcmp(name, cfg->Name, slen) == 0) return cfg;
|
||||
|
||||
cfg = cfg->Next();
|
||||
}
|
||||
|
||||
// 如果需要添加,返回最后一个非法块的地址
|
||||
return fAppend ? cfg : NULL;
|
||||
}
|
||||
|
||||
// 废弃
|
||||
bool Config::Invalid(const char* name)
|
||||
{
|
||||
return Set(name, ByteArray(0));
|
||||
}
|
||||
|
||||
// 根据名称更新块
|
||||
const void* ConfigBlock::Set(const char* name, const ByteArray& bs, uint addr, Storage* storage)
|
||||
const void* Config::Set(const char* name, const ByteArray& bs)
|
||||
{
|
||||
if(name == NULL) return NULL;
|
||||
|
||||
if(!addr) addr = BaseAddress;
|
||||
if(!storage) storage = Device;
|
||||
assert_param2(storage, "未指定配置段的存储设备");
|
||||
assert_param2(Device, "未指定配置段的存储设备");
|
||||
|
||||
const ConfigBlock* cfg = Find(name, addr, true);
|
||||
const ConfigBlock* cfg = (const ConfigBlock*)Find(name, true);
|
||||
if(cfg)
|
||||
{
|
||||
// 重新搞一个配置头,使用新的数据去重新初始化
|
||||
ConfigBlock header;
|
||||
header.Init(name, bs);
|
||||
header.Write(storage, (uint)cfg, bs);
|
||||
header.Write(Device, (uint)cfg, bs);
|
||||
|
||||
return cfg->Data();
|
||||
}
|
||||
|
@ -151,37 +145,44 @@ const void* ConfigBlock::Set(const char* name, const ByteArray& bs, uint addr, S
|
|||
}
|
||||
|
||||
// 获取配置数据
|
||||
bool ConfigBlock::Get(const char* name, ByteArray& bs, uint addr)
|
||||
bool Config::Get(const char* name, ByteArray& bs)
|
||||
{
|
||||
if(name == NULL) return false;
|
||||
|
||||
if(!addr) addr = BaseAddress;
|
||||
const ConfigBlock* cfg = Find(name, addr, false);
|
||||
if(cfg)
|
||||
{
|
||||
if(cfg->Size <= bs.Capacity())
|
||||
{
|
||||
bs.Copy(cfg->Data(), 0, cfg->Size);
|
||||
bs.SetLength(cfg->Size);
|
||||
const ConfigBlock* cfg = (const ConfigBlock*)Find(name, false);
|
||||
if(cfg && cfg->Size <= bs.Capacity())
|
||||
{
|
||||
bs.Copy(cfg->Data(), 0, cfg->Size);
|
||||
bs.SetLength(cfg->Size);
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const void* ConfigBlock::Get(const char* name, uint addr)
|
||||
const void* Config::Get(const char* name)
|
||||
{
|
||||
if(name == NULL) return NULL;
|
||||
|
||||
if(!addr) addr = BaseAddress;
|
||||
const ConfigBlock* cfg = Find(name, addr, false);
|
||||
const ConfigBlock* cfg = (const ConfigBlock*)Find(name, false);
|
||||
if(cfg) return cfg->Data();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Flash最后一块作为配置区
|
||||
Config* Config::CreateFlash()
|
||||
{
|
||||
// 最后一块作为配置区
|
||||
static Flash flash;
|
||||
static Config cfg;
|
||||
cfg.Device = &flash;
|
||||
cfg.Address = flash.Start + flash.Size - flash.Block;
|
||||
|
||||
return &cfg;
|
||||
}
|
||||
|
||||
// 初始化
|
||||
TConfig::TConfig()
|
||||
{
|
||||
|
|
41
Config.h
41
Config.h
|
@ -5,41 +5,32 @@
|
|||
#include "Stream.h"
|
||||
#include "Storage\Storage.h"
|
||||
|
||||
class ConfigBlock
|
||||
// 配置管理
|
||||
// 配置区以指定签名开头,后续链式跟随各配置块
|
||||
class Config
|
||||
{
|
||||
private:
|
||||
static const uint c_Version = 0x534F5453; // STOS
|
||||
|
||||
public:
|
||||
static Storage* Device;
|
||||
static uint BaseAddress;
|
||||
|
||||
public:
|
||||
uint Signature;
|
||||
ushort HeaderCRC;
|
||||
ushort DataCRC;
|
||||
uint Size;
|
||||
char Name[4];
|
||||
|
||||
bool IsGoodBlock() const;
|
||||
bool IsGoodData () const;
|
||||
|
||||
const ConfigBlock* Next() const;
|
||||
const void* Data() const;
|
||||
|
||||
bool Init(const char* name, const ByteArray& bs);
|
||||
bool Write(Storage* storage, uint addr, const ByteArray& bs);
|
||||
Storage* Device;
|
||||
uint Address;
|
||||
|
||||
// 查找
|
||||
static const ConfigBlock* Find(const char* name, uint addr = NULL, bool fAppend = false);
|
||||
// 废弃
|
||||
static bool Invalid(const char* name, uint addr = NULL, Storage* storage = NULL);
|
||||
const void* Find(const char* name, bool fAppend = false);
|
||||
// 废弃。仅清空名称,并不删除数据区
|
||||
bool Invalid(const char* name);
|
||||
// 设置配置数据
|
||||
static const void* Set(const char* name, const ByteArray& bs, uint addr = NULL, Storage* storage = NULL);
|
||||
const void* Set(const char* name, const ByteArray& bs);
|
||||
// 获取配置数据
|
||||
static bool Get(const char* name, ByteArray& bs, uint addr = NULL);
|
||||
bool Get(const char* name, ByteArray& bs);
|
||||
// 获取配置数据
|
||||
static const void* Get(const char* name, uint addr = NULL);
|
||||
const void* Get(const char* name);
|
||||
|
||||
// 当前
|
||||
static Config* Current;
|
||||
// Flash最后一块作为配置区
|
||||
static Config* CreateFlash();
|
||||
};
|
||||
|
||||
// 必须设定为1字节对齐,否则offsetof会得到错误的位置
|
||||
|
|
Loading…
Reference in New Issue