#!/usr/bin/env python3 # SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import argparse import os import sys import traceback import nvs_check import nvs_logger import nvs_parser from nvs_logger import nvs_log from nvs_parser import nvs_const def program_args() -> argparse.Namespace: parser = argparse.ArgumentParser( description='Parse NVS partition', formatter_class=argparse.RawTextHelpFormatter ) parser.add_argument('file', help='Path to dumped NVS partition') parser.add_argument( '-i', '--integrity-check', action='store_true', help='check partition for potential errors', ) tmp = { 'all': 'print written, erased and empty entries', 'written': 'print only currently written entries', 'minimal': 'print only namespace:key=value pairs', 'blobs': 'print all blobs and strings', 'namespaces': 'list all written namespaces', 'storage_info': 'print storage related information (free/used entries, etc)', 'none': 'do not print anything (if you only want to do integrity check)', } parser.add_argument( '-d', '--dump', choices=tmp, default='all', metavar='type', help=( f"""type: {str(list(tmp.keys()))[1:-1]} {os.linesep.join([f'{opt} - {tmp[opt]}' for opt in tmp])}""" ), ) parser.add_argument( '--color', choices=['never', 'auto', 'always'], default='auto', help='Enable color (ANSI)', ) tmp = { 'text': 'print output as a human-readable text', 'json': 'print output as JSON and exit', } parser.add_argument( '-f', '--format', choices=tmp, default='text', help='Output format' ) return parser.parse_args() def main() -> None: args = program_args() if nvs_const.entry_size != 32: raise ValueError(f'Entry size is not 32B! This is currently non negotiable.') nvs_log.set_color(args.color) nvs_log.set_format(args.format) try: with open(args.file, 'rb') as f: partition = f.read() except IndexError: nvs_log.error('No file given') raise except FileNotFoundError: nvs_log.error('Bad filename') raise nvs = nvs_parser.NVS_Partition(args.file.split('/')[-1], bytearray(partition)) def noop(_: nvs_parser.NVS_Partition) -> None: pass def format_not_implemented(_: nvs_parser.NVS_Partition) -> None: raise RuntimeError(f'{args.format} is not implemented') def cmd_not_implemented(_: nvs_parser.NVS_Partition) -> None: raise RuntimeError(f'{args.dump} is not implemented') formats = { 'text': noop, 'json': nvs_logger.print_json, } formats.get(args.format, format_not_implemented)(nvs) if args.format == 'text': cmds = { 'all': nvs_logger.dump_everything, 'written': nvs_logger.dump_written_entries, 'minimal': nvs_logger.dump_key_value_pairs, 'namespaces': nvs_logger.list_namespaces, 'blobs': nvs_logger.dump_written_blobs, 'storage_info': nvs_logger.storage_stats, 'none': noop, } cmds.get(args.dump, cmd_not_implemented)(nvs) # type: ignore if args.integrity_check: nvs_log.info() nvs_check.integrity_check(nvs, nvs_log) if __name__ == '__main__': try: main() except ValueError: traceback.print_exc(file=sys.stderr) sys.exit(1) except nvs_parser.NVS_Constants.ConstantError: traceback.print_exc(file=sys.stderr) sys.exit(1)