libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
block_ops.hpp
1
19size_t AvailableSize() { return GetChecksumOffset() - GetUsedBlockSize(BlockType::MAIN); }
20
26size_t GetBlockOffset(BlockType block)
27{
28 return block == BlockType::BACKUP ? block_size_ : 0;
29}
30
35size_t GetChecksumOffset() { return block_size_ - GetChecksumSize(); }
36
41size_t GetChecksumSize() { return AlignSize(sizeof(CHECKSUM_BYTE)); }
42
50void WriteEmptyBlockPrefix(BlockType block)
51{
52 const size_t offset = GetBlockOffset(block);
53 EraseFlashOrExit(offset, block_size_);
54
55 FlashInfo info; // padding filled with 0xFF by constructor
56 info.header = FLASH_HEADER;
57 KeyInfo& tmp_key = info.key;
61 tmp_key.SetNameLength(0);
62 tmp_key.SetDataSize(0);
63 WriteFlashOrExit(offset, {reinterpret_cast<uint8_t*>(&info), sizeof(FlashInfo)});
64}
65
70void WriteBlockChecksum(BlockType block)
71{
72 WriteFlashOrExit(GetBlockOffset(block) + GetChecksumOffset(),
73 {&CHECKSUM_BYTE, sizeof(CHECKSUM_BYTE)});
74}
75
84void InitBlock(BlockType block)
85{
86 WriteEmptyBlockPrefix(block);
87 WriteBlockChecksum(block);
88}
89
97void PrepareBackup() { WriteEmptyBlockPrefix(BlockType::BACKUP); }
98
111bool IsBackupPrepared()
112{
113 const size_t sentinel_offset = GetSentinelOffset(BlockType::BACKUP);
114 FlashInfo info;
115 ReadFlashOrExit(GetBlockOffset(BlockType::BACKUP), info);
116 if (info.header != FLASH_HEADER ||
119 info.key.raw_info != 0)
120 {
121 return false;
122 }
123 return IsErased(sentinel_offset + AlignSize(sizeof(KeyInfo)),
124 GetBlockOffset(BlockType::BACKUP) + block_size_);
125}
126
131size_t GetCrcSize() { return AlignSize(sizeof(uint32_t)); }
132
138uint32_t GetBackupCrc(size_t used_size)
139{
140 uint32_t crc = 0xFFFFFFFFU;
141 uint8_t buffer[32];
142 const size_t offset = GetBlockOffset(BlockType::BACKUP);
143 for (size_t done = 0; done < used_size;)
144 {
145 const size_t size = LibXR::min<size_t>(sizeof(buffer), used_size - done);
146 ReadFlashOrExit(offset + done, RawData(buffer, size));
147 for (size_t i = 0; i < size; ++i)
148 {
149 crc ^= buffer[i];
150 for (int bit = 0; bit < 8; ++bit)
151 {
152 crc = (crc >> 1) ^ (0xEDB88320U & (0U - (crc & 1U)));
153 }
154 }
155 done += size;
156 }
157 return ~crc;
158}
159
175bool IsBackupRestorable(size_t& used_size)
176{
177 return IsBlockValid(BlockType::BACKUP) && !IsBlockEmpty(BlockType::BACKUP) &&
178 TryGetUsedBlockSize(BlockType::BACKUP, used_size);
179}
180
196bool IsBackupComplete(size_t& used_size)
197{
198 if (!IsBackupRestorable(used_size) || used_size + GetCrcSize() > GetChecksumOffset())
199 {
200 return false;
201 }
202 uint32_t stored_crc = 0;
203 ReadFlashOrExit(GetBlockOffset(BlockType::BACKUP) + used_size, stored_crc);
204 return stored_crc == GetBackupCrc(used_size);
205}
206
212bool IsBlockInited(BlockType block)
213{
214 const size_t offset = GetBlockOffset(block);
215 FlashInfo flash_data;
216 ReadFlashOrExit(offset, flash_data);
217 return flash_data.header == FLASH_HEADER;
218}
219
229bool IsBlockEmpty(BlockType block)
230{
231 const size_t offset = GetBlockOffset(block);
232 FlashInfo flash_data;
233 ReadFlashOrExit(offset, flash_data);
235}
236
243bool IsBlockError(BlockType block)
244{
245 const size_t offset = GetBlockOffset(block);
246 uint32_t checksum = 0;
247 ReadFlashOrExit(offset + GetChecksumOffset(), checksum);
248 return checksum != CHECKSUM_BYTE;
249}
250
262bool IsBlockValid(BlockType block)
263{
264 if (!IsBlockInited(block) || IsBlockError(block))
265 {
266 return false;
267 }
268 KeyInfo sentinel;
269 ReadFlashOrExit(GetSentinelOffset(block), sentinel);
270 return sentinel.raw_info == 0;
271}
272
279size_t GetSentinelOffset(BlockType block)
280{
281 return GetBlockOffset(block) + LibXR::OffsetOf(&FlashInfo::key);
282}
283
291bool IsErased(size_t offset, size_t end)
292{
293 uint8_t buffer[32];
294 while (offset < end)
295 {
296 const size_t size = LibXR::min<size_t>(sizeof(buffer), end - offset);
297 ReadFlashOrExit(offset, RawData(buffer, size));
298 for (size_t i = 0; i < size; ++i)
299 {
300 if (buffer[i] != 0xFF)
301 {
302 return false;
303 }
304 }
305 offset += size;
306 }
307 return true;
308}
309
323bool TryGetUsedBlockSize(BlockType block, size_t& used_size)
324{
325 const size_t block_offset = GetBlockOffset(block);
326 const size_t checksum_offset = block_offset + GetChecksumOffset();
327 size_t key_offset = block_offset + LibXR::OffsetOf(&FlashInfo::key);
328
329 while (true)
330 {
331 if (key_offset + AlignSize(sizeof(KeyInfo)) > checksum_offset)
332 {
333 return false;
334 }
335
336 KeyInfo key;
337 ReadFlashOrExit(key_offset, key);
338
339 // Recovery cannot trust erased or half-written key metadata to bound copies.
343 {
344 return false;
345 }
346
347 const size_t next_key_offset = key_offset + AlignSize(sizeof(KeyInfo)) +
348 AlignSize(key.GetNameLength()) +
349 AlignSize(key.GetDataSize());
350 if (next_key_offset > checksum_offset)
351 {
352 return false;
353 }
354
356 {
357 used_size = next_key_offset - block_offset;
358 return true;
359 }
360
361 key_offset = next_key_offset;
362 }
363}
364
371size_t GetUsedBlockSize(BlockType block)
372{
373 return GetNextKey(GetLastKey(block)) - GetBlockOffset(block);
374}
375
385void CopyBlockPrefixAndChecksum(BlockType dst_block, BlockType src_block,
386 size_t used_size)
387{
388 const size_t dst_offset = GetBlockOffset(dst_block);
389 const size_t src_offset = GetBlockOffset(src_block);
390 const size_t checksum_offset = GetChecksumOffset();
391
392 DEV_ASSERT(used_size <= checksum_offset);
393 // Only the live key prefix and checksum are needed; erased tail bytes are irrelevant.
394 CopyFlashData(dst_offset, src_offset, used_size);
395 CopyFlashData(dst_offset + checksum_offset, src_offset + checksum_offset,
396 GetChecksumSize());
397}
读写对齐布尔位图块的工具 Helpers for reading and writing aligned boolean flag blocks.
Definition layout.hpp:36
static void SetFlag(BlockBoolData< BlockSize > &obj, bool value)
把一个布尔值编码进位图块 / Encode one boolean value into a flag block.
Definition layout.hpp:43
static bool ReadFlag(const BlockBoolData< BlockSize > &obj)
从位图块读取布尔值 / Decode one boolean value from a flag block.
Definition layout.hpp:64
constexpr auto min(LeftType a, RightType b) -> std::common_type_t< LeftType, RightType >
计算两个数的最小值 / Computes the minimum of two numbers
size_t OffsetOf(MemberType OwnerType::*member) noexcept
计算成员在宿主对象中的偏移量 Computes the offset of a member within the owning object
Definition libxr_def.hpp:95
Flash 存储的块信息结构 Structure representing a Flash storage block.
Definition layout.hpp:177
KeyInfo key
Definition layout.hpp:199
uint32_t header
Flash 块头签名 / Flash block-header signature.
Definition layout.hpp:195
键信息结构,存储键的元数据 Structure containing key metadata.
Definition layout.hpp:119
BlockBoolData< MinWriteSize > uninit
该键是否未初始化
Definition layout.hpp:122
BlockBoolData< MinWriteSize > available_flag
该键是否有效
Definition layout.hpp:121
uint32_t GetDataSize() const
获取数据字节数 / Get the payload size in bytes.
Definition layout.hpp:167
uint32_t raw_info
Definition layout.hpp:124
void SetNameLength(uint8_t len)
设置键名长度 / Set the key name length.
Definition layout.hpp:143
BlockBoolData< MinWriteSize > no_next_key
是否是最后一个键
Definition layout.hpp:120
void SetDataSize(uint32_t size)
设置数据字节数 / Set the payload size in bytes.
Definition layout.hpp:158
uint8_t GetNameLength() const
获取键名长度 / Get the key name length.
Definition layout.hpp:152