Mercurial > lcfOS
comparison python/hexfile.py @ 104:ed230e947dc6
Added hexviewer
author | windel |
---|---|
date | Sun, 30 Dec 2012 22:31:55 +0100 |
parents | |
children | d3dccf12ca88 |
comparison
equal
deleted
inserted
replaced
103:28a35161ef23 | 104:ed230e947dc6 |
---|---|
1 import os | |
2 | |
3 class HexFileException(Exception): | |
4 pass | |
5 | |
6 def parseHexLine(line): | |
7 """ Parses a hexfile line into three parts """ | |
8 line = line[1:] # Remove ':' | |
9 nums = bytes.fromhex(line) | |
10 bytecount = nums[0] | |
11 if len(nums) != bytecount + 5: | |
12 raise HexFileException('byte count field incorrect') | |
13 crc = sum(nums) | |
14 if (crc & 0xFF) != 0: | |
15 raise HexFileException('crc incorrect') | |
16 address = nums[1] * 256 + nums[2] | |
17 typ = nums[3] | |
18 data = nums[4:-1] | |
19 return (address, typ, data) | |
20 | |
21 class HexFile: | |
22 """ Represents an intel hexfile """ | |
23 def __init__(self, filename=None): | |
24 self.regions = [] | |
25 self.startAddress = 0 | |
26 self.filename = None | |
27 if filename: | |
28 self.load(filename) | |
29 | |
30 def load(self, filename): | |
31 with open(filename, 'r') as f: | |
32 endOfFile = False | |
33 offset = 0 | |
34 startAddress = 0 | |
35 curAddress = 0 | |
36 curData = bytearray() | |
37 for line in f: | |
38 line = line.strip() # Strip spaces and newlines | |
39 if not line: continue # Skip empty lines | |
40 if line[0] != ':': continue # Skip lines that do not start with a ':' | |
41 if endOfFile: raise HexFileException('hexfile line after end of file record') | |
42 address, typ, data = parseHexLine(line) | |
43 if typ == 0x0: # Data record | |
44 address += offset # Fix address with offset | |
45 # Append data | |
46 if address == curAddress: | |
47 curData += data | |
48 curAddress += len(data) | |
49 else: | |
50 if curData: | |
51 self.regions.append(HexFileRegion(startAddress, bytes(curData))) | |
52 startAddress = address | |
53 curAddress = address + len(data) | |
54 curData = bytearray(data) | |
55 elif typ == 0x4: # Extended linear address record | |
56 offset = ((data[0] << 8) + data[1]) << 16 | |
57 elif typ == 0x1: # End of file record | |
58 if len(data) != 0: | |
59 raise HexFileException('end of file record must contain no data') | |
60 endOfFile = True | |
61 elif typ == 0x5: # Start address record (where IP goes after loading) | |
62 self.startAddress = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3] | |
63 else: | |
64 raise HexFileException('record type {0} not implemented'.format(typ)) | |
65 print(hex(address), typ, data) | |
66 # After all lines: | |
67 if curData: | |
68 self.regions.append(HexFileRegion(startAddress, bytes(curData))) | |
69 # Store the filename: | |
70 self.filename = filename | |
71 def __repr__(self): | |
72 i = [] | |
73 i.append(super().__repr__()) | |
74 i.append('Start address {0}'.format(hex(self.startAddress))) | |
75 i.append('Filename: {0}'.format(self.filename)) | |
76 for r in self.regions: | |
77 i.append(str(r)) | |
78 return os.linesep.join(i) | |
79 def save(self, filename): | |
80 with open(filename, 'w') as f: | |
81 for line in f: | |
82 pass | |
83 | |
84 class HexFileRegion: | |
85 def __init__(self, address, data = bytes()): | |
86 self.address = address | |
87 self.data = data | |
88 def __repr__(self): | |
89 return 'Region at 0x{0:X} of {1} bytes'.format(self.address, len(self.data)) | |
90 | |
91 if __name__ == '__main__': | |
92 h = HexFile() | |
93 print(h) | |
94 """ Test hexfile implementation with some hexfile """ | |
95 h1 = HexFile('audio.hex') | |
96 print(h1) | |
97 |