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