summaryrefslogtreecommitdiffstats
path: root/firmware/zpu/bin/sbf.py
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/zpu/bin/sbf.py')
-rwxr-xr-xfirmware/zpu/bin/sbf.py134
1 files changed, 134 insertions, 0 deletions
diff --git a/firmware/zpu/bin/sbf.py b/firmware/zpu/bin/sbf.py
new file mode 100755
index 000000000..8e2c868a5
--- /dev/null
+++ b/firmware/zpu/bin/sbf.py
@@ -0,0 +1,134 @@
+#
+# Copyright 2009 Free Software Foundation, Inc.
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+_SBF_MAGIC = 'SBF!'
+_SBF_DONT_EXECUTE = 0x1
+_SBF_MAX_SECTIONS = 14
+_SBF_HEADER_LEN = 128
+
+import struct
+import sys
+from pprint import pprint
+
+def dump_data(f, offset, data):
+ L = len(data) // 4
+ for i in range(L):
+ f.write('%08x: %08x\n' % (offset + 4 * i, struct.unpack('>I', data[4*i:4*(i+1)])[0]))
+ remainder = len(data) - L * 4
+ if remainder != 0:
+ f.write('%08x: ' % (offset + L*4,))
+ i = 0
+ while i < remainder:
+ f.write('%02x' % ((ord(data[L*4 + i]),)))
+ i += 1
+ f.write('\n')
+
+
+
+class sec_desc(object):
+ def __init__(self, target_addr, data):
+ self.target_addr = target_addr
+ self.data = data
+
+ def __repr__(self):
+ #print >>sys.stderr, "target_addr:", self.target_addr
+ #print >>sys.stderr, "data:", self.data
+ return "<sec_desc target_addr=0x%x len=%d>" % (
+ self.target_addr, len(self.data))
+
+
+class header(object):
+ def __init__(self, entry, sections):
+ self.entry = entry
+ self.section = sections
+
+ def dump(self, f):
+ if self.entry == _SBF_DONT_EXECUTE:
+ f.write("Entry: DONT_EXECUTE\n")
+ else:
+ f.write("Entry: 0x%x\n" % (self.entry,))
+ for i in range(len(self.section)):
+ s = self.section[i]
+ f.write("Section[%d]: target_addr = 0x%x length = %d\n" % (i,
+ s.target_addr,
+ len(s.data)))
+ dump_data(f, s.target_addr, s.data)
+
+ #
+ # Returns an iterator. Each yield returns (target_addr, data)
+ #
+ def iterator(self, max_piece=512):
+ for s in self.section:
+ offset = 0
+ L = len(s.data)
+ while offset < L:
+ n = min(max_piece, L - offset)
+ yield (s.target_addr + offset,
+ s.data[offset:offset+n])
+ offset += n
+
+
+
+def read_sbf(input_file):
+ """Parse an SBF file"""
+
+ f = input_file.read(_SBF_HEADER_LEN)
+ #if len(f) < _SBF_HEADER_LEN or not f.startswith(_SBF_MAGIC):
+ #raise ValueError, '%s: not an SBF file' % (input_file.name,)
+
+ def extract(i):
+ start = 16+8*i
+ stop = start+8
+ return struct.unpack('>2I', f[start:stop])
+
+ def get_data(ss):
+ L = ss[1]
+ s = input_file.read(L)
+ #if len(s) != L:
+ #raise ValueError, '%s: file is too short' % (input_file.name(),)
+ return s
+
+ (magic, entry, nsections, reserved) = struct.unpack('>4s3I', f[0:16])
+ assert nsections <= _SBF_MAX_SECTIONS
+ descs = [extract(i) for i in range(nsections)]
+ #pprint(descs, sys.stderr)
+ data = map(get_data, descs)
+ secs = map(lambda ss, data: sec_desc(ss[0], data), descs, data)
+ return header(entry, secs)
+
+
+def write_sbf(output_file, sbf_header):
+ assert(len(sbf_header.section) <= _SBF_MAX_SECTIONS)
+ sbf_header.nsections = len(sbf_header.section)
+ f = output_file
+
+ # write the file header
+ f.write(struct.pack('>4s3I', _SBF_MAGIC, sbf_header.entry, sbf_header.nsections, 0))
+
+ # write the section headers
+ for i in range(sbf_header.nsections):
+ f.write(struct.pack('>2I',
+ sbf_header.section[i].target_addr,
+ len(sbf_header.section[i].data)))
+ for i in range(_SBF_MAX_SECTIONS - sbf_header.nsections):
+ f.write(struct.pack('>2I', 0, 0))
+
+ # write the section data
+ for i in range(sbf_header.nsections):
+ f.write(sbf_header.section[i].data)
+
+ return True