From 1e3b2a00b90bfb2186eeb679ab01f450f43aa037 Mon Sep 17 00:00:00 2001 From: Junjie Mao Date: Mon, 9 Aug 2021 10:52:55 +0800 Subject: [PATCH] board-inspector: add interpretation of OnesOp, DefMatch and DefSizeOf This patch enables the interpretation of the following AML objects. * OnesOp. A OnesOp object always evaluates to a 64-bit integer with all bits set to 1. It is assumed that the host DSDT is always revision 2 or above, which is typically the case on modern platforms. * DefMatch. A DefMatch object evaluates to the index of the first element (starting from a given index) in a package that matches the given two predicates. If a match is not found, the constant Ones is returned. * DefSizeOf. A DefSizeOf object evaluates to the byte length of a buffer, the length of a string (without the terminating NUL character) or the number of elements in a package. Tracked-On: #6287 Signed-off-by: Junjie Mao --- .../acpiparser/aml/interpreter.py | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/misc/config_tools/board_inspector/acpiparser/aml/interpreter.py b/misc/config_tools/board_inspector/acpiparser/aml/interpreter.py index 7e6893245..d1106c626 100644 --- a/misc/config_tools/board_inspector/acpiparser/aml/interpreter.py +++ b/misc/config_tools/board_inspector/acpiparser/aml/interpreter.py @@ -178,6 +178,9 @@ class ConcreteInterpreter(Interpreter): def OneOp(self, tree): return Integer(0x01) + def OnesOp(self, tree): + return Integer(0xffffffffffffffff) + # 20.2.5 Term Objects Encoding def TermList(self, tree): for child in tree.children: @@ -545,6 +548,41 @@ class ConcreteInterpreter(Interpreter): def DefLOr(self, tree): return self.__eval_binary_op(tree, lambda x,y: 1 if x or y else 0) + def __match(self, op, obj, match_obj): + try: + if isinstance(match_obj, String): + return op(obj.to_string().get(), match_obj.get()) + elif isinstance(match_obj, (Integer, BufferField)): + return op(obj.to_integer().get(), match_obj.get()) + else: + # Comparison of buffer fields is not implemented yet + return False + except NotImplementedError: + return False + + match_ops = { + 0: lambda x,y: True, # TRUE + 1: lambda x,y: x == y, # EQ + 2: lambda x,y: x <= y, # LE + 3: lambda x,y: x < y, # LT + 4: lambda x,y: x >= y, # GE + 5: lambda x,y: x > y, # GT + } + + def DefMatch(self, tree): + pkg = self.interpret(tree.SearchPkg) + op1 = self.match_ops[tree.MatchOpcode1.value] + match_obj1 = self.interpret(tree.Operand1) + op2 = self.match_ops[tree.MatchOpcode2.value] + match_obj2 = self.interpret(tree.Operand2) + start_index = self.interpret(tree.StartIndex).get() + if isinstance(pkg, Package) and isinstance(start_index, int): + for i in range(start_index, len(pkg.elements)): + obj = pkg.elements[i] + if self.__match(op1, obj, match_obj1) and self.__match(op2, obj, match_obj2): + return Integer(i) + return Integer(0xffffffffffffffff) # Ones is 64-bit in DSDT rev 2 and above + def DefMod(self, tree): return self.__eval_binary_op(tree, lambda x,y: x % y) @@ -582,6 +620,19 @@ class ConcreteInterpreter(Interpreter): def DefShiftRight(self, tree): return self.__eval_binary_op(tree, lambda x,y: x >> y) + def DefSizeOf(self, tree): + obj = self.interpret(tree.SuperName) + if isinstance(obj, (self.Argument, self.LocalVariable)): + obj = obj.get_obj() + + if isinstance(obj, Buffer): + return Integer(len(obj.get())) + elif isinstance(obj, String): + return Integer(len(obj.get())) + elif isinstance(obj, Package): + return Integer(len(obj.elements)) + raise NotImplementedError(f"Cannot calculate the size of object of type {obj.__class__.__name__}") + def DefStore(self, tree): obj = self.interpret(tree.children[0]) target = self.interpret(tree.children[1])