mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-08-02 08:19:16 +00:00
config_tools/acpiparser: port the ACPI module from BITS
This patch ports the ACPI parsing module from BITS (BIOS Implementation Test Suite) in order to ease the access to ACPI tables during board XML generation. This library allows accessing ACPI table fields as Python class members, getting rid of hard coding or calculating offsets within tables. Compared to the original library, this port makes the following changes. * Extract only the scripts and functions that contribute to ACPI parsing. * Separate the parser of each ACPI table into different files. * Read raw ACPI tables from Linux sysfs. * Adapt to Python 3. Tracked-On: #5649 Signed-off-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
parent
e8a76868c9
commit
ba02583f2d
30
misc/config_tools/target/acpiparser/__init__.py
Normal file
30
misc/config_tools/target/acpiparser/__init__.py
Normal file
@ -0,0 +1,30 @@
|
||||
# Copyright (C) 2021 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
import sys
|
||||
|
||||
from acpiparser.apic import APIC
|
||||
from acpiparser.asf import ASF
|
||||
from acpiparser.dmar import DMAR
|
||||
from acpiparser.facp import FACP
|
||||
from acpiparser.rtct import RTCT
|
||||
|
||||
def parse_table(signature, path=None):
|
||||
if not path:
|
||||
path = f"/sys/firmware/acpi/tables/{signature}"
|
||||
signature = signature.rstrip("!")
|
||||
fn = getattr(sys.modules[f"acpiparser.{signature.lower()}"], signature)
|
||||
return fn(path)
|
||||
|
||||
def make_parser(signature):
|
||||
def parse(path=None):
|
||||
return parse_table(signature, path)
|
||||
return parse
|
||||
|
||||
parse_apic = make_parser('APIC')
|
||||
parse_asf = make_parser('ASF!')
|
||||
parse_dmar = make_parser('DMAR')
|
||||
parse_facp = make_parser('FACP')
|
||||
parse_rtct = make_parser('RTCT')
|
68
misc/config_tools/target/acpiparser/_utils.py
Normal file
68
misc/config_tools/target/acpiparser/_utils.py
Normal file
@ -0,0 +1,68 @@
|
||||
# Copyright (C) 2021 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
import ctypes
|
||||
|
||||
import acpiparser.cdata as cdata
|
||||
import acpiparser.unpack as unpack
|
||||
|
||||
class TableHeader(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('signature', ctypes.c_char * 4),
|
||||
('length', ctypes.c_uint32),
|
||||
('revision', ctypes.c_ubyte),
|
||||
('checksum', ctypes.c_ubyte),
|
||||
('oemid', ctypes.c_char * 6),
|
||||
('oemtableid', ctypes.c_char * 8),
|
||||
('oemrevision', ctypes.c_uint32),
|
||||
('creatorid', ctypes.c_char * 4),
|
||||
('creatorrevision', ctypes.c_uint32),
|
||||
]
|
||||
|
||||
ASID_SYSTEM_MEMORY = 0
|
||||
ASID_SYSTEM_IO = 1
|
||||
ASID_PCI_CFG_SPACE = 2
|
||||
ASID_EMBEDDED_CONTROLLER = 3
|
||||
ASID_SMBUS = 4
|
||||
ASID_PCC = 0xA
|
||||
ASID_FFH = 0x7F
|
||||
|
||||
def _asid_str(asid):
|
||||
if asid >= 0xC0 and asid <= 0xff:
|
||||
return 'OEM Defined'
|
||||
_asid = {
|
||||
ASID_SYSTEM_MEMORY: 'System Memory',
|
||||
ASID_SYSTEM_IO: 'System IO',
|
||||
ASID_PCI_CFG_SPACE: 'PCI Configuration Space',
|
||||
ASID_EMBEDDED_CONTROLLER: 'Embedded Controller',
|
||||
ASID_SMBUS: 'SMBus',
|
||||
ASID_PCC: 'Platform Communications Channel (PCC)',
|
||||
ASID_FFH: 'Functional Fixed Hardware',
|
||||
}
|
||||
return _asid.get(asid, 'Reserved')
|
||||
|
||||
_access_sizes = {
|
||||
0: 'Undefined',
|
||||
1: 'Byte access',
|
||||
2: 'Word access',
|
||||
3: 'Dword access',
|
||||
4: 'Qword access',
|
||||
}
|
||||
|
||||
class GAS(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('address_space_id', ctypes.c_uint8),
|
||||
('register_bit_width', ctypes.c_uint8),
|
||||
('register_bit_offset', ctypes.c_uint8),
|
||||
('access_size', ctypes.c_uint8),
|
||||
('address', ctypes.c_uint64),
|
||||
]
|
||||
|
||||
_formats = {
|
||||
'address_space_id' : unpack.format_function("{:#x}", _asid_str),
|
||||
'access_size' : unpack.format_table("{}", _access_sizes),
|
||||
}
|
281
misc/config_tools/target/acpiparser/apic.py
Normal file
281
misc/config_tools/target/acpiparser/apic.py
Normal file
@ -0,0 +1,281 @@
|
||||
# Copyright (C) 2021 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
import ctypes
|
||||
import copy
|
||||
|
||||
import acpiparser.cdata as cdata
|
||||
import acpiparser.unpack as unpack
|
||||
from acpiparser._utils import TableHeader
|
||||
|
||||
class APICSubtable(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('subtype', ctypes.c_uint8),
|
||||
('length', ctypes.c_uint8),
|
||||
]
|
||||
|
||||
class local_apic_flags_bits(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('enabled', ctypes.c_uint32, 1),
|
||||
]
|
||||
|
||||
class local_apic_flags(cdata.Union):
|
||||
_pack_ = 1
|
||||
_anonymous_ = ("bits",)
|
||||
_fields_ = [
|
||||
('data', ctypes.c_uint32),
|
||||
('bits', local_apic_flags_bits),
|
||||
]
|
||||
|
||||
class APICSubtableLocalApic(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(APICSubtable._fields_) + [
|
||||
('proc_id', ctypes.c_uint8),
|
||||
('apic_id', ctypes.c_uint8),
|
||||
('flags', local_apic_flags),
|
||||
]
|
||||
|
||||
class APICSubtableIOApic(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(APICSubtable._fields_) + [
|
||||
('io_apic_id', ctypes.c_uint8),
|
||||
('reserved', ctypes.c_uint8),
|
||||
('io_apic_addr', ctypes.c_uint32),
|
||||
('global_sys_int_base', ctypes.c_uint32),
|
||||
]
|
||||
|
||||
mps_inti_polarity = {
|
||||
0b00: 'Conforms to bus specifications',
|
||||
0b01: 'Active high',
|
||||
0b11: 'Active low',
|
||||
}
|
||||
|
||||
mps_inti_trigger_mode = {
|
||||
0b00: 'Conforms to bus specifications',
|
||||
0b01: 'Edge-triggered',
|
||||
0b11: 'Level-triggered',
|
||||
}
|
||||
|
||||
class APICSubtable_int_flags_bits(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('polarity', ctypes.c_uint16, 2),
|
||||
('trigger_mode', ctypes.c_uint16, 2),
|
||||
]
|
||||
_formats = {
|
||||
'polarity': unpack.format_table("{}", mps_inti_polarity),
|
||||
'trigger_mode': unpack.format_table("{}", mps_inti_trigger_mode),
|
||||
}
|
||||
|
||||
class APICSubtable_int_flags(cdata.Union):
|
||||
_pack_ = 1
|
||||
_anonymous_ = ("bits",)
|
||||
_fields_ = [
|
||||
('data', ctypes.c_uint16),
|
||||
('bits', APICSubtable_int_flags_bits),
|
||||
]
|
||||
|
||||
class APICSubtableNmiIntSrc(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(APICSubtable._fields_) + [
|
||||
('flags', APICSubtable_int_flags),
|
||||
('global_sys_interrupt', ctypes.c_uint32),
|
||||
]
|
||||
|
||||
class APICSubtableLocalApicNmi(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(APICSubtable._fields_) + [
|
||||
('proc_id', ctypes.c_uint8),
|
||||
('flags', APICSubtable_int_flags),
|
||||
('lint_num', ctypes.c_uint8),
|
||||
]
|
||||
|
||||
class APICSubtableIntSrcOverride(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(APICSubtable._fields_) + [
|
||||
('bus', ctypes.c_uint8),
|
||||
('source', ctypes.c_uint8),
|
||||
('global_sys_interrupt', ctypes.c_uint32),
|
||||
('flags', APICSubtable_int_flags)
|
||||
]
|
||||
|
||||
class APICSubtableLocalx2Apic(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(APICSubtable._fields_) + [
|
||||
('reserved', ctypes.c_uint16),
|
||||
('x2apicid', ctypes.c_uint32),
|
||||
('flags', local_apic_flags),
|
||||
('uid', ctypes.c_uint32),
|
||||
]
|
||||
|
||||
class APICSubtableLocalx2ApicNmi(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(APICSubtable._fields_) + [
|
||||
('flags', APICSubtable_int_flags),
|
||||
('uid', ctypes.c_uint32),
|
||||
('lint_num', ctypes.c_uint8),
|
||||
('reserved', ctypes.c_uint8 * 3),
|
||||
]
|
||||
|
||||
_performance_interrupt_mode = {
|
||||
0: 'Level-triggered',
|
||||
1: 'Edge-triggered',
|
||||
}
|
||||
|
||||
class APICSubtableLocalGIC_flags_bits(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('enabled', ctypes.c_uint32, 1),
|
||||
('performance_interrupt_mode', ctypes.c_uint32, 1),
|
||||
]
|
||||
_formats = {
|
||||
'performance_interrupt_mode': unpack.format_table("{}", mps_inti_polarity),
|
||||
}
|
||||
|
||||
class APICSubtableLocalGIC_flags(cdata.Union):
|
||||
_pack_ = 1
|
||||
_anonymous_ = ("bits",)
|
||||
_fields_ = [
|
||||
('data', ctypes.c_uint32),
|
||||
('bits', APICSubtableLocalGIC_flags_bits),
|
||||
]
|
||||
|
||||
class APICSubtableLocalGIC(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(APICSubtable._fields_) + [
|
||||
('reserved', ctypes.c_uint16),
|
||||
('gic_id', ctypes.c_uint32),
|
||||
('uid', ctypes.c_uint32),
|
||||
('flags', APICSubtableLocalGIC_flags),
|
||||
('parking_protocol_version', ctypes.c_uint32),
|
||||
('performance_interrupt_gsiv', ctypes.c_uint32),
|
||||
('parked_address', ctypes.c_uint64),
|
||||
('physical_base_adddress', ctypes.c_uint64),
|
||||
]
|
||||
|
||||
class APICSubtableLocalGICDistributor(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(APICSubtable._fields_) + [
|
||||
('reserved1', ctypes.c_uint16),
|
||||
('gic_id', ctypes.c_uint32),
|
||||
('physical_base_adddress', ctypes.c_uint64),
|
||||
('system_vector_base', ctypes.c_uint32),
|
||||
('reserved2', ctypes.c_uint32),
|
||||
]
|
||||
|
||||
def APICSubtableUnknown_factory(_len):
|
||||
class APICSubtableUnknown(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = APICSubtable._fields_ + [
|
||||
('data', ctypes.c_uint8 * _len),
|
||||
]
|
||||
return APICSubtableUnknown
|
||||
|
||||
MADT_TYPE_LOCAL_APIC = 0
|
||||
MADT_TYPE_IO_APIC = 1
|
||||
MADT_TYPE_INT_SRC_OVERRIDE = 2
|
||||
MADT_TYPE_NMI_INT_SRC = 3
|
||||
MADT_TYPE_LOCAL_APIC_NMI = 4
|
||||
MADT_TYPE_LOCAL_X2APIC = 9
|
||||
MADT_TYPE_LOCAL_X2APIC_NMI = 0xA
|
||||
MADT_TYPE_LOCAL_GIC = 0xB
|
||||
MADT_TYPE_LOCAL_GIC_DISTRIBUTOR = 0xC
|
||||
|
||||
class APIC_table_flags_bits(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('pcat_compat', ctypes.c_uint32, 1),
|
||||
]
|
||||
|
||||
class APIC_table_flags(cdata.Union):
|
||||
_pack_ = 1
|
||||
_anonymous_ = ("bits",)
|
||||
_fields_ = [
|
||||
('data', ctypes.c_uint32),
|
||||
('bits', APIC_table_flags_bits),
|
||||
]
|
||||
|
||||
def apic_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 APIC_v3(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('header', TableHeader),
|
||||
('local_apic_address', ctypes.c_uint32),
|
||||
('flags', APIC_table_flags),
|
||||
('interrupt_controller_structures', subtables),
|
||||
]
|
||||
|
||||
@property
|
||||
def procid_apicid(self):
|
||||
procid_apicid_dict = {}
|
||||
for subtable in self.interrupt_controller_structures:
|
||||
# accumulate the dictionary
|
||||
if subtable.subtype == MADT_TYPE_LOCAL_APIC:
|
||||
if subtable.flags.bits.enabled == 1:
|
||||
procid_apicid_dict[subtable.proc_id] = subtable.apic_id
|
||||
return procid_apicid_dict
|
||||
|
||||
@property
|
||||
def uid_x2apicid(self):
|
||||
uid_x2apicid_dict = {}
|
||||
for subtable in self.interrupt_controller_structures:
|
||||
# accumulate the dictionary
|
||||
if subtable.subtype == MADT_TYPE_LOCAL_X2APIC:
|
||||
if subtable.flags.bits.enabled == 1:
|
||||
uid_x2apicid_dict[subtable.uid] = subtable.x2apicid
|
||||
return uid_x2apicid_dict
|
||||
|
||||
return APIC_v3
|
||||
|
||||
def apic_subtable_list(addr, length):
|
||||
end = addr + length
|
||||
field_list = list()
|
||||
subtable_num = 0
|
||||
while addr < end:
|
||||
subtable_num += 1
|
||||
subtable = APICSubtable.from_address(addr)
|
||||
addr += subtable.length
|
||||
if subtable.subtype == MADT_TYPE_LOCAL_APIC:
|
||||
cls = APICSubtableLocalApic
|
||||
elif subtable.subtype == MADT_TYPE_IO_APIC:
|
||||
cls = APICSubtableIOApic
|
||||
elif subtable.subtype == MADT_TYPE_INT_SRC_OVERRIDE:
|
||||
cls = APICSubtableIntSrcOverride
|
||||
elif subtable.subtype == MADT_TYPE_NMI_INT_SRC:
|
||||
cls = APICSubtableNmiIntSrc
|
||||
elif subtable.subtype == MADT_TYPE_LOCAL_APIC_NMI:
|
||||
cls = APICSubtableLocalApicNmi
|
||||
elif subtable.subtype == MADT_TYPE_LOCAL_X2APIC:
|
||||
cls = APICSubtableLocalx2Apic
|
||||
elif subtable.subtype == MADT_TYPE_LOCAL_X2APIC_NMI:
|
||||
cls = APICSubtableLocalx2ApicNmi
|
||||
elif subtable.subtype == MADT_TYPE_LOCAL_GIC:
|
||||
cls = APICSubtableLocalGIC
|
||||
elif subtable.subtype == MADT_TYPE_LOCAL_GIC_DISTRIBUTOR:
|
||||
cls = APICSubtableLocalGICDistributor
|
||||
else:
|
||||
cls = APICSubtableUnknown_factory(subtable.length - ctypes.sizeof(APICSubtable))
|
||||
field_list.append( ('subtable{}'.format(subtable_num), cls) )
|
||||
return field_list
|
||||
|
||||
def APIC(val):
|
||||
"""Create class based on decode of an APIC table from filename."""
|
||||
preamble_length = ctypes.sizeof(apic_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)
|
||||
subtable_list = apic_subtable_list(addr + preamble_length, hdr.length - preamble_length)
|
||||
return apic_factory(subtable_list).from_buffer_copy(data)
|
278
misc/config_tools/target/acpiparser/asf.py
Normal file
278
misc/config_tools/target/acpiparser/asf.py
Normal file
@ -0,0 +1,278 @@
|
||||
# Copyright (C) 2021 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
import ctypes
|
||||
import copy
|
||||
|
||||
import acpiparser.cdata as cdata
|
||||
from acpiparser._utils import TableHeader
|
||||
|
||||
class ASFSubtable(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('record_type', ctypes.c_uint8, 7),
|
||||
('last_record', ctypes.c_uint8, 1),
|
||||
('reserved', ctypes.c_uint8),
|
||||
('record_length', ctypes.c_uint16),
|
||||
]
|
||||
|
||||
def ASF_subtable_unknown_factory(data_len):
|
||||
class ASFSubtableUnknown(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(ASFSubtable._fields_) + [
|
||||
('data', ctypes.c_uint8 * data_len),
|
||||
]
|
||||
return ASFSubtableUnknown
|
||||
|
||||
class ASF_info_flags_bits(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('smbus_support', ctypes.c_uint8, 1),
|
||||
]
|
||||
|
||||
class ASF_info_flags(cdata.Union):
|
||||
_pack_ = 1
|
||||
_anonymous_ = ("bits",)
|
||||
_fields_ = [
|
||||
('data', ctypes.c_uint8),
|
||||
('bits', ASF_info_flags_bits),
|
||||
]
|
||||
|
||||
class fixed_smbus_address(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('ASF_compliant_device', ctypes.c_uint8, 1),
|
||||
('address', ctypes.c_uint8, 7),
|
||||
]
|
||||
|
||||
class ASF_info_record(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(ASFSubtable._fields_) + [
|
||||
('min_watchdog_reset_value', ctypes.c_uint8),
|
||||
('min_pollng_interval', ctypes.c_uint8),
|
||||
('system_id', ctypes.c_uint16),
|
||||
('iana_manufacturer_id', ctypes.c_uint8 * 4),
|
||||
('flags', ASF_info_flags),
|
||||
('reserved2', ctypes.c_uint8 * 3),
|
||||
]
|
||||
|
||||
class ASF_ALERTDATA(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('device_address', ctypes.c_uint8),
|
||||
('command', ctypes.c_uint8),
|
||||
('data_mask', ctypes.c_uint8),
|
||||
('compare_value', ctypes.c_uint8),
|
||||
('event_sensor_type', ctypes.c_uint8),
|
||||
('event_type', ctypes.c_uint8),
|
||||
('event_offset', ctypes.c_uint8),
|
||||
('event_source_type', ctypes.c_uint8),
|
||||
('event_severity', ctypes.c_uint8),
|
||||
('sendor_number', ctypes.c_uint8),
|
||||
('entity', ctypes.c_uint8),
|
||||
('entity_instance', ctypes.c_uint8),
|
||||
]
|
||||
|
||||
def ASF_alrt_factory(num_alerts):
|
||||
class ASF_ALRT(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(ASFSubtable._fields_) + [
|
||||
('assertion_event_mask', ctypes.c_uint8),
|
||||
('deassertion_event_mask', ctypes.c_uint8),
|
||||
('number_alerts', ctypes.c_uint8),
|
||||
('array_element_length', ctypes.c_uint8),
|
||||
('device_array', ASF_ALERTDATA * num_alerts),
|
||||
]
|
||||
return ASF_ALRT
|
||||
|
||||
class ASF_CONTROLDATA(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('function', ctypes.c_uint8),
|
||||
('device_address', ctypes.c_uint8),
|
||||
('command', ctypes.c_uint8),
|
||||
('data_value', ctypes.c_uint8),
|
||||
]
|
||||
|
||||
def ASF_rctl_factory(num_controls):
|
||||
class ASF_RCTL(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(ASFSubtable._fields_) + [
|
||||
('number_controls', ctypes.c_uint8),
|
||||
('array_element_length', ctypes.c_uint8),
|
||||
('reserved2', ctypes.c_uint16),
|
||||
('control_array', ASF_CONTROLDATA * num_controls),
|
||||
]
|
||||
return ASF_RCTL
|
||||
|
||||
class ASF_boot_options_capabilities_1_bits(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('firmware_verbosity_screen_blank', ctypes.c_uint8, 1),
|
||||
('power_button_lock', ctypes.c_uint8, 1),
|
||||
('reset_button_lock', ctypes.c_uint8, 1),
|
||||
('reserved_4_3', ctypes.c_uint8, 2),
|
||||
('lock_keyboard', ctypes.c_uint8, 1),
|
||||
('sleep_button_lock', ctypes.c_uint8, 1),
|
||||
('reserved_7', ctypes.c_uint8, 1),
|
||||
]
|
||||
|
||||
class ASF_boot_options_capabilities_1(cdata.Union):
|
||||
_pack_ = 1
|
||||
_anonymous_ = ("bits",)
|
||||
_fields_ = [
|
||||
('data', ctypes.c_uint8),
|
||||
('bits', ASF_boot_options_capabilities_1_bits),
|
||||
]
|
||||
|
||||
class ASF_boot_options_capabilities_2_bits(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('reserved_2_0', ctypes.c_uint8, 3),
|
||||
('user_password_bypass', ctypes.c_uint8, 1),
|
||||
('forced_progress_events', ctypes.c_uint8, 1),
|
||||
('firmware_verbosity_verbose', ctypes.c_uint8, 1),
|
||||
('firmware_verbosity_quiet', ctypes.c_uint8, 1),
|
||||
('configuration_data_reset', ctypes.c_uint8, 1),
|
||||
]
|
||||
|
||||
class ASF_boot_options_capabilities_2(cdata.Union):
|
||||
_pack_ = 1
|
||||
_anonymous_ = ("bits",)
|
||||
_fields_ = [
|
||||
('data', ctypes.c_uint8),
|
||||
('bits', ASF_boot_options_capabilities_2_bits),
|
||||
]
|
||||
|
||||
class ASF_special_commands_2_bits(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('force_pxe_boot', ctypes.c_uint8, 1),
|
||||
('force_hard_drive_boot', ctypes.c_uint8, 1),
|
||||
('force_hard_drive_safe_mode_boot', ctypes.c_uint8, 1),
|
||||
('force_diagnostic_boot', ctypes.c_uint8, 1),
|
||||
('force_cd_dvd_boot', ctypes.c_uint8, 1),
|
||||
('reserved', ctypes.c_uint8, 3),
|
||||
]
|
||||
|
||||
class ASF_special_commands_2(cdata.Union):
|
||||
_pack_ = 1
|
||||
_anonymous_ = ("bits",)
|
||||
_fields_ = [
|
||||
('data', ctypes.c_uint8),
|
||||
('bits', ASF_special_commands_2_bits),
|
||||
]
|
||||
|
||||
class ASF_system_capabilities_bits(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('power_cycle_reset_only_on_secure_port', ctypes.c_uint8, 1),
|
||||
('power_down_only_on_secure_port', ctypes.c_uint8, 1),
|
||||
('power_on_only_on_secure_port', ctypes.c_uint8, 1),
|
||||
('reset_only_on_secure_port', ctypes.c_uint8, 1),
|
||||
('power_cycle_reset_on_compat_or_secure_port', ctypes.c_uint8, 1),
|
||||
('power_down_on_compat_or_secure_port', ctypes.c_uint8, 1),
|
||||
('power_on_via_compat_or_secure_port', ctypes.c_uint8, 1),
|
||||
('reset_only_on_compat_or_secure_port', ctypes.c_uint8, 1),
|
||||
]
|
||||
|
||||
class ASF_system_capabilities(cdata.Union):
|
||||
_pack_ = 1
|
||||
_anonymous_ = ("bits",)
|
||||
_fields_ = [
|
||||
('data', ctypes.c_uint8),
|
||||
('bits', ASF_system_capabilities_bits),
|
||||
]
|
||||
|
||||
class ASF_rmcp(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(ASFSubtable._fields_) + [
|
||||
('boot_options_capabilities_1', ASF_boot_options_capabilities_1),
|
||||
('boot_options_capabilities_2', ASF_boot_options_capabilities_2),
|
||||
('boot_options_capabilities_3', ctypes.c_uint8),
|
||||
('boot_options_capabilities_4', ctypes.c_uint8),
|
||||
('special_commands_1', ctypes.c_uint8),
|
||||
('special_commands_2', ASF_special_commands_2),
|
||||
('system_capabilities', ASF_system_capabilities),
|
||||
('completion_code', ctypes.c_uint8),
|
||||
('iana', ctypes.c_uint8 * 4),
|
||||
('special_command', ctypes.c_uint8),
|
||||
('special_command_parameter', ctypes.c_uint8 * 2),
|
||||
('boot_options', ctypes.c_uint8 * 2),
|
||||
('oem_parameters', ctypes.c_uint8 * 2),
|
||||
]
|
||||
|
||||
def ASF_addr_record_factory(num_devices):
|
||||
|
||||
class ASF_addr_record(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(ASFSubtable._fields_) + [
|
||||
('seeprom_address', ctypes.c_uint8),
|
||||
('num_devices', ctypes.c_uint8),
|
||||
('fixed_smbus_addresses', fixed_smbus_address * num_devices),
|
||||
]
|
||||
return ASF_addr_record
|
||||
|
||||
def ASF_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 ASF_v1(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('header', TableHeader),
|
||||
('information_records', subtables),
|
||||
]
|
||||
|
||||
return ASF_v1
|
||||
|
||||
ASF_INFO = 0
|
||||
ASF_ALRT = 1
|
||||
ASF_RCTL = 2
|
||||
ASF_RMCP = 3
|
||||
ASF_ADDR = 4
|
||||
|
||||
def ASF_subtable_list(addr, length):
|
||||
end = addr + length
|
||||
field_list = list()
|
||||
subtable_num = 0
|
||||
ASF_addr_record_base_len = ctypes.sizeof(ASF_addr_record_factory(0))
|
||||
ASF_alrt_base = ASF_alrt_factory(0)
|
||||
ASF_rctl_base = ASF_rctl_factory(0)
|
||||
while addr < end:
|
||||
subtable_num += 1
|
||||
subtable = ASFSubtable.from_address(addr)
|
||||
if subtable.record_type == ASF_INFO:
|
||||
cls = ASF_info_record
|
||||
elif subtable.record_type == ASF_ALRT:
|
||||
num_alerts = ASF_alrt_base.from_address(addr).number_alerts
|
||||
cls = ASF_alrt_factory(num_alerts)
|
||||
elif subtable.record_type == ASF_RCTL:
|
||||
num_controls = ASF_rctl_base.from_address(addr).number_controls
|
||||
cls = ASF_rctl_factory(num_controls)
|
||||
elif subtable.record_type == ASF_RMCP:
|
||||
cls = ASF_rmcp
|
||||
elif subtable.record_type == ASF_ADDR:
|
||||
cls = ASF_addr_record_factory(subtable.record_length - ASF_addr_record_base_len)
|
||||
else:
|
||||
cls = (subtable.record_length - ctypes.sizeof(ASFSubtable))
|
||||
addr += subtable.record_length
|
||||
field_list.append( ('subtable{}'.format(subtable_num), cls) )
|
||||
return field_list
|
||||
|
||||
def ASF(val):
|
||||
"""Create class based on decode of an ASF! table from filename."""
|
||||
base_length = ctypes.sizeof(ASF_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 = ASF_subtable_list(addr + base_length, hdr.length - base_length)
|
||||
return ASF_factory(field_list).from_buffer_copy(data)
|
69
misc/config_tools/target/acpiparser/bitfields.py
Normal file
69
misc/config_tools/target/acpiparser/bitfields.py
Normal file
@ -0,0 +1,69 @@
|
||||
# Copyright (c) 2015, Intel Corporation
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Intel Corporation nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""Helper functions to work with bitfields.
|
||||
|
||||
Documentation frequently writes bitfields as the inclusive range [msb:lsb];
|
||||
this module provides functions to work with bitfields using msb and lsb rather
|
||||
than manually computing shifts and masks from those."""
|
||||
|
||||
def bitfield_max(msb, lsb=None):
|
||||
"""Return the largest value that fits in the bitfield [msb:lsb] (or [msb] if lsb is None)"""
|
||||
if lsb is None:
|
||||
lsb = msb
|
||||
return (1 << (msb - lsb + 1)) - 1
|
||||
|
||||
def bitmask(msb, lsb=None):
|
||||
"""Creates a mask with bits [msb:lsb] (or [msb] if lsb is None) set."""
|
||||
if lsb is None:
|
||||
lsb = msb
|
||||
return bitfield_max(msb, lsb) << lsb
|
||||
|
||||
def bitfield(value, msb, lsb=None):
|
||||
"""Shift value to fit in the bitfield [msb:lsb] (or [msb] if lsb is None).
|
||||
|
||||
Raise OverflowError if value does not fit in that bitfield."""
|
||||
if lsb is None:
|
||||
lsb = msb
|
||||
if value > bitfield_max(msb, lsb):
|
||||
if msb == lsb:
|
||||
field = "[{0}]".format(msb)
|
||||
else:
|
||||
field = "[{0}:{1}]".format(msb, lsb)
|
||||
raise OverflowError("Value {value:#x} too big for bitfield {field}".format(**locals()))
|
||||
return value << lsb
|
||||
|
||||
def getbits(value, msb, lsb=None):
|
||||
"""From the specified value, extract the bitfield [msb:lsb] (or [msb] if lsb is None)"""
|
||||
if lsb is None:
|
||||
lsb = msb
|
||||
return (value >> lsb) & bitfield_max(msb, lsb)
|
||||
|
||||
def setbits(value, fieldvalue, msb, lsb=None):
|
||||
"""In the specified value, set the bitfield [msb:lsb] (or [msb] if lsb is None) to fieldvalue"""
|
||||
value &= ~bitmask(msb, lsb)
|
||||
value |= bitfield(fieldvalue, msb, lsb)
|
||||
return value
|
201
misc/config_tools/target/acpiparser/cdata.py
Normal file
201
misc/config_tools/target/acpiparser/cdata.py
Normal file
@ -0,0 +1,201 @@
|
||||
# Copyright (c) 2015, Intel Corporation
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Intel Corporation nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""bits.cdata module."""
|
||||
|
||||
from __future__ import print_function
|
||||
import binascii
|
||||
import ctypes
|
||||
import textwrap
|
||||
import uuid
|
||||
|
||||
def print_fields(cls):
|
||||
with ttypager.page():
|
||||
print("{}".format(cls.__name__))
|
||||
print("{:20s} {:6} {:6}".format('field', 'length', 'offset'))
|
||||
for f in cls._fields_:
|
||||
a = getattr(cls, f[0])
|
||||
print("{:20s} {:6} {:6}".format(f[0], a.size, a.offset))
|
||||
|
||||
def to_bytes(var):
|
||||
return (ctypes.c_char * ctypes.sizeof(var)).from_buffer(var).raw
|
||||
|
||||
_CTYPES_HEX_TYPES = (
|
||||
ctypes.c_void_p,
|
||||
ctypes.c_uint8, ctypes.c_uint16, ctypes.c_uint32, ctypes.c_uint64,
|
||||
ctypes.c_ubyte, ctypes.c_ushort, ctypes.c_uint, ctypes.c_ulong, ctypes.c_ulonglong,
|
||||
)
|
||||
|
||||
class c_base(object):
|
||||
"""Base class for ctypes structures and unions."""
|
||||
@staticmethod
|
||||
def _formatval(t, val):
|
||||
if val is not None and t in _CTYPES_HEX_TYPES:
|
||||
return "{:#x}".format(val)
|
||||
if issubclass(t, ctypes.Array):
|
||||
if issubclass(t._type_, (ctypes.c_char, ctypes.c_wchar)):
|
||||
return "'{}'".format(val)
|
||||
else:
|
||||
return "[{}]".format(", ".join(Struct._formatval(t._type_, item) for item in val))
|
||||
return "{}".format(val)
|
||||
|
||||
|
||||
def _formatter(self, field):
|
||||
name = field[0]
|
||||
t = field[1]
|
||||
val = getattr(self, name)
|
||||
if hasattr(self, '_formats'):
|
||||
f = self._formats.get(name, None)
|
||||
if f:
|
||||
return f(val)
|
||||
if issubclass(t, (Struct, Union)):
|
||||
val._indent = self._indent
|
||||
return str(val)
|
||||
if issubclass(t, ctypes.Array):
|
||||
if issubclass(t._type_, (Struct, Union)):
|
||||
s = "["
|
||||
for item in val:
|
||||
item._indent = self._indent + " "
|
||||
s += "\n" + str(item)
|
||||
s += "]"
|
||||
return s
|
||||
return self._formatval(t, val)
|
||||
|
||||
_indent = ""
|
||||
|
||||
def _wrap(self, str, indent=True):
|
||||
line_len = 77 - len(self._indent + ' ')
|
||||
_wrapper = textwrap.TextWrapper(width=line_len, initial_indent=self._indent, subsequent_indent=self._indent + ' ')
|
||||
_wrapper_indentall = textwrap.TextWrapper(width=line_len, initial_indent=self._indent + ' ', subsequent_indent=self._indent + ' ')
|
||||
def __wrap():
|
||||
wrapper = _wrapper
|
||||
for line in str.split("\n"):
|
||||
# Preserve blank lines, for which wrapper emits an empty list
|
||||
if not line:
|
||||
yield ""
|
||||
for wrapped_line in wrapper.wrap(line):
|
||||
yield wrapped_line
|
||||
if indent:
|
||||
wrapper = _wrapper_indentall
|
||||
return '\n'.join(__wrap())
|
||||
|
||||
def preface_field(self, field):
|
||||
a = getattr(self.__class__, field[0])
|
||||
return "ofs={} ".format(a.offset)
|
||||
|
||||
def bitfield_info(self, field):
|
||||
a = getattr(self.__class__, field[0])
|
||||
bit_count = a.size >> 16
|
||||
lo_bit = a.size & 0xFFFF
|
||||
hi_bit = lo_bit + bit_count - 1
|
||||
return bit_count, hi_bit, lo_bit
|
||||
|
||||
def preface_bitfield(self, field):
|
||||
bit_count, hi_bit, lo_bit = self.bitfield_info(field)
|
||||
if bit_count > 1:
|
||||
return "bits[{}:{}]=".format(hi_bit, lo_bit)
|
||||
if bit_count == 1:
|
||||
return "bit[{}]=".format(lo_bit)
|
||||
return ""
|
||||
|
||||
def __str__(self):
|
||||
self._indent += " "
|
||||
s = "{}({})".format(self.__class__.__name__, "".join("\n{}{}={}{}".format(self.preface_field(field), field[0], self.preface_bitfield(field), self._formatter(field)) for field in self._fields_))
|
||||
self._indent = ""
|
||||
return self._wrap(s)
|
||||
|
||||
class Struct(ctypes.Structure, c_base):
|
||||
"""Base class for ctypes structures."""
|
||||
def __hash__(self):
|
||||
buf = (ctypes.c_uint8 * ctypes.sizeof(self)).from_buffer(self)
|
||||
return binascii.crc32(buf)
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(hash(self), hash(other))
|
||||
|
||||
class Union(ctypes.Union, c_base):
|
||||
"""Base class for ctypes unions."""
|
||||
def __hash__(self):
|
||||
buf = (ctypes.c_uint8 * ctypes.sizeof(self)).from_buffer(self)
|
||||
return binascii.crc32(buf)
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(hash(self), hash(other))
|
||||
|
||||
class GUID(Struct):
|
||||
_fields_ = [
|
||||
('Data', ctypes.c_ubyte * 16),
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Create a GUID. Accepts any arguments the uuid.UUID constructor
|
||||
would accept. Also accepts an instance of uuid.UUID, either as the
|
||||
first argument or as a keyword argument "uuid". As with other
|
||||
ctypes structures, passing no parameters yields a zero-initialized
|
||||
structure."""
|
||||
u = kwargs.get("uuid")
|
||||
if u is not None:
|
||||
self.uuid = u
|
||||
elif not(args) and not(kwargs):
|
||||
self.uuid = uuid.UUID(int=0)
|
||||
elif args and isinstance(args[0], uuid.UUID):
|
||||
self.uuid = args[0]
|
||||
else:
|
||||
self.uuid = uuid.UUID(*args, **kwargs)
|
||||
|
||||
def _get_uuid(self):
|
||||
return uuid.UUID(bytes_le=to_bytes(self))
|
||||
|
||||
def _set_uuid(self, u):
|
||||
ctypes.memmove(ctypes.addressof(self), ctypes.c_char_p(u.bytes_le), ctypes.sizeof(self))
|
||||
|
||||
uuid = property(_get_uuid, _set_uuid)
|
||||
|
||||
def __cmp__(self, other):
|
||||
if isinstance(other, GUID):
|
||||
return cmp(self.uuid, other.uuid)
|
||||
if isinstance(other, uuid.UUID):
|
||||
return cmp(self.uuid, other)
|
||||
return NotImplemented
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.uuid)
|
||||
|
||||
def __repr__(self):
|
||||
return "GUID({})".format(self.uuid)
|
||||
|
||||
def __str__(self):
|
||||
return "{}".format(self.uuid)
|
||||
|
||||
def _format_guid(val):
|
||||
try:
|
||||
import efi
|
||||
guid_str = efi.known_uuids.get(val.uuid, None)
|
||||
except:
|
||||
guid_str = None
|
||||
if guid_str:
|
||||
return '{} ({})'.format(val, guid_str)
|
||||
return '{}'.format(val)
|
252
misc/config_tools/target/acpiparser/dmar.py
Normal file
252
misc/config_tools/target/acpiparser/dmar.py
Normal file
@ -0,0 +1,252 @@
|
||||
# Copyright (C) 2021 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
import ctypes
|
||||
import copy
|
||||
|
||||
import acpiparser.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)
|
373
misc/config_tools/target/acpiparser/facp.py
Normal file
373
misc/config_tools/target/acpiparser/facp.py
Normal file
@ -0,0 +1,373 @@
|
||||
# Copyright (C) 2021 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
import ctypes
|
||||
import copy
|
||||
|
||||
import acpiparser.cdata as cdata
|
||||
import acpiparser.unpack as unpack
|
||||
from acpiparser._utils import TableHeader, GAS
|
||||
|
||||
_preferred_pm_profile = {
|
||||
0: 'Unspecified',
|
||||
1: 'Desktop',
|
||||
2: 'Mobile',
|
||||
3: 'Workstation',
|
||||
4: 'Enterprise Server',
|
||||
5: 'SOHO Server',
|
||||
6: 'Appliance PC',
|
||||
7: 'Performance Server',
|
||||
8: 'Tablet'
|
||||
}
|
||||
|
||||
class facp_flags_bits_v1(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('wbinvd', ctypes.c_uint32, 1),
|
||||
('wbinvd_flush', ctypes.c_uint32, 1),
|
||||
('proc_c1', ctypes.c_uint32, 1),
|
||||
('p_lvl2_up', ctypes.c_uint32, 1),
|
||||
('pwr_button', ctypes.c_uint32, 1),
|
||||
('slp_button', ctypes.c_uint32, 1),
|
||||
('fix_rtc', ctypes.c_uint32, 1),
|
||||
('rtc_s4', ctypes.c_uint32, 1),
|
||||
('tmr_val_ext', ctypes.c_uint32, 1),
|
||||
('dck_cap', ctypes.c_uint32, 1),
|
||||
]
|
||||
|
||||
class facp_flags_v1(cdata.Union):
|
||||
_pack_ = 1
|
||||
_anonymous_ = ("bits",)
|
||||
_fields_ = [
|
||||
('data', ctypes.c_uint32),
|
||||
('bits', facp_flags_bits_v1),
|
||||
]
|
||||
|
||||
class FACP_v1(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('header', TableHeader),
|
||||
('firmware_ctrl', ctypes.c_uint32),
|
||||
('dsdt', ctypes.c_uint32),
|
||||
('int_model', ctypes.c_uint8),
|
||||
('reserved0', ctypes.c_uint8),
|
||||
('sci_int', ctypes.c_uint16),
|
||||
('smi_cmd', ctypes.c_uint32),
|
||||
('acpi_enable', ctypes.c_uint8),
|
||||
('acpi_disable', ctypes.c_uint8),
|
||||
('s4bios_req', ctypes.c_uint8),
|
||||
('reserved1', ctypes.c_uint8),
|
||||
('pm1a_evt_blk', ctypes.c_uint32),
|
||||
('pm1b_evt_blk', ctypes.c_uint32),
|
||||
('pm1a_cnt_blk', ctypes.c_uint32),
|
||||
('pm1b_cnt_blk', ctypes.c_uint32),
|
||||
('pm2_cnt_blk', ctypes.c_uint32),
|
||||
('pm_tmr_blk', ctypes.c_uint32),
|
||||
('gpe0_blk', ctypes.c_uint32),
|
||||
('gpe1_blk', ctypes.c_uint32),
|
||||
('pm1_evt_len', ctypes.c_uint8),
|
||||
('pm1_cnt_len', ctypes.c_uint8),
|
||||
('pm2_cnt_len', ctypes.c_uint8),
|
||||
('pm_tmr_len', ctypes.c_uint8),
|
||||
('gpe0_blk_len', ctypes.c_uint8),
|
||||
('gpe1_blk_len', ctypes.c_uint8),
|
||||
('gpe1_base', ctypes.c_uint8),
|
||||
('reserved2', ctypes.c_uint8),
|
||||
('p_lvl2_lat', ctypes.c_uint16),
|
||||
('p_lvl3_lat', ctypes.c_uint16),
|
||||
('flush_size', ctypes.c_uint16),
|
||||
('flush_stride', ctypes.c_uint16),
|
||||
('duty_offset', ctypes.c_uint8),
|
||||
('duty_width', ctypes.c_uint8),
|
||||
('day_alrm', ctypes.c_uint8),
|
||||
('mon_alrm', ctypes.c_uint8),
|
||||
('century', ctypes.c_uint8),
|
||||
('reserved3', ctypes.c_uint8 * 3),
|
||||
('flags', facp_flags_v1),
|
||||
]
|
||||
|
||||
class facp_flags_bits_v3(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(facp_flags_bits_v1._fields_) + [
|
||||
('reset_reg_sup', ctypes.c_uint32, 1),
|
||||
('sealed_case', ctypes.c_uint32, 1),
|
||||
('headless', ctypes.c_uint32, 1),
|
||||
('cpu_sw_slp', ctypes.c_uint32, 1),
|
||||
('pci_exp_wak', ctypes.c_uint32, 1),
|
||||
('use_platform_clock', ctypes.c_uint32, 1),
|
||||
('s4_rtc_sts_valid', ctypes.c_uint32, 1),
|
||||
('remote_power_on_capable', ctypes.c_uint32, 1),
|
||||
('force_apic_cluster_mode', ctypes.c_uint32, 1),
|
||||
('force_apic_physical_destination_mode', ctypes.c_uint32, 1),
|
||||
]
|
||||
|
||||
class facp_flags_v3(cdata.Union):
|
||||
_pack_ = 1
|
||||
_anonymous_ = ("bits",)
|
||||
_fields_ = [
|
||||
('data', ctypes.c_uint32),
|
||||
('bits', facp_flags_bits_v3),
|
||||
]
|
||||
|
||||
class facp_iapc_arch_bits_v3(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('legacy_devices', ctypes.c_uint16, 1),
|
||||
('8042', ctypes.c_uint16, 1),
|
||||
('vga_not_present', ctypes.c_uint16, 1),
|
||||
('msi_not_supported', ctypes.c_uint16, 1),
|
||||
]
|
||||
|
||||
class facp_iapc_arch_v3(cdata.Union):
|
||||
_pack_ = 1
|
||||
_anonymous_ = ("bits",)
|
||||
_fields_ = [
|
||||
('data', ctypes.c_uint16),
|
||||
('bits', facp_iapc_arch_bits_v3),
|
||||
]
|
||||
|
||||
class FACP_v3(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('header', TableHeader),
|
||||
('firmware_ctrl', ctypes.c_uint32),
|
||||
('dsdt', ctypes.c_uint32),
|
||||
('reserved0', ctypes.c_uint8),
|
||||
('preferred_pm_profile', ctypes.c_uint8),
|
||||
('sci_int', ctypes.c_uint16),
|
||||
('smi_cmd', ctypes.c_uint32),
|
||||
('acpi_enable', ctypes.c_uint8),
|
||||
('acpi_disable', ctypes.c_uint8),
|
||||
('s4bios_req', ctypes.c_uint8),
|
||||
('pstate_cnt', ctypes.c_uint8),
|
||||
('pm1a_evt_blk', ctypes.c_uint32),
|
||||
('pm1b_evt_blk', ctypes.c_uint32),
|
||||
('pm1a_cnt_blk', ctypes.c_uint32),
|
||||
('pm1b_cnt_blk', ctypes.c_uint32),
|
||||
('pm2_cnt_blk', ctypes.c_uint32),
|
||||
('pm_tmr_blk', ctypes.c_uint32),
|
||||
('gpe0_blk', ctypes.c_uint32),
|
||||
('gpe1_blk', ctypes.c_uint32),
|
||||
('pm1_evt_len', ctypes.c_uint8),
|
||||
('pm1_cnt_len', ctypes.c_uint8),
|
||||
('pm2_cnt_len', ctypes.c_uint8),
|
||||
('pm_tmr_len', ctypes.c_uint8),
|
||||
('gpe0_blk_len', ctypes.c_uint8),
|
||||
('gpe1_blk_len', ctypes.c_uint8),
|
||||
('gpe1_base', ctypes.c_uint8),
|
||||
('cst_cnt', ctypes.c_uint8),
|
||||
('p_lvl2_lat', ctypes.c_uint16),
|
||||
('p_lvl3_lat', ctypes.c_uint16),
|
||||
('flush_size', ctypes.c_uint16),
|
||||
('flush_stride', ctypes.c_uint16),
|
||||
('duty_offset', ctypes.c_uint8),
|
||||
('duty_width', ctypes.c_uint8),
|
||||
('day_alrm', ctypes.c_uint8),
|
||||
('mon_alrm', ctypes.c_uint8),
|
||||
('century', ctypes.c_uint8),
|
||||
('iapc_boot_arch', facp_iapc_arch_v3),
|
||||
('reserved1', ctypes.c_uint8),
|
||||
('flags', facp_flags_v3),
|
||||
('reset_reg', GAS),
|
||||
('reset_value', ctypes.c_uint8),
|
||||
('reserved2', ctypes.c_uint8 * 3),
|
||||
('x_firmware_ctrl', ctypes.c_uint64),
|
||||
('x_dsdt', ctypes.c_uint64),
|
||||
('x_pm1a_evt_blk', GAS),
|
||||
('x_pm1b_evt_blk', GAS),
|
||||
('x_pm1a_cnt_blk', GAS),
|
||||
('x_pm1b_cnt_blk', GAS),
|
||||
('x_pm2_cnt_blk', GAS),
|
||||
('x_pm_tmr_blk', GAS),
|
||||
('x_gpe0_blk', GAS),
|
||||
('x_gpe1_blk', GAS),
|
||||
]
|
||||
|
||||
_formats = {
|
||||
'preferred_pm_profile': unpack.format_table("{}", _preferred_pm_profile),
|
||||
}
|
||||
|
||||
class facp_iapc_arch_bits_v4(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(facp_iapc_arch_bits_v3._fields_) + [
|
||||
('pcie_aspm_controls', ctypes.c_uint16, 1),
|
||||
]
|
||||
|
||||
class facp_iapc_arch_v4(cdata.Union):
|
||||
_pack_ = 1
|
||||
_anonymous_ = ("bits",)
|
||||
_fields_ = [
|
||||
('data', ctypes.c_uint16),
|
||||
('bits', facp_iapc_arch_bits_v4),
|
||||
]
|
||||
|
||||
class FACP_v4(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('header', TableHeader),
|
||||
('firmware_ctrl', ctypes.c_uint32),
|
||||
('dsdt', ctypes.c_uint32),
|
||||
('reserved0', ctypes.c_uint8),
|
||||
('preferred_pm_profile', ctypes.c_uint8),
|
||||
('sci_int', ctypes.c_uint16),
|
||||
('smi_cmd', ctypes.c_uint32),
|
||||
('acpi_enable', ctypes.c_uint8),
|
||||
('acpi_disable', ctypes.c_uint8),
|
||||
('s4bios_req', ctypes.c_uint8),
|
||||
('pstate_cnt', ctypes.c_uint8),
|
||||
('pm1a_evt_blk', ctypes.c_uint32),
|
||||
('pm1b_evt_blk', ctypes.c_uint32),
|
||||
('pm1a_cnt_blk', ctypes.c_uint32),
|
||||
('pm1b_cnt_blk', ctypes.c_uint32),
|
||||
('pm2_cnt_blk', ctypes.c_uint32),
|
||||
('pm_tmr_blk', ctypes.c_uint32),
|
||||
('gpe0_blk', ctypes.c_uint32),
|
||||
('gpe1_blk', ctypes.c_uint32),
|
||||
('pm1_evt_len', ctypes.c_uint8),
|
||||
('pm1_cnt_len', ctypes.c_uint8),
|
||||
('pm2_cnt_len', ctypes.c_uint8),
|
||||
('pm_tmr_len', ctypes.c_uint8),
|
||||
('gpe0_blk_len', ctypes.c_uint8),
|
||||
('gpe1_blk_len', ctypes.c_uint8),
|
||||
('gpe1_base', ctypes.c_uint8),
|
||||
('cst_cnt', ctypes.c_uint8),
|
||||
('p_lvl2_lat', ctypes.c_uint16),
|
||||
('p_lvl3_lat', ctypes.c_uint16),
|
||||
('flush_size', ctypes.c_uint16),
|
||||
('flush_stride', ctypes.c_uint16),
|
||||
('duty_offset', ctypes.c_uint8),
|
||||
('duty_width', ctypes.c_uint8),
|
||||
('day_alrm', ctypes.c_uint8),
|
||||
('mon_alrm', ctypes.c_uint8),
|
||||
('century', ctypes.c_uint8),
|
||||
('iapc_boot_arch', facp_iapc_arch_v4),
|
||||
('reserved1', ctypes.c_uint8),
|
||||
('flags', facp_flags_v3),
|
||||
('reset_reg', GAS),
|
||||
('reset_value', ctypes.c_uint8),
|
||||
('reserved2', ctypes.c_uint8 * 3),
|
||||
('x_firmware_ctrl', ctypes.c_uint64),
|
||||
('x_dsdt', ctypes.c_uint64),
|
||||
('x_pm1a_evt_blk', GAS),
|
||||
('x_pm1b_evt_blk', GAS),
|
||||
('x_pm1a_cnt_blk', GAS),
|
||||
('x_pm1b_cnt_blk', GAS),
|
||||
('x_pm2_cnt_blk', GAS),
|
||||
('x_pm_tmr_blk', GAS),
|
||||
('x_gpe0_blk', GAS),
|
||||
('x_gpe1_blk', GAS),
|
||||
]
|
||||
|
||||
_formats = {
|
||||
'preferred_pm_profile': unpack.format_table("{}", _preferred_pm_profile),
|
||||
}
|
||||
|
||||
class facp_flags_bits_v5(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(facp_flags_bits_v3._fields_) + [
|
||||
('hw_reduced_acpi', ctypes.c_uint32, 1),
|
||||
('low_power_s0_idle_capable', ctypes.c_uint32, 1),
|
||||
]
|
||||
|
||||
class facp_flags_v5(cdata.Union):
|
||||
_pack_ = 1
|
||||
_anonymous_ = ("bits",)
|
||||
_fields_ = [
|
||||
('data', ctypes.c_uint32),
|
||||
('bits', facp_flags_bits_v5),
|
||||
]
|
||||
|
||||
class facp_iapc_arch_bits_v5(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(facp_iapc_arch_bits_v4._fields_) + [
|
||||
('cmos_rtc_not_present', ctypes.c_uint16, 1),
|
||||
]
|
||||
|
||||
class facp_iapc_arch_v5(cdata.Union):
|
||||
_pack_ = 1
|
||||
_anonymous_ = ("bits",)
|
||||
_fields_ = [
|
||||
('data', ctypes.c_uint16),
|
||||
('bits', facp_iapc_arch_bits_v5),
|
||||
]
|
||||
|
||||
class FACP_v5(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('header', TableHeader),
|
||||
('firmware_ctrl', ctypes.c_uint32),
|
||||
('dsdt', ctypes.c_uint32),
|
||||
('reserved0', ctypes.c_uint8),
|
||||
('preferred_pm_profile', ctypes.c_uint8),
|
||||
('sci_int', ctypes.c_uint16),
|
||||
('smi_cmd', ctypes.c_uint32),
|
||||
('acpi_enable', ctypes.c_uint8),
|
||||
('acpi_disable', ctypes.c_uint8),
|
||||
('s4bios_req', ctypes.c_uint8),
|
||||
('pstate_cnt', ctypes.c_uint8),
|
||||
('pm1a_evt_blk', ctypes.c_uint32),
|
||||
('pm1b_evt_blk', ctypes.c_uint32),
|
||||
('pm1a_cnt_blk', ctypes.c_uint32),
|
||||
('pm1b_cnt_blk', ctypes.c_uint32),
|
||||
('pm2_cnt_blk', ctypes.c_uint32),
|
||||
('pm_tmr_blk', ctypes.c_uint32),
|
||||
('gpe0_blk', ctypes.c_uint32),
|
||||
('gpe1_blk', ctypes.c_uint32),
|
||||
('pm1_evt_len', ctypes.c_uint8),
|
||||
('pm1_cnt_len', ctypes.c_uint8),
|
||||
('pm2_cnt_len', ctypes.c_uint8),
|
||||
('pm_tmr_len', ctypes.c_uint8),
|
||||
('gpe0_blk_len', ctypes.c_uint8),
|
||||
('gpe1_blk_len', ctypes.c_uint8),
|
||||
('gpe1_base', ctypes.c_uint8),
|
||||
('cst_cnt', ctypes.c_uint8),
|
||||
('p_lvl2_lat', ctypes.c_uint16),
|
||||
('p_lvl3_lat', ctypes.c_uint16),
|
||||
('flush_size', ctypes.c_uint16),
|
||||
('flush_stride', ctypes.c_uint16),
|
||||
('duty_offset', ctypes.c_uint8),
|
||||
('duty_width', ctypes.c_uint8),
|
||||
('day_alrm', ctypes.c_uint8),
|
||||
('mon_alrm', ctypes.c_uint8),
|
||||
('century', ctypes.c_uint8),
|
||||
('iapc_boot_arch', facp_iapc_arch_v5),
|
||||
('reserved1', ctypes.c_uint8),
|
||||
('flags', facp_flags_v5),
|
||||
('reset_reg', GAS),
|
||||
('reset_value', ctypes.c_uint8),
|
||||
('reserved2', ctypes.c_uint8 * 3),
|
||||
('x_firmware_ctrl', ctypes.c_uint64),
|
||||
('x_dsdt', ctypes.c_uint64),
|
||||
('x_pm1a_evt_blk', GAS),
|
||||
('x_pm1b_evt_blk', GAS),
|
||||
('x_pm1a_cnt_blk', GAS),
|
||||
('x_pm1b_cnt_blk', GAS),
|
||||
('x_pm2_cnt_blk', GAS),
|
||||
('x_pm_tmr_blk', GAS),
|
||||
('x_gpe0_blk', GAS),
|
||||
('x_gpe1_blk', GAS),
|
||||
('sleep_control_reg', GAS),
|
||||
('sleep_status_reg', GAS),
|
||||
]
|
||||
|
||||
_formats = {
|
||||
'preferred_pm_profile': unpack.format_table("{}", _preferred_pm_profile),
|
||||
}
|
||||
|
||||
def FACP(val):
|
||||
"""Create class based on decode of an FACP table from filename."""
|
||||
data = open(val, mode='rb').read()
|
||||
buf = ctypes.create_string_buffer(data, len(data))
|
||||
addr = ctypes.addressof(buf)
|
||||
hdr = TableHeader.from_address(addr)
|
||||
if hdr.revision < 3:
|
||||
cls = FACP_v1
|
||||
elif hdr.revision == 3:
|
||||
cls = FACP_v3
|
||||
elif hdr.revision == 4:
|
||||
cls = FACP_v4
|
||||
else:
|
||||
cls = FACP_v5
|
||||
return cls.from_buffer_copy(data)
|
130
misc/config_tools/target/acpiparser/rtct.py
Normal file
130
misc/config_tools/target/acpiparser/rtct.py
Normal file
@ -0,0 +1,130 @@
|
||||
# Copyright (C) 2021 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
import ctypes
|
||||
import copy
|
||||
|
||||
import acpiparser.cdata as cdata
|
||||
from acpiparser._utils import TableHeader
|
||||
|
||||
class RTCTSubtable(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('size', ctypes.c_uint16),
|
||||
('format', ctypes.c_uint16),
|
||||
('type', ctypes.c_uint32),
|
||||
]
|
||||
|
||||
class RTCTSubtableRTCMBinary(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(RTCTSubtable._fields_) + [
|
||||
('address', ctypes.c_uint64),
|
||||
('size', ctypes.c_uint32),
|
||||
]
|
||||
|
||||
def RTCTSubtableWRCL3Waymasks_factory(data_len):
|
||||
class RTCTSubtableWRCL3Waymasks(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(RTCTSubtable._fields_) + [
|
||||
('waskmask', ctypes.c_uint32 * (data_len // 4)),
|
||||
]
|
||||
return RTCTSubtableWRCL3Waymasks
|
||||
|
||||
def RTCTSubtableGTL3Waymasks_factory(data_len):
|
||||
class RTCTSubtableGTL3Waymasks(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(RTCTSubtable._fields_) + [
|
||||
('waskmask', ctypes.c_uint32 * (data_len // 4)),
|
||||
]
|
||||
return RTCTSubtableGTL3Waymasks
|
||||
|
||||
def RTCTSubtableSoftwareSRAM_factory(data_len):
|
||||
class RTCTSubtableSoftwareSRAM(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(RTCTSubtable._fields_) + [
|
||||
('cache_level', ctypes.c_uint32),
|
||||
('base', ctypes.c_uint64),
|
||||
('ways', ctypes.c_uint32),
|
||||
('size', ctypes.c_uint32),
|
||||
('apic_id_tbl', ctypes.c_uint32 * ((data_len - 20) // 4)),
|
||||
]
|
||||
return RTCTSubtableSoftwareSRAM
|
||||
|
||||
def RTCTSubtableMemoryHierarchyLatency_factory(data_len):
|
||||
class RTCTSubtableMemoryHierarchyLatency(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(RTCTSubtable._fields_) + [
|
||||
('hierarchy', ctypes.c_uint32),
|
||||
('clock_cycles', ctypes.c_uint32),
|
||||
('apic_id_tbl', ctypes.c_uint32 * ((data_len - 8) // 4)),
|
||||
]
|
||||
return RTCTSubtableMemoryHierarchyLatency
|
||||
|
||||
def RTCTSubtableUnknown_factory(data_len):
|
||||
class RTCTSubtableUnknown(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = copy.copy(RTCTSubtable._fields_) + [
|
||||
('data', ctypes.c_uint8 * data_len),
|
||||
]
|
||||
return RTCTSubtableUnknown
|
||||
|
||||
ACPI_RTCT_TYPE_RTCM_BINARY = 2
|
||||
ACPI_RTCT_TYPE_WRC_L3Waymasks = 3
|
||||
ACPI_RTCT_TYPE_GT_L3Waymasks = 4
|
||||
ACPI_RTCT_TYPE_SoftwareSRAM = 5
|
||||
ACPI_RTCT_TYPE_Memory_Hierarchy_Latency = 9
|
||||
|
||||
def rtct_subtable_list(addr, length):
|
||||
end = addr + length
|
||||
field_list = list()
|
||||
subtable_num = 0
|
||||
while addr < end:
|
||||
subtable_num += 1
|
||||
subtable = RTCTSubtable.from_address(addr)
|
||||
data_len = subtable.size - ctypes.sizeof(RTCTSubtable)
|
||||
if subtable.type == ACPI_RTCT_TYPE_RTCM_BINARY:
|
||||
cls = RTCTSubtableRTCMBinary
|
||||
elif subtable.type == ACPI_RTCT_TYPE_WRC_L3Waymasks:
|
||||
cls = RTCTSubtableWRCL3Waymasks_factory(data_len)
|
||||
elif subtable.type == ACPI_RTCT_TYPE_GT_L3Waymasks:
|
||||
cls = RTCTSubtableGTL3Waymasks_factory(data_len)
|
||||
elif subtable.type == ACPI_RTCT_TYPE_SoftwareSRAM:
|
||||
cls = RTCTSubtableSoftwareSRAM_factory(data_len)
|
||||
elif subtable.type == ACPI_RTCT_TYPE_Memory_Hierarchy_Latency:
|
||||
cls = RTCTSubtableMemoryHierarchyLatency_factory(data_len)
|
||||
else:
|
||||
cls = RTCTSubtableUnknown_factory(data_len)
|
||||
addr += subtable.size
|
||||
field_list.append( ('subtable{}'.format(subtable_num), cls) )
|
||||
return field_list
|
||||
|
||||
def rtct_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 RTCT(cdata.Struct):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('header', TableHeader),
|
||||
('entries', subtables),
|
||||
]
|
||||
|
||||
return RTCT
|
||||
|
||||
def RTCT(val):
|
||||
"""Create class based on decode of an RTCT table from filename."""
|
||||
base_length = ctypes.sizeof(rtct_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 = rtct_subtable_list(addr + base_length, hdr.length - base_length)
|
||||
return rtct_factory(field_list).from_buffer_copy(data)
|
202
misc/config_tools/target/acpiparser/unpack.py
Normal file
202
misc/config_tools/target/acpiparser/unpack.py
Normal file
@ -0,0 +1,202 @@
|
||||
# Copyright (c) 2013, Intel Corporation
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Intel Corporation nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""unpack module."""
|
||||
|
||||
from collections import OrderedDict
|
||||
import struct
|
||||
|
||||
class UnpackError(Exception):
|
||||
pass
|
||||
|
||||
class Unpackable(object):
|
||||
def __init__(self, data, offset=0, size=None):
|
||||
self.data = data
|
||||
data_size = len(data)
|
||||
if offset > data_size:
|
||||
raise UnpackError("Unpackable.__init__: offset={} but len(data)={}".format(offset, data_size))
|
||||
self.offset = offset
|
||||
if size is None:
|
||||
self.size = data_size
|
||||
else:
|
||||
self.size = offset + size
|
||||
if self.size > data_size:
|
||||
raise UnpackError("Unpackable.__init__: offset+size={} but len(data)={}".format(self.size, data_size))
|
||||
|
||||
def _check_unpack(self, size):
|
||||
if self.offset + size > self.size:
|
||||
raise UnpackError("Unpackable: Attempted to unpack {} bytes, but only {} bytes remaining".format(size, self.size - self.offset))
|
||||
|
||||
def skip(self, size):
|
||||
self._check_unpack(size)
|
||||
self.offset += size
|
||||
|
||||
def unpack(self, fmt):
|
||||
try:
|
||||
l = struct.calcsize(fmt)
|
||||
self._check_unpack(l)
|
||||
value = struct.unpack_from(fmt, self.data, self.offset)
|
||||
self.offset += l
|
||||
return value
|
||||
except struct.error as e:
|
||||
raise UnpackError("Unpackable.unpack: " + str(e))
|
||||
|
||||
def unpack_one(self, fmt):
|
||||
return self.unpack(fmt)[0]
|
||||
|
||||
def unpack_peek(self, fmt):
|
||||
try:
|
||||
l = struct.calcsize(fmt)
|
||||
self._check_unpack(l)
|
||||
return struct.unpack_from(fmt, self.data, self.offset)
|
||||
except struct.error as e:
|
||||
raise UnpackError("Unpackable.unpack_peek: " + str(e))
|
||||
|
||||
def unpack_peek_one(self, fmt):
|
||||
return self.unpack_peek(fmt)[0]
|
||||
|
||||
def unpack_peek_raw(self, size):
|
||||
"""Peek at the specified number of bytes as a str"""
|
||||
self._check_unpack(size)
|
||||
return self.data[self.offset:self.offset+size]
|
||||
|
||||
def unpack_peek_rest(self):
|
||||
"""Peek at the remainder of the unpackable as a str"""
|
||||
return self.data[self.offset:self.size]
|
||||
|
||||
def unpack_raw(self, size):
|
||||
"""Unpack the specified number of bytes as a str"""
|
||||
self._check_unpack(size)
|
||||
old_offset = self.offset
|
||||
self.offset += size
|
||||
return self.data[old_offset:self.offset]
|
||||
|
||||
def unpack_rest(self):
|
||||
"""Return the remainder of the unpackable as a str"""
|
||||
offset = self.offset
|
||||
self.offset = self.size
|
||||
return self.data[offset:self.size]
|
||||
|
||||
def unpack_unpackable(self, size):
|
||||
"""Unpack the specified number of bytes as an Unpackable"""
|
||||
u = Unpackable(self.data, self.offset, size)
|
||||
self.offset += size
|
||||
return u
|
||||
|
||||
def at_end(self):
|
||||
return self.offset == self.size
|
||||
|
||||
class StructError(Exception):
|
||||
pass
|
||||
|
||||
class Struct(object):
|
||||
def __init__(self):
|
||||
self.fields = OrderedDict()
|
||||
|
||||
@classmethod
|
||||
def unpack(cls, u):
|
||||
s = cls()
|
||||
for field in cls._unpack(u):
|
||||
s.add_field(*field)
|
||||
return s
|
||||
|
||||
def add_field(self, name, value, fmt=None):
|
||||
if hasattr(self, name):
|
||||
raise StructError("Internal error: Duplicate Struct field name {}".format(name))
|
||||
if fmt is None:
|
||||
if isinstance(value, (int, long)) and not isinstance(value, bool):
|
||||
fmt = "{:#x}".format
|
||||
else:
|
||||
fmt = "{!r}".format
|
||||
elif isinstance(fmt, str):
|
||||
fmt = fmt.format
|
||||
elif not callable(fmt):
|
||||
raise StructError("Internal error: Expected a format string or callable, but got: {}".format(fmt))
|
||||
setattr(self, name, value)
|
||||
self.fields[name] = fmt
|
||||
|
||||
def format_field(self, name):
|
||||
return self.fields[name](getattr(self, name))
|
||||
|
||||
def __repr__(self):
|
||||
return "{}({})".format(self.__class__.__name__, ", ".join("{}={}".format(k, self.format_field(k)) for k in self.fields.iterkeys()))
|
||||
|
||||
def __iter__(self):
|
||||
return (getattr(self, k) for k in self.fields.iterkeys())
|
||||
|
||||
def __eq__(self, other):
|
||||
if type(self) is not type(other):
|
||||
return NotImplemented
|
||||
return self.fields.keys() == other.fields.keys() and all(getattr(self, name) == getattr(other, name) for name in self.fields.iterkeys())
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(tuple((name, getattr(self, name)) for name in self.fields.iterkeys()))
|
||||
|
||||
def format_each(fmt_one):
|
||||
def f(it):
|
||||
return "({})".format(", ".join(fmt_one.format(i) for i in it))
|
||||
return f
|
||||
|
||||
format_each_hex = format_each("{:#x}")
|
||||
|
||||
def format_table(fmt, table, default='Reserved'):
|
||||
def f(value):
|
||||
return "{} ({})".format(fmt.format(value), table.get(value, default))
|
||||
return f
|
||||
|
||||
def format_function(fmt, function):
|
||||
def f(value):
|
||||
return "{} ({})".format(fmt.format(value), function(value))
|
||||
return f
|
||||
|
||||
def reserved_None(fmt="{!r}"):
|
||||
def f(value):
|
||||
if value is None:
|
||||
return "Reserved"
|
||||
return fmt.format(value)
|
||||
return f
|
||||
|
||||
def unpack_all(u, structs, *args):
|
||||
"""Keep constructing structs from the unpackable u until it runs out of data.
|
||||
|
||||
structs should consist of a list of Struct subclasses to be tried in order.
|
||||
Each of them should return None from their constructor if they're not the
|
||||
correct type to unpack the next chunk of data. Any catch-all generic
|
||||
structure should apepar last in the list. Raises a StructError if no
|
||||
struct matches."""
|
||||
def _substructs():
|
||||
while not u.at_end():
|
||||
for s in structs:
|
||||
temp = s(u, *args)
|
||||
if temp is not None:
|
||||
yield temp
|
||||
break
|
||||
else:
|
||||
raise StructError("Internal error: unable to unpack any structure at byte {} of unpackable".format(u.offset))
|
||||
return tuple(_substructs())
|
Loading…
Reference in New Issue
Block a user