1*5c2921b0SApple OSS Distributionsfrom __future__ import absolute_import, print_function 2*5c2921b0SApple OSS Distributions 3*5c2921b0SApple OSS Distributionsfrom builtins import range 4*5c2921b0SApple OSS Distributions 5*5c2921b0SApple OSS Distributionsfrom xnu import * 6*5c2921b0SApple OSS Distributions 7*5c2921b0SApple OSS Distributions###################################### 8*5c2921b0SApple OSS Distributions# Helper functions 9*5c2921b0SApple OSS Distributions###################################### 10*5c2921b0SApple OSS Distributionsdef GetMemMappedPciCfgAddrFromRegistry(): 11*5c2921b0SApple OSS Distributions """ Retrieve the base address of the memory mapped PCI config space. It is 12*5c2921b0SApple OSS Distributions found in registry entry AppleACPIPlatformExpert, property acpi-mmcfg-seg0. 13*5c2921b0SApple OSS Distributions Returns: 14*5c2921b0SApple OSS Distributions int base address of memory mapped PCI config space 15*5c2921b0SApple OSS Distributions """ 16*5c2921b0SApple OSS Distributions kgm_pci_cfg_base_default = 0xe0000000 17*5c2921b0SApple OSS Distributions acpi_pe_obj = FindRegistryObjectRecurse(kern.globals.gRegistryRoot, 18*5c2921b0SApple OSS Distributions "AppleACPIPlatformExpert") 19*5c2921b0SApple OSS Distributions if acpi_pe_obj is None: 20*5c2921b0SApple OSS Distributions print("Could not find AppleACPIPlatformExpert in registry, \ 21*5c2921b0SApple OSS Distributions using default base address for memory mapped PCI config space") 22*5c2921b0SApple OSS Distributions return kgm_pci_cfg_base_default 23*5c2921b0SApple OSS Distributions entry = kern.GetValueFromAddress(int(acpi_pe_obj), 'IOService *') 24*5c2921b0SApple OSS Distributions acpi_mmcfg_seg_prop = LookupKeyInPropTable(entry.fPropertyTable, "acpi-mmcfg-seg0") 25*5c2921b0SApple OSS Distributions if acpi_mmcfg_seg_prop is None: 26*5c2921b0SApple OSS Distributions print("Could not find acpi-mmcfg-seg0 property, \ 27*5c2921b0SApple OSS Distributions using default base address for memory mapped PCI config space") 28*5c2921b0SApple OSS Distributions return kgm_pci_cfg_base_default 29*5c2921b0SApple OSS Distributions else: 30*5c2921b0SApple OSS Distributions return int(GetNumber(acpi_mmcfg_seg_prop)) 31*5c2921b0SApple OSS Distributions 32*5c2921b0SApple OSS Distributions@static_var('kgm_pci_cfg_base', -1) 33*5c2921b0SApple OSS Distributionsdef GetMemMappedPciCfgAddrBase(): 34*5c2921b0SApple OSS Distributions """ Returns the base address of the memory mapped PCI config space. The address 35*5c2921b0SApple OSS Distributions is retrieved once from the registry, and is remembered for all subsequent 36*5c2921b0SApple OSS Distributions calls to this function 37*5c2921b0SApple OSS Distributions Returns: 38*5c2921b0SApple OSS Distributions int base address of memory mapped PCI config space 39*5c2921b0SApple OSS Distributions """ 40*5c2921b0SApple OSS Distributions if GetMemMappedPciCfgAddrBase.kgm_pci_cfg_base == -1: 41*5c2921b0SApple OSS Distributions # Retrieve the base address from the registry if it hasn't been 42*5c2921b0SApple OSS Distributions # initialized yet 43*5c2921b0SApple OSS Distributions GetMemMappedPciCfgAddrBase.kgm_pci_cfg_base = GetMemMappedPciCfgAddrFromRegistry() 44*5c2921b0SApple OSS Distributions return GetMemMappedPciCfgAddrBase.kgm_pci_cfg_base 45*5c2921b0SApple OSS Distributions 46*5c2921b0SApple OSS Distributionsdef MakeMemMappedPciCfgAddr(bus, dev, func, offs): 47*5c2921b0SApple OSS Distributions """ Construct the memory address for the PCI config register specified by the 48*5c2921b0SApple OSS Distributions bus, device, function, and offset 49*5c2921b0SApple OSS Distributions Params: 50*5c2921b0SApple OSS Distributions bus, dev, func, offs: int - bus, device, function, and offset that specifies 51*5c2921b0SApple OSS Distributions the PCI config space register 52*5c2921b0SApple OSS Distributions Returns: 53*5c2921b0SApple OSS Distributions int - the physical memory address that maps to the PCI config space register 54*5c2921b0SApple OSS Distributions """ 55*5c2921b0SApple OSS Distributions return GetMemMappedPciCfgAddrBase() | (bus << 20) | (dev << 15) | (func << 12) | offs 56*5c2921b0SApple OSS Distributions 57*5c2921b0SApple OSS Distributionsdef DoPciCfgRead(bits, bus, dev, func, offs): 58*5c2921b0SApple OSS Distributions """ Helper function that performs PCI config space read 59*5c2921b0SApple OSS Distributions Params: 60*5c2921b0SApple OSS Distributions bits: int - bit width of access: 8, 16, or 32 bits 61*5c2921b0SApple OSS Distributions bus, dev, func, offs: int - PCI config bus, device, function and offset 62*5c2921b0SApple OSS Distributions Returns: 63*5c2921b0SApple OSS Distributions int - the value read from PCI config space 64*5c2921b0SApple OSS Distributions """ 65*5c2921b0SApple OSS Distributions phys_addr = MakeMemMappedPciCfgAddr(bus, dev, func, offs) 66*5c2921b0SApple OSS Distributions return ReadPhysInt(phys_addr, bits) 67*5c2921b0SApple OSS Distributions 68*5c2921b0SApple OSS Distributionsdef DoPciCfgWrite(bits, bus, dev, func, offs, val): 69*5c2921b0SApple OSS Distributions """ Helper function that performs PCI config space write 70*5c2921b0SApple OSS Distributions Params: 71*5c2921b0SApple OSS Distributions bits: int - bit width of access: 8, 16, or 32 bits 72*5c2921b0SApple OSS Distributions bus, dev, func, offs: int - PCI config bus, device, function and offset 73*5c2921b0SApple OSS Distributions Returns: 74*5c2921b0SApple OSS Distributions boolean - True upon success, False otherwise 75*5c2921b0SApple OSS Distributions """ 76*5c2921b0SApple OSS Distributions phys_addr = MakeMemMappedPciCfgAddr(bus, dev, func, offs) 77*5c2921b0SApple OSS Distributions return WritePhysInt(phys_addr, val, bits) 78*5c2921b0SApple OSS Distributions 79*5c2921b0SApple OSS Distributionsdef ShowPciCfgBytes(bus, dev, func, offset): 80*5c2921b0SApple OSS Distributions """ Prints 16 bytes of PCI config space starting at specified offset 81*5c2921b0SApple OSS Distributions Params: 82*5c2921b0SApple OSS Distributions bus, dev, func, offset: int - bus, dev, function, and offset of the 83*5c2921b0SApple OSS Distributions PCI config space register 84*5c2921b0SApple OSS Distributions """ 85*5c2921b0SApple OSS Distributions # Print mem-mapped address at beginning of each 16-byte line 86*5c2921b0SApple OSS Distributions phys_addr = MakeMemMappedPciCfgAddr(bus, dev, func, offset) 87*5c2921b0SApple OSS Distributions read_vals = [DoPciCfgRead(32, bus, dev, func, offset + byte) 88*5c2921b0SApple OSS Distributions for byte in range(0, 16, 4)] 89*5c2921b0SApple OSS Distributions # It would be nicer to have a shorter format that we could loop 90*5c2921b0SApple OSS Distributions # over, but each call to print results in a newline which 91*5c2921b0SApple OSS Distributions # would prevent us from printing all 16 bytes on one line. 92*5c2921b0SApple OSS Distributions bytes_fmt = "{:08x}:" + "{:02x} " * 16 93*5c2921b0SApple OSS Distributions print(bytes_fmt.format( 94*5c2921b0SApple OSS Distributions phys_addr, 95*5c2921b0SApple OSS Distributions read_vals[0] & 0xff, (read_vals[0] >> 8) & 0xff, 96*5c2921b0SApple OSS Distributions (read_vals[0] >> 16) & 0xff, (read_vals[0] >> 24) & 0xff, 97*5c2921b0SApple OSS Distributions read_vals[1] & 0xff, (read_vals[1] >> 8) & 0xff, 98*5c2921b0SApple OSS Distributions (read_vals[1] >> 16) & 0xff, (read_vals[1] >> 24) & 0xff, 99*5c2921b0SApple OSS Distributions read_vals[2] & 0xff, (read_vals[2] >> 8) & 0xff, 100*5c2921b0SApple OSS Distributions (read_vals[2] >> 16) & 0xff, (read_vals[2] >> 24) & 0xff, 101*5c2921b0SApple OSS Distributions read_vals[3] & 0xff, (read_vals[3] >> 8) & 0xff, 102*5c2921b0SApple OSS Distributions (read_vals[3] >> 16) & 0xff, (read_vals[3] >> 24) & 0xff)) 103*5c2921b0SApple OSS Distributions 104*5c2921b0SApple OSS Distributionsdef DoPciCfgDump(bus, dev, func): 105*5c2921b0SApple OSS Distributions """ Dumps PCI config space of the PCI device specified by bus, dev, function 106*5c2921b0SApple OSS Distributions Params: 107*5c2921b0SApple OSS Distributions bus, dev, func: int - bus, dev, function of PCI config space to dump 108*5c2921b0SApple OSS Distributions """ 109*5c2921b0SApple OSS Distributions # Check for a valid PCI device 110*5c2921b0SApple OSS Distributions vendor_id = DoPciCfgRead(16, bus, dev, func, 0) 111*5c2921b0SApple OSS Distributions if (vendor_id == 0xbad10ad) or not (vendor_id > 0 and vendor_id < 0xffff): 112*5c2921b0SApple OSS Distributions return 113*5c2921b0SApple OSS Distributions # Show the standard PCI config space 114*5c2921b0SApple OSS Distributions print("address: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n") 115*5c2921b0SApple OSS Distributions print("--------------------------------------------------------") 116*5c2921b0SApple OSS Distributions for offset in range(0, 256, 16): 117*5c2921b0SApple OSS Distributions ShowPciCfgBytes(bus, dev, func, offset) 118*5c2921b0SApple OSS Distributions # Check for PCIE extended capability config space 119*5c2921b0SApple OSS Distributions if DoPciCfgRead(8, bus, dev, func, 256) < 0xff: 120*5c2921b0SApple OSS Distributions print(" \n") 121*5c2921b0SApple OSS Distributions for offset in range(256, 4096, 16): 122*5c2921b0SApple OSS Distributions ShowPciCfgBytes(bus, dev, func, offset) 123*5c2921b0SApple OSS Distributions 124*5c2921b0SApple OSS Distributionsdef DoPciCfgScan(max_bus, dump): 125*5c2921b0SApple OSS Distributions """ Do a PCI config scan starting at bus 0 up to specified max bus 126*5c2921b0SApple OSS Distributions Params: 127*5c2921b0SApple OSS Distributions max_bus: int - maximum bus to scan 128*5c2921b0SApple OSS Distributions dump: bool - if True, dump the config space of each scanned device 129*5c2921b0SApple OSS Distributions if False, print basic information of each scanned device 130*5c2921b0SApple OSS Distributions """ 131*5c2921b0SApple OSS Distributions max_dev = 32 132*5c2921b0SApple OSS Distributions max_func = 8 133*5c2921b0SApple OSS Distributions bdfs = ({'bus':bus, 'dev':dev, 'func':func} 134*5c2921b0SApple OSS Distributions for bus in range(max_bus) 135*5c2921b0SApple OSS Distributions for dev in range(max_dev) 136*5c2921b0SApple OSS Distributions for func in range(max_func)) 137*5c2921b0SApple OSS Distributions fmt_string = "{:03x}:" * 3 + " " + \ 138*5c2921b0SApple OSS Distributions "{:02x}" * 2 + " " + \ 139*5c2921b0SApple OSS Distributions "{:02x}" * 2 + " {:02x} | " + \ 140*5c2921b0SApple OSS Distributions "{:02x}" * 3 141*5c2921b0SApple OSS Distributions for bdf in bdfs: 142*5c2921b0SApple OSS Distributions bus = bdf['bus'] 143*5c2921b0SApple OSS Distributions dev = bdf['dev'] 144*5c2921b0SApple OSS Distributions func = bdf['func'] 145*5c2921b0SApple OSS Distributions vend_dev_id = DoPciCfgRead(32, bus, dev, func, 0) 146*5c2921b0SApple OSS Distributions if not (vend_dev_id > 0 and vend_dev_id < 0xffffffff): 147*5c2921b0SApple OSS Distributions continue 148*5c2921b0SApple OSS Distributions if dump == False: 149*5c2921b0SApple OSS Distributions class_rev_id = DoPciCfgRead(32, bus, dev, func, 8) 150*5c2921b0SApple OSS Distributions print(fmt_string.format( 151*5c2921b0SApple OSS Distributions bus, dev, func, 152*5c2921b0SApple OSS Distributions (vend_dev_id >> 8) & 0xff, vend_dev_id & 0xff, 153*5c2921b0SApple OSS Distributions (vend_dev_id >> 24) & 0xff, (vend_dev_id >> 16) & 0xff, 154*5c2921b0SApple OSS Distributions class_rev_id & 0xff, (class_rev_id >> 24) & 0xff, 155*5c2921b0SApple OSS Distributions (class_rev_id >> 16) & 0xff, (class_rev_id >> 8) & 0xff)) 156*5c2921b0SApple OSS Distributions else: 157*5c2921b0SApple OSS Distributions print("{:03x}:{:03x}:{:03x}".format(bus, dev, func)) 158*5c2921b0SApple OSS Distributions DoPciCfgDump(bus, dev, func) 159*5c2921b0SApple OSS Distributions 160*5c2921b0SApple OSS Distributions###################################### 161*5c2921b0SApple OSS Distributions# LLDB commands 162*5c2921b0SApple OSS Distributions###################################### 163*5c2921b0SApple OSS Distributions@lldb_command('pci_cfg_read') 164*5c2921b0SApple OSS Distributionsdef PciCfgRead(cmd_args=None): 165*5c2921b0SApple OSS Distributions """ Read PCI config space at the specified bus, device, function, and offset 166*5c2921b0SApple OSS Distributions Syntax: pci_cfg_read <bits> <bus> <device> <function> <offset> 167*5c2921b0SApple OSS Distributions bits: 8, 16, 32 168*5c2921b0SApple OSS Distributions """ 169*5c2921b0SApple OSS Distributions if cmd_args == None or len(cmd_args) < 5: 170*5c2921b0SApple OSS Distributions print(PciCfgRead.__doc__) 171*5c2921b0SApple OSS Distributions return 172*5c2921b0SApple OSS Distributions 173*5c2921b0SApple OSS Distributions bits = ArgumentStringToInt(cmd_args[0]) 174*5c2921b0SApple OSS Distributions bus = ArgumentStringToInt(cmd_args[1]) 175*5c2921b0SApple OSS Distributions dev = ArgumentStringToInt(cmd_args[2]) 176*5c2921b0SApple OSS Distributions func = ArgumentStringToInt(cmd_args[3]) 177*5c2921b0SApple OSS Distributions offs = ArgumentStringToInt(cmd_args[4]) 178*5c2921b0SApple OSS Distributions 179*5c2921b0SApple OSS Distributions read_val = DoPciCfgRead(bits, bus, dev, func, offs) 180*5c2921b0SApple OSS Distributions if read_val == 0xbad10ad: 181*5c2921b0SApple OSS Distributions print("ERROR: Failed to read PCI config space") 182*5c2921b0SApple OSS Distributions return 183*5c2921b0SApple OSS Distributions 184*5c2921b0SApple OSS Distributions format_for_bits = {8:"{:#04x}", 16:"{:#06x}", 32:"{:#010x}"} 185*5c2921b0SApple OSS Distributions phys_addr = MakeMemMappedPciCfgAddr(bus, dev, func, offs) 186*5c2921b0SApple OSS Distributions fmt_string = "{:08x}: " + format_for_bits[bits] 187*5c2921b0SApple OSS Distributions print(fmt_string.format(phys_addr, read_val)) 188*5c2921b0SApple OSS Distributions 189*5c2921b0SApple OSS Distributionslldb_alias('pci_cfg_read8', 'pci_cfg_read 8') 190*5c2921b0SApple OSS Distributionslldb_alias('pci_cfg_read16', 'pci_cfg_read 16') 191*5c2921b0SApple OSS Distributionslldb_alias('pci_cfg_read32', 'pci_cfg_read 32') 192*5c2921b0SApple OSS Distributions 193*5c2921b0SApple OSS Distributions@lldb_command('pci_cfg_write') 194*5c2921b0SApple OSS Distributionsdef PciCfgWrite(cmd_args=None): 195*5c2921b0SApple OSS Distributions """ Write PCI config space at the specified bus, device, function, and offset 196*5c2921b0SApple OSS Distributions Syntax: pci_cfg_write <bits> <bus> <device> <function> <offset> <write val> 197*5c2921b0SApple OSS Distributions bits: 8, 16, 32 198*5c2921b0SApple OSS Distributions 199*5c2921b0SApple OSS Distributions Prints an error message if there was a problem 200*5c2921b0SApple OSS Distributions Prints nothing upon success. 201*5c2921b0SApple OSS Distributions """ 202*5c2921b0SApple OSS Distributions if cmd_args == None or len(cmd_args) < 6: 203*5c2921b0SApple OSS Distributions print(PciCfgWrite.__doc__) 204*5c2921b0SApple OSS Distributions return 205*5c2921b0SApple OSS Distributions 206*5c2921b0SApple OSS Distributions bits = ArgumentStringToInt(cmd_args[0]) 207*5c2921b0SApple OSS Distributions bus = ArgumentStringToInt(cmd_args[1]) 208*5c2921b0SApple OSS Distributions dev = ArgumentStringToInt(cmd_args[2]) 209*5c2921b0SApple OSS Distributions func = ArgumentStringToInt(cmd_args[3]) 210*5c2921b0SApple OSS Distributions offs = ArgumentStringToInt(cmd_args[4]) 211*5c2921b0SApple OSS Distributions write_val = ArgumentStringToInt(cmd_args[5]) 212*5c2921b0SApple OSS Distributions 213*5c2921b0SApple OSS Distributions if DoPciCfgWrite(bits, bus, dev, func, offs, write_val) == False: 214*5c2921b0SApple OSS Distributions print("ERROR: Failed to write PCI config space") 215*5c2921b0SApple OSS Distributions 216*5c2921b0SApple OSS Distributionslldb_alias('pci_cfg_write8', 'pci_cfg_write 8') 217*5c2921b0SApple OSS Distributionslldb_alias('pci_cfg_write16', 'pci_cfg_write 16') 218*5c2921b0SApple OSS Distributionslldb_alias('pci_cfg_write32', 'pci_cfg_write 32') 219*5c2921b0SApple OSS Distributions 220*5c2921b0SApple OSS Distributions@lldb_command('pci_cfg_dump') 221*5c2921b0SApple OSS Distributionsdef PciCfgDump(cmd_args=None): 222*5c2921b0SApple OSS Distributions """ Dump PCI config space for specified bus, device, and function 223*5c2921b0SApple OSS Distributions If an invalid/inaccessible PCI device is specified, nothing will 224*5c2921b0SApple OSS Distributions be printed out. 225*5c2921b0SApple OSS Distributions Syntax: pci_cfg_dump <bus> <dev> <fuction> 226*5c2921b0SApple OSS Distributions """ 227*5c2921b0SApple OSS Distributions if cmd_args == None or len(cmd_args) < 3: 228*5c2921b0SApple OSS Distributions print(PciCfgDump.__doc__) 229*5c2921b0SApple OSS Distributions return 230*5c2921b0SApple OSS Distributions 231*5c2921b0SApple OSS Distributions bus = ArgumentStringToInt(cmd_args[0]) 232*5c2921b0SApple OSS Distributions dev = ArgumentStringToInt(cmd_args[1]) 233*5c2921b0SApple OSS Distributions func = ArgumentStringToInt(cmd_args[2]) 234*5c2921b0SApple OSS Distributions 235*5c2921b0SApple OSS Distributions DoPciCfgDump(bus, dev, func) 236*5c2921b0SApple OSS Distributions 237*5c2921b0SApple OSS Distributions@lldb_command('pci_cfg_scan') 238*5c2921b0SApple OSS Distributionsdef PciCfgScan(cmd_args=None): 239*5c2921b0SApple OSS Distributions """ Scan for pci devices. The maximum bus number to be scanned defaults to 8, 240*5c2921b0SApple OSS Distributions but can be specified as an argument 241*5c2921b0SApple OSS Distributions Syntax: pci_cfg_scan [max bus number] 242*5c2921b0SApple OSS Distributions """ 243*5c2921b0SApple OSS Distributions if cmd_args == None or len(cmd_args) == 0: 244*5c2921b0SApple OSS Distributions max_bus = 8 245*5c2921b0SApple OSS Distributions elif len(cmd_args) == 1: 246*5c2921b0SApple OSS Distributions max_bus = ArgumentStringToInt(cmd_args[0]) 247*5c2921b0SApple OSS Distributions else: 248*5c2921b0SApple OSS Distributions print(PciCfgScan.__doc__) 249*5c2921b0SApple OSS Distributions return 250*5c2921b0SApple OSS Distributions 251*5c2921b0SApple OSS Distributions print("bus:dev:fcn: vendor device rev | class") 252*5c2921b0SApple OSS Distributions print("--------------------------------------") 253*5c2921b0SApple OSS Distributions DoPciCfgScan(max_bus, False) 254*5c2921b0SApple OSS Distributions 255*5c2921b0SApple OSS Distributions@lldb_command('pci_cfg_dump_all') 256*5c2921b0SApple OSS Distributionsdef PciCfgDumpAll(cmd_args=None): 257*5c2921b0SApple OSS Distributions """ Dump config space for all scanned PCI devices. The maximum bus number to 258*5c2921b0SApple OSS Distributions be scanned defaults to 8, but can be specified as an argument 259*5c2921b0SApple OSS Distributions Syntax: pci_cfg_dump_all [max bus number] 260*5c2921b0SApple OSS Distributions """ 261*5c2921b0SApple OSS Distributions if cmd_args == None or len(cmd_args) == 0: 262*5c2921b0SApple OSS Distributions max_bus = 8 263*5c2921b0SApple OSS Distributions elif len(cmd_args) == 1: 264*5c2921b0SApple OSS Distributions max_bus = ArgumentStringToInt(cmd_args[0]) 265*5c2921b0SApple OSS Distributions else: 266*5c2921b0SApple OSS Distributions print(PciCfgDumpAll.__doc__) 267*5c2921b0SApple OSS Distributions return 268*5c2921b0SApple OSS Distributions 269*5c2921b0SApple OSS Distributions DoPciCfgScan(max_bus, True) 270