Mercurial > lcfOS
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) +