xref: /dflybsd-src/sys/contrib/dev/acpica/source/compiler/aslxref.c (revision 965b839fa3b6a8029b586326f283ad2260a4871c)
1 /******************************************************************************
2  *
3  * Module Name: aslxref - Namespace cross-reference
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "aslcompiler.h"
45 #include "aslcompiler.y.h"
46 #include "acparser.h"
47 #include "amlcode.h"
48 #include "acnamesp.h"
49 #include "acdispat.h"
50 
51 
52 #define _COMPONENT          ACPI_COMPILER
53         ACPI_MODULE_NAME    ("aslxref")
54 
55 /* Local prototypes */
56 
57 static ACPI_STATUS
58 XfNamespaceLocateBegin (
59     ACPI_PARSE_OBJECT       *Op,
60     UINT32                  Level,
61     void                    *Context);
62 
63 static ACPI_STATUS
64 XfNamespaceLocateEnd (
65     ACPI_PARSE_OBJECT       *Op,
66     UINT32                  Level,
67     void                    *Context);
68 
69 static BOOLEAN
70 XfObjectExists (
71     char                    *Name);
72 
73 static ACPI_STATUS
74 XfCompareOneNamespaceObject (
75     ACPI_HANDLE             ObjHandle,
76     UINT32                  Level,
77     void                    *Context,
78     void                    **ReturnValue);
79 
80 static void
81 XfCheckFieldRange (
82     ACPI_PARSE_OBJECT       *Op,
83     UINT32                  RegionBitLength,
84     UINT32                  FieldBitOffset,
85     UINT32                  FieldBitLength,
86     UINT32                  AccessBitWidth);
87 
88 #ifdef __UNDER_DEVELOPMENT
89 static ACPI_PARSE_OBJECT *
90 XfGetParentMethod (
91     ACPI_PARSE_OBJECT       *Op);
92 
93 static void
94 XfCheckIllegalReference (
95     ACPI_PARSE_OBJECT       *Op,
96     ACPI_NAMESPACE_NODE     *Node);
97 
98 static BOOLEAN
99 XfIsObjectParental (
100     ACPI_PARSE_OBJECT       *MethodOp1,
101     ACPI_PARSE_OBJECT       *MethodOp2);
102 #endif
103 
104 
105 /*******************************************************************************
106  *
107  * FUNCTION:    XfCrossReferenceNamespace
108  *
109  * PARAMETERS:  None
110  *
111  * RETURN:      Status
112  *
113  * DESCRIPTION: Perform a cross reference check of the parse tree against the
114  *              namespace. Every named referenced within the parse tree
115  *              should be get resolved with a namespace lookup. If not, the
116  *              original reference in the ASL code is invalid -- i.e., refers
117  *              to a non-existent object.
118  *
119  * NOTE:  The ASL "External" operator causes the name to be inserted into the
120  *        namespace so that references to the external name will be resolved
121  *        correctly here.
122  *
123  ******************************************************************************/
124 
125 ACPI_STATUS
126 XfCrossReferenceNamespace (
127     void)
128 {
129     ACPI_WALK_STATE         *WalkState;
130 
131 
132     DbgPrint (ASL_DEBUG_OUTPUT, "\nCross referencing namespace\n\n");
133 
134     /*
135      * Create a new walk state for use when looking up names
136      * within the namespace (Passed as context to the callbacks)
137      */
138     WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
139     if (!WalkState)
140     {
141         return (AE_NO_MEMORY);
142     }
143 
144     /* Walk the entire parse tree */
145 
146     TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE, XfNamespaceLocateBegin,
147                         XfNamespaceLocateEnd, WalkState);
148 
149     ACPI_FREE (WalkState);
150     return (AE_OK);
151 }
152 
153 
154 /*******************************************************************************
155  *
156  * FUNCTION:    XfObjectExists
157  *
158  * PARAMETERS:  Name            - 4 char ACPI name
159  *
160  * RETURN:      TRUE if name exists in namespace
161  *
162  * DESCRIPTION: Walk the namespace to find an object
163  *
164  ******************************************************************************/
165 
166 static BOOLEAN
167 XfObjectExists (
168     char                    *Name)
169 {
170     ACPI_STATUS             Status;
171 
172 
173     /* Walk entire namespace from the supplied root */
174 
175     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
176                 ACPI_UINT32_MAX, FALSE, XfCompareOneNamespaceObject, NULL,
177                 Name, NULL);
178     if (Status == AE_CTRL_TRUE)
179     {
180         /* At least one instance of the name was found */
181 
182         return (TRUE);
183     }
184 
185     return (FALSE);
186 }
187 
188 
189 /*******************************************************************************
190  *
191  * FUNCTION:    XfCompareOneNamespaceObject
192  *
193  * PARAMETERS:  ACPI_WALK_CALLBACK
194  *
195  * RETURN:      Status
196  *
197  * DESCRIPTION: Compare name of one object.
198  *
199  ******************************************************************************/
200 
201 static ACPI_STATUS
202 XfCompareOneNamespaceObject (
203     ACPI_HANDLE             ObjHandle,
204     UINT32                  Level,
205     void                    *Context,
206     void                    **ReturnValue)
207 {
208     ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
209 
210 
211     /* Simply check the name */
212 
213     if (*((UINT32 *) (Context)) == Node->Name.Integer)
214     {
215         /* Abort walk if we found one instance */
216 
217         return (AE_CTRL_TRUE);
218     }
219 
220     return (AE_OK);
221 }
222 
223 
224 /*******************************************************************************
225  *
226  * FUNCTION:    XfCheckFieldRange
227  *
228  * PARAMETERS:  RegionBitLength     - Length of entire parent region
229  *              FieldBitOffset      - Start of the field unit (within region)
230  *              FieldBitLength      - Entire length of field unit
231  *              AccessBitWidth      - Access width of the field unit
232  *
233  * RETURN:      None
234  *
235  * DESCRIPTION: Check one field unit to make sure it fits in the parent
236  *              op region.
237  *
238  * Note: AccessBitWidth must be either 8,16,32, or 64
239  *
240  ******************************************************************************/
241 
242 static void
243 XfCheckFieldRange (
244     ACPI_PARSE_OBJECT       *Op,
245     UINT32                  RegionBitLength,
246     UINT32                  FieldBitOffset,
247     UINT32                  FieldBitLength,
248     UINT32                  AccessBitWidth)
249 {
250     UINT32                  FieldEndBitOffset;
251 
252 
253     /*
254      * Check each field unit against the region size. The entire
255      * field unit (start offset plus length) must fit within the
256      * region.
257      */
258     FieldEndBitOffset = FieldBitOffset + FieldBitLength;
259 
260     if (FieldEndBitOffset > RegionBitLength)
261     {
262         /* Field definition itself is beyond the end-of-region */
263 
264         AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_OFFSET, Op, NULL);
265         return;
266     }
267 
268     /*
269      * Now check that the field plus AccessWidth doesn't go beyond
270      * the end-of-region. Assumes AccessBitWidth is a power of 2
271      */
272     FieldEndBitOffset = ACPI_ROUND_UP (FieldEndBitOffset, AccessBitWidth);
273 
274     if (FieldEndBitOffset > RegionBitLength)
275     {
276         /* Field definition combined with the access is beyond EOR */
277 
278         AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_ACCESS_WIDTH, Op, NULL);
279     }
280 }
281 
282 
283 #ifdef __UNDER_DEVELOPMENT
284 /*******************************************************************************
285  *
286  * FUNCTION:    XfIsObjectParental
287  *
288  * PARAMETERS:  ChildOp                 - Op to be checked
289  *              PossibleParentOp        - Determine if this op is in the family
290  *
291  * RETURN:      TRUE if ChildOp is a descendent of PossibleParentOp
292  *
293  * DESCRIPTION: Determine if an Op is a descendent of another Op. Used to
294  *              detect if a method is declared within another method.
295  *
296  ******************************************************************************/
297 
298 static BOOLEAN
299 XfIsObjectParental (
300     ACPI_PARSE_OBJECT       *ChildOp,
301     ACPI_PARSE_OBJECT       *PossibleParentOp)
302 {
303     ACPI_PARSE_OBJECT       *ParentOp;
304 
305 
306     /* Search upwards through the tree for possible parent */
307 
308     ParentOp = ChildOp;
309     while (ParentOp)
310     {
311         if (ParentOp == PossibleParentOp)
312         {
313             return (TRUE);
314         }
315 
316         ParentOp = ParentOp->Asl.Parent;
317     }
318 
319     return (FALSE);
320 }
321 
322 
323 /*******************************************************************************
324  *
325  * FUNCTION:    XfGetParentMethod
326  *
327  * PARAMETERS:  Op                      - Op to be checked
328  *
329  * RETURN:      Op for parent method. NULL if object is not within a method.
330  *
331  * DESCRIPTION: Determine if an object is within a control method. Used to
332  *              implement special rules for named references from within a
333  *              control method.
334  *
335  * NOTE: It would be better to have the parser set a flag in the Op if possible.
336  *
337  ******************************************************************************/
338 
339 static ACPI_PARSE_OBJECT *
340 XfGetParentMethod (
341     ACPI_PARSE_OBJECT       *Op)
342 {
343     ACPI_PARSE_OBJECT       *ParentOp;
344 
345 
346     if (!Op)
347     {
348         return (NULL);
349     }
350 
351     if (Op->Asl.ParseOpcode == PARSEOP_METHOD)
352     {
353         return (NULL);
354     }
355 
356     /* Walk upwards through the parse tree, up to the root if necessary */
357 
358     ParentOp = Op;
359     while (ParentOp)
360     {
361         if (ParentOp->Asl.ParseOpcode == PARSEOP_METHOD)
362         {
363             return (ParentOp);
364         }
365 
366         ParentOp = ParentOp->Asl.Parent;
367     }
368 
369     /* Object is not within a method */
370 
371     return (NULL);
372 }
373 
374 
375 /*******************************************************************************
376  *
377  * FUNCTION:    XfCheckIllegalReference
378  *
379  * PARAMETERS:  Op                      - Op referring to the target
380  *              TargetNode              - Target of the reference
381  *
382  * RETURN:      None. Emits error message for an illegal reference
383  *
384  * DESCRIPTION: Determine if a named reference is legal. A "named" reference
385  *              is something like: Store(ABCD, ...), where ABCD is an AML
386  *              Nameseg or Namepath.
387  *
388  * NOTE: Caller must ensure that the name Op is in fact a reference, and not
389  *       an actual name declaration (creation of a named object).
390  *
391  ******************************************************************************/
392 
393 static void
394 XfCheckIllegalReference (
395     ACPI_PARSE_OBJECT       *Op,
396     ACPI_NAMESPACE_NODE     *TargetNode)
397 {
398     ACPI_PARSE_OBJECT       *MethodOp1;
399     ACPI_PARSE_OBJECT       *MethodOp2;
400     ACPI_PARSE_OBJECT       *TargetOp;
401 
402 
403     /*
404      * Check for an illegal reference to a named object:
405      *
406      * 1) References from one control method to another, non-parent
407      *    method are not allowed, they will fail at runtime.
408      *
409      * 2) Forward references within a control method are not allowed.
410      *    AML interpreters use a one-pass parse of control methods
411      *    so these forward references will fail at runtime.
412      */
413     TargetOp = TargetNode->Op;
414 
415     MethodOp1 = XfGetParentMethod (Op);
416     MethodOp2 = XfGetParentMethod (TargetOp);
417 
418     /* Are both objects within control method(s)? */
419 
420     if (!MethodOp1 || !MethodOp2)
421     {
422         return;
423     }
424 
425     /* Objects not in the same method? */
426 
427     if (MethodOp1 != MethodOp2)
428     {
429         /*
430          * 1) Cross-method named reference
431          *
432          * This is OK if and only if the target reference is within in a
433          * method that is a parent of current method
434          */
435         if (!XfIsObjectParental (MethodOp1, MethodOp2))
436         {
437             AslError (ASL_ERROR, ASL_MSG_ILLEGAL_METHOD_REF, Op,
438                 Op->Asl.ExternalName);
439         }
440     }
441 
442     /*
443      * 2) Both reference and target are in the same method. Check if this is
444      * an (illegal) forward reference by examining the exact source code
445      * location of each (the referenced object and the object declaration).
446      * This is a bit nasty, yet effective.
447      */
448     else if (Op->Asl.LogicalByteOffset < TargetOp->Asl.LogicalByteOffset)
449     {
450         AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op,
451             Op->Asl.ExternalName);
452     }
453 
454 }
455 #endif
456 
457 
458 typedef struct asl_method_local
459 {
460     UINT32                  Flags;
461     ACPI_PARSE_OBJECT       *Op;
462 
463 } ASL_METHOD_LOCAL;
464 
465 
466 /*******************************************************************************
467  *
468  * FUNCTION:    XfNamespaceLocateBegin
469  *
470  * PARAMETERS:  ASL_WALK_CALLBACK
471  *
472  * RETURN:      Status
473  *
474  * DESCRIPTION: Descending callback used during cross-reference. For named
475  *              object references, attempt to locate the name in the
476  *              namespace.
477  *
478  * NOTE: ASL references to named fields within resource descriptors are
479  *       resolved to integer values here. Therefore, this step is an
480  *       important part of the code generation. We don't know that the
481  *       name refers to a resource descriptor until now.
482  *
483  ******************************************************************************/
484 
485 static ACPI_STATUS
486 XfNamespaceLocateBegin (
487     ACPI_PARSE_OBJECT       *Op,
488     UINT32                  Level,
489     void                    *Context)
490 {
491     ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
492     ACPI_NAMESPACE_NODE     *Node;
493     ACPI_STATUS             Status;
494     ACPI_OBJECT_TYPE        ObjectType;
495     char                    *Path;
496     UINT8                   PassedArgs;
497     ACPI_PARSE_OBJECT       *NextOp;
498     ACPI_PARSE_OBJECT       *OwningOp;
499     ACPI_PARSE_OBJECT       *SpaceIdOp;
500     UINT32                  MinimumLength;
501     UINT32                  Offset;
502     UINT32                  FieldBitLength;
503     UINT32                  TagBitLength;
504     UINT8                   Message = 0;
505     const ACPI_OPCODE_INFO  *OpInfo;
506     UINT32                  Flags;
507     ASL_METHOD_LOCAL        *MethodLocals;
508 
509 
510     ACPI_FUNCTION_TRACE_PTR (XfNamespaceLocateBegin, Op);
511 
512     /*
513      * If this node is the actual declaration of a name
514      * [such as the XXXX name in "Method (XXXX)"],
515      * we are not interested in it here. We only care about names that are
516      * references to other objects within the namespace and the parent objects
517      * of name declarations
518      */
519     if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)
520     {
521         return_ACPI_STATUS (AE_OK);
522     }
523 
524     /* We are only interested in opcodes that have an associated name */
525 
526     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
527 
528 
529     if (OpInfo->Type == AML_TYPE_LOCAL_VARIABLE)
530     {
531         if (!(Op->Asl.CompileFlags & NODE_IS_TARGET))
532         {
533             return_ACPI_STATUS (AE_OK);
534         }
535 
536         /* Find parent method Op */
537 
538         NextOp = Op->Asl.Parent;
539         while (NextOp)
540         {
541             if (NextOp->Asl.AmlOpcode == AML_METHOD_OP)
542             {
543                 break;
544             }
545             NextOp = NextOp->Asl.Parent;
546         }
547 
548         if (!NextOp)
549         {
550             return_ACPI_STATUS (AE_OK);
551         }
552 
553         /* Get method node */
554 
555         Node = NextOp->Asl.Node;
556 
557         /* Create local/arg object and install in method node */
558 
559         if (!Node->Object)
560         {
561             MethodLocals = UtLocalCalloc (sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_LOCALS);
562             Node->Object = (ACPI_OPERAND_OBJECT *) MethodLocals;
563 
564             /* Mark this Local as referenced */
565 
566             MethodLocals[Op->Asl.AmlOpcode & 0x0007].Flags = ANOBJ_IS_REFERENCED;
567             MethodLocals[Op->Asl.AmlOpcode & 0x0007].Op = Op;
568         }
569 
570         return_ACPI_STATUS (AE_OK);
571     }
572 
573     if (OpInfo->Type == AML_TYPE_METHOD_ARGUMENT)
574     {
575         return_ACPI_STATUS (AE_OK);
576     }
577 
578     if ((!(OpInfo->Flags & AML_NAMED)) &&
579         (!(OpInfo->Flags & AML_CREATE)) &&
580         (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
581         (Op->Asl.ParseOpcode != PARSEOP_NAMESEG)    &&
582         (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
583     {
584         return_ACPI_STATUS (AE_OK);
585     }
586 
587     /*
588      * One special case: CondRefOf operator - we don't care if the name exists
589      * or not at this point, just ignore it, the point of the operator is to
590      * determine if the name exists at runtime.
591      */
592     if ((Op->Asl.Parent) &&
593         (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF))
594     {
595         return_ACPI_STATUS (AE_OK);
596     }
597 
598     /*
599      * We must enable the "search-to-root" for single NameSegs, but
600      * we have to be very careful about opening up scopes
601      */
602     Flags = ACPI_NS_SEARCH_PARENT;
603     if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
604         (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
605         (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
606     {
607         /*
608          * These are name references, do not push the scope stack
609          * for them.
610          */
611         Flags |= ACPI_NS_DONT_OPEN_SCOPE;
612     }
613 
614     /* Get the NamePath from the appropriate place */
615 
616     if (OpInfo->Flags & AML_NAMED)
617     {
618         /* For nearly all NAMED operators, the name reference is the first child */
619 
620         Path = Op->Asl.Child->Asl.Value.String;
621         if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
622         {
623             /*
624              * ALIAS is the only oddball opcode, the name declaration
625              * (alias name) is the second operand
626              */
627             Path = Op->Asl.Child->Asl.Next->Asl.Value.String;
628         }
629     }
630     else if (OpInfo->Flags & AML_CREATE)
631     {
632         /* Name must appear as the last parameter */
633 
634         NextOp = Op->Asl.Child;
635         while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
636         {
637             NextOp = NextOp->Asl.Next;
638         }
639         Path = NextOp->Asl.Value.String;
640     }
641     else
642     {
643         Path = Op->Asl.Value.String;
644     }
645 
646     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
647     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
648         "Type=%s\n", AcpiUtGetTypeName (ObjectType)));
649 
650     /*
651      * Lookup the name in the namespace. Name must exist at this point, or it
652      * is an invalid reference.
653      *
654      * The namespace is also used as a lookup table for references to resource
655      * descriptors and the fields within them.
656      */
657     Gbl_NsLookupCount++;
658 
659     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
660                 ACPI_IMODE_EXECUTE, Flags, WalkState, &(Node));
661     if (ACPI_FAILURE (Status))
662     {
663         if (Status == AE_NOT_FOUND)
664         {
665             /*
666              * We didn't find the name reference by path -- we can qualify this
667              * a little better before we print an error message
668              */
669             if (strlen (Path) == ACPI_NAME_SIZE)
670             {
671                 /* A simple, one-segment ACPI name */
672 
673                 if (XfObjectExists (Path))
674                 {
675                     /*
676                      * There exists such a name, but we couldn't get to it
677                      * from this scope
678                      */
679                     AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op,
680                         Op->Asl.ExternalName);
681                 }
682                 else
683                 {
684                     /* The name doesn't exist, period */
685 
686                     AslError (ASL_ERROR, ASL_MSG_NOT_EXIST,
687                         Op, Op->Asl.ExternalName);
688                 }
689             }
690             else
691             {
692                 /* Check for a fully qualified path */
693 
694                 if (Path[0] == AML_ROOT_PREFIX)
695                 {
696                     /* Gave full path, the object does not exist */
697 
698                     AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op,
699                         Op->Asl.ExternalName);
700                 }
701                 else
702                 {
703                     /*
704                      * We can't tell whether it doesn't exist or just
705                      * can't be reached.
706                      */
707                     AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op,
708                         Op->Asl.ExternalName);
709                 }
710             }
711 
712             Status = AE_OK;
713         }
714 
715         return_ACPI_STATUS (Status);
716     }
717 
718     /* Check for a reference vs. name declaration */
719 
720     if (!(OpInfo->Flags & AML_NAMED) &&
721         !(OpInfo->Flags & AML_CREATE))
722     {
723         /* This node has been referenced, mark it for reference check */
724 
725         Node->Flags |= ANOBJ_IS_REFERENCED;
726 
727 #ifdef __UNDER_DEVELOPMENT
728 
729         /* Check for an illegal reference */
730 
731         XfCheckIllegalReference (Op, Node);
732 #endif
733     }
734 
735     /* Attempt to optimize the NamePath */
736 
737     OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node);
738 
739     /*
740      * 1) Dereference an alias (A name reference that is an alias)
741      *    Aliases are not nested, the alias always points to the final object
742      */
743     if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) &&
744         (Node->Type == ACPI_TYPE_LOCAL_ALIAS))
745     {
746         /* This node points back to the original PARSEOP_ALIAS */
747 
748         NextOp = Node->Op;
749 
750         /* The first child is the alias target op */
751 
752         NextOp = NextOp->Asl.Child;
753 
754         /* That in turn points back to original target alias node */
755 
756         if (NextOp->Asl.Node)
757         {
758             Node = NextOp->Asl.Node;
759         }
760 
761         /* Else - forward reference to alias, will be resolved later */
762     }
763 
764     /* 2) Check for a reference to a resource descriptor */
765 
766     if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
767         (Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
768     {
769         /*
770          * This was a reference to a field within a resource descriptor.
771          * Extract the associated field offset (either a bit or byte
772          * offset depending on the field type) and change the named
773          * reference into an integer for AML code generation
774          */
775         Offset = Node->Value;
776         TagBitLength = Node->Length;
777 
778         /*
779          * If a field is being created, generate the length (in bits) of
780          * the field. Note: Opcodes other than CreateXxxField and Index
781          * can come through here. For other opcodes, we just need to
782          * convert the resource tag reference to an integer offset.
783          */
784         switch (Op->Asl.Parent->Asl.AmlOpcode)
785         {
786         case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */
787             /*
788              * We know the length operand is an integer constant because
789              * we know that it contains a reference to a resource
790              * descriptor tag.
791              */
792             FieldBitLength = (UINT32) Op->Asl.Next->Asl.Value.Integer;
793             break;
794 
795         case AML_CREATE_BIT_FIELD_OP:
796 
797             FieldBitLength = 1;
798             break;
799 
800         case AML_CREATE_BYTE_FIELD_OP:
801         case AML_INDEX_OP:
802 
803             FieldBitLength = 8;
804             break;
805 
806         case AML_CREATE_WORD_FIELD_OP:
807 
808             FieldBitLength = 16;
809             break;
810 
811         case AML_CREATE_DWORD_FIELD_OP:
812 
813             FieldBitLength = 32;
814             break;
815 
816         case AML_CREATE_QWORD_FIELD_OP:
817 
818             FieldBitLength = 64;
819             break;
820 
821         default:
822 
823             FieldBitLength = 0;
824             break;
825         }
826 
827         /* Check the field length against the length of the resource tag */
828 
829         if (FieldBitLength)
830         {
831             if (TagBitLength < FieldBitLength)
832             {
833                 Message = ASL_MSG_TAG_SMALLER;
834             }
835             else if (TagBitLength > FieldBitLength)
836             {
837                 Message = ASL_MSG_TAG_LARGER;
838             }
839 
840             if (Message)
841             {
842                 sprintf (MsgBuffer, "Size mismatch, Tag: %u bit%s, Field: %u bit%s",
843                     TagBitLength, (TagBitLength > 1) ? "s" : "",
844                     FieldBitLength, (FieldBitLength > 1) ? "s" : "");
845 
846                 AslError (ASL_WARNING, Message, Op, MsgBuffer);
847             }
848         }
849 
850         /* Convert the BitOffset to a ByteOffset for certain opcodes */
851 
852         switch (Op->Asl.Parent->Asl.AmlOpcode)
853         {
854         case AML_CREATE_BYTE_FIELD_OP:
855         case AML_CREATE_WORD_FIELD_OP:
856         case AML_CREATE_DWORD_FIELD_OP:
857         case AML_CREATE_QWORD_FIELD_OP:
858         case AML_INDEX_OP:
859 
860             Offset = ACPI_DIV_8 (Offset);
861             break;
862 
863         default:
864 
865             break;
866         }
867 
868         /* Now convert this node to an integer whose value is the field offset */
869 
870         Op->Asl.AmlLength = 0;
871         Op->Asl.ParseOpcode = PARSEOP_INTEGER;
872         Op->Asl.Value.Integer = (UINT64) Offset;
873         Op->Asl.CompileFlags |= NODE_IS_RESOURCE_FIELD;
874 
875         OpcGenerateAmlOpcode (Op);
876     }
877 
878     /* 3) Check for a method invocation */
879 
880     else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) &&
881                 (Node->Type == ACPI_TYPE_METHOD) &&
882                 (Op->Asl.Parent) &&
883                 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD))   ||
884 
885                 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
886     {
887         /*
888          * A reference to a method within one of these opcodes is not an
889          * invocation of the method, it is simply a reference to the method.
890          */
891         if ((Op->Asl.Parent) &&
892            ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF)      ||
893             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEREFOF)    ||
894             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_PACKAGE)    ||
895             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)||
896             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE)))
897         {
898             return_ACPI_STATUS (AE_OK);
899         }
900         /*
901          * There are two types of method invocation:
902          * 1) Invocation with arguments -- the parser recognizes this
903          *    as a METHODCALL.
904          * 2) Invocation with no arguments --the parser cannot determine that
905          *    this is a method invocation, therefore we have to figure it out
906          *    here.
907          */
908         if (Node->Type != ACPI_TYPE_METHOD)
909         {
910             sprintf (MsgBuffer, "%s is a %s",
911                     Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type));
912 
913             AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, MsgBuffer);
914             return_ACPI_STATUS (AE_OK);
915         }
916 
917         /* Save the method node in the caller's op */
918 
919         Op->Asl.Node = Node;
920         if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)
921         {
922             return_ACPI_STATUS (AE_OK);
923         }
924 
925         /*
926          * This is a method invocation, with or without arguments.
927          * Count the number of arguments, each appears as a child
928          * under the parent node
929          */
930         Op->Asl.ParseOpcode = PARSEOP_METHODCALL;
931         UtSetParseOpName (Op);
932 
933         PassedArgs = 0;
934         NextOp     = Op->Asl.Child;
935 
936         while (NextOp)
937         {
938             PassedArgs++;
939             NextOp = NextOp->Asl.Next;
940         }
941 
942         if (Node->Value != ASL_EXTERNAL_METHOD)
943         {
944             /*
945              * Check the parsed arguments with the number expected by the
946              * method declaration itself
947              */
948             if (PassedArgs != Node->Value)
949             {
950                 sprintf (MsgBuffer, "%s requires %u", Op->Asl.ExternalName,
951                             Node->Value);
952 
953                 if (PassedArgs < Node->Value)
954                 {
955                     AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, MsgBuffer);
956                 }
957                 else
958                 {
959                     AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, MsgBuffer);
960                 }
961             }
962         }
963     }
964 
965     /* 4) Check for an ASL Field definition */
966 
967     else if ((Op->Asl.Parent) &&
968             ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD)     ||
969              (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD)))
970     {
971         /*
972          * Offset checking for fields. If the parent operation region has a
973          * constant length (known at compile time), we can check fields
974          * defined in that region against the region length. This will catch
975          * fields and field units that cannot possibly fit within the region.
976          *
977          * Note: Index fields do not directly reference an operation region,
978          * thus they are not included in this check.
979          */
980         if (Op == Op->Asl.Parent->Asl.Child)
981         {
982             /*
983              * This is the first child of the field node, which is
984              * the name of the region. Get the parse node for the
985              * region -- which contains the length of the region.
986              */
987             OwningOp = Node->Op;
988             Op->Asl.Parent->Asl.ExtraValue =
989                 ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer);
990 
991             /* Examine the field access width */
992 
993             switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer)
994             {
995             case AML_FIELD_ACCESS_ANY:
996             case AML_FIELD_ACCESS_BYTE:
997             case AML_FIELD_ACCESS_BUFFER:
998             default:
999 
1000                 MinimumLength = 1;
1001                 break;
1002 
1003             case AML_FIELD_ACCESS_WORD:
1004 
1005                 MinimumLength = 2;
1006                 break;
1007 
1008             case AML_FIELD_ACCESS_DWORD:
1009 
1010                 MinimumLength = 4;
1011                 break;
1012 
1013             case AML_FIELD_ACCESS_QWORD:
1014 
1015                 MinimumLength = 8;
1016                 break;
1017             }
1018 
1019             /*
1020              * Is the region at least as big as the access width?
1021              * Note: DataTableRegions have 0 length
1022              */
1023             if (((UINT32) OwningOp->Asl.Value.Integer) &&
1024                 ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength))
1025             {
1026                 AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL);
1027             }
1028 
1029             /*
1030              * Check EC/CMOS/SMBUS fields to make sure that the correct
1031              * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS)
1032              */
1033             SpaceIdOp = OwningOp->Asl.Child->Asl.Next;
1034             switch ((UINT32) SpaceIdOp->Asl.Value.Integer)
1035             {
1036             case ACPI_ADR_SPACE_EC:
1037             case ACPI_ADR_SPACE_CMOS:
1038             case ACPI_ADR_SPACE_GPIO:
1039 
1040                 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BYTE)
1041                 {
1042                     AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL);
1043                 }
1044                 break;
1045 
1046             case ACPI_ADR_SPACE_SMBUS:
1047             case ACPI_ADR_SPACE_IPMI:
1048             case ACPI_ADR_SPACE_GSBUS:
1049 
1050                 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BUFFER)
1051                 {
1052                     AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL);
1053                 }
1054                 break;
1055 
1056             default:
1057 
1058                 /* Nothing to do for other address spaces */
1059 
1060                 break;
1061             }
1062         }
1063         else
1064         {
1065             /*
1066              * This is one element of the field list. Check to make sure
1067              * that it does not go beyond the end of the parent operation region.
1068              *
1069              * In the code below:
1070              *    Op->Asl.Parent->Asl.ExtraValue      - Region Length (bits)
1071              *    Op->Asl.ExtraValue                  - Field start offset (bits)
1072              *    Op->Asl.Child->Asl.Value.Integer32  - Field length (bits)
1073              *    Op->Asl.Child->Asl.ExtraValue       - Field access width (bits)
1074              */
1075             if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child)
1076             {
1077                 XfCheckFieldRange (Op,
1078                             Op->Asl.Parent->Asl.ExtraValue,
1079                             Op->Asl.ExtraValue,
1080                             (UINT32) Op->Asl.Child->Asl.Value.Integer,
1081                             Op->Asl.Child->Asl.ExtraValue);
1082             }
1083         }
1084     }
1085 
1086     /* 5) Check for a connection object */
1087 #if 0
1088     else if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION)
1089     {
1090         return_ACPI_STATUS (Status);
1091     }
1092 #endif
1093 
1094     Op->Asl.Node = Node;
1095     return_ACPI_STATUS (Status);
1096 }
1097 
1098 
1099 /*******************************************************************************
1100  *
1101  * FUNCTION:    XfNamespaceLocateEnd
1102  *
1103  * PARAMETERS:  ASL_WALK_CALLBACK
1104  *
1105  * RETURN:      Status
1106  *
1107  * DESCRIPTION: Ascending callback used during cross reference. We only
1108  *              need to worry about scope management here.
1109  *
1110  ******************************************************************************/
1111 
1112 static ACPI_STATUS
1113 XfNamespaceLocateEnd (
1114     ACPI_PARSE_OBJECT       *Op,
1115     UINT32                  Level,
1116     void                    *Context)
1117 {
1118     ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
1119     const ACPI_OPCODE_INFO  *OpInfo;
1120 
1121 
1122     ACPI_FUNCTION_TRACE (XfNamespaceLocateEnd);
1123 
1124 
1125     /* We are only interested in opcodes that have an associated name */
1126 
1127     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
1128     if (!(OpInfo->Flags & AML_NAMED))
1129     {
1130         return_ACPI_STATUS (AE_OK);
1131     }
1132 
1133     /* Not interested in name references, we did not open a scope for them */
1134 
1135     if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
1136         (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
1137         (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
1138     {
1139         return_ACPI_STATUS (AE_OK);
1140     }
1141 
1142     /* Pop the scope stack if necessary */
1143 
1144     if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode)))
1145     {
1146 
1147         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
1148             "%s: Popping scope for Op %p\n",
1149             AcpiUtGetTypeName (OpInfo->ObjectType), Op));
1150 
1151         (void) AcpiDsScopeStackPop (WalkState);
1152     }
1153 
1154     return_ACPI_STATUS (AE_OK);
1155 }
1156