diff --git a/misc/config_tools/board_inspector/acpiparser/__init__.py b/misc/config_tools/board_inspector/acpiparser/__init__.py index e8fcbe093..126dcea32 100644 --- a/misc/config_tools/board_inspector/acpiparser/__init__.py +++ b/misc/config_tools/board_inspector/acpiparser/__init__.py @@ -11,6 +11,7 @@ from acpiparser.dmar import DMAR from acpiparser.dsdt import DSDT from acpiparser.facp import FACP from acpiparser.rtct import RTCT +from acpiparser.tpm2 import TPM2 def parse_table(signature, path=None): if not path: @@ -29,6 +30,7 @@ parse_asf = make_parser('ASF!') parse_dsdt = make_parser('DSDT') parse_dmar = make_parser('DMAR') parse_facp = make_parser('FACP') +parse_tpm2 = make_parser('TPM2') def parse_rtct(path=None): if not path: diff --git a/misc/config_tools/board_inspector/acpiparser/tpm2.py b/misc/config_tools/board_inspector/acpiparser/tpm2.py new file mode 100644 index 000000000..1a1adc841 --- /dev/null +++ b/misc/config_tools/board_inspector/acpiparser/tpm2.py @@ -0,0 +1,51 @@ +# Copyright (C) 2021 Intel Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +import ctypes +import logging + +import lib.cdata as cdata +from acpiparser._utils import TableHeader + +def tpm2_optional_data(data_len): + start_method_data_len = 0 + has_log_area = False + if data_len <= 12: + start_method_data_len = data_len + elif data_len == 24: + start_method_data_len = 12 + has_log_area = True + else: + start_method_data_len = 12 + logging.warning(f"TPM2 data length: {data_len + 52} is greater than 64 bytes but less than 76 bytes.") + logging.warning(f"The TPM2 data is still processed but the 65 to {data_len + 52} bytes are discard.") + return start_method_data_len, has_log_area + +def tpm2_factory(start_method_data_len, has_log_area): + class TPM2(cdata.Struct): + _pack_ = 1 + _fields_ = [ + ('header', TableHeader), + ('platform_class', ctypes.c_uint16), + ('reserved', ctypes.c_uint16), + ('address_of_control_area', ctypes.c_uint64), + ('start_method', ctypes.c_uint32), + ('start_method_specific_parameters', ctypes.c_ubyte * start_method_data_len), + ] + ([ + ('log_area_minimum_length', ctypes.c_uint32), + ('log_area_start_address', ctypes.c_uint64), + ] if has_log_area else []) + + return TPM2 + +def TPM2(val): + """Create class based on decode of a TPM2 table from filename.""" + if isinstance(val, str): + base_length = 52 + data = open(val, mode='rb').read() + start_method_data_len, has_log_area = tpm2_optional_data(len(data) - base_length) + return tpm2_factory(start_method_data_len, has_log_area).from_buffer_copy(data) + elif isinstance(val, bytearray): + return tpm2_factory(12, True).from_buffer(val) if len(val) > 64 else tpm2_factory(12, False).from_buffer(val) diff --git a/misc/config_tools/board_inspector/extractors/50-acpi.py b/misc/config_tools/board_inspector/extractors/50-acpi.py index fea1a183a..489e5a6b0 100644 --- a/misc/config_tools/board_inspector/extractors/50-acpi.py +++ b/misc/config_tools/board_inspector/extractors/50-acpi.py @@ -3,10 +3,10 @@ # SPDX-License-Identifier: BSD-3-Clause # +import ctypes import logging -import lxml.etree -from acpiparser import parse_dsdt +from acpiparser import parse_dsdt, parse_tpm2 from acpiparser.aml.interpreter import ConcreteInterpreter from acpiparser.aml.exception import UndefinedSymbol, FutureWork from acpiparser.rdt import * @@ -95,6 +95,23 @@ def parse_extended_irq(item, elem): for irq in item._INT: add_child(elem, "resource", type="irq", int=hex(irq)) +def parse_tpm(elem): + try: + tpm2 = parse_tpm2() + + control_area = add_child(elem, "capability", None, id="control_area") + add_child(control_area, "address_of_control_area", hex(tpm2.address_of_control_area)) + start_method = add_child(elem, "capability", None, id="start_method") + add_child(start_method, "value", hex(tpm2.start_method)) + for parameter in tpm2.start_method_specific_parameters: + add_child(start_method, "parameter", hex(parameter)) + if hasattr(tpm2, "log_area_minimum_length"): + add_child(elem, "capability", None, id="log_area") + except Exception as e: + logging.info(f"Parse ACPI TPM2 failed: {str(e)}") + logging.info(f"Will not extract information from ACPI TPM2") + return + resource_parsers = { (0, SMALL_RESOURCE_ITEM_IRQ_FORMAT): parse_irq, (0, SMALL_RESOURCE_ITEM_IO_PORT): parse_io_port, @@ -145,6 +162,9 @@ def fetch_device_info(devices_node, interpreter, namepath): element.tag = "bus" element.set("type", buses[hid]) + if hid == "MSFT0101": + parse_tpm(element) + # Address if interpreter.context.has_symbol(f"{namepath}._ADR"): adr = interpreter.interpret_method_call(f"{namepath}._ADR").get()