acrn-hypervisor/misc/config_tools/board_inspector/acpiparser/dmar.py
Junjie Mao bd4ddbd31d board-inspector: reorganize the scripts
This patch reorganize the files of the board inspector as follows.

1. Rename the directory name from `target` to `board_inspector`, in order to
   align with the name used in ACRN documentation.
2. Move the scripts that generate the current board XML into the `legacy`
   sub-directory. The legacy nodes will be removed after transitioning to the
   new board XML schema completely,
3. Add the main script `cli.py` which is the command line interface of the board
   inspector.

v1 -> v2:
 - Rename `run.py` to `cli.py`.

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

253 lines
7.7 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
from acpiparser._utils import TableHeader
class DMARSubtable(cdata.Struct):
_pack_ = 1
_fields_ = [
('subtype', ctypes.c_uint16),
('length', ctypes.c_uint16),
]
class DMARDeviceScopePath(cdata.Struct):
_pack_ = 1
_fields_ = [
('pci_device', ctypes.c_uint8),
('pci_function', ctypes.c_uint8),
]
def DMARDeviceScope_factory(num_dev_scope_path):
class DMARDeviceScope(cdata.Struct):
_pack_ = 1
_fields_ = [
('type', ctypes.c_uint8),
('length', ctypes.c_uint8),
('reserved', ctypes.c_uint16),
('enumeration_id', ctypes.c_uint8),
('start_bus_number', ctypes.c_uint8),
('paths', DMARDeviceScopePath * num_dev_scope_path),
]
return DMARDeviceScope
def dmar_device_scope_list(addr, length):
end = addr + length
field_list = list()
subtable_num = 0
base_len_DMARDeviceScope = ctypes.sizeof(DMARDeviceScope_factory(0))
len_DMARDeviceScopePath = ctypes.sizeof(DMARDeviceScopePath)
while addr < end:
subtable_num += 1
subtable = DMARDeviceScope_factory(0).from_address(addr)
num_dev_scope_path = (subtable.length - base_len_DMARDeviceScope) // len_DMARDeviceScopePath
cls = DMARDeviceScope_factory(num_dev_scope_path)
addr += subtable.length
field_list.append( ('subtable{}'.format(subtable_num), cls) )
return field_list
class drhd_flags_bits(cdata.Struct):
_pack_ = 1
_fields_ = [
('include_pci_all', ctypes.c_uint8, 1),
]
class drhd_flags(cdata.Union):
_pack_ = 1
_anonymous_ = ("bits",)
_fields_ = [
('data', ctypes.c_uint8),
('bits', drhd_flags_bits),
]
def DMARSubtableDRHD_factory(field_list):
class subtables(cdata.Struct):
_pack_ = 1
_fields_ = field_list
def __iter__(self):
for f in self._fields_:
yield getattr(self, f[0])
class DMARSubtableDRHD(cdata.Struct):
_pack_ = 1
_fields_ = copy.copy(DMARSubtable._fields_) + [
('flags', drhd_flags),
('reserved', ctypes.c_uint8),
('segment_number', ctypes.c_uint16),
('base_address', ctypes.c_uint64),
('device_scopes', subtables)
]
return DMARSubtableDRHD
def DMARSubtableRMRR_factory(field_list):
class subtables(cdata.Struct):
_pack_ = 1
_fields_ = field_list
def __iter__(self):
for f in self._fields_:
yield getattr(self, f[0])
class DMARSubtableRMRR(cdata.Struct):
_pack_ = 1
_fields_ = copy.copy(DMARSubtable._fields_) + [
('reserved', ctypes.c_uint16),
('segment_number', ctypes.c_uint16),
('base_address', ctypes.c_uint64),
('limit_address', ctypes.c_uint64),
('device_scopes', subtables),
]
return DMARSubtableRMRR
class atsr_flags_bits(cdata.Struct):
_pack_ = 1
_fields_ = [
('all_ports', ctypes.c_uint8, 1),
]
class atsr_flags(cdata.Union):
_pack_ = 1
_anonymous_ = ("bits",)
_fields_ = [
('data', ctypes.c_uint8),
('bits', atsr_flags_bits),
]
def DMARSubtableATSR_factory(field_list):
class subtables(cdata.Struct):
_pack_ = 1
_fields_ = field_list
def __iter__(self):
for f in self._fields_:
yield getattr(self, f[0])
class DMARSubtableATSR(cdata.Struct):
_pack = 1
_fields_ = copy.copy(DMARSubtable._fields_) + [
('flags', atsr_flags),
('reserved', ctypes.c_uint8),
('segment_number', ctypes.c_uint16),
('device_scopes', subtables),
]
return DMARSubtableATSR
class DMARSubtableRHSA(cdata.Struct):
_pack = 1
_fields_ = copy.copy(DMARSubtable._fields_) + [
('reserved', ctypes.c_uint32),
('base_address', ctypes.c_uint64),
('proximity_domain', ctypes.c_uint32),
]
def DMARSubTableANDD_factory(obj_name_len):
class DMARSubTableANDD(cdata.Struct):
_pack = 1
_fields_ = copy.copy(DMARSubtable._fields_) + [
('reserved', ctypes.c_uint8 * 3),
('device_num', ctypes.c_uint8),
('object_name', ctypes.c_char * obj_name_len),
]
return DMARSubTableANDD
def DMARSubtableUnknown_factory(data_len):
class DMARSubtableUnknown(cdata.Struct):
_pack = 1
_fields_ = copy.copy(DMARSubtable._fields_) + [
('data', ctypes.c_uint8 * data_len),
]
return DMARSubtableUnknown
ACPI_DMAR_TYPE_DRHD = 0
ACPI_DMAR_TYPE_RMRR = 1
ACPI_DMAR_TYPE_ATSR = 2
ACPI_DMAR_TYPE_RHSA = 3
ACPI_DMAR_TYPE_ANDD = 4
def dmar_subtable_list(addr, length):
end = addr + length
field_list = list()
subtable_num = 0
base_len_DRHD = ctypes.sizeof(DMARSubtableDRHD_factory(list()))
base_len_RMRR = ctypes.sizeof(DMARSubtableRMRR_factory(list()))
base_len_ATSR = ctypes.sizeof(DMARSubtableATSR_factory(list()))
base_len_ANDD = ctypes.sizeof(DMARSubTableANDD_factory(0))
while addr < end:
subtable_num += 1
subtable = DMARSubtable.from_address(addr)
if subtable.subtype == ACPI_DMAR_TYPE_DRHD:
next_field_list = dmar_device_scope_list(addr + base_len_DRHD, subtable.length - base_len_DRHD)
cls = DMARSubtableDRHD_factory(next_field_list)
elif subtable.subtype == ACPI_DMAR_TYPE_RMRR:
next_field_list = dmar_device_scope_list(addr + base_len_RMRR, subtable.length - base_len_RMRR)
cls = DMARSubtableRMRR_factory(next_field_list)
elif subtable.subtype == ACPI_DMAR_TYPE_ATSR:
next_field_list = dmar_device_scope_list(addr + base_len_ATSR, subtable.length - base_len_ATSR)
cls = DMARSubtableATSR_factory(next_field_list)
elif subtable.subtype == ACPI_DMAR_TYPE_RHSA:
cls = DMARSubtableRHSA
elif subtable.subtype == ACPI_DMAR_TYPE_ANDD:
cls = DMARSubTableANDD_factory(subtable.length - base_len_ANDD)
else:
cls = DMARSubtableUnknown_factory(subtable.length - ctypes.sizeof(DMARSubtable))
addr += subtable.length
field_list.append( ('subtable{}'.format(subtable_num), cls) )
return field_list
class dmar_flags_bits(cdata.Struct):
_pack_ = 1
_fields_ = [
('intr_remap', ctypes.c_uint8, 1),
('x2apic_opt_out', ctypes.c_uint8, 1),
]
class dmar_flags(cdata.Union):
_pack_ = 1
_anonymous_ = ("bits",)
_fields_ = [
('data', ctypes.c_uint8),
('bits', dmar_flags_bits),
]
def dmar_factory(field_list):
class subtables(cdata.Struct):
_pack_ = 1
_fields_ = field_list
def __iter__(self):
for f in self._fields_:
yield getattr(self, f[0])
class DMAR_v1(cdata.Struct):
_pack = 1
_fields_ = [
('header', TableHeader),
('host_addr_width', ctypes.c_uint8),
('flags', ctypes.c_uint8),
('reserved', ctypes.c_uint8 * 10),
('remapping_structures', subtables),
]
return DMAR_v1
def DMAR(val):
"""Create class based on decode of an DMAR table from filename."""
base_length = ctypes.sizeof(dmar_factory(list()))
data = open(val, mode='rb').read()
buf = ctypes.create_string_buffer(data, len(data))
addr = ctypes.addressof(buf)
hdr = TableHeader.from_address(addr)
field_list = dmar_subtable_list(addr + base_length, hdr.length - base_length)
return dmar_factory(field_list).from_buffer_copy(data)