Support upgrade with passwd
[gnuk/neug.git] / tool / intel_hex.py
1 """
2 intel_hex.py - Intel Hex file reader.
3
4 Copyright (C) 2010 Free Software Initiative of Japan
5 Author: NIIBE Yutaka <gniibe@fsij.org>
6
7 You can use/distribute/modify/etc. this for any purpose.
8 """
9
10 import binascii
11
12 class intel_hex:
13     def __init__(self, filename):
14         self.start_address = 0
15         self.address = 0
16         self.memory = {}
17         self.lineno = 0
18         file = open(filename, 'r')
19         for line in file:
20             self.lineno += 1
21             if self.parse_line(line):
22                 break
23         file.close()
24         self.pack()
25
26     def pack(self):
27         memory = {}
28         prev_addr = 0
29         prev_data_len = 0
30         for addr in sorted(self.memory.keys()):
31             data = self.memory[addr]
32             if addr == prev_addr + prev_data_len:
33                 memory[prev_addr] += data
34                 prev_data_len += len(data)
35             else:
36                 memory[addr] = data
37                 prev_addr = addr
38                 prev_data_len = len(data)
39         self.memory = memory
40
41     def calc_checksum(self, byte_count, offset, type_code, data):
42         s = byte_count
43         s += (offset >> 8)
44         s += offset & 0xff
45         s += type_code
46         for d in data:
47             s += (ord(d) & 0xff)
48         s &= 0xff
49         if s != 0:
50             s = 256 - s
51         return s
52
53     def add_data(self, count, offset, data):
54         address = self.address + offset
55         try:
56             self.memory[address]
57         except:
58             pass
59         else:
60             raise ValueError, "data overwritten (%d)" % self.lineno
61         self.memory[address] = data
62
63     def parse_line(self, line):
64         if line[0] != ':':
65             raise ValueError, "invalid line (%d)" % self.lineno
66         count = int(line[1:3], 16)
67         offset = int(line[3:7], 16)
68         type_code = int(line[7:9], 16)
69         data = binascii.unhexlify(line[9:(9+count*2)])
70         check_sum = int(line[(9+count*2):], 16)
71         if check_sum != self.calc_checksum(count, offset, type_code, data):
72             raise ValueError, "invalid checksum (%d)" % self.lineno
73         if type_code == 0x00:
74             self.add_data(count, offset, data)
75             return 0
76         elif type_code == 0x01:
77             return 1
78         elif type_code == 0x04:
79             if count != 2:
80                 raise ValueError, "invalid count (%d): (%d) Expected 2" \
81                     % (self.lineno, count)
82             self.address = ((ord(data[0])&0xff)<<24) + ((ord(data[1])&0xff)<<16)
83             return 0
84         elif type_code == 0x05:
85             if count != 4:
86                 raise ValueError, "invalid count (%d): (%d) Expected 4" \
87                     % (self.lineno, count)
88             self.start_address \
89                 = ((ord(data[0])&0xff)<<24) + ((ord(data[1])&0xff)<<16) \
90                 + ((ord(data[2])&0xff)<<8) + ((ord(data[3])&0xff))
91             return 0
92         else:
93             raise ValueError, "invalid type code (%d): (%d)" \
94                 % (self.lineno, type_code)