asllookup.c revision 118611
1118611Snjl/******************************************************************************
2118611Snjl *
3118611Snjl * Module Name: asllookup- Namespace lookup
4118611Snjl *              $Revision: 82 $
5118611Snjl *
6118611Snjl *****************************************************************************/
7118611Snjl
8118611Snjl/******************************************************************************
9118611Snjl *
10118611Snjl * 1. Copyright Notice
11118611Snjl *
12118611Snjl * Some or all of this work - Copyright (c) 1999 - 2003, Intel Corp.
13118611Snjl * All rights reserved.
14118611Snjl *
15118611Snjl * 2. License
16118611Snjl *
17118611Snjl * 2.1. This is your license from Intel Corp. under its intellectual property
18118611Snjl * rights.  You may have additional license terms from the party that provided
19118611Snjl * you this software, covering your right to use that party's intellectual
20118611Snjl * property rights.
21118611Snjl *
22118611Snjl * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23118611Snjl * copy of the source code appearing in this file ("Covered Code") an
24118611Snjl * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25118611Snjl * base code distributed originally by Intel ("Original Intel Code") to copy,
26118611Snjl * make derivatives, distribute, use and display any portion of the Covered
27118611Snjl * Code in any form, with the right to sublicense such rights; and
28118611Snjl *
29118611Snjl * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30118611Snjl * license (with the right to sublicense), under only those claims of Intel
31118611Snjl * patents that are infringed by the Original Intel Code, to make, use, sell,
32118611Snjl * offer to sell, and import the Covered Code and derivative works thereof
33118611Snjl * solely to the minimum extent necessary to exercise the above copyright
34118611Snjl * license, and in no event shall the patent license extend to any additions
35118611Snjl * to or modifications of the Original Intel Code.  No other license or right
36118611Snjl * is granted directly or by implication, estoppel or otherwise;
37118611Snjl *
38118611Snjl * The above copyright and patent license is granted only if the following
39118611Snjl * conditions are met:
40118611Snjl *
41118611Snjl * 3. Conditions
42118611Snjl *
43118611Snjl * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44118611Snjl * Redistribution of source code of any substantial portion of the Covered
45118611Snjl * Code or modification with rights to further distribute source must include
46118611Snjl * the above Copyright Notice, the above License, this list of Conditions,
47118611Snjl * and the following Disclaimer and Export Compliance provision.  In addition,
48118611Snjl * Licensee must cause all Covered Code to which Licensee contributes to
49118611Snjl * contain a file documenting the changes Licensee made to create that Covered
50118611Snjl * Code and the date of any change.  Licensee must include in that file the
51118611Snjl * documentation of any changes made by any predecessor Licensee.  Licensee
52118611Snjl * must include a prominent statement that the modification is derived,
53118611Snjl * directly or indirectly, from Original Intel Code.
54118611Snjl *
55118611Snjl * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56118611Snjl * Redistribution of source code of any substantial portion of the Covered
57118611Snjl * Code or modification without rights to further distribute source must
58118611Snjl * include the following Disclaimer and Export Compliance provision in the
59118611Snjl * documentation and/or other materials provided with distribution.  In
60118611Snjl * addition, Licensee may not authorize further sublicense of source of any
61118611Snjl * portion of the Covered Code, and must include terms to the effect that the
62118611Snjl * license from Licensee to its licensee is limited to the intellectual
63118611Snjl * property embodied in the software Licensee provides to its licensee, and
64118611Snjl * not to intellectual property embodied in modifications its licensee may
65118611Snjl * make.
66118611Snjl *
67118611Snjl * 3.3. Redistribution of Executable. Redistribution in executable form of any
68118611Snjl * substantial portion of the Covered Code or modification must reproduce the
69118611Snjl * above Copyright Notice, and the following Disclaimer and Export Compliance
70118611Snjl * provision in the documentation and/or other materials provided with the
71118611Snjl * distribution.
72118611Snjl *
73118611Snjl * 3.4. Intel retains all right, title, and interest in and to the Original
74118611Snjl * Intel Code.
75118611Snjl *
76118611Snjl * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77118611Snjl * Intel shall be used in advertising or otherwise to promote the sale, use or
78118611Snjl * other dealings in products derived from or relating to the Covered Code
79118611Snjl * without prior written authorization from Intel.
80118611Snjl *
81118611Snjl * 4. Disclaimer and Export Compliance
82118611Snjl *
83118611Snjl * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84118611Snjl * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85118611Snjl * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86118611Snjl * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87118611Snjl * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88118611Snjl * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89118611Snjl * PARTICULAR PURPOSE.
90118611Snjl *
91118611Snjl * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92118611Snjl * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93118611Snjl * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94118611Snjl * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95118611Snjl * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96118611Snjl * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97118611Snjl * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98118611Snjl * LIMITED REMEDY.
99118611Snjl *
100118611Snjl * 4.3. Licensee shall not export, either directly or indirectly, any of this
101118611Snjl * software or system incorporating such software without first obtaining any
102118611Snjl * required license or other approval from the U. S. Department of Commerce or
103118611Snjl * any other agency or department of the United States Government.  In the
104118611Snjl * event Licensee exports any such software from the United States or
105118611Snjl * re-exports any such software from a foreign destination, Licensee shall
106118611Snjl * ensure that the distribution and export/re-export of the software is in
107118611Snjl * compliance with all laws, regulations, orders, or other restrictions of the
108118611Snjl * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109118611Snjl * any of its subsidiaries will export/re-export any technical data, process,
110118611Snjl * software, or service, directly or indirectly, to any country for which the
111118611Snjl * United States government or any agency thereof requires an export license,
112118611Snjl * other governmental approval, or letter of assurance, without first obtaining
113118611Snjl * such license, approval or letter.
114118611Snjl *
115118611Snjl *****************************************************************************/
116118611Snjl
117118611Snjl
118118611Snjl#include "aslcompiler.h"
119118611Snjl#include "aslcompiler.y.h"
120118611Snjl
121118611Snjl#include "acparser.h"
122118611Snjl#include "amlcode.h"
123118611Snjl#include "acnamesp.h"
124118611Snjl#include "acdispat.h"
125118611Snjl
126118611Snjl
127118611Snjl#define _COMPONENT          ACPI_COMPILER
128118611Snjl        ACPI_MODULE_NAME    ("asllookup")
129118611Snjl
130118611Snjl
131118611Snjl/*******************************************************************************
132118611Snjl *
133118611Snjl * FUNCTION:    LsDoOneNamespaceObject
134118611Snjl *
135118611Snjl * PARAMETERS:  ACPI_WALK_CALLBACK
136118611Snjl *
137118611Snjl * RETURN:      Status
138118611Snjl *
139118611Snjl * DESCRIPTION: Dump a namespace object to the namespace output file.
140118611Snjl *              Called during the walk of the namespace to dump all objects.
141118611Snjl *
142118611Snjl ******************************************************************************/
143118611Snjl
144118611SnjlACPI_STATUS
145118611SnjlLsDoOneNamespaceObject (
146118611Snjl    ACPI_HANDLE             ObjHandle,
147118611Snjl    UINT32                  Level,
148118611Snjl    void                    *Context,
149118611Snjl    void                    **ReturnValue)
150118611Snjl{
151118611Snjl    ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
152118611Snjl    ACPI_PARSE_OBJECT       *Op;
153118611Snjl
154118611Snjl
155118611Snjl    Gbl_NumNamespaceObjects++;
156118611Snjl
157118611Snjl    FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "%5d  [%d]  %*s %4.4s - %s",
158118611Snjl                        Gbl_NumNamespaceObjects, Level, (Level * 3), " ",
159118611Snjl                        &Node->Name,
160118611Snjl                        AcpiUtGetTypeName (Node->Type));
161118611Snjl
162118611Snjl    Op = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Node->Object);
163118611Snjl
164118611Snjl    if (Op)
165118611Snjl    {
166118611Snjl        if (Op->Asl.ParseOpcode == PARSEOP_NAME)
167118611Snjl        {
168118611Snjl            Op = Op->Asl.Child;
169118611Snjl        }
170118611Snjl
171118611Snjl        switch (Node->Type)
172118611Snjl        {
173118611Snjl        case ACPI_TYPE_INTEGER:
174118611Snjl
175118611Snjl            if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG)  ||
176118611Snjl                (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
177118611Snjl            {
178118611Snjl                Op = Op->Asl.Next;
179118611Snjl            }
180118611Snjl
181118611Snjl            if (Op->Asl.Value.Integer > ACPI_UINT32_MAX)
182118611Snjl            {
183118611Snjl                FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "    [Initial Value = 0x%X%X]",
184118611Snjl                            ACPI_HIDWORD (Op->Asl.Value.Integer64), (UINT32) Op->Asl.Value.Integer);
185118611Snjl            }
186118611Snjl            else
187118611Snjl            {
188118611Snjl                FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "    [Initial Value = 0x%X]",
189118611Snjl                            (UINT32) Op->Asl.Value.Integer);
190118611Snjl            }
191118611Snjl            break;
192118611Snjl
193118611Snjl
194118611Snjl        case ACPI_TYPE_STRING:
195118611Snjl
196118611Snjl            if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG)  ||
197118611Snjl                (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
198118611Snjl            {
199118611Snjl                Op = Op->Asl.Next;
200118611Snjl            }
201118611Snjl
202118611Snjl            FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "    [Initial Value = \"%s\"]",
203118611Snjl                        Op->Asl.Value.String);
204118611Snjl            break;
205118611Snjl
206118611Snjl
207118611Snjl        case ACPI_TYPE_LOCAL_REGION_FIELD:
208118611Snjl
209118611Snjl            if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG)  ||
210118611Snjl                (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
211118611Snjl            {
212118611Snjl                Op = Op->Asl.Child;
213118611Snjl            }
214118611Snjl            FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "    [Offset 0x%02X, Length 0x%02X]",
215118611Snjl                        Op->Asl.Parent->Asl.ExtraValue, (UINT32) Op->Asl.Value.Integer);
216118611Snjl            break;
217118611Snjl
218118611Snjl
219118611Snjl        default:
220118611Snjl            /* Nothing to do for other types */
221118611Snjl            break;
222118611Snjl        }
223118611Snjl    }
224118611Snjl
225118611Snjl    FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\n");
226118611Snjl    return (AE_OK);
227118611Snjl}
228118611Snjl
229118611Snjl
230118611Snjl/*******************************************************************************
231118611Snjl *
232118611Snjl * FUNCTION:    LsDisplayNamespace
233118611Snjl *
234118611Snjl * PARAMETERS:  None
235118611Snjl *
236118611Snjl * RETURN:      None
237118611Snjl *
238118611Snjl * DESCRIPTION: Walk the namespace an display information about each node
239118611Snjl *              in the tree.  Information is written to the optional
240118611Snjl *              namespace output file.
241118611Snjl *
242118611Snjl ******************************************************************************/
243118611Snjl
244118611SnjlACPI_STATUS
245118611SnjlLsDisplayNamespace (
246118611Snjl    void)
247118611Snjl{
248118611Snjl    ACPI_STATUS             Status;
249118611Snjl
250118611Snjl
251118611Snjl    if (!Gbl_NsOutputFlag)
252118611Snjl    {
253118611Snjl        return (AE_OK);
254118611Snjl    }
255118611Snjl
256118611Snjl    /* File header */
257118611Snjl
258118611Snjl    FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "Contents of ACPI Namespace\n\n");
259118611Snjl    FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "Count  Depth    Name - Type\n\n");
260118611Snjl
261118611Snjl    /* Walk entire namespace from the root */
262118611Snjl
263118611Snjl    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
264118611Snjl                                ACPI_UINT32_MAX, FALSE, LsDoOneNamespaceObject,
265118611Snjl                                NULL, NULL);
266118611Snjl    return (Status);
267118611Snjl}
268118611Snjl
269118611Snjl
270118611Snjl/*******************************************************************************
271118611Snjl *
272118611Snjl * FUNCTION:    LsCompareOneNamespaceObject
273118611Snjl *
274118611Snjl * PARAMETERS:  ACPI_WALK_CALLBACK
275118611Snjl *
276118611Snjl * RETURN:      Status
277118611Snjl *
278118611Snjl * DESCRIPTION: Compare name of one object.
279118611Snjl *
280118611Snjl ******************************************************************************/
281118611Snjl
282118611SnjlACPI_STATUS
283118611SnjlLsCompareOneNamespaceObject (
284118611Snjl    ACPI_HANDLE             ObjHandle,
285118611Snjl    UINT32                  Level,
286118611Snjl    void                    *Context,
287118611Snjl    void                    **ReturnValue)
288118611Snjl{
289118611Snjl    ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
290118611Snjl
291118611Snjl
292118611Snjl    /* Simply check the name */
293118611Snjl
294118611Snjl    if (*((UINT32 *) (Context)) == Node->Name.Integer)
295118611Snjl    {
296118611Snjl        /* Abort walk if we found one instance */
297118611Snjl
298118611Snjl        return (AE_CTRL_TRUE);
299118611Snjl    }
300118611Snjl
301118611Snjl    return (AE_OK);
302118611Snjl}
303118611Snjl
304118611Snjl
305118611Snjl/*******************************************************************************
306118611Snjl *
307118611Snjl * FUNCTION:    LkObjectExists
308118611Snjl *
309118611Snjl * PARAMETERS:  Name            - 4 char ACPI name
310118611Snjl *
311118611Snjl * RETURN:      TRUE if name exists in namespace
312118611Snjl *
313118611Snjl * DESCRIPTION: Walk the namespace to find an object
314118611Snjl *
315118611Snjl ******************************************************************************/
316118611Snjl
317118611SnjlBOOLEAN
318118611SnjlLkObjectExists (
319118611Snjl    char                    *Name)
320118611Snjl{
321118611Snjl    ACPI_STATUS             Status;
322118611Snjl
323118611Snjl
324118611Snjl    /* Walk entire namespace from the supplied root */
325118611Snjl
326118611Snjl    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
327118611Snjl                                ACPI_UINT32_MAX, FALSE, LsCompareOneNamespaceObject,
328118611Snjl                                Name, NULL);
329118611Snjl    if (Status == AE_CTRL_TRUE)
330118611Snjl    {
331118611Snjl        /* At least one instance of the name was found */
332118611Snjl
333118611Snjl        return (TRUE);
334118611Snjl    }
335118611Snjl
336118611Snjl    return (FALSE);
337118611Snjl}
338118611Snjl
339118611Snjl
340118611Snjl/*******************************************************************************
341118611Snjl *
342118611Snjl * FUNCTION:    LkCrossReferenceNamespace
343118611Snjl *
344118611Snjl * PARAMETERS:  None
345118611Snjl *
346118611Snjl * RETURN:      Status
347118611Snjl *
348118611Snjl * DESCRIPTION: Perform a cross reference check of the parse tree against the
349118611Snjl *              namespace.  Every named referenced within the parse tree
350118611Snjl *              should be get resolved with a namespace lookup.  If not, the
351118611Snjl *              original reference in the ASL code is invalid -- i.e., refers
352118611Snjl *              to a non-existent object.
353118611Snjl *
354118611Snjl * NOTE:  The ASL "External" operator causes the name to be inserted into the
355118611Snjl *        namespace so that references to the external name will be resolved
356118611Snjl *        correctly here.
357118611Snjl *
358118611Snjl ******************************************************************************/
359118611Snjl
360118611SnjlACPI_STATUS
361118611SnjlLkCrossReferenceNamespace (
362118611Snjl    void)
363118611Snjl{
364118611Snjl    ACPI_WALK_STATE         *WalkState;
365118611Snjl
366118611Snjl
367118611Snjl    DbgPrint (ASL_DEBUG_OUTPUT, "\nCross referencing namespace\n\n");
368118611Snjl
369118611Snjl    /*
370118611Snjl     * Create a new walk state for use when looking up names
371118611Snjl     * within the namespace (Passed as context to the callbacks)
372118611Snjl     */
373118611Snjl    WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
374118611Snjl    if (!WalkState)
375118611Snjl    {
376118611Snjl        return AE_NO_MEMORY;
377118611Snjl    }
378118611Snjl
379118611Snjl    /* Walk the entire parse tree */
380118611Snjl
381118611Snjl    TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE, LkNamespaceLocateBegin,
382118611Snjl                        LkNamespaceLocateEnd, WalkState);
383118611Snjl    return AE_OK;
384118611Snjl}
385118611Snjl
386118611Snjl
387118611Snjl/*******************************************************************************
388118611Snjl *
389118611Snjl * FUNCTION:    LkCheckFieldRange
390118611Snjl *
391118611Snjl * PARAMETERS:  RegionBitLength     - Length of entire parent region
392118611Snjl *              FieldBitOffset      - Start of the field unit (within region)
393118611Snjl *              FieldBitLength      - Entire length of field unit
394118611Snjl *              AccessBitWidth      - Access width of the field unit
395118611Snjl *
396118611Snjl * RETURN:      None
397118611Snjl *
398118611Snjl * DESCRIPTION: Check one field unit to make sure it fits in the parent
399118611Snjl *              op region.
400118611Snjl *
401118611Snjl * Note: AccessBitWidth must be either 8,16,32, or 64
402118611Snjl *
403118611Snjl ******************************************************************************/
404118611Snjl
405118611Snjlvoid
406118611SnjlLkCheckFieldRange (
407118611Snjl    ACPI_PARSE_OBJECT       *Op,
408118611Snjl    UINT32                  RegionBitLength,
409118611Snjl    UINT32                  FieldBitOffset,
410118611Snjl    UINT32                  FieldBitLength,
411118611Snjl    UINT32                  AccessBitWidth)
412118611Snjl{
413118611Snjl    UINT32                  FieldEndBitOffset;
414118611Snjl
415118611Snjl    /*
416118611Snjl     * Check each field unit against the region size.  The entire
417118611Snjl     * field unit (start offset plus length) must fit within the
418118611Snjl     * region.
419118611Snjl     */
420118611Snjl    FieldEndBitOffset = FieldBitOffset + FieldBitLength;
421118611Snjl
422118611Snjl    if (FieldEndBitOffset > RegionBitLength)
423118611Snjl    {
424118611Snjl        /* Field definition itself is beyond the end-of-region */
425118611Snjl
426118611Snjl        AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_OFFSET, Op, NULL);
427118611Snjl        return;
428118611Snjl    }
429118611Snjl
430118611Snjl    /*
431118611Snjl     * Now check that the field plus AccessWidth doesn't go beyond
432118611Snjl     * the end-of-region.  Assumes AccessBitWidth is a power of 2
433118611Snjl     */
434118611Snjl    FieldEndBitOffset = ACPI_ROUND_UP (FieldEndBitOffset, AccessBitWidth);
435118611Snjl
436118611Snjl    if (FieldEndBitOffset > RegionBitLength)
437118611Snjl    {
438118611Snjl        /* Field definition combined with the access is beyond EOR */
439118611Snjl
440118611Snjl        AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_ACCESS_WIDTH, Op, NULL);
441118611Snjl    }
442118611Snjl}
443118611Snjl
444118611Snjl/*******************************************************************************
445118611Snjl *
446118611Snjl * FUNCTION:    LkNamespaceLocateBegin
447118611Snjl *
448118611Snjl * PARAMETERS:  ASL_WALK_CALLBACK
449118611Snjl *
450118611Snjl * RETURN:      Status
451118611Snjl *
452118611Snjl * DESCRIPTION: Descending callback used during cross-reference.  For named
453118611Snjl *              object references, attempt to locate the name in the
454118611Snjl *              namespace.
455118611Snjl *
456118611Snjl * NOTE: ASL references to named fields within resource descriptors are
457118611Snjl *       resolved to integer values here.  Therefore, this step is an
458118611Snjl *       important part of the code generation.  We don't know that the
459118611Snjl *       name refers to a resource descriptor until now.
460118611Snjl *
461118611Snjl ******************************************************************************/
462118611Snjl
463118611SnjlACPI_STATUS
464118611SnjlLkNamespaceLocateBegin (
465118611Snjl    ACPI_PARSE_OBJECT       *Op,
466118611Snjl    UINT32                  Level,
467118611Snjl    void                    *Context)
468118611Snjl{
469118611Snjl    ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
470118611Snjl    ACPI_NAMESPACE_NODE     *Node;
471118611Snjl    ACPI_STATUS             Status;
472118611Snjl    ACPI_OBJECT_TYPE        ObjectType;
473118611Snjl    char                    *Path;
474118611Snjl    UINT8                   PassedArgs;
475118611Snjl    ACPI_PARSE_OBJECT       *NextOp;
476118611Snjl    ACPI_PARSE_OBJECT       *OwningOp;
477118611Snjl    ACPI_PARSE_OBJECT       *SpaceIdOp;
478118611Snjl    UINT32                  MinimumLength;
479118611Snjl    UINT32                  Temp;
480118611Snjl    const ACPI_OPCODE_INFO  *OpInfo;
481118611Snjl    UINT32                  Flags;
482118611Snjl
483118611Snjl
484118611Snjl    ACPI_FUNCTION_TRACE_PTR ("LkNamespaceLocateBegin", Op);
485118611Snjl
486118611Snjl    /*
487118611Snjl     * If this node is the actual declaration of a name
488118611Snjl     * [such as the XXXX name in "Method (XXXX)"],
489118611Snjl     * we are not interested in it here.  We only care about names that are
490118611Snjl     * references to other objects within the namespace and the parent objects
491118611Snjl     * of name declarations
492118611Snjl     */
493118611Snjl    if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)
494118611Snjl    {
495118611Snjl        return (AE_OK);
496118611Snjl    }
497118611Snjl
498118611Snjl    /* We are only interested in opcodes that have an associated name */
499118611Snjl
500118611Snjl    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
501118611Snjl
502118611Snjl    if ((!(OpInfo->Flags & AML_NAMED)) &&
503118611Snjl        (!(OpInfo->Flags & AML_CREATE)) &&
504118611Snjl        (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
505118611Snjl        (Op->Asl.ParseOpcode != PARSEOP_NAMESEG)    &&
506118611Snjl        (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
507118611Snjl    {
508118611Snjl        return (AE_OK);
509118611Snjl    }
510118611Snjl
511118611Snjl    /*
512118611Snjl     * We must enable the "search-to-root" for single NameSegs, but
513118611Snjl     * we have to be very careful about opening up scopes
514118611Snjl     */
515118611Snjl    Flags = ACPI_NS_SEARCH_PARENT;
516118611Snjl    if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
517118611Snjl        (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
518118611Snjl        (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
519118611Snjl    {
520118611Snjl        /*
521118611Snjl         * These are name references, do not push the scope stack
522118611Snjl         * for them.
523118611Snjl         */
524118611Snjl        Flags |= ACPI_NS_DONT_OPEN_SCOPE;
525118611Snjl    }
526118611Snjl
527118611Snjl    /* Get the NamePath from the appropriate place */
528118611Snjl
529118611Snjl    if (OpInfo->Flags & AML_NAMED)
530118611Snjl    {
531118611Snjl        /* For all NAMED operators, the name reference is the first child */
532118611Snjl
533118611Snjl        Path = Op->Asl.Child->Asl.Value.String;
534118611Snjl        if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
535118611Snjl        {
536118611Snjl            /*
537118611Snjl             * ALIAS is the only oddball opcode, the name declaration
538118611Snjl             * (alias name) is the second operand
539118611Snjl             */
540118611Snjl            Path = Op->Asl.Child->Asl.Next->Asl.Value.String;
541118611Snjl        }
542118611Snjl    }
543118611Snjl    else if (OpInfo->Flags & AML_CREATE)
544118611Snjl    {
545118611Snjl        /* Name must appear as the last parameter */
546118611Snjl
547118611Snjl        NextOp = Op->Asl.Child;
548118611Snjl        while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
549118611Snjl        {
550118611Snjl            NextOp = NextOp->Asl.Next;
551118611Snjl        }
552118611Snjl        Path = NextOp->Asl.Value.String;
553118611Snjl    }
554118611Snjl    else
555118611Snjl    {
556118611Snjl        Path = Op->Asl.Value.String;
557118611Snjl    }
558118611Snjl
559118611Snjl    ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
560118611Snjl    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Type=%s\n", AcpiUtGetTypeName (ObjectType)));
561118611Snjl
562118611Snjl    /*
563118611Snjl     * Lookup the name in the namespace.  Name must exist at this point, or it
564118611Snjl     * is an invalid reference.
565118611Snjl     *
566118611Snjl     * The namespace is also used as a lookup table for references to resource
567118611Snjl     * descriptors and the fields within them.
568118611Snjl     */
569118611Snjl    Gbl_NsLookupCount++;
570118611Snjl
571118611Snjl    Status = AcpiNsLookup (WalkState->ScopeInfo,  Path, ObjectType,
572118611Snjl                    ACPI_IMODE_EXECUTE, Flags, WalkState, &(Node));
573118611Snjl    if (ACPI_FAILURE (Status))
574118611Snjl    {
575118611Snjl        if (Status == AE_NOT_FOUND)
576118611Snjl        {
577118611Snjl            /*
578118611Snjl             * We didn't find the name reference by path -- we can qualify this
579118611Snjl             * a little better before we print an error message
580118611Snjl             */
581118611Snjl            if (strlen (Path) == ACPI_NAME_SIZE)
582118611Snjl            {
583118611Snjl                /* A simple, one-segment ACPI name */
584118611Snjl
585118611Snjl                if (LkObjectExists (Path))
586118611Snjl                {
587118611Snjl                    /* There exists such a name, but we couldn't get to it from this scope */
588118611Snjl
589118611Snjl                    AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op, Op->Asl.ExternalName);
590118611Snjl                }
591118611Snjl                else
592118611Snjl                {
593118611Snjl                    /* The name doesn't exist, period */
594118611Snjl
595118611Snjl                    AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op, Op->Asl.ExternalName);
596118611Snjl                }
597118611Snjl            }
598118611Snjl            else
599118611Snjl            {
600118611Snjl                /* Check for a fully qualified path */
601118611Snjl
602118611Snjl                if (Path[0] == AML_ROOT_PREFIX)
603118611Snjl                {
604118611Snjl                    /* Gave full path, the object does not exist */
605118611Snjl
606118611Snjl                    AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op, Op->Asl.ExternalName);
607118611Snjl                }
608118611Snjl                else
609118611Snjl                {
610118611Snjl                    /* We can't tell whether it doesn't exist or just can't be reached. */
611118611Snjl
612118611Snjl                    AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, Op->Asl.ExternalName);
613118611Snjl                }
614118611Snjl            }
615118611Snjl
616118611Snjl            Status = AE_OK;
617118611Snjl        }
618118611Snjl        return (Status);
619118611Snjl    }
620118611Snjl
621118611Snjl    /* Attempt to optimize the NamePath */
622118611Snjl
623118611Snjl    OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node);
624118611Snjl
625118611Snjl    /*
626118611Snjl     * Dereference an alias. (A name reference that is an alias.)
627118611Snjl     * Aliases are not nested;  The alias always points to the final object
628118611Snjl     */
629118611Snjl    if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) && (Node->Type == ACPI_TYPE_LOCAL_ALIAS))
630118611Snjl    {
631118611Snjl        /* This node points back to the original PARSEOP_ALIAS */
632118611Snjl
633118611Snjl        NextOp = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Node->Object);
634118611Snjl
635118611Snjl        /* The first child is the alias target op */
636118611Snjl
637118611Snjl        NextOp = NextOp->Asl.Child;
638118611Snjl
639118611Snjl        /* Who in turn points back to original target alias node */
640118611Snjl
641118611Snjl        if (NextOp->Asl.Node)
642118611Snjl        {
643118611Snjl            Node = NextOp->Asl.Node;
644118611Snjl        }
645118611Snjl        else
646118611Snjl        {
647118611Snjl            AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, "Missing alias link");
648118611Snjl        }
649118611Snjl    }
650118611Snjl
651118611Snjl    /* 1) Check for a reference to a resource descriptor */
652118611Snjl
653118611Snjl    else if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
654118611Snjl             (Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
655118611Snjl    {
656118611Snjl        /*
657118611Snjl         * This was a reference to a field within a resource descriptor.  Extract
658118611Snjl         * the associated field offset (either a bit or byte offset depending on
659118611Snjl         * the field type) and change the named reference into an integer for
660118611Snjl         * AML code generation
661118611Snjl         */
662118611Snjl        Temp = (UINT32) Node->OwnerId;
663118611Snjl        if (Node->Flags & ANOBJ_IS_BIT_OFFSET)
664118611Snjl        {
665118611Snjl            Op->Asl.CompileFlags |= NODE_IS_BIT_OFFSET;
666118611Snjl        }
667118611Snjl
668118611Snjl        /* Perform BitOffset <--> ByteOffset conversion if necessary */
669118611Snjl
670118611Snjl        switch (Op->Asl.Parent->Asl.AmlOpcode)
671118611Snjl        {
672118611Snjl        case AML_CREATE_FIELD_OP:
673118611Snjl
674118611Snjl            /* We allow a Byte offset to Bit Offset conversion for this op */
675118611Snjl
676118611Snjl            if (!(Op->Asl.CompileFlags & NODE_IS_BIT_OFFSET))
677118611Snjl            {
678118611Snjl                /* Simply multiply byte offset times 8 to get bit offset */
679118611Snjl
680118611Snjl                Temp = ACPI_MUL_8 (Temp);
681118611Snjl            }
682118611Snjl            break;
683118611Snjl
684118611Snjl
685118611Snjl        case AML_CREATE_BIT_FIELD_OP:
686118611Snjl
687118611Snjl            /* This op requires a Bit Offset */
688118611Snjl
689118611Snjl            if (!(Op->Asl.CompileFlags & NODE_IS_BIT_OFFSET))
690118611Snjl            {
691118611Snjl                AslError (ASL_ERROR, ASL_MSG_BYTES_TO_BITS, Op, NULL);
692118611Snjl            }
693118611Snjl            break;
694118611Snjl
695118611Snjl
696118611Snjl        case AML_CREATE_BYTE_FIELD_OP:
697118611Snjl        case AML_CREATE_WORD_FIELD_OP:
698118611Snjl        case AML_CREATE_DWORD_FIELD_OP:
699118611Snjl        case AML_CREATE_QWORD_FIELD_OP:
700118611Snjl        case AML_INDEX_OP:
701118611Snjl
702118611Snjl            /* These Ops require Byte offsets */
703118611Snjl
704118611Snjl            if (Op->Asl.CompileFlags & NODE_IS_BIT_OFFSET)
705118611Snjl            {
706118611Snjl                AslError (ASL_ERROR, ASL_MSG_BITS_TO_BYTES, Op, NULL);
707118611Snjl            }
708118611Snjl            break;
709118611Snjl
710118611Snjl
711118611Snjl        default:
712118611Snjl            /* Nothing to do for other opcodes */
713118611Snjl            break;
714118611Snjl        }
715118611Snjl
716118611Snjl        /* Now convert this node to an integer whose value is the field offset */
717118611Snjl
718118611Snjl        Op->Asl.ParseOpcode     = PARSEOP_INTEGER;
719118611Snjl        Op->Asl.Value.Integer   = (UINT64) Temp;
720118611Snjl        Op->Asl.CompileFlags   |= NODE_IS_RESOURCE_FIELD;
721118611Snjl
722118611Snjl        OpcGenerateAmlOpcode (Op);
723118611Snjl        Op->Asl.AmlLength = OpcSetOptimalIntegerSize (Op);
724118611Snjl    }
725118611Snjl
726118611Snjl    /* 2) Check for a method invocation */
727118611Snjl
728118611Snjl    else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) &&
729118611Snjl                (Node->Type == ACPI_TYPE_METHOD) &&
730118611Snjl                (Op->Asl.Parent) &&
731118611Snjl                (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD))   ||
732118611Snjl
733118611Snjl                (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
734118611Snjl    {
735118611Snjl
736118611Snjl        /*
737118611Snjl         * There are two types of method invocation:
738118611Snjl         * 1) Invocation with arguments -- the parser recognizes this as a METHODCALL
739118611Snjl         * 2) Invocation with no arguments --the parser cannot determine that this is a method
740118611Snjl         *    invocation, therefore we have to figure it out here.
741118611Snjl         */
742118611Snjl        if (Node->Type != ACPI_TYPE_METHOD)
743118611Snjl        {
744118611Snjl            sprintf (MsgBuffer, "%s is a %s", Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type));
745118611Snjl
746118611Snjl            AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, MsgBuffer);
747118611Snjl            return (AE_OK);
748118611Snjl        }
749118611Snjl
750118611Snjl        /* Save the method node in the caller's op */
751118611Snjl
752118611Snjl        Op->Asl.Node = Node;
753118611Snjl        if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)
754118611Snjl        {
755118611Snjl            return (AE_OK);
756118611Snjl        }
757118611Snjl
758118611Snjl        /*
759118611Snjl         * This is a method invocation, with or without arguments.
760118611Snjl         * Count the number of arguments, each appears as a child
761118611Snjl         * under the parent node
762118611Snjl         */
763118611Snjl        Op->Asl.ParseOpcode = PARSEOP_METHODCALL;
764118611Snjl        UtSetParseOpName (Op);
765118611Snjl
766118611Snjl        PassedArgs = 0;
767118611Snjl        NextOp     = Op->Asl.Child;
768118611Snjl
769118611Snjl        while (NextOp)
770118611Snjl        {
771118611Snjl            PassedArgs++;
772118611Snjl            NextOp = NextOp->Asl.Next;
773118611Snjl        }
774118611Snjl
775118611Snjl        if (Node->OwnerId != ASL_EXTERNAL_METHOD)
776118611Snjl        {
777118611Snjl            /*
778118611Snjl             * Check the parsed arguments with the number expected by the
779118611Snjl             * method declaration itself
780118611Snjl             */
781118611Snjl            if (PassedArgs != Node->OwnerId)
782118611Snjl            {
783118611Snjl                sprintf (MsgBuffer, "%s requires %d", Op->Asl.ExternalName,
784118611Snjl                            Node->OwnerId);
785118611Snjl
786118611Snjl                if (PassedArgs < Node->OwnerId)
787118611Snjl                {
788118611Snjl                    AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, MsgBuffer);
789118611Snjl                }
790118611Snjl                else
791118611Snjl                {
792118611Snjl                    AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, MsgBuffer);
793118611Snjl                }
794118611Snjl            }
795118611Snjl        }
796118611Snjl    }
797118611Snjl
798118611Snjl    /*
799118611Snjl     * 3) Check for an ASL Field definition
800118611Snjl     */
801118611Snjl    else if ((Op->Asl.Parent) &&
802118611Snjl            ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD)     ||
803118611Snjl             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD)))
804118611Snjl    {
805118611Snjl        /*
806118611Snjl         * Offset checking for fields.  If the parent operation region has a
807118611Snjl         * constant length (known at compile time), we can check fields
808118611Snjl         * defined in that region against the region length.  This will catch
809118611Snjl         * fields and field units that cannot possibly fit within the region.
810118611Snjl         *
811118611Snjl         * Note: Index fields do not directly reference an operation region,
812118611Snjl         * thus they are not included in this check.
813118611Snjl         */
814118611Snjl        if (Op == Op->Asl.Parent->Asl.Child)
815118611Snjl        {
816118611Snjl            /*
817118611Snjl             * This is the first child of the field node, which is
818118611Snjl             * the name of the region.  Get the parse node for the
819118611Snjl             * region -- which contains the length of the region.
820118611Snjl             */
821118611Snjl            OwningOp = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Node->Object);
822118611Snjl            Op->Asl.Parent->Asl.ExtraValue = ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer);
823118611Snjl
824118611Snjl            /* Examine the field access width */
825118611Snjl
826118611Snjl            switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer)
827118611Snjl            {
828118611Snjl            case AML_FIELD_ACCESS_ANY:
829118611Snjl            case AML_FIELD_ACCESS_BYTE:
830118611Snjl            case AML_FIELD_ACCESS_BUFFER:
831118611Snjl            default:
832118611Snjl                MinimumLength = 1;
833118611Snjl                break;
834118611Snjl
835118611Snjl            case AML_FIELD_ACCESS_WORD:
836118611Snjl                MinimumLength = 2;
837118611Snjl                break;
838118611Snjl
839118611Snjl            case AML_FIELD_ACCESS_DWORD:
840118611Snjl                MinimumLength = 4;
841118611Snjl                break;
842118611Snjl
843118611Snjl            case AML_FIELD_ACCESS_QWORD:
844118611Snjl                MinimumLength = 8;
845118611Snjl                break;
846118611Snjl            }
847118611Snjl
848118611Snjl            /*
849118611Snjl             * Is the region at least as big as the access width?
850118611Snjl             * Note: DataTableRegions have 0 length
851118611Snjl             */
852118611Snjl            if (((UINT32) OwningOp->Asl.Value.Integer) &&
853118611Snjl                ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength))
854118611Snjl            {
855118611Snjl                AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL);
856118611Snjl            }
857118611Snjl
858118611Snjl            /*
859118611Snjl             * Check EC/CMOS/SMBUS fields to make sure that the correct
860118611Snjl             * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS)
861118611Snjl             */
862118611Snjl            SpaceIdOp = OwningOp->Asl.Child->Asl.Next;
863118611Snjl            switch ((UINT32) SpaceIdOp->Asl.Value.Integer)
864118611Snjl            {
865118611Snjl            case REGION_EC:
866118611Snjl            case REGION_CMOS:
867118611Snjl
868118611Snjl                if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BYTE)
869118611Snjl                {
870118611Snjl                    AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL);
871118611Snjl                }
872118611Snjl                break;
873118611Snjl
874118611Snjl            case REGION_SMBUS:
875118611Snjl
876118611Snjl                if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BUFFER)
877118611Snjl                {
878118611Snjl                    AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL);
879118611Snjl                }
880118611Snjl                break;
881118611Snjl
882118611Snjl            default:
883118611Snjl
884118611Snjl                /* Nothing to do for other address spaces */
885118611Snjl                break;
886118611Snjl            }
887118611Snjl        }
888118611Snjl        else
889118611Snjl        {
890118611Snjl            /*
891118611Snjl             * This is one element of the field list.  Check to make sure
892118611Snjl             * that it does not go beyond the end of the parent operation region.
893118611Snjl             *
894118611Snjl             * In the code below:
895118611Snjl             *    Op->Asl.Parent->Asl.ExtraValue      - Region Length (bits)
896118611Snjl             *    Op->Asl.ExtraValue                  - Field start offset (bits)
897118611Snjl             *    Op->Asl.Child->Asl.Value.Integer32  - Field length (bits)
898118611Snjl             *    Op->Asl.Child->Asl.ExtraValue       - Field access width (bits)
899118611Snjl             */
900118611Snjl            if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child)
901118611Snjl            {
902118611Snjl                LkCheckFieldRange (Op,
903118611Snjl                            Op->Asl.Parent->Asl.ExtraValue,
904118611Snjl                            Op->Asl.ExtraValue,
905118611Snjl                            (UINT32) Op->Asl.Child->Asl.Value.Integer,
906118611Snjl                            Op->Asl.Child->Asl.ExtraValue);
907118611Snjl            }
908118611Snjl        }
909118611Snjl    }
910118611Snjl
911118611Snjl    Op->Asl.Node = Node;
912118611Snjl    return (Status);
913118611Snjl}
914118611Snjl
915118611Snjl
916118611Snjl/*******************************************************************************
917118611Snjl *
918118611Snjl * FUNCTION:    LkNamespaceLocateEnd
919118611Snjl *
920118611Snjl * PARAMETERS:  ASL_WALK_CALLBACK
921118611Snjl *
922118611Snjl * RETURN:      Status
923118611Snjl *
924118611Snjl * DESCRIPTION: Ascending callback used during cross reference.  We only
925118611Snjl *              need to worry about scope management here.
926118611Snjl *
927118611Snjl ******************************************************************************/
928118611Snjl
929118611SnjlACPI_STATUS
930118611SnjlLkNamespaceLocateEnd (
931118611Snjl    ACPI_PARSE_OBJECT       *Op,
932118611Snjl    UINT32                  Level,
933118611Snjl    void                    *Context)
934118611Snjl{
935118611Snjl    ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
936118611Snjl    const ACPI_OPCODE_INFO  *OpInfo;
937118611Snjl
938118611Snjl
939118611Snjl    ACPI_FUNCTION_TRACE ("LkNamespaceLocateEnd");
940118611Snjl
941118611Snjl
942118611Snjl    /* We are only interested in opcodes that have an associated name */
943118611Snjl
944118611Snjl    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
945118611Snjl    if (!(OpInfo->Flags & AML_NAMED))
946118611Snjl    {
947118611Snjl        return (AE_OK);
948118611Snjl    }
949118611Snjl
950118611Snjl    /* Not interested in name references, we did not open a scope for them */
951118611Snjl
952118611Snjl    if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
953118611Snjl        (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
954118611Snjl        (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
955118611Snjl    {
956118611Snjl        return (AE_OK);
957118611Snjl    }
958118611Snjl
959118611Snjl    /* Pop the scope stack if necessary */
960118611Snjl
961118611Snjl    if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode)))
962118611Snjl    {
963118611Snjl
964118611Snjl        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
965118611Snjl            "%s: Popping scope for Op %p\n",
966118611Snjl            AcpiUtGetTypeName (OpInfo->ObjectType), Op));
967118611Snjl
968118611Snjl        AcpiDsScopeStackPop (WalkState);
969118611Snjl    }
970118611Snjl
971118611Snjl    return (AE_OK);
972118611Snjl}
973118611Snjl
974118611Snjl
975