summaryrefslogtreecommitdiffstats
path: root/libtoprammer/ihex.py
blob: c837d855193df33eedc9b2d307769ce8f349e11d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
"""
#    TOP2049 Open Source programming suite
#
#    IHEX file layout
#
#    Copyright (c) 2013 Michael Buesch <m@bues.ch>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License along
#    with this program; if not, write to the Free Software Foundation, Inc.,
#    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""

from util import *


class AddressRange(object):
	"""Address range type."""

	def __init__(self, startAddress = 0, endAddress = -1):
		# endAddress of -1 means "to the end of the image".
		assert(startAddress >= 0)
		assert(endAddress >= -1)
		assert(startAddress <= endAddress or endAddress == -1)
		self.startAddress = startAddress
		self.endAddress = endAddress

	def overlaps(self, other):
		"""Check if self overlaps with other."""
		if (other.startAddress <= self.endAddress or self.endAddress < 0) and\
		   (other.endAddress >= self.startAddress or other.endAddress < 0):
			return True
		return False

	@classmethod
	def overlapsAny(cls, addressRangeList, addressRange):
		"""Check if 'addressRange' overlaps with any
		AddressRange in 'addressRangeList'"""
		return any(r.overlaps(addressRange) for r in addressRangeList)

class IHexInterpreter(object):
	"""Generic interpreter for a cumulative IHEX file.
	This class must be subclassed to be usable."""

	# Definition of the address ranges.
	# For each memory area type, several possible address
	# ranges can be defined. They are tried first to last.
	# Override these in the subclass.
	progmemRanges = None
	eepromRanges = None
	fuseRanges = None
	lockRanges = None
	ramRanges = None
	uilRanges = None

	# Definition of default memory values.
	# Override these in the subclass.
	progmemDefaultBytes = b"\xFF"
	eepromDefaultBytes = b"\xFF"
	fuseDefaultBytes = b"\xFF"
	lockDefaultBytes = b"\xFF"
	ramDefaultBytes = b"\x00"
	uilDefaultBytes = b"\xFF"

	def __init__(self):
		self.__ihexData = None
		self.__progmem = None
		self.__eeprom = None
		self.__fusebits = None
		self.__lockbits = None
		self.__ram = None
		self.__uil = None

	def cumulativeSupported(self):
		"""Returns True, if parsing of cumulative IHEX files
		is supported by the implementation."""
		return self.progmemRanges or\
		       self.eepromRanges or\
		       self.fuseRanges or\
		       self.lockRanges or\
		       self.ramRanges or\
		       self.uilRanges

	def interpret(self, ihexData):
		self.__ihexData = ihexData
		usedRanges = []
		self.__progmem = self.tryExtract(ihexData, self.progmemDefaultBytes,
						 usedRanges, self.progmemRanges)
		self.__eeprom = self.tryExtract(ihexData, self.eepromDefaultBytes,
						usedRanges, self.eepromRanges)
		self.__fusebits = self.tryExtract(ihexData, self.fuseDefaultBytes,
						  usedRanges, self.fuseRanges)
		self.__lockbits = self.tryExtract(ihexData, self.lockDefaultBytes,
						  usedRanges, self.lockRanges)
		self.__ram = self.tryExtract(ihexData, self.ramDefaultBytes,
					     usedRanges, self.ramRanges)
		self.__uil = self.tryExtract(ihexData, self.uilDefaultBytes,
					     usedRanges, self.uilRanges)

	def tryExtract(self, ihexData, defaultBytes, alreadyUsedRanges, tryRanges):
		if not tryRanges:
			return None
		for tryRange in tryRanges:
			if AddressRange.overlapsAny(alreadyUsedRanges, tryRange):
				continue
			image = IO_ihex().toBinary(ihexData,
						   addressRange = tryRange,
						   defaultBytes = defaultBytes)
			if not image:
				continue
			alreadyUsedRanges.append(tryRange)
			return image
		return None

	def getRaw(self, defaultBytes=b"\xFF"):
		return IO_ihex().toBinary(self.__ihexData,
					  defaultBytes = defaultBytes)

	def getProgmem(self, dontInterpretSections=False):
		if dontInterpretSections:
			return self.getRaw(defaultBytes = self.progmemDefaultBytes)
		return self.__progmem

	def getEEPROM(self, dontInterpretSections=False):
		if dontInterpretSections:
			return self.getRaw(defaultBytes = self.eepromDefaultBytes)
		return self.__eeprom

	def getFusebits(self, dontInterpretSections=False):
		if dontInterpretSections:
			return self.getRaw(defaultBytes = self.fuseDefaultBytes)
		return self.__fusebits

	def getLockbits(self, dontInterpretSections=False):
		if dontInterpretSections:
			return self.getRaw(defaultBytes = self.lockDefaultBytes)
		return self.__lockbits

	def getRAM(self, dontInterpretSections=False):
		if dontInterpretSections:
			return self.getRaw(defaultBytes = self.ramDefaultBytes)
		return self.__ram

	def getUIL(self, dontInterpretSections=False):
		if dontInterpretSections:
			return self.getRaw(defaultBytes = self.uilDefaultBytes)
		return self.__uil
bues.ch cgit interface