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