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