1 | /****************************************************************************** |
2 | * |
3 | * Module Name: dswexec - Dispatcher method execution callbacks; |
4 | * dispatch to interpreter. |
5 | * |
6 | *****************************************************************************/ |
7 | |
8 | /* |
9 | * Copyright (C) 2000 - 2016, Intel Corp. |
10 | * All rights reserved. |
11 | * |
12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions |
14 | * are met: |
15 | * 1. Redistributions of source code must retain the above copyright |
16 | * notice, this list of conditions, and the following disclaimer, |
17 | * without modification. |
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer |
19 | * substantially similar to the "NO WARRANTY" disclaimer below |
20 | * ("Disclaimer") and any redistribution must be conditioned upon |
21 | * including a substantially similar Disclaimer requirement for further |
22 | * binary redistribution. |
23 | * 3. Neither the names of the above-listed copyright holders nor the names |
24 | * of any contributors may be used to endorse or promote products derived |
25 | * from this software without specific prior written permission. |
26 | * |
27 | * Alternatively, this software may be distributed under the terms of the |
28 | * GNU General Public License ("GPL") version 2 as published by the Free |
29 | * Software Foundation. |
30 | * |
31 | * NO WARRANTY |
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR |
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
42 | * POSSIBILITY OF SUCH DAMAGES. |
43 | */ |
44 | |
45 | #include "acpi.h" |
46 | #include "accommon.h" |
47 | #include "acparser.h" |
48 | #include "amlcode.h" |
49 | #include "acdispat.h" |
50 | #include "acinterp.h" |
51 | #include "acnamesp.h" |
52 | #include "acdebug.h" |
53 | |
54 | |
55 | #define _COMPONENT ACPI_DISPATCHER |
56 | ACPI_MODULE_NAME ("dswexec" ) |
57 | |
58 | /* |
59 | * Dispatch table for opcode classes |
60 | */ |
61 | static ACPI_EXECUTE_OP AcpiGbl_OpTypeDispatch [] = |
62 | { |
63 | AcpiExOpcode_0A_0T_1R, |
64 | AcpiExOpcode_1A_0T_0R, |
65 | AcpiExOpcode_1A_0T_1R, |
66 | AcpiExOpcode_1A_1T_0R, |
67 | AcpiExOpcode_1A_1T_1R, |
68 | AcpiExOpcode_2A_0T_0R, |
69 | AcpiExOpcode_2A_0T_1R, |
70 | AcpiExOpcode_2A_1T_1R, |
71 | AcpiExOpcode_2A_2T_1R, |
72 | AcpiExOpcode_3A_0T_0R, |
73 | AcpiExOpcode_3A_1T_1R, |
74 | AcpiExOpcode_6A_0T_1R |
75 | }; |
76 | |
77 | |
78 | /***************************************************************************** |
79 | * |
80 | * FUNCTION: AcpiDsGetPredicateValue |
81 | * |
82 | * PARAMETERS: WalkState - Current state of the parse tree walk |
83 | * ResultObj - if non-zero, pop result from result stack |
84 | * |
85 | * RETURN: Status |
86 | * |
87 | * DESCRIPTION: Get the result of a predicate evaluation |
88 | * |
89 | ****************************************************************************/ |
90 | |
91 | ACPI_STATUS |
92 | AcpiDsGetPredicateValue ( |
93 | ACPI_WALK_STATE *WalkState, |
94 | ACPI_OPERAND_OBJECT *ResultObj) |
95 | { |
96 | ACPI_STATUS Status = AE_OK; |
97 | ACPI_OPERAND_OBJECT *ObjDesc; |
98 | ACPI_OPERAND_OBJECT *LocalObjDesc = NULL; |
99 | |
100 | |
101 | ACPI_FUNCTION_TRACE_PTR (DsGetPredicateValue, WalkState); |
102 | |
103 | |
104 | WalkState->ControlState->Common.State = 0; |
105 | |
106 | if (ResultObj) |
107 | { |
108 | Status = AcpiDsResultPop (&ObjDesc, WalkState); |
109 | if (ACPI_FAILURE (Status)) |
110 | { |
111 | ACPI_EXCEPTION ((AE_INFO, Status, |
112 | "Could not get result from predicate evaluation" )); |
113 | |
114 | return_ACPI_STATUS (Status); |
115 | } |
116 | } |
117 | else |
118 | { |
119 | Status = AcpiDsCreateOperand (WalkState, WalkState->Op, 0); |
120 | if (ACPI_FAILURE (Status)) |
121 | { |
122 | return_ACPI_STATUS (Status); |
123 | } |
124 | |
125 | Status = AcpiExResolveToValue (&WalkState->Operands [0], WalkState); |
126 | if (ACPI_FAILURE (Status)) |
127 | { |
128 | return_ACPI_STATUS (Status); |
129 | } |
130 | |
131 | ObjDesc = WalkState->Operands [0]; |
132 | } |
133 | |
134 | if (!ObjDesc) |
135 | { |
136 | ACPI_ERROR ((AE_INFO, |
137 | "No predicate ObjDesc=%p State=%p" , |
138 | ObjDesc, WalkState)); |
139 | |
140 | return_ACPI_STATUS (AE_AML_NO_OPERAND); |
141 | } |
142 | |
143 | /* |
144 | * Result of predicate evaluation must be an Integer |
145 | * object. Implicitly convert the argument if necessary. |
146 | */ |
147 | Status = AcpiExConvertToInteger (ObjDesc, &LocalObjDesc, |
148 | ACPI_STRTOUL_BASE16); |
149 | if (ACPI_FAILURE (Status)) |
150 | { |
151 | goto Cleanup; |
152 | } |
153 | |
154 | if (LocalObjDesc->Common.Type != ACPI_TYPE_INTEGER) |
155 | { |
156 | ACPI_ERROR ((AE_INFO, |
157 | "Bad predicate (not an integer) ObjDesc=%p State=%p Type=0x%X" , |
158 | ObjDesc, WalkState, ObjDesc->Common.Type)); |
159 | |
160 | Status = AE_AML_OPERAND_TYPE; |
161 | goto Cleanup; |
162 | } |
163 | |
164 | /* Truncate the predicate to 32-bits if necessary */ |
165 | |
166 | (void) AcpiExTruncateFor32bitTable (LocalObjDesc); |
167 | |
168 | /* |
169 | * Save the result of the predicate evaluation on |
170 | * the control stack |
171 | */ |
172 | if (LocalObjDesc->Integer.Value) |
173 | { |
174 | WalkState->ControlState->Common.Value = TRUE; |
175 | } |
176 | else |
177 | { |
178 | /* |
179 | * Predicate is FALSE, we will just toss the |
180 | * rest of the package |
181 | */ |
182 | WalkState->ControlState->Common.Value = FALSE; |
183 | Status = AE_CTRL_FALSE; |
184 | } |
185 | |
186 | /* Predicate can be used for an implicit return value */ |
187 | |
188 | (void) AcpiDsDoImplicitReturn (LocalObjDesc, WalkState, TRUE); |
189 | |
190 | |
191 | Cleanup: |
192 | |
193 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, |
194 | "Completed a predicate eval=%X Op=%p\n" , |
195 | WalkState->ControlState->Common.Value, WalkState->Op)); |
196 | |
197 | /* Break to debugger to display result */ |
198 | |
199 | AcpiDbDisplayResultObject (LocalObjDesc, WalkState); |
200 | |
201 | /* |
202 | * Delete the predicate result object (we know that |
203 | * we don't need it anymore) |
204 | */ |
205 | if (LocalObjDesc != ObjDesc) |
206 | { |
207 | AcpiUtRemoveReference (LocalObjDesc); |
208 | } |
209 | AcpiUtRemoveReference (ObjDesc); |
210 | |
211 | WalkState->ControlState->Common.State = ACPI_CONTROL_NORMAL; |
212 | return_ACPI_STATUS (Status); |
213 | } |
214 | |
215 | |
216 | /***************************************************************************** |
217 | * |
218 | * FUNCTION: AcpiDsExecBeginOp |
219 | * |
220 | * PARAMETERS: WalkState - Current state of the parse tree walk |
221 | * OutOp - Where to return op if a new one is created |
222 | * |
223 | * RETURN: Status |
224 | * |
225 | * DESCRIPTION: Descending callback used during the execution of control |
226 | * methods. This is where most operators and operands are |
227 | * dispatched to the interpreter. |
228 | * |
229 | ****************************************************************************/ |
230 | |
231 | ACPI_STATUS |
232 | AcpiDsExecBeginOp ( |
233 | ACPI_WALK_STATE *WalkState, |
234 | ACPI_PARSE_OBJECT **OutOp) |
235 | { |
236 | ACPI_PARSE_OBJECT *Op; |
237 | ACPI_STATUS Status = AE_OK; |
238 | UINT32 OpcodeClass; |
239 | |
240 | |
241 | ACPI_FUNCTION_TRACE_PTR (DsExecBeginOp, WalkState); |
242 | |
243 | |
244 | Op = WalkState->Op; |
245 | if (!Op) |
246 | { |
247 | Status = AcpiDsLoad2BeginOp (WalkState, OutOp); |
248 | if (ACPI_FAILURE (Status)) |
249 | { |
250 | goto ErrorExit; |
251 | } |
252 | |
253 | Op = *OutOp; |
254 | WalkState->Op = Op; |
255 | WalkState->Opcode = Op->Common.AmlOpcode; |
256 | WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); |
257 | |
258 | if (AcpiNsOpensScope (WalkState->OpInfo->ObjectType)) |
259 | { |
260 | ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, |
261 | "(%s) Popping scope for Op %p\n" , |
262 | AcpiUtGetTypeName (WalkState->OpInfo->ObjectType), Op)); |
263 | |
264 | Status = AcpiDsScopeStackPop (WalkState); |
265 | if (ACPI_FAILURE (Status)) |
266 | { |
267 | goto ErrorExit; |
268 | } |
269 | } |
270 | } |
271 | |
272 | if (Op == WalkState->Origin) |
273 | { |
274 | if (OutOp) |
275 | { |
276 | *OutOp = Op; |
277 | } |
278 | |
279 | return_ACPI_STATUS (AE_OK); |
280 | } |
281 | |
282 | /* |
283 | * If the previous opcode was a conditional, this opcode |
284 | * must be the beginning of the associated predicate. |
285 | * Save this knowledge in the current scope descriptor |
286 | */ |
287 | if ((WalkState->ControlState) && |
288 | (WalkState->ControlState->Common.State == |
289 | ACPI_CONTROL_CONDITIONAL_EXECUTING)) |
290 | { |
291 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, |
292 | "Exec predicate Op=%p State=%p\n" , |
293 | Op, WalkState)); |
294 | |
295 | WalkState->ControlState->Common.State = |
296 | ACPI_CONTROL_PREDICATE_EXECUTING; |
297 | |
298 | /* Save start of predicate */ |
299 | |
300 | WalkState->ControlState->Control.PredicateOp = Op; |
301 | } |
302 | |
303 | |
304 | OpcodeClass = WalkState->OpInfo->Class; |
305 | |
306 | /* We want to send namepaths to the load code */ |
307 | |
308 | if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP) |
309 | { |
310 | OpcodeClass = AML_CLASS_NAMED_OBJECT; |
311 | } |
312 | |
313 | /* |
314 | * Handle the opcode based upon the opcode type |
315 | */ |
316 | switch (OpcodeClass) |
317 | { |
318 | case AML_CLASS_CONTROL: |
319 | |
320 | Status = AcpiDsExecBeginControlOp (WalkState, Op); |
321 | break; |
322 | |
323 | case AML_CLASS_NAMED_OBJECT: |
324 | |
325 | if (WalkState->WalkType & ACPI_WALK_METHOD) |
326 | { |
327 | /* |
328 | * Found a named object declaration during method execution; |
329 | * we must enter this object into the namespace. The created |
330 | * object is temporary and will be deleted upon completion of |
331 | * the execution of this method. |
332 | * |
333 | * Note 10/2010: Except for the Scope() op. This opcode does |
334 | * not actually create a new object, it refers to an existing |
335 | * object. However, for Scope(), we want to indeed open a |
336 | * new scope. |
337 | */ |
338 | if (Op->Common.AmlOpcode != AML_SCOPE_OP) |
339 | { |
340 | Status = AcpiDsLoad2BeginOp (WalkState, NULL); |
341 | } |
342 | else |
343 | { |
344 | Status = AcpiDsScopeStackPush ( |
345 | Op->Named.Node, Op->Named.Node->Type, WalkState); |
346 | if (ACPI_FAILURE (Status)) |
347 | { |
348 | return_ACPI_STATUS (Status); |
349 | } |
350 | } |
351 | } |
352 | break; |
353 | |
354 | case AML_CLASS_EXECUTE: |
355 | case AML_CLASS_CREATE: |
356 | |
357 | break; |
358 | |
359 | default: |
360 | |
361 | break; |
362 | } |
363 | |
364 | /* Nothing to do here during method execution */ |
365 | |
366 | return_ACPI_STATUS (Status); |
367 | |
368 | |
369 | ErrorExit: |
370 | Status = AcpiDsMethodError (Status, WalkState); |
371 | return_ACPI_STATUS (Status); |
372 | } |
373 | |
374 | |
375 | /***************************************************************************** |
376 | * |
377 | * FUNCTION: AcpiDsExecEndOp |
378 | * |
379 | * PARAMETERS: WalkState - Current state of the parse tree walk |
380 | * |
381 | * RETURN: Status |
382 | * |
383 | * DESCRIPTION: Ascending callback used during the execution of control |
384 | * methods. The only thing we really need to do here is to |
385 | * notice the beginning of IF, ELSE, and WHILE blocks. |
386 | * |
387 | ****************************************************************************/ |
388 | |
389 | ACPI_STATUS |
390 | AcpiDsExecEndOp ( |
391 | ACPI_WALK_STATE *WalkState) |
392 | { |
393 | ACPI_PARSE_OBJECT *Op; |
394 | ACPI_STATUS Status = AE_OK; |
395 | UINT32 OpType; |
396 | UINT32 OpClass; |
397 | ACPI_PARSE_OBJECT *NextOp; |
398 | ACPI_PARSE_OBJECT *FirstArg; |
399 | |
400 | |
401 | ACPI_FUNCTION_TRACE_PTR (DsExecEndOp, WalkState); |
402 | |
403 | |
404 | Op = WalkState->Op; |
405 | OpType = WalkState->OpInfo->Type; |
406 | OpClass = WalkState->OpInfo->Class; |
407 | |
408 | if (OpClass == AML_CLASS_UNKNOWN) |
409 | { |
410 | ACPI_ERROR ((AE_INFO, "Unknown opcode 0x%X" , Op->Common.AmlOpcode)); |
411 | return_ACPI_STATUS (AE_NOT_IMPLEMENTED); |
412 | } |
413 | |
414 | FirstArg = Op->Common.Value.Arg; |
415 | |
416 | /* Init the walk state */ |
417 | |
418 | WalkState->NumOperands = 0; |
419 | WalkState->OperandIndex = 0; |
420 | WalkState->ReturnDesc = NULL; |
421 | WalkState->ResultObj = NULL; |
422 | |
423 | /* Call debugger for single step support (DEBUG build only) */ |
424 | |
425 | Status = AcpiDbSingleStep (WalkState, Op, OpClass); |
426 | if (ACPI_FAILURE (Status)) |
427 | { |
428 | return_ACPI_STATUS (Status); |
429 | } |
430 | |
431 | /* Decode the Opcode Class */ |
432 | |
433 | switch (OpClass) |
434 | { |
435 | case AML_CLASS_ARGUMENT: /* Constants, literals, etc. */ |
436 | |
437 | if (WalkState->Opcode == AML_INT_NAMEPATH_OP) |
438 | { |
439 | Status = AcpiDsEvaluateNamePath (WalkState); |
440 | if (ACPI_FAILURE (Status)) |
441 | { |
442 | goto Cleanup; |
443 | } |
444 | } |
445 | break; |
446 | |
447 | case AML_CLASS_EXECUTE: /* Most operators with arguments */ |
448 | |
449 | /* Build resolved operand stack */ |
450 | |
451 | Status = AcpiDsCreateOperands (WalkState, FirstArg); |
452 | if (ACPI_FAILURE (Status)) |
453 | { |
454 | goto Cleanup; |
455 | } |
456 | |
457 | /* |
458 | * All opcodes require operand resolution, with the only exceptions |
459 | * being the ObjectType and SizeOf operators. |
460 | */ |
461 | if (!(WalkState->OpInfo->Flags & AML_NO_OPERAND_RESOLVE)) |
462 | { |
463 | /* Resolve all operands */ |
464 | |
465 | Status = AcpiExResolveOperands (WalkState->Opcode, |
466 | &(WalkState->Operands [WalkState->NumOperands -1]), |
467 | WalkState); |
468 | } |
469 | |
470 | if (ACPI_SUCCESS (Status)) |
471 | { |
472 | /* |
473 | * Dispatch the request to the appropriate interpreter handler |
474 | * routine. There is one routine per opcode "type" based upon the |
475 | * number of opcode arguments and return type. |
476 | */ |
477 | Status = AcpiGbl_OpTypeDispatch[OpType] (WalkState); |
478 | } |
479 | else |
480 | { |
481 | /* |
482 | * Treat constructs of the form "Store(LocalX,LocalX)" as noops when the |
483 | * Local is uninitialized. |
484 | */ |
485 | if ((Status == AE_AML_UNINITIALIZED_LOCAL) && |
486 | (WalkState->Opcode == AML_STORE_OP) && |
487 | (WalkState->Operands[0]->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) && |
488 | (WalkState->Operands[1]->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) && |
489 | (WalkState->Operands[0]->Reference.Class == |
490 | WalkState->Operands[1]->Reference.Class) && |
491 | (WalkState->Operands[0]->Reference.Value == |
492 | WalkState->Operands[1]->Reference.Value)) |
493 | { |
494 | Status = AE_OK; |
495 | } |
496 | else |
497 | { |
498 | ACPI_EXCEPTION ((AE_INFO, Status, |
499 | "While resolving operands for [%s]" , |
500 | AcpiPsGetOpcodeName (WalkState->Opcode))); |
501 | } |
502 | } |
503 | |
504 | /* Always delete the argument objects and clear the operand stack */ |
505 | |
506 | AcpiDsClearOperands (WalkState); |
507 | |
508 | /* |
509 | * If a result object was returned from above, push it on the |
510 | * current result stack |
511 | */ |
512 | if (ACPI_SUCCESS (Status) && |
513 | WalkState->ResultObj) |
514 | { |
515 | Status = AcpiDsResultPush (WalkState->ResultObj, WalkState); |
516 | } |
517 | break; |
518 | |
519 | default: |
520 | |
521 | switch (OpType) |
522 | { |
523 | case AML_TYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */ |
524 | |
525 | /* 1 Operand, 0 ExternalResult, 0 InternalResult */ |
526 | |
527 | Status = AcpiDsExecEndControlOp (WalkState, Op); |
528 | |
529 | break; |
530 | |
531 | case AML_TYPE_METHOD_CALL: |
532 | /* |
533 | * If the method is referenced from within a package |
534 | * declaration, it is not a invocation of the method, just |
535 | * a reference to it. |
536 | */ |
537 | if ((Op->Asl.Parent) && |
538 | ((Op->Asl.Parent->Asl.AmlOpcode == AML_PACKAGE_OP) || |
539 | (Op->Asl.Parent->Asl.AmlOpcode == AML_VAR_PACKAGE_OP))) |
540 | { |
541 | ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, |
542 | "Method Reference in a Package, Op=%p\n" , Op)); |
543 | |
544 | Op->Common.Node = (ACPI_NAMESPACE_NODE *) |
545 | Op->Asl.Value.Arg->Asl.Node; |
546 | AcpiUtAddReference (Op->Asl.Value.Arg->Asl.Node->Object); |
547 | return_ACPI_STATUS (AE_OK); |
548 | } |
549 | |
550 | ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, |
551 | "Method invocation, Op=%p\n" , Op)); |
552 | |
553 | /* |
554 | * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains |
555 | * the method Node pointer |
556 | */ |
557 | /* NextOp points to the op that holds the method name */ |
558 | |
559 | NextOp = FirstArg; |
560 | |
561 | /* NextOp points to first argument op */ |
562 | |
563 | NextOp = NextOp->Common.Next; |
564 | |
565 | /* |
566 | * Get the method's arguments and put them on the operand stack |
567 | */ |
568 | Status = AcpiDsCreateOperands (WalkState, NextOp); |
569 | if (ACPI_FAILURE (Status)) |
570 | { |
571 | break; |
572 | } |
573 | |
574 | /* |
575 | * Since the operands will be passed to another control method, |
576 | * we must resolve all local references here (Local variables, |
577 | * arguments to *this* method, etc.) |
578 | */ |
579 | Status = AcpiDsResolveOperands (WalkState); |
580 | if (ACPI_FAILURE (Status)) |
581 | { |
582 | /* On error, clear all resolved operands */ |
583 | |
584 | AcpiDsClearOperands (WalkState); |
585 | break; |
586 | } |
587 | |
588 | /* |
589 | * Tell the walk loop to preempt this running method and |
590 | * execute the new method |
591 | */ |
592 | Status = AE_CTRL_TRANSFER; |
593 | |
594 | /* |
595 | * Return now; we don't want to disturb anything, |
596 | * especially the operand count! |
597 | */ |
598 | return_ACPI_STATUS (Status); |
599 | |
600 | case AML_TYPE_CREATE_FIELD: |
601 | |
602 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, |
603 | "Executing CreateField Buffer/Index Op=%p\n" , Op)); |
604 | |
605 | Status = AcpiDsLoad2EndOp (WalkState); |
606 | if (ACPI_FAILURE (Status)) |
607 | { |
608 | break; |
609 | } |
610 | |
611 | Status = AcpiDsEvalBufferFieldOperands (WalkState, Op); |
612 | break; |
613 | |
614 | |
615 | case AML_TYPE_CREATE_OBJECT: |
616 | |
617 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, |
618 | "Executing CreateObject (Buffer/Package) Op=%p\n" , Op)); |
619 | |
620 | switch (Op->Common.Parent->Common.AmlOpcode) |
621 | { |
622 | case AML_NAME_OP: |
623 | /* |
624 | * Put the Node on the object stack (Contains the ACPI Name |
625 | * of this object) |
626 | */ |
627 | WalkState->Operands[0] = (void *) |
628 | Op->Common.Parent->Common.Node; |
629 | WalkState->NumOperands = 1; |
630 | |
631 | Status = AcpiDsCreateNode (WalkState, |
632 | Op->Common.Parent->Common.Node, Op->Common.Parent); |
633 | if (ACPI_FAILURE (Status)) |
634 | { |
635 | break; |
636 | } |
637 | |
638 | /* Fall through */ |
639 | /*lint -fallthrough */ |
640 | |
641 | case AML_INT_EVAL_SUBTREE_OP: |
642 | |
643 | Status = AcpiDsEvalDataObjectOperands (WalkState, Op, |
644 | AcpiNsGetAttachedObject (Op->Common.Parent->Common.Node)); |
645 | break; |
646 | |
647 | default: |
648 | |
649 | Status = AcpiDsEvalDataObjectOperands (WalkState, Op, NULL); |
650 | break; |
651 | } |
652 | |
653 | /* |
654 | * If a result object was returned from above, push it on the |
655 | * current result stack |
656 | */ |
657 | if (WalkState->ResultObj) |
658 | { |
659 | Status = AcpiDsResultPush (WalkState->ResultObj, WalkState); |
660 | } |
661 | break; |
662 | |
663 | case AML_TYPE_NAMED_FIELD: |
664 | case AML_TYPE_NAMED_COMPLEX: |
665 | case AML_TYPE_NAMED_SIMPLE: |
666 | case AML_TYPE_NAMED_NO_OBJ: |
667 | |
668 | Status = AcpiDsLoad2EndOp (WalkState); |
669 | if (ACPI_FAILURE (Status)) |
670 | { |
671 | break; |
672 | } |
673 | |
674 | if (Op->Common.AmlOpcode == AML_REGION_OP) |
675 | { |
676 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, |
677 | "Executing OpRegion Address/Length Op=%p\n" , Op)); |
678 | |
679 | Status = AcpiDsEvalRegionOperands (WalkState, Op); |
680 | if (ACPI_FAILURE (Status)) |
681 | { |
682 | break; |
683 | } |
684 | } |
685 | else if (Op->Common.AmlOpcode == AML_DATA_REGION_OP) |
686 | { |
687 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, |
688 | "Executing DataTableRegion Strings Op=%p\n" , Op)); |
689 | |
690 | Status = AcpiDsEvalTableRegionOperands (WalkState, Op); |
691 | if (ACPI_FAILURE (Status)) |
692 | { |
693 | break; |
694 | } |
695 | } |
696 | else if (Op->Common.AmlOpcode == AML_BANK_FIELD_OP) |
697 | { |
698 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, |
699 | "Executing BankField Op=%p\n" , Op)); |
700 | |
701 | Status = AcpiDsEvalBankFieldOperands (WalkState, Op); |
702 | if (ACPI_FAILURE (Status)) |
703 | { |
704 | break; |
705 | } |
706 | } |
707 | break; |
708 | |
709 | case AML_TYPE_UNDEFINED: |
710 | |
711 | ACPI_ERROR ((AE_INFO, |
712 | "Undefined opcode type Op=%p" , Op)); |
713 | return_ACPI_STATUS (AE_NOT_IMPLEMENTED); |
714 | |
715 | case AML_TYPE_BOGUS: |
716 | |
717 | ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, |
718 | "Internal opcode=%X type Op=%p\n" , |
719 | WalkState->Opcode, Op)); |
720 | break; |
721 | |
722 | default: |
723 | |
724 | ACPI_ERROR ((AE_INFO, |
725 | "Unimplemented opcode, class=0x%X " |
726 | "type=0x%X Opcode=0x%X Op=%p" , |
727 | OpClass, OpType, Op->Common.AmlOpcode, Op)); |
728 | |
729 | Status = AE_NOT_IMPLEMENTED; |
730 | break; |
731 | } |
732 | } |
733 | |
734 | /* |
735 | * ACPI 2.0 support for 64-bit integers: Truncate numeric |
736 | * result value if we are executing from a 32-bit ACPI table |
737 | */ |
738 | (void) AcpiExTruncateFor32bitTable (WalkState->ResultObj); |
739 | |
740 | /* |
741 | * Check if we just completed the evaluation of a |
742 | * conditional predicate |
743 | */ |
744 | if ((ACPI_SUCCESS (Status)) && |
745 | (WalkState->ControlState) && |
746 | (WalkState->ControlState->Common.State == |
747 | ACPI_CONTROL_PREDICATE_EXECUTING) && |
748 | (WalkState->ControlState->Control.PredicateOp == Op)) |
749 | { |
750 | Status = AcpiDsGetPredicateValue (WalkState, WalkState->ResultObj); |
751 | WalkState->ResultObj = NULL; |
752 | } |
753 | |
754 | |
755 | Cleanup: |
756 | |
757 | if (WalkState->ResultObj) |
758 | { |
759 | /* Break to debugger to display result */ |
760 | |
761 | AcpiDbDisplayResultObject (WalkState->ResultObj,WalkState); |
762 | |
763 | /* |
764 | * Delete the result op if and only if: |
765 | * Parent will not use the result -- such as any |
766 | * non-nested type2 op in a method (parent will be method) |
767 | */ |
768 | AcpiDsDeleteResultIfNotUsed (Op, WalkState->ResultObj, WalkState); |
769 | } |
770 | |
771 | #ifdef _UNDER_DEVELOPMENT |
772 | |
773 | if (WalkState->ParserState.Aml == WalkState->ParserState.AmlEnd) |
774 | { |
775 | AcpiDbMethodEnd (WalkState); |
776 | } |
777 | #endif |
778 | |
779 | /* Invoke exception handler on error */ |
780 | |
781 | if (ACPI_FAILURE (Status)) |
782 | { |
783 | Status = AcpiDsMethodError (Status, WalkState); |
784 | } |
785 | |
786 | /* Always clear the object stack */ |
787 | |
788 | WalkState->NumOperands = 0; |
789 | return_ACPI_STATUS (Status); |
790 | } |
791 | |