nvs_tool.py 3.6 KB

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