annotate python/hexfile.py @ 245:66912720d712

Added grinder
author Windel Bouwman
date Wed, 24 Jul 2013 22:40:29 +0200
parents 58155c7c4a8e
children f254b87258e6
rev   line source
104
ed230e947dc6 Added hexviewer
windel
parents:
diff changeset
1 import os
244
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
2 import struct
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
3 import binascii
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
4
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
5 DATA = 0
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
6 EOF = 1
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
7 EXTLINADR = 4
104
ed230e947dc6 Added hexviewer
windel
parents:
diff changeset
8
ed230e947dc6 Added hexviewer
windel
parents:
diff changeset
9 class HexFileException(Exception):
233
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
10 pass
104
ed230e947dc6 Added hexviewer
windel
parents:
diff changeset
11
ed230e947dc6 Added hexviewer
windel
parents:
diff changeset
12 def parseHexLine(line):
233
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
13 """ Parses a hexfile line into three parts """
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
14 line = line[1:] # Remove ':'
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
15 nums = bytes.fromhex(line)
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
16 bytecount = nums[0]
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
17 if len(nums) != bytecount + 5:
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
18 raise HexFileException('byte count field incorrect')
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
19 crc = sum(nums)
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
20 if (crc & 0xFF) != 0:
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
21 raise HexFileException('crc incorrect')
244
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
22 address = struct.unpack('>H', nums[1:3])[0]
233
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
23 typ = nums[3]
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
24 data = nums[4:-1]
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
25 return (address, typ, data)
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
26
244
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
27 def makeHexLine(address, typ, data=bytes()):
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
28 bytecount = len(data)
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
29 nums = bytearray()
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
30 nums.append(bytecount)
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
31 nums.extend(struct.pack('>H', address))
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
32 nums.append(typ)
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
33 nums.extend(data)
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
34 crc = sum(nums)
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
35 crc = ((~crc) + 1) & 0xFF
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
36 nums.append(crc)
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
37 line = ':' + binascii.hexlify(nums).decode('ascii')
244
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
38 return line
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
39
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
40 def chunks(data, csize=16):
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
41 idx = 0
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
42 while idx < len(data):
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
43 s = min(len(data) - idx, csize)
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
44 yield data[idx:idx+s]
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
45 idx += s
104
ed230e947dc6 Added hexviewer
windel
parents:
diff changeset
46
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
47 def hexfields(f):
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
48 for line in f:
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
49 line = line.strip() # Strip spaces and newlines
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
50 if not line:
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
51 continue # Skip empty lines
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
52 if line[0] != ':':
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
53 continue # Skip lines that do not start with a ':'
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
54 yield parseHexLine(line)
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
55
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
56
104
ed230e947dc6 Added hexviewer
windel
parents:
diff changeset
57 class HexFile:
233
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
58 """ Represents an intel hexfile """
240
6259856841a0 Remove project
Windel Bouwman
parents: 233
diff changeset
59 def __init__(self):
6259856841a0 Remove project
Windel Bouwman
parents: 233
diff changeset
60 self.regions = []
6259856841a0 Remove project
Windel Bouwman
parents: 233
diff changeset
61 self.startAddress = 0
104
ed230e947dc6 Added hexviewer
windel
parents:
diff changeset
62
233
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
63 def load(self, f):
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
64 endOfFile = False
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
65 ext = 0
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
66 for address, typ, data in hexfields(f):
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
67 if endOfFile:
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
68 raise HexFileException('hexfile line after end of file record')
104
ed230e947dc6 Added hexviewer
windel
parents:
diff changeset
69 if typ == 0x0: # Data record
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
70 self.addRegion(address + ext, data)
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
71 elif typ == EXTLINADR: # Extended linear address record
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
72 ext = (struct.unpack('>H', data[0:2])[0]) << 16
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
73 elif typ == EOF: # End of file record
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
74 if len(data) != 0:
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
75 raise HexFileException('end of file not empty')
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
76 endOfFile = True
104
ed230e947dc6 Added hexviewer
windel
parents:
diff changeset
77 elif typ == 0x5: # Start address record (where IP goes after loading)
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
78 self.startAddress = struct.unpack('>I', data[0:4])[0]
104
ed230e947dc6 Added hexviewer
windel
parents:
diff changeset
79 else:
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
80 raise HexFileException('record type {0} not implemented'.format(typ))
233
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
81
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
82 def __repr__(self):
244
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
83 return 'Hexfile with {} regions'.format(len(self.regions))
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
84
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
85 def dump(self):
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
86 print(self)
233
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
87 for r in self.regions:
244
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
88 print(r)
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
89
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
90 def __eq__(self, other):
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
91 regions = self.regions
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
92 oregions = other.regions
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
93 if len(regions) != len(oregions):
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
94 return False
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
95 return all(rs == ro for rs, ro in zip(regions, oregions))
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
96
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
97 def addRegion(self, address, data):
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
98 r = HexFileRegion(address, data)
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
99 self.regions.append(r)
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
100 self.check()
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
101
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
102 def check(self):
244
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
103 self.regions.sort(key=lambda r: r.address)
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
104 if len(self.regions) > 1:
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
105 for r1, r2 in zip(self.regions[:-1], self.regions[1:]):
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
106 if r1.EndAddress > r2.address:
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
107 raise HexFileException('Overlapping regions')
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
108 change = True
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
109 while change and len(self.regions) > 1:
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
110 change = False
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
111 for r1, r2 in zip(self.regions[:-1], self.regions[1:]):
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
112 if r1.EndAddress == r2.address:
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
113 r1.addData(r2.data)
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
114 self.regions.remove(r2)
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
115 change = True
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
116
233
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
117
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
118 def save(self, f):
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
119 def emit(address, typ, data=bytes()):
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
120 print(makeHexLine(address, typ, data), file=f)
233
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
121 for r in self.regions:
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
122 ext = r.address & 0xFFFF0000
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
123 emit(0, EXTLINADR, struct.pack('>H', ext >> 16))
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
124 address = r.address - ext
244
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
125 for chunk in chunks(r.data):
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
126 if address >= 0x10000:
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
127 ext += 0x10000
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
128 emit(0, EXTLINADR, struct.pack('>H', ext >> 16))
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
129 address -= 0x10000
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
130 emit(address, DATA, chunk)
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
131 address += len(chunk)
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
132 emit(0, EOF)
233
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
133
104
ed230e947dc6 Added hexviewer
windel
parents:
diff changeset
134 class HexFileRegion:
244
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
135 def __init__(self, address, data = bytes()):
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
136 self.address = address
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
137 self.data = data
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
138
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
139 def __repr__(self):
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
140 return 'Region at 0x{:08X} of {} bytes'.format(self.address, len(self.data))
244
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
141
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
142 def __eq__(self, other):
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
143 return (self.address, self.data) == (other.address, other.data)
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
144
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
145 def addData(self, d):
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
146 self.data = self.data + d
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
147
244
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
148 @property
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
149 def EndAddress(self):
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
150 return self.address + len(self.data)
104
ed230e947dc6 Added hexviewer
windel
parents:
diff changeset
151
233
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
152