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