xref: /titanic_44/usr/src/uts/intel/io/acpica/dispatcher/dsopcode.c (revision 5bbb4db2c3f208d12bf0fd11769728f9e5ba66a2)
1 /******************************************************************************
2  *
3  * Module Name: dsopcode - Dispatcher Op Region support and handling of
4  *                         "control" opcodes
5  *
6  *****************************************************************************/
7 
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
13  * All rights reserved.
14  *
15  * 2. License
16  *
17  * 2.1. This is your license from Intel Corp. under its intellectual property
18  * rights.  You may have additional license terms from the party that provided
19  * you this software, covering your right to use that party's intellectual
20  * property rights.
21  *
22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23  * copy of the source code appearing in this file ("Covered Code") an
24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25  * base code distributed originally by Intel ("Original Intel Code") to copy,
26  * make derivatives, distribute, use and display any portion of the Covered
27  * Code in any form, with the right to sublicense such rights; and
28  *
29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30  * license (with the right to sublicense), under only those claims of Intel
31  * patents that are infringed by the Original Intel Code, to make, use, sell,
32  * offer to sell, and import the Covered Code and derivative works thereof
33  * solely to the minimum extent necessary to exercise the above copyright
34  * license, and in no event shall the patent license extend to any additions
35  * to or modifications of the Original Intel Code.  No other license or right
36  * is granted directly or by implication, estoppel or otherwise;
37  *
38  * The above copyright and patent license is granted only if the following
39  * conditions are met:
40  *
41  * 3. Conditions
42  *
43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44  * Redistribution of source code of any substantial portion of the Covered
45  * Code or modification with rights to further distribute source must include
46  * the above Copyright Notice, the above License, this list of Conditions,
47  * and the following Disclaimer and Export Compliance provision.  In addition,
48  * Licensee must cause all Covered Code to which Licensee contributes to
49  * contain a file documenting the changes Licensee made to create that Covered
50  * Code and the date of any change.  Licensee must include in that file the
51  * documentation of any changes made by any predecessor Licensee.  Licensee
52  * must include a prominent statement that the modification is derived,
53  * directly or indirectly, from Original Intel Code.
54  *
55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56  * Redistribution of source code of any substantial portion of the Covered
57  * Code or modification without rights to further distribute source must
58  * include the following Disclaimer and Export Compliance provision in the
59  * documentation and/or other materials provided with distribution.  In
60  * addition, Licensee may not authorize further sublicense of source of any
61  * portion of the Covered Code, and must include terms to the effect that the
62  * license from Licensee to its licensee is limited to the intellectual
63  * property embodied in the software Licensee provides to its licensee, and
64  * not to intellectual property embodied in modifications its licensee may
65  * make.
66  *
67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
68  * substantial portion of the Covered Code or modification must reproduce the
69  * above Copyright Notice, and the following Disclaimer and Export Compliance
70  * provision in the documentation and/or other materials provided with the
71  * distribution.
72  *
73  * 3.4. Intel retains all right, title, and interest in and to the Original
74  * Intel Code.
75  *
76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77  * Intel shall be used in advertising or otherwise to promote the sale, use or
78  * other dealings in products derived from or relating to the Covered Code
79  * without prior written authorization from Intel.
80  *
81  * 4. Disclaimer and Export Compliance
82  *
83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89  * PARTICULAR PURPOSE.
90  *
91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98  * LIMITED REMEDY.
99  *
100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
101  * software or system incorporating such software without first obtaining any
102  * required license or other approval from the U. S. Department of Commerce or
103  * any other agency or department of the United States Government.  In the
104  * event Licensee exports any such software from the United States or
105  * re-exports any such software from a foreign destination, Licensee shall
106  * ensure that the distribution and export/re-export of the software is in
107  * compliance with all laws, regulations, orders, or other restrictions of the
108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109  * any of its subsidiaries will export/re-export any technical data, process,
110  * software, or service, directly or indirectly, to any country for which the
111  * United States government or any agency thereof requires an export license,
112  * other governmental approval, or letter of assurance, without first obtaining
113  * such license, approval or letter.
114  *
115  *****************************************************************************/
116 
117 #define __DSOPCODE_C__
118 
119 #include "acpi.h"
120 #include "accommon.h"
121 #include "acparser.h"
122 #include "amlcode.h"
123 #include "acdispat.h"
124 #include "acinterp.h"
125 #include "acnamesp.h"
126 #include "acevents.h"
127 #include "actables.h"
128 
129 #define _COMPONENT          ACPI_DISPATCHER
130         ACPI_MODULE_NAME    ("dsopcode")
131 
132 /* Local prototypes */
133 
134 static ACPI_STATUS
135 AcpiDsExecuteArguments (
136     ACPI_NAMESPACE_NODE     *Node,
137     ACPI_NAMESPACE_NODE     *ScopeNode,
138     UINT32                  AmlLength,
139     UINT8                   *AmlStart);
140 
141 static ACPI_STATUS
142 AcpiDsInitBufferField (
143     UINT16                  AmlOpcode,
144     ACPI_OPERAND_OBJECT     *ObjDesc,
145     ACPI_OPERAND_OBJECT     *BufferDesc,
146     ACPI_OPERAND_OBJECT     *OffsetDesc,
147     ACPI_OPERAND_OBJECT     *LengthDesc,
148     ACPI_OPERAND_OBJECT     *ResultDesc);
149 
150 
151 /*******************************************************************************
152  *
153  * FUNCTION:    AcpiDsExecuteArguments
154  *
155  * PARAMETERS:  Node                - Object NS node
156  *              ScopeNode           - Parent NS node
157  *              AmlLength           - Length of executable AML
158  *              AmlStart            - Pointer to the AML
159  *
160  * RETURN:      Status.
161  *
162  * DESCRIPTION: Late (deferred) execution of region or field arguments
163  *
164  ******************************************************************************/
165 
166 static ACPI_STATUS
167 AcpiDsExecuteArguments (
168     ACPI_NAMESPACE_NODE     *Node,
169     ACPI_NAMESPACE_NODE     *ScopeNode,
170     UINT32                  AmlLength,
171     UINT8                   *AmlStart)
172 {
173     ACPI_STATUS             Status;
174     ACPI_PARSE_OBJECT       *Op;
175     ACPI_WALK_STATE         *WalkState;
176 
177 
178     ACPI_FUNCTION_TRACE (DsExecuteArguments);
179 
180 
181     /*
182      * Allocate a new parser op to be the root of the parsed tree
183      */
184     Op = AcpiPsAllocOp (AML_INT_EVAL_SUBTREE_OP);
185     if (!Op)
186     {
187         return_ACPI_STATUS (AE_NO_MEMORY);
188     }
189 
190     /* Save the Node for use in AcpiPsParseAml */
191 
192     Op->Common.Node = ScopeNode;
193 
194     /* Create and initialize a new parser state */
195 
196     WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
197     if (!WalkState)
198     {
199         Status = AE_NO_MEMORY;
200         goto Cleanup;
201     }
202 
203     Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, AmlStart,
204                     AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
205     if (ACPI_FAILURE (Status))
206     {
207         AcpiDsDeleteWalkState (WalkState);
208         goto Cleanup;
209     }
210 
211     /* Mark this parse as a deferred opcode */
212 
213     WalkState->ParseFlags = ACPI_PARSE_DEFERRED_OP;
214     WalkState->DeferredNode = Node;
215 
216     /* Pass1: Parse the entire declaration */
217 
218     Status = AcpiPsParseAml (WalkState);
219     if (ACPI_FAILURE (Status))
220     {
221         goto Cleanup;
222     }
223 
224     /* Get and init the Op created above */
225 
226     Op->Common.Node = Node;
227     AcpiPsDeleteParseTree (Op);
228 
229     /* Evaluate the deferred arguments */
230 
231     Op = AcpiPsAllocOp (AML_INT_EVAL_SUBTREE_OP);
232     if (!Op)
233     {
234         return_ACPI_STATUS (AE_NO_MEMORY);
235     }
236 
237     Op->Common.Node = ScopeNode;
238 
239     /* Create and initialize a new parser state */
240 
241     WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
242     if (!WalkState)
243     {
244         Status = AE_NO_MEMORY;
245         goto Cleanup;
246     }
247 
248     /* Execute the opcode and arguments */
249 
250     Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, AmlStart,
251                     AmlLength, NULL, ACPI_IMODE_EXECUTE);
252     if (ACPI_FAILURE (Status))
253     {
254         AcpiDsDeleteWalkState (WalkState);
255         goto Cleanup;
256     }
257 
258     /* Mark this execution as a deferred opcode */
259 
260     WalkState->DeferredNode = Node;
261     Status = AcpiPsParseAml (WalkState);
262 
263 Cleanup:
264     AcpiPsDeleteParseTree (Op);
265     return_ACPI_STATUS (Status);
266 }
267 
268 
269 /*******************************************************************************
270  *
271  * FUNCTION:    AcpiDsGetBufferFieldArguments
272  *
273  * PARAMETERS:  ObjDesc         - A valid BufferField object
274  *
275  * RETURN:      Status.
276  *
277  * DESCRIPTION: Get BufferField Buffer and Index.  This implements the late
278  *              evaluation of these field attributes.
279  *
280  ******************************************************************************/
281 
282 ACPI_STATUS
283 AcpiDsGetBufferFieldArguments (
284     ACPI_OPERAND_OBJECT     *ObjDesc)
285 {
286     ACPI_OPERAND_OBJECT     *ExtraDesc;
287     ACPI_NAMESPACE_NODE     *Node;
288     ACPI_STATUS             Status;
289 
290 
291     ACPI_FUNCTION_TRACE_PTR (DsGetBufferFieldArguments, ObjDesc);
292 
293 
294     if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
295     {
296         return_ACPI_STATUS (AE_OK);
297     }
298 
299     /* Get the AML pointer (method object) and BufferField node */
300 
301     ExtraDesc = AcpiNsGetSecondaryObject (ObjDesc);
302     Node = ObjDesc->BufferField.Node;
303 
304     ACPI_DEBUG_EXEC(AcpiUtDisplayInitPathname (ACPI_TYPE_BUFFER_FIELD, Node, NULL));
305     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n",
306         AcpiUtGetNodeName (Node)));
307 
308     /* Execute the AML code for the TermArg arguments */
309 
310     Status = AcpiDsExecuteArguments (Node, AcpiNsGetParentNode (Node),
311                 ExtraDesc->Extra.AmlLength, ExtraDesc->Extra.AmlStart);
312     return_ACPI_STATUS (Status);
313 }
314 
315 
316 /*******************************************************************************
317  *
318  * FUNCTION:    AcpiDsGetBankFieldArguments
319  *
320  * PARAMETERS:  ObjDesc         - A valid BankField object
321  *
322  * RETURN:      Status.
323  *
324  * DESCRIPTION: Get BankField BankValue.  This implements the late
325  *              evaluation of these field attributes.
326  *
327  ******************************************************************************/
328 
329 ACPI_STATUS
330 AcpiDsGetBankFieldArguments (
331     ACPI_OPERAND_OBJECT     *ObjDesc)
332 {
333     ACPI_OPERAND_OBJECT     *ExtraDesc;
334     ACPI_NAMESPACE_NODE     *Node;
335     ACPI_STATUS             Status;
336 
337 
338     ACPI_FUNCTION_TRACE_PTR (DsGetBankFieldArguments, ObjDesc);
339 
340 
341     if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
342     {
343         return_ACPI_STATUS (AE_OK);
344     }
345 
346     /* Get the AML pointer (method object) and BankField node */
347 
348     ExtraDesc = AcpiNsGetSecondaryObject (ObjDesc);
349     Node = ObjDesc->BankField.Node;
350 
351     ACPI_DEBUG_EXEC(AcpiUtDisplayInitPathname (ACPI_TYPE_LOCAL_BANK_FIELD, Node, NULL));
352     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n",
353         AcpiUtGetNodeName (Node)));
354 
355     /* Execute the AML code for the TermArg arguments */
356 
357     Status = AcpiDsExecuteArguments (Node, AcpiNsGetParentNode (Node),
358                 ExtraDesc->Extra.AmlLength, ExtraDesc->Extra.AmlStart);
359     return_ACPI_STATUS (Status);
360 }
361 
362 
363 /*******************************************************************************
364  *
365  * FUNCTION:    AcpiDsGetBufferArguments
366  *
367  * PARAMETERS:  ObjDesc         - A valid Buffer object
368  *
369  * RETURN:      Status.
370  *
371  * DESCRIPTION: Get Buffer length and initializer byte list.  This implements
372  *              the late evaluation of these attributes.
373  *
374  ******************************************************************************/
375 
376 ACPI_STATUS
377 AcpiDsGetBufferArguments (
378     ACPI_OPERAND_OBJECT     *ObjDesc)
379 {
380     ACPI_NAMESPACE_NODE     *Node;
381     ACPI_STATUS             Status;
382 
383 
384     ACPI_FUNCTION_TRACE_PTR (DsGetBufferArguments, ObjDesc);
385 
386 
387     if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
388     {
389         return_ACPI_STATUS (AE_OK);
390     }
391 
392     /* Get the Buffer node */
393 
394     Node = ObjDesc->Buffer.Node;
395     if (!Node)
396     {
397         ACPI_ERROR ((AE_INFO,
398             "No pointer back to NS node in buffer obj %p", ObjDesc));
399         return_ACPI_STATUS (AE_AML_INTERNAL);
400     }
401 
402     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Buffer Arg Init\n"));
403 
404     /* Execute the AML code for the TermArg arguments */
405 
406     Status = AcpiDsExecuteArguments (Node, Node,
407                 ObjDesc->Buffer.AmlLength, ObjDesc->Buffer.AmlStart);
408     return_ACPI_STATUS (Status);
409 }
410 
411 
412 /*******************************************************************************
413  *
414  * FUNCTION:    AcpiDsGetPackageArguments
415  *
416  * PARAMETERS:  ObjDesc         - A valid Package object
417  *
418  * RETURN:      Status.
419  *
420  * DESCRIPTION: Get Package length and initializer byte list.  This implements
421  *              the late evaluation of these attributes.
422  *
423  ******************************************************************************/
424 
425 ACPI_STATUS
426 AcpiDsGetPackageArguments (
427     ACPI_OPERAND_OBJECT     *ObjDesc)
428 {
429     ACPI_NAMESPACE_NODE     *Node;
430     ACPI_STATUS             Status;
431 
432 
433     ACPI_FUNCTION_TRACE_PTR (DsGetPackageArguments, ObjDesc);
434 
435 
436     if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
437     {
438         return_ACPI_STATUS (AE_OK);
439     }
440 
441     /* Get the Package node */
442 
443     Node = ObjDesc->Package.Node;
444     if (!Node)
445     {
446         ACPI_ERROR ((AE_INFO,
447             "No pointer back to NS node in package %p", ObjDesc));
448         return_ACPI_STATUS (AE_AML_INTERNAL);
449     }
450 
451     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Package Arg Init\n"));
452 
453     /* Execute the AML code for the TermArg arguments */
454 
455     Status = AcpiDsExecuteArguments (Node, Node,
456                 ObjDesc->Package.AmlLength, ObjDesc->Package.AmlStart);
457     return_ACPI_STATUS (Status);
458 }
459 
460 
461 /*****************************************************************************
462  *
463  * FUNCTION:    AcpiDsGetRegionArguments
464  *
465  * PARAMETERS:  ObjDesc         - A valid region object
466  *
467  * RETURN:      Status.
468  *
469  * DESCRIPTION: Get region address and length.  This implements the late
470  *              evaluation of these region attributes.
471  *
472  ****************************************************************************/
473 
474 ACPI_STATUS
475 AcpiDsGetRegionArguments (
476     ACPI_OPERAND_OBJECT     *ObjDesc)
477 {
478     ACPI_NAMESPACE_NODE     *Node;
479     ACPI_STATUS             Status;
480     ACPI_OPERAND_OBJECT     *ExtraDesc;
481 
482 
483     ACPI_FUNCTION_TRACE_PTR (DsGetRegionArguments, ObjDesc);
484 
485 
486     if (ObjDesc->Region.Flags & AOPOBJ_DATA_VALID)
487     {
488         return_ACPI_STATUS (AE_OK);
489     }
490 
491     ExtraDesc = AcpiNsGetSecondaryObject (ObjDesc);
492     if (!ExtraDesc)
493     {
494         return_ACPI_STATUS (AE_NOT_EXIST);
495     }
496 
497     /* Get the Region node */
498 
499     Node = ObjDesc->Region.Node;
500 
501     ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (ACPI_TYPE_REGION, Node, NULL));
502 
503     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n",
504         AcpiUtGetNodeName (Node), ExtraDesc->Extra.AmlStart));
505 
506     /* Execute the argument AML */
507 
508     Status = AcpiDsExecuteArguments (Node, AcpiNsGetParentNode (Node),
509                 ExtraDesc->Extra.AmlLength, ExtraDesc->Extra.AmlStart);
510     return_ACPI_STATUS (Status);
511 }
512 
513 
514 /*******************************************************************************
515  *
516  * FUNCTION:    AcpiDsInitializeRegion
517  *
518  * PARAMETERS:  ObjHandle       - Region namespace node
519  *
520  * RETURN:      Status
521  *
522  * DESCRIPTION: Front end to EvInitializeRegion
523  *
524  ******************************************************************************/
525 
526 ACPI_STATUS
527 AcpiDsInitializeRegion (
528     ACPI_HANDLE             ObjHandle)
529 {
530     ACPI_OPERAND_OBJECT     *ObjDesc;
531     ACPI_STATUS             Status;
532 
533 
534     ObjDesc = AcpiNsGetAttachedObject (ObjHandle);
535 
536     /* Namespace is NOT locked */
537 
538     Status = AcpiEvInitializeRegion (ObjDesc, FALSE);
539     return (Status);
540 }
541 
542 
543 /*******************************************************************************
544  *
545  * FUNCTION:    AcpiDsInitBufferField
546  *
547  * PARAMETERS:  AmlOpcode       - CreateXxxField
548  *              ObjDesc         - BufferField object
549  *              BufferDesc      - Host Buffer
550  *              OffsetDesc      - Offset into buffer
551  *              LengthDesc      - Length of field (CREATE_FIELD_OP only)
552  *              ResultDesc      - Where to store the result
553  *
554  * RETURN:      Status
555  *
556  * DESCRIPTION: Perform actual initialization of a buffer field
557  *
558  ******************************************************************************/
559 
560 static ACPI_STATUS
561 AcpiDsInitBufferField (
562     UINT16                  AmlOpcode,
563     ACPI_OPERAND_OBJECT     *ObjDesc,
564     ACPI_OPERAND_OBJECT     *BufferDesc,
565     ACPI_OPERAND_OBJECT     *OffsetDesc,
566     ACPI_OPERAND_OBJECT     *LengthDesc,
567     ACPI_OPERAND_OBJECT     *ResultDesc)
568 {
569     UINT32                  Offset;
570     UINT32                  BitOffset;
571     UINT32                  BitCount;
572     UINT8                   FieldFlags;
573     ACPI_STATUS             Status;
574 
575 
576     ACPI_FUNCTION_TRACE_PTR (DsInitBufferField, ObjDesc);
577 
578 
579     /* Host object must be a Buffer */
580 
581     if (BufferDesc->Common.Type != ACPI_TYPE_BUFFER)
582     {
583         ACPI_ERROR ((AE_INFO,
584             "Target of Create Field is not a Buffer object - %s",
585             AcpiUtGetObjectTypeName (BufferDesc)));
586 
587         Status = AE_AML_OPERAND_TYPE;
588         goto Cleanup;
589     }
590 
591     /*
592      * The last parameter to all of these opcodes (ResultDesc) started
593      * out as a NameString, and should therefore now be a NS node
594      * after resolution in AcpiExResolveOperands().
595      */
596     if (ACPI_GET_DESCRIPTOR_TYPE (ResultDesc) != ACPI_DESC_TYPE_NAMED)
597     {
598         ACPI_ERROR ((AE_INFO,
599             "(%s) destination not a NS Node [%s]",
600             AcpiPsGetOpcodeName (AmlOpcode),
601             AcpiUtGetDescriptorName (ResultDesc)));
602 
603         Status = AE_AML_OPERAND_TYPE;
604         goto Cleanup;
605     }
606 
607     Offset = (UINT32) OffsetDesc->Integer.Value;
608 
609     /*
610      * Setup the Bit offsets and counts, according to the opcode
611      */
612     switch (AmlOpcode)
613     {
614     case AML_CREATE_FIELD_OP:
615 
616         /* Offset is in bits, count is in bits */
617 
618         FieldFlags = AML_FIELD_ACCESS_BYTE;
619         BitOffset  = Offset;
620         BitCount   = (UINT32) LengthDesc->Integer.Value;
621 
622         /* Must have a valid (>0) bit count */
623 
624         if (BitCount == 0)
625         {
626             ACPI_ERROR ((AE_INFO,
627                 "Attempt to CreateField of length zero"));
628             Status = AE_AML_OPERAND_VALUE;
629             goto Cleanup;
630         }
631         break;
632 
633     case AML_CREATE_BIT_FIELD_OP:
634 
635         /* Offset is in bits, Field is one bit */
636 
637         BitOffset  = Offset;
638         BitCount   = 1;
639         FieldFlags = AML_FIELD_ACCESS_BYTE;
640         break;
641 
642     case AML_CREATE_BYTE_FIELD_OP:
643 
644         /* Offset is in bytes, field is one byte */
645 
646         BitOffset  = 8 * Offset;
647         BitCount   = 8;
648         FieldFlags = AML_FIELD_ACCESS_BYTE;
649         break;
650 
651     case AML_CREATE_WORD_FIELD_OP:
652 
653         /* Offset is in bytes, field is one word */
654 
655         BitOffset  = 8 * Offset;
656         BitCount   = 16;
657         FieldFlags = AML_FIELD_ACCESS_WORD;
658         break;
659 
660     case AML_CREATE_DWORD_FIELD_OP:
661 
662         /* Offset is in bytes, field is one dword */
663 
664         BitOffset  = 8 * Offset;
665         BitCount   = 32;
666         FieldFlags = AML_FIELD_ACCESS_DWORD;
667         break;
668 
669     case AML_CREATE_QWORD_FIELD_OP:
670 
671         /* Offset is in bytes, field is one qword */
672 
673         BitOffset  = 8 * Offset;
674         BitCount   = 64;
675         FieldFlags = AML_FIELD_ACCESS_QWORD;
676         break;
677 
678     default:
679 
680         ACPI_ERROR ((AE_INFO,
681             "Unknown field creation opcode %02x",
682             AmlOpcode));
683         Status = AE_AML_BAD_OPCODE;
684         goto Cleanup;
685     }
686 
687     /* Entire field must fit within the current length of the buffer */
688 
689     if ((BitOffset + BitCount) >
690         (8 * (UINT32) BufferDesc->Buffer.Length))
691     {
692         ACPI_ERROR ((AE_INFO,
693             "Field [%4.4s] at %d exceeds Buffer [%4.4s] size %d (bits)",
694             AcpiUtGetNodeName (ResultDesc),
695             BitOffset + BitCount,
696             AcpiUtGetNodeName (BufferDesc->Buffer.Node),
697             8 * (UINT32) BufferDesc->Buffer.Length));
698         Status = AE_AML_BUFFER_LIMIT;
699         goto Cleanup;
700     }
701 
702     /*
703      * Initialize areas of the field object that are common to all fields
704      * For FieldFlags, use LOCK_RULE = 0 (NO_LOCK),
705      * UPDATE_RULE = 0 (UPDATE_PRESERVE)
706      */
707     Status = AcpiExPrepCommonFieldObject (ObjDesc, FieldFlags, 0,
708                                             BitOffset, BitCount);
709     if (ACPI_FAILURE (Status))
710     {
711         goto Cleanup;
712     }
713 
714     ObjDesc->BufferField.BufferObj = BufferDesc;
715 
716     /* Reference count for BufferDesc inherits ObjDesc count */
717 
718     BufferDesc->Common.ReferenceCount = (UINT16)
719         (BufferDesc->Common.ReferenceCount + ObjDesc->Common.ReferenceCount);
720 
721 
722 Cleanup:
723 
724     /* Always delete the operands */
725 
726     AcpiUtRemoveReference (OffsetDesc);
727     AcpiUtRemoveReference (BufferDesc);
728 
729     if (AmlOpcode == AML_CREATE_FIELD_OP)
730     {
731         AcpiUtRemoveReference (LengthDesc);
732     }
733 
734     /* On failure, delete the result descriptor */
735 
736     if (ACPI_FAILURE (Status))
737     {
738         AcpiUtRemoveReference (ResultDesc);     /* Result descriptor */
739     }
740     else
741     {
742         /* Now the address and length are valid for this BufferField */
743 
744         ObjDesc->BufferField.Flags |= AOPOBJ_DATA_VALID;
745     }
746 
747     return_ACPI_STATUS (Status);
748 }
749 
750 
751 /*******************************************************************************
752  *
753  * FUNCTION:    AcpiDsEvalBufferFieldOperands
754  *
755  * PARAMETERS:  WalkState       - Current walk
756  *              Op              - A valid BufferField Op object
757  *
758  * RETURN:      Status
759  *
760  * DESCRIPTION: Get BufferField Buffer and Index
761  *              Called from AcpiDsExecEndOp during BufferField parse tree walk
762  *
763  ******************************************************************************/
764 
765 ACPI_STATUS
766 AcpiDsEvalBufferFieldOperands (
767     ACPI_WALK_STATE         *WalkState,
768     ACPI_PARSE_OBJECT       *Op)
769 {
770     ACPI_STATUS             Status;
771     ACPI_OPERAND_OBJECT     *ObjDesc;
772     ACPI_NAMESPACE_NODE     *Node;
773     ACPI_PARSE_OBJECT       *NextOp;
774 
775 
776     ACPI_FUNCTION_TRACE_PTR (DsEvalBufferFieldOperands, Op);
777 
778 
779     /*
780      * This is where we evaluate the address and length fields of the
781      * CreateXxxField declaration
782      */
783     Node =  Op->Common.Node;
784 
785     /* NextOp points to the op that holds the Buffer */
786 
787     NextOp = Op->Common.Value.Arg;
788 
789     /* Evaluate/create the address and length operands */
790 
791     Status = AcpiDsCreateOperands (WalkState, NextOp);
792     if (ACPI_FAILURE (Status))
793     {
794         return_ACPI_STATUS (Status);
795     }
796 
797     ObjDesc = AcpiNsGetAttachedObject (Node);
798     if (!ObjDesc)
799     {
800         return_ACPI_STATUS (AE_NOT_EXIST);
801     }
802 
803     /* Resolve the operands */
804 
805     Status = AcpiExResolveOperands (Op->Common.AmlOpcode,
806                     ACPI_WALK_OPERANDS, WalkState);
807     if (ACPI_FAILURE (Status))
808     {
809         ACPI_ERROR ((AE_INFO, "(%s) bad operand(s) (%X)",
810             AcpiPsGetOpcodeName (Op->Common.AmlOpcode), Status));
811 
812         return_ACPI_STATUS (Status);
813     }
814 
815     /* Initialize the Buffer Field */
816 
817     if (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP)
818     {
819         /* NOTE: Slightly different operands for this opcode */
820 
821         Status = AcpiDsInitBufferField (Op->Common.AmlOpcode, ObjDesc,
822                     WalkState->Operands[0], WalkState->Operands[1],
823                     WalkState->Operands[2], WalkState->Operands[3]);
824     }
825     else
826     {
827         /* All other, CreateXxxField opcodes */
828 
829         Status = AcpiDsInitBufferField (Op->Common.AmlOpcode, ObjDesc,
830                     WalkState->Operands[0], WalkState->Operands[1],
831                                       NULL, WalkState->Operands[2]);
832     }
833 
834     return_ACPI_STATUS (Status);
835 }
836 
837 
838 /*******************************************************************************
839  *
840  * FUNCTION:    AcpiDsEvalRegionOperands
841  *
842  * PARAMETERS:  WalkState       - Current walk
843  *              Op              - A valid region Op object
844  *
845  * RETURN:      Status
846  *
847  * DESCRIPTION: Get region address and length
848  *              Called from AcpiDsExecEndOp during OpRegion parse tree walk
849  *
850  ******************************************************************************/
851 
852 ACPI_STATUS
853 AcpiDsEvalRegionOperands (
854     ACPI_WALK_STATE         *WalkState,
855     ACPI_PARSE_OBJECT       *Op)
856 {
857     ACPI_STATUS             Status;
858     ACPI_OPERAND_OBJECT     *ObjDesc;
859     ACPI_OPERAND_OBJECT     *OperandDesc;
860     ACPI_NAMESPACE_NODE     *Node;
861     ACPI_PARSE_OBJECT       *NextOp;
862 
863 
864     ACPI_FUNCTION_TRACE_PTR (DsEvalRegionOperands, Op);
865 
866 
867     /*
868      * This is where we evaluate the address and length fields of the
869      * OpRegion declaration
870      */
871     Node =  Op->Common.Node;
872 
873     /* NextOp points to the op that holds the SpaceID */
874 
875     NextOp = Op->Common.Value.Arg;
876 
877     /* NextOp points to address op */
878 
879     NextOp = NextOp->Common.Next;
880 
881     /* Evaluate/create the address and length operands */
882 
883     Status = AcpiDsCreateOperands (WalkState, NextOp);
884     if (ACPI_FAILURE (Status))
885     {
886         return_ACPI_STATUS (Status);
887     }
888 
889     /* Resolve the length and address operands to numbers */
890 
891     Status = AcpiExResolveOperands (Op->Common.AmlOpcode,
892                 ACPI_WALK_OPERANDS, WalkState);
893     if (ACPI_FAILURE (Status))
894     {
895         return_ACPI_STATUS (Status);
896     }
897 
898     ObjDesc = AcpiNsGetAttachedObject (Node);
899     if (!ObjDesc)
900     {
901         return_ACPI_STATUS (AE_NOT_EXIST);
902     }
903 
904     /*
905      * Get the length operand and save it
906      * (at Top of stack)
907      */
908     OperandDesc = WalkState->Operands[WalkState->NumOperands - 1];
909 
910     ObjDesc->Region.Length = (UINT32) OperandDesc->Integer.Value;
911     AcpiUtRemoveReference (OperandDesc);
912 
913     /*
914      * Get the address and save it
915      * (at top of stack - 1)
916      */
917     OperandDesc = WalkState->Operands[WalkState->NumOperands - 2];
918 
919     ObjDesc->Region.Address = (ACPI_PHYSICAL_ADDRESS)
920                                 OperandDesc->Integer.Value;
921     AcpiUtRemoveReference (OperandDesc);
922 
923     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
924         ObjDesc,
925         ACPI_FORMAT_NATIVE_UINT (ObjDesc->Region.Address),
926         ObjDesc->Region.Length));
927 
928     /* Now the address and length are valid for this opregion */
929 
930     ObjDesc->Region.Flags |= AOPOBJ_DATA_VALID;
931 
932     return_ACPI_STATUS (Status);
933 }
934 
935 
936 /*******************************************************************************
937  *
938  * FUNCTION:    AcpiDsEvalTableRegionOperands
939  *
940  * PARAMETERS:  WalkState       - Current walk
941  *              Op              - A valid region Op object
942  *
943  * RETURN:      Status
944  *
945  * DESCRIPTION: Get region address and length
946  *              Called from AcpiDsExecEndOp during DataTableRegion parse tree walk
947  *
948  ******************************************************************************/
949 
950 ACPI_STATUS
951 AcpiDsEvalTableRegionOperands (
952     ACPI_WALK_STATE         *WalkState,
953     ACPI_PARSE_OBJECT       *Op)
954 {
955     ACPI_STATUS             Status;
956     ACPI_OPERAND_OBJECT     *ObjDesc;
957     ACPI_OPERAND_OBJECT     **Operand;
958     ACPI_NAMESPACE_NODE     *Node;
959     ACPI_PARSE_OBJECT       *NextOp;
960     UINT32                  TableIndex;
961     ACPI_TABLE_HEADER       *Table;
962 
963 
964     ACPI_FUNCTION_TRACE_PTR (DsEvalTableRegionOperands, Op);
965 
966 
967     /*
968      * This is where we evaluate the SignatureString and OemIDString
969      * and OemTableIDString of the DataTableRegion declaration
970      */
971     Node =  Op->Common.Node;
972 
973     /* NextOp points to SignatureString op */
974 
975     NextOp = Op->Common.Value.Arg;
976 
977     /*
978      * Evaluate/create the SignatureString and OemIDString
979      * and OemTableIDString operands
980      */
981     Status = AcpiDsCreateOperands (WalkState, NextOp);
982     if (ACPI_FAILURE (Status))
983     {
984         return_ACPI_STATUS (Status);
985     }
986 
987     /*
988      * Resolve the SignatureString and OemIDString
989      * and OemTableIDString operands
990      */
991     Status = AcpiExResolveOperands (Op->Common.AmlOpcode,
992                 ACPI_WALK_OPERANDS, WalkState);
993     if (ACPI_FAILURE (Status))
994     {
995         return_ACPI_STATUS (Status);
996     }
997 
998     Operand = &WalkState->Operands[0];
999 
1000     /* Find the ACPI table */
1001 
1002     Status = AcpiTbFindTable (Operand[0]->String.Pointer,
1003                 Operand[1]->String.Pointer, Operand[2]->String.Pointer,
1004                 &TableIndex);
1005     if (ACPI_FAILURE (Status))
1006     {
1007         return_ACPI_STATUS (Status);
1008     }
1009 
1010     AcpiUtRemoveReference (Operand[0]);
1011     AcpiUtRemoveReference (Operand[1]);
1012     AcpiUtRemoveReference (Operand[2]);
1013 
1014     Status = AcpiGetTableByIndex (TableIndex, &Table);
1015     if (ACPI_FAILURE (Status))
1016     {
1017         return_ACPI_STATUS (Status);
1018     }
1019 
1020     ObjDesc = AcpiNsGetAttachedObject (Node);
1021     if (!ObjDesc)
1022     {
1023         return_ACPI_STATUS (AE_NOT_EXIST);
1024     }
1025 
1026     ObjDesc->Region.Address = (ACPI_PHYSICAL_ADDRESS) ACPI_TO_INTEGER (Table);
1027     ObjDesc->Region.Length = Table->Length;
1028 
1029     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
1030         ObjDesc,
1031         ACPI_FORMAT_NATIVE_UINT (ObjDesc->Region.Address),
1032         ObjDesc->Region.Length));
1033 
1034     /* Now the address and length are valid for this opregion */
1035 
1036     ObjDesc->Region.Flags |= AOPOBJ_DATA_VALID;
1037 
1038     return_ACPI_STATUS (Status);
1039 }
1040 
1041 
1042 /*******************************************************************************
1043  *
1044  * FUNCTION:    AcpiDsEvalDataObjectOperands
1045  *
1046  * PARAMETERS:  WalkState       - Current walk
1047  *              Op              - A valid DataObject Op object
1048  *              ObjDesc         - DataObject
1049  *
1050  * RETURN:      Status
1051  *
1052  * DESCRIPTION: Get the operands and complete the following data object types:
1053  *              Buffer, Package.
1054  *
1055  ******************************************************************************/
1056 
1057 ACPI_STATUS
1058 AcpiDsEvalDataObjectOperands (
1059     ACPI_WALK_STATE         *WalkState,
1060     ACPI_PARSE_OBJECT       *Op,
1061     ACPI_OPERAND_OBJECT     *ObjDesc)
1062 {
1063     ACPI_STATUS             Status;
1064     ACPI_OPERAND_OBJECT     *ArgDesc;
1065     UINT32                  Length;
1066 
1067 
1068     ACPI_FUNCTION_TRACE (DsEvalDataObjectOperands);
1069 
1070 
1071     /* The first operand (for all of these data objects) is the length */
1072 
1073     /*
1074      * Set proper index into operand stack for AcpiDsObjStackPush
1075      * invoked inside AcpiDsCreateOperand.
1076      */
1077     WalkState->OperandIndex = WalkState->NumOperands;
1078 
1079     Status = AcpiDsCreateOperand (WalkState, Op->Common.Value.Arg, 1);
1080     if (ACPI_FAILURE (Status))
1081     {
1082         return_ACPI_STATUS (Status);
1083     }
1084 
1085     Status = AcpiExResolveOperands (WalkState->Opcode,
1086                     &(WalkState->Operands [WalkState->NumOperands -1]),
1087                     WalkState);
1088     if (ACPI_FAILURE (Status))
1089     {
1090         return_ACPI_STATUS (Status);
1091     }
1092 
1093     /* Extract length operand */
1094 
1095     ArgDesc = WalkState->Operands [WalkState->NumOperands - 1];
1096     Length = (UINT32) ArgDesc->Integer.Value;
1097 
1098     /* Cleanup for length operand */
1099 
1100     Status = AcpiDsObjStackPop (1, WalkState);
1101     if (ACPI_FAILURE (Status))
1102     {
1103         return_ACPI_STATUS (Status);
1104     }
1105 
1106     AcpiUtRemoveReference (ArgDesc);
1107 
1108     /*
1109      * Create the actual data object
1110      */
1111     switch (Op->Common.AmlOpcode)
1112     {
1113     case AML_BUFFER_OP:
1114 
1115         Status = AcpiDsBuildInternalBufferObj (WalkState, Op, Length, &ObjDesc);
1116         break;
1117 
1118     case AML_PACKAGE_OP:
1119     case AML_VAR_PACKAGE_OP:
1120 
1121         Status = AcpiDsBuildInternalPackageObj (WalkState, Op, Length, &ObjDesc);
1122         break;
1123 
1124     default:
1125         return_ACPI_STATUS (AE_AML_BAD_OPCODE);
1126     }
1127 
1128     if (ACPI_SUCCESS (Status))
1129     {
1130         /*
1131          * Return the object in the WalkState, unless the parent is a package -
1132          * in this case, the return object will be stored in the parse tree
1133          * for the package.
1134          */
1135         if ((!Op->Common.Parent) ||
1136             ((Op->Common.Parent->Common.AmlOpcode != AML_PACKAGE_OP) &&
1137              (Op->Common.Parent->Common.AmlOpcode != AML_VAR_PACKAGE_OP) &&
1138              (Op->Common.Parent->Common.AmlOpcode != AML_NAME_OP)))
1139         {
1140             WalkState->ResultObj = ObjDesc;
1141         }
1142     }
1143 
1144     return_ACPI_STATUS (Status);
1145 }
1146 
1147 
1148 /*******************************************************************************
1149  *
1150  * FUNCTION:    AcpiDsEvalBankFieldOperands
1151  *
1152  * PARAMETERS:  WalkState       - Current walk
1153  *              Op              - A valid BankField Op object
1154  *
1155  * RETURN:      Status
1156  *
1157  * DESCRIPTION: Get BankField BankValue
1158  *              Called from AcpiDsExecEndOp during BankField parse tree walk
1159  *
1160  ******************************************************************************/
1161 
1162 ACPI_STATUS
1163 AcpiDsEvalBankFieldOperands (
1164     ACPI_WALK_STATE         *WalkState,
1165     ACPI_PARSE_OBJECT       *Op)
1166 {
1167     ACPI_STATUS             Status;
1168     ACPI_OPERAND_OBJECT     *ObjDesc;
1169     ACPI_OPERAND_OBJECT     *OperandDesc;
1170     ACPI_NAMESPACE_NODE     *Node;
1171     ACPI_PARSE_OBJECT       *NextOp;
1172     ACPI_PARSE_OBJECT       *Arg;
1173 
1174 
1175     ACPI_FUNCTION_TRACE_PTR (DsEvalBankFieldOperands, Op);
1176 
1177 
1178     /*
1179      * This is where we evaluate the BankValue field of the
1180      * BankField declaration
1181      */
1182 
1183     /* NextOp points to the op that holds the Region */
1184 
1185     NextOp = Op->Common.Value.Arg;
1186 
1187     /* NextOp points to the op that holds the Bank Register */
1188 
1189     NextOp = NextOp->Common.Next;
1190 
1191     /* NextOp points to the op that holds the Bank Value */
1192 
1193     NextOp = NextOp->Common.Next;
1194 
1195     /*
1196      * Set proper index into operand stack for AcpiDsObjStackPush
1197      * invoked inside AcpiDsCreateOperand.
1198      *
1199      * We use WalkState->Operands[0] to store the evaluated BankValue
1200      */
1201     WalkState->OperandIndex = 0;
1202 
1203     Status = AcpiDsCreateOperand (WalkState, NextOp, 0);
1204     if (ACPI_FAILURE (Status))
1205     {
1206         return_ACPI_STATUS (Status);
1207     }
1208 
1209     Status = AcpiExResolveToValue (&WalkState->Operands[0], WalkState);
1210     if (ACPI_FAILURE (Status))
1211     {
1212         return_ACPI_STATUS (Status);
1213     }
1214 
1215     ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS,
1216         AcpiPsGetOpcodeName (Op->Common.AmlOpcode), 1);
1217     /*
1218      * Get the BankValue operand and save it
1219      * (at Top of stack)
1220      */
1221     OperandDesc = WalkState->Operands[0];
1222 
1223     /* Arg points to the start Bank Field */
1224 
1225     Arg = AcpiPsGetArg (Op, 4);
1226     while (Arg)
1227     {
1228         /* Ignore OFFSET and ACCESSAS terms here */
1229 
1230         if (Arg->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP)
1231         {
1232             Node = Arg->Common.Node;
1233 
1234             ObjDesc = AcpiNsGetAttachedObject (Node);
1235             if (!ObjDesc)
1236             {
1237                 return_ACPI_STATUS (AE_NOT_EXIST);
1238             }
1239 
1240             ObjDesc->BankField.Value = (UINT32) OperandDesc->Integer.Value;
1241         }
1242 
1243         /* Move to next field in the list */
1244 
1245         Arg = Arg->Common.Next;
1246     }
1247 
1248     AcpiUtRemoveReference (OperandDesc);
1249     return_ACPI_STATUS (Status);
1250 }
1251 
1252 
1253 /*******************************************************************************
1254  *
1255  * FUNCTION:    AcpiDsExecBeginControlOp
1256  *
1257  * PARAMETERS:  WalkList        - The list that owns the walk stack
1258  *              Op              - The control Op
1259  *
1260  * RETURN:      Status
1261  *
1262  * DESCRIPTION: Handles all control ops encountered during control method
1263  *              execution.
1264  *
1265  ******************************************************************************/
1266 
1267 ACPI_STATUS
1268 AcpiDsExecBeginControlOp (
1269     ACPI_WALK_STATE         *WalkState,
1270     ACPI_PARSE_OBJECT       *Op)
1271 {
1272     ACPI_STATUS             Status = AE_OK;
1273     ACPI_GENERIC_STATE      *ControlState;
1274 
1275 
1276     ACPI_FUNCTION_NAME (DsExecBeginControlOp);
1277 
1278 
1279     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", Op,
1280         Op->Common.AmlOpcode, WalkState));
1281 
1282     switch (Op->Common.AmlOpcode)
1283     {
1284     case AML_WHILE_OP:
1285 
1286         /*
1287          * If this is an additional iteration of a while loop, continue.
1288          * There is no need to allocate a new control state.
1289          */
1290         if (WalkState->ControlState)
1291         {
1292             if (WalkState->ControlState->Control.AmlPredicateStart ==
1293                 (WalkState->ParserState.Aml - 1))
1294             {
1295                 /* Reset the state to start-of-loop */
1296 
1297                 WalkState->ControlState->Common.State = ACPI_CONTROL_CONDITIONAL_EXECUTING;
1298                 break;
1299             }
1300         }
1301 
1302         /*lint -fallthrough */
1303 
1304     case AML_IF_OP:
1305 
1306         /*
1307          * IF/WHILE: Create a new control state to manage these
1308          * constructs. We need to manage these as a stack, in order
1309          * to handle nesting.
1310          */
1311         ControlState = AcpiUtCreateControlState ();
1312         if (!ControlState)
1313         {
1314             Status = AE_NO_MEMORY;
1315             break;
1316         }
1317         /*
1318          * Save a pointer to the predicate for multiple executions
1319          * of a loop
1320          */
1321         ControlState->Control.AmlPredicateStart = WalkState->ParserState.Aml - 1;
1322         ControlState->Control.PackageEnd = WalkState->ParserState.PkgEnd;
1323         ControlState->Control.Opcode = Op->Common.AmlOpcode;
1324 
1325 
1326         /* Push the control state on this walk's control stack */
1327 
1328         AcpiUtPushGenericState (&WalkState->ControlState, ControlState);
1329         break;
1330 
1331     case AML_ELSE_OP:
1332 
1333         /* Predicate is in the state object */
1334         /* If predicate is true, the IF was executed, ignore ELSE part */
1335 
1336         if (WalkState->LastPredicate)
1337         {
1338             Status = AE_CTRL_TRUE;
1339         }
1340 
1341         break;
1342 
1343     case AML_RETURN_OP:
1344 
1345         break;
1346 
1347     default:
1348         break;
1349     }
1350 
1351     return (Status);
1352 }
1353 
1354 
1355 /*******************************************************************************
1356  *
1357  * FUNCTION:    AcpiDsExecEndControlOp
1358  *
1359  * PARAMETERS:  WalkList        - The list that owns the walk stack
1360  *              Op              - The control Op
1361  *
1362  * RETURN:      Status
1363  *
1364  * DESCRIPTION: Handles all control ops encountered during control method
1365  *              execution.
1366  *
1367  ******************************************************************************/
1368 
1369 ACPI_STATUS
1370 AcpiDsExecEndControlOp (
1371     ACPI_WALK_STATE         *WalkState,
1372     ACPI_PARSE_OBJECT       *Op)
1373 {
1374     ACPI_STATUS             Status = AE_OK;
1375     ACPI_GENERIC_STATE      *ControlState;
1376 
1377 
1378     ACPI_FUNCTION_NAME (DsExecEndControlOp);
1379 
1380 
1381     switch (Op->Common.AmlOpcode)
1382     {
1383     case AML_IF_OP:
1384 
1385         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", Op));
1386 
1387         /*
1388          * Save the result of the predicate in case there is an
1389          * ELSE to come
1390          */
1391         WalkState->LastPredicate =
1392             (BOOLEAN) WalkState->ControlState->Common.Value;
1393 
1394         /*
1395          * Pop the control state that was created at the start
1396          * of the IF and free it
1397          */
1398         ControlState = AcpiUtPopGenericState (&WalkState->ControlState);
1399         AcpiUtDeleteGenericState (ControlState);
1400         break;
1401 
1402 
1403     case AML_ELSE_OP:
1404 
1405         break;
1406 
1407 
1408     case AML_WHILE_OP:
1409 
1410         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", Op));
1411 
1412         ControlState = WalkState->ControlState;
1413         if (ControlState->Common.Value)
1414         {
1415             /* Predicate was true, the body of the loop was just executed */
1416 
1417             /*
1418              * This loop counter mechanism allows the interpreter to escape
1419              * possibly infinite loops. This can occur in poorly written AML
1420              * when the hardware does not respond within a while loop and the
1421              * loop does not implement a timeout.
1422              */
1423             ControlState->Control.LoopCount++;
1424             if (ControlState->Control.LoopCount > ACPI_MAX_LOOP_ITERATIONS)
1425             {
1426                 Status = AE_AML_INFINITE_LOOP;
1427                 break;
1428             }
1429 
1430             /*
1431              * Go back and evaluate the predicate and maybe execute the loop
1432              * another time
1433              */
1434             Status = AE_CTRL_PENDING;
1435             WalkState->AmlLastWhile = ControlState->Control.AmlPredicateStart;
1436             break;
1437         }
1438 
1439         /* Predicate was false, terminate this while loop */
1440 
1441         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
1442             "[WHILE_OP] termination! Op=%p\n",Op));
1443 
1444         /* Pop this control state and free it */
1445 
1446         ControlState = AcpiUtPopGenericState (&WalkState->ControlState);
1447         AcpiUtDeleteGenericState (ControlState);
1448         break;
1449 
1450 
1451     case AML_RETURN_OP:
1452 
1453         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
1454             "[RETURN_OP] Op=%p Arg=%p\n",Op, Op->Common.Value.Arg));
1455 
1456         /*
1457          * One optional operand -- the return value
1458          * It can be either an immediate operand or a result that
1459          * has been bubbled up the tree
1460          */
1461         if (Op->Common.Value.Arg)
1462         {
1463             /* Since we have a real Return(), delete any implicit return */
1464 
1465             AcpiDsClearImplicitReturn (WalkState);
1466 
1467             /* Return statement has an immediate operand */
1468 
1469             Status = AcpiDsCreateOperands (WalkState, Op->Common.Value.Arg);
1470             if (ACPI_FAILURE (Status))
1471             {
1472                 return (Status);
1473             }
1474 
1475             /*
1476              * If value being returned is a Reference (such as
1477              * an arg or local), resolve it now because it may
1478              * cease to exist at the end of the method.
1479              */
1480             Status = AcpiExResolveToValue (&WalkState->Operands [0], WalkState);
1481             if (ACPI_FAILURE (Status))
1482             {
1483                 return (Status);
1484             }
1485 
1486             /*
1487              * Get the return value and save as the last result
1488              * value.  This is the only place where WalkState->ReturnDesc
1489              * is set to anything other than zero!
1490              */
1491             WalkState->ReturnDesc = WalkState->Operands[0];
1492         }
1493         else if (WalkState->ResultCount)
1494         {
1495             /* Since we have a real Return(), delete any implicit return */
1496 
1497             AcpiDsClearImplicitReturn (WalkState);
1498 
1499             /*
1500              * The return value has come from a previous calculation.
1501              *
1502              * If value being returned is a Reference (such as
1503              * an arg or local), resolve it now because it may
1504              * cease to exist at the end of the method.
1505              *
1506              * Allow references created by the Index operator to return unchanged.
1507              */
1508             if ((ACPI_GET_DESCRIPTOR_TYPE (WalkState->Results->Results.ObjDesc[0]) == ACPI_DESC_TYPE_OPERAND) &&
1509                 ((WalkState->Results->Results.ObjDesc [0])->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) &&
1510                 ((WalkState->Results->Results.ObjDesc [0])->Reference.Class != ACPI_REFCLASS_INDEX))
1511             {
1512                 Status = AcpiExResolveToValue (&WalkState->Results->Results.ObjDesc [0], WalkState);
1513                 if (ACPI_FAILURE (Status))
1514                 {
1515                     return (Status);
1516                 }
1517             }
1518 
1519             WalkState->ReturnDesc = WalkState->Results->Results.ObjDesc [0];
1520         }
1521         else
1522         {
1523             /* No return operand */
1524 
1525             if (WalkState->NumOperands)
1526             {
1527                 AcpiUtRemoveReference (WalkState->Operands [0]);
1528             }
1529 
1530             WalkState->Operands [0]     = NULL;
1531             WalkState->NumOperands      = 0;
1532             WalkState->ReturnDesc       = NULL;
1533         }
1534 
1535 
1536         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
1537             "Completed RETURN_OP State=%p, RetVal=%p\n",
1538             WalkState, WalkState->ReturnDesc));
1539 
1540         /* End the control method execution right now */
1541 
1542         Status = AE_CTRL_TERMINATE;
1543         break;
1544 
1545 
1546     case AML_NOOP_OP:
1547 
1548         /* Just do nothing! */
1549         break;
1550 
1551 
1552     case AML_BREAK_POINT_OP:
1553 
1554         /*
1555          * Set the single-step flag. This will cause the debugger (if present)
1556          * to break to the console within the AML debugger at the start of the
1557          * next AML instruction.
1558          */
1559         ACPI_DEBUGGER_EXEC (
1560             AcpiGbl_CmSingleStep = TRUE);
1561         ACPI_DEBUGGER_EXEC (
1562             AcpiOsPrintf ("**break** Executed AML BreakPoint opcode\n"));
1563 
1564         /* Call to the OSL in case OS wants a piece of the action */
1565 
1566         Status = AcpiOsSignal (ACPI_SIGNAL_BREAKPOINT,
1567                     "Executed AML Breakpoint opcode");
1568         break;
1569 
1570 
1571     case AML_BREAK_OP:
1572     case AML_CONTINUE_OP: /* ACPI 2.0 */
1573 
1574 
1575         /* Pop and delete control states until we find a while */
1576 
1577         while (WalkState->ControlState &&
1578                 (WalkState->ControlState->Control.Opcode != AML_WHILE_OP))
1579         {
1580             ControlState = AcpiUtPopGenericState (&WalkState->ControlState);
1581             AcpiUtDeleteGenericState (ControlState);
1582         }
1583 
1584         /* No while found? */
1585 
1586         if (!WalkState->ControlState)
1587         {
1588             return (AE_AML_NO_WHILE);
1589         }
1590 
1591         /* Was: WalkState->AmlLastWhile = WalkState->ControlState->Control.AmlPredicateStart; */
1592 
1593         WalkState->AmlLastWhile = WalkState->ControlState->Control.PackageEnd;
1594 
1595         /* Return status depending on opcode */
1596 
1597         if (Op->Common.AmlOpcode == AML_BREAK_OP)
1598         {
1599             Status = AE_CTRL_BREAK;
1600         }
1601         else
1602         {
1603             Status = AE_CTRL_CONTINUE;
1604         }
1605         break;
1606 
1607 
1608     default:
1609 
1610         ACPI_ERROR ((AE_INFO, "Unknown control opcode=%X Op=%p",
1611             Op->Common.AmlOpcode, Op));
1612 
1613         Status = AE_AML_BAD_OPCODE;
1614         break;
1615     }
1616 
1617     return (Status);
1618 }
1619 
1620