#!/usr/bin/env python """ # Copyright (C) 2010 Michael Buesch # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 # as published by the Free Software Foundation. # # 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. """ import sys import getopt def indexToName(index): D11UCODE_NAMETAG_START = 0 D11LCN0BSINITVALS24 = 1 D11LCN0INITVALS24 = 2 D11LCN1BSINITVALS24 = 3 D11LCN1INITVALS24 = 4 D11LCN2BSINITVALS24 = 5 D11LCN2INITVALS24 = 6 D11N0ABSINITVALS16 = 7 D11N0BSINITVALS16 = 8 D11N0INITVALS16 = 9 D11UCODE_OVERSIGHT16_MIMO = 10 D11UCODE_OVERSIGHT16_MIMOSZ = 11 D11UCODE_OVERSIGHT24_LCN = 12 D11UCODE_OVERSIGHT24_LCNSZ = 13 D11UCODE_OVERSIGHT_BOMMAJOR = 14 D11UCODE_OVERSIGHT_BOMMINOR = 15 namemap = { D11UCODE_NAMETAG_START : "start", D11LCN0BSINITVALS24 : "LCN0 bs initvals 24", D11LCN0INITVALS24 : "LCN0 initvals 24", D11LCN1BSINITVALS24 : "LCN1 bs initvals 24", D11LCN1INITVALS24 : "LCN1 initvals 24", D11LCN2BSINITVALS24 : "LCN2 bs initvals 24", D11LCN2INITVALS24 : "LCN2 initvals 24", D11N0ABSINITVALS16 : "N0A bs initvals 16", D11N0BSINITVALS16 : "N0 bs initvals 16", D11N0INITVALS16 : "N0 initvals 16", D11UCODE_OVERSIGHT16_MIMO : "microcode 16 MIMO", D11UCODE_OVERSIGHT16_MIMOSZ : "microcode 16 MIMO size", D11UCODE_OVERSIGHT24_LCN : "microcode 24 LCN", D11UCODE_OVERSIGHT24_LCNSZ : "microcode 24 LCN size", D11UCODE_OVERSIGHT_BOMMAJOR : "bom major", D11UCODE_OVERSIGHT_BOMMINOR : "bom minor", } try: return namemap[index] except KeyError: return "Unknown" def parseHeader(hdr_data): sections = [] for i in range(0, len(hdr_data), 3 * 4): offset = ord(hdr_data[i + 0]) | (ord(hdr_data[i + 1]) << 8) |\ (ord(hdr_data[i + 2]) << 16) | (ord(hdr_data[i + 3]) << 24) length = ord(hdr_data[i + 4]) | (ord(hdr_data[i + 5]) << 8) |\ (ord(hdr_data[i + 6]) << 16) | (ord(hdr_data[i + 7]) << 24) index = ord(hdr_data[i + 8]) | (ord(hdr_data[i + 9]) << 8) |\ (ord(hdr_data[i + 10]) << 16) | (ord(hdr_data[i + 11]) << 24) sections.append( (offset, length, index) ) sections.sort(key = lambda x: x[2]) # Sort by index return sections def getSectionByIndex(sections, searchIndex): for section in sections: (offset, length, index) = section if searchIndex == index: return section return None def parseHeaderFile(hdr_filepath): try: hdr_data = file(hdr_filepath, "rb").read() except (IOError), e: print "Failed to read header file: %s" % e.strerror return None if len(hdr_data) % (3 * 4) != 0: print "Invalid header file format" return None return parseHeader(hdr_data) def dumpInfo(hdr_filepath): sections = parseHeaderFile(hdr_filepath) if not sections: return 1 for section in sections: (offset, length, index) = section print "Index %2d %24s ==> offset:0x%08X length:0x%08X" %\ (index, indexToName(index), offset, length) return 0 def extractSection(hdr_filepath, bin_filepath, extractIndex, outfile): sections = parseHeaderFile(hdr_filepath) if not sections: return 1 section = getSectionByIndex(sections, extractIndex) if not section: print "Did not find a section with index %d" % extractIndex return 1 (offset, length, index) = section try: bin_data = file(bin_filepath, "rb").read() except (IOError), e: print "Failed to read bin file: %s" % e.strerror return 1 try: outfile.write(bin_data[offset : offset + length]) except IndexError: print "Binfile index error." return 1 return 0 def usage(): print "BRCM80211 firmware converter tool" print "" print "Usage: %s [OPTIONS]" % sys.argv[0] print "" print " -H|--header FILE Use FILE as input header file" print " -B|--bin FILE Use FILE as bin file" print " -O|--outfile FILE Use FILE as output file. If not set, stdout is used." print "" print "Actions:" print " -d|--dump Dump general information" print " -x|--extract INDEX Extract the section with index INDEX" print "" print " -h|--help Print this help text" def main(): opt_header = None opt_bin = None opt_action = None opt_index = None opt_outfile = sys.stdout try: (opts, args) = getopt.getopt(sys.argv[1:], "hH:B:O:dx:", [ "help", "header=", "bin=", "outfile=", "dump", "extract=", ]) except getopt.GetoptError: usage() return 1 for (o, v) in opts: if o in ("-h", "--help"): usage() return 0; if o in ("-H", "--header"): opt_header = v if o in ("-B", "--bin"): opt_bin = v if o in ("-O", "--outfile"): try: opt_outfile = file(v, "wb") except (IOError), e: print "Failed to open output file: %s" % e.strerror return 1 if o in ("-d", "--dump"): opt_action = "dump" if o in ("-x", "--extract"): opt_action = "extract" try: opt_index = int(v) except ValueError: print "Invalid -x|--extract index number\n" usage() return 1 if not opt_action: print "No action specified\n" usage() return 1 if opt_action == "dump": if not opt_header: print "No header file specified\n" usage() return 1 return dumpInfo(opt_header) elif opt_action == "extract": if not opt_header or not opt_bin: print "No header or bin file specified\n" usage() return 1 return extractSection(opt_header, opt_bin, opt_index, opt_outfile) return 1 if __name__ == "__main__": sys.exit(main())