nvs_tool.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #!/usr/bin/env python3
  2. # SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
  3. # SPDX-License-Identifier: Apache-2.0
  4. import argparse
  5. import os
  6. import sys
  7. import traceback
  8. import nvs_logger
  9. import nvs_parser
  10. from nvs_logger import nvs_log
  11. from nvs_parser import nvs_const
  12. def program_args() -> argparse.Namespace:
  13. parser = argparse.ArgumentParser(
  14. description='Parse NVS partition', formatter_class=argparse.RawTextHelpFormatter
  15. )
  16. parser.add_argument('file', help='Path to dumped NVS partition')
  17. parser.add_argument(
  18. '-i',
  19. '--integrity-check',
  20. action='store_true',
  21. help='check partition for potential errors',
  22. )
  23. tmp = {
  24. 'all': 'print everything',
  25. 'written': 'print only currently written entries',
  26. 'minimal': 'print only namespace:key=value pairs',
  27. 'namespaces': 'list all written namespaces',
  28. 'blobs': 'print all blobs and strings',
  29. 'storage_info': 'print storage related information (free/used entries, etc)',
  30. 'none': 'do not print anything (if you only want to do integrity check)',
  31. }
  32. parser.add_argument(
  33. '-d',
  34. '--dump',
  35. choices=tmp,
  36. default='all',
  37. metavar='type',
  38. help=(
  39. f"""type: {str(list(tmp.keys()))[1:-1]}
  40. {os.linesep.join([f'{opt} - {tmp[opt]}' for opt in tmp])}"""
  41. ),
  42. )
  43. parser.add_argument(
  44. '--color',
  45. choices=['never', 'auto', 'always'],
  46. default='auto',
  47. help='Enable color (ANSI)',
  48. )
  49. tmp = {
  50. 'text': 'print output as a human-readable text',
  51. 'json': 'print output as JSON and exit',
  52. }
  53. parser.add_argument(
  54. '-f', '--format', choices=tmp, default='text', help='Output format'
  55. )
  56. return parser.parse_args()
  57. def main() -> None:
  58. args = program_args()
  59. if nvs_const.entry_size != 32:
  60. raise ValueError(f'Entry size is not 32B! This is currently non negotiable.')
  61. nvs_log.set_color(args.color)
  62. nvs_log.set_format(args.format)
  63. try:
  64. with open(args.file, 'rb') as f:
  65. partition = f.read()
  66. except IndexError:
  67. nvs_log.error('No file given')
  68. raise
  69. except FileNotFoundError:
  70. nvs_log.error('Bad filename')
  71. raise
  72. nvs = nvs_parser.NVS_Partition(args.file.split('/')[-1], bytearray(partition))
  73. def noop(_: nvs_parser.NVS_Partition) -> None:
  74. pass
  75. def format_not_implemented(_: nvs_parser.NVS_Partition) -> None:
  76. raise RuntimeError(f'{args.format} is not implemented')
  77. def cmd_not_implemented(_: nvs_parser.NVS_Partition) -> None:
  78. raise RuntimeError(f'{args.dump} is not implemented')
  79. formats = {
  80. 'text': noop,
  81. 'json': nvs_logger.print_json,
  82. }
  83. formats.get(args.format, format_not_implemented)(nvs)
  84. if args.format == 'text':
  85. cmds = {
  86. 'all': nvs_logger.dump_everything,
  87. 'written': nvs_logger.dump_written_entries,
  88. 'minimal': nvs_logger.dump_key_value_pairs,
  89. 'namespaces': nvs_logger.list_namespaces,
  90. 'blobs': nvs_logger.dump_written_blobs,
  91. 'storage_info': nvs_logger.storage_stats,
  92. 'none': noop,
  93. }
  94. cmds.get(args.dump, cmd_not_implemented)(nvs) # type: ignore
  95. if args.integrity_check:
  96. nvs_log.info()
  97. nvs_logger.integrity_check(nvs)
  98. if __name__ == '__main__':
  99. try:
  100. main()
  101. except ValueError:
  102. traceback.print_exc(file=sys.stderr)
  103. sys.exit(1)
  104. except nvs_parser.NVS_Constants.ConstantError:
  105. traceback.print_exc(file=sys.stderr)
  106. sys.exit(1)