X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=debug%2Flibb43.py;h=c8b953372a18ba2bedb2f76fbd22e2181b486f9d;hb=HEAD;hp=00da13bfced95788004f3820cb057f533f9bdf3f;hpb=e41dd6db735d02338c1d5bb6ae84d3b492c37fc4;p=b43-tools.git diff --git a/debug/libb43.py b/debug/libb43.py index 00da13b..c8b9533 100644 --- a/debug/libb43.py +++ b/debug/libb43.py @@ -1,7 +1,7 @@ """ # b43 debugging library # -# Copyright (C) 2008 Michael Buesch +# Copyright (C) 2008-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 3 @@ -19,7 +19,7 @@ import sys import os import re -import md5 +import hashlib from tempfile import * @@ -60,7 +60,9 @@ class B43PsmDebug: class B43: - def __init__(self, phy): + """Hardware access layer. This accesses the hardware through the debugfs interface.""" + + def __init__(self, phy=None): debugfs_path = self.__debugfs_find() # Construct the debugfs b43 path to the device @@ -69,7 +71,11 @@ class B43: b43_path += phy else: # Get the PHY. - phys = os.listdir(b43_path) + try: + phys = os.listdir(b43_path) + except OSError: + print "Could not find B43's debugfs directory: %s" % b43_path + raise B43Exception if not phys: print "Could not find any b43 device" raise B43Exception @@ -337,7 +343,7 @@ class TextPatcher: self.deleted = False def __init__(self, text, expected_md5sum): - sum = md5.md5(text).hexdigest() + sum = hashlib.md5(text).hexdigest() if sum != expected_md5sum: print "Patcher: The text does not match the expected MD5 sum" print "Expected: " + expected_md5sum @@ -388,3 +394,305 @@ class TextPatcher: self.lines.insert(index, TextPatcher.TextLine(-1, l)) index += 1 +class B43SymbolicSpr: + """This class converts numeric SPR names into symbolic SPR names.""" + + def __init__(self, header_file): + """The passed header_file parameter is a file path to the + assembly file containing the symbolic SPR definitions.""" + try: + defs = file(header_file).readlines() + except IOError, e: + print "B43SymbolicSpr: Could not read %s: %s" % (e.filename, e.strerror) + B43Exception + # Parse the definitions + self.spr_names = { } + r = re.compile(r"#define\s+(\w+)\s+(spr[a-fA-F0-9]+)") + for line in defs: + m = r.match(line) + if not m: + continue # unknown line + name = m.group(1) + offset = m.group(2) + self.spr_names[offset.lower()] = name + + def get(self, spr): + """Get the symbolic name for an SPR. The spr parameter + must be a string like "sprXXX", where XXX is a hex number.""" + try: + spr = self.spr_names[spr.lower()] + except KeyError: + pass # Symbol not found. Return numeric name. + return spr + + def getRaw(self, spr_hexnumber): + """Get the symbolic name for an SPR. The spr_hexnumber + parameter is the hexadecimal number for the SPR.""" + return self.get("spr%03X" % spr_hexnumber) + +class B43SymbolicShm: + """This class converts numeric SHM offsets into symbolic SHM names.""" + + def __init__(self, header_file): + """The passed header_file parameter is a file path to the + assembly file containing the symbolic SHM definitions.""" + try: + defs = file(header_file).readlines() + except IOError, e: + print "B43SymbolicShm: Could not read %s: %s" % (e.filename, e.strerror) + raise B43Exception + # Parse the definitions + self.shm_names = { } + in_abi_section = False + r = re.compile(r"#define\s+(\w+)\s+SHM\((\w+)\).*") + for line in defs: + if line.startswith("/* BEGIN ABI"): + in_abi_section = True + if line.startswith("/* END ABI"): + in_abi_section = False + if not in_abi_section: + continue # Only parse ABI definitions + m = r.match(line) + if not m: + continue # unknown line + name = m.group(1) + offset = int(m.group(2), 16) + offset /= 2 + self.shm_names[offset] = name + + def get(self, shm_wordoffset): + """Get the symbolic name for an SHM offset.""" + try: + sym = self.shm_names[shm_wordoffset] + except KeyError: + # Symbol not found. Return numeric name. + sym = "0x%03X" % shm_wordoffset + return sym + +class B43SymbolicCondition: + """This class converts numeric External Conditions into symbolic names.""" + + def __init__(self, header_file): + """The passed header_file parameter is a file path to the + assembly file containing the symbolic condition definitions.""" + try: + defs = file(header_file).readlines() + except IOError, e: + print "B43SymbolicCondition: Could not read %s: %s" % (e.filename, e.strerror) + raise B43Exception + # Parse the definitions + self.cond_names = { } + r = re.compile(r"#define\s+(\w+)\s+EXTCOND\(\s*(\w+),\s*(\d+)\s*\).*") + for line in defs: + m = r.match(line) + if not m: + continue # unknown line + name = m.group(1) + register = m.group(2) + bit = int(m.group(3)) + if register == "CONDREG_RX": + register = 0 + elif register == "CONDREG_TX": + register = 2 + elif register == "CONDREG_PHY": + register = 3 + elif register == "CONDREG_4": + register = 4 + elif register == "CONDREG_PSM": + continue # No lookup table for this one + elif register == "CONDREG_RCM": + register = 6 + elif register == "CONDREG_7": + register = 7 + else: + continue # unknown register + cond_number = bit | (register << 4) + self.cond_names[cond_number] = name + + def get(self, cond_number): + """Get the symbolic name for an External Condition.""" + register = (cond_number >> 4) & 0x7 + bit = cond_number & 0xF + eoi = ((cond_number & 0x80) != 0) + cond_number &= ~0x80 + if register == 5: # PSM register + return "COND_PSM(%d)" % bit + try: + sym = self.cond_names[cond_number] + except KeyError: + # Symbol not found. Return numeric name. + sym = "0x%02X" % cond_number + if eoi: + sym = "EOI(%s)" % sym + return sym + +class B43AsmLine: + def __init__(self, text): + self.text = text + + def getLine(self): + return self.text + + def __repr__(self): + return self.getLine() + + def isInstruction(self): + return False + +class B43AsmInstruction(B43AsmLine): + def __init__(self, opcode): + self.setOpcode(opcode) + self.clearOperands() + + def getOpcode(self): + return self.opcode + + def setOpcode(self, opcode): + self.opcode = opcode + + def clearOperands(self): + self.operands = [] + + def addOperand(self, operand): + self.operands.append(operand) + + def getOperands(self): + return self.operands + + def getLine(self): + ret = "\t" + self.opcode + if self.operands: + ret += "\t" + for op in self.operands: + ret += op + ", " + if self.operands: + ret = ret[:-2] + return ret + + def isInstruction(self): + return True + +class B43AsmParser: + """A simple B43 assembly code parser.""" + + def __init__(self, asm_code): + self.__parse_code(asm_code) + + def __parse_code(self, asm_code): + self.codelines = [] + label = re.compile(r"^\s*\w+:\s*$") + insn_0 = re.compile(r"^\s*([@\.\w]+)\s*$") + insn_2 = re.compile(r"^\s*([@\.\w]+)\s+([@\[\],\w]+),\s*([@\[\],\w]+)\s*$") + insn_3 = re.compile(r"^\s*([@\.\w]+)\s+([@\[\],\w]+),\s*([@\[\],\w]+),\s*([@\[\],\w]+)\s*$") + insn_5 = re.compile(r"^\s*([@\.\w]+)\s+([@\[\],\w]+),\s*([@\[\],\w]+),\s*([@\[\],\w]+),\s*([@\[\],\w]+),\s*([@\[\],\w]+)\s*$") + for line in asm_code.splitlines(): + m = label.match(line) + if m: # Label: + l = B43AsmLine(line) + self.codelines.append(l) + continue + m = insn_0.match(line) + if m: # No operands + insn = B43AsmInstruction(m.group(1)) + self.codelines.append(insn) + continue + m = insn_2.match(line) + if m: # Two operands + insn = B43AsmInstruction(m.group(1)) + insn.addOperand(m.group(2)) + insn.addOperand(m.group(3)) + self.codelines.append(insn) + continue + m = insn_3.match(line) + if m: # Three operands + insn = B43AsmInstruction(m.group(1)) + insn.addOperand(m.group(2)) + insn.addOperand(m.group(3)) + insn.addOperand(m.group(4)) + self.codelines.append(insn) + continue + m = insn_5.match(line) + if m: # Three operands + insn = B43AsmInstruction(m.group(1)) + insn.addOperand(m.group(2)) + insn.addOperand(m.group(3)) + insn.addOperand(m.group(4)) + insn.addOperand(m.group(5)) + insn.addOperand(m.group(6)) + self.codelines.append(insn) + continue + # Unknown line + l = B43AsmLine(line) + self.codelines.append(l) + +class B43Beautifier(B43AsmParser): + """A B43 assembly code beautifier.""" + + def __init__(self, asm_code, headers_dir): + """asm_code is the assembly code. headers_dir is a full + path to the directory containing the symbolic SPR,SHM,etc... definitions""" + if headers_dir.endswith("/"): + headers_dir = headers_dir[:-1] + B43AsmParser.__init__(self, asm_code) + self.symSpr = B43SymbolicSpr(headers_dir + "/spr.inc") + self.symShm = B43SymbolicShm(headers_dir + "/shm.inc") + self.symCond = B43SymbolicCondition(headers_dir + "/cond.inc") + self.preamble = "#include \"%s/spr.inc\"\n" % headers_dir + self.preamble += "#include \"%s/shm.inc\"\n" % headers_dir + self.preamble += "#include \"%s/cond.inc\"\n" % headers_dir + self.preamble += "\n" + self.__process_code() + + def __process_code(self): + spr_re = re.compile(r"^spr\w\w\w$") + shm_re = re.compile(r"^\[(0x\w+)\]$") + code = self.codelines + for line in code: + if not line.isInstruction(): + continue + opcode = line.getOpcode() + operands = line.getOperands() + # Transform unconditional jump + if opcode == "jext" and int(operands[0], 16) == 0x7F: + label = operands[1] + line.setOpcode("jmp") + line.clearOperands() + line.addOperand(label) + continue + # Transform external conditions + if opcode == "jext" or opcode == "jnext": + operands[0] = self.symCond.get(int(operands[0], 16)) + continue + # Transform orx 7,8,imm,imm,target to mov + if opcode == "orx" and \ + int(operands[0], 16) == 7 and int(operands[1], 16) == 8 and\ + operands[2].startswith("0x") and operands[3].startswith("0x"): + value = int(operands[3], 16) & 0xFF + value |= (int(operands[2], 16) & 0xFF) << 8 + target = operands[4] + line.setOpcode("mov") + line.clearOperands() + line.addOperand("0x%X" % value) + line.addOperand(target) + opcode = line.getOpcode() + operands = line.getOperands() + for i in range(0, len(operands)): + o = operands[i] + # Transform SPR operands + m = spr_re.match(o) + if m: + operands[i] = self.symSpr.get(o) + continue + # Transform SHM operands + m = shm_re.match(o) + if m: + offset = int(m.group(1), 16) + operands[i] = "[" + self.symShm.get(offset) + "]" + continue + + def getAsm(self): + """Returns the beautified asm code.""" + ret = [ self.preamble ] + for line in self.codelines: + ret.append(str(line)) + return "\n".join(ret)