Browse Source

tools: add xfimg2dump

Yuri D'Elia 2 years ago
parent
commit
1b22aac9fc
3 changed files with 54 additions and 2 deletions
  1. 4 0
      tools/README.md
  2. 4 2
      tools/lib/dump.py
  3. 46 0
      tools/xfimg2dump

+ 4 - 0
tools/README.md

@@ -34,6 +34,10 @@ Requires Python3 and the [pyelftools](https://github.com/eliben/pyelftools) modu
 
 Parse and decode a memory dump obtained from the D2/D21/D23 g-code into readable metadata and binary. The output binary is padded and extended to fit the original address range.
 
+### ``xfimg2dump``
+
+Extract a crash dump from an external flash image and output the same format produced by the D21 g-code.
+
 ### ``update_eeprom``
 
 Given one EEPROM dump, convert the dump to update instructions that can be sent to a printer.

+ 4 - 2
tools/lib/dump.py

@@ -5,8 +5,10 @@ import struct
 from . import avr
 
 
-FILL_BYTE  = b'\0'      # used to fill memory gaps in the dump
-DUMP_MAGIC = 0x55525547 # XFLASH dump magic
+FILL_BYTE   = b'\0'      # used to fill memory gaps in the dump
+DUMP_MAGIC  = 0x55525547 # XFLASH dump magic
+DUMP_OFFSET = 0x3d000    # XFLASH dump offset
+DUMP_SIZE   = 0x2300     # XFLASH dump size
 
 class CrashReason(enum.IntEnum):
     MANUAL = 0

+ 46 - 0
tools/xfimg2dump

@@ -0,0 +1,46 @@
+#!/usr/bin/env python3
+import argparse
+import struct
+import os, sys
+
+from lib.dump import DUMP_MAGIC, DUMP_OFFSET, DUMP_SIZE
+
+
+def error(msg):
+    print(msg, file=sys.stderr)
+
+def main():
+    # parse the arguments
+    ap = argparse.ArgumentParser(description="""
+        Extract a crash dump from an external flash image and output
+        the same format produced by the D21 g-code.
+    """)
+    ap.add_argument('image')
+    args = ap.parse_args()
+
+    # read the image
+    off = DUMP_OFFSET
+    with open(args.image, 'rb') as fd:
+        fd.seek(off)
+        data = fd.read(DUMP_SIZE)
+    if len(data) != DUMP_SIZE:
+        error('incorrect image size')
+        return os.EX_DATAERR
+
+    # check for magic header
+    magic, = struct.unpack('<L', data[:4])
+    if magic != DUMP_MAGIC:
+        error('invalid dump magic or no dump')
+        return os.EX_DATAERR
+
+    # output D21 dump
+    print('D21 - read crash dump', end='')
+    for i in range(len(data)):
+        if i % 16 == 0:
+            print('\n{:06x} '.format(off + i), end='')
+        print(' {:02x}'.format(data[i]), end='')
+    print('\nok')
+
+
+if __name__ == '__main__':
+    exit(main())