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