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