]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/dev/acpica/compiler/asllookup.c
This commit was generated by cvs2svn to compensate for changes in r163299,
[FreeBSD/FreeBSD.git] / sys / contrib / dev / acpica / compiler / asllookup.c
1 /******************************************************************************
2  *
3  * Module Name: asllookup- Namespace lookup
4  *              $Revision: 1.95 $
5  *
6  *****************************************************************************/
7
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp.
13  * All rights reserved.
14  *
15  * 2. License
16  *
17  * 2.1. This is your license from Intel Corp. under its intellectual property
18  * rights.  You may have additional license terms from the party that provided
19  * you this software, covering your right to use that party's intellectual
20  * property rights.
21  *
22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23  * copy of the source code appearing in this file ("Covered Code") an
24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25  * base code distributed originally by Intel ("Original Intel Code") to copy,
26  * make derivatives, distribute, use and display any portion of the Covered
27  * Code in any form, with the right to sublicense such rights; and
28  *
29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30  * license (with the right to sublicense), under only those claims of Intel
31  * patents that are infringed by the Original Intel Code, to make, use, sell,
32  * offer to sell, and import the Covered Code and derivative works thereof
33  * solely to the minimum extent necessary to exercise the above copyright
34  * license, and in no event shall the patent license extend to any additions
35  * to or modifications of the Original Intel Code.  No other license or right
36  * is granted directly or by implication, estoppel or otherwise;
37  *
38  * The above copyright and patent license is granted only if the following
39  * conditions are met:
40  *
41  * 3. Conditions
42  *
43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44  * Redistribution of source code of any substantial portion of the Covered
45  * Code or modification with rights to further distribute source must include
46  * the above Copyright Notice, the above License, this list of Conditions,
47  * and the following Disclaimer and Export Compliance provision.  In addition,
48  * Licensee must cause all Covered Code to which Licensee contributes to
49  * contain a file documenting the changes Licensee made to create that Covered
50  * Code and the date of any change.  Licensee must include in that file the
51  * documentation of any changes made by any predecessor Licensee.  Licensee
52  * must include a prominent statement that the modification is derived,
53  * directly or indirectly, from Original Intel Code.
54  *
55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56  * Redistribution of source code of any substantial portion of the Covered
57  * Code or modification without rights to further distribute source must
58  * include the following Disclaimer and Export Compliance provision in the
59  * documentation and/or other materials provided with distribution.  In
60  * addition, Licensee may not authorize further sublicense of source of any
61  * portion of the Covered Code, and must include terms to the effect that the
62  * license from Licensee to its licensee is limited to the intellectual
63  * property embodied in the software Licensee provides to its licensee, and
64  * not to intellectual property embodied in modifications its licensee may
65  * make.
66  *
67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
68  * substantial portion of the Covered Code or modification must reproduce the
69  * above Copyright Notice, and the following Disclaimer and Export Compliance
70  * provision in the documentation and/or other materials provided with the
71  * distribution.
72  *
73  * 3.4. Intel retains all right, title, and interest in and to the Original
74  * Intel Code.
75  *
76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77  * Intel shall be used in advertising or otherwise to promote the sale, use or
78  * other dealings in products derived from or relating to the Covered Code
79  * without prior written authorization from Intel.
80  *
81  * 4. Disclaimer and Export Compliance
82  *
83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89  * PARTICULAR PURPOSE.
90  *
91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98  * LIMITED REMEDY.
99  *
100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
101  * software or system incorporating such software without first obtaining any
102  * required license or other approval from the U. S. Department of Commerce or
103  * any other agency or department of the United States Government.  In the
104  * event Licensee exports any such software from the United States or
105  * re-exports any such software from a foreign destination, Licensee shall
106  * ensure that the distribution and export/re-export of the software is in
107  * compliance with all laws, regulations, orders, or other restrictions of the
108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109  * any of its subsidiaries will export/re-export any technical data, process,
110  * software, or service, directly or indirectly, to any country for which the
111  * United States government or any agency thereof requires an export license,
112  * other governmental approval, or letter of assurance, without first obtaining
113  * such license, approval or letter.
114  *
115  *****************************************************************************/
116
117
118 #include <contrib/dev/acpica/compiler/aslcompiler.h>
119 #include "aslcompiler.y.h"
120
121 #include <contrib/dev/acpica/acparser.h>
122 #include <contrib/dev/acpica/amlcode.h>
123 #include <contrib/dev/acpica/acnamesp.h>
124 #include <contrib/dev/acpica/acdispat.h>
125
126
127 #define _COMPONENT          ACPI_COMPILER
128         ACPI_MODULE_NAME    ("asllookup")
129
130 /* Local prototypes */
131
132 static ACPI_STATUS
133 LsCompareOneNamespaceObject (
134     ACPI_HANDLE             ObjHandle,
135     UINT32                  Level,
136     void                    *Context,
137     void                    **ReturnValue);
138
139 static ACPI_STATUS
140 LsDoOneNamespaceObject (
141     ACPI_HANDLE             ObjHandle,
142     UINT32                  Level,
143     void                    *Context,
144     void                    **ReturnValue);
145
146 static BOOLEAN
147 LkObjectExists (
148     char                    *Name);
149
150 static void
151 LkCheckFieldRange (
152     ACPI_PARSE_OBJECT       *Op,
153     UINT32                  RegionBitLength,
154     UINT32                  FieldBitOffset,
155     UINT32                  FieldBitLength,
156     UINT32                  AccessBitWidth);
157
158 static ACPI_STATUS
159 LkNamespaceLocateBegin (
160     ACPI_PARSE_OBJECT       *Op,
161     UINT32                  Level,
162     void                    *Context);
163
164 static ACPI_STATUS
165 LkNamespaceLocateEnd (
166     ACPI_PARSE_OBJECT       *Op,
167     UINT32                  Level,
168     void                    *Context);
169
170
171 /*******************************************************************************
172  *
173  * FUNCTION:    LsDoOneNamespaceObject
174  *
175  * PARAMETERS:  ACPI_WALK_CALLBACK
176  *
177  * RETURN:      Status
178  *
179  * DESCRIPTION: Dump a namespace object to the namespace output file.
180  *              Called during the walk of the namespace to dump all objects.
181  *
182  ******************************************************************************/
183
184 static ACPI_STATUS
185 LsDoOneNamespaceObject (
186     ACPI_HANDLE             ObjHandle,
187     UINT32                  Level,
188     void                    *Context,
189     void                    **ReturnValue)
190 {
191     ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
192     ACPI_OPERAND_OBJECT     *ObjDesc;
193     ACPI_PARSE_OBJECT       *Op;
194
195
196     Gbl_NumNamespaceObjects++;
197
198     FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "%5d  [%d]  %*s %4.4s - %s",
199                         Gbl_NumNamespaceObjects, Level, (Level * 3), " ",
200                         &Node->Name,
201                         AcpiUtGetTypeName (Node->Type));
202
203     Op = Node->Op;
204     ObjDesc = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Node->Object);
205
206     if (!Op)
207     {
208         FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\n");
209         return (AE_OK);
210     }
211
212
213     if ((ObjDesc) &&
214         (ObjDesc->Common.Descriptor == ACPI_DESC_TYPE_OPERAND))
215     {
216         switch (Node->Type)
217         {
218         case ACPI_TYPE_INTEGER:
219
220             FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
221                 "       [Initial Value   0x%8.8X%8.8X]",
222                 ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value));
223             break;
224
225
226         case ACPI_TYPE_STRING:
227
228             FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
229                 "        [Initial Value   \"%s\"]",
230                 ObjDesc->String.Pointer);
231             break;
232
233         default:
234             /* Nothing to do for other types */
235             break;
236         }
237
238     }
239     else
240     {
241         switch (Node->Type)
242         {
243         case ACPI_TYPE_INTEGER:
244
245             if (Op->Asl.ParseOpcode == PARSEOP_NAME)
246             {
247                 Op = Op->Asl.Child;
248             }
249             if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG)  ||
250                 (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
251             {
252                 Op = Op->Asl.Next;
253             }
254             FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
255                 "       [Initial Value   0x%8.8X%8.8X]",
256                 ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
257             break;
258
259
260         case ACPI_TYPE_STRING:
261
262             if (Op->Asl.ParseOpcode == PARSEOP_NAME)
263             {
264                 Op = Op->Asl.Child;
265             }
266             if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG)  ||
267                 (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
268             {
269                 Op = Op->Asl.Next;
270             }
271             FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
272                 "        [Initial Value   \"%s\"]",
273                 Op->Asl.Value.String);
274             break;
275
276
277         case ACPI_TYPE_LOCAL_REGION_FIELD:
278
279             if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG)  ||
280                 (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
281             {
282                 Op = Op->Asl.Child;
283             }
284             FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
285                 "   [Offset 0x%04X   Length 0x%04X bits]",
286                 Op->Asl.Parent->Asl.ExtraValue, (UINT32) Op->Asl.Value.Integer);
287             break;
288
289
290         case ACPI_TYPE_BUFFER_FIELD:
291
292             switch (Op->Asl.ParseOpcode)
293             {
294             case PARSEOP_CREATEBYTEFIELD:
295                 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "   [BYTE  ( 8 bit)]");
296                 break;
297
298             case PARSEOP_CREATEDWORDFIELD:
299                 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "   [DWORD (32 bit)]");
300                 break;
301
302             case PARSEOP_CREATEQWORDFIELD:
303                 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "   [QWORD (64 bit)]");
304                 break;
305
306             case PARSEOP_CREATEWORDFIELD:
307                 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "   [WORD  (16 bit)]");
308                 break;
309
310             case PARSEOP_CREATEBITFIELD:
311                 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "   [BIT   ( 1 bit)]");
312                 break;
313
314             case PARSEOP_CREATEFIELD:
315                 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "   [Arbitrary Bit Field]");
316                 break;
317
318             default:
319                 break;
320
321             }
322             break;
323
324
325         case ACPI_TYPE_PACKAGE:
326
327             if (Op->Asl.ParseOpcode == PARSEOP_NAME)
328             {
329                 Op = Op->Asl.Child;
330             }
331             if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG)  ||
332                 (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
333             {
334                 Op = Op->Asl.Next;
335             }
336             Op = Op->Asl.Child;
337
338             if ((Op->Asl.ParseOpcode == PARSEOP_BYTECONST) ||
339                 (Op->Asl.ParseOpcode == PARSEOP_RAW_DATA))
340             {
341                 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
342                     "       [Initial Length  0x%.2X elements]",
343                     Op->Asl.Value.Integer);
344             }
345             break;
346
347
348         case ACPI_TYPE_BUFFER:
349
350             if (Op->Asl.ParseOpcode == PARSEOP_NAME)
351             {
352                 Op = Op->Asl.Child;
353             }
354             if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG)  ||
355                 (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
356             {
357                 Op = Op->Asl.Next;
358             }
359             Op = Op->Asl.Child;
360
361             if (Op->Asl.ParseOpcode == PARSEOP_INTEGER)
362             {
363                 FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
364                     "        [Initial Length  0x%.2X bytes]",
365                     Op->Asl.Value.Integer);
366             }
367             break;
368
369
370         case ACPI_TYPE_METHOD:
371
372             FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
373                 "        [Code Length     0x%.4X bytes]",
374                 Op->Asl.AmlSubtreeLength);
375             break;
376
377
378         default:
379             /* Nothing to do for other types */
380             break;
381         }
382     }
383
384     FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\n");
385     return (AE_OK);
386 }
387
388
389 /*******************************************************************************
390  *
391  * FUNCTION:    LsDisplayNamespace
392  *
393  * PARAMETERS:  None
394  *
395  * RETURN:      Status
396  *
397  * DESCRIPTION: Walk the namespace an display information about each node
398  *              in the tree.  Information is written to the optional
399  *              namespace output file.
400  *
401  ******************************************************************************/
402
403 ACPI_STATUS
404 LsDisplayNamespace (
405     void)
406 {
407     ACPI_STATUS             Status;
408
409
410     if (!Gbl_NsOutputFlag)
411     {
412         return (AE_OK);
413     }
414
415     /* File header */
416
417     FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "Contents of ACPI Namespace\n\n");
418     FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "Count  Depth    Name - Type\n\n");
419
420     /* Walk entire namespace from the root */
421
422     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
423                 ACPI_UINT32_MAX, FALSE, LsDoOneNamespaceObject,
424                 NULL, NULL);
425     return (Status);
426 }
427
428
429 /*******************************************************************************
430  *
431  * FUNCTION:    LsCompareOneNamespaceObject
432  *
433  * PARAMETERS:  ACPI_WALK_CALLBACK
434  *
435  * RETURN:      Status
436  *
437  * DESCRIPTION: Compare name of one object.
438  *
439  ******************************************************************************/
440
441 static ACPI_STATUS
442 LsCompareOneNamespaceObject (
443     ACPI_HANDLE             ObjHandle,
444     UINT32                  Level,
445     void                    *Context,
446     void                    **ReturnValue)
447 {
448     ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
449
450
451     /* Simply check the name */
452
453     if (*((UINT32 *) (Context)) == Node->Name.Integer)
454     {
455         /* Abort walk if we found one instance */
456
457         return (AE_CTRL_TRUE);
458     }
459
460     return (AE_OK);
461 }
462
463
464 /*******************************************************************************
465  *
466  * FUNCTION:    LkObjectExists
467  *
468  * PARAMETERS:  Name            - 4 char ACPI name
469  *
470  * RETURN:      TRUE if name exists in namespace
471  *
472  * DESCRIPTION: Walk the namespace to find an object
473  *
474  ******************************************************************************/
475
476 static BOOLEAN
477 LkObjectExists (
478     char                    *Name)
479 {
480     ACPI_STATUS             Status;
481
482
483     /* Walk entire namespace from the supplied root */
484
485     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
486                 ACPI_UINT32_MAX, FALSE, LsCompareOneNamespaceObject,
487                 Name, NULL);
488     if (Status == AE_CTRL_TRUE)
489     {
490         /* At least one instance of the name was found */
491
492         return (TRUE);
493     }
494
495     return (FALSE);
496 }
497
498
499 /*******************************************************************************
500  *
501  * FUNCTION:    LkCrossReferenceNamespace
502  *
503  * PARAMETERS:  None
504  *
505  * RETURN:      Status
506  *
507  * DESCRIPTION: Perform a cross reference check of the parse tree against the
508  *              namespace.  Every named referenced within the parse tree
509  *              should be get resolved with a namespace lookup.  If not, the
510  *              original reference in the ASL code is invalid -- i.e., refers
511  *              to a non-existent object.
512  *
513  * NOTE:  The ASL "External" operator causes the name to be inserted into the
514  *        namespace so that references to the external name will be resolved
515  *        correctly here.
516  *
517  ******************************************************************************/
518
519 ACPI_STATUS
520 LkCrossReferenceNamespace (
521     void)
522 {
523     ACPI_WALK_STATE         *WalkState;
524
525
526     DbgPrint (ASL_DEBUG_OUTPUT, "\nCross referencing namespace\n\n");
527
528     /*
529      * Create a new walk state for use when looking up names
530      * within the namespace (Passed as context to the callbacks)
531      */
532     WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
533     if (!WalkState)
534     {
535         return AE_NO_MEMORY;
536     }
537
538     /* Walk the entire parse tree */
539
540     TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE, LkNamespaceLocateBegin,
541                         LkNamespaceLocateEnd, WalkState);
542     return AE_OK;
543 }
544
545
546 /*******************************************************************************
547  *
548  * FUNCTION:    LkCheckFieldRange
549  *
550  * PARAMETERS:  RegionBitLength     - Length of entire parent region
551  *              FieldBitOffset      - Start of the field unit (within region)
552  *              FieldBitLength      - Entire length of field unit
553  *              AccessBitWidth      - Access width of the field unit
554  *
555  * RETURN:      None
556  *
557  * DESCRIPTION: Check one field unit to make sure it fits in the parent
558  *              op region.
559  *
560  * Note: AccessBitWidth must be either 8,16,32, or 64
561  *
562  ******************************************************************************/
563
564 static void
565 LkCheckFieldRange (
566     ACPI_PARSE_OBJECT       *Op,
567     UINT32                  RegionBitLength,
568     UINT32                  FieldBitOffset,
569     UINT32                  FieldBitLength,
570     UINT32                  AccessBitWidth)
571 {
572     UINT32                  FieldEndBitOffset;
573
574
575     /*
576      * Check each field unit against the region size.  The entire
577      * field unit (start offset plus length) must fit within the
578      * region.
579      */
580     FieldEndBitOffset = FieldBitOffset + FieldBitLength;
581
582     if (FieldEndBitOffset > RegionBitLength)
583     {
584         /* Field definition itself is beyond the end-of-region */
585
586         AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_OFFSET, Op, NULL);
587         return;
588     }
589
590     /*
591      * Now check that the field plus AccessWidth doesn't go beyond
592      * the end-of-region.  Assumes AccessBitWidth is a power of 2
593      */
594     FieldEndBitOffset = ACPI_ROUND_UP (FieldEndBitOffset, AccessBitWidth);
595
596     if (FieldEndBitOffset > RegionBitLength)
597     {
598         /* Field definition combined with the access is beyond EOR */
599
600         AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_ACCESS_WIDTH, Op, NULL);
601     }
602 }
603
604 /*******************************************************************************
605  *
606  * FUNCTION:    LkNamespaceLocateBegin
607  *
608  * PARAMETERS:  ASL_WALK_CALLBACK
609  *
610  * RETURN:      Status
611  *
612  * DESCRIPTION: Descending callback used during cross-reference.  For named
613  *              object references, attempt to locate the name in the
614  *              namespace.
615  *
616  * NOTE: ASL references to named fields within resource descriptors are
617  *       resolved to integer values here.  Therefore, this step is an
618  *       important part of the code generation.  We don't know that the
619  *       name refers to a resource descriptor until now.
620  *
621  ******************************************************************************/
622
623 static ACPI_STATUS
624 LkNamespaceLocateBegin (
625     ACPI_PARSE_OBJECT       *Op,
626     UINT32                  Level,
627     void                    *Context)
628 {
629     ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
630     ACPI_NAMESPACE_NODE     *Node;
631     ACPI_STATUS             Status;
632     ACPI_OBJECT_TYPE        ObjectType;
633     char                    *Path;
634     UINT8                   PassedArgs;
635     ACPI_PARSE_OBJECT       *NextOp;
636     ACPI_PARSE_OBJECT       *OwningOp;
637     ACPI_PARSE_OBJECT       *SpaceIdOp;
638     UINT32                  MinimumLength;
639     UINT32                  Temp;
640     const ACPI_OPCODE_INFO  *OpInfo;
641     UINT32                  Flags;
642
643
644     ACPI_FUNCTION_TRACE_PTR ("LkNamespaceLocateBegin", Op);
645
646     /*
647      * If this node is the actual declaration of a name
648      * [such as the XXXX name in "Method (XXXX)"],
649      * we are not interested in it here.  We only care about names that are
650      * references to other objects within the namespace and the parent objects
651      * of name declarations
652      */
653     if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)
654     {
655         return (AE_OK);
656     }
657
658     /* We are only interested in opcodes that have an associated name */
659
660     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
661
662     if ((!(OpInfo->Flags & AML_NAMED)) &&
663         (!(OpInfo->Flags & AML_CREATE)) &&
664         (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
665         (Op->Asl.ParseOpcode != PARSEOP_NAMESEG)    &&
666         (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
667     {
668         return (AE_OK);
669     }
670
671     /*
672      * We must enable the "search-to-root" for single NameSegs, but
673      * we have to be very careful about opening up scopes
674      */
675     Flags = ACPI_NS_SEARCH_PARENT;
676     if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
677         (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
678         (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
679     {
680         /*
681          * These are name references, do not push the scope stack
682          * for them.
683          */
684         Flags |= ACPI_NS_DONT_OPEN_SCOPE;
685     }
686
687     /* Get the NamePath from the appropriate place */
688
689     if (OpInfo->Flags & AML_NAMED)
690     {
691         /* For all NAMED operators, the name reference is the first child */
692
693         Path = Op->Asl.Child->Asl.Value.String;
694         if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
695         {
696             /*
697              * ALIAS is the only oddball opcode, the name declaration
698              * (alias name) is the second operand
699              */
700             Path = Op->Asl.Child->Asl.Next->Asl.Value.String;
701         }
702     }
703     else if (OpInfo->Flags & AML_CREATE)
704     {
705         /* Name must appear as the last parameter */
706
707         NextOp = Op->Asl.Child;
708         while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
709         {
710             NextOp = NextOp->Asl.Next;
711         }
712         Path = NextOp->Asl.Value.String;
713     }
714     else
715     {
716         Path = Op->Asl.Value.String;
717     }
718
719     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
720     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
721         "Type=%s\n", AcpiUtGetTypeName (ObjectType)));
722
723     /*
724      * Lookup the name in the namespace.  Name must exist at this point, or it
725      * is an invalid reference.
726      *
727      * The namespace is also used as a lookup table for references to resource
728      * descriptors and the fields within them.
729      */
730     Gbl_NsLookupCount++;
731
732     Status = AcpiNsLookup (WalkState->ScopeInfo,  Path, ObjectType,
733                 ACPI_IMODE_EXECUTE, Flags, WalkState, &(Node));
734     if (ACPI_FAILURE (Status))
735     {
736         if (Status == AE_NOT_FOUND)
737         {
738             /*
739              * We didn't find the name reference by path -- we can qualify this
740              * a little better before we print an error message
741              */
742             if (strlen (Path) == ACPI_NAME_SIZE)
743             {
744                 /* A simple, one-segment ACPI name */
745
746                 if (LkObjectExists (Path))
747                 {
748                     /*
749                      * There exists such a name, but we couldn't get to it
750                      * from this scope
751                      */
752                     AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op,
753                         Op->Asl.ExternalName);
754                 }
755                 else
756                 {
757                     /* The name doesn't exist, period */
758
759                     if ((Op->Asl.Parent) &&
760                         (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF))
761                     {
762                         /* Ignore not found if parent is CondRefOf */
763
764                         return (AE_OK);
765                     }
766
767                     AslError (ASL_ERROR, ASL_MSG_NOT_EXIST,
768                         Op, Op->Asl.ExternalName);
769                 }
770             }
771             else
772             {
773                 /* Check for a fully qualified path */
774
775                 if (Path[0] == AML_ROOT_PREFIX)
776                 {
777                     /* Gave full path, the object does not exist */
778
779                     if ((Op->Asl.Parent) &&
780                         (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF))
781                     {
782                         /* Ignore not found if parent is CondRefOf */
783
784                         return (AE_OK);
785                     }
786
787                     AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op,
788                         Op->Asl.ExternalName);
789                 }
790                 else
791                 {
792                     /*
793                      * We can't tell whether it doesn't exist or just
794                      * can't be reached.
795                      */
796                     AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op,
797                         Op->Asl.ExternalName);
798                 }
799             }
800
801             Status = AE_OK;
802         }
803         return (Status);
804     }
805
806     /* Attempt to optimize the NamePath */
807
808     OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node);
809
810     /*
811      * Dereference an alias. (A name reference that is an alias.)
812      * Aliases are not nested;  The alias always points to the final object
813      */
814     if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) &&
815         (Node->Type == ACPI_TYPE_LOCAL_ALIAS))
816     {
817         /* This node points back to the original PARSEOP_ALIAS */
818
819         NextOp = Node->Op;
820
821         /* The first child is the alias target op */
822
823         NextOp = NextOp->Asl.Child;
824
825         /* Who in turn points back to original target alias node */
826
827         if (NextOp->Asl.Node)
828         {
829             Node = NextOp->Asl.Node;
830         }
831         else
832         {
833             AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
834                 "Missing alias link");
835         }
836     }
837
838     /* 1) Check for a reference to a resource descriptor */
839
840     else if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
841              (Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
842     {
843         /*
844          * This was a reference to a field within a resource descriptor.  Extract
845          * the associated field offset (either a bit or byte offset depending on
846          * the field type) and change the named reference into an integer for
847          * AML code generation
848          */
849         Temp = Node->Value;
850         if (Node->Flags & ANOBJ_IS_BIT_OFFSET)
851         {
852             Op->Asl.CompileFlags |= NODE_IS_BIT_OFFSET;
853         }
854
855         /* Perform BitOffset <--> ByteOffset conversion if necessary */
856
857         switch (Op->Asl.Parent->Asl.AmlOpcode)
858         {
859         case AML_CREATE_FIELD_OP:
860
861             /* We allow a Byte offset to Bit Offset conversion for this op */
862
863             if (!(Op->Asl.CompileFlags & NODE_IS_BIT_OFFSET))
864             {
865                 /* Simply multiply byte offset times 8 to get bit offset */
866
867                 Temp = ACPI_MUL_8 (Temp);
868             }
869             break;
870
871
872         case AML_CREATE_BIT_FIELD_OP:
873
874             /* This op requires a Bit Offset */
875
876             if (!(Op->Asl.CompileFlags & NODE_IS_BIT_OFFSET))
877             {
878                 AslError (ASL_ERROR, ASL_MSG_BYTES_TO_BITS, Op, NULL);
879             }
880             break;
881
882
883         case AML_CREATE_BYTE_FIELD_OP:
884         case AML_CREATE_WORD_FIELD_OP:
885         case AML_CREATE_DWORD_FIELD_OP:
886         case AML_CREATE_QWORD_FIELD_OP:
887         case AML_INDEX_OP:
888
889             /* These Ops require Byte offsets */
890
891             if (Op->Asl.CompileFlags & NODE_IS_BIT_OFFSET)
892             {
893                 AslError (ASL_ERROR, ASL_MSG_BITS_TO_BYTES, Op, NULL);
894             }
895             break;
896
897
898         default:
899             /* Nothing to do for other opcodes */
900             break;
901         }
902
903         /* Now convert this node to an integer whose value is the field offset */
904
905         Op->Asl.AmlLength       = 0;
906         Op->Asl.ParseOpcode     = PARSEOP_INTEGER;
907         Op->Asl.Value.Integer   = (UINT64) Temp;
908         Op->Asl.CompileFlags   |= NODE_IS_RESOURCE_FIELD;
909
910         OpcGenerateAmlOpcode (Op);
911     }
912
913     /* 2) Check for a method invocation */
914
915     else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) &&
916                 (Node->Type == ACPI_TYPE_METHOD) &&
917                 (Op->Asl.Parent) &&
918                 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD))   ||
919
920                 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
921     {
922
923         /*
924          * A reference to a method within one of these opcodes is not an
925          * invocation of the method, it is simply a reference to the method.
926          */
927         if ((Op->Asl.Parent) &&
928            ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF)      ||
929             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEREFOF)    ||
930             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE)))
931         {
932             return (AE_OK);
933         }
934         /*
935          * There are two types of method invocation:
936          * 1) Invocation with arguments -- the parser recognizes this
937          *    as a METHODCALL.
938          * 2) Invocation with no arguments --the parser cannot determine that
939          *    this is a method invocation, therefore we have to figure it out
940          *    here.
941          */
942         if (Node->Type != ACPI_TYPE_METHOD)
943         {
944             sprintf (MsgBuffer, "%s is a %s",
945                     Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type));
946
947             AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, MsgBuffer);
948             return (AE_OK);
949         }
950
951         /* Save the method node in the caller's op */
952
953         Op->Asl.Node = Node;
954         if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)
955         {
956             return (AE_OK);
957         }
958
959         /*
960          * This is a method invocation, with or without arguments.
961          * Count the number of arguments, each appears as a child
962          * under the parent node
963          */
964         Op->Asl.ParseOpcode = PARSEOP_METHODCALL;
965         UtSetParseOpName (Op);
966
967         PassedArgs = 0;
968         NextOp     = Op->Asl.Child;
969
970         while (NextOp)
971         {
972             PassedArgs++;
973             NextOp = NextOp->Asl.Next;
974         }
975
976         if (Node->Value != ASL_EXTERNAL_METHOD)
977         {
978             /*
979              * Check the parsed arguments with the number expected by the
980              * method declaration itself
981              */
982             if (PassedArgs != Node->Value)
983             {
984                 sprintf (MsgBuffer, "%s requires %d", Op->Asl.ExternalName,
985                             Node->Value);
986
987                 if (PassedArgs < Node->Value)
988                 {
989                     AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, MsgBuffer);
990                 }
991                 else
992                 {
993                     AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, MsgBuffer);
994                 }
995             }
996         }
997     }
998
999     /* 3) Check for an ASL Field definition */
1000
1001     else if ((Op->Asl.Parent) &&
1002             ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD)     ||
1003              (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD)))
1004     {
1005         /*
1006          * Offset checking for fields.  If the parent operation region has a
1007          * constant length (known at compile time), we can check fields
1008          * defined in that region against the region length.  This will catch
1009          * fields and field units that cannot possibly fit within the region.
1010          *
1011          * Note: Index fields do not directly reference an operation region,
1012          * thus they are not included in this check.
1013          */
1014         if (Op == Op->Asl.Parent->Asl.Child)
1015         {
1016             /*
1017              * This is the first child of the field node, which is
1018              * the name of the region.  Get the parse node for the
1019              * region -- which contains the length of the region.
1020              */
1021             OwningOp = Node->Op;
1022             Op->Asl.Parent->Asl.ExtraValue =
1023                 ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer);
1024
1025             /* Examine the field access width */
1026
1027             switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer)
1028             {
1029             case AML_FIELD_ACCESS_ANY:
1030             case AML_FIELD_ACCESS_BYTE:
1031             case AML_FIELD_ACCESS_BUFFER:
1032             default:
1033                 MinimumLength = 1;
1034                 break;
1035
1036             case AML_FIELD_ACCESS_WORD:
1037                 MinimumLength = 2;
1038                 break;
1039
1040             case AML_FIELD_ACCESS_DWORD:
1041                 MinimumLength = 4;
1042                 break;
1043
1044             case AML_FIELD_ACCESS_QWORD:
1045                 MinimumLength = 8;
1046                 break;
1047             }
1048
1049             /*
1050              * Is the region at least as big as the access width?
1051              * Note: DataTableRegions have 0 length
1052              */
1053             if (((UINT32) OwningOp->Asl.Value.Integer) &&
1054                 ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength))
1055             {
1056                 AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL);
1057             }
1058
1059             /*
1060              * Check EC/CMOS/SMBUS fields to make sure that the correct
1061              * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS)
1062              */
1063             SpaceIdOp = OwningOp->Asl.Child->Asl.Next;
1064             switch ((UINT32) SpaceIdOp->Asl.Value.Integer)
1065             {
1066             case REGION_EC:
1067             case REGION_CMOS:
1068
1069                 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BYTE)
1070                 {
1071                     AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL);
1072                 }
1073                 break;
1074
1075             case REGION_SMBUS:
1076
1077                 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BUFFER)
1078                 {
1079                     AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL);
1080                 }
1081                 break;
1082
1083             default:
1084
1085                 /* Nothing to do for other address spaces */
1086                 break;
1087             }
1088         }
1089         else
1090         {
1091             /*
1092              * This is one element of the field list.  Check to make sure
1093              * that it does not go beyond the end of the parent operation region.
1094              *
1095              * In the code below:
1096              *    Op->Asl.Parent->Asl.ExtraValue      - Region Length (bits)
1097              *    Op->Asl.ExtraValue                  - Field start offset (bits)
1098              *    Op->Asl.Child->Asl.Value.Integer32  - Field length (bits)
1099              *    Op->Asl.Child->Asl.ExtraValue       - Field access width (bits)
1100              */
1101             if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child)
1102             {
1103                 LkCheckFieldRange (Op,
1104                             Op->Asl.Parent->Asl.ExtraValue,
1105                             Op->Asl.ExtraValue,
1106                             (UINT32) Op->Asl.Child->Asl.Value.Integer,
1107                             Op->Asl.Child->Asl.ExtraValue);
1108             }
1109         }
1110     }
1111
1112     Op->Asl.Node = Node;
1113     return (Status);
1114 }
1115
1116
1117 /*******************************************************************************
1118  *
1119  * FUNCTION:    LkNamespaceLocateEnd
1120  *
1121  * PARAMETERS:  ASL_WALK_CALLBACK
1122  *
1123  * RETURN:      Status
1124  *
1125  * DESCRIPTION: Ascending callback used during cross reference.  We only
1126  *              need to worry about scope management here.
1127  *
1128  ******************************************************************************/
1129
1130 static ACPI_STATUS
1131 LkNamespaceLocateEnd (
1132     ACPI_PARSE_OBJECT       *Op,
1133     UINT32                  Level,
1134     void                    *Context)
1135 {
1136     ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
1137     const ACPI_OPCODE_INFO  *OpInfo;
1138
1139
1140     ACPI_FUNCTION_TRACE ("LkNamespaceLocateEnd");
1141
1142
1143     /* We are only interested in opcodes that have an associated name */
1144
1145     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
1146     if (!(OpInfo->Flags & AML_NAMED))
1147     {
1148         return (AE_OK);
1149     }
1150
1151     /* Not interested in name references, we did not open a scope for them */
1152
1153     if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
1154         (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
1155         (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
1156     {
1157         return (AE_OK);
1158     }
1159
1160     /* Pop the scope stack if necessary */
1161
1162     if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode)))
1163     {
1164
1165         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
1166             "%s: Popping scope for Op %p\n",
1167             AcpiUtGetTypeName (OpInfo->ObjectType), Op));
1168
1169         (void) AcpiDsScopeStackPop (WalkState);
1170     }
1171
1172     return (AE_OK);
1173 }
1174
1175