feat(nvs): NVS tool add key consistency check

This commit is contained in:
Adam Múdry 2023-08-30 17:03:04 +02:00
parent c276e2ca05
commit d42bde0378
2 changed files with 44 additions and 14 deletions

View File

@ -18,7 +18,7 @@ def integrity_check(nvs_partition: NVS_Partition, nvs_log: NVS_Logger) -> None:
if len(nvs_partition.pages) < 3:
nvs_log.info(
nvs_log.yellow(
'Partition has to have at least 3 pages to function properly!'
'NVS Partition must contain 3 pages (sectors) at least to function properly!'
)
)
@ -26,10 +26,11 @@ def integrity_check(nvs_partition: NVS_Partition, nvs_log: NVS_Logger) -> None:
if not any(page.header['status'] == 'Empty' for page in nvs_partition.pages):
nvs_log.info(
nvs_log.red(
'There are no free (empty) pages in the partition, there needs to be at least one free page!'
'''No free (empty) page found in the NVS partition,
at least one free page is required for proper function!'''
)
)
nvs_log.info(nvs_log.red('Has the NVS partition been truncated?\n'))
nvs_log.info(nvs_log.red('NVS partition possibly truncated?\n'))
for page in nvs_partition.pages:
# page: NVS_Page
@ -42,12 +43,12 @@ def integrity_check(nvs_partition: NVS_Partition, nvs_log: NVS_Logger) -> None:
if page.raw_entry_state_bitmap != bytearray({0xFF}) * nvs_const.entry_size:
nvs_log.info(
nvs_log.red(
'Page is reported as empty but entry state bitmap is not empty!'
'The page is reported as Empty but its entry state bitmap is not empty!'
)
)
if any([not e.is_empty for e in page.entries]):
nvs_log.info(
nvs_log.red('Page is reported as empty but there are data written!')
nvs_log.red('The page is reported as Empty but there are data written!')
)
else:
# Check page header CRC32
@ -65,22 +66,35 @@ def integrity_check(nvs_partition: NVS_Partition, nvs_log: NVS_Logger) -> None:
)
# Check all entries
seen_written_entires: Dict[str, list[NVS_Entry]] = {}
for entry in page.entries:
# entry: NVS_Entry
# Entry state check
# Entries stored in 'page.entries' are primitive data types, blob indexes or string/blob data
# Variable length values themselves occupy whole 32 bytes (therefore metadata values are meaningless)
# and are stored in as entries inside string/blob data entry 'entry.children' list
# Duplicate entry check (1) - same key, different index - find duplicates
if entry.state == 'Written':
if entry.key in seen_written_entires:
seen_written_entires[entry.key].append(entry)
else:
seen_written_entires[entry.key] = [entry]
# Entry state check - doesn't check variable length values (metadata such as state are meaningless as all 32 bytes are pure data)
if entry.is_empty:
if entry.state == 'Written':
nvs_log.info(
nvs_log.red(
f' Entry #{entry.index:03d} is reported as written but is empty!'
f' Entry #{entry.index:03d} is reported as Written but it is empty!'
)
)
continue
elif entry.state == 'Erased':
nvs_log.info(
nvs_log.yellow(
f' Entry #{entry.index:03d} is reported as erased but is empty!'
f' Entry #{entry.index:03d} is reported as Erased but it is empty! (Only entries reported as Empty should be empty)'
)
)
@ -103,17 +117,16 @@ def integrity_check(nvs_partition: NVS_Partition, nvs_log: NVS_Logger) -> None:
# Entry children CRC32 check
if (
entry.metadata['span'] > 1
and entry.metadata['crc']['data_original']
!= entry.metadata['crc']['data_computed']
and (entry.metadata['crc']['data_original'] != entry.metadata['crc']['data_computed'])
):
nvs_log.info(
nvs_log.red(
f' Entry #{entry.index:03d} {entry.key} data has wrong CRC32!'
f' Entry #{entry.index:03d} {entry.key} data (string, blob) has wrong CRC32!'
),
f'Written:',
nvs_log.red(f'{entry.metadata["crc"]["original"]:x}'),
nvs_log.red(f'{entry.metadata["crc"]["data_original"]:x}'),
f'Generated:',
nvs_log.green(f'{entry.metadata["crc"]["computed"]:x}'),
nvs_log.green(f'{entry.metadata["crc"]["data_computed"]:x}'),
)
# Entry type check
@ -161,6 +174,23 @@ def integrity_check(nvs_partition: NVS_Partition, nvs_log: NVS_Logger) -> None:
else:
used_namespaces[entry.metadata['namespace']] = None
# Duplicate entry check (2) - same key, different index - print duplicates
duplicate_entries_list = [seen_written_entires[key] for key in seen_written_entires if len(seen_written_entires[key]) > 1]
for duplicate_entries in duplicate_entries_list:
# duplicate_entries: list[NVS_Entry]
nvs_log.info(
nvs_log.red(
f'''Entry key {duplicate_entries[0].key} on page no. {page.header["page_index"]}
with status {page.header["status"]} is used by the following entries:'''
)
)
for entry in duplicate_entries:
nvs_log.info(
nvs_log.red(
f'Entry #{entry.index:03d} {entry.key} is a duplicate!'
)
)
nvs_log.info()
# Blob checks

View File

@ -110,7 +110,7 @@ def main() -> None:
if args.integrity_check:
nvs_log.info()
nvs_check.integrity_check(nvs, nvs_logger)
nvs_check.integrity_check(nvs, nvs_log)
if __name__ == '__main__':