1# Copyright (C) 2021-2022 Intel Corporation. 2# 3# SPDX-License-Identifier: BSD-3-Clause 4# 5 6from .context import * 7from .datatypes import * 8from .tree import Tree, Interpreter 9from . import builder 10 11class MethodReturn(Exception): 12 """ A pseudo exception to return from a method""" 13 def __init__(self): 14 pass 15 16class ConcreteInterpreter(Interpreter): 17 class Argument(Object): 18 def __init__(self, frame, index): 19 self.__frame = frame 20 self.__index = index 21 22 def get(self): 23 return self.__frame.arg_objs[self.__index].get() 24 25 def to_buffer(self): 26 return self.__frame.arg_objs[self.__index].to_buffer() 27 28 def to_decimal_string(self): 29 return self.__frame.arg_objs[self.__index].to_decimal_string() 30 31 def to_hex_string(self): 32 return self.__frame.arg_objs[self.__index].to_hex_string() 33 34 def to_integer(self): 35 return self.__frame.arg_objs[self.__index].to_integer() 36 37 def to_string(self): 38 return self.__frame.arg_objs[self.__index].to_string() 39 40 def get_obj(self): 41 return self.__frame.arg_objs[self.__index] 42 43 class LocalVariable(Object): 44 def __init__(self, frame, index): 45 self.__frame = frame 46 self.__index = index 47 48 def get(self): 49 return self.__frame.local_objs[self.__index].get() 50 51 def set(self, obj): 52 self.__frame.local_objs[self.__index] = obj 53 54 def to_buffer(self): 55 return self.__frame.local_objs[self.__index].to_buffer() 56 57 def to_decimal_string(self): 58 return self.__frame.local_objs[self.__index].to_decimal_string() 59 60 def to_hex_string(self): 61 return self.__frame.local_objs[self.__index].to_hex_string() 62 63 def to_integer(self): 64 return self.__frame.local_objs[self.__index].to_integer() 65 66 def to_string(self): 67 return self.__frame.local_objs[self.__index].to_string() 68 69 def get_obj(self): 70 return self.__frame.local_objs[self.__index] 71 72 class StackFrame: 73 def __init__(self, method, args): 74 self.method = method 75 self.arg_objs = args + [UninitializedObject()] * (7 - len(args)) 76 self.local_objs = [UninitializedObject()] * 8 77 self.return_value = UninitializedObject() 78 79 def __init__(self, context): 80 super().__init__(context) 81 82 self.operation_regions = {} 83 self.stack = [] 84 85 self.to_break = False 86 self.to_continue = False 87 88 def interpret_method_call(self, name, *args): 89 stack_depth_before = len(self.stack) 90 name_string = builder.NameString(name) 91 name_string.scope = self.context.parent(name) 92 93 arg_trees = [] 94 for arg in args: 95 v = builder.build_value(arg) 96 if v != None: 97 arg_trees.append(v) 98 else: 99 raise NotImplementedError(f"Unsupported type of method argument: {arg}") 100 101 pseudo_invocation = builder.MethodInvocation(name_string, *arg_trees) 102 try: 103 val = self.interpret(pseudo_invocation) 104 except: 105 self.stack = self.stack[:stack_depth_before] 106 raise 107 assert len(self.stack) == stack_depth_before 108 return val 109 110 def dump(self): 111 def format_obj(obj): 112 if isinstance(obj, UninitializedObject): 113 return "None" 114 elif isinstance(obj, Object): 115 return str(obj.get()) 116 else: 117 return str(obj) 118 print("Stack:") 119 for idx, frame in enumerate(self.stack): 120 arg = ', '.join(map(format_obj, frame.arg_objs)) 121 local = ', '.join(map(format_obj, frame.local_objs)) 122 print(f" {idx}@{frame.method}: args: [{arg}] locals: [{local}]") 123 print("Binding:") 124 self.context.dump_bindings() 125 126 # 20.2.2 Name Objects Encoding 127 def NullName(self, tree): 128 return None 129 130 def NameString(self, tree): 131 name = tree.value 132 obj = self.context.lookup_binding(name) 133 if not obj: 134 sym = self.context.lookup_symbol(name) 135 if isinstance(sym, PredefinedMethodDecl): 136 obj = PredefinedMethod(sym.fn) 137 realpath = self.context.realpath("\\", name) 138 self.context.register_binding(realpath, obj) 139 else: 140 obj = self.interpret(sym.tree) 141 self.context.register_binding(name, obj) 142 return obj 143 144 # 20.2.3 Data Objects Encoding 145 def ByteList(self, tree): 146 return RawDataBuffer(tree.value) 147 148 def ByteConst(self, tree): 149 return self.interpret(tree.children[0]) 150 151 def WordConst(self, tree): 152 return self.interpret(tree.children[0]) 153 154 def DWordConst(self, tree): 155 return self.interpret(tree.children[0]) 156 157 def QWordConst(self, tree): 158 return self.interpret(tree.children[0]) 159 160 def String(self, tree): 161 return String(tree.value) 162 163 def ByteData(self, tree): 164 return Integer(tree.value) 165 166 def WordData(self, tree): 167 return Integer(tree.value) 168 169 def DWordData(self, tree): 170 return Integer(tree.value) 171 172 def QWordData(self, tree): 173 return Integer(tree.value) 174 175 def ZeroOp(self, tree): 176 return Integer(0x00) 177 178 def OneOp(self, tree): 179 return Integer(0x01) 180 181 def OnesOp(self, tree): 182 return Integer(0xffffffffffffffff) 183 184 # 20.2.5 Term Objects Encoding 185 def TermList(self, tree): 186 for child in tree.children: 187 self.interpret(child) 188 if self.to_break or self.to_continue: 189 break 190 return None 191 192 def MethodInvocation(self, tree): 193 self.context.change_scope(tree.children[0].scope) 194 value = self.interpret(tree.children[0]) 195 self.context.pop_scope() 196 197 if isinstance(value, Method): 198 # Evaluate arguments 199 args = list(map(self.interpret, tree.children[1:])) 200 201 # Switch to the scope of the callee 202 realpath = self.context.realpath(value.tree.scope, value.name) 203 assert realpath 204 self.context.change_scope(realpath) 205 206 # Evaluate the statements of the callee 207 self.stack.append(self.StackFrame(realpath, args)) 208 logging.debug(f"Calling {realpath} with args {args}") 209 try: 210 self.interpret(value.body) 211 except MethodReturn: 212 pass 213 frame = self.stack.pop() 214 self.context.pop_scope() 215 216 # Return the return value of the callee 217 return frame.return_value 218 elif isinstance(value, PredefinedMethod): 219 # Evaluate arguments 220 args = list(map(self.interpret, tree.children[1:])) 221 222 # Invoke the predefined function in Python 223 return Integer(value.fn(args)) 224 else: 225 assert value == None or isinstance(value, Object), \ 226 f"{tree.children[0]} evaluates to a non-object value {value}" 227 return value 228 229 # 20.2.5.1 Namespace Modifier Objects Encoding 230 def DefAlias(self, tree): 231 return None 232 233 def DefName(self, tree): 234 self.context.change_scope(tree.children[0].scope) 235 name = tree.children[0].value 236 obj = self.context.lookup_binding(name) 237 if not obj: 238 obj = self.interpret(tree.children[1]) 239 self.context.register_binding(name, obj) 240 self.context.pop_scope() 241 return obj 242 243 # 20.2.5.2 Named Objects Encoding 244 def NamedField(self, tree): 245 name = tree.children[0].value 246 sym = self.context.lookup_symbol(self.context.realpath(tree.scope, name)) 247 assert isinstance(sym, OperationFieldDecl) 248 assert sym.region, f"Field {sym.name} does not belong to any operation region." 249 if isinstance(sym.region, str): 250 buf = self.context.lookup_operation_region(sym.region) 251 if not buf: 252 buf = self.interpret(self.context.lookup_symbol(sym.region).tree) 253 buf.create_field(name, sym.offset, sym.length, sym.access_width) 254 field = BufferField(buf, name) 255 elif isinstance(sym.region, tuple): 256 index_register = self.interpret(sym.region[0].tree) 257 data_register = self.interpret(sym.region[1].tree) 258 buf = OperationRegion.open_indexed_region(index_register, data_register) 259 buf.create_field(name, sym.offset, sym.length, sym.access_width) 260 field = BufferField(buf, name) 261 else: 262 assert False, f"Cannot interpret the operation region: {sym.region}" 263 return field 264 265 def create_field(self, tree, bitwidth, name_idx): 266 buf = self.interpret(tree.children[0]) 267 assert isinstance(buf, Buffer) 268 index = self.interpret(tree.children[1]).get() 269 name = tree.children[name_idx].value 270 if bitwidth == 1 or name_idx == 3: 271 buf.create_field(name, index, bitwidth, 8) 272 else: 273 # bitwidth is 8, 16, 32 or 64 in this case. Reuse it as the access width. 274 buf.create_field(name, index * 8, bitwidth, bitwidth) 275 obj = BufferField(buf, name) 276 self.context.register_binding(name, obj) 277 return obj 278 279 def DefCreateBitField(self, tree): 280 return self.create_field(tree, 1, 2) 281 282 def DefCreateByteField(self, tree): 283 return self.create_field(tree, 8, 2) 284 285 def DefCreateWordField(self, tree): 286 return self.create_field(tree, 16, 2) 287 288 def DefCreateDWordField(self, tree): 289 return self.create_field(tree, 32, 2) 290 291 def DefCreateQWordField(self, tree): 292 return self.create_field(tree, 64, 2) 293 294 def DefCreateField(self, tree): 295 numbits = self.interpret(tree.children[2]).get() 296 return self.create_field(tree, numbits, 3) 297 298 def DefDevice(self, tree): 299 name = tree.children[1].value 300 fullpath = self.context.realpath(tree.scope, name) 301 sym = self.context.lookup_symbol(fullpath) 302 return Device(sym) 303 304 def DefExternal(self, tree): 305 logging.debug(f"The loaded tables do not have a definition of {tree.children[0].value}") 306 return None 307 308 def DefField(self, tree): 309 # Fields of operation regions are evaluated when they are used. 310 return None 311 312 def DefMethod(self, tree): 313 return Method(tree) 314 315 def DefOpRegion(self, tree): 316 name = tree.children[0].value 317 sym = self.context.lookup_symbol(self.context.realpath(tree.scope, name)) 318 319 space = self.interpret(tree.children[1]).get() 320 offset = self.interpret(tree.children[2]).get() 321 length = self.interpret(tree.children[3]).get() 322 assert isinstance(space, int) and isinstance(offset, int) and (length, int) 323 324 if space == 0x00: # SystemMemory 325 op_region = OperationRegion.open_system_memory(sym.name, offset, length) 326 elif space == 0x01: # SystemIO 327 op_region = OperationRegion.open_system_io(sym.name, offset, length) 328 elif space == 0x02: # PCI_Config 329 self.context.change_scope(tree.scope) 330 device_path = self.context.parent(sym.name) 331 bus_id = self.interpret_method_call(f"_BBN").get() 332 if self.context.has_symbol(f"{device_path}._ADR"): 333 device_id = self.interpret_method_call(f"{device_path}._ADR").get() 334 elif self.context.has_symbol(f"{device_path}._BBN"): 335 # Device objects representing PCI host bridges may not have an _ADR object 336 device_id = 0 337 self.context.pop_scope() 338 op_region = OperationRegion.open_pci_configuration_space(bus_id, device_id, offset, length) 339 pass 340 else: 341 raise NotImplementedError(f"Cannot load operation region in space {space}") 342 343 self.context.register_operation_region(sym.name, op_region) 344 return op_region 345 346 def DefPowerRes(self, tree): 347 return PowerResource(tree.NameString.value) 348 349 # 20.2.5.3 Statement Opcodes Encoding 350 def DefBreak(self, tree): 351 self.to_break = True 352 return None 353 354 def DefContinue(self, tree): 355 self.to_continue = True 356 return None 357 358 def DefElse(self, tree): 359 self.interpret(tree.children[1]) 360 return None 361 362 def DefIfElse(self, tree): 363 cond = self.interpret(tree.children[1]) 364 if cond.get(): 365 self.interpret(tree.children[2]) 366 else: 367 if len(tree.children) == 4: 368 self.interpret(tree.children[3]) 369 return None 370 371 def DefRelease(self, tree): 372 return None 373 374 def DefReturn(self, tree): 375 obj = self.interpret(tree.children[0]) 376 while isinstance(obj, (self.Argument, self.LocalVariable)): 377 obj = obj.get_obj() 378 self.stack[-1].return_value = obj 379 raise MethodReturn() 380 return None 381 382 def DefSignal(self, tree): 383 # Skip 384 return None 385 386 def DefWhile(self, tree): 387 while self.interpret(tree.children[1]).get() != 0: 388 self.interpret(tree.children[2]) 389 if self.to_break: 390 self.to_break = False 391 break 392 return None 393 394 # 20.2.5.4 Expression Opcodes Encoding 395 def __eval_binary_op(self, tree, op): 396 lhs = self.interpret(tree.children[0]) 397 rhs = self.interpret(tree.children[1]) 398 # FIXME: The current design of AML parsing, objects are first defined in the namespace and later dropped if they 399 # are in a False branch. This leads to incorrect interpretation of the AML code where: 400 # 401 # 1. A name T is defined in the root scope as an integer. 402 # 2. A method M in an inner scope S references T. 403 # 3. The name T is defined as a device, power resource or other named objects in scope S under conditions 404 # where M will not be called. 405 # 406 # As a workaround, check if both the left and right hand sides are integers first. If either is not the case, 407 # the condition is evaluated to False. 408 try: 409 res = Integer(op(lhs.to_integer().get(), rhs.to_integer().get())) 410 except NotImplementedError: 411 if isinstance(lhs, String) and isinstance(rhs, String): 412 res = Integer(op(lhs.get(), rhs.get())) 413 else: 414 res = Integer(0) 415 if len(tree.children) >= 3: 416 target = self.interpret(tree.children[2]) 417 if target: 418 target.set(res) 419 return res 420 421 def DefAcquire(self, tree): 422 # Pretend that the mutex is acquired 423 return Integer(0x1) 424 425 def DefAdd(self, tree): 426 return self.__eval_binary_op(tree, lambda x,y: x + y) 427 428 def DefAnd(self, tree): 429 return self.__eval_binary_op(tree, lambda x,y: x & y) 430 431 def DefBuffer(self, tree): 432 size = self.interpret(tree.children[1]).get() 433 assert isinstance(size, int) 434 data = self.interpret(tree.children[2]).get() 435 if len(data) < size: 436 data = data + bytes(size - len(data)) 437 return Buffer(data) 438 439 def DefConcat(self, tree): 440 source1 = self.interpret(tree.children[0]) 441 source2 = self.interpret(tree.children[1]) 442 if isinstance(source1, Integer): 443 data = bytearray() 444 data.extend(source1.to_buffer().get()) 445 data.extend(source2.to_integer().to_buffer().get()) 446 result = Buffer(data) 447 elif isinstance(source1, String): 448 data = source1.get() 449 data += source2.to_string().get() 450 result = String(data) 451 elif isinstance(source1, Buffer): 452 data = bytearray() 453 data.extend(source1.get()) 454 data.extend(source2.to_buffer().get()) 455 result = Buffer(data) 456 else: 457 data = source1.to_string().get() + source2.to_string().get() 458 result = String(data) 459 target = self.interpret(tree.children[2]) 460 if target: 461 target.set(result) 462 return result 463 464 def DefConcatRes(self, tree): 465 data = bytearray() 466 source1 = self.interpret(tree.children[0]) 467 buf = source1.to_buffer().get() 468 if len(buf) >= 2 and buf[-2] == 0x79: 469 data.extend(buf[:-2]) 470 else: 471 data.extend(buf) 472 source2 = self.interpret(tree.children[1]) 473 data.extend(source2.to_buffer().get()) 474 result = Buffer(data) 475 target = self.interpret(tree.children[2]) 476 if target: 477 target.set(result) 478 return result 479 480 def DefCondRefOf(self, tree): 481 try: 482 source = self.interpret(tree.children[0]) 483 if source is not None: 484 target = self.interpret(tree.children[1]) 485 if target: 486 target.set(ObjectReference(source)) 487 return Integer(1) 488 else: 489 return Integer(0) 490 except UndefinedSymbol: 491 return Integer(0) 492 493 def DefDecrement(self, tree): 494 obj = self.interpret(tree.children[0]) 495 obj.set(Integer(obj.get() - 1)) 496 return None 497 498 def DefDerefOf(self, tree): 499 ref = self.interpret(tree.children[0]) 500 if isinstance(ref, (self.Argument, self.LocalVariable)): 501 ref = ref.get_obj() 502 if isinstance(ref, ObjectReference): 503 return ref.get() 504 else: 505 logging.debug(f"Attempt to dereference an object of type {ref.__class__.__name__}") 506 return ref 507 508 def DefDivide(self, tree): 509 dividend = self.interpret(tree.children[0]).get() 510 divisor = self.interpret(tree.children[1]).get() 511 if len(tree.children) >= 3: 512 remainer = self.interpret(tree.children[2]) 513 if remainer: 514 remainer.set(Integer(dividend % divisor)) 515 res = Integer(dividend // divisor) 516 if len(tree.children) >= 4: 517 target = self.interpret(tree.children[3]) 518 if target: 519 target.set(res) 520 return res 521 522 def DefIncrement(self, tree): 523 obj = self.interpret(tree.children[0]) 524 obj.set(Integer(obj.get() + 1)) 525 return None 526 527 def DefIndex(self, tree): 528 obj = self.interpret(tree.children[0]) 529 index = self.interpret(tree.children[1]) 530 target = self.interpret(tree.children[2]) 531 ret = ObjectReference(obj.get_obj(), index.get()) 532 if target: 533 target.set(ret) 534 return ret 535 536 def DefLAnd(self, tree): 537 return self.__eval_binary_op(tree, lambda x,y: 1 if x and y else 0) 538 539 def DefLEqual(self, tree): 540 return self.__eval_binary_op(tree, lambda x,y: x == y) 541 542 def DefLGreater(self, tree): 543 return self.__eval_binary_op(tree, lambda x,y: x > y) 544 545 def DefLLess(self, tree): 546 return self.__eval_binary_op(tree, lambda x,y: x < y) 547 548 def DefLNot(self, tree): 549 operand = self.interpret(tree.children[0]).get() 550 return Integer(1 if not operand else 0) 551 552 def DefLOr(self, tree): 553 return self.__eval_binary_op(tree, lambda x,y: 1 if x or y else 0) 554 555 def __match(self, op, obj, match_obj): 556 try: 557 if isinstance(match_obj, String): 558 return op(obj.to_string().get(), match_obj.get()) 559 elif isinstance(match_obj, (Integer, BufferField)): 560 return op(obj.to_integer().get(), match_obj.get()) 561 else: 562 # Comparison of buffer fields is not implemented yet 563 return False 564 except NotImplementedError: 565 return False 566 567 match_ops = { 568 0: lambda x,y: True, # TRUE 569 1: lambda x,y: x == y, # EQ 570 2: lambda x,y: x <= y, # LE 571 3: lambda x,y: x < y, # LT 572 4: lambda x,y: x >= y, # GE 573 5: lambda x,y: x > y, # GT 574 } 575 576 def DefMatch(self, tree): 577 pkg = self.interpret(tree.SearchPkg) 578 op1 = self.match_ops[tree.MatchOpcode1.value] 579 match_obj1 = self.interpret(tree.Operand1) 580 op2 = self.match_ops[tree.MatchOpcode2.value] 581 match_obj2 = self.interpret(tree.Operand2) 582 start_index = self.interpret(tree.StartIndex).get() 583 if isinstance(pkg, Package) and isinstance(start_index, int): 584 for i in range(start_index, len(pkg.elements)): 585 obj = pkg.elements[i] 586 if self.__match(op1, obj, match_obj1) and self.__match(op2, obj, match_obj2): 587 return Integer(i) 588 return Integer(0xffffffffffffffff) # Ones is 64-bit in DSDT rev 2 and above 589 590 def DefMod(self, tree): 591 return self.__eval_binary_op(tree, lambda x,y: x % y) 592 593 def DefMultiply(self, tree): 594 return self.__eval_binary_op(tree, lambda x,y: x * y) 595 596 def DefNAnd(self, tree): 597 return self.__eval_binary_op(tree, lambda x,y: ~(x & y)) 598 599 def DefNOr(self, tree): 600 return self.__eval_binary_op(tree, lambda x,y: ~(x | y)) 601 602 def DefNot(self, tree): 603 operand = self.interpret(tree.children[0]) 604 target = self.interpret(tree.children[1]) 605 ret = Integer(~operand.get()) 606 if target: 607 target.set(ret) 608 return ret 609 610 def DefOr(self, tree): 611 return self.__eval_binary_op(tree, lambda x,y: x | y) 612 613 def DefPackage(self, tree): 614 elements = list(map(lambda x: self.interpret(x), tree.children[2].children)) 615 return Package(elements) 616 617 def DefRefOf(self, tree): 618 obj = self.interpret(tree.children[0]) 619 return ObjectReference(obj) 620 621 def DefShiftLeft(self, tree): 622 return self.__eval_binary_op(tree, lambda x,y: x << y) 623 624 def DefShiftRight(self, tree): 625 return self.__eval_binary_op(tree, lambda x,y: x >> y) 626 627 def DefSizeOf(self, tree): 628 obj = self.interpret(tree.SuperName) 629 if isinstance(obj, (self.Argument, self.LocalVariable)): 630 obj = obj.get_obj() 631 632 if isinstance(obj, Buffer): 633 return Integer(len(obj.get())) 634 elif isinstance(obj, String): 635 return Integer(len(obj.get())) 636 elif isinstance(obj, Package): 637 return Integer(len(obj.elements)) 638 raise NotImplementedError(f"Cannot calculate the size of object of type {obj.__class__.__name__}") 639 640 def DefStore(self, tree): 641 obj = self.interpret(tree.children[0]) 642 target = self.interpret(tree.children[1]) 643 target.set(obj) 644 return None 645 646 def DefSubtract(self, tree): 647 return self.__eval_binary_op(tree, lambda x,y: x - y) 648 649 def DefToHexString(self, tree): 650 operand = self.interpret(tree.children[0]) 651 result = operand.to_hex_string() 652 target = self.interpret(tree.children[1]) 653 if target: 654 target.set(result) 655 return result 656 657 def DefToInteger(self, tree): 658 operand = self.interpret(tree.children[0]) 659 result = operand.to_integer() 660 target = self.interpret(tree.children[1]) 661 if target: 662 target.set(result) 663 return result 664 665 # 20.2.6.2 Local Objects Encoding 666 def Arg0Op(self, tree): 667 return self.Argument(self.stack[-1], 0) 668 669 def Arg1Op(self, tree): 670 return self.Argument(self.stack[-1], 1) 671 672 def Arg2Op(self, tree): 673 return self.Argument(self.stack[-1], 2) 674 675 def Arg3Op(self, tree): 676 return self.Argument(self.stack[-1], 3) 677 678 def Arg4Op(self, tree): 679 return self.Argument(self.stack[-1], 4) 680 681 def Arg5Op(self, tree): 682 return self.Argument(self.stack[-1], 5) 683 684 def Arg6Op(self, tree): 685 return self.Argument(self.stack[-1], 6) 686 687 def Local0Op(self, tree): 688 return self.LocalVariable(self.stack[-1], 0) 689 690 def Local1Op(self, tree): 691 return self.LocalVariable(self.stack[-1], 1) 692 693 def Local2Op(self, tree): 694 return self.LocalVariable(self.stack[-1], 2) 695 696 def Local3Op(self, tree): 697 return self.LocalVariable(self.stack[-1], 3) 698 699 def Local4Op(self, tree): 700 return self.LocalVariable(self.stack[-1], 4) 701 702 def Local5Op(self, tree): 703 return self.LocalVariable(self.stack[-1], 5) 704 705 def Local6Op(self, tree): 706 return self.LocalVariable(self.stack[-1], 6) 707 708 def Local7Op(self, tree): 709 return self.LocalVariable(self.stack[-1], 7) 710