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