psobject.c revision 281075
1/******************************************************************************
2 *
3 * Module Name: psobject - Support for parse objects
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2015, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <contrib/dev/acpica/include/acpi.h>
45#include <contrib/dev/acpica/include/accommon.h>
46#include <contrib/dev/acpica/include/acparser.h>
47#include <contrib/dev/acpica/include/amlcode.h>
48
49#define _COMPONENT          ACPI_PARSER
50        ACPI_MODULE_NAME    ("psobject")
51
52
53/* Local prototypes */
54
55static ACPI_STATUS
56AcpiPsGetAmlOpcode (
57    ACPI_WALK_STATE         *WalkState);
58
59
60/*******************************************************************************
61 *
62 * FUNCTION:    AcpiPsGetAmlOpcode
63 *
64 * PARAMETERS:  WalkState           - Current state
65 *
66 * RETURN:      Status
67 *
68 * DESCRIPTION: Extract the next AML opcode from the input stream.
69 *
70 ******************************************************************************/
71
72static ACPI_STATUS
73AcpiPsGetAmlOpcode (
74    ACPI_WALK_STATE         *WalkState)
75{
76
77    ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState);
78
79
80    WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml,
81                                WalkState->ParserState.AmlStart);
82    WalkState->Opcode = AcpiPsPeekOpcode (&(WalkState->ParserState));
83
84    /*
85     * First cut to determine what we have found:
86     * 1) A valid AML opcode
87     * 2) A name string
88     * 3) An unknown/invalid opcode
89     */
90    WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
91
92    switch (WalkState->OpInfo->Class)
93    {
94    case AML_CLASS_ASCII:
95    case AML_CLASS_PREFIX:
96        /*
97         * Starts with a valid prefix or ASCII char, this is a name
98         * string. Convert the bare name string to a namepath.
99         */
100        WalkState->Opcode = AML_INT_NAMEPATH_OP;
101        WalkState->ArgTypes = ARGP_NAMESTRING;
102        break;
103
104    case AML_CLASS_UNKNOWN:
105
106        /* The opcode is unrecognized. Complain and skip unknown opcodes */
107
108        if (WalkState->PassNumber == 2)
109        {
110            ACPI_ERROR ((AE_INFO,
111                "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring",
112                WalkState->Opcode,
113                (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER))));
114
115            ACPI_DUMP_BUFFER ((WalkState->ParserState.Aml - 16), 48);
116
117#ifdef ACPI_ASL_COMPILER
118            /*
119             * This is executed for the disassembler only. Output goes
120             * to the disassembled ASL output file.
121             */
122            AcpiOsPrintf (
123                "/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n",
124                WalkState->Opcode,
125                (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER)));
126
127            /* Dump the context surrounding the invalid opcode */
128
129            AcpiUtDumpBuffer (((UINT8 *) WalkState->ParserState.Aml - 16),
130                48, DB_BYTE_DISPLAY,
131                (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER) - 16));
132            AcpiOsPrintf (" */\n");
133#endif
134        }
135
136        /* Increment past one-byte or two-byte opcode */
137
138        WalkState->ParserState.Aml++;
139        if (WalkState->Opcode > 0xFF) /* Can only happen if first byte is 0x5B */
140        {
141            WalkState->ParserState.Aml++;
142        }
143
144        return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
145
146    default:
147
148        /* Found opcode info, this is a normal opcode */
149
150        WalkState->ParserState.Aml += AcpiPsGetOpcodeSize (WalkState->Opcode);
151        WalkState->ArgTypes = WalkState->OpInfo->ParseArgs;
152        break;
153    }
154
155    return_ACPI_STATUS (AE_OK);
156}
157
158
159/*******************************************************************************
160 *
161 * FUNCTION:    AcpiPsBuildNamedOp
162 *
163 * PARAMETERS:  WalkState           - Current state
164 *              AmlOpStart          - Begin of named Op in AML
165 *              UnnamedOp           - Early Op (not a named Op)
166 *              Op                  - Returned Op
167 *
168 * RETURN:      Status
169 *
170 * DESCRIPTION: Parse a named Op
171 *
172 ******************************************************************************/
173
174ACPI_STATUS
175AcpiPsBuildNamedOp (
176    ACPI_WALK_STATE         *WalkState,
177    UINT8                   *AmlOpStart,
178    ACPI_PARSE_OBJECT       *UnnamedOp,
179    ACPI_PARSE_OBJECT       **Op)
180{
181    ACPI_STATUS             Status = AE_OK;
182    ACPI_PARSE_OBJECT       *Arg = NULL;
183
184
185    ACPI_FUNCTION_TRACE_PTR (PsBuildNamedOp, WalkState);
186
187
188    UnnamedOp->Common.Value.Arg = NULL;
189    UnnamedOp->Common.ArgListLength = 0;
190    UnnamedOp->Common.AmlOpcode = WalkState->Opcode;
191
192    /*
193     * Get and append arguments until we find the node that contains
194     * the name (the type ARGP_NAME).
195     */
196    while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) &&
197          (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME))
198    {
199        Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState),
200                    GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
201        if (ACPI_FAILURE (Status))
202        {
203            return_ACPI_STATUS (Status);
204        }
205
206        AcpiPsAppendArg (UnnamedOp, Arg);
207        INCREMENT_ARG_LIST (WalkState->ArgTypes);
208    }
209
210    /*
211     * Make sure that we found a NAME and didn't run out of arguments
212     */
213    if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes))
214    {
215        return_ACPI_STATUS (AE_AML_NO_OPERAND);
216    }
217
218    /* We know that this arg is a name, move to next arg */
219
220    INCREMENT_ARG_LIST (WalkState->ArgTypes);
221
222    /*
223     * Find the object. This will either insert the object into
224     * the namespace or simply look it up
225     */
226    WalkState->Op = NULL;
227
228    Status = WalkState->DescendingCallback (WalkState, Op);
229    if (ACPI_FAILURE (Status))
230    {
231        if (Status != AE_CTRL_TERMINATE)
232        {
233            ACPI_EXCEPTION ((AE_INFO, Status, "During name lookup/catalog"));
234        }
235        return_ACPI_STATUS (Status);
236    }
237
238    if (!*Op)
239    {
240        return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
241    }
242
243    Status = AcpiPsNextParseState (WalkState, *Op, Status);
244    if (ACPI_FAILURE (Status))
245    {
246        if (Status == AE_CTRL_PENDING)
247        {
248            Status = AE_CTRL_PARSE_PENDING;
249        }
250        return_ACPI_STATUS (Status);
251    }
252
253    AcpiPsAppendArg (*Op, UnnamedOp->Common.Value.Arg);
254
255    if ((*Op)->Common.AmlOpcode == AML_REGION_OP ||
256        (*Op)->Common.AmlOpcode == AML_DATA_REGION_OP)
257    {
258        /*
259         * Defer final parsing of an OperationRegion body, because we don't
260         * have enough info in the first pass to parse it correctly (i.e.,
261         * there may be method calls within the TermArg elements of the body.)
262         *
263         * However, we must continue parsing because the opregion is not a
264         * standalone package -- we don't know where the end is at this point.
265         *
266         * (Length is unknown until parse of the body complete)
267         */
268        (*Op)->Named.Data = AmlOpStart;
269        (*Op)->Named.Length = 0;
270    }
271
272    return_ACPI_STATUS (AE_OK);
273}
274
275
276/*******************************************************************************
277 *
278 * FUNCTION:    AcpiPsCreateOp
279 *
280 * PARAMETERS:  WalkState           - Current state
281 *              AmlOpStart          - Op start in AML
282 *              NewOp               - Returned Op
283 *
284 * RETURN:      Status
285 *
286 * DESCRIPTION: Get Op from AML
287 *
288 ******************************************************************************/
289
290ACPI_STATUS
291AcpiPsCreateOp (
292    ACPI_WALK_STATE         *WalkState,
293    UINT8                   *AmlOpStart,
294    ACPI_PARSE_OBJECT       **NewOp)
295{
296    ACPI_STATUS             Status = AE_OK;
297    ACPI_PARSE_OBJECT       *Op;
298    ACPI_PARSE_OBJECT       *NamedOp = NULL;
299    ACPI_PARSE_OBJECT       *ParentScope;
300    UINT8                   ArgumentCount;
301    const ACPI_OPCODE_INFO  *OpInfo;
302
303
304    ACPI_FUNCTION_TRACE_PTR (PsCreateOp, WalkState);
305
306
307    Status = AcpiPsGetAmlOpcode (WalkState);
308    if (Status == AE_CTRL_PARSE_CONTINUE)
309    {
310        return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
311    }
312
313    /* Create Op structure and append to parent's argument list */
314
315    WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
316    Op = AcpiPsAllocOp (WalkState->Opcode);
317    if (!Op)
318    {
319        return_ACPI_STATUS (AE_NO_MEMORY);
320    }
321
322    if (WalkState->OpInfo->Flags & AML_NAMED)
323    {
324        Status = AcpiPsBuildNamedOp (WalkState, AmlOpStart, Op, &NamedOp);
325        AcpiPsFreeOp (Op);
326        if (ACPI_FAILURE (Status))
327        {
328            return_ACPI_STATUS (Status);
329        }
330
331        *NewOp = NamedOp;
332        return_ACPI_STATUS (AE_OK);
333    }
334
335    /* Not a named opcode, just allocate Op and append to parent */
336
337    if (WalkState->OpInfo->Flags & AML_CREATE)
338    {
339        /*
340         * Backup to beginning of CreateXXXfield declaration
341         * BodyLength is unknown until we parse the body
342         */
343        Op->Named.Data = AmlOpStart;
344        Op->Named.Length = 0;
345    }
346
347    if (WalkState->Opcode == AML_BANK_FIELD_OP)
348    {
349        /*
350         * Backup to beginning of BankField declaration
351         * BodyLength is unknown until we parse the body
352         */
353        Op->Named.Data = AmlOpStart;
354        Op->Named.Length = 0;
355    }
356
357    ParentScope = AcpiPsGetParentScope (&(WalkState->ParserState));
358    AcpiPsAppendArg (ParentScope, Op);
359
360    if (ParentScope)
361    {
362        OpInfo = AcpiPsGetOpcodeInfo (ParentScope->Common.AmlOpcode);
363        if (OpInfo->Flags & AML_HAS_TARGET)
364        {
365            ArgumentCount = AcpiPsGetArgumentCount (OpInfo->Type);
366            if (ParentScope->Common.ArgListLength > ArgumentCount)
367            {
368                Op->Common.Flags |= ACPI_PARSEOP_TARGET;
369            }
370        }
371        else if (ParentScope->Common.AmlOpcode == AML_INCREMENT_OP)
372        {
373            Op->Common.Flags |= ACPI_PARSEOP_TARGET;
374        }
375    }
376
377    if (WalkState->DescendingCallback != NULL)
378    {
379        /*
380         * Find the object. This will either insert the object into
381         * the namespace or simply look it up
382         */
383        WalkState->Op = *NewOp = Op;
384
385        Status = WalkState->DescendingCallback (WalkState, &Op);
386        Status = AcpiPsNextParseState (WalkState, Op, Status);
387        if (Status == AE_CTRL_PENDING)
388        {
389            Status = AE_CTRL_PARSE_PENDING;
390        }
391    }
392
393    return_ACPI_STATUS (Status);
394}
395
396
397/*******************************************************************************
398 *
399 * FUNCTION:    AcpiPsCompleteOp
400 *
401 * PARAMETERS:  WalkState           - Current state
402 *              Op                  - Returned Op
403 *              Status              - Parse status before complete Op
404 *
405 * RETURN:      Status
406 *
407 * DESCRIPTION: Complete Op
408 *
409 ******************************************************************************/
410
411ACPI_STATUS
412AcpiPsCompleteOp (
413    ACPI_WALK_STATE         *WalkState,
414    ACPI_PARSE_OBJECT       **Op,
415    ACPI_STATUS             Status)
416{
417    ACPI_STATUS             Status2;
418
419
420    ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState);
421
422
423    /*
424     * Finished one argument of the containing scope
425     */
426    WalkState->ParserState.Scope->ParseScope.ArgCount--;
427
428    /* Close this Op (will result in parse subtree deletion) */
429
430    Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
431    if (ACPI_FAILURE (Status2))
432    {
433        return_ACPI_STATUS (Status2);
434    }
435
436    *Op = NULL;
437
438    switch (Status)
439    {
440    case AE_OK:
441
442        break;
443
444    case AE_CTRL_TRANSFER:
445
446        /* We are about to transfer to a called method */
447
448        WalkState->PrevOp = NULL;
449        WalkState->PrevArgTypes = WalkState->ArgTypes;
450        return_ACPI_STATUS (Status);
451
452    case AE_CTRL_END:
453
454        AcpiPsPopScope (&(WalkState->ParserState), Op,
455            &WalkState->ArgTypes, &WalkState->ArgCount);
456
457        if (*Op)
458        {
459            WalkState->Op = *Op;
460            WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
461            WalkState->Opcode = (*Op)->Common.AmlOpcode;
462
463            Status = WalkState->AscendingCallback (WalkState);
464            Status = AcpiPsNextParseState (WalkState, *Op, Status);
465
466            Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
467            if (ACPI_FAILURE (Status2))
468            {
469                return_ACPI_STATUS (Status2);
470            }
471        }
472
473        Status = AE_OK;
474        break;
475
476    case AE_CTRL_BREAK:
477    case AE_CTRL_CONTINUE:
478
479        /* Pop off scopes until we find the While */
480
481        while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP))
482        {
483            AcpiPsPopScope (&(WalkState->ParserState), Op,
484                &WalkState->ArgTypes, &WalkState->ArgCount);
485        }
486
487        /* Close this iteration of the While loop */
488
489        WalkState->Op = *Op;
490        WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
491        WalkState->Opcode = (*Op)->Common.AmlOpcode;
492
493        Status = WalkState->AscendingCallback (WalkState);
494        Status = AcpiPsNextParseState (WalkState, *Op, Status);
495
496        Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
497        if (ACPI_FAILURE (Status2))
498        {
499            return_ACPI_STATUS (Status2);
500        }
501
502        Status = AE_OK;
503        break;
504
505    case AE_CTRL_TERMINATE:
506
507        /* Clean up */
508        do
509        {
510            if (*Op)
511            {
512                Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
513                if (ACPI_FAILURE (Status2))
514                {
515                    return_ACPI_STATUS (Status2);
516                }
517
518                AcpiUtDeleteGenericState (
519                    AcpiUtPopGenericState (&WalkState->ControlState));
520            }
521
522            AcpiPsPopScope (&(WalkState->ParserState), Op,
523                &WalkState->ArgTypes, &WalkState->ArgCount);
524
525        } while (*Op);
526
527        return_ACPI_STATUS (AE_OK);
528
529    default:  /* All other non-AE_OK status */
530
531        do
532        {
533            if (*Op)
534            {
535                Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
536                if (ACPI_FAILURE (Status2))
537                {
538                    return_ACPI_STATUS (Status2);
539                }
540            }
541
542            AcpiPsPopScope (&(WalkState->ParserState), Op,
543                &WalkState->ArgTypes, &WalkState->ArgCount);
544
545        } while (*Op);
546
547
548#if 0
549        /*
550         * TBD: Cleanup parse ops on error
551         */
552        if (*Op == NULL)
553        {
554            AcpiPsPopScope (ParserState, Op,
555                &WalkState->ArgTypes, &WalkState->ArgCount);
556        }
557#endif
558        WalkState->PrevOp = NULL;
559        WalkState->PrevArgTypes = WalkState->ArgTypes;
560        return_ACPI_STATUS (Status);
561    }
562
563    /* This scope complete? */
564
565    if (AcpiPsHasCompletedScope (&(WalkState->ParserState)))
566    {
567        AcpiPsPopScope (&(WalkState->ParserState), Op,
568            &WalkState->ArgTypes, &WalkState->ArgCount);
569        ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op));
570    }
571    else
572    {
573        *Op = NULL;
574    }
575
576    return_ACPI_STATUS (AE_OK);
577}
578
579
580/*******************************************************************************
581 *
582 * FUNCTION:    AcpiPsCompleteFinalOp
583 *
584 * PARAMETERS:  WalkState           - Current state
585 *              Op                  - Current Op
586 *              Status              - Current parse status before complete last
587 *                                    Op
588 *
589 * RETURN:      Status
590 *
591 * DESCRIPTION: Complete last Op.
592 *
593 ******************************************************************************/
594
595ACPI_STATUS
596AcpiPsCompleteFinalOp (
597    ACPI_WALK_STATE         *WalkState,
598    ACPI_PARSE_OBJECT       *Op,
599    ACPI_STATUS             Status)
600{
601    ACPI_STATUS             Status2;
602
603
604    ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState);
605
606
607    /*
608     * Complete the last Op (if not completed), and clear the scope stack.
609     * It is easily possible to end an AML "package" with an unbounded number
610     * of open scopes (such as when several ASL blocks are closed with
611     * sequential closing braces). We want to terminate each one cleanly.
612     */
613    ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op));
614    do
615    {
616        if (Op)
617        {
618            if (WalkState->AscendingCallback != NULL)
619            {
620                WalkState->Op = Op;
621                WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
622                WalkState->Opcode = Op->Common.AmlOpcode;
623
624                Status = WalkState->AscendingCallback (WalkState);
625                Status = AcpiPsNextParseState (WalkState, Op, Status);
626                if (Status == AE_CTRL_PENDING)
627                {
628                    Status = AcpiPsCompleteOp (WalkState, &Op, AE_OK);
629                    if (ACPI_FAILURE (Status))
630                    {
631                        return_ACPI_STATUS (Status);
632                    }
633                }
634
635                if (Status == AE_CTRL_TERMINATE)
636                {
637                    Status = AE_OK;
638
639                    /* Clean up */
640                    do
641                    {
642                        if (Op)
643                        {
644                            Status2 = AcpiPsCompleteThisOp (WalkState, Op);
645                            if (ACPI_FAILURE (Status2))
646                            {
647                                return_ACPI_STATUS (Status2);
648                            }
649                        }
650
651                        AcpiPsPopScope (&(WalkState->ParserState), &Op,
652                            &WalkState->ArgTypes, &WalkState->ArgCount);
653
654                    } while (Op);
655
656                    return_ACPI_STATUS (Status);
657                }
658
659                else if (ACPI_FAILURE (Status))
660                {
661                    /* First error is most important */
662
663                    (void) AcpiPsCompleteThisOp (WalkState, Op);
664                    return_ACPI_STATUS (Status);
665                }
666            }
667
668            Status2 = AcpiPsCompleteThisOp (WalkState, Op);
669            if (ACPI_FAILURE (Status2))
670            {
671                return_ACPI_STATUS (Status2);
672            }
673        }
674
675        AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes,
676            &WalkState->ArgCount);
677
678    } while (Op);
679
680    return_ACPI_STATUS (Status);
681}
682