annotate python/hexfile.py @ 280:02385f62f250

Rework from str interface to Instruction interface
author Windel Bouwman
date Sat, 02 Nov 2013 10:03:26 +0100
parents 6ed3d3a82a63
children
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):
246
f254b87258e6 Added hexfile to zcc
Windel Bouwman
parents: 245
diff changeset
83 size = sum(len(r.data) for r in self.regions)
f254b87258e6 Added hexfile to zcc
Windel Bouwman
parents: 245
diff changeset
84 return 'Hexfile containing {} bytes'.format(size)
244
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
85
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
86 def dump(self):
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
87 print(self)
233
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
88 for r in self.regions:
244
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
89 print(r)
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
90
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
91 def __eq__(self, other):
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
92 regions = self.regions
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
93 oregions = other.regions
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
94 if len(regions) != len(oregions):
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
95 return False
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
96 return all(rs == ro for rs, ro in zip(regions, oregions))
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
97
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
98 def addRegion(self, address, data):
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
99 r = HexFileRegion(address, data)
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
100 self.regions.append(r)
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
101 self.check()
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
102
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
103 def check(self):
244
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
104 self.regions.sort(key=lambda r: r.address)
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
105 change = True
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
106 while change and len(self.regions) > 1:
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
107 change = False
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
108 for r1, r2 in zip(self.regions[:-1], self.regions[1:]):
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
109 if r1.EndAddress == r2.address:
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
110 r1.addData(r2.data)
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
111 self.regions.remove(r2)
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
112 change = True
251
6ed3d3a82a63 Added another c3 example. First import attempt
Windel Bouwman
parents: 246
diff changeset
113 elif r1.EndAddress > r2.address:
6ed3d3a82a63 Added another c3 example. First import attempt
Windel Bouwman
parents: 246
diff changeset
114 raise HexFileException('Overlapping regions')
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
115
246
f254b87258e6 Added hexfile to zcc
Windel Bouwman
parents: 245
diff changeset
116 def merge(self, other):
f254b87258e6 Added hexfile to zcc
Windel Bouwman
parents: 245
diff changeset
117 for r in other.regions:
f254b87258e6 Added hexfile to zcc
Windel Bouwman
parents: 245
diff changeset
118 self.addRegion(r.address, r.data)
233
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
119
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
120 def save(self, f):
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
121 def emit(address, typ, data=bytes()):
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
122 print(makeHexLine(address, typ, data), file=f)
233
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
123 for r in self.regions:
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
124 ext = r.address & 0xFFFF0000
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
125 emit(0, EXTLINADR, struct.pack('>H', ext >> 16))
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
126 address = r.address - ext
244
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
127 for chunk in chunks(r.data):
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
128 if address >= 0x10000:
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
129 ext += 0x10000
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
130 emit(0, EXTLINADR, struct.pack('>H', ext >> 16))
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
131 address -= 0x10000
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
132 emit(address, DATA, chunk)
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
133 address += len(chunk)
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
134 emit(0, EOF)
233
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
135
104
ed230e947dc6 Added hexviewer
windel
parents:
diff changeset
136 class HexFileRegion:
244
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
137 def __init__(self, address, data = bytes()):
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
138 self.address = address
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
139 self.data = data
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
140
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
141 def __repr__(self):
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
142 return 'Region at 0x{:08X} of {} bytes'.format(self.address, len(self.data))
244
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
143
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
144 def __eq__(self, other):
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
145 return (self.address, self.data) == (other.address, other.data)
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
146
245
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
147 def addData(self, d):
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
148 self.data = self.data + d
66912720d712 Added grinder
Windel Bouwman
parents: 244
diff changeset
149
244
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
150 @property
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
151 def EndAddress(self):
58155c7c4a8e Add hexutil
Windel Bouwman
parents: 240
diff changeset
152 return self.address + len(self.data)
104
ed230e947dc6 Added hexviewer
windel
parents:
diff changeset
153
233
d3dccf12ca88 Added hexfile tests
Windel Bouwman
parents: 104
diff changeset
154