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