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