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