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