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 <junjie.mao@intel.com>
This commit is contained in:
Junjie Mao 2021-07-27 14:08:42 +08:00 committed by wenlingz
parent 6ccd7660a4
commit 52c3ed7e09
2 changed files with 49 additions and 6 deletions

View File

@ -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 = "<unknown>"
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

View File

@ -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":