summaryrefslogtreecommitdiffstats
path: root/bitfile.py
blob: ae0a5e02f67d2e9a554b8ff84eb629c8e54f99c6 (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
"""
#    *.BIT file parser
#
#    Copyright (c) 2009 Michael Buesch <mb@bu3sch.de>
#
#    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.
"""

import sys

class BitfileException(Exception): pass

class Bitfile:
	# Magic header
	MAGIC		= "\x00\x09\x0f\xf0\x0f\xf0\x0f\xf0\x0f\xf0\x00\x00\x01"
	# Field IDs
	FIELD_SRCFILE	= 0x61
	FIELD_FPGA	= 0x62
	FIELD_DATE	= 0x63
	FIELD_TIME	= 0x64
	FIELD_PAYLOAD	= 0x65

	def __init__(self):
		self.srcfile = ""
		self.fpga = ""
		self.date = ""
		self.time = ""
		self.payload = ""

	def getSrcFile(self):
		return self.srcfile

	def getFPGA(self):
		return self.fpga

	def getDate(self):
		return self.date

	def getTime(self):
		return self.time

	def getPayload(self):
		return self.payload

	def parseFile(self, filename):
		try:
			data = file(filename, "rb").read()
		except (IOError), e:
			raise BitfileException("Failed to read \"" + filename + "\": " + e.strerror)
		self.__parse(data)

	def __parse(self, data):
		try:
			magic = data[0:len(self.MAGIC)]
			if magic != self.MAGIC:
				raise BitfileException("Invalid magic header")
			i = len(self.MAGIC)
			while i < len(data):
				i += self.__parseNextField(data, i)
		except (IndexError), e:
			raise BitfileException("Failed to parse BIT file")
		if not self.fpga:
			raise BitfileException("No FPGA ID string found")
		if not self.payload:
			raise BitfileException("No payload found")

	def __parseNextField(self, data, i):
		fieldId = ord(data[i + 0])
		if (fieldId == self.FIELD_SRCFILE):
			data = self.__parse16bitField(data, i + 1)
			self.srcfile = data.strip().strip("\x00")
			return len(data) + 3
		if (fieldId == self.FIELD_FPGA):
			data = self.__parse16bitField(data, i + 1)
			self.fpga = data.strip().strip("\x00")
			return len(data) + 3
		if (fieldId == self.FIELD_DATE):
			data = self.__parse16bitField(data, i + 1)
			self.date = data.strip().strip("\x00")
			return len(data) + 3
		if (fieldId == self.FIELD_TIME):
			data = self.__parse16bitField(data, i + 1)
			self.time = data.strip().strip("\x00")
			return len(data) + 3
		if (fieldId == self.FIELD_PAYLOAD):
			self.payload = self.__parse32bitField(data, i + 1)
			return len(self.payload) + 5
		raise BitfileException("Found unknown data field 0x%02X" % fieldId)

	def __parse16bitField(self, data, i):
		fieldLen = (ord(data[i + 0]) << 8) | ord(data[i + 1])
		return data[i + 2 : i + 2 + fieldLen]

	def __parse32bitField(self, data, i):
		fieldLen = (ord(data[i + 0]) << 24) | (ord(data[i + 1]) << 16) |\
			   (ord(data[i + 2]) << 8) | ord(data[i + 3])
		return data[i + 4 : i + 4 + fieldLen]

if __name__ == "__main__":
	b = Bitfile()
	b.parseFile(sys.argv[1])
	print "Source file", b.getSrcFile()
	print "FPGA", b.getFPGA()
	print "Date", b.getDate()
	print "Time", b.getTime()
bues.ch cgit interface