xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/aslxref.c (revision 2c7d7e3ca2e4f0b675c6c58e614f6aede66c678e)
1ff4a156dSchristos /******************************************************************************
2ff4a156dSchristos  *
3ff4a156dSchristos  * Module Name: aslxref - Namespace cross-reference
4ff4a156dSchristos  *
5ff4a156dSchristos  *****************************************************************************/
6ff4a156dSchristos 
7ff4a156dSchristos /*
8*2c7d7e3cSchristos  * Copyright (C) 2000 - 2023, Intel Corp.
9ff4a156dSchristos  * All rights reserved.
10ff4a156dSchristos  *
11ff4a156dSchristos  * Redistribution and use in source and binary forms, with or without
12ff4a156dSchristos  * modification, are permitted provided that the following conditions
13ff4a156dSchristos  * are met:
14ff4a156dSchristos  * 1. Redistributions of source code must retain the above copyright
15ff4a156dSchristos  *    notice, this list of conditions, and the following disclaimer,
16ff4a156dSchristos  *    without modification.
17ff4a156dSchristos  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18ff4a156dSchristos  *    substantially similar to the "NO WARRANTY" disclaimer below
19ff4a156dSchristos  *    ("Disclaimer") and any redistribution must be conditioned upon
20ff4a156dSchristos  *    including a substantially similar Disclaimer requirement for further
21ff4a156dSchristos  *    binary redistribution.
22ff4a156dSchristos  * 3. Neither the names of the above-listed copyright holders nor the names
23ff4a156dSchristos  *    of any contributors may be used to endorse or promote products derived
24ff4a156dSchristos  *    from this software without specific prior written permission.
25ff4a156dSchristos  *
26ff4a156dSchristos  * Alternatively, this software may be distributed under the terms of the
27ff4a156dSchristos  * GNU General Public License ("GPL") version 2 as published by the Free
28ff4a156dSchristos  * Software Foundation.
29ff4a156dSchristos  *
30ff4a156dSchristos  * NO WARRANTY
31ff4a156dSchristos  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32ff4a156dSchristos  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3398244dcfSchristos  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34ff4a156dSchristos  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35ff4a156dSchristos  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36ff4a156dSchristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37ff4a156dSchristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38ff4a156dSchristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39ff4a156dSchristos  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40ff4a156dSchristos  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41ff4a156dSchristos  * POSSIBILITY OF SUCH DAMAGES.
42ff4a156dSchristos  */
43ff4a156dSchristos 
44ff4a156dSchristos #include "aslcompiler.h"
45ff4a156dSchristos #include "aslcompiler.y.h"
46ff4a156dSchristos #include "acparser.h"
47ff4a156dSchristos #include "amlcode.h"
48ff4a156dSchristos #include "acnamesp.h"
49ff4a156dSchristos #include "acdispat.h"
50ff4a156dSchristos 
51ff4a156dSchristos 
52ff4a156dSchristos #define _COMPONENT          ACPI_COMPILER
53ff4a156dSchristos         ACPI_MODULE_NAME    ("aslxref")
54ff4a156dSchristos 
55ff4a156dSchristos /* Local prototypes */
56ff4a156dSchristos 
57ff4a156dSchristos static ACPI_STATUS
58ff4a156dSchristos XfNamespaceLocateBegin (
59ff4a156dSchristos     ACPI_PARSE_OBJECT       *Op,
60ff4a156dSchristos     UINT32                  Level,
61ff4a156dSchristos     void                    *Context);
62ff4a156dSchristos 
63ff4a156dSchristos static ACPI_STATUS
64ff4a156dSchristos XfNamespaceLocateEnd (
65ff4a156dSchristos     ACPI_PARSE_OBJECT       *Op,
66ff4a156dSchristos     UINT32                  Level,
67ff4a156dSchristos     void                    *Context);
68ff4a156dSchristos 
695b948c02Schristos static BOOLEAN
705b948c02Schristos XfValidateCrossReference (
715b948c02Schristos     ACPI_PARSE_OBJECT       *Op,
725b948c02Schristos     const ACPI_OPCODE_INFO  *OpInfo,
735b948c02Schristos     ACPI_NAMESPACE_NODE     *Node);
745b948c02Schristos 
75ff4a156dSchristos static BOOLEAN
76ff4a156dSchristos XfObjectExists (
77ff4a156dSchristos     char                    *Name);
78ff4a156dSchristos 
79ff4a156dSchristos static ACPI_STATUS
80ff4a156dSchristos XfCompareOneNamespaceObject (
81ff4a156dSchristos     ACPI_HANDLE             ObjHandle,
82ff4a156dSchristos     UINT32                  Level,
83ff4a156dSchristos     void                    *Context,
84ff4a156dSchristos     void                    **ReturnValue);
85ff4a156dSchristos 
86ff4a156dSchristos static void
87ff4a156dSchristos XfCheckFieldRange (
88ff4a156dSchristos     ACPI_PARSE_OBJECT       *Op,
89ff4a156dSchristos     UINT32                  RegionBitLength,
90ff4a156dSchristos     UINT32                  FieldBitOffset,
91ff4a156dSchristos     UINT32                  FieldBitLength,
92ff4a156dSchristos     UINT32                  AccessBitWidth);
93ff4a156dSchristos 
94f5b481b3Schristos static BOOLEAN
95f5b481b3Schristos XfFindCondRefOfName (
96f5b481b3Schristos     ACPI_NAMESPACE_NODE     *Node,
97f5b481b3Schristos     ACPI_PARSE_OBJECT       *Op);
98f5b481b3Schristos 
99f5b481b3Schristos static BOOLEAN
100f5b481b3Schristos XfRefIsGuardedByIfCondRefOf (
101f5b481b3Schristos     ACPI_NAMESPACE_NODE     *Node,
102f5b481b3Schristos     ACPI_PARSE_OBJECT       *Op);
103f5b481b3Schristos 
104ff4a156dSchristos 
105ff4a156dSchristos /*******************************************************************************
106ff4a156dSchristos  *
107ff4a156dSchristos  * FUNCTION:    XfCrossReferenceNamespace
108ff4a156dSchristos  *
109ff4a156dSchristos  * PARAMETERS:  None
110ff4a156dSchristos  *
111ff4a156dSchristos  * RETURN:      Status
112ff4a156dSchristos  *
113ff4a156dSchristos  * DESCRIPTION: Perform a cross reference check of the parse tree against the
114ff4a156dSchristos  *              namespace. Every named referenced within the parse tree
115ff4a156dSchristos  *              should be get resolved with a namespace lookup. If not, the
116ff4a156dSchristos  *              original reference in the ASL code is invalid -- i.e., refers
117ff4a156dSchristos  *              to a non-existent object.
118ff4a156dSchristos  *
119ff4a156dSchristos  * NOTE:  The ASL "External" operator causes the name to be inserted into the
120ff4a156dSchristos  *        namespace so that references to the external name will be resolved
121ff4a156dSchristos  *        correctly here.
122ff4a156dSchristos  *
123ff4a156dSchristos  ******************************************************************************/
124ff4a156dSchristos 
125ff4a156dSchristos ACPI_STATUS
XfCrossReferenceNamespace(void)126ff4a156dSchristos XfCrossReferenceNamespace (
127ff4a156dSchristos     void)
128ff4a156dSchristos {
129ff4a156dSchristos     ACPI_WALK_STATE         *WalkState;
130ff4a156dSchristos 
131ff4a156dSchristos 
132ff4a156dSchristos     /*
133ff4a156dSchristos      * Create a new walk state for use when looking up names
134ff4a156dSchristos      * within the namespace (Passed as context to the callbacks)
135ff4a156dSchristos      */
136ff4a156dSchristos     WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
137ff4a156dSchristos     if (!WalkState)
138ff4a156dSchristos     {
139ff4a156dSchristos         return (AE_NO_MEMORY);
140ff4a156dSchristos     }
141ff4a156dSchristos 
142ff4a156dSchristos     /* Walk the entire parse tree */
143ff4a156dSchristos 
1447efa3256Schristos     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_TWICE,
14549c2f1f4Schristos         XfNamespaceLocateBegin, XfNamespaceLocateEnd, WalkState);
146414ef032Schristos 
147414ef032Schristos     ACPI_FREE (WalkState);
148ff4a156dSchristos     return (AE_OK);
149ff4a156dSchristos }
150ff4a156dSchristos 
151ff4a156dSchristos 
152ff4a156dSchristos /*******************************************************************************
153ff4a156dSchristos  *
154ff4a156dSchristos  * FUNCTION:    XfObjectExists
155ff4a156dSchristos  *
156ff4a156dSchristos  * PARAMETERS:  Name            - 4 char ACPI name
157ff4a156dSchristos  *
158ff4a156dSchristos  * RETURN:      TRUE if name exists in namespace
159ff4a156dSchristos  *
160ff4a156dSchristos  * DESCRIPTION: Walk the namespace to find an object
161ff4a156dSchristos  *
162ff4a156dSchristos  ******************************************************************************/
163ff4a156dSchristos 
164ff4a156dSchristos static BOOLEAN
XfObjectExists(char * Name)165ff4a156dSchristos XfObjectExists (
166ff4a156dSchristos     char                    *Name)
167ff4a156dSchristos {
168ff4a156dSchristos     ACPI_STATUS             Status;
169ff4a156dSchristos 
170ff4a156dSchristos 
171ff4a156dSchristos     /* Walk entire namespace from the supplied root */
172ff4a156dSchristos 
173ff4a156dSchristos     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
174ff4a156dSchristos         ACPI_UINT32_MAX, FALSE, XfCompareOneNamespaceObject, NULL,
175ff4a156dSchristos         Name, NULL);
176ff4a156dSchristos     if (Status == AE_CTRL_TRUE)
177ff4a156dSchristos     {
178ff4a156dSchristos         /* At least one instance of the name was found */
179ff4a156dSchristos 
180ff4a156dSchristos         return (TRUE);
181ff4a156dSchristos     }
182ff4a156dSchristos 
183ff4a156dSchristos     return (FALSE);
184ff4a156dSchristos }
185ff4a156dSchristos 
186ff4a156dSchristos 
187ff4a156dSchristos /*******************************************************************************
188ff4a156dSchristos  *
189ff4a156dSchristos  * FUNCTION:    XfCompareOneNamespaceObject
190ff4a156dSchristos  *
191ff4a156dSchristos  * PARAMETERS:  ACPI_WALK_CALLBACK
192ff4a156dSchristos  *
193ff4a156dSchristos  * RETURN:      Status
194ff4a156dSchristos  *
195ff4a156dSchristos  * DESCRIPTION: Compare name of one object.
196ff4a156dSchristos  *
197ff4a156dSchristos  ******************************************************************************/
198ff4a156dSchristos 
199ff4a156dSchristos static ACPI_STATUS
XfCompareOneNamespaceObject(ACPI_HANDLE ObjHandle,UINT32 Level,void * Context,void ** ReturnValue)200ff4a156dSchristos XfCompareOneNamespaceObject (
201ff4a156dSchristos     ACPI_HANDLE             ObjHandle,
202ff4a156dSchristos     UINT32                  Level,
203ff4a156dSchristos     void                    *Context,
204ff4a156dSchristos     void                    **ReturnValue)
205ff4a156dSchristos {
206ff4a156dSchristos     ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
207ff4a156dSchristos 
208ff4a156dSchristos 
209ff4a156dSchristos     /* Simply check the name */
210ff4a156dSchristos 
211ff4a156dSchristos     if (*((UINT32 *) (Context)) == Node->Name.Integer)
212ff4a156dSchristos     {
213ff4a156dSchristos         /* Abort walk if we found one instance */
214ff4a156dSchristos 
215ff4a156dSchristos         return (AE_CTRL_TRUE);
216ff4a156dSchristos     }
217ff4a156dSchristos 
218ff4a156dSchristos     return (AE_OK);
219ff4a156dSchristos }
220ff4a156dSchristos 
221ff4a156dSchristos 
222ff4a156dSchristos /*******************************************************************************
223ff4a156dSchristos  *
224ff4a156dSchristos  * FUNCTION:    XfCheckFieldRange
225ff4a156dSchristos  *
226ff4a156dSchristos  * PARAMETERS:  RegionBitLength     - Length of entire parent region
227ff4a156dSchristos  *              FieldBitOffset      - Start of the field unit (within region)
228ff4a156dSchristos  *              FieldBitLength      - Entire length of field unit
229ff4a156dSchristos  *              AccessBitWidth      - Access width of the field unit
230ff4a156dSchristos  *
231ff4a156dSchristos  * RETURN:      None
232ff4a156dSchristos  *
233ff4a156dSchristos  * DESCRIPTION: Check one field unit to make sure it fits in the parent
234ff4a156dSchristos  *              op region.
235ff4a156dSchristos  *
236ff4a156dSchristos  * Note: AccessBitWidth must be either 8,16,32, or 64
237ff4a156dSchristos  *
238ff4a156dSchristos  ******************************************************************************/
239ff4a156dSchristos 
240ff4a156dSchristos static void
XfCheckFieldRange(ACPI_PARSE_OBJECT * Op,UINT32 RegionBitLength,UINT32 FieldBitOffset,UINT32 FieldBitLength,UINT32 AccessBitWidth)241ff4a156dSchristos XfCheckFieldRange (
242ff4a156dSchristos     ACPI_PARSE_OBJECT       *Op,
243ff4a156dSchristos     UINT32                  RegionBitLength,
244ff4a156dSchristos     UINT32                  FieldBitOffset,
245ff4a156dSchristos     UINT32                  FieldBitLength,
246ff4a156dSchristos     UINT32                  AccessBitWidth)
247ff4a156dSchristos {
248ff4a156dSchristos     UINT32                  FieldEndBitOffset;
249ff4a156dSchristos 
250ff4a156dSchristos 
251ff4a156dSchristos     /*
252ff4a156dSchristos      * Check each field unit against the region size. The entire
253ff4a156dSchristos      * field unit (start offset plus length) must fit within the
254ff4a156dSchristos      * region.
255ff4a156dSchristos      */
256ff4a156dSchristos     FieldEndBitOffset = FieldBitOffset + FieldBitLength;
257ff4a156dSchristos 
258ff4a156dSchristos     if (FieldEndBitOffset > RegionBitLength)
259ff4a156dSchristos     {
260ff4a156dSchristos         /* Field definition itself is beyond the end-of-region */
261ff4a156dSchristos 
262ff4a156dSchristos         AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_OFFSET, Op, NULL);
263ff4a156dSchristos         return;
264ff4a156dSchristos     }
265ff4a156dSchristos 
266ff4a156dSchristos     /*
267ff4a156dSchristos      * Now check that the field plus AccessWidth doesn't go beyond
268ff4a156dSchristos      * the end-of-region. Assumes AccessBitWidth is a power of 2
269ff4a156dSchristos      */
270ff4a156dSchristos     FieldEndBitOffset = ACPI_ROUND_UP (FieldEndBitOffset, AccessBitWidth);
271ff4a156dSchristos 
272ff4a156dSchristos     if (FieldEndBitOffset > RegionBitLength)
273ff4a156dSchristos     {
274ff4a156dSchristos         /* Field definition combined with the access is beyond EOR */
275ff4a156dSchristos 
276ff4a156dSchristos         AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_ACCESS_WIDTH, Op, NULL);
277ff4a156dSchristos     }
278ff4a156dSchristos }
279ff4a156dSchristos 
280414ef032Schristos 
281414ef032Schristos /*******************************************************************************
282414ef032Schristos  *
283ff4a156dSchristos  * FUNCTION:    XfNamespaceLocateBegin
284ff4a156dSchristos  *
285ff4a156dSchristos  * PARAMETERS:  ASL_WALK_CALLBACK
286ff4a156dSchristos  *
287ff4a156dSchristos  * RETURN:      Status
288ff4a156dSchristos  *
289ff4a156dSchristos  * DESCRIPTION: Descending callback used during cross-reference. For named
290ff4a156dSchristos  *              object references, attempt to locate the name in the
291ff4a156dSchristos  *              namespace.
292ff4a156dSchristos  *
293ff4a156dSchristos  * NOTE: ASL references to named fields within resource descriptors are
294ff4a156dSchristos  *       resolved to integer values here. Therefore, this step is an
295ff4a156dSchristos  *       important part of the code generation. We don't know that the
296ff4a156dSchristos  *       name refers to a resource descriptor until now.
297ff4a156dSchristos  *
298ff4a156dSchristos  ******************************************************************************/
299ff4a156dSchristos 
300ff4a156dSchristos static ACPI_STATUS
XfNamespaceLocateBegin(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)301ff4a156dSchristos XfNamespaceLocateBegin (
302ff4a156dSchristos     ACPI_PARSE_OBJECT       *Op,
303ff4a156dSchristos     UINT32                  Level,
304ff4a156dSchristos     void                    *Context)
305ff4a156dSchristos {
306ff4a156dSchristos     ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
307ff4a156dSchristos     ACPI_NAMESPACE_NODE     *Node;
308ff4a156dSchristos     ACPI_STATUS             Status;
309ff4a156dSchristos     ACPI_OBJECT_TYPE        ObjectType;
310ff4a156dSchristos     char                    *Path;
311ff4a156dSchristos     UINT8                   PassedArgs;
312ff4a156dSchristos     ACPI_PARSE_OBJECT       *NextOp;
313ff4a156dSchristos     ACPI_PARSE_OBJECT       *OwningOp;
314ff4a156dSchristos     ACPI_PARSE_OBJECT       *SpaceIdOp;
315ff4a156dSchristos     UINT32                  MinimumLength;
316ff4a156dSchristos     UINT32                  Offset;
317ff4a156dSchristos     UINT32                  FieldBitLength;
318ff4a156dSchristos     UINT32                  TagBitLength;
319ff4a156dSchristos     UINT8                   Message = 0;
320ff4a156dSchristos     const ACPI_OPCODE_INFO  *OpInfo;
321ff4a156dSchristos     UINT32                  Flags;
3229b9ee194Schristos     ASL_METHOD_LOCAL        *MethodLocals = NULL;
3239b9ee194Schristos     ASL_METHOD_LOCAL        *MethodArgs = NULL;
3249b9ee194Schristos     int                     RegisterNumber;
3259b9ee194Schristos     UINT32                  i;
3267ab6b89bSchristos     ACPI_NAMESPACE_NODE     *DeclarationParentMethod;
3277ab6b89bSchristos     ACPI_PARSE_OBJECT       *ReferenceParentMethod;
328b558e860Schristos     char                    *ExternalPath;
329ff4a156dSchristos 
330ff4a156dSchristos 
331ff4a156dSchristos     ACPI_FUNCTION_TRACE_PTR (XfNamespaceLocateBegin, Op);
332ff4a156dSchristos 
3339b9ee194Schristos 
3349b9ee194Schristos     if ((Op->Asl.AmlOpcode == AML_METHOD_OP) && Op->Asl.Node)
3359b9ee194Schristos     {
3369b9ee194Schristos         Node = Op->Asl.Node;
3379b9ee194Schristos 
3389b9ee194Schristos         /* Support for method LocalX/ArgX analysis */
3399b9ee194Schristos 
3409b9ee194Schristos         if (!Node->MethodLocals)
3419b9ee194Schristos         {
3429b9ee194Schristos             /* Create local/arg info blocks */
3439b9ee194Schristos 
3449b9ee194Schristos             MethodLocals = UtLocalCalloc (
3459b9ee194Schristos                 sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_LOCALS);
3469b9ee194Schristos             Node->MethodLocals = MethodLocals;
3479b9ee194Schristos 
3489b9ee194Schristos             MethodArgs = UtLocalCalloc (
3499b9ee194Schristos                 sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_ARGS);
3509b9ee194Schristos             Node->MethodArgs = MethodArgs;
3519b9ee194Schristos 
3529b9ee194Schristos             /*
3539b9ee194Schristos              * Get the method argument count
3549b9ee194Schristos              * First, get the name node
3559b9ee194Schristos              */
3569b9ee194Schristos             NextOp = Op->Asl.Child;
3579b9ee194Schristos 
3589b9ee194Schristos             /* Get the NumArguments node */
3599b9ee194Schristos 
3609b9ee194Schristos             NextOp = NextOp->Asl.Next;
3619b9ee194Schristos             Node->ArgCount = (UINT8)
3629b9ee194Schristos                 (((UINT8) NextOp->Asl.Value.Integer) & 0x07);
3639b9ee194Schristos 
3645b948c02Schristos             /* We will track all possible ArgXs */
3659b9ee194Schristos 
3669b9ee194Schristos             for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++)
3679b9ee194Schristos             {
3689b9ee194Schristos                 if (i < Node->ArgCount)
3699b9ee194Schristos                 {
3709b9ee194Schristos                     /* Real Args are always "initialized" */
3719b9ee194Schristos 
3729b9ee194Schristos                     MethodArgs[i].Flags = ASL_ARG_INITIALIZED;
3739b9ee194Schristos                 }
3749b9ee194Schristos                 else
3759b9ee194Schristos                 {
3769b9ee194Schristos                     /* Other ArgXs can be used as locals */
3779b9ee194Schristos 
3789b9ee194Schristos                     MethodArgs[i].Flags = ASL_ARG_IS_LOCAL;
3799b9ee194Schristos                 }
3809b9ee194Schristos 
3819b9ee194Schristos                 MethodArgs[i].Op = Op;
3829b9ee194Schristos             }
3839b9ee194Schristos         }
3849b9ee194Schristos     }
3859b9ee194Schristos 
386ff4a156dSchristos     /*
387ff4a156dSchristos      * If this node is the actual declaration of a name
388ff4a156dSchristos      * [such as the XXXX name in "Method (XXXX)"],
389ff4a156dSchristos      * we are not interested in it here. We only care about names that are
390ff4a156dSchristos      * references to other objects within the namespace and the parent objects
391ff4a156dSchristos      * of name declarations
392ff4a156dSchristos      */
393ae01dbf5Schristos     if (Op->Asl.CompileFlags & OP_IS_NAME_DECLARATION)
394ff4a156dSchristos     {
395ff4a156dSchristos         return_ACPI_STATUS (AE_OK);
396ff4a156dSchristos     }
397ff4a156dSchristos 
398ff4a156dSchristos     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
399ff4a156dSchristos 
4009b9ee194Schristos     /* Check method LocalX variables */
4019b9ee194Schristos 
4029b9ee194Schristos     if (OpInfo->Type == AML_TYPE_LOCAL_VARIABLE)
4039b9ee194Schristos     {
4049b9ee194Schristos         /* Find parent method Op */
4059b9ee194Schristos 
4069ddb8508Schristos         NextOp = UtGetParentMethodOp (Op);
4079b9ee194Schristos         if (!NextOp)
4089b9ee194Schristos         {
4099b9ee194Schristos             return_ACPI_STATUS (AE_OK);
4109b9ee194Schristos         }
4119b9ee194Schristos 
4129b9ee194Schristos         /* Get method node */
4139b9ee194Schristos 
4149b9ee194Schristos         Node = NextOp->Asl.Node;
4159b9ee194Schristos 
4169b9ee194Schristos         RegisterNumber = Op->Asl.AmlOpcode & 0x0007; /* 0x60 through 0x67 */
4179b9ee194Schristos         MethodLocals = Node->MethodLocals;
4189b9ee194Schristos 
419ae01dbf5Schristos         if (Op->Asl.CompileFlags & OP_IS_TARGET)
4209b9ee194Schristos         {
4219b9ee194Schristos             /* Local is being initialized */
4229b9ee194Schristos 
4239b9ee194Schristos             MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_INITIALIZED;
4249b9ee194Schristos             MethodLocals[RegisterNumber].Op = Op;
4259b9ee194Schristos 
4269b9ee194Schristos             return_ACPI_STATUS (AE_OK);
4279b9ee194Schristos         }
4289b9ee194Schristos 
4299b9ee194Schristos         /* Mark this Local as referenced */
4309b9ee194Schristos 
4319b9ee194Schristos         MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_REFERENCED;
4329b9ee194Schristos         MethodLocals[RegisterNumber].Op = Op;
4339b9ee194Schristos 
4349b9ee194Schristos         return_ACPI_STATUS (AE_OK);
4359b9ee194Schristos     }
4369b9ee194Schristos 
4379b9ee194Schristos     /* Check method ArgX variables */
4389b9ee194Schristos 
4399b9ee194Schristos     if (OpInfo->Type == AML_TYPE_METHOD_ARGUMENT)
4409b9ee194Schristos     {
4419b9ee194Schristos         /* Find parent method Op */
4429b9ee194Schristos 
4439ddb8508Schristos         NextOp = UtGetParentMethodOp (Op);
4449b9ee194Schristos         if (!NextOp)
4459b9ee194Schristos         {
4469b9ee194Schristos             return_ACPI_STATUS (AE_OK);
4479b9ee194Schristos         }
4489b9ee194Schristos 
4499b9ee194Schristos         /* Get method node */
4509b9ee194Schristos 
4519b9ee194Schristos         Node = NextOp->Asl.Node;
4529b9ee194Schristos 
4539b9ee194Schristos         /* Get Arg # */
4549b9ee194Schristos 
4559b9ee194Schristos         RegisterNumber = Op->Asl.AmlOpcode - AML_ARG0; /* 0x68 through 0x6F */
4569b9ee194Schristos         MethodArgs = Node->MethodArgs;
4579b9ee194Schristos 
458660602a8Schristos         /* Mark this Arg as referenced */
459660602a8Schristos 
460660602a8Schristos         MethodArgs[RegisterNumber].Flags |= ASL_ARG_REFERENCED;
461660602a8Schristos         MethodArgs[RegisterNumber].Op = Op;
462660602a8Schristos 
463ae01dbf5Schristos         if (Op->Asl.CompileFlags & OP_IS_TARGET)
4649b9ee194Schristos         {
4659b9ee194Schristos             /* Arg is being initialized */
4669b9ee194Schristos 
4679b9ee194Schristos             MethodArgs[RegisterNumber].Flags |= ASL_ARG_INITIALIZED;
4689b9ee194Schristos         }
4699b9ee194Schristos 
4709b9ee194Schristos         return_ACPI_STATUS (AE_OK);
4719b9ee194Schristos     }
4729b9ee194Schristos 
4739b9ee194Schristos     /*
4749b9ee194Schristos      * After method ArgX and LocalX, we are only interested in opcodes
4759b9ee194Schristos      * that have an associated name
4769b9ee194Schristos      */
477ff4a156dSchristos     if ((!(OpInfo->Flags & AML_NAMED)) &&
478ff4a156dSchristos         (!(OpInfo->Flags & AML_CREATE)) &&
479ff4a156dSchristos         (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
480ff4a156dSchristos         (Op->Asl.ParseOpcode != PARSEOP_NAMESEG)    &&
481ae01dbf5Schristos         (Op->Asl.ParseOpcode != PARSEOP_METHODCALL) &&
4827ab6b89bSchristos         (Op->Asl.ParseOpcode != PARSEOP_EXTERNAL))
483ff4a156dSchristos     {
484ff4a156dSchristos         return_ACPI_STATUS (AE_OK);
485ff4a156dSchristos     }
486ff4a156dSchristos 
487ff4a156dSchristos     /*
488ff4a156dSchristos      * We must enable the "search-to-root" for single NameSegs, but
489ff4a156dSchristos      * we have to be very careful about opening up scopes
490ff4a156dSchristos      */
491ff4a156dSchristos     Flags = ACPI_NS_SEARCH_PARENT;
492ff4a156dSchristos     if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
493ff4a156dSchristos         (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
494ae01dbf5Schristos         (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
495f5b481b3Schristos         (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)   ||
496f5b481b3Schristos         (Op->Asl.ParseOpcode == PARSEOP_CONDREFOF))
497ff4a156dSchristos     {
498ff4a156dSchristos         /*
499ff4a156dSchristos          * These are name references, do not push the scope stack
500ff4a156dSchristos          * for them.
501ff4a156dSchristos          */
502ff4a156dSchristos         Flags |= ACPI_NS_DONT_OPEN_SCOPE;
503ff4a156dSchristos     }
504ff4a156dSchristos 
505ff4a156dSchristos     /* Get the NamePath from the appropriate place */
506ff4a156dSchristos 
507ff4a156dSchristos     if (OpInfo->Flags & AML_NAMED)
508ff4a156dSchristos     {
509ff4a156dSchristos         /* For nearly all NAMED operators, the name reference is the first child */
510ff4a156dSchristos 
511ff4a156dSchristos         Path = Op->Asl.Child->Asl.Value.String;
512ff4a156dSchristos         if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
513ff4a156dSchristos         {
514ff4a156dSchristos             /*
515ff4a156dSchristos              * ALIAS is the only oddball opcode, the name declaration
516ff4a156dSchristos              * (alias name) is the second operand
517ff4a156dSchristos              */
518ff4a156dSchristos             Path = Op->Asl.Child->Asl.Next->Asl.Value.String;
519ff4a156dSchristos         }
520ff4a156dSchristos     }
521ff4a156dSchristos     else if (OpInfo->Flags & AML_CREATE)
522ff4a156dSchristos     {
523ff4a156dSchristos         /* Name must appear as the last parameter */
524ff4a156dSchristos 
525ff4a156dSchristos         NextOp = Op->Asl.Child;
526ae01dbf5Schristos         while (!(NextOp->Asl.CompileFlags & OP_IS_NAME_DECLARATION))
527ff4a156dSchristos         {
528ff4a156dSchristos             NextOp = NextOp->Asl.Next;
529ff4a156dSchristos         }
53081bd9c9cSchristos 
531ff4a156dSchristos         Path = NextOp->Asl.Value.String;
532ff4a156dSchristos     }
533ff4a156dSchristos     else
534ff4a156dSchristos     {
535ff4a156dSchristos         Path = Op->Asl.Value.String;
536ff4a156dSchristos     }
537ff4a156dSchristos 
538ff4a156dSchristos     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
539ff4a156dSchristos     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
540ff4a156dSchristos         "Type=%s\n", AcpiUtGetTypeName (ObjectType)));
541ff4a156dSchristos 
542ff4a156dSchristos     /*
543ff4a156dSchristos      * Lookup the name in the namespace. Name must exist at this point, or it
544ff4a156dSchristos      * is an invalid reference.
545ff4a156dSchristos      *
546ff4a156dSchristos      * The namespace is also used as a lookup table for references to resource
547ff4a156dSchristos      * descriptors and the fields within them.
548ff4a156dSchristos      */
5497efa3256Schristos     AslGbl_NsLookupCount++;
550ff4a156dSchristos 
551ff4a156dSchristos     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
552a40a9998Schristos         ACPI_IMODE_EXECUTE, Flags, WalkState, &Node);
553ff4a156dSchristos     if (ACPI_FAILURE (Status))
554ff4a156dSchristos     {
555ff4a156dSchristos         if (Status == AE_NOT_FOUND)
556ff4a156dSchristos         {
557ff4a156dSchristos             /*
558ff4a156dSchristos              * We didn't find the name reference by path -- we can qualify this
559ff4a156dSchristos              * a little better before we print an error message
560ff4a156dSchristos              */
561f5b481b3Schristos 
562f5b481b3Schristos             if ((Op->Asl.Parent) &&
563f5b481b3Schristos                 (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF))
564f5b481b3Schristos             {
565f5b481b3Schristos                 /*
566f5b481b3Schristos                  * One special case: CondRefOf operator - if the name doesn't
567f5b481b3Schristos                  * exist at this point, it means that there's no actual or
568f5b481b3Schristos                  * external declaration. If the name is not found, just ignore
569f5b481b3Schristos                  * it, the point of the operator is to determine if the name
570f5b481b3Schristos                  * exists at runtime. We wanted to see if this named object
571f5b481b3Schristos                  * exists to facilitate analysis to allow protected usage of
572f5b481b3Schristos                  * undeclared externals.
573f5b481b3Schristos                  */
574f5b481b3Schristos                 return_ACPI_STATUS (AE_OK);
575f5b481b3Schristos             }
576f5b481b3Schristos             else if (strlen (Path) == ACPI_NAMESEG_SIZE)
577ff4a156dSchristos             {
578ff4a156dSchristos                 /* A simple, one-segment ACPI name */
579ff4a156dSchristos 
580ff4a156dSchristos                 if (XfObjectExists (Path))
581ff4a156dSchristos                 {
582ff4a156dSchristos                     /*
583ff4a156dSchristos                      * There exists such a name, but we couldn't get to it
584ff4a156dSchristos                      * from this scope
585ff4a156dSchristos                      */
586ff4a156dSchristos                     AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op,
587ff4a156dSchristos                         Op->Asl.ExternalName);
588ff4a156dSchristos                 }
589ff4a156dSchristos                 else
590ff4a156dSchristos                 {
591ff4a156dSchristos                     /* The name doesn't exist, period */
592ff4a156dSchristos 
593ff4a156dSchristos                     AslError (ASL_ERROR, ASL_MSG_NOT_EXIST,
594ff4a156dSchristos                         Op, Op->Asl.ExternalName);
595ff4a156dSchristos                 }
596ff4a156dSchristos             }
597ff4a156dSchristos             else
598ff4a156dSchristos             {
5997efa3256Schristos                 /* The NamePath contains multiple NameSegs */
600ff4a156dSchristos 
6017efa3256Schristos                 if ((OpInfo->Flags & AML_CREATE) ||
6027efa3256Schristos                     (OpInfo->ObjectType == ACPI_TYPE_LOCAL_ALIAS))
603ff4a156dSchristos                 {
6047efa3256Schristos                     /*
6057efa3256Schristos                      * The new name is the last parameter. For the
6067efa3256Schristos                      * CreateXXXXField and Alias operators
6077efa3256Schristos                      */
6087efa3256Schristos                     NextOp = Op->Asl.Child;
6097efa3256Schristos                     while (!(NextOp->Asl.CompileFlags & OP_IS_NAME_DECLARATION))
6107efa3256Schristos                     {
6117efa3256Schristos                         NextOp = NextOp->Asl.Next;
6127efa3256Schristos                     }
6137efa3256Schristos 
6147efa3256Schristos                     AslError (ASL_ERROR, ASL_MSG_PREFIX_NOT_EXIST, NextOp,
6157efa3256Schristos                         NextOp->Asl.ExternalName);
6167efa3256Schristos                 }
6177efa3256Schristos                 else if (OpInfo->Flags & AML_NAMED)
6187efa3256Schristos                 {
6197efa3256Schristos                     /* The new name is the first parameter */
6207efa3256Schristos 
6217efa3256Schristos                     AslError (ASL_ERROR, ASL_MSG_PREFIX_NOT_EXIST, Op,
6227efa3256Schristos                         Op->Asl.ExternalName);
6237efa3256Schristos                 }
6247efa3256Schristos                 else if (Path[0] == AML_ROOT_PREFIX)
6257efa3256Schristos                 {
6267efa3256Schristos                     /* Full namepath from root, the object does not exist */
627ff4a156dSchristos 
628ff4a156dSchristos                     AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op,
629ff4a156dSchristos                         Op->Asl.ExternalName);
630ff4a156dSchristos                 }
631ff4a156dSchristos                 else
632ff4a156dSchristos                 {
633ff4a156dSchristos                     /*
6347efa3256Schristos                      * Generic "not found" error. Cannot determine whether it
6357efa3256Schristos                      * doesn't exist or just can't be reached. However, we
6367efa3256Schristos                      * can differentiate between a NameSeg vs. NamePath.
637ff4a156dSchristos                      */
6385b948c02Schristos                     if (strlen (Op->Asl.ExternalName) == ACPI_NAMESEG_SIZE)
6397efa3256Schristos                     {
640ff4a156dSchristos                         AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op,
641ff4a156dSchristos                             Op->Asl.ExternalName);
642ff4a156dSchristos                     }
6437efa3256Schristos                     else
6447efa3256Schristos                     {
6457efa3256Schristos                         AslError (ASL_ERROR, ASL_MSG_NAMEPATH_NOT_EXIST, Op,
6467efa3256Schristos                             Op->Asl.ExternalName);
6477efa3256Schristos                     }
6487efa3256Schristos                 }
649ff4a156dSchristos             }
650ff4a156dSchristos 
651ff4a156dSchristos             Status = AE_OK;
652ff4a156dSchristos         }
653ff4a156dSchristos 
654ff4a156dSchristos         return_ACPI_STATUS (Status);
655ff4a156dSchristos     }
656ff4a156dSchristos 
6575b948c02Schristos     /* Check for an attempt to access an object in another method */
6585b948c02Schristos 
6595b948c02Schristos     if (!XfValidateCrossReference (Op, OpInfo, Node))
6605b948c02Schristos     {
6615b948c02Schristos         AslError (ASL_ERROR, ASL_MSG_TEMPORARY_OBJECT, Op,
6625b948c02Schristos             Op->Asl.ExternalName);
6635b948c02Schristos         return_ACPI_STATUS (Status);
6645b948c02Schristos     }
6655b948c02Schristos 
666a40a9998Schristos    /* Object was found above, check for an illegal forward reference */
667a40a9998Schristos 
668a40a9998Schristos     if (Op->Asl.CompileFlags & OP_NOT_FOUND_DURING_LOAD)
669a40a9998Schristos     {
670a40a9998Schristos         /*
671a40a9998Schristos          * During the load phase, this Op was flagged as a possible
6727ab6b89bSchristos          * illegal forward reference. In other words, Op is a name path or
6737ab6b89bSchristos          * name segment that refers to a named object declared after the
6747ab6b89bSchristos          * reference. In this scinario, Node refers to the actual declaration
6757ab6b89bSchristos          * and Op is a parse node that references the named object.
676a40a9998Schristos          *
6777ab6b89bSchristos          * Note:
6787ab6b89bSchristos          *
6797ab6b89bSchristos          * Object references inside of control methods are allowed to
6807ab6b89bSchristos          * refer to objects declared outside of control methods.
6817ab6b89bSchristos          *
6827ab6b89bSchristos          * If the declaration and reference are both contained inside of the
6837ab6b89bSchristos          * same method or outside of any method, this is a forward reference
6847ab6b89bSchristos          * and should be reported as a compiler error.
685a40a9998Schristos          */
6869ddb8508Schristos         DeclarationParentMethod = UtGetParentMethodNode (Node);
6879ddb8508Schristos         ReferenceParentMethod = UtGetParentMethodOp (Op);
6887ab6b89bSchristos 
6899ddb8508Schristos         /* case 1: declaration and reference are both outside of method */
6907ab6b89bSchristos 
6917ab6b89bSchristos         if (!ReferenceParentMethod && !DeclarationParentMethod)
6927ab6b89bSchristos         {
6937ab6b89bSchristos             AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op,
6947ab6b89bSchristos                 Op->Asl.ExternalName);
6957ab6b89bSchristos         }
6967ab6b89bSchristos 
6977ab6b89bSchristos         /* case 2: declaration and reference are both inside of the same method */
6987ab6b89bSchristos 
6997ab6b89bSchristos         else if (ReferenceParentMethod && DeclarationParentMethod &&
7007ab6b89bSchristos             ReferenceParentMethod == DeclarationParentMethod->Op)
701a40a9998Schristos         {
702a40a9998Schristos              AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op,
703a40a9998Schristos                 Op->Asl.ExternalName);
704a40a9998Schristos         }
705a40a9998Schristos     }
706a40a9998Schristos 
707ff4a156dSchristos     /* Check for a reference vs. name declaration */
708ff4a156dSchristos 
709ff4a156dSchristos     if (!(OpInfo->Flags & AML_NAMED) &&
710ff4a156dSchristos         !(OpInfo->Flags & AML_CREATE))
711ff4a156dSchristos     {
712ff4a156dSchristos         /* This node has been referenced, mark it for reference check */
713ff4a156dSchristos 
714ff4a156dSchristos         Node->Flags |= ANOBJ_IS_REFERENCED;
715ff4a156dSchristos     }
716ff4a156dSchristos 
717531a0538Schristos     /*
718531a0538Schristos      * Attempt to optimize the NamePath
719531a0538Schristos      *
720531a0538Schristos      * One special case: CondRefOf operator - not all AML interpreter
721531a0538Schristos      * implementations expect optimized namepaths as a parameter to this
722531a0538Schristos      * operator. They require relative name paths with prefix operators or
723531a0538Schristos      * namepaths starting with the root scope.
724531a0538Schristos      *
725531a0538Schristos      * Other AML interpreter implementations do not perform the namespace
726531a0538Schristos      * search that starts at the current scope and recursively searching the
727531a0538Schristos      * parent scope until the root scope. The lack of search is only known to
728531a0538Schristos      * occur for the namestring parameter for the CondRefOf operator.
729531a0538Schristos      */
730531a0538Schristos     if ((Op->Asl.Parent) &&
731531a0538Schristos         (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_CONDREFOF))
732531a0538Schristos     {
733ff4a156dSchristos         OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node);
734531a0538Schristos     }
735ff4a156dSchristos 
736ff4a156dSchristos     /*
737ff4a156dSchristos      * 1) Dereference an alias (A name reference that is an alias)
738ff4a156dSchristos      *    Aliases are not nested, the alias always points to the final object
739ff4a156dSchristos      */
740ff4a156dSchristos     if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) &&
741ff4a156dSchristos         (Node->Type == ACPI_TYPE_LOCAL_ALIAS))
742ff4a156dSchristos     {
743ff4a156dSchristos         /* This node points back to the original PARSEOP_ALIAS */
744ff4a156dSchristos 
745ff4a156dSchristos         NextOp = Node->Op;
746ff4a156dSchristos 
747ff4a156dSchristos         /* The first child is the alias target op */
748ff4a156dSchristos 
749ff4a156dSchristos         NextOp = NextOp->Asl.Child;
750ff4a156dSchristos 
751ff4a156dSchristos         /* That in turn points back to original target alias node */
752ff4a156dSchristos 
753ff4a156dSchristos         if (NextOp->Asl.Node)
754ff4a156dSchristos         {
755ff4a156dSchristos             Node = NextOp->Asl.Node;
756ff4a156dSchristos         }
757ff4a156dSchristos 
758ff4a156dSchristos         /* Else - forward reference to alias, will be resolved later */
759ff4a156dSchristos     }
760ff4a156dSchristos 
761ff4a156dSchristos     /* 2) Check for a reference to a resource descriptor */
762ff4a156dSchristos 
763ff4a156dSchristos     if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
764ff4a156dSchristos         (Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
765ff4a156dSchristos     {
766ff4a156dSchristos         /*
767ff4a156dSchristos          * This was a reference to a field within a resource descriptor.
768ff4a156dSchristos          * Extract the associated field offset (either a bit or byte
769ff4a156dSchristos          * offset depending on the field type) and change the named
770ff4a156dSchristos          * reference into an integer for AML code generation
771ff4a156dSchristos          */
772ff4a156dSchristos         Offset = Node->Value;
773ff4a156dSchristos         TagBitLength = Node->Length;
774ff4a156dSchristos 
775ff4a156dSchristos         /*
776ff4a156dSchristos          * If a field is being created, generate the length (in bits) of
777ff4a156dSchristos          * the field. Note: Opcodes other than CreateXxxField and Index
778ff4a156dSchristos          * can come through here. For other opcodes, we just need to
779ff4a156dSchristos          * convert the resource tag reference to an integer offset.
780ff4a156dSchristos          */
781ff4a156dSchristos         switch (Op->Asl.Parent->Asl.AmlOpcode)
782ff4a156dSchristos         {
783ff4a156dSchristos         case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */
784ff4a156dSchristos             /*
785ff4a156dSchristos              * We know the length operand is an integer constant because
786ff4a156dSchristos              * we know that it contains a reference to a resource
787ff4a156dSchristos              * descriptor tag.
788ff4a156dSchristos              */
789ff4a156dSchristos             FieldBitLength = (UINT32) Op->Asl.Next->Asl.Value.Integer;
790ff4a156dSchristos             break;
791ff4a156dSchristos 
792ff4a156dSchristos         case AML_CREATE_BIT_FIELD_OP:
793ff4a156dSchristos 
794ff4a156dSchristos             FieldBitLength = 1;
795ff4a156dSchristos             break;
796ff4a156dSchristos 
797ff4a156dSchristos         case AML_CREATE_BYTE_FIELD_OP:
798ff4a156dSchristos         case AML_INDEX_OP:
799ff4a156dSchristos 
800ff4a156dSchristos             FieldBitLength = 8;
801ff4a156dSchristos             break;
802ff4a156dSchristos 
803ff4a156dSchristos         case AML_CREATE_WORD_FIELD_OP:
804ff4a156dSchristos 
805ff4a156dSchristos             FieldBitLength = 16;
806ff4a156dSchristos             break;
807ff4a156dSchristos 
808ff4a156dSchristos         case AML_CREATE_DWORD_FIELD_OP:
809ff4a156dSchristos 
810ff4a156dSchristos             FieldBitLength = 32;
811ff4a156dSchristos             break;
812ff4a156dSchristos 
813ff4a156dSchristos         case AML_CREATE_QWORD_FIELD_OP:
814ff4a156dSchristos 
815ff4a156dSchristos             FieldBitLength = 64;
816ff4a156dSchristos             break;
817ff4a156dSchristos 
818ff4a156dSchristos         default:
819ff4a156dSchristos 
820ff4a156dSchristos             FieldBitLength = 0;
821ff4a156dSchristos             break;
822ff4a156dSchristos         }
823ff4a156dSchristos 
824ff4a156dSchristos         /* Check the field length against the length of the resource tag */
825ff4a156dSchristos 
826ff4a156dSchristos         if (FieldBitLength)
827ff4a156dSchristos         {
828ff4a156dSchristos             if (TagBitLength < FieldBitLength)
829ff4a156dSchristos             {
830ff4a156dSchristos                 Message = ASL_MSG_TAG_SMALLER;
831ff4a156dSchristos             }
832ff4a156dSchristos             else if (TagBitLength > FieldBitLength)
833ff4a156dSchristos             {
834ff4a156dSchristos                 Message = ASL_MSG_TAG_LARGER;
835ff4a156dSchristos             }
836ff4a156dSchristos 
837ff4a156dSchristos             if (Message)
838ff4a156dSchristos             {
8397efa3256Schristos                 snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer),
84081bd9c9cSchristos                     "Size mismatch, Tag: %u bit%s, Field: %u bit%s",
841ff4a156dSchristos                     TagBitLength, (TagBitLength > 1) ? "s" : "",
842ff4a156dSchristos                     FieldBitLength, (FieldBitLength > 1) ? "s" : "");
843ff4a156dSchristos 
8447efa3256Schristos                 AslError (ASL_WARNING, Message, Op, AslGbl_MsgBuffer);
845ff4a156dSchristos             }
846ff4a156dSchristos         }
847ff4a156dSchristos 
848ff4a156dSchristos         /* Convert the BitOffset to a ByteOffset for certain opcodes */
849ff4a156dSchristos 
850ff4a156dSchristos         switch (Op->Asl.Parent->Asl.AmlOpcode)
851ff4a156dSchristos         {
852ff4a156dSchristos         case AML_CREATE_BYTE_FIELD_OP:
853ff4a156dSchristos         case AML_CREATE_WORD_FIELD_OP:
854ff4a156dSchristos         case AML_CREATE_DWORD_FIELD_OP:
855ff4a156dSchristos         case AML_CREATE_QWORD_FIELD_OP:
856ff4a156dSchristos         case AML_INDEX_OP:
857ff4a156dSchristos 
858ff4a156dSchristos             Offset = ACPI_DIV_8 (Offset);
859ff4a156dSchristos             break;
860ff4a156dSchristos 
861ff4a156dSchristos         default:
862ff4a156dSchristos 
863ff4a156dSchristos             break;
864ff4a156dSchristos         }
865ff4a156dSchristos 
866ff4a156dSchristos         /* Now convert this node to an integer whose value is the field offset */
867ff4a156dSchristos 
868ff4a156dSchristos         Op->Asl.AmlLength = 0;
869ff4a156dSchristos         Op->Asl.ParseOpcode = PARSEOP_INTEGER;
870ff4a156dSchristos         Op->Asl.Value.Integer = (UINT64) Offset;
871ae01dbf5Schristos         Op->Asl.CompileFlags |= OP_IS_RESOURCE_FIELD;
872ff4a156dSchristos 
873ff4a156dSchristos         OpcGenerateAmlOpcode (Op);
874ff4a156dSchristos     }
875ff4a156dSchristos 
876ff4a156dSchristos     /* 3) Check for a method invocation */
877ff4a156dSchristos 
878ff4a156dSchristos     else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) &&
879ff4a156dSchristos                 (Node->Type == ACPI_TYPE_METHOD) &&
880ff4a156dSchristos                 (Op->Asl.Parent) &&
881ff4a156dSchristos                 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD))   ||
882ff4a156dSchristos 
883ff4a156dSchristos                 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
884ff4a156dSchristos     {
885ff4a156dSchristos         /*
886ff4a156dSchristos          * A reference to a method within one of these opcodes is not an
887ff4a156dSchristos          * invocation of the method, it is simply a reference to the method.
88847dc3895Schristos          *
88947dc3895Schristos          * September 2016: Removed DeRefOf from this list
890531a0538Schristos          * July 2020: Added Alias to this list
891ff4a156dSchristos          */
892ff4a156dSchristos         if ((Op->Asl.Parent) &&
893ff4a156dSchristos             ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF)     ||
894cb2bd8f0Schristos             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_PACKAGE)    ||
895cb2bd8f0Schristos             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)||
896531a0538Schristos             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE) ||
897531a0538Schristos             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_ALIAS)))
898ff4a156dSchristos         {
899ff4a156dSchristos             return_ACPI_STATUS (AE_OK);
900ff4a156dSchristos         }
90147dc3895Schristos 
902ff4a156dSchristos         /*
903ff4a156dSchristos          * There are two types of method invocation:
904ff4a156dSchristos          * 1) Invocation with arguments -- the parser recognizes this
905ff4a156dSchristos          *    as a METHODCALL.
906ff4a156dSchristos          * 2) Invocation with no arguments --the parser cannot determine that
907ff4a156dSchristos          *    this is a method invocation, therefore we have to figure it out
908ff4a156dSchristos          *    here.
909ff4a156dSchristos          */
910ff4a156dSchristos         if (Node->Type != ACPI_TYPE_METHOD)
911ff4a156dSchristos         {
9127efa3256Schristos             snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "%s is a %s",
913ff4a156dSchristos                 Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type));
914ff4a156dSchristos 
9157efa3256Schristos             AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, AslGbl_MsgBuffer);
916ff4a156dSchristos             return_ACPI_STATUS (AE_OK);
917ff4a156dSchristos         }
918ff4a156dSchristos 
919ff4a156dSchristos         /* Save the method node in the caller's op */
920ff4a156dSchristos 
921ff4a156dSchristos         Op->Asl.Node = Node;
922ff4a156dSchristos         if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)
923ff4a156dSchristos         {
924ff4a156dSchristos             return_ACPI_STATUS (AE_OK);
925ff4a156dSchristos         }
926ff4a156dSchristos 
927ff4a156dSchristos         /*
928ff4a156dSchristos          * This is a method invocation, with or without arguments.
929ff4a156dSchristos          * Count the number of arguments, each appears as a child
930ff4a156dSchristos          * under the parent node
931ff4a156dSchristos          */
932ff4a156dSchristos         Op->Asl.ParseOpcode = PARSEOP_METHODCALL;
933ff4a156dSchristos         UtSetParseOpName (Op);
934ff4a156dSchristos 
935ff4a156dSchristos         PassedArgs = 0;
936ff4a156dSchristos         NextOp = Op->Asl.Child;
937ff4a156dSchristos 
938ff4a156dSchristos         while (NextOp)
939ff4a156dSchristos         {
940ff4a156dSchristos             PassedArgs++;
941ff4a156dSchristos             NextOp = NextOp->Asl.Next;
942ff4a156dSchristos         }
943ff4a156dSchristos 
9441c663068Schristos         if (Node->Value != ASL_EXTERNAL_METHOD_UNKNOWN_PARAMS &&
94549c2f1f4Schristos             Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_EXTERNAL)
946ff4a156dSchristos         {
947ff4a156dSchristos             /*
948ff4a156dSchristos              * Check the parsed arguments with the number expected by the
949ff4a156dSchristos              * method declaration itself
950ff4a156dSchristos              */
951ff4a156dSchristos             if (PassedArgs != Node->Value)
952ff4a156dSchristos             {
9531c663068Schristos                 if (Node->Flags & ANOBJ_IS_EXTERNAL)
9541c663068Schristos                 {
9551c663068Schristos                     snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer),
9561c663068Schristos                         "according to previous use, %s requires %u",
9571c663068Schristos                         Op->Asl.ExternalName, Node->Value);
9581c663068Schristos                 }
9591c663068Schristos                 else
9601c663068Schristos                 {
9611c663068Schristos                     snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer),
9621c663068Schristos 			"%s requires %u", Op->Asl.ExternalName,
963ff4a156dSchristos                         Node->Value);
9641c663068Schristos                 }
965ff4a156dSchristos 
966ff4a156dSchristos                 if (PassedArgs < Node->Value)
967ff4a156dSchristos                 {
9687efa3256Schristos                     AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, AslGbl_MsgBuffer);
969ff4a156dSchristos                 }
970ff4a156dSchristos                 else
971ff4a156dSchristos                 {
9727efa3256Schristos                     AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, AslGbl_MsgBuffer);
973ff4a156dSchristos                 }
974ff4a156dSchristos             }
975ff4a156dSchristos         }
9761c663068Schristos 
9771c663068Schristos         /*
9781c663068Schristos          * At this point, a method call to an external method has been
9791c663068Schristos          * detected. As of 11/19/2019, iASL does not support parameter counts
9801c663068Schristos          * for methods declared as external. Therefore, save the parameter
9811c663068Schristos          * count of the first method call and use this count check other
9821c663068Schristos          * method calls to ensure that the methods are being called with the
9831c663068Schristos          * same amount of parameters.
9841c663068Schristos          */
9851c663068Schristos         else if (Node->Type == ACPI_TYPE_METHOD &&
9861c663068Schristos             (Node->Flags & ANOBJ_IS_EXTERNAL) &&
9871c663068Schristos             Node->Value == ASL_EXTERNAL_METHOD_UNKNOWN_PARAMS &&
9881c663068Schristos             Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_EXTERNAL)
9891c663068Schristos         {
9901c663068Schristos             Node->Value = PassedArgs;
9911c663068Schristos         }
992ff4a156dSchristos     }
993ff4a156dSchristos 
994ff4a156dSchristos     /* 4) Check for an ASL Field definition */
995ff4a156dSchristos 
996ff4a156dSchristos     else if ((Op->Asl.Parent) &&
997ff4a156dSchristos             ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD)     ||
998ff4a156dSchristos              (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD)))
999ff4a156dSchristos     {
1000ff4a156dSchristos         /*
1001ff4a156dSchristos          * Offset checking for fields. If the parent operation region has a
1002ff4a156dSchristos          * constant length (known at compile time), we can check fields
1003ff4a156dSchristos          * defined in that region against the region length. This will catch
1004ff4a156dSchristos          * fields and field units that cannot possibly fit within the region.
1005ff4a156dSchristos          *
1006ff4a156dSchristos          * Note: Index fields do not directly reference an operation region,
1007ff4a156dSchristos          * thus they are not included in this check.
1008ff4a156dSchristos          */
1009ff4a156dSchristos         if (Op == Op->Asl.Parent->Asl.Child)
1010ff4a156dSchristos         {
1011ff4a156dSchristos             /*
1012ff4a156dSchristos              * This is the first child of the field node, which is
1013ff4a156dSchristos              * the name of the region. Get the parse node for the
1014ff4a156dSchristos              * region -- which contains the length of the region.
1015ff4a156dSchristos              */
1016ff4a156dSchristos             OwningOp = Node->Op;
1017ff4a156dSchristos             Op->Asl.Parent->Asl.ExtraValue =
1018ff4a156dSchristos                 ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer);
1019ff4a156dSchristos 
1020ff4a156dSchristos             /* Examine the field access width */
1021ff4a156dSchristos 
1022ff4a156dSchristos             switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer)
1023ff4a156dSchristos             {
1024ff4a156dSchristos             case AML_FIELD_ACCESS_ANY:
1025ff4a156dSchristos             case AML_FIELD_ACCESS_BYTE:
1026ff4a156dSchristos             case AML_FIELD_ACCESS_BUFFER:
1027ff4a156dSchristos             default:
1028ff4a156dSchristos 
1029ff4a156dSchristos                 MinimumLength = 1;
1030ff4a156dSchristos                 break;
1031ff4a156dSchristos 
1032ff4a156dSchristos             case AML_FIELD_ACCESS_WORD:
1033ff4a156dSchristos 
1034ff4a156dSchristos                 MinimumLength = 2;
1035ff4a156dSchristos                 break;
1036ff4a156dSchristos 
1037ff4a156dSchristos             case AML_FIELD_ACCESS_DWORD:
1038ff4a156dSchristos 
1039ff4a156dSchristos                 MinimumLength = 4;
1040ff4a156dSchristos                 break;
1041ff4a156dSchristos 
1042ff4a156dSchristos             case AML_FIELD_ACCESS_QWORD:
1043ff4a156dSchristos 
1044ff4a156dSchristos                 MinimumLength = 8;
1045ff4a156dSchristos                 break;
1046ff4a156dSchristos             }
1047ff4a156dSchristos 
1048ff4a156dSchristos             /*
1049ff4a156dSchristos              * Is the region at least as big as the access width?
1050ff4a156dSchristos              * Note: DataTableRegions have 0 length
1051ff4a156dSchristos              */
1052ff4a156dSchristos             if (((UINT32) OwningOp->Asl.Value.Integer) &&
1053ff4a156dSchristos                 ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength))
1054ff4a156dSchristos             {
1055ff4a156dSchristos                 AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL);
1056ff4a156dSchristos             }
1057ff4a156dSchristos 
1058ff4a156dSchristos             /*
1059ff4a156dSchristos              * Check EC/CMOS/SMBUS fields to make sure that the correct
1060ff4a156dSchristos              * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS)
1061ff4a156dSchristos              */
1062ff4a156dSchristos             SpaceIdOp = OwningOp->Asl.Child->Asl.Next;
1063ff4a156dSchristos             switch ((UINT32) SpaceIdOp->Asl.Value.Integer)
1064ff4a156dSchristos             {
1065ff4a156dSchristos             case ACPI_ADR_SPACE_EC:
1066ff4a156dSchristos             case ACPI_ADR_SPACE_CMOS:
1067ff4a156dSchristos             case ACPI_ADR_SPACE_GPIO:
1068ff4a156dSchristos 
106981bd9c9cSchristos                 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer !=
107081bd9c9cSchristos                     AML_FIELD_ACCESS_BYTE)
1071ff4a156dSchristos                 {
1072ff4a156dSchristos                     AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL);
1073ff4a156dSchristos                 }
1074ff4a156dSchristos                 break;
1075ff4a156dSchristos 
1076ff4a156dSchristos             case ACPI_ADR_SPACE_SMBUS:
1077ff4a156dSchristos             case ACPI_ADR_SPACE_IPMI:
1078ff4a156dSchristos             case ACPI_ADR_SPACE_GSBUS:
1079ff4a156dSchristos 
108081bd9c9cSchristos                 if ((UINT8) Op->Asl.Parent->Asl.Value.Integer !=
108181bd9c9cSchristos                     AML_FIELD_ACCESS_BUFFER)
1082ff4a156dSchristos                 {
1083ff4a156dSchristos                     AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL);
1084ff4a156dSchristos                 }
1085ff4a156dSchristos                 break;
1086ff4a156dSchristos 
1087ff4a156dSchristos             default:
1088ff4a156dSchristos 
1089ff4a156dSchristos                 /* Nothing to do for other address spaces */
1090ff4a156dSchristos 
1091ff4a156dSchristos                 break;
1092ff4a156dSchristos             }
1093ff4a156dSchristos         }
1094ff4a156dSchristos         else
1095ff4a156dSchristos         {
1096ff4a156dSchristos             /*
1097ff4a156dSchristos              * This is one element of the field list. Check to make sure
1098ff4a156dSchristos              * that it does not go beyond the end of the parent operation region.
1099ff4a156dSchristos              *
1100ff4a156dSchristos              * In the code below:
1101ff4a156dSchristos              *    Op->Asl.Parent->Asl.ExtraValue      - Region Length (bits)
1102ff4a156dSchristos              *    Op->Asl.ExtraValue                  - Field start offset (bits)
1103ff4a156dSchristos              *    Op->Asl.Child->Asl.Value.Integer32  - Field length (bits)
1104ff4a156dSchristos              *    Op->Asl.Child->Asl.ExtraValue       - Field access width (bits)
1105ff4a156dSchristos              */
1106ff4a156dSchristos             if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child)
1107ff4a156dSchristos             {
1108ff4a156dSchristos                 XfCheckFieldRange (Op,
1109ff4a156dSchristos                     Op->Asl.Parent->Asl.ExtraValue,
1110ff4a156dSchristos                     Op->Asl.ExtraValue,
1111ff4a156dSchristos                     (UINT32) Op->Asl.Child->Asl.Value.Integer,
1112ff4a156dSchristos                     Op->Asl.Child->Asl.ExtraValue);
1113ff4a156dSchristos             }
1114ff4a156dSchristos         }
1115ff4a156dSchristos     }
1116ff4a156dSchristos 
11175b948c02Schristos     /*
11185b948c02Schristos      * 5) Check for external resolution
1119f5b481b3Schristos      *
11205b948c02Schristos      * By this point, everything should be loaded in the namespace. If a
11215b948c02Schristos      * namespace lookup results in a namespace node that is an external, it
11225b948c02Schristos      * means that this named object was not defined in the input ASL. This
11235b948c02Schristos      * causes issues because there are plenty of incidents where developers
11245b948c02Schristos      * use the external keyword to suppress compiler errors about undefined
11255b948c02Schristos      * objects. Note: this only applies when compiling multiple definition
11265b948c02Schristos      * blocks.
1127f5b481b3Schristos      *
1128f5b481b3Schristos      * Do not check for external resolution in the following cases:
1129f5b481b3Schristos      *
1130f5b481b3Schristos      * case 1) External (ABCD)
1131f5b481b3Schristos      *
1132f5b481b3Schristos      *         This declares ABCD as an external so there is no requirement for
1133f5b481b3Schristos      *         ABCD to be loaded in the namespace when analyzing the actual
1134f5b481b3Schristos      *         External() statement.
1135f5b481b3Schristos      *
1136f5b481b3Schristos      * case 2) CondRefOf (ABCD)
1137f5b481b3Schristos      *
1138f5b481b3Schristos      *         This operator will query the ACPI namespace on the existence of
1139f5b481b3Schristos      *         ABCD. If ABCD does not exist, this operator will return a 0
1140f5b481b3Schristos      *         without incurring AML runtime errors. Therefore, ABCD is allowed
1141f5b481b3Schristos      *         to not exist when analyzing the CondRefOf operator.
1142f5b481b3Schristos      *
1143f5b481b3Schristos      * case 3) External (ABCD)
1144f5b481b3Schristos      *         if (CondRefOf (ABCD))
1145f5b481b3Schristos      *         {
1146f5b481b3Schristos      *             Store (0, ABCD)
1147f5b481b3Schristos      *         }
1148f5b481b3Schristos      *
1149f5b481b3Schristos      *         In this case, ABCD is accessed only if it exists due to the if
1150f5b481b3Schristos      *         statement so there is no need to flag the ABCD nested in the
1151f5b481b3Schristos      *         store operator.
11525b948c02Schristos      */
11535b948c02Schristos     if (AslGbl_ParseTreeRoot->Asl.Child && AslGbl_ParseTreeRoot->Asl.Child->Asl.Next &&
1154f5b481b3Schristos         (Node->Flags & ANOBJ_IS_EXTERNAL) &&
1155f5b481b3Schristos         Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_EXTERNAL &&
1156f5b481b3Schristos         Op->Asl.ParseOpcode != PARSEOP_EXTERNAL &&
1157f5b481b3Schristos         Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_CONDREFOF &&
1158f5b481b3Schristos         !XfRefIsGuardedByIfCondRefOf (Node, Op))
11595b948c02Schristos     {
1160b558e860Schristos         ExternalPath = AcpiNsGetNormalizedPathname (Node, TRUE);
1161b558e860Schristos         sprintf (AslGbl_MsgBuffer, "full path of external object: %s",
1162b558e860Schristos             ExternalPath);
1163b558e860Schristos         AslDualParseOpError (ASL_ERROR, ASL_MSG_UNDEFINED_EXTERNAL, Op, NULL,
1164b558e860Schristos             ASL_MSG_EXTERNAL_FOUND_HERE, Node->Op, AslGbl_MsgBuffer);
1165b558e860Schristos         if (ExternalPath)
1166b558e860Schristos         {
1167b558e860Schristos             ACPI_FREE (ExternalPath);
1168b558e860Schristos         }
11695b948c02Schristos     }
11705b948c02Schristos 
1171414ef032Schristos     /* 5) Check for a connection object */
1172414ef032Schristos #if 0
1173414ef032Schristos     else if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION)
1174414ef032Schristos     {
1175414ef032Schristos         return_ACPI_STATUS (Status);
1176414ef032Schristos     }
1177414ef032Schristos #endif
1178414ef032Schristos 
1179ff4a156dSchristos     Op->Asl.Node = Node;
1180ff4a156dSchristos     return_ACPI_STATUS (Status);
1181ff4a156dSchristos }
1182ff4a156dSchristos 
1183ff4a156dSchristos 
1184ff4a156dSchristos /*******************************************************************************
1185ff4a156dSchristos  *
1186f5b481b3Schristos  * FUNCTION:    XfRefIsGuardedByIfCondRefOf
1187f5b481b3Schristos  *
1188f5b481b3Schristos  * PARAMETERS:  Node        - Named object reference node
1189f5b481b3Schristos  *              Op          - Named object reference parse node
1190f5b481b3Schristos  *
1191f5b481b3Schristos  * RETURN:      BOOLEAN
1192f5b481b3Schristos  *
1193f5b481b3Schristos  * DESCRIPTION: returns true if Op checked inside if (CondRefOf (...))
1194f5b481b3Schristos  *              refers to Node.
1195f5b481b3Schristos  *
1196f5b481b3Schristos  ******************************************************************************/
1197f5b481b3Schristos 
1198f5b481b3Schristos static BOOLEAN
XfRefIsGuardedByIfCondRefOf(ACPI_NAMESPACE_NODE * Node,ACPI_PARSE_OBJECT * Op)1199f5b481b3Schristos XfRefIsGuardedByIfCondRefOf (
1200f5b481b3Schristos     ACPI_NAMESPACE_NODE     *Node,
1201f5b481b3Schristos     ACPI_PARSE_OBJECT       *Op)
1202f5b481b3Schristos {
1203f5b481b3Schristos     ACPI_PARSE_OBJECT       *Parent = Op->Asl.Parent;
1204f5b481b3Schristos 
1205f5b481b3Schristos 
1206f5b481b3Schristos     while (Parent)
1207f5b481b3Schristos     {
1208f5b481b3Schristos         if (Parent->Asl.ParseOpcode == PARSEOP_IF &&
1209f5b481b3Schristos             XfFindCondRefOfName (Node, Parent->Asl.Child))
1210f5b481b3Schristos         {
1211f5b481b3Schristos             return (TRUE);
1212f5b481b3Schristos         }
1213f5b481b3Schristos 
1214f5b481b3Schristos         Parent = Parent->Asl.Parent;
1215f5b481b3Schristos     }
1216f5b481b3Schristos 
1217f5b481b3Schristos     return (FALSE);
1218f5b481b3Schristos }
1219f5b481b3Schristos 
1220f5b481b3Schristos 
1221f5b481b3Schristos /*******************************************************************************
1222f5b481b3Schristos  *
1223f5b481b3Schristos  * FUNCTION:    XfRefIsGuardedByIfCondRefOf
1224f5b481b3Schristos  *
1225f5b481b3Schristos  * PARAMETERS:  Node        - Named object reference node
1226f5b481b3Schristos  *              Op          - Named object reference parse node
1227f5b481b3Schristos  *
1228f5b481b3Schristos  * RETURN:      BOOLEAN
1229f5b481b3Schristos  *
1230f5b481b3Schristos  * DESCRIPTION: returns true if Op checked inside if (CondRefOf (...))
1231f5b481b3Schristos  *              refers to Node.
1232f5b481b3Schristos  *
1233f5b481b3Schristos  ******************************************************************************/
1234f5b481b3Schristos 
1235f5b481b3Schristos static BOOLEAN
XfFindCondRefOfName(ACPI_NAMESPACE_NODE * Node,ACPI_PARSE_OBJECT * Op)1236f5b481b3Schristos XfFindCondRefOfName (
1237f5b481b3Schristos     ACPI_NAMESPACE_NODE     *Node,
1238f5b481b3Schristos     ACPI_PARSE_OBJECT       *Op)
1239f5b481b3Schristos {
1240f5b481b3Schristos     BOOLEAN                 CondRefOfFound = FALSE;
1241f5b481b3Schristos 
1242f5b481b3Schristos 
1243f5b481b3Schristos     if (!Op)
1244f5b481b3Schristos     {
1245f5b481b3Schristos         return (FALSE);
1246f5b481b3Schristos     }
1247f5b481b3Schristos 
1248f5b481b3Schristos     switch (Op->Asl.ParseOpcode)
1249f5b481b3Schristos     {
1250f5b481b3Schristos     case PARSEOP_CONDREFOF:
1251f5b481b3Schristos 
1252f5b481b3Schristos         return (Op->Asl.Child->Common.Node == Node);
1253f5b481b3Schristos         break;
1254f5b481b3Schristos 
1255f5b481b3Schristos     case PARSEOP_LAND:
1256f5b481b3Schristos 
1257f5b481b3Schristos         CondRefOfFound = XfFindCondRefOfName (Node, Op->Asl.Child);
1258f5b481b3Schristos         if (CondRefOfFound)
1259f5b481b3Schristos         {
1260f5b481b3Schristos             return (TRUE);
1261f5b481b3Schristos         }
1262f5b481b3Schristos 
1263f5b481b3Schristos         return (XfFindCondRefOfName (Node, Op->Asl.Child->Asl.Next));
1264f5b481b3Schristos         break;
1265f5b481b3Schristos 
1266f5b481b3Schristos     default:
1267f5b481b3Schristos 
1268f5b481b3Schristos         return (FALSE);
1269f5b481b3Schristos         break;
1270f5b481b3Schristos     }
1271f5b481b3Schristos }
1272f5b481b3Schristos 
1273f5b481b3Schristos 
1274f5b481b3Schristos /*******************************************************************************
1275f5b481b3Schristos  *
1276ff4a156dSchristos  * FUNCTION:    XfNamespaceLocateEnd
1277ff4a156dSchristos  *
1278ff4a156dSchristos  * PARAMETERS:  ASL_WALK_CALLBACK
1279ff4a156dSchristos  *
1280ff4a156dSchristos  * RETURN:      Status
1281ff4a156dSchristos  *
1282ff4a156dSchristos  * DESCRIPTION: Ascending callback used during cross reference. We only
1283ff4a156dSchristos  *              need to worry about scope management here.
1284ff4a156dSchristos  *
1285ff4a156dSchristos  ******************************************************************************/
1286ff4a156dSchristos 
1287ff4a156dSchristos static ACPI_STATUS
XfNamespaceLocateEnd(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)1288ff4a156dSchristos XfNamespaceLocateEnd (
1289ff4a156dSchristos     ACPI_PARSE_OBJECT       *Op,
1290ff4a156dSchristos     UINT32                  Level,
1291ff4a156dSchristos     void                    *Context)
1292ff4a156dSchristos {
1293ff4a156dSchristos     ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
1294ff4a156dSchristos     const ACPI_OPCODE_INFO  *OpInfo;
1295ff4a156dSchristos 
1296ff4a156dSchristos 
1297ff4a156dSchristos     ACPI_FUNCTION_TRACE (XfNamespaceLocateEnd);
1298ff4a156dSchristos 
1299ff4a156dSchristos 
1300ff4a156dSchristos     /* We are only interested in opcodes that have an associated name */
1301ff4a156dSchristos 
1302ff4a156dSchristos     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
1303ff4a156dSchristos     if (!(OpInfo->Flags & AML_NAMED))
1304ff4a156dSchristos     {
1305ff4a156dSchristos         return_ACPI_STATUS (AE_OK);
1306ff4a156dSchristos     }
1307ff4a156dSchristos 
1308ff4a156dSchristos     /* Not interested in name references, we did not open a scope for them */
1309ff4a156dSchristos 
1310ff4a156dSchristos     if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
1311ff4a156dSchristos         (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
1312ae01dbf5Schristos         (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
1313ae01dbf5Schristos         (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL))
1314ff4a156dSchristos     {
1315ff4a156dSchristos         return_ACPI_STATUS (AE_OK);
1316ff4a156dSchristos     }
1317ff4a156dSchristos 
1318ff4a156dSchristos     /* Pop the scope stack if necessary */
1319ff4a156dSchristos 
1320ff4a156dSchristos     if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode)))
1321ff4a156dSchristos     {
1322ff4a156dSchristos 
1323ff4a156dSchristos         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
1324ff4a156dSchristos             "%s: Popping scope for Op %p\n",
1325ff4a156dSchristos             AcpiUtGetTypeName (OpInfo->ObjectType), Op));
1326ff4a156dSchristos 
1327ff4a156dSchristos         (void) AcpiDsScopeStackPop (WalkState);
1328ff4a156dSchristos     }
1329ff4a156dSchristos 
1330ff4a156dSchristos     return_ACPI_STATUS (AE_OK);
1331ff4a156dSchristos }
13325b948c02Schristos 
13335b948c02Schristos 
13345b948c02Schristos /*******************************************************************************
13355b948c02Schristos  *
13365b948c02Schristos  * FUNCTION:    XfValidateCrossReference
13375b948c02Schristos  *
13385b948c02Schristos  * PARAMETERS:  Op                      - Parse Op that references the object
13395b948c02Schristos  *              OpInfo                  - Parse Op info struct
13405b948c02Schristos  *              Node                    - Node for the referenced object
13415b948c02Schristos  *
13425b948c02Schristos  * RETURN:      TRUE if the reference is legal, FALSE otherwise
13435b948c02Schristos  *
13445b948c02Schristos  * DESCRIPTION: Determine if a reference to another object is allowed.
13455b948c02Schristos  *
13465b948c02Schristos  * EXAMPLE:
13475b948c02Schristos  *      Method (A) {Name (INT1, 1)}     Declaration of object INT1
13485b948c02Schristos  *      Method (B) (Store (2, \A.INT1)} Illegal reference to object INT1
13495b948c02Schristos  *                                      (INT1 is temporary, valid only during
13505b948c02Schristos  *                                      execution of A)
13515b948c02Schristos  *
13525b948c02Schristos  * NOTES:
13539ddb8508Schristos  *      A null pointer returned by either UtGetParentMethodOp or
13549ddb8508Schristos  *      UtGetParentMethodNode indicates that the parameter object is not
13555b948c02Schristos  *      within a control method.
13565b948c02Schristos  *
13575b948c02Schristos  *      Five cases are handled: Case(Op, Node)
13585b948c02Schristos  *      1) Case(0,0): Op is not within a method, Node is not    --> OK
13595b948c02Schristos  *      2) Case(0,1): Op is not within a method, but Node is    --> Illegal
13605b948c02Schristos  *      3) Case(1,0): Op is within a method, Node is not        --> OK
13615b948c02Schristos  *      4) Case(1,1): Both are within the same method           --> OK
13625b948c02Schristos  *      5) Case(1,1): Both are in methods, but not same method  --> Illegal
13635b948c02Schristos  *
13645b948c02Schristos  ******************************************************************************/
13655b948c02Schristos 
13665b948c02Schristos static BOOLEAN
XfValidateCrossReference(ACPI_PARSE_OBJECT * Op,const ACPI_OPCODE_INFO * OpInfo,ACPI_NAMESPACE_NODE * Node)13675b948c02Schristos XfValidateCrossReference (
13685b948c02Schristos     ACPI_PARSE_OBJECT       *Op,
13695b948c02Schristos     const ACPI_OPCODE_INFO  *OpInfo,
13705b948c02Schristos     ACPI_NAMESPACE_NODE     *Node)
13715b948c02Schristos {
13725b948c02Schristos     ACPI_PARSE_OBJECT       *ReferencingMethodOp;
13735b948c02Schristos     ACPI_NAMESPACE_NODE     *ReferencedMethodNode;
13745b948c02Schristos 
13755b948c02Schristos 
13765b948c02Schristos     /* Ignore actual named (and related) object declarations */
13775b948c02Schristos 
13785b948c02Schristos     if (OpInfo->Flags & (AML_NAMED | AML_CREATE | AML_DEFER | AML_HAS_ARGS))
13795b948c02Schristos     {
13805b948c02Schristos         return (TRUE);
13815b948c02Schristos     }
13825b948c02Schristos 
13835b948c02Schristos     /*
13845b948c02Schristos      * 1) Search upwards in parse tree for owner of the referencing object
13855b948c02Schristos      * 2) Search upwards in namespace to find the owner of the referenced object
13865b948c02Schristos      */
13879ddb8508Schristos     ReferencingMethodOp = UtGetParentMethodOp (Op);
13889ddb8508Schristos     ReferencedMethodNode = UtGetParentMethodNode (Node);
13895b948c02Schristos 
13905b948c02Schristos     if (!ReferencingMethodOp && !ReferencedMethodNode)
13915b948c02Schristos     {
13925b948c02Schristos         /*
13935b948c02Schristos          * 1) Case (0,0): Both Op and Node are not within methods
13945b948c02Schristos          * --> OK
13955b948c02Schristos          */
13965b948c02Schristos         return (TRUE);
13975b948c02Schristos     }
13985b948c02Schristos 
13995b948c02Schristos     if (!ReferencingMethodOp && ReferencedMethodNode)
14005b948c02Schristos     {
14015b948c02Schristos         /*
14025b948c02Schristos          * 2) Case (0,1): Op is not in a method, but Node is within a
14035b948c02Schristos          * method --> illegal
14045b948c02Schristos          */
14055b948c02Schristos         return (FALSE);
14065b948c02Schristos     }
14075b948c02Schristos     else if (ReferencingMethodOp && !ReferencedMethodNode)
14085b948c02Schristos     {
14095b948c02Schristos         /*
14105b948c02Schristos          * 3) Case (1,0): Op is within a method, but Node is not
14115b948c02Schristos          * --> OK
14125b948c02Schristos          */
14135b948c02Schristos         return (TRUE);
14145b948c02Schristos     }
14155b948c02Schristos     else if (ReferencingMethodOp->Asl.Node == ReferencedMethodNode)
14165b948c02Schristos     {
14175b948c02Schristos         /*
14185b948c02Schristos          * 4) Case (1,1): Both Op and Node are within the same method
14195b948c02Schristos          * --> OK
14205b948c02Schristos          */
14215b948c02Schristos         return (TRUE);
14225b948c02Schristos     }
14235b948c02Schristos     else
14245b948c02Schristos     {
14255b948c02Schristos         /*
14265b948c02Schristos          * 5) Case (1,1), Op and Node are in different methods
14275b948c02Schristos          * --> Illegal
14285b948c02Schristos          */
14295b948c02Schristos         return (FALSE);
14305b948c02Schristos     }
14315b948c02Schristos }
1432