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