aslwalks.c revision 1.1.1.8 1 /******************************************************************************
2 *
3 * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2017, 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
49
50 #define _COMPONENT ACPI_COMPILER
51 ACPI_MODULE_NAME ("aslwalks")
52
53
54 /* Local prototypes */
55
56 static void
57 AnAnalyzeStoreOperator (
58 ACPI_PARSE_OBJECT *Op);
59
60
61 /*******************************************************************************
62 *
63 * FUNCTION: AnMethodTypingWalkEnd
64 *
65 * PARAMETERS: ASL_WALK_CALLBACK
66 *
67 * RETURN: Status
68 *
69 * DESCRIPTION: Ascending callback for typing walk. Complete the method
70 * return analysis. Check methods for:
71 * 1) Initialized local variables
72 * 2) Valid arguments
73 * 3) Return types
74 *
75 ******************************************************************************/
76
77 ACPI_STATUS
78 AnMethodTypingWalkEnd (
79 ACPI_PARSE_OBJECT *Op,
80 UINT32 Level,
81 void *Context)
82 {
83 UINT32 ThisOpBtype;
84
85
86 switch (Op->Asl.ParseOpcode)
87 {
88 case PARSEOP_METHOD:
89
90 Op->Asl.CompileFlags |= NODE_METHOD_TYPED;
91 break;
92
93 case PARSEOP_RETURN:
94
95 if ((Op->Asl.Child) &&
96 (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
97 {
98 ThisOpBtype = AnGetBtype (Op->Asl.Child);
99
100 if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
101 (ThisOpBtype == (ACPI_UINT32_MAX -1)))
102 {
103 /*
104 * The called method is untyped at this time (typically a
105 * forward reference).
106 *
107 * Check for a recursive method call first. Note: the
108 * Child->Node will be null if the method has not been
109 * resolved.
110 */
111 if (Op->Asl.Child->Asl.Node &&
112 (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op))
113 {
114 /* We must type the method here */
115
116 TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
117 ASL_WALK_VISIT_UPWARD, NULL,
118 AnMethodTypingWalkEnd, NULL);
119
120 ThisOpBtype = AnGetBtype (Op->Asl.Child);
121 }
122 }
123
124 /* Returns a value, save the value type */
125
126 if (Op->Asl.ParentMethod)
127 {
128 Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisOpBtype;
129 }
130 }
131 break;
132
133 default:
134
135 break;
136 }
137
138 return (AE_OK);
139 }
140
141
142 /*******************************************************************************
143 *
144 * FUNCTION: AnOperandTypecheckWalkEnd
145 *
146 * PARAMETERS: ASL_WALK_CALLBACK
147 *
148 * RETURN: Status
149 *
150 * DESCRIPTION: Ascending callback for analysis walk. Complete method
151 * return analysis.
152 *
153 ******************************************************************************/
154
155 ACPI_STATUS
156 AnOperandTypecheckWalkEnd (
157 ACPI_PARSE_OBJECT *Op,
158 UINT32 Level,
159 void *Context)
160 {
161 const ACPI_OPCODE_INFO *OpInfo;
162 UINT32 RuntimeArgTypes;
163 UINT32 RuntimeArgTypes2;
164 UINT32 RequiredBtypes;
165 UINT32 ThisNodeBtype;
166 UINT32 CommonBtypes;
167 UINT32 OpcodeClass;
168 ACPI_PARSE_OBJECT *ArgOp;
169 UINT32 ArgType;
170
171
172 switch (Op->Asl.AmlOpcode)
173 {
174 case AML_RAW_DATA_BYTE:
175 case AML_RAW_DATA_WORD:
176 case AML_RAW_DATA_DWORD:
177 case AML_RAW_DATA_QWORD:
178 case AML_RAW_DATA_BUFFER:
179 case AML_RAW_DATA_CHAIN:
180 case AML_PACKAGE_LENGTH:
181 case AML_UNASSIGNED_OPCODE:
182 case AML_DEFAULT_ARG_OP:
183
184 /* Ignore the internal (compiler-only) AML opcodes */
185
186 return (AE_OK);
187
188 default:
189
190 break;
191 }
192
193 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
194 if (!OpInfo)
195 {
196 return (AE_OK);
197 }
198
199 ArgOp = Op->Asl.Child;
200 OpcodeClass = OpInfo->Class;
201 RuntimeArgTypes = OpInfo->RuntimeArgs;
202
203 #ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
204 /*
205 * Update 11/2008: In practice, we can't perform this check. A simple
206 * analysis is not sufficient. Also, it can cause errors when compiling
207 * disassembled code because of the way Switch operators are implemented
208 * (a While(One) loop with a named temp variable created within.)
209 */
210
211 /*
212 * If we are creating a named object, check if we are within a while loop
213 * by checking if the parent is a WHILE op. This is a simple analysis, but
214 * probably sufficient for many cases.
215 *
216 * Allow Scope(), Buffer(), and Package().
217 */
218 if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) ||
219 ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE)))
220 {
221 if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP)
222 {
223 AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL);
224 }
225 }
226 #endif
227
228 /*
229 * Special case for control opcodes IF/RETURN/WHILE since they
230 * have no runtime arg list (at this time)
231 */
232 switch (Op->Asl.AmlOpcode)
233 {
234 case AML_IF_OP:
235 case AML_WHILE_OP:
236 case AML_RETURN_OP:
237
238 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
239 {
240 /* Check for an internal method */
241
242 if (AnIsInternalMethod (ArgOp))
243 {
244 return (AE_OK);
245 }
246
247 /* The lone arg is a method call, check it */
248
249 RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
250 if (Op->Asl.AmlOpcode == AML_RETURN_OP)
251 {
252 RequiredBtypes = 0xFFFFFFFF;
253 }
254
255 ThisNodeBtype = AnGetBtype (ArgOp);
256 if (ThisNodeBtype == ACPI_UINT32_MAX)
257 {
258 return (AE_OK);
259 }
260
261 AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
262 RequiredBtypes, ThisNodeBtype);
263 }
264 return (AE_OK);
265
266 case AML_EXTERNAL_OP:
267 /*
268 * Not really a "runtime" opcode since it used by disassembler only.
269 * The parser will find any issues with the operands.
270 */
271 return (AE_OK);
272
273 default:
274
275 break;
276 }
277
278 /* Ignore the non-executable opcodes */
279
280 if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
281 {
282 return (AE_OK);
283 }
284
285 /*
286 * Special handling for certain opcodes.
287 */
288 switch (Op->Asl.AmlOpcode)
289 {
290 /* BankField has one TermArg */
291
292 case AML_BANK_FIELD_OP:
293
294 OpcodeClass = AML_CLASS_EXECUTE;
295 ArgOp = ArgOp->Asl.Next;
296 ArgOp = ArgOp->Asl.Next;
297 break;
298
299 /* Operation Region has 2 TermArgs */
300
301 case AML_REGION_OP:
302
303 OpcodeClass = AML_CLASS_EXECUTE;
304 ArgOp = ArgOp->Asl.Next;
305 ArgOp = ArgOp->Asl.Next;
306 break;
307
308 /* DataTableRegion has 3 TermArgs */
309
310 case AML_DATA_REGION_OP:
311
312 OpcodeClass = AML_CLASS_EXECUTE;
313 ArgOp = ArgOp->Asl.Next;
314 break;
315
316 /* Buffers/Packages have a length that is a TermArg */
317
318 case AML_BUFFER_OP:
319 case AML_PACKAGE_OP:
320 case AML_VAR_PACKAGE_OP:
321
322 /* If length is a constant, we are done */
323
324 if ((ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) ||
325 (ArgOp->Asl.ParseOpcode == PARSEOP_RAW_DATA))
326 {
327 return (AE_OK);
328 }
329 break;
330
331 /* Store can write any object to the Debug object */
332
333 case AML_STORE_OP:
334 /*
335 * If this is a Store() to the Debug object, we don't need
336 * to perform any further validation -- because a Store of
337 * any object to Debug is permitted and supported.
338 */
339 if (ArgOp->Asl.Next->Asl.AmlOpcode == AML_DEBUG_OP)
340 {
341 return (AE_OK);
342 }
343 break;
344
345 default:
346 break;
347 }
348
349 switch (OpcodeClass)
350 {
351 case AML_CLASS_EXECUTE:
352 case AML_CLASS_CREATE:
353 case AML_CLASS_CONTROL:
354 case AML_CLASS_RETURN_VALUE:
355
356 /* Reverse the runtime argument list */
357
358 RuntimeArgTypes2 = 0;
359 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
360 {
361 RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
362 RuntimeArgTypes2 |= ArgType;
363 INCREMENT_ARG_LIST (RuntimeArgTypes);
364 }
365
366 /* Typecheck each argument */
367
368 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
369 {
370 /* Get the required type(s) for the argument */
371
372 RequiredBtypes = AnMapArgTypeToBtype (ArgType);
373
374 if (!ArgOp)
375 {
376 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
377 "Null ArgOp in argument loop");
378 AslAbort ();
379 }
380
381 /* Get the actual type of the argument */
382
383 ThisNodeBtype = AnGetBtype (ArgOp);
384 if (ThisNodeBtype == ACPI_UINT32_MAX)
385 {
386 goto NextArgument;
387 }
388
389 /* Examine the arg based on the required type of the arg */
390
391 switch (ArgType)
392 {
393 case ARGI_TARGETREF:
394
395 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
396 {
397 /* ZERO is the placeholder for "don't store result" */
398
399 ThisNodeBtype = RequiredBtypes;
400 break;
401 }
402
403 /* Fallthrough */
404
405 case ARGI_STORE_TARGET:
406
407 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
408 {
409 /*
410 * This is the case where an original reference to a resource
411 * descriptor field has been replaced by an (Integer) offset.
412 * These named fields are supported at compile-time only;
413 * the names are not passed to the interpreter (via the AML).
414 */
415 if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
416 (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
417 {
418 AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD,
419 ArgOp, NULL);
420 }
421 else
422 {
423 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE,
424 ArgOp, NULL);
425 }
426 }
427 break;
428
429
430 #ifdef __FUTURE_IMPLEMENTATION
431 /*
432 * Possible future typechecking support
433 */
434 case ARGI_REFERENCE: /* References */
435 case ARGI_INTEGER_REF:
436 case ARGI_OBJECT_REF:
437 case ARGI_DEVICE_REF:
438
439 switch (ArgOp->Asl.ParseOpcode)
440 {
441 case PARSEOP_LOCAL0:
442 case PARSEOP_LOCAL1:
443 case PARSEOP_LOCAL2:
444 case PARSEOP_LOCAL3:
445 case PARSEOP_LOCAL4:
446 case PARSEOP_LOCAL5:
447 case PARSEOP_LOCAL6:
448 case PARSEOP_LOCAL7:
449
450 /* TBD: implement analysis of current value (type) of the local */
451 /* For now, just treat any local as a typematch */
452
453 /*ThisNodeBtype = RequiredBtypes;*/
454 break;
455
456 case PARSEOP_ARG0:
457 case PARSEOP_ARG1:
458 case PARSEOP_ARG2:
459 case PARSEOP_ARG3:
460 case PARSEOP_ARG4:
461 case PARSEOP_ARG5:
462 case PARSEOP_ARG6:
463
464 /* Hard to analyze argument types, so we won't */
465 /* for now. Just treat any arg as a typematch */
466
467 /* ThisNodeBtype = RequiredBtypes; */
468 break;
469
470 case PARSEOP_DEBUG:
471 case PARSEOP_REFOF:
472 case PARSEOP_INDEX:
473 default:
474
475 break;
476 }
477 break;
478 #endif
479 case ARGI_INTEGER:
480 default:
481
482 break;
483 }
484
485
486 /* Check for a type mismatch (required versus actual) */
487
488 CommonBtypes = ThisNodeBtype & RequiredBtypes;
489
490 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
491 {
492 if (AnIsInternalMethod (ArgOp))
493 {
494 return (AE_OK);
495 }
496
497 /* Check a method call for a valid return value */
498
499 AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
500 RequiredBtypes, ThisNodeBtype);
501 }
502
503 /*
504 * Now check if the actual type(s) match at least one
505 * bit to the required type
506 */
507 else if (!CommonBtypes)
508 {
509 /* No match -- this is a type mismatch error */
510
511 AnFormatBtype (StringBuffer, ThisNodeBtype);
512 AnFormatBtype (StringBuffer2, RequiredBtypes);
513
514 sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]",
515 StringBuffer, OpInfo->Name, StringBuffer2);
516
517 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE,
518 ArgOp, MsgBuffer);
519 }
520
521 NextArgument:
522 ArgOp = ArgOp->Asl.Next;
523 INCREMENT_ARG_LIST (RuntimeArgTypes2);
524 }
525 break;
526
527 default:
528
529 break;
530 }
531
532 return (AE_OK);
533 }
534
535
536 /*******************************************************************************
537 *
538 * FUNCTION: AnOtherSemanticAnalysisWalkBegin
539 *
540 * PARAMETERS: ASL_WALK_CALLBACK
541 *
542 * RETURN: Status
543 *
544 * DESCRIPTION: Descending callback for the analysis walk. Checks for
545 * miscellaneous issues in the code.
546 *
547 ******************************************************************************/
548
549 ACPI_STATUS
550 AnOtherSemanticAnalysisWalkBegin (
551 ACPI_PARSE_OBJECT *Op,
552 UINT32 Level,
553 void *Context)
554 {
555 ACPI_PARSE_OBJECT *ArgOp;
556 ACPI_PARSE_OBJECT *PrevArgOp = NULL;
557 const ACPI_OPCODE_INFO *OpInfo;
558 ACPI_NAMESPACE_NODE *Node;
559
560
561 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
562
563
564 /*
565 * Determine if an execution class operator actually does something by
566 * checking if it has a target and/or the function return value is used.
567 * (Target is optional, so a standalone statement can actually do nothing.)
568 */
569 if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
570 (OpInfo->Flags & AML_HAS_RETVAL) &&
571 (!AnIsResultUsed (Op)))
572 {
573 if (OpInfo->Flags & AML_HAS_TARGET)
574 {
575 /*
576 * Find the target node, it is always the last child. If the target
577 * is not specified in the ASL, a default node of type Zero was
578 * created by the parser.
579 */
580 ArgOp = Op->Asl.Child;
581 while (ArgOp->Asl.Next)
582 {
583 PrevArgOp = ArgOp;
584 ArgOp = ArgOp->Asl.Next;
585 }
586
587 /* Divide() is the only weird case, it has two targets */
588
589 if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
590 {
591 if ((ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) &&
592 (PrevArgOp) &&
593 (PrevArgOp->Asl.ParseOpcode == PARSEOP_ZERO))
594 {
595 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
596 Op, Op->Asl.ExternalName);
597 }
598 }
599
600 else if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
601 {
602 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
603 Op, Op->Asl.ExternalName);
604 }
605 }
606 else
607 {
608 /*
609 * Has no target and the result is not used. Only a couple opcodes
610 * can have this combination.
611 */
612 switch (Op->Asl.ParseOpcode)
613 {
614 case PARSEOP_ACQUIRE:
615 case PARSEOP_WAIT:
616 case PARSEOP_LOADTABLE:
617
618 break;
619
620 default:
621
622 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
623 Op, Op->Asl.ExternalName);
624 break;
625 }
626 }
627 }
628
629
630 /*
631 * Semantic checks for individual ASL operators
632 */
633 switch (Op->Asl.ParseOpcode)
634 {
635 case PARSEOP_STORE:
636
637 if (Gbl_DoTypechecking)
638 {
639 AnAnalyzeStoreOperator (Op);
640 }
641 break;
642
643
644 case PARSEOP_ACQUIRE:
645 case PARSEOP_WAIT:
646 /*
647 * Emit a warning if the timeout parameter for these operators is not
648 * ACPI_WAIT_FOREVER, and the result value from the operator is not
649 * checked, meaning that a timeout could happen, but the code
650 * would not know about it.
651 */
652
653 /* First child is the namepath, 2nd child is timeout */
654
655 ArgOp = Op->Asl.Child;
656 ArgOp = ArgOp->Asl.Next;
657
658 /*
659 * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
660 * 0xFFFF or greater
661 */
662 if (((ArgOp->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
663 (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)) &&
664 (ArgOp->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
665 {
666 break;
667 }
668
669 /*
670 * The operation could timeout. If the return value is not used
671 * (indicates timeout occurred), issue a warning
672 */
673 if (!AnIsResultUsed (Op))
674 {
675 AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgOp,
676 Op->Asl.ExternalName);
677 }
678 break;
679
680 case PARSEOP_CREATEFIELD:
681 /*
682 * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand
683 */
684 ArgOp = Op->Asl.Child;
685 ArgOp = ArgOp->Asl.Next;
686 ArgOp = ArgOp->Asl.Next;
687
688 if ((ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) ||
689 ((ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) &&
690 (ArgOp->Asl.Value.Integer == 0)))
691 {
692 AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgOp, NULL);
693 }
694 break;
695
696 case PARSEOP_CONNECTION:
697 /*
698 * Ensure that the referenced operation region has the correct SPACE_ID.
699 * From the grammar/parser, we know the parent is a FIELD definition.
700 */
701 ArgOp = Op->Asl.Parent; /* Field definition */
702 ArgOp = ArgOp->Asl.Child; /* First child is the OpRegion Name */
703 Node = ArgOp->Asl.Node; /* OpRegion namespace node */
704 if (!Node)
705 {
706 break;
707 }
708
709 ArgOp = Node->Op; /* OpRegion definition */
710 ArgOp = ArgOp->Asl.Child; /* First child is the OpRegion Name */
711 ArgOp = ArgOp->Asl.Next; /* Next peer is the SPACE_ID (what we want) */
712
713 /*
714 * The Connection() operator is only valid for the following operation
715 * region SpaceIds: GeneralPurposeIo and GenericSerialBus.
716 */
717 if ((ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
718 (ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
719 {
720 AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL);
721 }
722 break;
723
724 case PARSEOP_FIELD:
725 /*
726 * Ensure that fields for GeneralPurposeIo and GenericSerialBus
727 * contain at least one Connection() operator
728 */
729 ArgOp = Op->Asl.Child; /* 1st child is the OpRegion Name */
730 Node = ArgOp->Asl.Node; /* OpRegion namespace node */
731 if (!Node)
732 {
733 break;
734 }
735
736 ArgOp = Node->Op; /* OpRegion definition */
737 ArgOp = ArgOp->Asl.Child; /* First child is the OpRegion Name */
738 ArgOp = ArgOp->Asl.Next; /* Next peer is the SPACE_ID (what we want) */
739
740 /* We are only interested in GeneralPurposeIo and GenericSerialBus */
741
742 if ((ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
743 (ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
744 {
745 break;
746 }
747
748 ArgOp = Op->Asl.Child; /* 1st child is the OpRegion Name */
749 ArgOp = ArgOp->Asl.Next; /* AccessType */
750 ArgOp = ArgOp->Asl.Next; /* LockRule */
751 ArgOp = ArgOp->Asl.Next; /* UpdateRule */
752 ArgOp = ArgOp->Asl.Next; /* Start of FieldUnitList */
753
754 /* Walk the FieldUnitList */
755
756 while (ArgOp)
757 {
758 if (ArgOp->Asl.ParseOpcode == PARSEOP_CONNECTION)
759 {
760 break;
761 }
762 else if (ArgOp->Asl.ParseOpcode == PARSEOP_NAMESEG)
763 {
764 AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgOp, NULL);
765 break;
766 }
767
768 ArgOp = ArgOp->Asl.Next;
769 }
770 break;
771
772 default:
773
774 break;
775 }
776
777 return (AE_OK);
778 }
779
780
781 /*******************************************************************************
782 *
783 * FUNCTION: AnAnalyzeStoreOperator
784 *
785 * PARAMETERS: Op - Store() operator
786 *
787 * RETURN: None
788 *
789 * DESCRIPTION: Analyze a store operator. Mostly for stores to/from package
790 * objects where there are more restrictions than other data
791 * types.
792 *
793 ******************************************************************************/
794
795 static void
796 AnAnalyzeStoreOperator (
797 ACPI_PARSE_OBJECT *Op)
798 {
799 ACPI_NAMESPACE_NODE *SourceNode;
800 ACPI_NAMESPACE_NODE *TargetNode;
801 ACPI_PARSE_OBJECT *SourceOperandOp;
802 ACPI_PARSE_OBJECT *TargetOperandOp;
803 UINT32 SourceOperandBtype;
804 UINT32 TargetOperandBtype;
805
806
807 /* Extract the two operands for STORE */
808
809 SourceOperandOp = Op->Asl.Child;
810 TargetOperandOp = SourceOperandOp->Asl.Next;
811
812 /*
813 * Ignore these Source operand opcodes, they cannot be typechecked,
814 * the actual result is unknown here.
815 */
816 switch (SourceOperandOp->Asl.ParseOpcode)
817 {
818 /* For these, type of the returned value is unknown at compile time */
819
820 case PARSEOP_DEREFOF:
821 case PARSEOP_METHODCALL:
822 case PARSEOP_STORE:
823 case PARSEOP_COPYOBJECT:
824
825 return;
826
827 case PARSEOP_INDEX:
828 case PARSEOP_REFOF:
829
830 if (!Gbl_EnableReferenceTypechecking)
831 {
832 return;
833 }
834
835 /*
836 * These opcodes always return an object reference, and thus
837 * the result can only be stored to a Local, Arg, or Debug.
838 */
839 if (TargetOperandOp->Asl.AmlOpcode == AML_DEBUG_OP)
840 {
841 return;
842 }
843
844 if ((TargetOperandOp->Asl.AmlOpcode < AML_LOCAL0) ||
845 (TargetOperandOp->Asl.AmlOpcode > AML_ARG6))
846 {
847 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, TargetOperandOp,
848 "Source [Reference], Target must be [Local/Arg/Debug]");
849 }
850 return;
851
852 default:
853 break;
854 }
855
856 /*
857 * Ignore these Target operand opcodes, they cannot be typechecked
858 */
859 switch (TargetOperandOp->Asl.ParseOpcode)
860 {
861 case PARSEOP_DEBUG:
862 case PARSEOP_DEREFOF:
863 case PARSEOP_REFOF:
864 case PARSEOP_INDEX:
865 case PARSEOP_STORE:
866
867 return;
868
869 default:
870 break;
871 }
872
873 /*
874 * Ignore typecheck for External() operands of type "UnknownObj",
875 * we don't know the actual type (source or target).
876 */
877 SourceNode = SourceOperandOp->Asl.Node;
878 if (SourceNode &&
879 (SourceNode->Flags & ANOBJ_IS_EXTERNAL) &&
880 (SourceNode->Type == ACPI_TYPE_ANY))
881 {
882 return;
883 }
884
885 TargetNode = TargetOperandOp->Asl.Node;
886 if (TargetNode &&
887 (TargetNode->Flags & ANOBJ_IS_EXTERNAL) &&
888 (TargetNode->Type == ACPI_TYPE_ANY))
889 {
890 return;
891 }
892
893 /*
894 * A NULL node with a namepath AML opcode indicates non-existent
895 * name. Just return, the error message is generated elsewhere.
896 */
897 if ((!SourceNode && (SourceOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)) ||
898 (!TargetNode && (TargetOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)))
899 {
900 return;
901 }
902
903 /*
904 * Simple check for source same as target via NS node.
905 * -- Could be expanded to locals and args.
906 */
907 if (SourceNode && TargetNode)
908 {
909 if (SourceNode == TargetNode)
910 {
911 AslError (ASL_WARNING, ASL_MSG_DUPLICATE_ITEM,
912 TargetOperandOp, "Source is the same as Target");
913 return;
914 }
915 }
916
917 /* Ignore typecheck if either source or target is a local or arg */
918
919 if ((SourceOperandOp->Asl.AmlOpcode >= AML_LOCAL0) &&
920 (SourceOperandOp->Asl.AmlOpcode <= AML_ARG6))
921 {
922 return; /* Cannot type a local/arg at compile time */
923 }
924
925 if ((TargetOperandOp->Asl.AmlOpcode >= AML_LOCAL0) &&
926 (TargetOperandOp->Asl.AmlOpcode <= AML_ARG6))
927 {
928 return; /* Cannot type a local/arg at compile time */
929 }
930
931 /*
932 * Package objects are a special case because they cannot by implicitly
933 * converted to/from anything. Check for these two illegal cases:
934 *
935 * Store (non-package, package)
936 * Store (package, non-package)
937 */
938 SourceOperandBtype = AnGetBtype (SourceOperandOp);
939 TargetOperandBtype = AnGetBtype (TargetOperandOp);
940
941 /* Check source first for (package, non-package) case */
942
943 if (SourceOperandBtype & ACPI_BTYPE_PACKAGE)
944 {
945 /* If Source is PACKAGE-->Target must be PACKAGE */
946
947 if (!(TargetOperandBtype & ACPI_BTYPE_PACKAGE))
948 {
949 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, TargetOperandOp,
950 "Source is [Package], Target must be a package also");
951 }
952 }
953
954 /* Else check target for (non-package, package) case */
955
956 else if (TargetOperandBtype & ACPI_BTYPE_PACKAGE)
957 {
958 /* If Target is PACKAGE, Source must be PACKAGE */
959
960 if (!(SourceOperandBtype & ACPI_BTYPE_PACKAGE))
961 {
962 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, SourceOperandOp,
963 "Target is [Package], Source must be a package also");
964 }
965 }
966 }
967