fwcutter/make: Avoid _DEFAULT_SOURCE warning
[b43-tools.git] / debug / b43-fwdump
1 #!/usr/bin/env python
2 """
3 #  b43 firmware state dumper
4 #
5 #  Copyright (C) 2008 Michael Buesch <m@bues.ch>
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 import re
25
26
27 def usage():
28         print "b43 firmware state dumper"
29         print ""
30         print "Copyright (C) 2008 Michael Buesch <m@bues.ch>"
31         print "Licensed under the GNU/GPL version 3"
32         print ""
33         print "Usage: b43-fwdump [OPTIONS]"
34         print ""
35         print "-h|--help            Print this help text"
36         print "-p|--phy WIPHY       The WIPHY to use. For example phy0."
37         print "                     Can be omitted, if there is only one device in the system."
38         print "-b|--binary BIN      The firmware binary. This is required for"
39         print "                     an instruction dump."
40         print "-d|--dasmopt OPT     Additional options to the disassembler."
41         print "-s|--shm             Also dump SHM."
42         print "-S|--shmbin          Do a binary SHM dump, only."
43         return
44
45 def parseArgs():
46         global phy
47         global binary
48         global dasmopt
49         global dumpShm
50         global dumpShmBin
51
52         phy = None # Autodetect
53         binary = None # No instruction dump
54         dasmopt = ""
55         dumpShm = False
56         dumpShmBin = False
57
58         try:
59                 (opts, args) = getopt.getopt(sys.argv[1:],
60                         "hp:b:d:sS",
61                         [ "help", "phy=", "binary=", "dasmopt=", "shm", "shmbin" ])
62         except getopt.GetoptError:
63                 usage()
64                 sys.exit(1)
65
66         for (o, v) in opts:
67                 if o in ("-h", "--help"):
68                         usage()
69                         sys.exit(0)
70                 if o in ("-p", "--phy"):
71                         phy = v
72                 if o in ("-b", "--binary"):
73                         binary = v
74                 if o in ("-d", "--dasmopt"):
75                         dasmopt = v
76                 if o in ("-s", "--shm"):
77                         dumpShm = True
78                 if o in ("-S", "--shmbin"):
79                         dumpShmBin = True
80         return
81
82
83 def dump_regs(prefix, regs):
84         if len(regs) >= 10:
85                 template = "%s%02u: %04X  "
86         else:
87                 template = "%s%01u: %04X  "
88         for i in range(0, len(regs)):
89                 if i != 0 and i % 4 == 0:
90                         stdout.write("\n")
91                 stdout.write(template % (prefix, i, regs[i]))
92         stdout.write("\n")
93         return
94
95 def dasmLineIsPC(line, pc):
96         m = re.match(r'.*/\*\s+([0-9a-fA-F]+)\s+\*/.*', line, re.DOTALL)
97         if not m:
98                 return False
99         linePC = int(m.group(1), 16)
100         return pc == linePC
101
102 def makeShortDump(dasm, pc):
103         dasm = dasm.splitlines()
104         i = 0
105         for line in dasm:
106                 if dasmLineIsPC(line, pc):
107                         break
108                 i += 1
109         else:
110                 return "<Could not find PC in the binary>"
111         ret = ""
112         pos = max(i - 8, 0)
113         end = min(i + 8, len(dasm) - 1)
114         while pos != end:
115                 ret += dasm[pos]
116                 if dasmLineIsPC(dasm[pos], pc):
117                         ret += "\t\t<<<<<<<<<<<"
118                 ret += "\n"
119                 pos += 1
120         return ret
121
122 def toAscii(char):
123         if char >= 32 and char <= 126:
124                 return chr(char)
125         return "."
126
127 def main():
128         parseArgs()
129
130         b43 = B43(phy)
131
132         # Fetch the hardware information
133         b43.ucodeStop()
134         gpr = b43.getGprs()
135         lr = b43.getLinkRegs()
136         off = b43.getOffsetRegs()
137         if dumpShm or dumpShmBin:
138                 shm = b43.shmSharedRead()
139         dbg = b43.getPsmDebug()
140         psmcond = b43.getPsmConditions()
141         b43.ucodeStart()
142
143         if dumpShmBin:
144                 # Only do a binary SHM dump
145                 stdout.write(shm)
146                 sys.exit(0)
147
148         print "--- B43 microcode state dump ---"
149         print "PC: %03X  PSM-COND: %04X" % (dbg.getPc(), psmcond)
150         print "Link registers:"
151         dump_regs("lr", lr)
152         print "Offset registers:"
153         dump_regs("off", off)
154         print "General purpose registers:"
155         dump_regs("r", gpr)
156
157         print "Code:"
158         if binary:
159                 try:
160                         bintext = file(binary, "r").read()
161                 except IOError, e:
162                         print "Could not read binary file %s: %s" % (binary, e.strerror)
163                         sys.exit(1)
164                 dasm = Disassembler(bintext, dasmopt + "--paddr").getAsm()
165                 print makeShortDump(dasm, dbg.getPc())
166         else:
167                 print "<No binary supplied. See --binary option>"
168
169         if dumpShm:
170                 print "Shared memory:"
171                 ascii = ""
172                 for i in range(0, len(shm)):
173                         if i % 16 == 0 and i != 0:
174                                 stdout.write("  " + ascii + "\n")
175                                 ascii = ""
176                         if i % 16 == 0:
177                                 stdout.write("0x%04X:  " % i)
178                         c = ord(shm[i])
179                         stdout.write("%02X" % c)
180                         if (i % 2 != 0):
181                                 stdout.write(" ")
182                         ascii += toAscii(c)
183                 stdout.write("  " + ascii + "\n")
184         return
185
186
187 try:
188         main()
189 except B43Exception:
190         sys.exit(1)