acrn-hypervisor/misc/config_tools/board_inspector/pcieparser/extcaps.py
Junjie Mao 0aa899271d board_inspector/extractors: extract device information
This patch extracts information on devices and put them under the
`/acrn-config/devices` node in the board XML.

The generated XML looks like the following:

  <devices>
    <bus type="system">
      <acpi_object>\_SB_</acpi_object>
      <bus id="PNP0A08" type="pci" address="0x0" description="...">
        <vendor>0x8086</vendor>
        <identifier>0x591f</identifier>
        <subsystem_vendor>0x1028</subsystem_vendor>
        <subsystem_identifier>0x07a1</subsystem_identifier>
        <class>0x060000</class>
        <acpi_object>\_SB_.PCI0</acpi_object>
        <resource type="bus_number" min="0x0" max="0x3e" len="0x3f"/>
        <resource type="io_port" min="0x0" max="0xcf7" len="0xcf8"/>
        <resource type="io_port" min="0xcf8" max="0xcf8" len="0x8"/>
        <resource type="io_port" min="0xd00" max="0xffff" len="0xf300"/>
        <resource type="memory" min="0x10000" max="0x1ffff" len="0x0"/>
        <resource type="memory" min="0xa0000" max="0xbffff" len="0x20000"/>
        <resource type="memory" min="0xc0000" max="0xc3fff" len="0x4000"/>
        <resource type="memory" min="0xc4000" max="0xc7fff" len="0x4000"/>
        ...
        <capability id="vendor_specific"/>
        <device address="0x1"> ... </device>
        ...
      <bus>
    <bus>
    <device> ... <device>
  <devices>

The hierarchy of devices are based on the hierarchy of device objects in
the ACPI namespace (which is established by interpreting the ACPI DSDT and
SSDT tables). Typically most device objects are under the predefined
`_SB_` (i.e. System Bus) object under which an object representing the PCI
root complex (`\_SB_.PCI0` in the example above) can be found. The PCI
devices attached to bus 0 are listed as children of the PCI root complex
node.

For each bus or device, the board inspector tries best to parse the
information from both ACPI device objects and PCI configuration space to
extract the following:

- the model (via `_HID` object and PCI vendor ID, device ID and class code),
- assigned resources (via `_CRS` object and PCI BARs),
- capabilities (via the PCI capability list)

v1 -> v2:
 - Fix references to undeclared modules or variables.
 - Make the ACPI extractor advanced and not enabled by default.
 - Extract the secondary I/O and memory-mapped I/O addresses of bridges.

Tracked-On: #5922
Signed-off-by: Junjie Mao <junjie.mao@intel.com>
2021-05-16 19:02:00 +08:00

91 lines
2.5 KiB
Python

# Copyright (C) 2021 Intel Corporation. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
import ctypes
import copy
import lib.cdata as cdata
class ExtendedCapability:
# Capability names from PCI Express Base Specification, mostly Table 9-23
_cap_names_ = {
0x01: "Advanced Error Reporting",
0x02: "Virtual Channel",
0x03: "Device Serial Number",
0x04: "Power Budgeting",
0x05: "Root Complex Link Declaration",
0x06: "Root Complex Internal Link Control",
0x07: "Root Complex Event Collector Endpoint Association",
0x08: "Multi-Function Virtual Channel",
0x09: "Virtual Channel",
0x0a: "RCRB Header",
0x0b: "Vendor-Specific Extended",
0x0c: "Configuration Access Correlation",
0x0d: "ACS",
0x0e: "ARI",
0x0f: "ATS",
0x10: "SR-IOV",
0x11: "MR-IOV",
0x12: "Multicast",
0x13: "PRI",
0x15: "Resizable BAR",
0x16: "DPA",
0x17: "TPH Requester",
0x18: "LTR",
0x19: "Secondary PCI Express",
0x1a: "PMUX",
0x1b: "PASID",
0x1c: "LNR",
0x1d: "DPC",
0x1e: "L1 PM Substates",
0x1f: "TPM",
0x20: "M-PCIe",
0x21: "FRS Queueing",
0x22: "Readiness Time Reporting",
0x23: "Designated Vendor-Specific",
0x24: "VF Resizable BAR",
0x25: "Data Link Feature",
0x26: "Physical Layer 16.0 GT/s",
0x27: "Lane Margining at the Receiver",
0x28: "Hierarchy ID",
0x29: "NPEM",
0x2a: "Physical Layer 32.0 GT/s",
0x2b: "Alternate Protocol",
0x2c: "SFI",
}
@property
def name(self):
if self.id in self._cap_names_.keys():
return self._cap_names_[self.id]
else:
return f"Reserved Extended ({hex(self.id)})"
class ExtendedCapabilityListRegister(cdata.Struct, ExtendedCapability):
_pack_ = 1
_fields_ = [
('id', ctypes.c_uint32, 16),
('version', ctypes.c_uint32, 4),
('next_cap_ptr_raw', ctypes.c_uint32, 12),
]
@property
def next_cap_ptr(self):
return self.next_cap_ptr_raw & 0xffc
# Module API
def extended_capabilities(data):
buf = ctypes.create_string_buffer(data, len(data))
cap_ptr = 0x100
acc = list()
while cap_ptr != 0:
caplist = ExtendedCapabilityListRegister.from_buffer_copy(buf, cap_ptr)
if caplist.id != 0:
acc.append(caplist)
cap_ptr = caplist.next_cap_ptr
return acc