From 52c3ed7e091c0cc33c7bdcf739c8b40b61eb51e1 Mon Sep 17 00:00:00 2001 From: Junjie Mao Date: Tue, 27 Jul 2021 14:08:42 +0800 Subject: [PATCH] board_inspector: add AML templates to board XML This patch adds AML template (in XML hexBinary format) for each device to board XMLs. For now these templates contain the following objects if they exists in the physical DSDT: - Device identification objects: _ADR, _HID, _UID and _STR - _CRS which encodes the current resources consumed by the device - _STA which encodes the status of the device An AML template is always a DefScope with a single DefDevice so that they can be appended anywhere in the vDSDT. v1 -> v2: * Remove the temporary visitor that collects cross-device dependencies. Such check will be replaced with another visitor introduced in the next patch. v2 -> v3: * The AML templates are now DefDevice objects with their names being the full namepath. The vDSDT generator will take care of this and organize the objects properly. Tracked-On: #6287 Signed-off-by: Junjie Mao --- .../board_inspector/extractors/50-acpi.py | 53 +++++++++++++++++-- .../board_inspector/extractors/90-sorting.py | 2 +- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/misc/config_tools/board_inspector/extractors/50-acpi.py b/misc/config_tools/board_inspector/extractors/50-acpi.py index cd7bd7b7f..1ed76a8a9 100644 --- a/misc/config_tools/board_inspector/extractors/50-acpi.py +++ b/misc/config_tools/board_inspector/extractors/50-acpi.py @@ -8,13 +8,19 @@ import lxml.etree from collections import defaultdict from acpiparser import parse_dsdt, parse_resource_data, parse_pci_routing +from acpiparser.aml.tree import Visitor, Direction +import acpiparser.aml.builder as builder import acpiparser.aml.context as context +import acpiparser.aml.datatypes as datatypes from acpiparser.aml.interpreter import ConcreteInterpreter from acpiparser.aml.exception import UndefinedSymbol, FutureWork +from acpiparser.aml.visitors import GenerateBinaryVisitor from acpiparser.rdt import * from extractors.helpers import add_child, get_node +device_objects = defaultdict(lambda: {}) + def parse_eisa_id(eisa_id): chars = [ (eisa_id & 0x7c) >> 2, # Bit 6:2 of the first byte @@ -111,6 +117,14 @@ resource_parsers = { (1, LARGE_RESOURCE_ITEM_EXTENDED_ADDRESS_SPACE): parse_address_space_resource, } +def add_object_to_device(context, device_path, obj_name, result): + if not obj_name in device_objects[device_path].keys(): + tree = builder.build_value(result) + if tree: + device_objects[device_path][obj_name] = builder.DefName(obj_name, tree) + else: + logging.warning(f"{device_path}.{obj_name}: will not added to vACPI due to unrecognized type: {result.__class__.__name__}") + def fetch_device_info(devices_node, interpreter, namepath): logging.info(f"Fetch information about device object {namepath}") @@ -123,14 +137,17 @@ def fetch_device_info(devices_node, interpreter, namepath): sta = None if interpreter.context.has_symbol(f"{namepath}._STA"): - sta = interpreter.interpret_method_call(f"{namepath}._STA").get() + result = interpreter.interpret_method_call(f"{namepath}._STA") + sta = result.get() if sta & 0x1 == 0: return + add_object_to_device(interpreter.context, namepath, "_STA", result) # Hardware ID hid = "" if interpreter.context.has_symbol(f"{namepath}._HID"): - hid = interpreter.interpret_method_call(f"{namepath}._HID").get() + result = interpreter.interpret_method_call(f"{namepath}._HID") + hid = result.get() if isinstance(hid, str): pass elif isinstance(hid, int): @@ -141,6 +158,7 @@ def fetch_device_info(devices_node, interpreter, namepath): hid = hex(hid) else: hid = "" + add_object_to_device(interpreter.context, namepath, "_HID", result) # Compatible ID cids = [] @@ -169,20 +187,32 @@ def fetch_device_info(devices_node, interpreter, namepath): for cid in cids: add_child(element, "compatible_id", cid) + # Unique ID + uid = "" + if interpreter.context.has_symbol(f"{namepath}._UID"): + result = interpreter.interpret_method_call(f"{namepath}._UID") + uid = result.get() + add_child(element, "acpi_uid", str(uid)) + add_object_to_device(interpreter.context, namepath, "_UID", result) + # Description if interpreter.context.has_symbol(f"{namepath}._STR"): - desc = interpreter.interpret_method_call(f"{namepath}._STR").get().decode(encoding="utf-16").strip("\00") + result = interpreter.interpret_method_call(f"{namepath}._STR") + desc = result.get().decode(encoding="utf-16").strip("\00") element.set("description", desc) + add_object_to_device(interpreter.context, namepath, "_STR", result) # Address if interpreter.context.has_symbol(f"{namepath}._ADR"): - adr = interpreter.interpret_method_call(f"{namepath}._ADR").get() + result = interpreter.interpret_method_call(f"{namepath}._ADR") + adr = result.get() if isinstance(adr, int): adr = hex(adr) if len(element.xpath(f"../*[@address='{adr}']")) > 0: logging.info(f"{namepath} has siblings with duplicated address {adr}.") else: element.set("address", hex(adr) if isinstance(adr, int) else adr) + add_object_to_device(interpreter.context, namepath, "_ADR", result) # Status if sta is not None: @@ -194,7 +224,8 @@ def fetch_device_info(devices_node, interpreter, namepath): # Resources if interpreter.context.has_symbol(f"{namepath}._CRS"): - data = interpreter.interpret_method_call(f"{namepath}._CRS").get() + result = interpreter.interpret_method_call(f"{namepath}._CRS") + data = result.get() rdt = parse_resource_data(data) for idx, item in enumerate(rdt.items): @@ -204,6 +235,8 @@ def fetch_device_info(devices_node, interpreter, namepath): else: add_child(element, "resource", type=item.__class__.__name__, id=f"res{idx}") + add_object_to_device(interpreter.context, namepath, "_CRS", result) + # PCI interrupt routing if interpreter.context.has_symbol(f"{namepath}._PRT"): pkg = interpreter.interpret_method_call(f"{namepath}._PRT") @@ -261,4 +294,14 @@ def extract(board_etree): except Exception as e: logging.info(f"Fetch information about device object {device.name} failed: {str(e)}") + visitor = GenerateBinaryVisitor() + for dev, objs in device_objects.items(): + element = get_node(devices_node, f"//device[acpi_object='{dev}']") + if element is not None: + tree = builder.DefDevice( + builder.PkgLength(), + dev, + builder.TermList(*list(objs.values()))) + add_child(element, "aml_template", visitor.generate(tree).hex()) + advanced = True diff --git a/misc/config_tools/board_inspector/extractors/90-sorting.py b/misc/config_tools/board_inspector/extractors/90-sorting.py index 82d485fc2..2d2cf7f8e 100644 --- a/misc/config_tools/board_inspector/extractors/90-sorting.py +++ b/misc/config_tools/board_inspector/extractors/90-sorting.py @@ -23,7 +23,7 @@ def getkey(child): return 0xFFFFFFFF tags = ["vendor", "identifier", "subsystem_vendor", "subsystem_identifier", "class", - "acpi_object", "compatible_id", "status", + "acpi_object", "compatible_id", "acpi_uid", "aml_template", "status", "resource", "capability", "interrupt_pin_routing", "bus", "device"] if child.tag == "resource":