Initial import
[sst_elf_firmware_convert.git] / baytrail_sst_firmware_parse.py
1 #!/usr/bin/env python
2 #
3 # baytrail_sst_firmware_parse.py - parse an SST firmware file
4 #
5 # Copyright (C) 2015  Antonio Ospite <ao2@ao2.it>
6 #
7 # This program is free software. It comes without any warranty, to
8 # the extent permitted by applicable law. You can redistribute it
9 # and/or modify it under the terms of the Do What The Fuck You Want
10 # To Public License, Version 2, as published by Sam Hocevar. See
11 # http://sam.zoy.org/wtfpl/COPYING for more details.
12
13 import os
14 import sys
15 import struct
16
17 FIRMWARE_HEADER_SIZE = 32
18 MODULE_HEADER_SIZE = 20
19
20
21 def get(f, fmt, offset=None):
22     if offset:
23         f.seek(offset)
24
25     length = struct.calcsize(fmt)
26     data = f.read(length)
27     value = struct.unpack_from(fmt, data)
28     return value[0]
29
30
31 def sst_firmware_parse(firmware_file_name):
32
33     f = open(firmware_file_name, "rb")
34     filesize = os.path.getsize(firmware_file_name)
35
36     signature = get(f, "4s")
37     if signature != "$SST":
38         print "Invalid file"
39         return False
40
41     payload_size = get(f, '<L')
42     print "Payload size:", payload_size
43
44     if (payload_size + FIRMWARE_HEADER_SIZE) != filesize:
45         print "invalid payload size"
46         return False
47
48     num_modules = get(f, '<L')
49     print "Number of modules:", num_modules
50
51     file_format = get(f, '<L')
52     print "File format:", file_format
53
54     # reserved fields
55     get(f, '<L')
56     get(f, '<L')
57     get(f, '<L')
58     get(f, '<L')
59
60     for i in range(0, num_modules):
61         print "\nModule %d" % i
62
63         signature = get(f, "4s")
64         if signature != "$SST":
65             print "Invalid module"
66             return False
67
68         module_size = get(f, '<L')
69         print "module size:", module_size
70
71         if (module_size + MODULE_HEADER_SIZE) != payload_size:
72             print "Invalid module size:"
73             return False
74
75         num_blocks = get(f, '<L')
76         print "Number of blocks:", num_blocks
77
78         block_type = get(f, '<L')
79         print "Block type: ", block_type
80
81         entry_point = get(f, '<L')
82         print "Entry point: 0x%08x" % entry_point
83
84         total_block_size = 0
85         for j in range(0, num_blocks):
86             print "\nBlock %d" % j
87
88             ram_type = get(f, '<L')
89             print "Ram type:", ram_type
90
91             block_size = get(f, '<L')
92             print "Block size: %d (0x%08x)" % (block_size, block_size)
93
94             total_block_size += block_size + 16
95             print "Total block size: %d (0x%08x)" % \
96                 (total_block_size, total_block_size)
97
98             ram_offset = get(f, '<L')
99             print "Ram offset: 0x%08x" % ram_offset
100
101             # reserved
102             get(f, '<L')
103
104             # actual data
105             get(f, "%db" % block_size)
106
107         if total_block_size != module_size:
108             print "Invalid total block size:"
109             return False
110
111     return True
112
113
114 if __name__ == "__main__":
115     filename = sys.argv[1]
116     ret = sst_firmware_parse(filename)
117
118     sys.exit(ret)