brcm80211-fwconv 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. #!/usr/bin/env python
  2. """
  3. # Copyright (C) 2010 Michael Buesch <mb@bu3sch.de>
  4. #
  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.
  8. #
  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.
  13. """
  14. import sys
  15. import getopt
  16. def indexToName(index):
  17. D11UCODE_NAMETAG_START = 0
  18. D11LCN0BSINITVALS24 = 1
  19. D11LCN0INITVALS24 = 2
  20. D11LCN1BSINITVALS24 = 3
  21. D11LCN1INITVALS24 = 4
  22. D11LCN2BSINITVALS24 = 5
  23. D11LCN2INITVALS24 = 6
  24. D11N0ABSINITVALS16 = 7
  25. D11N0BSINITVALS16 = 8
  26. D11N0INITVALS16 = 9
  27. D11UCODE_OVERSIGHT16_MIMO = 10
  28. D11UCODE_OVERSIGHT16_MIMOSZ = 11
  29. D11UCODE_OVERSIGHT24_LCN = 12
  30. D11UCODE_OVERSIGHT24_LCNSZ = 13
  31. D11UCODE_OVERSIGHT_BOMMAJOR = 14
  32. D11UCODE_OVERSIGHT_BOMMINOR = 15
  33. namemap = {
  34. D11UCODE_NAMETAG_START : "start",
  35. D11LCN0BSINITVALS24 : "LCN0 bs initvals 24",
  36. D11LCN0INITVALS24 : "LCN0 initvals 24",
  37. D11LCN1BSINITVALS24 : "LCN1 bs initvals 24",
  38. D11LCN1INITVALS24 : "LCN1 initvals 24",
  39. D11LCN2BSINITVALS24 : "LCN2 bs initvals 24",
  40. D11LCN2INITVALS24 : "LCN2 initvals 24",
  41. D11N0ABSINITVALS16 : "N0A bs initvals 16",
  42. D11N0BSINITVALS16 : "N0 bs initvals 16",
  43. D11N0INITVALS16 : "N0 initvals 16",
  44. D11UCODE_OVERSIGHT16_MIMO : "microcode 16 MIMO",
  45. D11UCODE_OVERSIGHT16_MIMOSZ : "microcode 16 MIMO size",
  46. D11UCODE_OVERSIGHT24_LCN : "microcode 24 LCN",
  47. D11UCODE_OVERSIGHT24_LCNSZ : "microcode 24 LCN size",
  48. D11UCODE_OVERSIGHT_BOMMAJOR : "bom major",
  49. D11UCODE_OVERSIGHT_BOMMINOR : "bom minor",
  50. }
  51. try:
  52. return namemap[index]
  53. except KeyError:
  54. return "Unknown"
  55. def parseHeader(hdr_data, sortByOffset):
  56. sections = []
  57. for i in range(0, len(hdr_data), 3 * 4):
  58. offset = ord(hdr_data[i + 0]) | (ord(hdr_data[i + 1]) << 8) |\
  59. (ord(hdr_data[i + 2]) << 16) | (ord(hdr_data[i + 3]) << 24)
  60. length = ord(hdr_data[i + 4]) | (ord(hdr_data[i + 5]) << 8) |\
  61. (ord(hdr_data[i + 6]) << 16) | (ord(hdr_data[i + 7]) << 24)
  62. index = ord(hdr_data[i + 8]) | (ord(hdr_data[i + 9]) << 8) |\
  63. (ord(hdr_data[i + 10]) << 16) | (ord(hdr_data[i + 11]) << 24)
  64. sections.append( (offset, length, index) )
  65. if sortByOffset:
  66. sections.sort(key = lambda x: x[0]) # Sort by offset
  67. else:
  68. sections.sort(key = lambda x: x[2]) # Sort by index
  69. return sections
  70. def generateHeaderData(sections):
  71. data = []
  72. for section in sections:
  73. (offset, length, index) = section
  74. data.append(chr(offset & 0xFF))
  75. data.append(chr((offset >> 8) & 0xFF))
  76. data.append(chr((offset >> 16) & 0xFF))
  77. data.append(chr((offset >> 24) & 0xFF))
  78. data.append(chr(length & 0xFF))
  79. data.append(chr((length >> 8) & 0xFF))
  80. data.append(chr((length >> 16) & 0xFF))
  81. data.append(chr((length >> 24) & 0xFF))
  82. data.append(chr(index & 0xFF))
  83. data.append(chr((index >> 8) & 0xFF))
  84. data.append(chr((index >> 16) & 0xFF))
  85. data.append(chr((index >> 24) & 0xFF))
  86. return "".join(data)
  87. def getSectionByIndex(sections, searchIndex):
  88. for section in sections:
  89. (offset, length, index) = section
  90. if searchIndex == index:
  91. return section
  92. return None
  93. def parseHeaderFile(hdr_filepath, sortByOffset=False):
  94. try:
  95. hdr_data = file(hdr_filepath, "rb").read()
  96. except (IOError), e:
  97. print "Failed to read header file: %s" % e.strerror
  98. return None
  99. if len(hdr_data) % (3 * 4) != 0:
  100. print "Invalid header file format"
  101. return None
  102. return parseHeader(hdr_data, sortByOffset)
  103. def dumpInfo(hdr_filepath):
  104. sections = parseHeaderFile(hdr_filepath)
  105. if not sections:
  106. return 1
  107. for section in sections:
  108. (offset, length, index) = section
  109. print "Index %2d %24s ==> offset:0x%08X length:0x%08X" %\
  110. (index, indexToName(index), offset, length)
  111. return 0
  112. def extractSection(hdr_filepath, bin_filepath, extractIndex, outfilePath):
  113. sections = parseHeaderFile(hdr_filepath)
  114. if not sections:
  115. return 1
  116. section = getSectionByIndex(sections, extractIndex)
  117. if not section:
  118. print "Did not find a section with index %d" % extractIndex
  119. return 1
  120. (offset, length, index) = section
  121. try:
  122. bin_data = file(bin_filepath, "rb").read()
  123. except (IOError), e:
  124. print "Failed to read bin file: %s" % e.strerror
  125. return 1
  126. try:
  127. outfile = file(outfilePath, "wb")
  128. outfile.write(bin_data[offset : offset + length])
  129. except IndexError:
  130. print "Binfile index error."
  131. return 1
  132. except (IOError), e:
  133. print "Failed to write output file: %s" % e.strerror
  134. return 1
  135. return 0
  136. def mergeSection(hdr_filepath, bin_filepath, mergeIndex, mergefilePath):
  137. sections = parseHeaderFile(hdr_filepath, sortByOffset=True)
  138. if not sections:
  139. return 1
  140. try:
  141. bin_data = file(bin_filepath, "rb").read()
  142. except (IOError), e:
  143. print "Failed to read bin file: %s" % e.strerror
  144. return 1
  145. try:
  146. merge_data = file(mergefilePath, "rb").read()
  147. except (IOError), e:
  148. print "Failed to open merge output file: %s" % e.strerror
  149. return 1
  150. newBin = []
  151. newSections = []
  152. newOffset = 0
  153. foundIt = False
  154. for section in sections:
  155. (offset, length, index) = section
  156. if index == mergeIndex:
  157. if foundIt:
  158. print "Confused. Multiple sections with index %d?" % index
  159. return 1
  160. foundIt = True
  161. # We overwrite this section
  162. newBin.append(merge_data)
  163. newSections.append( (newOffset, len(merge_data), index) )
  164. newOffset += len(merge_data)
  165. else:
  166. try:
  167. newBin.append(bin_data[offset : offset + length])
  168. except IndexError:
  169. print "Failed to read input data"
  170. return 1
  171. newSections.append( (newOffset, length, index) )
  172. newOffset += length
  173. if not foundIt:
  174. print "Did not find section with index %d" % mergeIndex
  175. return 1
  176. newBin = "".join(newBin)
  177. newHdr = generateHeaderData(newSections)
  178. try:
  179. file(bin_filepath, "wb").write(newBin)
  180. file(hdr_filepath, "wb").write(newHdr)
  181. except (IOError), e:
  182. print "Failed to write bin or header file: %s" % e.strerror
  183. return 1
  184. return 0
  185. def usage():
  186. print "BRCM80211 firmware converter tool"
  187. print ""
  188. print "Usage: %s [OPTIONS]" % sys.argv[0]
  189. print ""
  190. print " -H|--header FILE Use FILE as header file"
  191. print " -B|--bin FILE Use FILE as bin file"
  192. print ""
  193. print "Actions:"
  194. print " -d|--dump Dump general information"
  195. print " -x|--extract INDEX:FILE Extract the section with index INDEX to FILE"
  196. print " -m|--merge INDEX:FILE Merges FILE into the bin file stream at INDEX"
  197. print " A Merge modifies the files specified in -H and -B"
  198. print ""
  199. print " -h|--help Print this help text"
  200. def main():
  201. opt_header = None
  202. opt_bin = None
  203. opt_action = None
  204. opt_index = None
  205. opt_outfile = None
  206. opt_mergefile = None
  207. try:
  208. (opts, args) = getopt.getopt(sys.argv[1:],
  209. "hH:B:dx:m:",
  210. [ "help", "header=", "bin=", "dump", "extract=", "merge=", ])
  211. except getopt.GetoptError:
  212. usage()
  213. return 1
  214. for (o, v) in opts:
  215. if o in ("-h", "--help"):
  216. usage()
  217. return 0;
  218. if o in ("-H", "--header"):
  219. opt_header = v
  220. if o in ("-B", "--bin"):
  221. opt_bin = v
  222. if o in ("-d", "--dump"):
  223. opt_action = "dump"
  224. if o in ("-x", "--extract"):
  225. opt_action = "extract"
  226. try:
  227. v = v.split(':')
  228. opt_index = int(v[0])
  229. opt_outfile = v[1]
  230. except IndexError, ValueError:
  231. print "Invalid -x|--extract index number\n"
  232. usage()
  233. return 1
  234. if o in ("-m", "--merge"):
  235. opt_action = "merge"
  236. try:
  237. v = v.split(':')
  238. opt_index = int(v[0])
  239. opt_mergefile = v[1]
  240. except IndexError, ValueError:
  241. print "Invalid -m|--merge index and/or merge file name\n"
  242. usage()
  243. return 1
  244. if not opt_action:
  245. print "No action specified\n"
  246. usage()
  247. return 1
  248. if opt_action == "dump":
  249. if not opt_header:
  250. print "No header file specified\n"
  251. usage()
  252. return 1
  253. return dumpInfo(opt_header)
  254. elif opt_action == "extract":
  255. if not opt_header or not opt_bin:
  256. print "No header or bin file specified\n"
  257. usage()
  258. return 1
  259. return extractSection(opt_header, opt_bin, opt_index, opt_outfile)
  260. elif opt_action == "merge":
  261. if not opt_header or not opt_bin:
  262. print "No header or bin file specified\n"
  263. usage()
  264. return 1
  265. return mergeSection(opt_header, opt_bin, opt_index, opt_mergefile)
  266. return 1
  267. if __name__ == "__main__":
  268. sys.exit(main())