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