diff python/hexfile.py @ 104:ed230e947dc6

Added hexviewer
author windel
date Sun, 30 Dec 2012 22:31:55 +0100
parents
children d3dccf12ca88
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/hexfile.py	Sun Dec 30 22:31:55 2012 +0100
@@ -0,0 +1,97 @@
+import os
+
+class HexFileException(Exception):
+   pass
+
+def parseHexLine(line):
+   """ Parses a hexfile line into three parts """
+   line = line[1:] # Remove ':'
+   nums = bytes.fromhex(line)
+   bytecount = nums[0]
+   if len(nums) != bytecount + 5:
+      raise HexFileException('byte count field incorrect')
+   crc = sum(nums)
+   if (crc & 0xFF) != 0:
+      raise HexFileException('crc incorrect')
+   address = nums[1] * 256 + nums[2]
+   typ = nums[3]
+   data = nums[4:-1]
+   return (address, typ, data)
+
+class HexFile:
+   """ Represents an intel hexfile """
+   def __init__(self, filename=None):
+      self.regions = []
+      self.startAddress = 0
+      self.filename = None
+      if filename:
+         self.load(filename)
+
+   def load(self, filename):
+      with open(filename, 'r') as f:
+         endOfFile = False
+         offset = 0
+         startAddress = 0
+         curAddress = 0
+         curData = bytearray()
+         for line in f:
+            line = line.strip() # Strip spaces and newlines
+            if not line: continue # Skip empty lines
+            if line[0] != ':': continue # Skip lines that do not start with a ':'
+            if endOfFile: raise HexFileException('hexfile line after end of file record')
+            address, typ, data = parseHexLine(line)
+            if typ == 0x0: # Data record
+               address += offset # Fix address with offset
+               # Append data
+               if address == curAddress:
+                  curData += data
+                  curAddress += len(data)
+               else:
+                  if curData:
+                     self.regions.append(HexFileRegion(startAddress, bytes(curData)))
+                  startAddress = address
+                  curAddress = address + len(data)
+                  curData = bytearray(data)
+            elif typ == 0x4: # Extended linear address record
+               offset = ((data[0] << 8) + data[1]) << 16
+            elif typ == 0x1: # End of file record
+               if len(data) != 0:
+                  raise HexFileException('end of file record must contain no data')
+               endOfFile = True
+            elif typ == 0x5: # Start address record (where IP goes after loading)
+               self.startAddress = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]
+            else:
+               raise HexFileException('record type {0} not implemented'.format(typ))
+               print(hex(address), typ, data)
+         # After all lines:
+         if curData:
+            self.regions.append(HexFileRegion(startAddress, bytes(curData)))
+         # Store the filename:
+         self.filename = filename
+   def __repr__(self):
+      i = []
+      i.append(super().__repr__())
+      i.append('Start address {0}'.format(hex(self.startAddress)))
+      i.append('Filename: {0}'.format(self.filename))
+      for r in self.regions:
+         i.append(str(r))
+      return os.linesep.join(i)
+   def save(self, filename):
+      with open(filename, 'w') as f:
+         for line in f:
+            pass
+     
+class HexFileRegion:
+   def __init__(self, address, data = bytes()):
+      self.address = address
+      self.data = data
+   def __repr__(self):
+      return 'Region at 0x{0:X} of {1} bytes'.format(self.address, len(self.data))
+
+if __name__ == '__main__':
+   h = HexFile()
+   print(h)
+   """ Test hexfile implementation with some hexfile """
+   h1 = HexFile('audio.hex')
+   print(h1)
+