xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/parser/psobject.c (revision d0ac609964842f8cdb6d54b3c539c6c15293e172)
1 /******************************************************************************
2  *
3  * Module Name: psobject - Support for parse objects
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2015, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************/
115 
116 #include "acpi.h"
117 #include "accommon.h"
118 #include "acparser.h"
119 #include "amlcode.h"
120 
121 #define _COMPONENT          ACPI_PARSER
122         ACPI_MODULE_NAME    ("psobject")
123 
124 
125 /* Local prototypes */
126 
127 static ACPI_STATUS
128 AcpiPsGetAmlOpcode (
129     ACPI_WALK_STATE         *WalkState);
130 
131 
132 /*******************************************************************************
133  *
134  * FUNCTION:    AcpiPsGetAmlOpcode
135  *
136  * PARAMETERS:  WalkState           - Current state
137  *
138  * RETURN:      Status
139  *
140  * DESCRIPTION: Extract the next AML opcode from the input stream.
141  *
142  ******************************************************************************/
143 
144 static ACPI_STATUS
145 AcpiPsGetAmlOpcode (
146     ACPI_WALK_STATE         *WalkState)
147 {
148     UINT32                  AmlOffset;
149 
150 
151     ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState);
152 
153 
154     WalkState->Aml = WalkState->ParserState.Aml;
155     WalkState->Opcode = AcpiPsPeekOpcode (&(WalkState->ParserState));
156 
157     /*
158      * First cut to determine what we have found:
159      * 1) A valid AML opcode
160      * 2) A name string
161      * 3) An unknown/invalid opcode
162      */
163     WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
164 
165     switch (WalkState->OpInfo->Class)
166     {
167     case AML_CLASS_ASCII:
168     case AML_CLASS_PREFIX:
169         /*
170          * Starts with a valid prefix or ASCII char, this is a name
171          * string. Convert the bare name string to a namepath.
172          */
173         WalkState->Opcode = AML_INT_NAMEPATH_OP;
174         WalkState->ArgTypes = ARGP_NAMESTRING;
175         break;
176 
177     case AML_CLASS_UNKNOWN:
178 
179         /* The opcode is unrecognized. Complain and skip unknown opcodes */
180 
181         if (WalkState->PassNumber == 2)
182         {
183             AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->Aml,
184                             WalkState->ParserState.AmlStart);
185 
186             ACPI_ERROR ((AE_INFO,
187                 "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring",
188                 WalkState->Opcode,
189                 (UINT32) (AmlOffset + sizeof (ACPI_TABLE_HEADER))));
190 
191             ACPI_DUMP_BUFFER ((WalkState->ParserState.Aml - 16), 48);
192 
193 #ifdef ACPI_ASL_COMPILER
194             /*
195              * This is executed for the disassembler only. Output goes
196              * to the disassembled ASL output file.
197              */
198             AcpiOsPrintf (
199                 "/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n",
200                 WalkState->Opcode,
201                 (UINT32) (AmlOffset + sizeof (ACPI_TABLE_HEADER)));
202 
203             /* Dump the context surrounding the invalid opcode */
204 
205             AcpiUtDumpBuffer (((UINT8 *) WalkState->ParserState.Aml - 16),
206                 48, DB_BYTE_DISPLAY,
207                 (AmlOffset + sizeof (ACPI_TABLE_HEADER) - 16));
208             AcpiOsPrintf (" */\n");
209 #endif
210         }
211 
212         /* Increment past one-byte or two-byte opcode */
213 
214         WalkState->ParserState.Aml++;
215         if (WalkState->Opcode > 0xFF) /* Can only happen if first byte is 0x5B */
216         {
217             WalkState->ParserState.Aml++;
218         }
219 
220         return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
221 
222     default:
223 
224         /* Found opcode info, this is a normal opcode */
225 
226         WalkState->ParserState.Aml += AcpiPsGetOpcodeSize (WalkState->Opcode);
227         WalkState->ArgTypes = WalkState->OpInfo->ParseArgs;
228         break;
229     }
230 
231     return_ACPI_STATUS (AE_OK);
232 }
233 
234 
235 /*******************************************************************************
236  *
237  * FUNCTION:    AcpiPsBuildNamedOp
238  *
239  * PARAMETERS:  WalkState           - Current state
240  *              AmlOpStart          - Begin of named Op in AML
241  *              UnnamedOp           - Early Op (not a named Op)
242  *              Op                  - Returned Op
243  *
244  * RETURN:      Status
245  *
246  * DESCRIPTION: Parse a named Op
247  *
248  ******************************************************************************/
249 
250 ACPI_STATUS
251 AcpiPsBuildNamedOp (
252     ACPI_WALK_STATE         *WalkState,
253     UINT8                   *AmlOpStart,
254     ACPI_PARSE_OBJECT       *UnnamedOp,
255     ACPI_PARSE_OBJECT       **Op)
256 {
257     ACPI_STATUS             Status = AE_OK;
258     ACPI_PARSE_OBJECT       *Arg = NULL;
259 
260 
261     ACPI_FUNCTION_TRACE_PTR (PsBuildNamedOp, WalkState);
262 
263 
264     UnnamedOp->Common.Value.Arg = NULL;
265     UnnamedOp->Common.ArgListLength = 0;
266     UnnamedOp->Common.AmlOpcode = WalkState->Opcode;
267 
268     /*
269      * Get and append arguments until we find the node that contains
270      * the name (the type ARGP_NAME).
271      */
272     while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) &&
273           (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME))
274     {
275         Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState),
276                     GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
277         if (ACPI_FAILURE (Status))
278         {
279             return_ACPI_STATUS (Status);
280         }
281 
282         AcpiPsAppendArg (UnnamedOp, Arg);
283         INCREMENT_ARG_LIST (WalkState->ArgTypes);
284     }
285 
286     /*
287      * Make sure that we found a NAME and didn't run out of arguments
288      */
289     if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes))
290     {
291         return_ACPI_STATUS (AE_AML_NO_OPERAND);
292     }
293 
294     /* We know that this arg is a name, move to next arg */
295 
296     INCREMENT_ARG_LIST (WalkState->ArgTypes);
297 
298     /*
299      * Find the object. This will either insert the object into
300      * the namespace or simply look it up
301      */
302     WalkState->Op = NULL;
303 
304     Status = WalkState->DescendingCallback (WalkState, Op);
305     if (ACPI_FAILURE (Status))
306     {
307         if (Status != AE_CTRL_TERMINATE)
308         {
309             ACPI_EXCEPTION ((AE_INFO, Status, "During name lookup/catalog"));
310         }
311         return_ACPI_STATUS (Status);
312     }
313 
314     if (!*Op)
315     {
316         return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
317     }
318 
319     Status = AcpiPsNextParseState (WalkState, *Op, Status);
320     if (ACPI_FAILURE (Status))
321     {
322         if (Status == AE_CTRL_PENDING)
323         {
324             Status = AE_CTRL_PARSE_PENDING;
325         }
326         return_ACPI_STATUS (Status);
327     }
328 
329     AcpiPsAppendArg (*Op, UnnamedOp->Common.Value.Arg);
330 
331     if ((*Op)->Common.AmlOpcode == AML_REGION_OP ||
332         (*Op)->Common.AmlOpcode == AML_DATA_REGION_OP)
333     {
334         /*
335          * Defer final parsing of an OperationRegion body, because we don't
336          * have enough info in the first pass to parse it correctly (i.e.,
337          * there may be method calls within the TermArg elements of the body.)
338          *
339          * However, we must continue parsing because the opregion is not a
340          * standalone package -- we don't know where the end is at this point.
341          *
342          * (Length is unknown until parse of the body complete)
343          */
344         (*Op)->Named.Data = AmlOpStart;
345         (*Op)->Named.Length = 0;
346     }
347 
348     return_ACPI_STATUS (AE_OK);
349 }
350 
351 
352 /*******************************************************************************
353  *
354  * FUNCTION:    AcpiPsCreateOp
355  *
356  * PARAMETERS:  WalkState           - Current state
357  *              AmlOpStart          - Op start in AML
358  *              NewOp               - Returned Op
359  *
360  * RETURN:      Status
361  *
362  * DESCRIPTION: Get Op from AML
363  *
364  ******************************************************************************/
365 
366 ACPI_STATUS
367 AcpiPsCreateOp (
368     ACPI_WALK_STATE         *WalkState,
369     UINT8                   *AmlOpStart,
370     ACPI_PARSE_OBJECT       **NewOp)
371 {
372     ACPI_STATUS             Status = AE_OK;
373     ACPI_PARSE_OBJECT       *Op;
374     ACPI_PARSE_OBJECT       *NamedOp = NULL;
375     ACPI_PARSE_OBJECT       *ParentScope;
376     UINT8                   ArgumentCount;
377     const ACPI_OPCODE_INFO  *OpInfo;
378 
379 
380     ACPI_FUNCTION_TRACE_PTR (PsCreateOp, WalkState);
381 
382 
383     Status = AcpiPsGetAmlOpcode (WalkState);
384     if (Status == AE_CTRL_PARSE_CONTINUE)
385     {
386         return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
387     }
388 
389     /* Create Op structure and append to parent's argument list */
390 
391     WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
392     Op = AcpiPsAllocOp (WalkState->Opcode, AmlOpStart);
393     if (!Op)
394     {
395         return_ACPI_STATUS (AE_NO_MEMORY);
396     }
397 
398     if (WalkState->OpInfo->Flags & AML_NAMED)
399     {
400         Status = AcpiPsBuildNamedOp (WalkState, AmlOpStart, Op, &NamedOp);
401         AcpiPsFreeOp (Op);
402         if (ACPI_FAILURE (Status))
403         {
404             return_ACPI_STATUS (Status);
405         }
406 
407         *NewOp = NamedOp;
408         return_ACPI_STATUS (AE_OK);
409     }
410 
411     /* Not a named opcode, just allocate Op and append to parent */
412 
413     if (WalkState->OpInfo->Flags & AML_CREATE)
414     {
415         /*
416          * Backup to beginning of CreateXXXfield declaration
417          * BodyLength is unknown until we parse the body
418          */
419         Op->Named.Data = AmlOpStart;
420         Op->Named.Length = 0;
421     }
422 
423     if (WalkState->Opcode == AML_BANK_FIELD_OP)
424     {
425         /*
426          * Backup to beginning of BankField declaration
427          * BodyLength is unknown until we parse the body
428          */
429         Op->Named.Data = AmlOpStart;
430         Op->Named.Length = 0;
431     }
432 
433     ParentScope = AcpiPsGetParentScope (&(WalkState->ParserState));
434     AcpiPsAppendArg (ParentScope, Op);
435 
436     if (ParentScope)
437     {
438         OpInfo = AcpiPsGetOpcodeInfo (ParentScope->Common.AmlOpcode);
439         if (OpInfo->Flags & AML_HAS_TARGET)
440         {
441             ArgumentCount = AcpiPsGetArgumentCount (OpInfo->Type);
442             if (ParentScope->Common.ArgListLength > ArgumentCount)
443             {
444                 Op->Common.Flags |= ACPI_PARSEOP_TARGET;
445             }
446         }
447         else if (ParentScope->Common.AmlOpcode == AML_INCREMENT_OP)
448         {
449             Op->Common.Flags |= ACPI_PARSEOP_TARGET;
450         }
451     }
452 
453     if (WalkState->DescendingCallback != NULL)
454     {
455         /*
456          * Find the object. This will either insert the object into
457          * the namespace or simply look it up
458          */
459         WalkState->Op = *NewOp = Op;
460 
461         Status = WalkState->DescendingCallback (WalkState, &Op);
462         Status = AcpiPsNextParseState (WalkState, Op, Status);
463         if (Status == AE_CTRL_PENDING)
464         {
465             Status = AE_CTRL_PARSE_PENDING;
466         }
467     }
468 
469     return_ACPI_STATUS (Status);
470 }
471 
472 
473 /*******************************************************************************
474  *
475  * FUNCTION:    AcpiPsCompleteOp
476  *
477  * PARAMETERS:  WalkState           - Current state
478  *              Op                  - Returned Op
479  *              Status              - Parse status before complete Op
480  *
481  * RETURN:      Status
482  *
483  * DESCRIPTION: Complete Op
484  *
485  ******************************************************************************/
486 
487 ACPI_STATUS
488 AcpiPsCompleteOp (
489     ACPI_WALK_STATE         *WalkState,
490     ACPI_PARSE_OBJECT       **Op,
491     ACPI_STATUS             Status)
492 {
493     ACPI_STATUS             Status2;
494 
495 
496     ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState);
497 
498 
499     /*
500      * Finished one argument of the containing scope
501      */
502     WalkState->ParserState.Scope->ParseScope.ArgCount--;
503 
504     /* Close this Op (will result in parse subtree deletion) */
505 
506     Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
507     if (ACPI_FAILURE (Status2))
508     {
509         return_ACPI_STATUS (Status2);
510     }
511 
512     *Op = NULL;
513 
514     switch (Status)
515     {
516     case AE_OK:
517 
518         break;
519 
520     case AE_CTRL_TRANSFER:
521 
522         /* We are about to transfer to a called method */
523 
524         WalkState->PrevOp = NULL;
525         WalkState->PrevArgTypes = WalkState->ArgTypes;
526         return_ACPI_STATUS (Status);
527 
528     case AE_CTRL_END:
529 
530         AcpiPsPopScope (&(WalkState->ParserState), Op,
531             &WalkState->ArgTypes, &WalkState->ArgCount);
532 
533         if (*Op)
534         {
535             WalkState->Op = *Op;
536             WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
537             WalkState->Opcode = (*Op)->Common.AmlOpcode;
538 
539             Status = WalkState->AscendingCallback (WalkState);
540             Status = AcpiPsNextParseState (WalkState, *Op, Status);
541 
542             Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
543             if (ACPI_FAILURE (Status2))
544             {
545                 return_ACPI_STATUS (Status2);
546             }
547         }
548 
549         Status = AE_OK;
550         break;
551 
552     case AE_CTRL_BREAK:
553     case AE_CTRL_CONTINUE:
554 
555         /* Pop off scopes until we find the While */
556 
557         while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP))
558         {
559             AcpiPsPopScope (&(WalkState->ParserState), Op,
560                 &WalkState->ArgTypes, &WalkState->ArgCount);
561         }
562 
563         /* Close this iteration of the While loop */
564 
565         WalkState->Op = *Op;
566         WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
567         WalkState->Opcode = (*Op)->Common.AmlOpcode;
568 
569         Status = WalkState->AscendingCallback (WalkState);
570         Status = AcpiPsNextParseState (WalkState, *Op, Status);
571 
572         Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
573         if (ACPI_FAILURE (Status2))
574         {
575             return_ACPI_STATUS (Status2);
576         }
577 
578         Status = AE_OK;
579         break;
580 
581     case AE_CTRL_TERMINATE:
582 
583         /* Clean up */
584         do
585         {
586             if (*Op)
587             {
588                 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
589                 if (ACPI_FAILURE (Status2))
590                 {
591                     return_ACPI_STATUS (Status2);
592                 }
593 
594                 AcpiUtDeleteGenericState (
595                     AcpiUtPopGenericState (&WalkState->ControlState));
596             }
597 
598             AcpiPsPopScope (&(WalkState->ParserState), Op,
599                 &WalkState->ArgTypes, &WalkState->ArgCount);
600 
601         } while (*Op);
602 
603         return_ACPI_STATUS (AE_OK);
604 
605     default:  /* All other non-AE_OK status */
606 
607         do
608         {
609             if (*Op)
610             {
611                 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
612                 if (ACPI_FAILURE (Status2))
613                 {
614                     return_ACPI_STATUS (Status2);
615                 }
616             }
617 
618             AcpiPsPopScope (&(WalkState->ParserState), Op,
619                 &WalkState->ArgTypes, &WalkState->ArgCount);
620 
621         } while (*Op);
622 
623 
624 #if 0
625         /*
626          * TBD: Cleanup parse ops on error
627          */
628         if (*Op == NULL)
629         {
630             AcpiPsPopScope (ParserState, Op,
631                 &WalkState->ArgTypes, &WalkState->ArgCount);
632         }
633 #endif
634         WalkState->PrevOp = NULL;
635         WalkState->PrevArgTypes = WalkState->ArgTypes;
636         return_ACPI_STATUS (Status);
637     }
638 
639     /* This scope complete? */
640 
641     if (AcpiPsHasCompletedScope (&(WalkState->ParserState)))
642     {
643         AcpiPsPopScope (&(WalkState->ParserState), Op,
644             &WalkState->ArgTypes, &WalkState->ArgCount);
645         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op));
646     }
647     else
648     {
649         *Op = NULL;
650     }
651 
652     return_ACPI_STATUS (AE_OK);
653 }
654 
655 
656 /*******************************************************************************
657  *
658  * FUNCTION:    AcpiPsCompleteFinalOp
659  *
660  * PARAMETERS:  WalkState           - Current state
661  *              Op                  - Current Op
662  *              Status              - Current parse status before complete last
663  *                                    Op
664  *
665  * RETURN:      Status
666  *
667  * DESCRIPTION: Complete last Op.
668  *
669  ******************************************************************************/
670 
671 ACPI_STATUS
672 AcpiPsCompleteFinalOp (
673     ACPI_WALK_STATE         *WalkState,
674     ACPI_PARSE_OBJECT       *Op,
675     ACPI_STATUS             Status)
676 {
677     ACPI_STATUS             Status2;
678 
679 
680     ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState);
681 
682 
683     /*
684      * Complete the last Op (if not completed), and clear the scope stack.
685      * It is easily possible to end an AML "package" with an unbounded number
686      * of open scopes (such as when several ASL blocks are closed with
687      * sequential closing braces). We want to terminate each one cleanly.
688      */
689     ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op));
690     do
691     {
692         if (Op)
693         {
694             if (WalkState->AscendingCallback != NULL)
695             {
696                 WalkState->Op = Op;
697                 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
698                 WalkState->Opcode = Op->Common.AmlOpcode;
699 
700                 Status = WalkState->AscendingCallback (WalkState);
701                 Status = AcpiPsNextParseState (WalkState, Op, Status);
702                 if (Status == AE_CTRL_PENDING)
703                 {
704                     Status = AcpiPsCompleteOp (WalkState, &Op, AE_OK);
705                     if (ACPI_FAILURE (Status))
706                     {
707                         return_ACPI_STATUS (Status);
708                     }
709                 }
710 
711                 if (Status == AE_CTRL_TERMINATE)
712                 {
713                     Status = AE_OK;
714 
715                     /* Clean up */
716                     do
717                     {
718                         if (Op)
719                         {
720                             Status2 = AcpiPsCompleteThisOp (WalkState, Op);
721                             if (ACPI_FAILURE (Status2))
722                             {
723                                 return_ACPI_STATUS (Status2);
724                             }
725                         }
726 
727                         AcpiPsPopScope (&(WalkState->ParserState), &Op,
728                             &WalkState->ArgTypes, &WalkState->ArgCount);
729 
730                     } while (Op);
731 
732                     return_ACPI_STATUS (Status);
733                 }
734 
735                 else if (ACPI_FAILURE (Status))
736                 {
737                     /* First error is most important */
738 
739                     (void) AcpiPsCompleteThisOp (WalkState, Op);
740                     return_ACPI_STATUS (Status);
741                 }
742             }
743 
744             Status2 = AcpiPsCompleteThisOp (WalkState, Op);
745             if (ACPI_FAILURE (Status2))
746             {
747                 return_ACPI_STATUS (Status2);
748             }
749         }
750 
751         AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes,
752             &WalkState->ArgCount);
753 
754     } while (Op);
755 
756     return_ACPI_STATUS (Status);
757 }
758