1# Copyright (C) 2021-2022 Intel Corporation. 2# 3# SPDX-License-Identifier: BSD-3-Clause 4# 5 6import os 7import ctypes 8from collections import namedtuple 9 10from pcieparser.header import header 11from pcieparser.caps import capabilities 12from pcieparser.extcaps import extended_capabilities 13 14class PCIConfigSpace(namedtuple("PCIConfigSpace", ["header", "caps", "extcaps"])): 15 def __repr__(self): 16 acc = str(self.header) 17 for cap in self.caps: 18 acc += "\n" 19 acc += str(cap) 20 for extcap in self.extcaps: 21 acc += "\n" 22 acc += str(extcap) 23 return acc 24 25 def caps_as_dict(self): 26 if not hasattr(self, "_caps_as_dict"): 27 self._caps_as_dict = dict() 28 for cap in self.caps: 29 self._caps_as_dict[cap.name] = cap 30 for cap in self.extcaps: 31 self._caps_as_dict[cap.name] = cap 32 return self._caps_as_dict 33 34 def has_cap(self, cap_name): 35 return cap_name in self.caps_as_dict().keys() 36 37 def get_cap(self, cap_name): 38 return self.caps_as_dict().get(cap_name) 39 40def parse_config_space(path): 41 try: 42 data = open(os.path.join(path, "config"), mode='rb').read() 43 hdr = header(data) 44 caps = capabilities(data, hdr.capability_pointer) if hasattr(hdr, 'capability_pointer') else [] 45 config_space = PCIConfigSpace(hdr, caps, []) 46 # While PCI Express specification requires that a PCIe endpoint must have an extended capability header at 47 # offset 100h of its configuration space, we do see real PCIe endpoints not meeting this requirement 48 # occasionally. Thus, check the length of the configuration space as well before trying to parse its extended 49 # capability list. 50 if config_space.has_cap("PCI Express") and len(data) >= 260: 51 extcaps = extended_capabilities(data) 52 config_space = PCIConfigSpace(hdr, caps, extcaps) 53 return config_space 54 except FileNotFoundError: 55 return None 56