Implement firmware state dumper
[b43-tools.git] / debug / b43-fwdump
1 #!/usr/bin/env python
2 """
3 #  b43 firmware state dumper
4 #
5 #  Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
6 #
7 #  This program is free software: you can redistribute it and/or modify
8 #  it under the terms of the GNU General Public License version 3
9 #  as published by the Free Software Foundation.
10 #
11 #  This program is distributed in the hope that it will be useful,
12 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 #  GNU General Public License for more details.
15 #
16 #  You should have received a copy of the GNU General Public License
17 #  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 """
19
20 import getopt
21 from libb43 import *
22 from sys import stdout
23 from tempfile import *
24
25
26 def usage():
27         print "b43 firmware state dumper"
28         print ""
29         print "Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>"
30         print "Licensed under the GNU/GPL version 3"
31         print ""
32         print "Usage: b43-fwdump [OPTIONS]"
33         print ""
34         print "-h|--help            Print this help text"
35         print "-p|--phy PHY         The PHY to use. For example phy0"
36         print "-b|--binary BIN      The firmware binary. This is required for"
37         print "                     an instruction dump."
38         print "-d|--dasmopt OPT     Additional options to the disassembler."
39         return
40
41 def parseArgs():
42         global phy
43         global binary
44         global dasmopt
45
46         phy = None # Autodetect
47         binary = None # No instruction dump
48         dasmopt = ""
49
50         try:
51                 (opts, args) = getopt.getopt(sys.argv[1:],
52                         "hp:b:d:",
53                         [ "help", "phy=", "binary=", "dasmopt=" ])
54         except getopt.GetoptError:
55                 usage()
56                 sys.exit(1)
57
58         for (o, v) in opts:
59                 if o in ("-h", "--help"):
60                         usage()
61                         sys.exit(0)
62                 if o in ("-p", "--phy"):
63                         phy = v
64                 if o in ("-b", "--binary"):
65                         binary = v
66                 if o in ("-d", "--dasmopt"):
67                         dasmopt = v
68         return
69
70
71 def dump_regs(prefix, regs):
72         if len(regs) >= 10:
73                 template = "%s%02u: %04X  "
74         else:
75                 template = "%s%01u: %04X  "
76         for i in range(0, len(regs)):
77                 if i != 0 and i % 4 == 0:
78                         stdout.write("\n")
79                 stdout.write(template % (prefix, i, regs[i]))
80         stdout.write("\n")
81         return
82
83 def disassembleText(text):
84         input = NamedTemporaryFile()
85         output = NamedTemporaryFile()
86
87         input.write(text)
88         input.flush()
89         os.system("b43-dasm %s %s %s --paddr" % (input.name, dasmopt, output.name))
90
91         return output.read()
92
93 def makeShortDump(dasm, pc):
94         dasm = dasm.splitlines()
95         i = 0
96         for line in dasm:
97                 if "/* %03X */" % pc in line:
98                         break
99                 i += 1
100         if i >= len(dasm):
101                 return "<Could not find PC in the binary>"
102         ret = ""
103         pos = max(i - 8, 0)
104         end = min(i + 8, len(dasm) - 1)
105         while pos != end:
106                 ret += dasm[pos]
107                 if "/* %03X */" % pc in dasm[pos]:
108                         ret += "\t\t<<<<<<<<<<<"
109                 ret += "\n"
110                 pos += 1
111         return ret
112
113 def main():
114         parseArgs()
115
116         b43 = B43(phy)
117
118         # Fetch the hardware information
119         b43.ucodeStop()
120         gpr = b43.getGprs()
121         lr = b43.getLinkRegs()
122         off = b43.getOffsetRegs()
123         shm = b43.shmSharedRead()
124         dbg = b43.getPsmDebug()
125         psmcond = b43.getPsmConditions()
126         b43.ucodeStart()
127
128         print "--- B43 microcode state dump ---"
129         print "PC: %03X  PSM-COND: %04X" % (dbg.getPc(), psmcond)
130         print "Link registers:"
131         dump_regs("lr", lr)
132         print "Offset registers:"
133         dump_regs("off", off)
134         print "General purpose registers:"
135         dump_regs("r", gpr)
136
137         print "Code:"
138         if binary:
139                 try:
140                         bintext = file(binary, "r").read()
141                 except IOError, e:
142                         print "Could not read binary file %s: %s" % (binary, e.strerror)
143                         sys.exit(1)
144                 dasm = disassembleText(bintext)
145                 print makeShortDump(dasm, dbg.getPc())
146         else:
147                 print "<No binary supplied. See --binary option>"
148         return
149
150
151 try:
152         main()
153 except B43Exception:
154         sys.exit(1)