acrn-hypervisor/misc/config_tools/board_inspector/pcieparser/header.py
Hu Fenglin f65a87585b deb-pkg: add acrn-hypervisor and acrn-board-inspector into debian package
1. "make clean && make BOARD=nuc11tnbi5  SCENARIO=shared" will generate the acrn debian package.
 2. "make clean && make board_inspector" will generate the acrn board_inspector debian package

Tracked-On: #6688
Signed-off-by: Hu Fenglin <fenglin.hu@intel.com>
2021-11-02 15:31:18 +08:00

190 lines
5.8 KiB
Python

# Copyright (C) 2021 Intel Corporation. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
import ctypes
import copy
import inspectorlib.cdata as cdata
class Common(cdata.Struct):
_pack_ = 1
_fields_ = [
('vendor_id', ctypes.c_uint16),
('device_id', ctypes.c_uint16),
('command', ctypes.c_uint16),
('status', ctypes.c_uint16),
('revision_id', ctypes.c_uint32, 8),
('class_code', ctypes.c_uint32, 24),
('cacheline_size', ctypes.c_uint8),
('latency_timer', ctypes.c_uint8),
('header_type', ctypes.c_uint8, 7),
('multi_function', ctypes.c_uint8, 1),
('bist', ctypes.c_uint8),
]
class MemoryBar32(cdata.Struct):
_pack_ = 1
_fields_ = [
('indicator', ctypes.c_uint8, 1),
('type', ctypes.c_uint8, 2),
('prefetchable', ctypes.c_uint8, 1),
('base_z', ctypes.c_uint32, 28),
]
resource_type = "memory"
@property
def base(self):
return self.base_z << 4
class MemoryBar64(cdata.Struct):
_pack_ = 1
_fields_ = [
('indicator', ctypes.c_uint8, 1),
('type', ctypes.c_uint8, 2),
('prefetchable', ctypes.c_uint8, 1),
('base_z', ctypes.c_uint64, 60),
]
resource_type = "memory"
@property
def base(self):
return self.base_z << 4
class IOBar(cdata.Struct):
_pack_ = 1
_fields_ = [
('indicator', ctypes.c_uint8, 1),
('reserved', ctypes.c_uint8, 1),
('base_z', ctypes.c_uint32, 30),
]
resource_type = "io_port"
@property
def base(self):
return self.base_z << 2
PCIE_BAR_SPACE_MASK = 0x1
PCIE_BAR_MEMORY_SPACE = 0x0
PCIE_BAR_IO_SPACE = 0x1
PCIE_BAR_TYPE_MASK = 0x6
PCIE_BAR_TYPE_32_BIT = 0x0
PCIE_BAR_TYPE_64_BIT = 0x4
def header_type_0_field_list(addr):
bar_list = list()
bar_addr = addr
bar_end = addr + 0x18
while bar_addr < bar_end:
bar = ctypes.c_uint32.from_address(bar_addr).value
idx = int((bar_addr - addr) / 4)
if (bar & PCIE_BAR_SPACE_MASK) == PCIE_BAR_MEMORY_SPACE:
if (bar & PCIE_BAR_TYPE_MASK) == PCIE_BAR_TYPE_64_BIT:
bar_list.append((f"bar{idx}", MemoryBar64))
bar_addr += 0x8
else:
bar_list.append((f"bar{idx}", MemoryBar32))
bar_addr += 0x4
else:
bar_list.append((f"bar{idx}", IOBar))
bar_addr += 0x4
class Bars(cdata.Struct):
_pack_ = 1
_fields_ = bar_list
def __iter__(self):
for f in self._fields_:
yield getattr(self, f[0])
return [
('bars', Bars),
('cardbus_cis_pointer', ctypes.c_uint32),
('subsystem_vendor_id', ctypes.c_uint16),
('subsystem_device_id', ctypes.c_uint16),
('expansion_rom_base_address', ctypes.c_uint32),
('capability_pointer', ctypes.c_uint8),
('reserved', ctypes.c_uint8 * 7),
('interrupt_line', ctypes.c_uint8),
('interrupt_pin', ctypes.c_uint8),
('min_gnt', ctypes.c_uint8),
('max_lat', ctypes.c_uint8),
]
def header_type_1_field_list(addr):
bar_list = list()
bar_addr = addr
bar_end = addr + 0x08
while bar_addr < bar_end:
bar = ctypes.c_uint32.from_address(addr).value
idx = int((bar_addr - addr) / 4)
if (bar & PCIE_BAR_SPACE_MASK) == PCIE_BAR_MEMORY_SPACE:
if (bar & PCIE_BAR_TYPE_MASK) == PCIE_BAR_TYPE_64_BIT:
bar_list.append((f"bar{idx}", MemoryBar64))
bar_addr += 0x8
else:
bar_list.append((f"bar{idx}", MemoryBar32))
bar_addr += 0x4
else:
bar_list.append((f"bar{idx}", IOBar))
bar_addr += 0x4
class Bars(cdata.Struct):
_pack_ = 1
_fields_ = bar_list
def __iter__(self):
for f in self._fields_:
yield getattr(self, f[0])
return [
('bars', Bars),
('primary_bus_number', ctypes.c_uint8),
('secondary_bus_number', ctypes.c_uint8),
('subordinate_bus_number', ctypes.c_uint8),
('secondary_latency_timer', ctypes.c_uint8),
('io_base', ctypes.c_uint8),
('io_limit', ctypes.c_uint8),
('secondary_status', ctypes.c_uint16),
('memory_base', ctypes.c_uint16),
('memory_limit', ctypes.c_uint16),
('prefetchable_memory_base', ctypes.c_uint16),
('prefetchable_memory_limit', ctypes.c_uint16),
('prefetchable_base_upper_32_bits', ctypes.c_uint32),
('prefetchable_limit_upper_32_bits', ctypes.c_uint32),
('io_base_upper_16_bits', ctypes.c_uint16),
('io_limit_upper_16_bits', ctypes.c_uint16),
('capability_pointer', ctypes.c_uint8),
('reserved', ctypes.c_uint8 * 3),
('expansion_rom_base_address', ctypes.c_uint32),
('interrupt_line', ctypes.c_uint8),
('interrupt_pin', ctypes.c_uint8),
('bridge_control', ctypes.c_uint16),
]
def header_field_list(addr):
common_header = Common.from_address(addr)
if common_header.header_type == 0x00:
return header_type_0_field_list(addr + ctypes.sizeof(Common))
elif common_header.header_type == 0x01:
return header_type_1_field_list(addr + ctypes.sizeof(Common))
else:
return [('data', ctypes.c_uint8 * 0x30)]
def header_factory(field_list):
class Header(cdata.Struct):
_pack_ = 1
_fields_ = copy.copy(Common._fields_) + field_list
return Header
def header(data):
"""Create class based on decode of a PCI configuration space header from raw data."""
buf = ctypes.create_string_buffer(data, len(data))
addr = ctypes.addressof(buf)
field_list = header_field_list(addr)
return header_factory(field_list).from_buffer_copy(data)