xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/parser/psobject.c (revision 632e56d8e514ba6ac41f582ce580e51a3cd8922e)
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 - 2016, 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 +=
227             AcpiPsGetOpcodeSize (WalkState->Opcode);
228         WalkState->ArgTypes = WalkState->OpInfo->ParseArgs;
229         break;
230     }
231 
232     return_ACPI_STATUS (AE_OK);
233 }
234 
235 
236 /*******************************************************************************
237  *
238  * FUNCTION:    AcpiPsBuildNamedOp
239  *
240  * PARAMETERS:  WalkState           - Current state
241  *              AmlOpStart          - Begin of named Op in AML
242  *              UnnamedOp           - Early Op (not a named Op)
243  *              Op                  - Returned Op
244  *
245  * RETURN:      Status
246  *
247  * DESCRIPTION: Parse a named Op
248  *
249  ******************************************************************************/
250 
251 ACPI_STATUS
252 AcpiPsBuildNamedOp (
253     ACPI_WALK_STATE         *WalkState,
254     UINT8                   *AmlOpStart,
255     ACPI_PARSE_OBJECT       *UnnamedOp,
256     ACPI_PARSE_OBJECT       **Op)
257 {
258     ACPI_STATUS             Status = AE_OK;
259     ACPI_PARSE_OBJECT       *Arg = NULL;
260 
261 
262     ACPI_FUNCTION_TRACE_PTR (PsBuildNamedOp, WalkState);
263 
264 
265     UnnamedOp->Common.Value.Arg = NULL;
266     UnnamedOp->Common.ArgListLength = 0;
267     UnnamedOp->Common.AmlOpcode = WalkState->Opcode;
268 
269     /*
270      * Get and append arguments until we find the node that contains
271      * the name (the type ARGP_NAME).
272      */
273     while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) &&
274           (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME))
275     {
276         Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState),
277             GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
278         if (ACPI_FAILURE (Status))
279         {
280             return_ACPI_STATUS (Status);
281         }
282 
283         AcpiPsAppendArg (UnnamedOp, Arg);
284         INCREMENT_ARG_LIST (WalkState->ArgTypes);
285     }
286 
287     /*
288      * Make sure that we found a NAME and didn't run out of arguments
289      */
290     if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes))
291     {
292         return_ACPI_STATUS (AE_AML_NO_OPERAND);
293     }
294 
295     /* We know that this arg is a name, move to next arg */
296 
297     INCREMENT_ARG_LIST (WalkState->ArgTypes);
298 
299     /*
300      * Find the object. This will either insert the object into
301      * the namespace or simply look it up
302      */
303     WalkState->Op = NULL;
304 
305     Status = WalkState->DescendingCallback (WalkState, Op);
306     if (ACPI_FAILURE (Status))
307     {
308         if (Status != AE_CTRL_TERMINATE)
309         {
310             ACPI_EXCEPTION ((AE_INFO, Status, "During name lookup/catalog"));
311         }
312         return_ACPI_STATUS (Status);
313     }
314 
315     if (!*Op)
316     {
317         return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
318     }
319 
320     Status = AcpiPsNextParseState (WalkState, *Op, Status);
321     if (ACPI_FAILURE (Status))
322     {
323         if (Status == AE_CTRL_PENDING)
324         {
325             Status = AE_CTRL_PARSE_PENDING;
326         }
327         return_ACPI_STATUS (Status);
328     }
329 
330     AcpiPsAppendArg (*Op, UnnamedOp->Common.Value.Arg);
331 
332     if ((*Op)->Common.AmlOpcode == AML_REGION_OP ||
333         (*Op)->Common.AmlOpcode == AML_DATA_REGION_OP)
334     {
335         /*
336          * Defer final parsing of an OperationRegion body, because we don't
337          * have enough info in the first pass to parse it correctly (i.e.,
338          * there may be method calls within the TermArg elements of the body.)
339          *
340          * However, we must continue parsing because the opregion is not a
341          * standalone package -- we don't know where the end is at this point.
342          *
343          * (Length is unknown until parse of the body complete)
344          */
345         (*Op)->Named.Data = AmlOpStart;
346         (*Op)->Named.Length = 0;
347     }
348 
349     return_ACPI_STATUS (AE_OK);
350 }
351 
352 
353 /*******************************************************************************
354  *
355  * FUNCTION:    AcpiPsCreateOp
356  *
357  * PARAMETERS:  WalkState           - Current state
358  *              AmlOpStart          - Op start in AML
359  *              NewOp               - Returned Op
360  *
361  * RETURN:      Status
362  *
363  * DESCRIPTION: Get Op from AML
364  *
365  ******************************************************************************/
366 
367 ACPI_STATUS
368 AcpiPsCreateOp (
369     ACPI_WALK_STATE         *WalkState,
370     UINT8                   *AmlOpStart,
371     ACPI_PARSE_OBJECT       **NewOp)
372 {
373     ACPI_STATUS             Status = AE_OK;
374     ACPI_PARSE_OBJECT       *Op;
375     ACPI_PARSE_OBJECT       *NamedOp = NULL;
376     ACPI_PARSE_OBJECT       *ParentScope;
377     UINT8                   ArgumentCount;
378     const ACPI_OPCODE_INFO  *OpInfo;
379 
380 
381     ACPI_FUNCTION_TRACE_PTR (PsCreateOp, WalkState);
382 
383 
384     Status = AcpiPsGetAmlOpcode (WalkState);
385     if (Status == AE_CTRL_PARSE_CONTINUE)
386     {
387         return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
388     }
389 
390     /* Create Op structure and append to parent's argument list */
391 
392     WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
393     Op = AcpiPsAllocOp (WalkState->Opcode, AmlOpStart);
394     if (!Op)
395     {
396         return_ACPI_STATUS (AE_NO_MEMORY);
397     }
398 
399     if (WalkState->OpInfo->Flags & AML_NAMED)
400     {
401         Status = AcpiPsBuildNamedOp (WalkState, AmlOpStart, Op, &NamedOp);
402         AcpiPsFreeOp (Op);
403         if (ACPI_FAILURE (Status))
404         {
405             return_ACPI_STATUS (Status);
406         }
407 
408         *NewOp = NamedOp;
409         return_ACPI_STATUS (AE_OK);
410     }
411 
412     /* Not a named opcode, just allocate Op and append to parent */
413 
414     if (WalkState->OpInfo->Flags & AML_CREATE)
415     {
416         /*
417          * Backup to beginning of CreateXXXfield declaration
418          * BodyLength is unknown until we parse the body
419          */
420         Op->Named.Data = AmlOpStart;
421         Op->Named.Length = 0;
422     }
423 
424     if (WalkState->Opcode == AML_BANK_FIELD_OP)
425     {
426         /*
427          * Backup to beginning of BankField declaration
428          * BodyLength is unknown until we parse the body
429          */
430         Op->Named.Data = AmlOpStart;
431         Op->Named.Length = 0;
432     }
433 
434     ParentScope = AcpiPsGetParentScope (&(WalkState->ParserState));
435     AcpiPsAppendArg (ParentScope, Op);
436 
437     if (ParentScope)
438     {
439         OpInfo = AcpiPsGetOpcodeInfo (ParentScope->Common.AmlOpcode);
440         if (OpInfo->Flags & AML_HAS_TARGET)
441         {
442             ArgumentCount = AcpiPsGetArgumentCount (OpInfo->Type);
443             if (ParentScope->Common.ArgListLength > ArgumentCount)
444             {
445                 Op->Common.Flags |= ACPI_PARSEOP_TARGET;
446             }
447         }
448         else if (ParentScope->Common.AmlOpcode == AML_INCREMENT_OP)
449         {
450             Op->Common.Flags |= ACPI_PARSEOP_TARGET;
451         }
452     }
453 
454     if (WalkState->DescendingCallback != NULL)
455     {
456         /*
457          * Find the object. This will either insert the object into
458          * the namespace or simply look it up
459          */
460         WalkState->Op = *NewOp = Op;
461 
462         Status = WalkState->DescendingCallback (WalkState, &Op);
463         Status = AcpiPsNextParseState (WalkState, Op, Status);
464         if (Status == AE_CTRL_PENDING)
465         {
466             Status = AE_CTRL_PARSE_PENDING;
467         }
468     }
469 
470     return_ACPI_STATUS (Status);
471 }
472 
473 
474 /*******************************************************************************
475  *
476  * FUNCTION:    AcpiPsCompleteOp
477  *
478  * PARAMETERS:  WalkState           - Current state
479  *              Op                  - Returned Op
480  *              Status              - Parse status before complete Op
481  *
482  * RETURN:      Status
483  *
484  * DESCRIPTION: Complete Op
485  *
486  ******************************************************************************/
487 
488 ACPI_STATUS
489 AcpiPsCompleteOp (
490     ACPI_WALK_STATE         *WalkState,
491     ACPI_PARSE_OBJECT       **Op,
492     ACPI_STATUS             Status)
493 {
494     ACPI_STATUS             Status2;
495 
496 
497     ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState);
498 
499 
500     /*
501      * Finished one argument of the containing scope
502      */
503     WalkState->ParserState.Scope->ParseScope.ArgCount--;
504 
505     /* Close this Op (will result in parse subtree deletion) */
506 
507     Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
508     if (ACPI_FAILURE (Status2))
509     {
510         return_ACPI_STATUS (Status2);
511     }
512 
513     *Op = NULL;
514 
515     switch (Status)
516     {
517     case AE_OK:
518 
519         break;
520 
521     case AE_CTRL_TRANSFER:
522 
523         /* We are about to transfer to a called method */
524 
525         WalkState->PrevOp = NULL;
526         WalkState->PrevArgTypes = WalkState->ArgTypes;
527         return_ACPI_STATUS (Status);
528 
529     case AE_CTRL_END:
530 
531         AcpiPsPopScope (&(WalkState->ParserState), Op,
532             &WalkState->ArgTypes, &WalkState->ArgCount);
533 
534         if (*Op)
535         {
536             WalkState->Op = *Op;
537             WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
538             WalkState->Opcode = (*Op)->Common.AmlOpcode;
539 
540             Status = WalkState->AscendingCallback (WalkState);
541             Status = AcpiPsNextParseState (WalkState, *Op, Status);
542 
543             Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
544             if (ACPI_FAILURE (Status2))
545             {
546                 return_ACPI_STATUS (Status2);
547             }
548         }
549 
550         Status = AE_OK;
551         break;
552 
553     case AE_CTRL_BREAK:
554     case AE_CTRL_CONTINUE:
555 
556         /* Pop off scopes until we find the While */
557 
558         while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP))
559         {
560             AcpiPsPopScope (&(WalkState->ParserState), Op,
561                 &WalkState->ArgTypes, &WalkState->ArgCount);
562         }
563 
564         /* Close this iteration of the While loop */
565 
566         WalkState->Op = *Op;
567         WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
568         WalkState->Opcode = (*Op)->Common.AmlOpcode;
569 
570         Status = WalkState->AscendingCallback (WalkState);
571         Status = AcpiPsNextParseState (WalkState, *Op, Status);
572 
573         Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
574         if (ACPI_FAILURE (Status2))
575         {
576             return_ACPI_STATUS (Status2);
577         }
578 
579         Status = AE_OK;
580         break;
581 
582     case AE_CTRL_TERMINATE:
583 
584         /* Clean up */
585         do
586         {
587             if (*Op)
588             {
589                 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
590                 if (ACPI_FAILURE (Status2))
591                 {
592                     return_ACPI_STATUS (Status2);
593                 }
594 
595                 AcpiUtDeleteGenericState (
596                     AcpiUtPopGenericState (&WalkState->ControlState));
597             }
598 
599             AcpiPsPopScope (&(WalkState->ParserState), Op,
600                 &WalkState->ArgTypes, &WalkState->ArgCount);
601 
602         } while (*Op);
603 
604         return_ACPI_STATUS (AE_OK);
605 
606     default:  /* All other non-AE_OK status */
607 
608         do
609         {
610             if (*Op)
611             {
612                 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
613                 if (ACPI_FAILURE (Status2))
614                 {
615                     return_ACPI_STATUS (Status2);
616                 }
617             }
618 
619             AcpiPsPopScope (&(WalkState->ParserState), Op,
620                 &WalkState->ArgTypes, &WalkState->ArgCount);
621 
622         } while (*Op);
623 
624 
625 #if 0
626         /*
627          * TBD: Cleanup parse ops on error
628          */
629         if (*Op == NULL)
630         {
631             AcpiPsPopScope (ParserState, Op,
632                 &WalkState->ArgTypes, &WalkState->ArgCount);
633         }
634 #endif
635         WalkState->PrevOp = NULL;
636         WalkState->PrevArgTypes = WalkState->ArgTypes;
637         return_ACPI_STATUS (Status);
638     }
639 
640     /* This scope complete? */
641 
642     if (AcpiPsHasCompletedScope (&(WalkState->ParserState)))
643     {
644         AcpiPsPopScope (&(WalkState->ParserState), Op,
645             &WalkState->ArgTypes, &WalkState->ArgCount);
646         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op));
647     }
648     else
649     {
650         *Op = NULL;
651     }
652 
653     return_ACPI_STATUS (AE_OK);
654 }
655 
656 
657 /*******************************************************************************
658  *
659  * FUNCTION:    AcpiPsCompleteFinalOp
660  *
661  * PARAMETERS:  WalkState           - Current state
662  *              Op                  - Current Op
663  *              Status              - Current parse status before complete last
664  *                                    Op
665  *
666  * RETURN:      Status
667  *
668  * DESCRIPTION: Complete last Op.
669  *
670  ******************************************************************************/
671 
672 ACPI_STATUS
673 AcpiPsCompleteFinalOp (
674     ACPI_WALK_STATE         *WalkState,
675     ACPI_PARSE_OBJECT       *Op,
676     ACPI_STATUS             Status)
677 {
678     ACPI_STATUS             Status2;
679 
680 
681     ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState);
682 
683 
684     /*
685      * Complete the last Op (if not completed), and clear the scope stack.
686      * It is easily possible to end an AML "package" with an unbounded number
687      * of open scopes (such as when several ASL blocks are closed with
688      * sequential closing braces). We want to terminate each one cleanly.
689      */
690     ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op));
691     do
692     {
693         if (Op)
694         {
695             if (WalkState->AscendingCallback != NULL)
696             {
697                 WalkState->Op = Op;
698                 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
699                 WalkState->Opcode = Op->Common.AmlOpcode;
700 
701                 Status = WalkState->AscendingCallback (WalkState);
702                 Status = AcpiPsNextParseState (WalkState, Op, Status);
703                 if (Status == AE_CTRL_PENDING)
704                 {
705                     Status = AcpiPsCompleteOp (WalkState, &Op, AE_OK);
706                     if (ACPI_FAILURE (Status))
707                     {
708                         return_ACPI_STATUS (Status);
709                     }
710                 }
711 
712                 if (Status == AE_CTRL_TERMINATE)
713                 {
714                     Status = AE_OK;
715 
716                     /* Clean up */
717                     do
718                     {
719                         if (Op)
720                         {
721                             Status2 = AcpiPsCompleteThisOp (WalkState, Op);
722                             if (ACPI_FAILURE (Status2))
723                             {
724                                 return_ACPI_STATUS (Status2);
725                             }
726                         }
727 
728                         AcpiPsPopScope (&(WalkState->ParserState), &Op,
729                             &WalkState->ArgTypes, &WalkState->ArgCount);
730 
731                     } while (Op);
732 
733                     return_ACPI_STATUS (Status);
734                 }
735 
736                 else if (ACPI_FAILURE (Status))
737                 {
738                     /* First error is most important */
739 
740                     (void) AcpiPsCompleteThisOp (WalkState, Op);
741                     return_ACPI_STATUS (Status);
742                 }
743             }
744 
745             Status2 = AcpiPsCompleteThisOp (WalkState, Op);
746             if (ACPI_FAILURE (Status2))
747             {
748                 return_ACPI_STATUS (Status2);
749             }
750         }
751 
752         AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes,
753             &WalkState->ArgCount);
754 
755     } while (Op);
756 
757     return_ACPI_STATUS (Status);
758 }
759