From 7f0cc2700686534bd26f72000b29847a05924943 Mon Sep 17 00:00:00 2001 From: R Date: Sat, 9 Apr 2022 17:53:46 -0700 Subject: [PATCH 1/9] bluetooth: start tracing Signed-off-by: R --- proxyclient/hv/trace_bt.py | 110 +++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 proxyclient/hv/trace_bt.py diff --git a/proxyclient/hv/trace_bt.py b/proxyclient/hv/trace_bt.py new file mode 100644 index 000000000..3ee46b3a5 --- /dev/null +++ b/proxyclient/hv/trace_bt.py @@ -0,0 +1,110 @@ +from m1n1.trace import Tracer +from m1n1.trace.dart import DARTTracer +from m1n1.utils import * +import struct + + +class BTBAR0Regs(RegMap): + IMG_DOORBELL = 0x140, Register32 + RTI_CONTROL = 0x144, Register32 + RTI_SLEEP_CONTROL = 0x150, Register32 + DOORBELL_6 = 0x154, Register32 + DOORBELL_05 = 0x174, Register32 + + BTI_MSI_LO = 0x580, Register32 + BTI_MSI_HI = 0x584, Register32 + REG_24 = 0x588, Register32 + HOST_WINDOW_LO = 0x590, Register32 + HOST_WINDOW_HI = 0x594, Register32 + HOST_WINDOW_SZ = 0x598, Register32 + RTI_IMG_LO = 0x5a0, Register32 + RTI_IMG_HI = 0x5a4, Register32 + RTI_IMG_SZ = 0x5a8, Register32 + REG_21 = 0x610, Register32 + + AXI2AHB_ERR_LOG_STATUS = 0x1908, Register32 + + CHIPCOMMON_CHIP_STATUS = 0x302c, Register32 + + APBBRIDGECB0_ERR_LOG_STATUS = 0x5908, Register32 + APBBRIDGECB0_ERR_ADDR_LO = 0x590c, Register32 + APBBRIDGECB0_ERR_ADDR_HI = 0x5910, Register32 + APBBRIDGECB0_ERR_MASTER_ID = 0x5914, Register32 + + DOORBELL_UNK = irange(0x6620, 7, 4), Register32 + + +class BTBAR1Regs(RegMap): + REG_0 = 0x20044c, Register32 + RTI_GET_CAPABILITY = 0x200450, Register32 + BOOTSTAGE = 0x200454, Register32 + RTI_GET_STATUS = 0x20045c, Register32 + + REG_7 = 0x200464, Register32 + + IMG_ADDR_LO = 0x200478, Register32 + IMG_ADDR_HI = 0x20047c, Register32 + IMG_ADDR_SZ = 0x200480, Register32 + BTI_EXITCODE_RTI_IMG_RESPONSE = 0x200488, Register32 + RTI_CONTEXT_LO = 0x20048c, Register32 + RTI_CONTEXT_HI = 0x200490, Register32 + RTI_WINDOW_LO = 0x200494, Register32 + RTI_WINDOW_HI = 0x200498, Register32 + RTI_WINDOW_SZ = 0x20049c, Register32 + + RTI_MSI_LO = 0x2004f8, Register32 + RTI_MSI_HI = 0x2004fc, Register32 + RTI_MSI_DATA = 0x200500, Register32 + + REG_14 = 0x20054c, Register32 + + +class MemRangeTracer(Tracer): + REGMAPS = [] + REGRANGES = [] + NAMES = [] + PREFIXES = [] + + def __init__(self, hv, verbose=False): + super().__init__(hv, verbose=verbose, ident=type(self).__name__) + + @classmethod + def _reloadcls(cls): + cls.REGMAPS = [i._reloadcls() if i else None for i in cls.REGMAPS] + return super()._reloadcls() + + def start(self): + for i in range(len(self.REGRANGES)): + if i >= len(self.REGMAPS) or (regmap := self.REGMAPS[i]) is None: + continue + prefix = name = None + if i < len(self.NAMES): + name = self.NAMES[i] + if i < len(self.PREFIXES): + prefix = self.PREFIXES[i] + + start, size = self.REGRANGES[i] + self.trace_regmap(start, size, regmap, name=name, prefix=prefix) + + +class BTTracer(MemRangeTracer): + DEFAULT_MODE = TraceMode.ASYNC + REGMAPS = [BTBAR0Regs, BTBAR1Regs] + # FIXME this is kinda a hack + REGRANGES = [(0x5c2410000, 0x8000), (0x5c2000000, 0x400000)] + NAMES = ['BAR0', 'BAR1'] + + def __init__(self, hv, dart_tracer): + super().__init__(hv, verbose=3) + self.dart_tracer = dart_tracer + + +BTTracer = BTTracer._reloadcls() + +dart_tracer = DARTTracer(hv, "/arm-io/dart-apcie0", verbose=1) +# do not start, clock gates aren't enabled yet +print(dart_tracer) + +bt_tracer = BTTracer(hv, dart_tracer) +bt_tracer.start() +print(bt_tracer) From a5089dae08f785ee30b01f24fbd28de75d9d9413 Mon Sep 17 00:00:00 2001 From: R Date: Sat, 9 Apr 2022 18:33:51 -0700 Subject: [PATCH 2/9] bluetooth: dump firmware, a little bit of context Signed-off-by: R --- proxyclient/hv/trace_bt.py | 96 +++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/proxyclient/hv/trace_bt.py b/proxyclient/hv/trace_bt.py index 3ee46b3a5..6a67c33f9 100644 --- a/proxyclient/hv/trace_bt.py +++ b/proxyclient/hv/trace_bt.py @@ -88,7 +88,7 @@ def start(self): class BTTracer(MemRangeTracer): - DEFAULT_MODE = TraceMode.ASYNC + DEFAULT_MODE = TraceMode.SYNC REGMAPS = [BTBAR0Regs, BTBAR1Regs] # FIXME this is kinda a hack REGRANGES = [(0x5c2410000, 0x8000), (0x5c2000000, 0x400000)] @@ -97,11 +97,105 @@ class BTTracer(MemRangeTracer): def __init__(self, hv, dart_tracer): super().__init__(hv, verbose=3) self.dart_tracer = dart_tracer + self._dart_tracer_started = False + self._dumped_host_window = False + self._dump_idx = 0 + self._host_window_lo = 0 + self._host_window_hi = 0 + self._host_window_sz = 0 + self._rti_window_lo = 0 + self._rti_window_hi = 0 + self._rti_window_sz = 0 + self._rti_context_lo = 0 + self._rti_context_hi = 0 + + def w_DOORBELL_6(self, val): + # this is the first access macos does + if not self._dart_tracer_started: + self.dart_tracer.start() + self._dart_tracer_started = True + print("starting DART tracer") + + def w_HOST_WINDOW_LO(self, val): + self._host_window_lo = val + + def w_HOST_WINDOW_HI(self, val): + self._host_window_hi = val + + def w_HOST_WINDOW_SZ(self, val): + self._host_window_sz = val + + def w_IMG_DOORBELL(self, val): + print("Image doorbell was rung") + host_window_iova = int(self._host_window_hi) << 32 | int(self._host_window_lo) + host_window_sz = int(self._host_window_sz) + print(f"Host window @ {host_window_iova:016X} sz {host_window_sz:08X}") + + self.dart_tracer.dart.dump_all() + + # FIXME how do we get stream IDs without hardcoding? + try: + data = self.dart_tracer.dart.ioread(2, host_window_iova, host_window_sz) + with open(f'bt_dump_{self._dump_idx}.bin', 'wb') as f: + f.write(data) + chexdump(data[:0x400]) + self._dump_idx += 1 + except Exception as e: + print(e) + + + def w_RTI_WINDOW_LO(self, val): + self._rti_window_lo = val + + def w_RTI_WINDOW_HI(self, val): + self._rti_window_hi = val + + def w_RTI_WINDOW_SZ(self, val): + self._rti_window_sz = val + + def w_RTI_CONTEXT_LO(self, val): + self._rti_context_lo = val + + def w_RTI_CONTEXT_HI(self, val): + self._rti_context_hi = val + + def w_RTI_CONTROL(self, val): + print("RTI control was set") + host_window_iova = int(self._host_window_hi) << 32 | int(self._host_window_lo) + host_window_sz = int(self._host_window_sz) + print(f"Host window @ {host_window_iova:016X} sz {host_window_sz:08X}") + rti_window_iova = int(self._rti_window_hi) << 32 | int(self._rti_window_lo) + rti_window_sz = int(self._rti_window_sz) + print(f"RTI window @ {rti_window_iova:016X} sz {rti_window_sz:08X}") + rti_context_iova = int(self._rti_context_hi) << 32 | int(self._rti_context_lo) + print(f"RTI context @ {rti_context_iova:016X}") + + self.dart_tracer.dart.dump_all() + + # FIXME how do we get stream IDs without hardcoding? + try: + data = self.dart_tracer.dart.ioread(2, host_window_iova, host_window_sz) + with open(f'bt_dump_{self._dump_idx}.bin', 'wb') as f: + f.write(data) + chexdump(data[:0x400]) + self._dump_idx += 1 + except Exception as e: + print(e) + + try: + data = self.dart_tracer.dart.ioread(2, rti_context_iova, 0x100) + with open(f'bt_dump_{self._dump_idx}.bin', 'wb') as f: + f.write(data) + chexdump(data) + self._dump_idx += 1 + except Exception as e: + print(e) BTTracer = BTTracer._reloadcls() dart_tracer = DARTTracer(hv, "/arm-io/dart-apcie0", verbose=1) +dart_tracer.DEFAULT_MODE = TraceMode.SYNC # do not start, clock gates aren't enabled yet print(dart_tracer) From 23e8c240f72b9a6d8c5921f2a7a8a7deb7038704 Mon Sep 17 00:00:00 2001 From: R Date: Sat, 9 Apr 2022 21:42:16 -0700 Subject: [PATCH 3/9] bluetooth: trace the HIA/TIA access Signed-off-by: R --- proxyclient/hv/trace_bt.py | 61 ++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/proxyclient/hv/trace_bt.py b/proxyclient/hv/trace_bt.py index 6a67c33f9..8e748801e 100644 --- a/proxyclient/hv/trace_bt.py +++ b/proxyclient/hv/trace_bt.py @@ -1,9 +1,42 @@ from m1n1.trace import Tracer from m1n1.trace.dart import DARTTracer from m1n1.utils import * +from collections import namedtuple import struct +ContextStruct = namedtuple('ContextStruct', [ + 'version', + 'sz', + 'enabled_caps', + 'perInfo', + 'crHIA', + 'trTIA', + 'crTIA', + 'trHIA', + 'crIAEntry', + 'trIAEntry', + 'mcr', + 'mtr', + 'mtrEntry', + 'mcrEntry', + 'mtrDb', + 'mcrDb', + 'mtrMsi', + 'mcrMsi', + 'mtrOptHeadSize', + 'mtrOptFootSize', + 'mcrOptHeadSize', + 'mcrOptFootSize', + 'res_inPlaceComp_oOOComp', + 'piMsi', + 'scratchPa', + 'scratchSize', + 'res', +]) +CONTEXTSTRUCT_STR = " Date: Sat, 9 Apr 2022 23:57:23 -0700 Subject: [PATCH 4/9] bluetooth: trace rings also add an alignment hack Signed-off-by: R --- proxyclient/hv/trace_bt.py | 2 ++ proxyclient/m1n1/proxy.py | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/proxyclient/hv/trace_bt.py b/proxyclient/hv/trace_bt.py index 8e748801e..692120c54 100644 --- a/proxyclient/hv/trace_bt.py +++ b/proxyclient/hv/trace_bt.py @@ -238,6 +238,8 @@ def hook(name, iova, sz): hook('crTIA', context.crTIA, 12) hook('trHIA', context.trHIA, 18) hook('trTIA', context.trTIA, 18) + hook('mcr', context.mcr, 0x800) # no idea size + hook('mtr', context.mtr, 0x800) # i _think_ this is correct except Exception as e: print(e) diff --git a/proxyclient/m1n1/proxy.py b/proxyclient/m1n1/proxy.py index 39b8e3449..5f080b103 100644 --- a/proxyclient/m1n1/proxy.py +++ b/proxyclient/m1n1/proxy.py @@ -712,7 +712,8 @@ def reboot(self): def write64(self, addr, data): '''write 8 byte value to given address''' if addr & 7: - raise AlignmentError() + self.write32(addr, data & 0xFFFFFFFF) + self.write32(addr + 4, data >> 32) self.request(self.P_WRITE64, addr, data) def write32(self, addr, data): '''write 4 byte value to given address''' From fff333341cb5e14803805127ae7895cdb27da3ff Mon Sep 17 00:00:00 2001 From: R Date: Sun, 10 Apr 2022 00:54:23 -0700 Subject: [PATCH 5/9] bluetooth: dump pipe 0 messages, seemingly correctly Signed-off-by: R --- proxyclient/hv/trace_bt.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/proxyclient/hv/trace_bt.py b/proxyclient/hv/trace_bt.py index 692120c54..a56b1e743 100644 --- a/proxyclient/hv/trace_bt.py +++ b/proxyclient/hv/trace_bt.py @@ -241,9 +241,41 @@ def hook(name, iova, sz): hook('mcr', context.mcr, 0x800) # no idea size hook('mtr', context.mtr, 0x800) # i _think_ this is correct + self._ctx = context + self._last_ring_idx = {} + except Exception as e: print(e) + def w_DOORBELL_05(self, val): + val = int(val) + if val & 0x20 != 0x20: + print(f"UNKNOWN write to doorbell {val:X}") + else: + pipe = (val >> 8) & 0xFF + ring_idx = (val >> 16) & 0xFFFF + print(f"doorbell rung for pipe {pipe} @ {ring_idx}") + + if pipe not in self._last_ring_idx: + self._last_ring_idx[pipe] = 0 + + try: + if pipe == 0: + for i in range(self._last_ring_idx[pipe], ring_idx): + tr_data_addr = self._ctx.mtr + 0x10 * i + print(f"TR idx {i} @ iova {tr_data_addr:016X}") + tr_data = self.dart_tracer.dart.ioread(STREAM, tr_data_addr, 0x10) + chexdump(tr_data) + + _, buf_addr, _ = struct.unpack(" Date: Sun, 10 Apr 2022 02:00:20 -0700 Subject: [PATCH 6/9] bluetooth: this is wrong, but one pipe has HCI commands Signed-off-by: R --- proxyclient/hv/trace_bt.py | 49 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/proxyclient/hv/trace_bt.py b/proxyclient/hv/trace_bt.py index a56b1e743..80e285e74 100644 --- a/proxyclient/hv/trace_bt.py +++ b/proxyclient/hv/trace_bt.py @@ -37,6 +37,33 @@ CONTEXTSTRUCT_STR = " Date: Sun, 10 Apr 2022 02:18:50 -0700 Subject: [PATCH 7/9] bluetooth: can see hci messages Signed-off-by: R --- proxyclient/hv/trace_bt.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/proxyclient/hv/trace_bt.py b/proxyclient/hv/trace_bt.py index 80e285e74..94a9d8d7d 100644 --- a/proxyclient/hv/trace_bt.py +++ b/proxyclient/hv/trace_bt.py @@ -311,14 +311,15 @@ def w_DOORBELL_05(self, val): print(close_pipe) del self._open_pipes[close_pipe.pipe_idx] + self._last_ring_idx[close_pipe.pipe_idx] = 0 elif pipe in self._open_pipes: tr_iova = self._open_pipes[pipe].ring_iova for i in range(self._last_ring_idx[pipe], ring_idx): - # FIXME XXX what's going on here? - tr_data_addr = tr_iova + # FIXME where does this size come from? + tr_data_addr = tr_iova + 0x118 * i print(f"TR idx {i} @ iova {tr_data_addr:016X}") - tr_data = self.dart_tracer.dart.ioread(STREAM, tr_data_addr, 0x200) + tr_data = self.dart_tracer.dart.ioread(STREAM, tr_data_addr, 0x118) chexdump(tr_data) except Exception as e: print(e) From 40abf193e90079b0d04b9d9cb22cff87b718dab9 Mon Sep 17 00:00:00 2001 From: R Date: Sun, 10 Apr 2022 05:12:37 -0700 Subject: [PATCH 8/9] bluetooth: hci responses seem to be present Signed-off-by: R --- proxyclient/hv/trace_bt.py | 97 ++++++++++++++++++++++++++++++++++---- 1 file changed, 88 insertions(+), 9 deletions(-) diff --git a/proxyclient/hv/trace_bt.py b/proxyclient/hv/trace_bt.py index 94a9d8d7d..cf852324e 100644 --- a/proxyclient/hv/trace_bt.py +++ b/proxyclient/hv/trace_bt.py @@ -64,6 +64,36 @@ CLOSEPIPE_STR = " Date: Tue, 12 Apr 2022 00:07:46 -0700 Subject: [PATCH 9/9] bluetooth: bunch of ring fixes Signed-off-by: R --- proxyclient/hv/trace_bt.py | 158 ++++++++++++++++++++++--------------- 1 file changed, 93 insertions(+), 65 deletions(-) diff --git a/proxyclient/hv/trace_bt.py b/proxyclient/hv/trace_bt.py index cf852324e..d2c501661 100644 --- a/proxyclient/hv/trace_bt.py +++ b/proxyclient/hv/trace_bt.py @@ -2,6 +2,7 @@ from m1n1.trace.dart import DARTTracer from m1n1.utils import * from collections import namedtuple +import itertools import struct @@ -134,7 +135,7 @@ class BTBAR1Regs(RegMap): IMG_ADDR_LO = 0x200478, Register32 IMG_ADDR_HI = 0x20047c, Register32 - IMG_ADDR_SZ = 0x200480, Register32 + IMG_SZ = 0x200480, Register32 BTI_EXITCODE_RTI_IMG_RESPONSE = 0x200488, Register32 RTI_CONTEXT_LO = 0x20048c, Register32 RTI_CONTEXT_HI = 0x200490, Register32 @@ -290,7 +291,7 @@ def hook(name, iova, sz): print(f"hooking {name} @ IOVA {iova:016X} phys {physaddr:016X}") self.trace(physaddr, sz, TraceMode.SYNC, prefix=name) - hook('perInfo', context.perInfo, 0x10) + # hook('perInfo', context.perInfo, 0x10) # hook('crHIA', context.crHIA, 12) # hook('crTIA', context.crTIA, 12) # hook('trHIA', context.trHIA, 18) @@ -307,8 +308,8 @@ def hook(name, iova, sz): None ) + self._crhia_physaddr = crhia_physaddr self._ctx = context - self._last_ring_idx = {} self._open_pipes = {} self._open_crs = {} @@ -320,90 +321,117 @@ def w_DOORBELL_05(self, val): if val & 0x20 != 0x20: print(f"UNKNOWN write to doorbell {val:X}") else: - pipe = (val >> 8) & 0xFF + db_idx = (val >> 8) & 0xFF ring_idx = (val >> 16) & 0xFFFF - print(f"doorbell rung for pipe {pipe} @ {ring_idx}") - - if pipe not in self._last_ring_idx: - self._last_ring_idx[pipe] = 0 + print(f"doorbell #{db_idx} rung @ {ring_idx}") try: - if pipe == 0: - for i in range(self._last_ring_idx[pipe], ring_idx): - tr_data_addr = self._ctx.mtr + 0x10 * i - print(f"TR idx {i} @ iova {tr_data_addr:016X}") - tr_data = self.dart_tracer.dart.ioread(STREAM, tr_data_addr, 0x10) - chexdump(tr_data) + tr_heads = struct.unpack("= tr_tails[pipe_idx]: + range_ = range(tr_tails[pipe_idx], tr_heads[pipe_idx]) + else: + range_ = itertools.chain(range(tr_tails[pipe_idx], tr_ring_sz), range(0, tr_heads[pipe_idx])) - _, buf_addr, _ = struct.unpack("= cr_tails[cr_idx]: + range_ = range(cr_tails[cr_idx], cr_heads[cr_idx]) + else: + range_ = itertools.chain(range(cr_tails[cr_idx], cr_ring_sz), range(0, cr_heads[cr_idx])) + + for i in range_: + cr_data_addr = cr_iova_base + cr_ent_sz * i + print(f"CR{cr_idx} idx {i} @ iova {cr_data_addr:016X}") cr_data = self.dart_tracer.dart.ioread(STREAM, cr_data_addr, cr_ent_sz) chexdump(cr_data) - except Exception as e: - print(e) + except Exception as e: + print(e) BTTracer = BTTracer._reloadcls()