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