aslload.c revision 281075
1/******************************************************************************
2 *
3 * Module Name: dswload - Dispatcher namespace load callbacks
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/compiler/aslcompiler.h>
45#include <contrib/dev/acpica/include/amlcode.h>
46#include <contrib/dev/acpica/include/acdispat.h>
47#include <contrib/dev/acpica/include/acnamesp.h>
48
49#include "aslcompiler.y.h"
50
51#define _COMPONENT          ACPI_COMPILER
52        ACPI_MODULE_NAME    ("aslload")
53
54/* Local prototypes */
55
56static ACPI_STATUS
57LdLoadFieldElements (
58    ACPI_PARSE_OBJECT       *Op,
59    ACPI_WALK_STATE         *WalkState);
60
61static ACPI_STATUS
62LdLoadResourceElements (
63    ACPI_PARSE_OBJECT       *Op,
64    ACPI_WALK_STATE         *WalkState);
65
66static ACPI_STATUS
67LdNamespace1Begin (
68    ACPI_PARSE_OBJECT       *Op,
69    UINT32                  Level,
70    void                    *Context);
71
72static ACPI_STATUS
73LdNamespace2Begin (
74    ACPI_PARSE_OBJECT       *Op,
75    UINT32                  Level,
76    void                    *Context);
77
78static ACPI_STATUS
79LdCommonNamespaceEnd (
80    ACPI_PARSE_OBJECT       *Op,
81    UINT32                  Level,
82    void                    *Context);
83
84
85/*******************************************************************************
86 *
87 * FUNCTION:    LdLoadNamespace
88 *
89 * PARAMETERS:  RootOp      - Root of the parse tree
90 *
91 * RETURN:      Status
92 *
93 * DESCRIPTION: Perform a walk of the parse tree that in turn loads all of the
94 *              named ASL/AML objects into the namespace. The namespace is
95 *              constructed in order to resolve named references and references
96 *              to named fields within resource templates/descriptors.
97 *
98 ******************************************************************************/
99
100ACPI_STATUS
101LdLoadNamespace (
102    ACPI_PARSE_OBJECT       *RootOp)
103{
104    ACPI_WALK_STATE         *WalkState;
105
106
107    DbgPrint (ASL_DEBUG_OUTPUT, "\nCreating namespace\n\n");
108
109    /* Create a new walk state */
110
111    WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
112    if (!WalkState)
113    {
114        return (AE_NO_MEMORY);
115    }
116
117    /* Walk the entire parse tree, first pass */
118
119    TrWalkParseTree (RootOp, ASL_WALK_VISIT_TWICE, LdNamespace1Begin,
120        LdCommonNamespaceEnd, WalkState);
121
122    /* Second pass to handle forward references */
123
124    TrWalkParseTree (RootOp, ASL_WALK_VISIT_TWICE, LdNamespace2Begin,
125        LdCommonNamespaceEnd, WalkState);
126
127    /* Dump the namespace if debug is enabled */
128
129    AcpiNsDumpTables (ACPI_NS_ALL, ACPI_UINT32_MAX);
130    ACPI_FREE (WalkState);
131    return (AE_OK);
132}
133
134
135/*******************************************************************************
136 *
137 * FUNCTION:    LdLoadFieldElements
138 *
139 * PARAMETERS:  Op              - Parent node (Field)
140 *              WalkState       - Current walk state
141 *
142 * RETURN:      Status
143 *
144 * DESCRIPTION: Enter the named elements of the field (children of the parent)
145 *              into the namespace.
146 *
147 ******************************************************************************/
148
149static ACPI_STATUS
150LdLoadFieldElements (
151    ACPI_PARSE_OBJECT       *Op,
152    ACPI_WALK_STATE         *WalkState)
153{
154    ACPI_PARSE_OBJECT       *Child = NULL;
155    ACPI_NAMESPACE_NODE     *Node;
156    ACPI_STATUS             Status;
157
158
159    /* Get the first named field element */
160
161    switch (Op->Asl.AmlOpcode)
162    {
163    case AML_BANK_FIELD_OP:
164
165        Child = UtGetArg (Op, 6);
166        break;
167
168    case AML_INDEX_FIELD_OP:
169
170        Child = UtGetArg (Op, 5);
171        break;
172
173    case AML_FIELD_OP:
174
175        Child = UtGetArg (Op, 4);
176        break;
177
178    default:
179
180        /* No other opcodes should arrive here */
181
182        return (AE_BAD_PARAMETER);
183    }
184
185    /* Enter all elements into the namespace */
186
187    while (Child)
188    {
189        switch (Child->Asl.AmlOpcode)
190        {
191        case AML_INT_RESERVEDFIELD_OP:
192        case AML_INT_ACCESSFIELD_OP:
193        case AML_INT_CONNECTION_OP:
194            break;
195
196        default:
197
198            Status = AcpiNsLookup (WalkState->ScopeInfo,
199                        Child->Asl.Value.String,
200                        ACPI_TYPE_LOCAL_REGION_FIELD,
201                        ACPI_IMODE_LOAD_PASS1,
202                        ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
203                            ACPI_NS_ERROR_IF_FOUND,
204                        NULL, &Node);
205            if (ACPI_FAILURE (Status))
206            {
207                if (Status != AE_ALREADY_EXISTS)
208                {
209                    AslError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION, Child,
210                        Child->Asl.Value.String);
211                    return (Status);
212                }
213
214                /*
215                 * The name already exists in this scope
216                 * But continue processing the elements
217                 */
218                AslError (ASL_ERROR, ASL_MSG_NAME_EXISTS, Child,
219                    Child->Asl.Value.String);
220            }
221            else
222            {
223                Child->Asl.Node = Node;
224                Node->Op = Child;
225            }
226            break;
227        }
228
229        Child = Child->Asl.Next;
230    }
231
232    return (AE_OK);
233}
234
235
236/*******************************************************************************
237 *
238 * FUNCTION:    LdLoadResourceElements
239 *
240 * PARAMETERS:  Op              - Parent node (Resource Descriptor)
241 *              WalkState       - Current walk state
242 *
243 * RETURN:      Status
244 *
245 * DESCRIPTION: Enter the named elements of the resource descriptor (children
246 *              of the parent) into the namespace.
247 *
248 * NOTE: In the real AML namespace, these named elements never exist. But
249 *       we simply use the namespace here as a symbol table so we can look
250 *       them up as they are referenced.
251 *
252 ******************************************************************************/
253
254static ACPI_STATUS
255LdLoadResourceElements (
256    ACPI_PARSE_OBJECT       *Op,
257    ACPI_WALK_STATE         *WalkState)
258{
259    ACPI_PARSE_OBJECT       *InitializerOp = NULL;
260    ACPI_NAMESPACE_NODE     *Node;
261    ACPI_STATUS             Status;
262
263
264    /*
265     * Enter the resource name into the namespace. Name must not already exist.
266     * This opens a scope, so later field names are guaranteed to be new/unique.
267     */
268    Status = AcpiNsLookup (WalkState->ScopeInfo, Op->Asl.Namepath,
269                ACPI_TYPE_LOCAL_RESOURCE, ACPI_IMODE_LOAD_PASS1,
270                ACPI_NS_NO_UPSEARCH | ACPI_NS_ERROR_IF_FOUND,
271                WalkState, &Node);
272    if (ACPI_FAILURE (Status))
273    {
274        if (Status == AE_ALREADY_EXISTS)
275        {
276            /* Actual node causing the error was saved in ParentMethod */
277
278            AslError (ASL_ERROR, ASL_MSG_NAME_EXISTS,
279                (ACPI_PARSE_OBJECT *) Op->Asl.ParentMethod, Op->Asl.Namepath);
280            return (AE_OK);
281        }
282        return (Status);
283    }
284
285    Node->Value = (UINT32) Op->Asl.Value.Integer;
286    Node->Op = Op;
287    Op->Asl.Node = Node;
288
289    /*
290     * Now enter the predefined fields, for easy lookup when referenced
291     * by the source ASL
292     */
293    InitializerOp = ASL_GET_CHILD_NODE (Op);
294    while (InitializerOp)
295    {
296        if (InitializerOp->Asl.ExternalName)
297        {
298            Status = AcpiNsLookup (WalkState->ScopeInfo,
299                        InitializerOp->Asl.ExternalName,
300                        ACPI_TYPE_LOCAL_RESOURCE_FIELD,
301                        ACPI_IMODE_LOAD_PASS1,
302                        ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE,
303                        NULL, &Node);
304            if (ACPI_FAILURE (Status))
305            {
306                return (Status);
307            }
308
309            /*
310             * Store the field offset and length in the namespace node
311             * so it can be used when the field is referenced
312             */
313            Node->Value = InitializerOp->Asl.Value.Tag.BitOffset;
314            Node->Length = InitializerOp->Asl.Value.Tag.BitLength;
315            InitializerOp->Asl.Node = Node;
316            Node->Op = InitializerOp;
317        }
318
319        InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
320    }
321
322    return (AE_OK);
323}
324
325
326/*******************************************************************************
327 *
328 * FUNCTION:    LdNamespace1Begin
329 *
330 * PARAMETERS:  ASL_WALK_CALLBACK
331 *
332 * RETURN:      Status
333 *
334 * DESCRIPTION: Descending callback used during the parse tree walk. If this
335 *              is a named AML opcode, enter into the namespace
336 *
337 ******************************************************************************/
338
339static ACPI_STATUS
340LdNamespace1Begin (
341    ACPI_PARSE_OBJECT       *Op,
342    UINT32                  Level,
343    void                    *Context)
344{
345    ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
346    ACPI_NAMESPACE_NODE     *Node;
347    ACPI_STATUS             Status;
348    ACPI_OBJECT_TYPE        ObjectType;
349    ACPI_OBJECT_TYPE        ActualObjectType = ACPI_TYPE_ANY;
350    char                    *Path;
351    UINT32                  Flags = ACPI_NS_NO_UPSEARCH;
352    ACPI_PARSE_OBJECT       *Arg;
353    UINT32                  i;
354    BOOLEAN                 ForceNewScope = FALSE;
355
356
357    ACPI_FUNCTION_NAME (LdNamespace1Begin);
358    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op %p [%s]\n",
359        Op, Op->Asl.ParseOpName));
360
361    /*
362     * We are only interested in opcodes that have an associated name
363     * (or multiple names)
364     */
365    switch (Op->Asl.AmlOpcode)
366    {
367    case AML_BANK_FIELD_OP:
368    case AML_INDEX_FIELD_OP:
369    case AML_FIELD_OP:
370
371        Status = LdLoadFieldElements (Op, WalkState);
372        return (Status);
373
374    case AML_INT_CONNECTION_OP:
375
376
377        if (Op->Asl.Child->Asl.AmlOpcode != AML_INT_NAMEPATH_OP)
378        {
379            break;
380        }
381        Arg = Op->Asl.Child;
382
383        Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Asl.ExternalName,
384            ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
385            WalkState, &Node);
386        if (ACPI_FAILURE (Status))
387        {
388            break;
389        }
390
391        if (Node->Type == ACPI_TYPE_BUFFER)
392        {
393            Arg->Asl.Node = Node;
394
395            Arg = Node->Op->Asl.Child;  /* Get namepath */
396            Arg = Arg->Asl.Next;        /* Get actual buffer */
397            Arg = Arg->Asl.Child;       /* Buffer length */
398            Arg = Arg->Asl.Next;        /* RAW_DATA buffer */
399        }
400        break;
401
402    default:
403
404        /* All other opcodes go below */
405
406        break;
407    }
408
409    /* Check if this object has already been installed in the namespace */
410
411    if (Op->Asl.Node)
412    {
413        return (AE_OK);
414    }
415
416    Path = Op->Asl.Namepath;
417    if (!Path)
418    {
419        return (AE_OK);
420    }
421
422    /* Map the raw opcode into an internal object type */
423
424    switch (Op->Asl.ParseOpcode)
425    {
426    case PARSEOP_NAME:
427
428        Arg = Op->Asl.Child;  /* Get the NameSeg/NameString node */
429        Arg = Arg->Asl.Next;  /* First peer is the object to be associated with the name */
430
431        /*
432         * If this name refers to a ResourceTemplate, we will need to open
433         * a new scope so that the resource subfield names can be entered into
434         * the namespace underneath this name
435         */
436        if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
437        {
438            ForceNewScope = TRUE;
439        }
440
441        /* Get the data type associated with the named object, not the name itself */
442
443        /* Log2 loop to convert from Btype (binary) to Etype (encoded) */
444
445        ObjectType = 1;
446        for (i = 1; i < Arg->Asl.AcpiBtype; i *= 2)
447        {
448            ObjectType++;
449        }
450        break;
451
452
453    case PARSEOP_EXTERNAL:
454        /*
455         * "External" simply enters a name and type into the namespace.
456         * We must be careful to not open a new scope, however, no matter
457         * what type the external name refers to (e.g., a method)
458         *
459         * first child is name, next child is ObjectType
460         */
461        ActualObjectType = (UINT8) Op->Asl.Child->Asl.Next->Asl.Value.Integer;
462        ObjectType = ACPI_TYPE_ANY;
463
464        /*
465         * We will mark every new node along the path as "External". This
466         * allows some or all of the nodes to be created later in the ASL
467         * code. Handles cases like this:
468         *
469         *   External (\_SB_.PCI0.ABCD, IntObj)
470         *   Scope (_SB_)
471         *   {
472         *       Device (PCI0)
473         *       {
474         *       }
475         *   }
476         *   Method (X)
477         *   {
478         *       Store (\_SB_.PCI0.ABCD, Local0)
479         *   }
480         */
481        Flags |= ACPI_NS_EXTERNAL;
482        break;
483
484    case PARSEOP_DEFAULT_ARG:
485
486        if (Op->Asl.CompileFlags == NODE_IS_RESOURCE_DESC)
487        {
488            Status = LdLoadResourceElements (Op, WalkState);
489            return_ACPI_STATUS (Status);
490        }
491
492        ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
493        break;
494
495    case PARSEOP_SCOPE:
496        /*
497         * The name referenced by Scope(Name) must already exist at this point.
498         * In other words, forward references for Scope() are not supported.
499         * The only real reason for this is that the MS interpreter cannot
500         * handle this case. Perhaps someday this case can go away.
501         */
502        Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
503                    ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
504                    WalkState, &(Node));
505        if (ACPI_FAILURE (Status))
506        {
507            if (Status == AE_NOT_FOUND)
508            {
509                /* The name was not found, go ahead and create it */
510
511                Status = AcpiNsLookup (WalkState->ScopeInfo, Path,
512                            ACPI_TYPE_LOCAL_SCOPE,
513                            ACPI_IMODE_LOAD_PASS1, Flags,
514                            WalkState, &(Node));
515                if (ACPI_FAILURE (Status))
516                {
517                    return_ACPI_STATUS (Status);
518                }
519
520                /*
521                 * However, this is an error -- primarily because the MS
522                 * interpreter can't handle a forward reference from the
523                 * Scope() operator.
524                 */
525                AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op,
526                    Op->Asl.ExternalName);
527                AslError (ASL_ERROR, ASL_MSG_SCOPE_FWD_REF, Op,
528                    Op->Asl.ExternalName);
529                goto FinishNode;
530            }
531
532            AslCoreSubsystemError (Op, Status,
533                "Failure from namespace lookup", FALSE);
534
535            return_ACPI_STATUS (Status);
536        }
537
538        /* We found a node with this name, now check the type */
539
540        switch (Node->Type)
541        {
542        case ACPI_TYPE_LOCAL_SCOPE:
543        case ACPI_TYPE_DEVICE:
544        case ACPI_TYPE_POWER:
545        case ACPI_TYPE_PROCESSOR:
546        case ACPI_TYPE_THERMAL:
547
548            /* These are acceptable types - they all open a new scope */
549            break;
550
551        case ACPI_TYPE_INTEGER:
552        case ACPI_TYPE_STRING:
553        case ACPI_TYPE_BUFFER:
554            /*
555             * These types we will allow, but we will change the type.
556             * This enables some existing code of the form:
557             *
558             *  Name (DEB, 0)
559             *  Scope (DEB) { ... }
560             *
561             * Which is used to workaround the fact that the MS interpreter
562             * does not allow Scope() forward references.
563             */
564            sprintf (MsgBuffer, "%s [%s], changing type to [Scope]",
565                Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type));
566            AslError (ASL_REMARK, ASL_MSG_SCOPE_TYPE, Op, MsgBuffer);
567
568            /* Switch the type to scope, open the new scope */
569
570            Node->Type = ACPI_TYPE_LOCAL_SCOPE;
571            Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE,
572                        WalkState);
573            if (ACPI_FAILURE (Status))
574            {
575                return_ACPI_STATUS (Status);
576            }
577            break;
578
579        default:
580
581            /* All other types are an error */
582
583            sprintf (MsgBuffer, "%s [%s]", Op->Asl.ExternalName,
584                AcpiUtGetTypeName (Node->Type));
585            AslError (ASL_ERROR, ASL_MSG_SCOPE_TYPE, Op, MsgBuffer);
586
587            /*
588             * However, switch the type to be an actual scope so
589             * that compilation can continue without generating a whole
590             * cascade of additional errors. Open the new scope.
591             */
592            Node->Type = ACPI_TYPE_LOCAL_SCOPE;
593            Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE,
594                        WalkState);
595            if (ACPI_FAILURE (Status))
596            {
597                return_ACPI_STATUS (Status);
598            }
599            break;
600        }
601
602        Status = AE_OK;
603        goto FinishNode;
604
605
606    default:
607
608        ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
609        break;
610    }
611
612
613    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Loading name: %s, (%s)\n",
614            Op->Asl.ExternalName, AcpiUtGetTypeName (ObjectType)));
615
616    /* The name must not already exist */
617
618    Flags |= ACPI_NS_ERROR_IF_FOUND;
619
620    /*
621     * Enter the named type into the internal namespace. We enter the name
622     * as we go downward in the parse tree. Any necessary subobjects that
623     * involve arguments to the opcode must be created as we go back up the
624     * parse tree later.
625     */
626    Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
627                    ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &Node);
628    if (ACPI_FAILURE (Status))
629    {
630        if (Status == AE_ALREADY_EXISTS)
631        {
632            /* The name already exists in this scope */
633
634            if (Node->Type == ACPI_TYPE_LOCAL_SCOPE)
635            {
636                /* Allow multiple references to the same scope */
637
638                Node->Type = (UINT8) ObjectType;
639                Status = AE_OK;
640            }
641            else if ((Node->Flags & ANOBJ_IS_EXTERNAL) &&
642                     (Op->Asl.ParseOpcode != PARSEOP_EXTERNAL))
643            {
644                /*
645                 * Allow one create on an object or segment that was
646                 * previously declared External
647                 */
648                Node->Flags &= ~ANOBJ_IS_EXTERNAL;
649                Node->Type = (UINT8) ObjectType;
650
651                /* Just retyped a node, probably will need to open a scope */
652
653                if (AcpiNsOpensScope (ObjectType))
654                {
655                    Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState);
656                    if (ACPI_FAILURE (Status))
657                    {
658                        return_ACPI_STATUS (Status);
659                    }
660                }
661                Status = AE_OK;
662            }
663            else
664            {
665                /* Valid error, object already exists */
666
667                AslError (ASL_ERROR, ASL_MSG_NAME_EXISTS, Op,
668                    Op->Asl.ExternalName);
669                return_ACPI_STATUS (AE_OK);
670            }
671        }
672        else
673        {
674            AslCoreSubsystemError (Op, Status,
675                "Failure from namespace lookup", FALSE);
676            return_ACPI_STATUS (Status);
677        }
678    }
679
680    if (ForceNewScope)
681    {
682        Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState);
683        if (ACPI_FAILURE (Status))
684        {
685            return_ACPI_STATUS (Status);
686        }
687    }
688
689FinishNode:
690    /*
691     * Point the parse node to the new namespace node, and point
692     * the Node back to the original Parse node
693     */
694    Op->Asl.Node = Node;
695    Node->Op = Op;
696
697    /* Set the actual data type if appropriate (EXTERNAL term only) */
698
699    if (ActualObjectType != ACPI_TYPE_ANY)
700    {
701        Node->Type = (UINT8) ActualObjectType;
702        Node->Value = ASL_EXTERNAL_METHOD;
703    }
704
705    if (Op->Asl.ParseOpcode == PARSEOP_METHOD)
706    {
707        /*
708         * Get the method argument count from "Extra" and save
709         * it in the namespace node
710         */
711        Node->Value = (UINT32) Op->Asl.Extra;
712    }
713
714    return_ACPI_STATUS (Status);
715}
716
717
718/*******************************************************************************
719 *
720 * FUNCTION:    LdNamespace2Begin
721 *
722 * PARAMETERS:  ASL_WALK_CALLBACK
723 *
724 * RETURN:      Status
725 *
726 * DESCRIPTION: Descending callback used during the pass 2 parse tree walk.
727 *              Second pass resolves some forward references.
728 *
729 * Notes:
730 * Currently only needs to handle the Alias operator.
731 * Could be used to allow forward references from the Scope() operator, but
732 * the MS interpreter does not allow this, so this compiler does not either.
733 *
734 ******************************************************************************/
735
736static ACPI_STATUS
737LdNamespace2Begin (
738    ACPI_PARSE_OBJECT       *Op,
739    UINT32                  Level,
740    void                    *Context)
741{
742    ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
743    ACPI_STATUS             Status;
744    ACPI_NAMESPACE_NODE     *Node;
745    ACPI_OBJECT_TYPE        ObjectType;
746    BOOLEAN                 ForceNewScope = FALSE;
747    ACPI_PARSE_OBJECT       *Arg;
748    char                    *Path;
749    ACPI_NAMESPACE_NODE     *TargetNode;
750
751
752    ACPI_FUNCTION_NAME (LdNamespace2Begin);
753    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op %p [%s]\n",
754        Op, Op->Asl.ParseOpName));
755
756
757    /* Ignore Ops with no namespace node */
758
759    Node = Op->Asl.Node;
760    if (!Node)
761    {
762        return (AE_OK);
763    }
764
765    /* Get the type to determine if we should push the scope */
766
767    if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) &&
768        (Op->Asl.CompileFlags == NODE_IS_RESOURCE_DESC))
769    {
770        ObjectType = ACPI_TYPE_LOCAL_RESOURCE;
771    }
772    else
773    {
774        ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
775    }
776
777    /* Push scope for Resource Templates */
778
779    if (Op->Asl.ParseOpcode == PARSEOP_NAME)
780    {
781        if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
782        {
783            ForceNewScope = TRUE;
784        }
785    }
786
787    /* Push the scope stack */
788
789    if (ForceNewScope || AcpiNsOpensScope (ObjectType))
790    {
791        Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState);
792        if (ACPI_FAILURE (Status))
793        {
794            return_ACPI_STATUS (Status);
795        }
796    }
797
798    if (Op->Asl.ParseOpcode == PARSEOP_ALIAS)
799    {
800        /* Complete the alias node by getting and saving the target node */
801
802        /* First child is the alias target */
803
804        Arg = Op->Asl.Child;
805
806        /* Get the target pathname */
807
808        Path = Arg->Asl.Namepath;
809        if (!Path)
810        {
811            Status = UtInternalizeName (Arg->Asl.ExternalName, &Path);
812            if (ACPI_FAILURE (Status))
813            {
814                return (Status);
815            }
816        }
817
818        /* Get the NS node associated with the target. It must exist. */
819
820        Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
821                    ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
822                    WalkState, &TargetNode);
823        if (ACPI_FAILURE (Status))
824        {
825            if (Status == AE_NOT_FOUND)
826            {
827                AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op,
828                    Op->Asl.ExternalName);
829
830                /*
831                 * The name was not found, go ahead and create it.
832                 * This prevents more errors later.
833                 */
834                Status = AcpiNsLookup (WalkState->ScopeInfo, Path,
835                            ACPI_TYPE_ANY,
836                            ACPI_IMODE_LOAD_PASS1, ACPI_NS_NO_UPSEARCH,
837                            WalkState, &(Node));
838                return (AE_OK);
839            }
840
841            AslCoreSubsystemError (Op, Status,
842                "Failure from namespace lookup", FALSE);
843            return (AE_OK);
844        }
845
846        /* Save the target node within the alias node */
847
848        Node->Object = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, TargetNode);
849    }
850
851    return (AE_OK);
852}
853
854
855/*******************************************************************************
856 *
857 * FUNCTION:    LdCommonNamespaceEnd
858 *
859 * PARAMETERS:  ASL_WALK_CALLBACK
860 *
861 * RETURN:      Status
862 *
863 * DESCRIPTION: Ascending callback used during the loading of the namespace,
864 *              We only need to worry about managing the scope stack here.
865 *
866 ******************************************************************************/
867
868static ACPI_STATUS
869LdCommonNamespaceEnd (
870    ACPI_PARSE_OBJECT       *Op,
871    UINT32                  Level,
872    void                    *Context)
873{
874    ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
875    ACPI_OBJECT_TYPE        ObjectType;
876    BOOLEAN                 ForceNewScope = FALSE;
877
878
879    ACPI_FUNCTION_NAME (LdCommonNamespaceEnd);
880
881
882    /* We are only interested in opcodes that have an associated name */
883
884    if (!Op->Asl.Namepath)
885    {
886        return (AE_OK);
887    }
888
889    /* Get the type to determine if we should pop the scope */
890
891    if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) &&
892        (Op->Asl.CompileFlags == NODE_IS_RESOURCE_DESC))
893    {
894        /* TBD: Merge into AcpiDsMapNamedOpcodeToDataType */
895
896        ObjectType = ACPI_TYPE_LOCAL_RESOURCE;
897    }
898    else
899    {
900        ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
901    }
902
903    /* Pop scope that was pushed for Resource Templates */
904
905    if (Op->Asl.ParseOpcode == PARSEOP_NAME)
906    {
907        if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
908        {
909            ForceNewScope = TRUE;
910        }
911    }
912
913    /* Pop the scope stack */
914
915    if (ForceNewScope || AcpiNsOpensScope (ObjectType))
916    {
917        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
918            "(%s): Popping scope for Op [%s] %p\n",
919            AcpiUtGetTypeName (ObjectType), Op->Asl.ParseOpName, Op));
920
921        (void) AcpiDsScopeStackPop (WalkState);
922    }
923
924    return (AE_OK);
925}
926