1/******************************************************************************
2 *
3 * Module Name: dswload2 - Dispatcher second pass namespace load callbacks
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2011, 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#define __DSWLOAD2_C__
45
46#include "acpi.h"
47#include "accommon.h"
48#include "acparser.h"
49#include "amlcode.h"
50#include "acdispat.h"
51#include "acinterp.h"
52#include "acnamesp.h"
53#include "acevents.h"
54
55#define _COMPONENT          ACPI_DISPATCHER
56        ACPI_MODULE_NAME    ("dswload2")
57
58
59/*******************************************************************************
60 *
61 * FUNCTION:    AcpiDsLoad2BeginOp
62 *
63 * PARAMETERS:  WalkState       - Current state of the parse tree walk
64 *              OutOp           - Wher to return op if a new one is created
65 *
66 * RETURN:      Status
67 *
68 * DESCRIPTION: Descending callback used during the loading of ACPI tables.
69 *
70 ******************************************************************************/
71
72ACPI_STATUS
73AcpiDsLoad2BeginOp (
74    ACPI_WALK_STATE         *WalkState,
75    ACPI_PARSE_OBJECT       **OutOp)
76{
77    ACPI_PARSE_OBJECT       *Op;
78    ACPI_NAMESPACE_NODE     *Node;
79    ACPI_STATUS             Status;
80    ACPI_OBJECT_TYPE        ObjectType;
81    char                    *BufferPtr;
82    UINT32                  Flags;
83
84
85    ACPI_FUNCTION_TRACE (DsLoad2BeginOp);
86
87
88    Op = WalkState->Op;
89    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", Op, WalkState));
90
91    if (Op)
92    {
93        if ((WalkState->ControlState) &&
94            (WalkState->ControlState->Common.State ==
95                ACPI_CONTROL_CONDITIONAL_EXECUTING))
96        {
97            /* We are executing a while loop outside of a method */
98
99            Status = AcpiDsExecBeginOp (WalkState, OutOp);
100            return_ACPI_STATUS (Status);
101        }
102
103        /* We only care about Namespace opcodes here */
104
105        if ((!(WalkState->OpInfo->Flags & AML_NSOPCODE)   &&
106              (WalkState->Opcode != AML_INT_NAMEPATH_OP)) ||
107            (!(WalkState->OpInfo->Flags & AML_NAMED)))
108        {
109            return_ACPI_STATUS (AE_OK);
110        }
111
112        /* Get the name we are going to enter or lookup in the namespace */
113
114        if (WalkState->Opcode == AML_INT_NAMEPATH_OP)
115        {
116            /* For Namepath op, get the path string */
117
118            BufferPtr = Op->Common.Value.String;
119            if (!BufferPtr)
120            {
121                /* No name, just exit */
122
123                return_ACPI_STATUS (AE_OK);
124            }
125        }
126        else
127        {
128            /* Get name from the op */
129
130            BufferPtr = ACPI_CAST_PTR (char, &Op->Named.Name);
131        }
132    }
133    else
134    {
135        /* Get the namestring from the raw AML */
136
137        BufferPtr = AcpiPsGetNextNamestring (&WalkState->ParserState);
138    }
139
140    /* Map the opcode into an internal object type */
141
142    ObjectType = WalkState->OpInfo->ObjectType;
143
144    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
145        "State=%p Op=%p Type=%X\n", WalkState, Op, ObjectType));
146
147    switch (WalkState->Opcode)
148    {
149    case AML_FIELD_OP:
150    case AML_BANK_FIELD_OP:
151    case AML_INDEX_FIELD_OP:
152
153        Node = NULL;
154        Status = AE_OK;
155        break;
156
157    case AML_INT_NAMEPATH_OP:
158        /*
159         * The NamePath is an object reference to an existing object.
160         * Don't enter the name into the namespace, but look it up
161         * for use later.
162         */
163        Status = AcpiNsLookup (WalkState->ScopeInfo, BufferPtr, ObjectType,
164                        ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
165                        WalkState, &(Node));
166        break;
167
168    case AML_SCOPE_OP:
169
170        /* Special case for Scope(\) -> refers to the Root node */
171
172        if (Op && (Op->Named.Node == AcpiGbl_RootNode))
173        {
174            Node = Op->Named.Node;
175
176            Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState);
177            if (ACPI_FAILURE (Status))
178            {
179                return_ACPI_STATUS (Status);
180            }
181        }
182        else
183        {
184            /*
185             * The Path is an object reference to an existing object.
186             * Don't enter the name into the namespace, but look it up
187             * for use later.
188             */
189            Status = AcpiNsLookup (WalkState->ScopeInfo, BufferPtr, ObjectType,
190                        ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
191                        WalkState, &(Node));
192            if (ACPI_FAILURE (Status))
193            {
194#ifdef ACPI_ASL_COMPILER
195                if (Status == AE_NOT_FOUND)
196                {
197                    Status = AE_OK;
198                }
199                else
200                {
201                    ACPI_ERROR_NAMESPACE (BufferPtr, Status);
202                }
203#else
204                ACPI_ERROR_NAMESPACE (BufferPtr, Status);
205#endif
206                return_ACPI_STATUS (Status);
207            }
208        }
209
210        /*
211         * We must check to make sure that the target is
212         * one of the opcodes that actually opens a scope
213         */
214        switch (Node->Type)
215        {
216        case ACPI_TYPE_ANY:
217        case ACPI_TYPE_LOCAL_SCOPE:         /* Scope */
218        case ACPI_TYPE_DEVICE:
219        case ACPI_TYPE_POWER:
220        case ACPI_TYPE_PROCESSOR:
221        case ACPI_TYPE_THERMAL:
222
223            /* These are acceptable types */
224            break;
225
226        case ACPI_TYPE_INTEGER:
227        case ACPI_TYPE_STRING:
228        case ACPI_TYPE_BUFFER:
229
230            /*
231             * These types we will allow, but we will change the type.
232             * This enables some existing code of the form:
233             *
234             *  Name (DEB, 0)
235             *  Scope (DEB) { ... }
236             */
237            ACPI_WARNING ((AE_INFO,
238                "Type override - [%4.4s] had invalid type (%s) "
239                "for Scope operator, changed to type ANY\n",
240                AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type)));
241
242            Node->Type = ACPI_TYPE_ANY;
243            WalkState->ScopeInfo->Common.Value = ACPI_TYPE_ANY;
244            break;
245
246        default:
247
248            /* All other types are an error */
249
250            ACPI_ERROR ((AE_INFO,
251                "Invalid type (%s) for target of "
252                "Scope operator [%4.4s] (Cannot override)",
253                AcpiUtGetTypeName (Node->Type), AcpiUtGetNodeName (Node)));
254
255            return (AE_AML_OPERAND_TYPE);
256        }
257        break;
258
259    default:
260
261        /* All other opcodes */
262
263        if (Op && Op->Common.Node)
264        {
265            /* This op/node was previously entered into the namespace */
266
267            Node = Op->Common.Node;
268
269            if (AcpiNsOpensScope (ObjectType))
270            {
271                Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState);
272                if (ACPI_FAILURE (Status))
273                {
274                    return_ACPI_STATUS (Status);
275                }
276            }
277
278            return_ACPI_STATUS (AE_OK);
279        }
280
281        /*
282         * Enter the named type into the internal namespace. We enter the name
283         * as we go downward in the parse tree. Any necessary subobjects that
284         * involve arguments to the opcode must be created as we go back up the
285         * parse tree later.
286         *
287         * Note: Name may already exist if we are executing a deferred opcode.
288         */
289        if (WalkState->DeferredNode)
290        {
291            /* This name is already in the namespace, get the node */
292
293            Node = WalkState->DeferredNode;
294            Status = AE_OK;
295            break;
296        }
297
298        Flags = ACPI_NS_NO_UPSEARCH;
299        if (WalkState->PassNumber == ACPI_IMODE_EXECUTE)
300        {
301            /* Execution mode, node cannot already exist, node is temporary */
302
303            Flags |= ACPI_NS_ERROR_IF_FOUND;
304
305            if (!(WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL))
306            {
307                Flags |= ACPI_NS_TEMPORARY;
308            }
309        }
310
311        /* Add new entry or lookup existing entry */
312
313        Status = AcpiNsLookup (WalkState->ScopeInfo, BufferPtr, ObjectType,
314                    ACPI_IMODE_LOAD_PASS2, Flags, WalkState, &Node);
315
316        if (ACPI_SUCCESS (Status) && (Flags & ACPI_NS_TEMPORARY))
317        {
318            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
319                "***New Node [%4.4s] %p is temporary\n",
320                AcpiUtGetNodeName (Node), Node));
321        }
322        break;
323    }
324
325    if (ACPI_FAILURE (Status))
326    {
327        ACPI_ERROR_NAMESPACE (BufferPtr, Status);
328        return_ACPI_STATUS (Status);
329    }
330
331    if (!Op)
332    {
333        /* Create a new op */
334
335        Op = AcpiPsAllocOp (WalkState->Opcode);
336        if (!Op)
337        {
338            return_ACPI_STATUS (AE_NO_MEMORY);
339        }
340
341        /* Initialize the new op */
342
343        if (Node)
344        {
345            Op->Named.Name = Node->Name.Integer;
346        }
347        *OutOp = Op;
348    }
349
350    /*
351     * Put the Node in the "op" object that the parser uses, so we
352     * can get it again quickly when this scope is closed
353     */
354    Op->Common.Node = Node;
355    return_ACPI_STATUS (Status);
356}
357
358
359/*******************************************************************************
360 *
361 * FUNCTION:    AcpiDsLoad2EndOp
362 *
363 * PARAMETERS:  WalkState       - Current state of the parse tree walk
364 *
365 * RETURN:      Status
366 *
367 * DESCRIPTION: Ascending callback used during the loading of the namespace,
368 *              both control methods and everything else.
369 *
370 ******************************************************************************/
371
372ACPI_STATUS
373AcpiDsLoad2EndOp (
374    ACPI_WALK_STATE         *WalkState)
375{
376    ACPI_PARSE_OBJECT       *Op;
377    ACPI_STATUS             Status = AE_OK;
378    ACPI_OBJECT_TYPE        ObjectType;
379    ACPI_NAMESPACE_NODE     *Node;
380    ACPI_PARSE_OBJECT       *Arg;
381    ACPI_NAMESPACE_NODE     *NewNode;
382#ifndef ACPI_NO_METHOD_EXECUTION
383    UINT32                  i;
384    UINT8                   RegionSpace;
385#endif
386
387
388    ACPI_FUNCTION_TRACE (DsLoad2EndOp);
389
390    Op = WalkState->Op;
391    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n",
392            WalkState->OpInfo->Name, Op, WalkState));
393
394    /* Check if opcode had an associated namespace object */
395
396    if (!(WalkState->OpInfo->Flags & AML_NSOBJECT))
397    {
398        return_ACPI_STATUS (AE_OK);
399    }
400
401    if (Op->Common.AmlOpcode == AML_SCOPE_OP)
402    {
403        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
404            "Ending scope Op=%p State=%p\n", Op, WalkState));
405    }
406
407    ObjectType = WalkState->OpInfo->ObjectType;
408
409    /*
410     * Get the Node/name from the earlier lookup
411     * (It was saved in the *op structure)
412     */
413    Node = Op->Common.Node;
414
415    /*
416     * Put the Node on the object stack (Contains the ACPI Name of
417     * this object)
418     */
419    WalkState->Operands[0] = (void *) Node;
420    WalkState->NumOperands = 1;
421
422    /* Pop the scope stack */
423
424    if (AcpiNsOpensScope (ObjectType) &&
425       (Op->Common.AmlOpcode != AML_INT_METHODCALL_OP))
426    {
427        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %p\n",
428            AcpiUtGetTypeName (ObjectType), Op));
429
430        Status = AcpiDsScopeStackPop (WalkState);
431        if (ACPI_FAILURE (Status))
432        {
433            goto Cleanup;
434        }
435    }
436
437    /*
438     * Named operations are as follows:
439     *
440     * AML_ALIAS
441     * AML_BANKFIELD
442     * AML_CREATEBITFIELD
443     * AML_CREATEBYTEFIELD
444     * AML_CREATEDWORDFIELD
445     * AML_CREATEFIELD
446     * AML_CREATEQWORDFIELD
447     * AML_CREATEWORDFIELD
448     * AML_DATA_REGION
449     * AML_DEVICE
450     * AML_EVENT
451     * AML_FIELD
452     * AML_INDEXFIELD
453     * AML_METHOD
454     * AML_METHODCALL
455     * AML_MUTEX
456     * AML_NAME
457     * AML_NAMEDFIELD
458     * AML_OPREGION
459     * AML_POWERRES
460     * AML_PROCESSOR
461     * AML_SCOPE
462     * AML_THERMALZONE
463     */
464
465    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
466        "Create-Load [%s] State=%p Op=%p NamedObj=%p\n",
467        AcpiPsGetOpcodeName (Op->Common.AmlOpcode), WalkState, Op, Node));
468
469    /* Decode the opcode */
470
471    Arg = Op->Common.Value.Arg;
472
473    switch (WalkState->OpInfo->Type)
474    {
475#ifndef ACPI_NO_METHOD_EXECUTION
476
477    case AML_TYPE_CREATE_FIELD:
478        /*
479         * Create the field object, but the field buffer and index must
480         * be evaluated later during the execution phase
481         */
482        Status = AcpiDsCreateBufferField (Op, WalkState);
483        break;
484
485
486     case AML_TYPE_NAMED_FIELD:
487        /*
488         * If we are executing a method, initialize the field
489         */
490        if (WalkState->MethodNode)
491        {
492            Status = AcpiDsInitFieldObjects (Op, WalkState);
493        }
494
495        switch (Op->Common.AmlOpcode)
496        {
497        case AML_INDEX_FIELD_OP:
498
499            Status = AcpiDsCreateIndexField (Op, (ACPI_HANDLE) Arg->Common.Node,
500                        WalkState);
501            break;
502
503        case AML_BANK_FIELD_OP:
504
505            Status = AcpiDsCreateBankField (Op, Arg->Common.Node, WalkState);
506            break;
507
508        case AML_FIELD_OP:
509
510            Status = AcpiDsCreateField (Op, Arg->Common.Node, WalkState);
511            break;
512
513        default:
514            /* All NAMED_FIELD opcodes must be handled above */
515            break;
516        }
517        break;
518
519
520     case AML_TYPE_NAMED_SIMPLE:
521
522        Status = AcpiDsCreateOperands (WalkState, Arg);
523        if (ACPI_FAILURE (Status))
524        {
525            goto Cleanup;
526        }
527
528        switch (Op->Common.AmlOpcode)
529        {
530        case AML_PROCESSOR_OP:
531
532            Status = AcpiExCreateProcessor (WalkState);
533            break;
534
535        case AML_POWER_RES_OP:
536
537            Status = AcpiExCreatePowerResource (WalkState);
538            break;
539
540        case AML_MUTEX_OP:
541
542            Status = AcpiExCreateMutex (WalkState);
543            break;
544
545        case AML_EVENT_OP:
546
547            Status = AcpiExCreateEvent (WalkState);
548            break;
549
550
551        case AML_ALIAS_OP:
552
553            Status = AcpiExCreateAlias (WalkState);
554            break;
555
556        default:
557            /* Unknown opcode */
558
559            Status = AE_OK;
560            goto Cleanup;
561        }
562
563        /* Delete operands */
564
565        for (i = 1; i < WalkState->NumOperands; i++)
566        {
567            AcpiUtRemoveReference (WalkState->Operands[i]);
568            WalkState->Operands[i] = NULL;
569        }
570
571        break;
572#endif /* ACPI_NO_METHOD_EXECUTION */
573
574    case AML_TYPE_NAMED_COMPLEX:
575
576        switch (Op->Common.AmlOpcode)
577        {
578#ifndef ACPI_NO_METHOD_EXECUTION
579        case AML_REGION_OP:
580        case AML_DATA_REGION_OP:
581
582            if (Op->Common.AmlOpcode == AML_REGION_OP)
583            {
584                RegionSpace = (ACPI_ADR_SPACE_TYPE)
585                      ((Op->Common.Value.Arg)->Common.Value.Integer);
586            }
587            else
588            {
589                RegionSpace = ACPI_ADR_SPACE_DATA_TABLE;
590            }
591
592            /*
593             * The OpRegion is not fully parsed at this time. The only valid
594             * argument is the SpaceId. (We must save the address of the
595             * AML of the address and length operands)
596             *
597             * If we have a valid region, initialize it. The namespace is
598             * unlocked at this point.
599             *
600             * Need to unlock interpreter if it is locked (if we are running
601             * a control method), in order to allow _REG methods to be run
602             * during AcpiEvInitializeRegion.
603             */
604            if (WalkState->MethodNode)
605            {
606                /*
607                 * Executing a method: initialize the region and unlock
608                 * the interpreter
609                 */
610                Status = AcpiExCreateRegion (Op->Named.Data, Op->Named.Length,
611                            RegionSpace, WalkState);
612                if (ACPI_FAILURE (Status))
613                {
614                    return (Status);
615                }
616
617                AcpiExExitInterpreter ();
618            }
619
620            Status = AcpiEvInitializeRegion (AcpiNsGetAttachedObject (Node),
621                        FALSE);
622            if (WalkState->MethodNode)
623            {
624                AcpiExEnterInterpreter ();
625            }
626
627            if (ACPI_FAILURE (Status))
628            {
629                /*
630                 *  If AE_NOT_EXIST is returned, it is not fatal
631                 *  because many regions get created before a handler
632                 *  is installed for said region.
633                 */
634                if (AE_NOT_EXIST == Status)
635                {
636                    Status = AE_OK;
637                }
638            }
639            break;
640
641
642        case AML_NAME_OP:
643
644            Status = AcpiDsCreateNode (WalkState, Node, Op);
645            break;
646
647
648        case AML_METHOD_OP:
649            /*
650             * MethodOp PkgLength NameString MethodFlags TermList
651             *
652             * Note: We must create the method node/object pair as soon as we
653             * see the method declaration. This allows later pass1 parsing
654             * of invocations of the method (need to know the number of
655             * arguments.)
656             */
657            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
658                "LOADING-Method: State=%p Op=%p NamedObj=%p\n",
659                WalkState, Op, Op->Named.Node));
660
661            if (!AcpiNsGetAttachedObject (Op->Named.Node))
662            {
663                WalkState->Operands[0] = ACPI_CAST_PTR (void, Op->Named.Node);
664                WalkState->NumOperands = 1;
665
666                Status = AcpiDsCreateOperands (WalkState, Op->Common.Value.Arg);
667                if (ACPI_SUCCESS (Status))
668                {
669                    Status = AcpiExCreateMethod (Op->Named.Data,
670                                        Op->Named.Length, WalkState);
671                }
672                WalkState->Operands[0] = NULL;
673                WalkState->NumOperands = 0;
674
675                if (ACPI_FAILURE (Status))
676                {
677                    return_ACPI_STATUS (Status);
678                }
679            }
680            break;
681
682#endif /* ACPI_NO_METHOD_EXECUTION */
683
684        default:
685            /* All NAMED_COMPLEX opcodes must be handled above */
686            break;
687        }
688        break;
689
690
691    case AML_CLASS_INTERNAL:
692
693        /* case AML_INT_NAMEPATH_OP: */
694        break;
695
696
697    case AML_CLASS_METHOD_CALL:
698
699        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
700            "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n",
701            WalkState, Op, Node));
702
703        /*
704         * Lookup the method name and save the Node
705         */
706        Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.String,
707                        ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS2,
708                        ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
709                        WalkState, &(NewNode));
710        if (ACPI_SUCCESS (Status))
711        {
712            /*
713             * Make sure that what we found is indeed a method
714             * We didn't search for a method on purpose, to see if the name
715             * would resolve
716             */
717            if (NewNode->Type != ACPI_TYPE_METHOD)
718            {
719                Status = AE_AML_OPERAND_TYPE;
720            }
721
722            /* We could put the returned object (Node) on the object stack for
723             * later, but for now, we will put it in the "op" object that the
724             * parser uses, so we can get it again at the end of this scope
725             */
726            Op->Common.Node = NewNode;
727        }
728        else
729        {
730            ACPI_ERROR_NAMESPACE (Arg->Common.Value.String, Status);
731        }
732        break;
733
734
735    default:
736        break;
737    }
738
739Cleanup:
740
741    /* Remove the Node pushed at the very beginning */
742
743    WalkState->Operands[0] = NULL;
744    WalkState->NumOperands = 0;
745    return_ACPI_STATUS (Status);
746}
747
748