annotate python/utils/hexfile.py @ 299:674789d9ff37

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