From 3bcb3146ad570f9f7eed20b48eb322a862146b5e Mon Sep 17 00:00:00 2001 From: Junjie Mao Date: Fri, 16 Jul 2021 14:47:31 +0800 Subject: [PATCH] board_inspector: improve readability and performance of AML parser This patch refines the AML parser to improve its readability and performance in the following ways. 1. A Tree object now has the parts of the corresponding object being member fields. As an example, a Tree with label `DefMethod` now has members `NameString`, `MethodFlags` and `TermList`. 2. It is now possible to assign names each part of an object. The grammar is updated to assign different names to the parts with the same type in the same object. 3. Invocation to intermediate factories is now skipped. As an example, when parsing a ByteConst that acts as a ByteIndex, the original implementation invokes the following factories in sequence: ByteIndex -> TermArg -> DataObject -> ComputationalData -> ByteConst The factories TermArg, DataObject and ComputationalData does nothing but forward the parsing to the next-level factory according to the opcode of the next object. With this patch, the invocation sequence becomes: ByteIndex -> ByteConst i.e. ByteIndex directly passes to ByteConst which can parse the next opcode. Tracked-On: #6298 Signed-off-by: Junjie Mao --- .../board_inspector/acpiparser/aml/context.py | 6 +- .../acpiparser/aml/datatypes.py | 59 +++-- .../board_inspector/acpiparser/aml/grammar.py | 191 +++++++++------- .../acpiparser/aml/interpreter.py | 34 +-- .../board_inspector/acpiparser/aml/parser.py | 214 +++++++++++------- .../board_inspector/acpiparser/aml/tree.py | 77 +++---- .../acpiparser/aml/visitors.py | 13 +- .../board_inspector/acpiparser/dsdt.py | 3 +- 8 files changed, 329 insertions(+), 268 deletions(-) diff --git a/misc/config_tools/board_inspector/acpiparser/aml/context.py b/misc/config_tools/board_inspector/acpiparser/aml/context.py index 72ba78701..44f5d0d60 100644 --- a/misc/config_tools/board_inspector/acpiparser/aml/context.py +++ b/misc/config_tools/board_inspector/acpiparser/aml/context.py @@ -57,13 +57,13 @@ class OperationFieldDecl(NamedDecl): print(f"{self.name}: {self.__class__.__name__}, {self.length} bits") class AliasDecl(NamedDecl): - def __init__(self, name, target, tree): + def __init__(self, name, source, tree): super().__init__(name, tree) self.name = name - self.target = target + self.source = source def dump(self): - print(f"{self.name}: {self.__class__.__name__}, aliasing {self.target}") + print(f"{self.name}: {self.__class__.__name__}, aliasing {self.source}") class MethodDecl(NamedDecl): def __init__(self, name, nargs, tree): diff --git a/misc/config_tools/board_inspector/acpiparser/aml/datatypes.py b/misc/config_tools/board_inspector/acpiparser/aml/datatypes.py index 9fa4a2378..4e1b52401 100644 --- a/misc/config_tools/board_inspector/acpiparser/aml/datatypes.py +++ b/misc/config_tools/board_inspector/acpiparser/aml/datatypes.py @@ -48,10 +48,10 @@ class BufferBase(Object): self.__length = length self.__fields = {} # name -> (offset, bitwidth, access_width) - def read(self, norm_idx, bit_width): + def read(self, byte_idx, bit_width): return NotImplementedError(self.__class__.__name__) - def write(self, norm_idx, value, bit_width): + def write(self, byte_idx, value, bit_width): return NotImplementedError(self.__class__.__name__) def create_field(self, name, offset, bitwidth, access_width): @@ -69,23 +69,24 @@ class BufferBase(Object): # Bits out of byte boundary if bit_idx % access_width > 0: - norm_idx = floor(bit_idx / access_width) + # byte_idx shall be (access_width // 8)-byte aligned + byte_idx = (bit_idx // access_width) * (access_width // 8) bit_count = (access_width - bit_idx % access_width) if bit_count > bit_remaining: bit_count = bit_remaining mask = self.bitmask(bit_idx % access_width + bit_count - 1, bit_idx % access_width) - acc = (self.read(norm_idx, access_width) & mask) >> (bit_idx % access_width) + acc = (self.read(byte_idx, access_width) & mask) >> (bit_idx % access_width) acc_bit_count += bit_count bit_idx += bit_count bit_remaining -= bit_count while bit_remaining > 0: - norm_idx = floor(bit_idx / access_width) - bit_count = access_width if bit_remaining >= access_width else bit_remaining + byte_idx = bit_idx // 8 + bit_count = min(access_width, bit_remaining) mask = self.bitmask(bit_count - 1, 0) - acc |= (self.read(norm_idx, access_width) & mask) << acc_bit_count + acc |= (self.read(byte_idx, access_width) & mask) << acc_bit_count acc_bit_count += bit_count bit_idx += bit_count bit_remaining -= bit_count @@ -100,9 +101,9 @@ class BufferBase(Object): assert offset + bitwidth <= self.__length * 8, \ f"Buffer overflow: attempt to access field {name} at bit {offset + bitwidth} while the buffer has only {len(self.__data) * 8} bits" - # Bits out of byte boundary + # Bits out of access_width boundary if bit_idx % access_width > 0: - norm_idx = floor(bit_idx / access_width) + byte_idx = (bit_idx // access_width) * (access_width // 8) bit_count = (access_width - bit_idx % access_width) if bit_count > bit_remaining: bit_count = bit_remaining @@ -110,20 +111,20 @@ class BufferBase(Object): mask_of_write = self.bitmask(bit_idx % access_width + bit_count - 1, bit_idx % access_width) mask_of_keep = ((1 << access_width) - 1) - mask_of_write v = (value & ((1 << bit_count) - 1)) << (bit_idx % access_width) - self.write(norm_idx, (v & mask_of_write) | (self.read(norm_idx, access_width) & mask_of_keep), access_width) + self.write(byte_idx, (v & mask_of_write) | (self.read(byte_idx, access_width) & mask_of_keep), access_width) value >>= bit_count bit_idx += bit_count bit_remaining -= bit_count while bit_remaining > 0: - norm_idx = floor(bit_idx / access_width) - bit_count = access_width if bit_remaining >= access_width else bit_remaining + byte_idx = bit_idx // 8 + bit_count = min(access_width, bit_remaining) mask_of_write = self.bitmask(bit_count - 1, 0) mask_of_keep = ((1 << access_width) - 1) - mask_of_write v = (value & ((1 << bit_count) - 1)) - self.write(norm_idx, (v & mask_of_write) | (self.read(norm_idx, access_width) & mask_of_keep), access_width) + self.write(byte_idx, (v & mask_of_write) | (self.read(byte_idx, access_width) & mask_of_keep), access_width) value >>= bit_count bit_idx += bit_count @@ -142,16 +143,14 @@ class Buffer(BufferBase): def data(self): return bytes(self.__data) - def read(self, norm_idx, bit_width): + def read(self, byte_idx, bit_width): acc = 0 - byte_width = bit_width // 8 - offset = norm_idx * byte_width - return int.from_bytes(self.__data[offset : (offset + byte_width)], sys.byteorder) + byte_width = min(bit_width // 8, len(self.__data) - byte_idx) + return int.from_bytes(self.__data[byte_idx : (byte_idx + byte_width)], sys.byteorder) - def write(self, norm_idx, value, bit_width): - byte_width = bit_width // 8 - offset = norm_idx * byte_width - self.__data[offset : (offset + byte_width)] = value.to_bytes(byte_width, sys.byteorder) + def write(self, byte_idx, value, bit_width): + byte_width = min(bit_width // 8, len(self.__data) - byte_idx) + self.__data[byte_idx : (byte_idx + byte_width)] = value.to_bytes(byte_width, sys.byteorder) def get(self): return self.__data @@ -175,17 +174,15 @@ class StreamIOBuffer(BufferBase): self.__stream = stream self.__base = base - def read(self, norm_idx, bit_width): + def read(self, byte_idx, bit_width): byte_width = bit_width // 8 - address = norm_idx * byte_width - self.__stream.seek(self.__base + address) + self.__stream.seek(self.__base + byte_idx) data = self.__stream.read(byte_width) return int.from_bytes(data, sys.byteorder) - def write(self, norm_idx, value, bit_width): + def write(self, byte_idx, value, bit_width): byte_width = bit_width // 8 - address = norm_idx * byte_width - self.__stream.seek(self.__base + address) + self.__stream.seek(self.__base + byte_idx) self.__stream.write(value.to_bytes(byte_width, sys.byteorder)) class IndexedIOBuffer(BufferBase): @@ -195,12 +192,12 @@ class IndexedIOBuffer(BufferBase): self.__index_register = index_register self.__data_register = data_register - def read(self, norm_idx, bit_width): + def read(self, byte_idx, bit_width): assert bit_width == 8, f"Indexed I/O buffers can only be read one byte at a time" - self.__index_register.set(Integer(norm_idx, 8)) + self.__index_register.set(Integer(byte_idx, 8)) return self.__data_register.get() - def write(self, norm_idx, value, bit_width): + def write(self, byte_idx, value, bit_width): # Do not allow writes to indexed I/O buffer assert False, "Cannot write to indexed I/O buffers" @@ -273,7 +270,7 @@ class Integer(Object): class Method(Object): def __init__(self, tree): self.tree = tree - self.name = tree.children[1].children + self.name = tree.children[1].value self.body = tree.children[3] class PredefinedMethod(Object): diff --git a/misc/config_tools/board_inspector/acpiparser/aml/grammar.py b/misc/config_tools/board_inspector/acpiparser/aml/grammar.py index d6f57c741..fd40cf7f5 100644 --- a/misc/config_tools/board_inspector/acpiparser/aml/grammar.py +++ b/misc/config_tools/board_inspector/acpiparser/aml/grammar.py @@ -136,15 +136,15 @@ AML_DATA_REGION_OP = 0x885b AMLCode = ("DefBlockHeader", "TermObj*") DefBlockHeader = ("TableSignature", "TableLength", "SpecCompliance", "CheckSum", "OemID", "OemTableID", "OemRevision", "CreatorID", "CreatorRevision") -TableSignature = ("DWordData",) -TableLength = ("DWordData",) -SpecCompliance = ("ByteData",) -CheckSum = ("ByteData",) -OemID = ("TWordData",) -OemTableID = ("QWordData",) -OemRevision = ("DWordData",) -CreatorID = ("DWordData",) -CreatorRevision = ("DWordData",) +TableSignature = ["DWordData"] +TableLength = ["DWordData"] +SpecCompliance = ["ByteData"] +CheckSum = ["ByteData"] +OemID = ["TWordData"] +OemTableID = ["QWordData"] +OemRevision = ["DWordData"] +CreatorID = ["DWordData"] +CreatorRevision = ["DWordData"] ################################################################################ # 20.2.2 Name Objects Encoding @@ -202,7 +202,7 @@ TermArg = ["ExpressionOpcode", "DataObject", "ArgObj", "LocalObj"] NameSpaceModifierObj = ["DefAlias", "DefName", "DefScope"] -DefAlias = (AML_ALIAS_OP, "NameString", "NameString") +DefAlias = (AML_ALIAS_OP, "NameString:SourceObject", "NameString:AliasObject") DefName = (AML_NAME_OP, "NameString", "DataRefObject") DefScope = (AML_SCOPE_OP, "PkgLength", "NameString", "TermList") @@ -214,68 +214,68 @@ NamedObj = ["DefBankField", "DefCreateBitField", "DefCreateByteField", "DefCreat "DefField", "DefIndexField", "DefMethod", "DefMutex", "DefOpRegion", "DefPowerRes", "DefProcessor", "DefThermalZone"] -DefBankField = (AML_BANK_FIELD_OP, "PkgLength", "NameString", "NameString", "BankValue", "FieldFlags", "FieldList") -BankValue = ("TermArg",) -FieldFlags = ("ByteData",) +DefBankField = (AML_BANK_FIELD_OP, "PkgLength", "NameString:RegionName", "NameString:BankName", "BankValue", "FieldFlags", "FieldList") +BankValue = ["TermArg"] +FieldFlags = ["ByteData"] FieldList = ("FieldElement*",) NamedField = ("NameSeg", "FieldLength") ReservedField = (AML_RESERVED_FIELD_PREFIX, "FieldLength") AccessField = (AML_ACCESS_FIELD_PREFIX, "AccessType", "AccessAttrib") -AccessType = ("ByteData",) -AccessAttrib = ("ByteData",) -ConnectFieldDef = ["NameString", "BufferData"] +AccessType = ["ByteData"] +AccessAttrib = ["ByteData"] +ConnectFieldDef = ["NameString"] # FIXME: ACPI spec allows "BufferData" here but does not define what "BufferData" is ConnectField = (AML_CONNECT_FIELD_PREFIX, "ConnectFieldDef") DefCreateBitField = (AML_CREATE_BIT_FIELD_OP, "SourceBuff", "BitIndex", "NameString") -SourceBuff = ("TermArg",) -BitIndex = ("TermArg",) +SourceBuff = ["TermArg"] +BitIndex = ["TermArg"] DefCreateByteField = (AML_CREATE_BYTE_FIELD_OP, "SourceBuff", "ByteIndex", "NameString") -ByteIndex = ("TermArg",) +ByteIndex = ["TermArg"] DefCreateDWordField = (AML_CREATE_DWORD_FIELD_OP, "SourceBuff", "ByteIndex", "NameString") DefCreateField = (AML_CREATE_FIELD_OP, "SourceBuff", "BitIndex", "NumBits", "NameString") -NumBits = ("TermArg",) +NumBits = ["TermArg"] DefCreateQWordField = (AML_CREATE_QWORD_FIELD_OP, "SourceBuff", "ByteIndex", "NameString") DefCreateWordField = (AML_CREATE_WORD_FIELD_OP, "SourceBuff", "ByteIndex", "NameString") -DefDataRegion = (AML_DATA_REGION_OP, "NameString", "TermArg", "TermArg", "TermArg") +DefDataRegion = (AML_DATA_REGION_OP, "NameString", "TermArg:Signature", "TermArg:OEMID", "TermArg:OEMTableID") DefDevice = (AML_DEVICE_OP, "PkgLength", "NameString", "TermList") DefEvent = (AML_EVENT_OP, "NameString") DefExternal = (AML_EXTERNAL_OP, "NameString", "ObjectType", "ArgumentCount") -ObjectType = ("ByteData",) -ArgumentCount = ("ByteData",) +ObjectType = ["ByteData"] +ArgumentCount = ["ByteData"] DefField = (AML_FIELD_OP, "PkgLength", "NameString", "FieldFlags", "FieldList") -DefIndexField = (AML_INDEX_FIELD_OP, "PkgLength", "NameString", "NameString", "FieldFlags", "FieldList") +DefIndexField = (AML_INDEX_FIELD_OP, "PkgLength", "NameString:IndexName", "NameString:DataName", "FieldFlags", "FieldList") DefMethod = (AML_METHOD_OP, "PkgLength", "NameString", "MethodFlags", "TermList") -MethodFlags = ("ByteData",) +MethodFlags = ["ByteData"] DefMutex = (AML_MUTEX_OP, "NameString", "SyncFlags") -SyncFlags = ("ByteData",) +SyncFlags = ["ByteData"] DefOpRegion = (AML_REGION_OP, "NameString", "RegionSpace", "RegionOffset", "RegionLen") -RegionSpace = ("ByteData",) -RegionOffset = ("TermArg",) -RegionLen = ("TermArg",) +RegionSpace = ["ByteData"] +RegionOffset = ["TermArg"] +RegionLen = ["TermArg"] DefPowerRes = (AML_POWER_RESOURCE_OP, "PkgLength", "NameString", "SystemLevel", "ResourceOrder", "TermList") -SystemLevel = ("ByteData",) -ResourceOrder = ("WordData",) +SystemLevel = ["ByteData"] +ResourceOrder = ["WordData"] DefProcessor = (AML_PROCESSOR_OP, "PkgLength", "NameString", "ProcID", "PblkAddr", "PblkLen", "TermList") -ProcID = ("ByteData",) -PblkAddr = ("DWordData",) -PblkLen = ("ByteData",) +ProcID = ["ByteData"] +PblkAddr = ["DWordData"] +PblkLen = ["ByteData"] DefThermalZone = (AML_THERMAL_ZONE_OP, "PkgLength", "NameString", "TermList") ExtendedAccessField = (AML_EXTENDED_ACCESS_FIELD_PREFIX, "AccessType", "ExtendedAccessAttrib", "AccessLength") -ExtendedAccessAttrib = ("ByteData",) -AccessLength = ("ByteData",) +ExtendedAccessAttrib = ["ByteData"] +AccessLength = ["ByteData"] FieldElement = ["NamedField", "ReservedField", "AccessField", "ExtendedAccessField", "ConnectField"] # 20.2.5.3 Statement Opcodes Encoding @@ -293,35 +293,35 @@ DefContinue = (AML_CONTINUE_OP,) DefElse = (AML_ELSE_OP, "PkgLength", "TermList") DefFatal = (AML_FATAL_OP, "FatalType", "FatalCode", "FataArg") -FatalType = ("ByteData",) -FatalCode = ("DWordData",) -FatalArg = ("TermArg",) +FatalType = ["ByteData"] +FatalCode = ["DWordData"] +FatalArg = ["TermArg"] DefIfElse = (AML_IF_OP, "PkgLength", "Predicate", "TermList", "DefElse?") -Predicate = ("TermArg",) +Predicate = ["TermArg"] DefNoop = (AML_NOOP_OP,) DefNotify = (AML_NOTIFY_OP, "NotifyObject", "NotifyValue") -NotifyObject = ("SuperName",) -NotifyValue = ("TermArg",) +NotifyObject = ["SuperName"] +NotifyValue = ["TermArg"] DefRelease = (AML_RELEASE_OP, "MutexObject") -MutexObject = ("SuperName",) +MutexObject = ["SuperName"] DefReset = (AML_RESET_OP, "EventObject") -EventObject = ("SuperName",) +EventObject = ["SuperName"] DefReturn = (AML_RETURN_OP, "ArgObject") -ArgObject = ("TermArg",) +ArgObject = ["TermArg"] DefSignal = (AML_SIGNAL_OP, "EventObject") DefSleep = (AML_SLEEP_OP, "MsecTime") -MsecTime = ("TermArg",) +MsecTime = ["TermArg"] DefStall = (AML_STALL_OP, "UsecTime") -UsecTime = ("TermArg",) +UsecTime = ["TermArg"] DefUnload = (AML_UNLOAD_OP, "Target") @@ -342,21 +342,21 @@ ExpressionOpcode = ["DefAcquire", "DefAdd", "DefAnd", "DefBuffer", "DefConcat", ReferenceTypeOpcode = ["DefRefOf", "DefDerefOf", "DefIndex"] DefAcquire = (AML_ACQUIRE_OP, "MutexObject", "Timeout") -Timeout = ("WordData",) +Timeout = ["WordData"] -DefAdd = (AML_ADD_OP, "Operand", "Operand", "Target") +DefAdd = (AML_ADD_OP, "Operand:LeftOperand", "Operand:RightOperand", "Target") Operand = ["TermArg"] -DefAnd = (AML_AND_OP, "Operand", "Operand", "Target") +DefAnd = (AML_AND_OP, "Operand:LeftOperand", "Operand:RightOperand", "Target") DefBuffer = (AML_BUFFER_OP, "PkgLength", "BufferSize", "ByteList") -BufferSize = ("TermArg",) +BufferSize = ["TermArg"] -DefConcat = (AML_CONCAT_OP, "Data", "Data", "Target") -Data = ("TermArg",) +DefConcat = (AML_CONCAT_OP, "Data:Data1", "Data:Data2", "Target") +Data = ["TermArg"] -DefConcatRes = (AML_CONCAT_RES_OP, "BufData", "BufData", "Target") -BufData = ("TermArg",) +DefConcatRes = (AML_CONCAT_RES_OP, "BufData:BufData1", "BufData:BufData2", "Target") +BufData = ["TermArg"] DefCondRefOf = (AML_CONDITIONAL_REF_OF_OP, "SuperName", "Target") @@ -365,80 +365,80 @@ DefCopyObject = (AML_COPY_OBJECT_OP, "TermArg", "SimpleName") DefDecrement = (AML_DECREMENT_OP, "SuperName") DefDerefOf = (AML_DEREF_OF_OP, "ObjReference") -ObjReference = ("TermArg",) +ObjReference = ["TermArg"] DefDivide = (AML_DIVIDE_OP, "Dividend", "Divisor", "Remainder", "Quotient") -Dividend = ("TermArg",) -Divisor = ("TermArg",) -Remainder = ("Target",) -Quotient = ("Target",) +Dividend = ["TermArg"] +Divisor = ["TermArg"] +Remainder = ["Target"] +Quotient = ["Target"] DefFindSetLeftBit = (AML_FIND_SET_LEFT_BIT_OP, "Operand", "Target") DefFindSetRightBit = (AML_FIND_SET_RIGHT_BIT_OP, "Operand", "Target") DefFromBCD = (AML_FROM_BCD_OP, "BCDValue", "Target") -BCDValue = ("TermArg",) +BCDValue = ["TermArg"] DefIncrement = (AML_INCREMENT_OP, "SuperName") DefIndex = (AML_INDEX_OP, "BuffPkgStrObj", "IndexValue", "Target") -BuffPkgStrObj = ("TermArg",) -IndexValue = ("TermArg",) +BuffPkgStrObj = ["TermArg"] +IndexValue = ["TermArg"] -DefLAnd = (AML_LAND_OP, "Operand", "Operand") -DefLEqual = (AML_LEQUAL_OP, "Operand", "Operand") -DefLGreater = (AML_LGREATER_OP, "Operand", "Operand") +DefLAnd = (AML_LAND_OP, "Operand:LeftOperand", "Operand:RightOperand") +DefLEqual = (AML_LEQUAL_OP, "Operand:LeftOperand", "Operand:RightOperand") +DefLGreater = (AML_LGREATER_OP, "Operand:LeftOperand", "Operand:RightOperand") # DefLGreaterEqual is equivalent to (AML_LNOT_OP, DefLLess) -DefLLess = (AML_LLESS_OP, "Operand", "Operand") +DefLLess = (AML_LLESS_OP, "Operand:LeftOperand", "Operand:RightOperand") # DefLLessEqual is equivalent to (AML_LNOT_OP, DefLGreater) DefLNot = (AML_LNOT_OP, "Operand") # DefLNotEqual is equivalent to (AML_LNOT_OP, DefLEqual) DefLoad = (AML_LOAD_OP, "NameString", "Target") -DefLoadTable = (AML_LOAD_TABLE_OP, "TermArg", "TermArg", "TermArg", "TermArg", "TermArg", "TermArg") +DefLoadTable = (AML_LOAD_TABLE_OP, "TermArg:Signature", "TermArg:OEMID", "TermArg:TableID", "TermArg:RootPath", "TermArg:ParameterPath", "TermArg:ParameterData") -DefLOr = (AML_LOR_OP, "Operand", "Operand") +DefLOr = (AML_LOR_OP, "Operand:LeftOperand", "Operand:RightOperand") -DefMatch = (AML_MATCH_OP, "SearchPkg", "MatchOpcode", "Operand", "MatchOpcode", "Operand", "StartIndex") -SearchPkg = ("TermArg",) -MatchOpcode = ("ByteData",) -StartIndex = ("TermArg",) +DefMatch = (AML_MATCH_OP, "SearchPkg", "MatchOpcode:MatchOpcode1", "Operand:Operand1", "MatchOpcode:MatchOpcode2", "Operand:Operand2", "StartIndex") +SearchPkg = ["TermArg"] +MatchOpcode = ["ByteData"] +StartIndex = ["TermArg"] -DefMid = (AML_MID_OP, "MidObj", "TermArg", "TermArg", "Target") -MidObj = ("TermArg",) +DefMid = (AML_MID_OP, "MidObj", "TermArg:Source", "TermArg:Index", "Target") +MidObj = ["TermArg"] DefMod = (AML_MOD_OP, "Dividend", "Divisor", "Target") -DefMultiply = (AML_MULTIPLY_OP, "Operand", "Operand", "Target") +DefMultiply = (AML_MULTIPLY_OP, "Operand:LeftOperand", "Operand:RightOperand", "Target") -DefNAnd = (AML_NAND_OP, "Operand", "Operand", "Target") -DefNOr = (AML_NOR_OP, "Operand", "Operand", "Target") +DefNAnd = (AML_NAND_OP, "Operand:LeftOperand", "Operand:RightOperand", "Target") +DefNOr = (AML_NOR_OP, "Operand:LeftOperand", "Operand:RightOperand", "Target") DefNot = (AML_NOT_OP, "Operand", "Target") DefObjectType = (AML_OBJECT_TYPE_OP, "ObjectTypeContent") ObjectTypeContent = ["SimpleName", "DebugObj", "DefRefof", "DefDerefof", "DefIndex"] -DefOr = (AML_OR_OP, "Operand", "Operand", "Target") +DefOr = (AML_OR_OP, "Operand:LeftOperand", "Operand:RightOperand", "Target") DefPackage = (AML_PACKAGE_OP, "PkgLength", "NumElements", "PackageElementList") DefVarPackage = (AML_VAR_PACKAGE_OP, "PkgLength", "VarNumElements", "PackageElementList") -NumElements = ("ByteData",) -VarNumElements = ("TermArg",) +NumElements = ["ByteData"] +VarNumElements = ["TermArg"] PackageElementList = ("PackageElement*",) PackageElement = ["DataRefObject", "NameString"] DefRefOf = (AML_REF_OF_OP, "SuperName") DefShiftLeft = (AML_SHIFT_LEFT_OP, "Operand", "ShiftCount", "Target") -ShiftCount = ("TermArg",) +ShiftCount = ["TermArg"] DefShiftRight = (AML_SHIFT_RIGHT_OP, "Operand", "ShiftCount", "Target") DefSizeOf = (AML_SIZE_OF_OP, "SuperName") DefStore = (AML_STORE_OP, "TermArg", "SuperName") -DefSubtract = (AML_SUBTRACT_OP, "Operand", "Operand", "Target") +DefSubtract = (AML_SUBTRACT_OP, "Operand:LeftOperand", "Operand:RightOperand", "Target") DefTimer = (AML_TIMER_OP,) @@ -453,11 +453,11 @@ DefToHexString = (AML_TO_HEX_STRING_OP, "Operand", "Target") DefToInteger = (AML_TO_INTEGER_OP, "Operand", "Target") DefToString = (AML_TO_STRING_OP, "TermArg", "LengthArg", "Target") -LengthArg = ("TermArg",) +LengthArg = ["TermArg"] DefWait = (AML_WAIT_OP, "EventObject", "Operand") -DefXOr = (AML_XOR_OP, "Operand", "Operand", "Target") +DefXOr = (AML_XOR_OP, "Operand:LeftOperand", "Operand:RightOperand", "Target") ################################################################################ # 20.2.6 Miscellaneous Objects Encoding @@ -492,3 +492,24 @@ Local7Op = (AML_LOCAL7_OP,) ################################################################################ DebugObj = (AML_DEBUG_OP,) + +################################################################################ +# Helper methods +################################################################################ + +def __get_spec(sym, fn): + spec = globals()[sym] + if isinstance(spec, tuple): + return tuple(map(fn, spec)) + else: + return spec + +def get_definition(sym): + def __get_definition(elem): + return elem.split(":")[0] if isinstance(elem, str) else elem + return __get_spec(sym, __get_definition) + +def get_names(sym): + def __get_names(elem): + return elem.split(":")[-1] if isinstance(elem, str) else elem + return __get_spec(sym, __get_names) diff --git a/misc/config_tools/board_inspector/acpiparser/aml/interpreter.py b/misc/config_tools/board_inspector/acpiparser/aml/interpreter.py index d78e080e9..5b1a9665b 100644 --- a/misc/config_tools/board_inspector/acpiparser/aml/interpreter.py +++ b/misc/config_tools/board_inspector/acpiparser/aml/interpreter.py @@ -86,9 +86,13 @@ class ConcreteInterpreter(Interpreter): def interpret_method_call(self, name, *args): stack_depth_before = len(self.stack) - name_string = Tree("NameString", name) + name_string = Tree("NameString", [name]) + name_string.register_structure(("value",)) + name_string.complete_parsing() name_string.scope = self.context.parent(name) pseudo_invocation = Tree("MethodInvocation", [name_string]) + pseudo_invocation.register_structure(("NameString", "TermArg*")) + pseudo_invocation.complete_parsing() try: val = self.interpret(pseudo_invocation) except: @@ -118,7 +122,7 @@ class ConcreteInterpreter(Interpreter): return None def NameString(self, tree): - name = tree.children + name = tree.value obj = self.context.lookup_binding(name) if not obj: sym = self.context.lookup_symbol(name) @@ -133,7 +137,7 @@ class ConcreteInterpreter(Interpreter): # 20.2.3 Data Objects Encoding def ByteList(self, tree): - return RawDataBuffer(tree.children) + return RawDataBuffer(tree.value) def ByteConst(self, tree): return self.interpret(tree.children[0]) @@ -148,19 +152,19 @@ class ConcreteInterpreter(Interpreter): return self.interpret(tree.children[0]) def String(self, tree): - return String(tree.children) + return String(tree.value) def ByteData(self, tree): - return Integer(tree.children) + return Integer(tree.value) def WordData(self, tree): - return Integer(tree.children) + return Integer(tree.value) def DWordData(self, tree): - return Integer(tree.children) + return Integer(tree.value) def QWordData(self, tree): - return Integer(tree.children) + return Integer(tree.value) def ZeroOp(self, tree): return Integer(0x00) @@ -210,7 +214,7 @@ class ConcreteInterpreter(Interpreter): return Integer(value.fn(args)) else: assert value == None or isinstance(value, Object), \ - f"{tree.children[0].children} evaluates to a non-object value {value}" + f"{tree.children[0]} evaluates to a non-object value {value}" return value # 20.2.5.1 Namespace Modifier Objects Encoding @@ -219,7 +223,7 @@ class ConcreteInterpreter(Interpreter): def DefName(self, tree): self.context.change_scope(tree.children[0].scope) - name = tree.children[0].children + name = tree.children[0].value obj = self.context.lookup_binding(name) if not obj: obj = self.interpret(tree.children[1]) @@ -229,7 +233,7 @@ class ConcreteInterpreter(Interpreter): # 20.2.5.2 Named Objects Encoding def NamedField(self, tree): - name = tree.children[0].children + name = tree.children[0].value sym = self.context.lookup_symbol(self.context.realpath(tree.scope, name)) assert isinstance(sym, OperationFieldDecl) assert sym.region, f"Field {sym.name} does not belong to any operation region." @@ -253,7 +257,7 @@ class ConcreteInterpreter(Interpreter): buf = self.interpret(tree.children[0]) assert isinstance(buf, Buffer) index = self.interpret(tree.children[1]).get() - name = tree.children[name_idx].children + name = tree.children[name_idx].value if bitwidth == 1 or name_idx == 3: buf.create_field(name, index, bitwidth, 8) else: @@ -283,13 +287,13 @@ class ConcreteInterpreter(Interpreter): return self.create_field(tree, numbits, 3) def DefDevice(self, tree): - name = tree.children[1].children + name = tree.children[1].value fullpath = self.context.realpath(tree.scope, name) sym = self.context.lookup_symbol(fullpath) return Device(sym) def DefExternal(self, tree): - logging.info(f"The loaded tables do not have a definition of {tree.children[0].children}") + logging.info(f"The loaded tables do not have a definition of {tree.children[0].value}") return None def DefField(self, tree): @@ -300,7 +304,7 @@ class ConcreteInterpreter(Interpreter): return Method(tree) def DefOpRegion(self, tree): - name = tree.children[0].children + name = tree.children[0].value sym = self.context.lookup_symbol(self.context.realpath(tree.scope, name)) space = self.interpret(tree.children[1]).get() diff --git a/misc/config_tools/board_inspector/acpiparser/aml/parser.py b/misc/config_tools/board_inspector/acpiparser/aml/parser.py index f993c71dc..2af685f35 100644 --- a/misc/config_tools/board_inspector/acpiparser/aml/parser.py +++ b/misc/config_tools/board_inspector/acpiparser/aml/parser.py @@ -56,7 +56,8 @@ class Factory: self.mark_end() return tree - def opcodes(self): + @property + def decoder(self): raise NotImplementedError ################################################################################ @@ -66,17 +67,20 @@ class Factory: class NameSegFactory(Factory): def __init__(self): super().__init__() - self.__opcodes = [] + self.__decoder = {} for i in range(ord('A'), ord('Z') + 1): - self.__opcodes.append(i) - self.__opcodes.append(ord('_')) + self.__decoder[i] = self + self.__decoder[ord('_')] = self self.label = "NameSeg" def match(self, context, stream, tree): - tree.children = stream.get_fixed_length_string(4) + tree.register_structure(("value",)) + tree.append_child(stream.get_fixed_length_string(4)) + tree.complete_parsing() - def opcodes(self): - return self.__opcodes + @property + def decoder(self): + return self.__decoder NameSeg = NameSegFactory() @@ -84,12 +88,14 @@ class NameStringFactory(Factory): def __init__(self): super().__init__() self.label = "NameString" - self.__opcodes = [] + self.__decoder = {} for i in range(ord('A'), ord('Z') + 1): - self.__opcodes.append(i) - self.__opcodes.extend([ord('_'), ord('\\'), ord('^'), grammar.AML_DUAL_NAME_PREFIX, grammar.AML_MULTI_NAME_PREFIX]) + self.__decoder[i] = self + for i in [ord('_'), ord('\\'), ord('^'), grammar.AML_DUAL_NAME_PREFIX, grammar.AML_MULTI_NAME_PREFIX]: + self.__decoder[i] = self def match(self, context, stream, tree): + tree.register_structure(("value",)) acc = "" # Namespace prefixes @@ -117,10 +123,12 @@ class NameStringFactory(Factory): stream.seek(-1) acc += stream.get_fixed_length_string(4) - tree.children = acc + tree.append_child(acc) + tree.complete_parsing() - def opcodes(self): - return self.__opcodes + @property + def decoder(self): + return self.__decoder NameString = NameStringFactory() @@ -135,12 +143,11 @@ class ConstDataFactory(Factory): self.width = width def match(self, context, stream, tree): - tree.children = stream.get_integer(self.width) + tree.register_structure(("value",)) + tree.append_child(stream.get_integer(self.width)) + tree.complete_parsing() return tree - def opcodes(self): - return None - ByteData = ConstDataFactory("ByteData", 1) WordData = ConstDataFactory("WordData", 2) DWordData = ConstDataFactory("DWordData", 4) @@ -155,11 +162,14 @@ class StringFactory(Factory): def match(self, context, stream, tree): assert stream.get_opcode()[0] == grammar.AML_STRING_PREFIX - tree.children = stream.get_string() + tree.register_structure(("value",)) + tree.append_child(stream.get_string()) + tree.complete_parsing() return tree - def opcodes(self): - return [grammar.AML_STRING_PREFIX] + @property + def decoder(self): + return {grammar.AML_STRING_PREFIX: self} String = StringFactory() @@ -169,7 +179,9 @@ class ByteListFactory(Factory): self.label = "ByteList" def match(self, context, stream, tree): - tree.children = stream.get_buffer() + tree.register_structure(("value",)) + tree.append_child(stream.get_buffer()) + tree.complete_parsing() stream.pop_scope() ByteList = ByteListFactory() @@ -200,10 +212,12 @@ class PkgLengthFactory(Factory): byte_count = pkg_lead_byte >> 6 assert byte_count <= 3 - tree.children = self.get_package_length(byte_count, stream.get_integer(byte_count + 1)) + tree.register_structure(("value",)) + tree.append_child(self.get_package_length(byte_count, stream.get_integer(byte_count + 1))) + tree.complete_parsing() if self.create_new_scope: - remaining = tree.children - byte_count - 1 + remaining = tree.value - byte_count - 1 stream.push_scope(remaining) tree.package_range = (stream.current, remaining) return tree @@ -218,27 +232,33 @@ FieldLength = PkgLengthFactory("FieldLength", False) class MethodInvocationFactory(Factory): def __init__(self): super().__init__() - self.__opcodes = None + self.__decoder = None self.label = "MethodInvocation" def match(self, context, stream, tree): + tree.register_structure(("NameString", "TermArg*")) + child_namestring = Tree() globals()["NameString"].parse(context, child_namestring) tree.append_child(child_namestring) - sym = context.lookup_symbol(child_namestring.children) + sym = context.lookup_symbol(child_namestring.value) if isinstance(sym, (MethodDecl, PredefinedMethodDecl)): for i in range(0, sym.nargs): child_arg = Tree() globals()["TermArg"].parse(context, child_arg) tree.append_child(child_arg) + tree.complete_parsing() return tree - def opcodes(self): - if not self.__opcodes: - self.__opcodes = globals()["NameString"].opcodes() - return self.__opcodes + @property + def decoder(self): + if not self.__decoder: + self.__decoder = {} + for k in globals()["NameString"].decoder.keys(): + self.__decoder[k] = self + return self.__decoder MethodInvocation = MethodInvocationFactory() @@ -250,15 +270,31 @@ class SequenceFactory(Factory): def __init__(self, label, seq): super().__init__() self.label = label - self.seq = seq - self.__opcodes = None + # Some objects in ACPI AML have multiple occurrences of the same type of object in the grammar. In order to + # refer to these different occurrences, the grammar module uses the following notation to give names to each of + # them: + # + # ":" + # + # The grammar module provides the get_definition() and get_names() methods to get the specification solely in + # object types or alias names, respectively. For objects without aliases, the type is reused as the name. + try: + self.seq = grammar.get_definition(label) + self.structure = grammar.get_names(label) + except KeyError: + self.seq = seq + self.structure = seq + self.__decoder = None def match(self, context, stream, tree): + tree.register_structure(self.structure) + # When a TermList is empty, the stream has already come to the end of the current scope here. Do not attempt to # peek the next opcode in such cases. if stream.at_end() and \ (self.seq[0][-1] in ["*", "?"]): stream.pop_scope() + tree.complete_parsing() return tree opcode, opcode_width = stream.peek_opcode() @@ -268,6 +304,7 @@ class SequenceFactory(Factory): # cleanup actions upon exceptions. to_recover_from_deferred_mode = False to_pop_stream_scope = False + completed = True for i,elem in enumerate(self.seq): pos = stream.current @@ -288,7 +325,7 @@ class SequenceFactory(Factory): factory = globals()[elem] if not stream.at_end(): sub_opcode, _ = stream.peek_opcode() - if sub_opcode in factory.opcodes(): + if sub_opcode in factory.decoder.keys(): child = Tree() factory.parse(context, child) tree.append_child(child) @@ -312,7 +349,7 @@ class SequenceFactory(Factory): context.enter_deferred_mode() to_recover_from_deferred_mode = True elif child.label == "NameString": - self.hook_named(context, tree, child.children) + self.hook_named(context, tree, child.value) except (DecodeError, DeferLater, ScopeMismatch, UndefinedSymbol) as e: if to_pop_stream_scope: stream.pop_scope(force=True) @@ -321,49 +358,54 @@ class SequenceFactory(Factory): tree.context_scope = context.get_scope() tree.factory = SequenceFactory(f"{self.label}.deferred", self.seq[i:]) stream.seek(package_end, absolute=True) + completed = False break else: raise e + if completed: + tree.complete_parsing() + if to_recover_from_deferred_mode: context.exit_deferred_mode() return tree - def opcodes(self): - if not self.__opcodes: + @property + def decoder(self): + if not self.__decoder: if isinstance(self.seq[0], int): - self.__opcodes = [self.seq[0]] + self.__decoder = {self.seq[0]: self} else: - self.__opcodes = globals()[self.seq[0]].opcodes() - return self.__opcodes + self.__decoder = {} + for k in globals()[self.seq[0]].decoder.keys(): + self.__decoder[k] = self + return self.__decoder class OptionFactory(Factory): def __init__(self, label, opts): super().__init__() self.label = label self.opts = opts - self.__opcodes = None + self.__decoder = None def match(self, context, stream, tree): opcode, _ = stream.peek_opcode() + try: + if len(self.opts) == 1: + globals()[self.opts[0]].parse(context, tree) + else: + self.decoder[opcode].parse(context, tree) + return tree + except KeyError: + raise DecodeError(opcode, self.label) - for opt in self.opts: - factory = globals()[opt] - matched_opcodes = factory.opcodes() - if matched_opcodes is None or opcode in matched_opcodes: - child = Tree() - tree.append_child(child) - factory.parse(context, child) - return tree - - raise DecodeError(opcode, self.label) - - def opcodes(self): - if not self.__opcodes: - self.__opcodes = [] + @property + def decoder(self): + if not self.__decoder: + self.__decoder = {} for opt in self.opts: - self.__opcodes.extend(globals()[opt].opcodes()) - return self.__opcodes + self.__decoder.update(globals()[opt].decoder) + return self.__decoder class DeferredExpansion(Transformer): def __init__(self, context): @@ -390,6 +432,7 @@ class DeferredExpansion(Transformer): tree.children.extend(aux_tree.children) tree.deferred_range = None tree.factory = None + tree.complete_parsing() except (DecodeError, DeferLater, ScopeMismatch, UndefinedSymbol) as e: logging.debug(f"expansion of {tree.label} at {hex(tree.deferred_range[0])} failed due to: " + str(e)) @@ -402,9 +445,9 @@ class DeferredExpansion(Transformer): ################################################################################ def DefAlias_hook_post(context, tree): - target = tree.children[0].children - name = tree.children[1].children - sym = AliasDecl(name, target, tree) + source = tree.SourceObject.value + alias = tree.AliasObject.value + sym = AliasDecl(alias, source, tree) context.register_symbol(sym) def DefName_hook_named(context, tree, name): @@ -419,32 +462,32 @@ def DefScope_hook_post(context, tree): def DefCreateBitField_hook_named(context, tree, name): - name = tree.children[2].children + name = tree.children[2].value sym = FieldDecl(name, 1, tree) context.register_symbol(sym) def DefCreateByteField_hook_named(context, tree, name): - name = tree.children[2].children + name = tree.children[2].value sym = FieldDecl(name, 8, tree) context.register_symbol(sym) def DefCreateDWordField_hook_named(context, tree, name): - name = tree.children[2].children + name = tree.children[2].value sym = FieldDecl(name, 32, tree) context.register_symbol(sym) def DefCreateField_hook_named(context, tree, name): - name = tree.children[3].children + name = tree.children[3].value sym = FieldDecl(name, 0, tree) context.register_symbol(sym) def DefCreateQWordField_hook_named(context, tree, name): - name = tree.children[2].children + name = tree.children[2].value sym = FieldDecl(name, 64, tree) context.register_symbol(sym) def DefCreateWordField_hook_named(context, tree, name): - name = tree.children[2].children + name = tree.children[2].value sym = FieldDecl(name, 16, tree) context.register_symbol(sym) @@ -457,9 +500,9 @@ def DefDevice_hook_post(context, tree): context.pop_scope() def DefExternal_hook_post(context, tree): - name = tree.children[0].children - ty = tree.children[1].children[0].children - nargs = tree.children[2].children[0].children + name = tree.NameString.value + ty = tree.ObjectType.value + nargs = tree.ArgumentCount.value if ty == 0x8: # an external method sym = MethodDecl(name, nargs, tree) @@ -479,52 +522,50 @@ access_width_map = { def DefField_hook_post(context, tree): # Update the fields with region & offset info - region_name = context.lookup_symbol(tree.children[1].children).name - flags = tree.children[2].children[0].children + region_name = context.lookup_symbol(tree.NameString.value).name + flags = tree.FieldFlags.value access_width = access_width_map[flags & 0xF] - fields = tree.children[3].children + fields = tree.FieldList.FieldElements bit_offset = 0 for field in fields: - field = field.children[0] if field.label == "NamedField": - name = field.children[0].children - length = field.children[1].children + name = field.NameSeg.value + length = field.FieldLength.value sym = context.lookup_symbol(name) assert isinstance(sym, OperationFieldDecl) sym.set_location(region_name, bit_offset, access_width) bit_offset += length elif field.label == "ReservedField": - length = field.children[0].children + length = field.FieldLength.value bit_offset += length else: break def DefIndexField_hook_post(context, tree): # Update the fields with region & offset info - index_register = context.lookup_symbol(tree.children[1].children) - data_register = context.lookup_symbol(tree.children[2].children) - flags = tree.children[3].children[0].children + index_register = context.lookup_symbol(tree.IndexName.value) + data_register = context.lookup_symbol(tree.DataName.value) + flags = tree.FieldFlags.value access_width = access_width_map[flags & 0xF] - fields = tree.children[4].children + fields = tree.FieldList.FieldElements bit_offset = 0 for field in fields: - field = field.children[0] if field.label == "NamedField": - name = field.children[0].children - length = field.children[1].children + name = field.NameSeg.value + length = field.FieldLength.value sym = context.lookup_symbol(name) assert isinstance(sym, OperationFieldDecl) sym.set_indexed_location(index_register, data_register, bit_offset, access_width) bit_offset += length elif field.label == "ReservedField": - length = field.children[0].children + length = field.FieldLength.value bit_offset += length else: break def NamedField_hook_post(context, tree): - name = tree.children[0].children - length = tree.children[1].children + name = tree.NameSeg.value + length = tree.FieldLength.value sym = OperationFieldDecl(name, length, tree) context.register_symbol(sym) @@ -534,8 +575,9 @@ def DefMethod_hook_named(context, tree, name): def DefMethod_hook_post(context, tree): context.pop_scope() if len(tree.children) >= 3: - name = tree.children[1].children - flags = tree.children[2].children[0].children + # Parsing of the method may be deferred. Do not use named fields to access its children. + name = tree.children[1].value + flags = tree.children[2].value nargs = flags & 0x7 sym = MethodDecl(name, nargs, tree) context.register_symbol(sym) diff --git a/misc/config_tools/board_inspector/acpiparser/aml/tree.py b/misc/config_tools/board_inspector/acpiparser/aml/tree.py index ae2ecbcb8..d33159222 100644 --- a/misc/config_tools/board_inspector/acpiparser/aml/tree.py +++ b/misc/config_tools/board_inspector/acpiparser/aml/tree.py @@ -13,6 +13,8 @@ class Tree: self.children = copy(children) self.scope = None + self.structure = None + self.package_range = None self.deferred_range = None @@ -22,6 +24,26 @@ class Tree: def append_child(self, child): self.children.append(child) + def register_structure(self, structure): + self.structure = structure + + def complete_parsing(self): + i = 0 + for elem in self.structure: + if isinstance(elem, str): + if elem.endswith("?"): + if i < len(self.children): + setattr(self, elem[:-1], self.children[i]) + else: + setattr(self, elem[:-1], None) + break + elif elem.endswith("*"): + setattr(self, elem[:-1] + "s", self.children[i:]) + break + else: + setattr(self, elem, self.children[i]) + i += 1 + class Visitor: def __init__(self): self.depth = 0 @@ -35,12 +57,11 @@ class Visitor: def visit_topdown(self, tree): self.__visit(tree) - if isinstance(tree.children, list): - self.depth += 1 - for child in tree.children: - if isinstance(child, Tree): - self.visit_topdown(child) - self.depth -= 1 + self.depth += 1 + for child in tree.children: + if isinstance(child, Tree): + self.visit_topdown(child) + self.depth -= 1 class Transformer: def __init__(self): @@ -57,45 +78,21 @@ class Transformer: def transform_topdown(self, tree): new_tree = self.__transform(tree) - if isinstance(new_tree.children, list): - self.depth += 1 - for i, child in enumerate(tree.children): - if isinstance(child, Tree): - tree.children[i] = self.transform_topdown(child) - self.depth -= 1 + self.depth += 1 + for i, child in enumerate(tree.children): + if isinstance(child, Tree): + tree.children[i] = self.transform_topdown(child) + self.depth -= 1 return new_tree def transform_bottomup(self, tree): - if isinstance(tree.children, list): - self.depth += 1 - for i, child in enumerate(tree.children): - if isinstance(child, Tree): - tree.children[i] = self.transform_bottomup(child) - self.depth -= 1 + self.depth += 1 + for i, child in enumerate(tree.children): + if isinstance(child, Tree): + tree.children[i] = self.transform_bottomup(child) + self.depth -= 1 return self.__transform(tree) -single_operand_op = ["MethodInvocation"] -for sym in dir(grammar): - # Ignore builtin members and opcode constants - if sym.startswith("__") or (sym.upper() == sym): - continue - - definition = getattr(grammar, sym) - if isinstance(definition, tuple) and\ - isinstance(definition[0], int) and\ - len(definition) == 2: - single_operand_op.append(sym) - -class FlattenTransformer(Transformer): - def default(self, tree): - if tree.label not in single_operand_op and \ - isinstance(tree.children, list) and \ - len(tree.children) == 1 and \ - not tree.deferred_range: - return tree.children[0] - else: - return tree - class Interpreter: def __init__(self, context): self.context = context diff --git a/misc/config_tools/board_inspector/acpiparser/aml/visitors.py b/misc/config_tools/board_inspector/acpiparser/aml/visitors.py index b85476f29..d94de1beb 100644 --- a/misc/config_tools/board_inspector/acpiparser/aml/visitors.py +++ b/misc/config_tools/board_inspector/acpiparser/aml/visitors.py @@ -13,11 +13,12 @@ class PrintLayoutVisitor(Visitor): def default(self, tree): indent = " " * self.depth print(f"{indent}{tree.label}", end="") - if isinstance(tree.children, int): - print(f" = {hex(tree.children)}", end="") - elif isinstance(tree.children, str): - if self.__is_printable(tree.children): - print(f" = '{tree.children}'", end="") + if hasattr(tree, "value"): + if isinstance(tree.value, int): + print(f" = {hex(tree.value)}", end="") + elif isinstance(tree.value, str): + if self.__is_printable(tree.value): + print(f" = '{tree.value}'", end="") if tree.deferred_range: print(f" (deferred at {hex(tree.deferred_range[0])}, length {hex(tree.deferred_range[1])})", end="") if tree.factory: @@ -39,7 +40,7 @@ class ConditionallyUnregisterSymbolVisitor(Visitor): def f(tree): if self.conditionally_hidden: scope = tree.scope - name = tree.children[name_string_idx].children + name = tree.children[name_string_idx].value realpath = self.context.realpath(scope, name) self.context.unregister_object(realpath) return f diff --git a/misc/config_tools/board_inspector/acpiparser/dsdt.py b/misc/config_tools/board_inspector/acpiparser/dsdt.py index 4af22c106..9f3eba813 100644 --- a/misc/config_tools/board_inspector/acpiparser/dsdt.py +++ b/misc/config_tools/board_inspector/acpiparser/dsdt.py @@ -8,7 +8,7 @@ import logging from acpiparser.aml.stream import Stream from acpiparser.aml.parser import AMLCode, DeferredExpansion -from acpiparser.aml.tree import Tree, FlattenTransformer +from acpiparser.aml.tree import Tree from acpiparser.aml.context import Context from acpiparser.aml.interpreter import ConcreteInterpreter from acpiparser.aml.visitors import ConditionallyUnregisterSymbolVisitor @@ -29,7 +29,6 @@ def DSDT(val): tree = Tree() AMLCode.parse(context, tree) tree = DeferredExpansion(context).transform_topdown(tree) - tree = FlattenTransformer().transform_bottomup(tree) trees.append(tree) except Exception as e: context.current_stream.dump()