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