3 # Copyright (C) 2010 Michael Buesch <mb@bu3sch.de>
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License version 2
7 # as published by the Free Software Foundation.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
18 def indexToName(index):
19 D11UCODE_NAMETAG_START = 0
20 D11LCN0BSINITVALS24 = 1
22 D11LCN1BSINITVALS24 = 3
24 D11LCN2BSINITVALS24 = 5
26 D11N0ABSINITVALS16 = 7
29 D11UCODE_OVERSIGHT16_MIMO = 10
30 D11UCODE_OVERSIGHT16_MIMOSZ = 11
31 D11UCODE_OVERSIGHT24_LCN = 12
32 D11UCODE_OVERSIGHT24_LCNSZ = 13
33 D11UCODE_OVERSIGHT_BOMMAJOR = 14
34 D11UCODE_OVERSIGHT_BOMMINOR = 15
37 D11UCODE_NAMETAG_START : "start",
38 D11LCN0BSINITVALS24 : "LCN0 bs initvals 24",
39 D11LCN0INITVALS24 : "LCN0 initvals 24",
40 D11LCN1BSINITVALS24 : "LCN1 bs initvals 24",
41 D11LCN1INITVALS24 : "LCN1 initvals 24",
42 D11LCN2BSINITVALS24 : "LCN2 bs initvals 24",
43 D11LCN2INITVALS24 : "LCN2 initvals 24",
44 D11N0ABSINITVALS16 : "N0A bs initvals 16",
45 D11N0BSINITVALS16 : "N0 bs initvals 16",
46 D11N0INITVALS16 : "N0 initvals 16",
47 D11UCODE_OVERSIGHT16_MIMO : "microcode 16 MIMO",
48 D11UCODE_OVERSIGHT16_MIMOSZ : "microcode 16 MIMO size",
49 D11UCODE_OVERSIGHT24_LCN : "microcode 24 LCN",
50 D11UCODE_OVERSIGHT24_LCNSZ : "microcode 24 LCN size",
51 D11UCODE_OVERSIGHT_BOMMAJOR : "bom major",
52 D11UCODE_OVERSIGHT_BOMMINOR : "bom minor",
59 def parseHeader(hdr_data, sortByOffset):
61 for i in range(0, len(hdr_data), 3 * 4):
62 offset = ord(hdr_data[i + 0]) | (ord(hdr_data[i + 1]) << 8) |\
63 (ord(hdr_data[i + 2]) << 16) | (ord(hdr_data[i + 3]) << 24)
64 length = ord(hdr_data[i + 4]) | (ord(hdr_data[i + 5]) << 8) |\
65 (ord(hdr_data[i + 6]) << 16) | (ord(hdr_data[i + 7]) << 24)
66 index = ord(hdr_data[i + 8]) | (ord(hdr_data[i + 9]) << 8) |\
67 (ord(hdr_data[i + 10]) << 16) | (ord(hdr_data[i + 11]) << 24)
69 sections.append( (offset, length, index) )
71 sections.sort(key = lambda x: x[0]) # Sort by offset
73 sections.sort(key = lambda x: x[2]) # Sort by index
76 def generateHeaderData(sections):
78 for section in sections:
79 (offset, length, index) = section
80 data.append(chr(offset & 0xFF))
81 data.append(chr((offset >> 8) & 0xFF))
82 data.append(chr((offset >> 16) & 0xFF))
83 data.append(chr((offset >> 24) & 0xFF))
84 data.append(chr(length & 0xFF))
85 data.append(chr((length >> 8) & 0xFF))
86 data.append(chr((length >> 16) & 0xFF))
87 data.append(chr((length >> 24) & 0xFF))
88 data.append(chr(index & 0xFF))
89 data.append(chr((index >> 8) & 0xFF))
90 data.append(chr((index >> 16) & 0xFF))
91 data.append(chr((index >> 24) & 0xFF))
94 def getSectionByIndex(sections, searchIndex):
95 for section in sections:
96 (offset, length, index) = section
97 if searchIndex == index:
101 def parseHeaderFile(hdr_filepath, sortByOffset=False):
103 hdr_data = file(hdr_filepath, "rb").read()
105 print "Failed to read header file: %s" % e.strerror
107 if len(hdr_data) % (3 * 4) != 0:
108 print "Invalid header file format"
110 return parseHeader(hdr_data, sortByOffset)
112 def dumpInfo(hdr_filepath):
113 sections = parseHeaderFile(hdr_filepath)
116 for section in sections:
117 (offset, length, index) = section
118 print "Index %2d %24s ==> offset:0x%08X length:0x%08X" %\
119 (index, indexToName(index), offset, length)
122 def extractSection(hdr_filepath, bin_filepath, extractIndex, outfilePath):
123 sections = parseHeaderFile(hdr_filepath)
126 section = getSectionByIndex(sections, extractIndex)
128 print "Did not find a section with index %d" % extractIndex
130 (offset, length, index) = section
132 bin_data = file(bin_filepath, "rb").read()
134 print "Failed to read bin file: %s" % e.strerror
137 outfile = file(outfilePath, "wb")
138 outfile.write(bin_data[offset : offset + length])
140 print "Binfile index error."
143 print "Failed to write output file: %s" % e.strerror
147 def mergeSection(hdr_filepath, bin_filepath, mergeIndex, mergefilePath):
148 sections = parseHeaderFile(hdr_filepath, sortByOffset=True)
152 bin_data = file(bin_filepath, "rb").read()
154 print "Failed to read bin file: %s" % e.strerror
157 merge_data = file(mergefilePath, "rb").read()
159 print "Failed to open merge output file: %s" % e.strerror
165 for section in sections:
166 (offset, length, index) = section
167 if index == mergeIndex:
169 print "Confused. Multiple sections with index %d?" % index
172 # We overwrite this section
173 newBin.append(merge_data)
174 newSections.append( (newOffset, len(merge_data), index) )
175 newOffset += len(merge_data)
178 newBin.append(bin_data[offset : offset + length])
180 print "Failed to read input data"
182 newSections.append( (newOffset, length, index) )
185 print "Did not find section with index %d" % mergeIndex
187 newBin = "".join(newBin)
188 newHdr = generateHeaderData(newSections)
190 file(bin_filepath, "wb").write(newBin)
191 file(hdr_filepath, "wb").write(newHdr)
193 print "Failed to write bin or header file: %s" % e.strerror
198 print "BRCM80211 firmware converter tool"
200 print "Usage: %s [OPTIONS]" % sys.argv[0]
202 print " -H|--header FILE Use FILE as header file"
203 print " -B|--bin FILE Use FILE as bin file"
206 print " -d|--dump Dump general information"
207 print " -x|--extract INDEX:FILE Extract the section with index INDEX to FILE"
208 print " -m|--merge INDEX:FILE Merges FILE into the bin file stream at INDEX"
209 print " A Merge modifies the files specified in -H and -B"
211 print " -h|--help Print this help text"
222 (opts, args) = getopt.getopt(sys.argv[1:],
224 [ "help", "header=", "bin=", "dump", "extract=", "merge=", ])
225 except getopt.GetoptError:
229 if o in ("-h", "--help"):
232 if o in ("-H", "--header"):
234 if o in ("-B", "--bin"):
236 if o in ("-d", "--dump"):
238 if o in ("-x", "--extract"):
239 opt_action = "extract"
242 opt_index = int(v[0])
244 except IndexError, ValueError:
245 print "Invalid -x|--extract index number\n"
248 if o in ("-m", "--merge"):
252 opt_index = int(v[0])
254 except IndexError, ValueError:
255 print "Invalid -m|--merge index and/or merge file name\n"
259 print "No action specified\n"
262 if opt_action == "dump":
264 print "No header file specified\n"
267 return dumpInfo(opt_header)
268 elif opt_action == "extract":
269 if not opt_header or not opt_bin:
270 print "No header or bin file specified\n"
273 return extractSection(opt_header, opt_bin, opt_index, opt_outfile)
274 elif opt_action == "merge":
275 if not opt_header or not opt_bin:
276 print "No header or bin file specified\n"
279 return mergeSection(opt_header, opt_bin, opt_index, opt_mergefile)
282 if __name__ == "__main__":