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