1 /******************************************************************************
2 *
3 * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2022, 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 MERCHANTABILITY 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 static BOOLEAN
61 AnIsValidBufferConstant (
62 ACPI_PARSE_OBJECT *Op);
63
64 static void
65 AnValidateCreateBufferField (
66 ACPI_PARSE_OBJECT *CreateBufferFieldOp);
67
68
69 /*******************************************************************************
70 *
71 * FUNCTION: AnMethodTypingWalkEnd
72 *
73 * PARAMETERS: ASL_WALK_CALLBACK
74 *
75 * RETURN: Status
76 *
77 * DESCRIPTION: Ascending callback for typing walk. Complete the method
78 * return analysis. Check methods for:
79 * 1) Initialized local variables
80 * 2) Valid arguments
81 * 3) Return types
82 *
83 ******************************************************************************/
84
85 ACPI_STATUS
AnMethodTypingWalkEnd(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)86 AnMethodTypingWalkEnd (
87 ACPI_PARSE_OBJECT *Op,
88 UINT32 Level,
89 void *Context)
90 {
91 UINT32 ThisOpBtype;
92
93
94 switch (Op->Asl.ParseOpcode)
95 {
96 case PARSEOP_METHOD:
97
98 Op->Asl.CompileFlags |= OP_METHOD_TYPED;
99 break;
100
101 case PARSEOP_RETURN:
102
103 if ((Op->Asl.Child) &&
104 (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
105 {
106 ThisOpBtype = AnGetBtype (Op->Asl.Child);
107
108 if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
109 (ThisOpBtype == (ACPI_UINT32_MAX -1)))
110 {
111 /*
112 * The called method is untyped at this time (typically a
113 * forward reference).
114 *
115 * Check for a recursive method call first. Note: the
116 * Child->Node will be null if the method has not been
117 * resolved.
118 */
119 if (Op->Asl.Child->Asl.Node &&
120 (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op))
121 {
122 /* We must type the method here */
123
124 TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
125 ASL_WALK_VISIT_UPWARD, NULL,
126 AnMethodTypingWalkEnd, NULL);
127
128 ThisOpBtype = AnGetBtype (Op->Asl.Child);
129 }
130 }
131
132 /* Returns a value, save the value type */
133
134 if (Op->Asl.ParentMethod)
135 {
136 Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisOpBtype;
137 }
138 }
139 break;
140
141 default:
142
143 break;
144 }
145
146 return (AE_OK);
147 }
148
149
150 /*******************************************************************************
151 *
152 * FUNCTION: AnOperandTypecheckWalkEnd
153 *
154 * PARAMETERS: ASL_WALK_CALLBACK
155 *
156 * RETURN: Status
157 *
158 * DESCRIPTION: Ascending callback for analysis walk. Complete method
159 * return analysis.
160 *
161 ******************************************************************************/
162
163 ACPI_STATUS
AnOperandTypecheckWalkEnd(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)164 AnOperandTypecheckWalkEnd (
165 ACPI_PARSE_OBJECT *Op,
166 UINT32 Level,
167 void *Context)
168 {
169 const ACPI_OPCODE_INFO *OpInfo;
170 UINT32 RuntimeArgTypes;
171 UINT32 RuntimeArgTypes2;
172 UINT32 RequiredBtypes;
173 UINT32 ThisNodeBtype;
174 UINT32 CommonBtypes;
175 UINT32 OpcodeClass;
176 ACPI_PARSE_OBJECT *ArgOp;
177 UINT32 ArgType;
178
179
180 switch (Op->Asl.AmlOpcode)
181 {
182 case AML_RAW_DATA_BYTE:
183 case AML_RAW_DATA_WORD:
184 case AML_RAW_DATA_DWORD:
185 case AML_RAW_DATA_QWORD:
186 case AML_RAW_DATA_BUFFER:
187 case AML_RAW_DATA_CHAIN:
188 case AML_PACKAGE_LENGTH:
189 case AML_UNASSIGNED_OPCODE:
190 case AML_DEFAULT_ARG_OP:
191
192 /* Ignore the internal (compiler-only) AML opcodes */
193
194 return (AE_OK);
195
196 default:
197
198 break;
199 }
200
201 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
202 if (!OpInfo)
203 {
204 return (AE_OK);
205 }
206
207 ArgOp = Op->Asl.Child;
208 OpcodeClass = OpInfo->Class;
209 RuntimeArgTypes = OpInfo->RuntimeArgs;
210
211 #ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
212 /*
213 * Update 11/2008: In practice, we can't perform this check. A simple
214 * analysis is not sufficient. Also, it can cause errors when compiling
215 * disassembled code because of the way Switch operators are implemented
216 * (a While(One) loop with a named temp variable created within.)
217 */
218
219 /*
220 * If we are creating a named object, check if we are within a while loop
221 * by checking if the parent is a WHILE op. This is a simple analysis, but
222 * probably sufficient for many cases.
223 *
224 * Allow Scope(), Buffer(), and Package().
225 */
226 if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) ||
227 ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE)))
228 {
229 if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP)
230 {
231 AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL);
232 }
233 }
234 #endif
235
236 /*
237 * Special case for control opcodes IF/RETURN/WHILE since they
238 * have no runtime arg list (at this time)
239 */
240 switch (Op->Asl.AmlOpcode)
241 {
242 case AML_IF_OP:
243 case AML_WHILE_OP:
244 case AML_RETURN_OP:
245
246 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
247 {
248 /* Check for an internal method */
249
250 if (AnIsInternalMethod (ArgOp))
251 {
252 return (AE_OK);
253 }
254
255 /* The lone arg is a method call, check it */
256
257 RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
258 if (Op->Asl.AmlOpcode == AML_RETURN_OP)
259 {
260 RequiredBtypes = 0xFFFFFFFF;
261 }
262
263 ThisNodeBtype = AnGetBtype (ArgOp);
264 if (ThisNodeBtype == ACPI_UINT32_MAX)
265 {
266 return (AE_OK);
267 }
268
269 AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
270 RequiredBtypes, ThisNodeBtype);
271 }
272 return (AE_OK);
273
274 case AML_EXTERNAL_OP:
275 /*
276 * Not really a "runtime" opcode since it used by disassembler only.
277 * The parser will find any issues with the operands.
278 */
279 return (AE_OK);
280
281 default:
282
283 break;
284 }
285
286 /* Ignore the non-executable opcodes */
287
288 if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
289 {
290 return (AE_OK);
291 }
292
293 /*
294 * Special handling for certain opcodes.
295 */
296 switch (Op->Asl.AmlOpcode)
297 {
298 /* BankField has one TermArg */
299
300 case AML_BANK_FIELD_OP:
301
302 OpcodeClass = AML_CLASS_EXECUTE;
303 ArgOp = ArgOp->Asl.Next;
304 ArgOp = ArgOp->Asl.Next;
305 break;
306
307 /* Operation Region has 2 TermArgs */
308
309 case AML_REGION_OP:
310
311 OpcodeClass = AML_CLASS_EXECUTE;
312 ArgOp = ArgOp->Asl.Next;
313 ArgOp = ArgOp->Asl.Next;
314 break;
315
316 /* DataTableRegion has 3 TermArgs */
317
318 case AML_DATA_REGION_OP:
319
320 OpcodeClass = AML_CLASS_EXECUTE;
321 ArgOp = ArgOp->Asl.Next;
322 break;
323
324 /* Buffers/Packages have a length that is a TermArg */
325
326 case AML_BUFFER_OP:
327 case AML_PACKAGE_OP:
328 case AML_VARIABLE_PACKAGE_OP:
329
330 /* If length is a constant, we are done */
331
332 if ((ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) ||
333 (ArgOp->Asl.ParseOpcode == PARSEOP_RAW_DATA))
334 {
335 return (AE_OK);
336 }
337 break;
338
339 /* Store can write any object to the Debug object */
340
341 case AML_STORE_OP:
342 /*
343 * If this is a Store() to the Debug object, we don't need
344 * to perform any further validation -- because a Store of
345 * any object to Debug is permitted and supported.
346 */
347 if (ArgOp->Asl.Next->Asl.AmlOpcode == AML_DEBUG_OP)
348 {
349 return (AE_OK);
350 }
351 break;
352
353 default:
354 break;
355 }
356
357 switch (OpcodeClass)
358 {
359 case AML_CLASS_EXECUTE:
360 case AML_CLASS_CREATE:
361 case AML_CLASS_CONTROL:
362 case AML_CLASS_RETURN_VALUE:
363
364 /* Reverse the runtime argument list */
365
366 RuntimeArgTypes2 = 0;
367 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
368 {
369 RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
370 RuntimeArgTypes2 |= ArgType;
371 INCREMENT_ARG_LIST (RuntimeArgTypes);
372 }
373
374 /* Typecheck each argument */
375
376 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
377 {
378 /* Get the required type(s) for the argument */
379
380 RequiredBtypes = AnMapArgTypeToBtype (ArgType);
381
382 if (!ArgOp)
383 {
384 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
385 "Null ArgOp in argument loop");
386 AslAbort ();
387 }
388
389 /* Get the actual type of the argument */
390
391 ThisNodeBtype = AnGetBtype (ArgOp);
392 if (ThisNodeBtype == ACPI_UINT32_MAX)
393 {
394 goto NextArgument;
395 }
396
397 /* Examine the arg based on the required type of the arg */
398
399 switch (ArgType)
400 {
401 case ARGI_TARGETREF:
402
403 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
404 {
405 /* ZERO is the placeholder for "don't store result" */
406
407 ThisNodeBtype = RequiredBtypes;
408 break;
409 }
410
411 ACPI_FALLTHROUGH;
412
413 case ARGI_STORE_TARGET:
414
415 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
416 {
417 /*
418 * This is the case where an original reference to a resource
419 * descriptor field has been replaced by an (Integer) offset.
420 * These named fields are supported at compile-time only;
421 * the names are not passed to the interpreter (via the AML).
422 */
423 if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
424 (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
425 {
426 AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD,
427 ArgOp, NULL);
428 }
429 else
430 {
431 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE,
432 ArgOp, NULL);
433 }
434 }
435 break;
436
437
438 #ifdef __FUTURE_IMPLEMENTATION
439 /*
440 * Possible future typechecking support
441 */
442 case ARGI_REFERENCE: /* References */
443 case ARGI_INTEGER_REF:
444 case ARGI_OBJECT_REF:
445 case ARGI_DEVICE_REF:
446
447 switch (ArgOp->Asl.ParseOpcode)
448 {
449 case PARSEOP_LOCAL0:
450 case PARSEOP_LOCAL1:
451 case PARSEOP_LOCAL2:
452 case PARSEOP_LOCAL3:
453 case PARSEOP_LOCAL4:
454 case PARSEOP_LOCAL5:
455 case PARSEOP_LOCAL6:
456 case PARSEOP_LOCAL7:
457
458 /* TBD: implement analysis of current value (type) of the local */
459 /* For now, just treat any local as a typematch */
460
461 /*ThisNodeBtype = RequiredBtypes;*/
462 break;
463
464 case PARSEOP_ARG0:
465 case PARSEOP_ARG1:
466 case PARSEOP_ARG2:
467 case PARSEOP_ARG3:
468 case PARSEOP_ARG4:
469 case PARSEOP_ARG5:
470 case PARSEOP_ARG6:
471
472 /* Hard to analyze argument types, so we won't */
473 /* for now. Just treat any arg as a typematch */
474
475 /* ThisNodeBtype = RequiredBtypes; */
476 break;
477
478 case PARSEOP_DEBUG:
479 case PARSEOP_REFOF:
480 case PARSEOP_INDEX:
481 default:
482
483 break;
484 }
485 break;
486 #endif
487 case ARGI_INTEGER:
488 default:
489
490 break;
491 }
492
493
494 /* Check for a type mismatch (required versus actual) */
495
496 CommonBtypes = ThisNodeBtype & RequiredBtypes;
497
498 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
499 {
500 if (AnIsInternalMethod (ArgOp))
501 {
502 return (AE_OK);
503 }
504
505 /* Check a method call for a valid return value */
506
507 AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
508 RequiredBtypes, ThisNodeBtype);
509 }
510
511 /*
512 * Now check if the actual type(s) match at least one
513 * bit to the required type
514 */
515 else if (!CommonBtypes)
516 {
517 /* No match -- this is a type mismatch error */
518
519 AnFormatBtype (AslGbl_StringBuffer, ThisNodeBtype);
520 AnFormatBtype (AslGbl_StringBuffer2, RequiredBtypes);
521
522 snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "[%s] found, %s operator requires [%s]",
523 AslGbl_StringBuffer, OpInfo->Name, AslGbl_StringBuffer2);
524
525 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE,
526 ArgOp, AslGbl_MsgBuffer);
527 }
528
529 NextArgument:
530 ArgOp = ArgOp->Asl.Next;
531 INCREMENT_ARG_LIST (RuntimeArgTypes2);
532 }
533 break;
534
535 default:
536
537 break;
538 }
539
540 return (AE_OK);
541 }
542
543
544 /*******************************************************************************
545 *
546 * FUNCTION: AnOtherSemanticAnalysisWalkBegin
547 *
548 * PARAMETERS: ASL_WALK_CALLBACK
549 *
550 * RETURN: Status
551 *
552 * DESCRIPTION: Descending callback for the analysis walk. Checks for
553 * miscellaneous issues in the code.
554 *
555 ******************************************************************************/
556
557 ACPI_STATUS
AnOtherSemanticAnalysisWalkBegin(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)558 AnOtherSemanticAnalysisWalkBegin (
559 ACPI_PARSE_OBJECT *Op,
560 UINT32 Level,
561 void *Context)
562 {
563 ACPI_PARSE_OBJECT *ArgOp;
564 ACPI_PARSE_OBJECT *PrevArgOp = NULL;
565 const ACPI_OPCODE_INFO *OpInfo;
566 ACPI_NAMESPACE_NODE *Node;
567
568
569 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
570
571
572 if (OpInfo->Flags & AML_CREATE)
573 {
574 /* This group contains all of the Create Buffer Field operators */
575
576 AnValidateCreateBufferField (Op);
577 return (AE_OK);
578 }
579
580 /*
581 * Determine if an execution class operator actually does something by
582 * checking if it has a target and/or the function return value is used.
583 * (Target is optional, so a standalone statement can actually do nothing.)
584 */
585 if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
586 (OpInfo->Flags & AML_HAS_RETVAL) &&
587 (!AnIsResultUsed (Op)))
588 {
589 if (OpInfo->Flags & AML_HAS_TARGET)
590 {
591 /*
592 * Find the target node, it is always the last child. If the target
593 * is not specified in the ASL, a default node of type Zero was
594 * created by the parser.
595 */
596 ArgOp = Op->Asl.Child;
597 while (ArgOp->Asl.Next)
598 {
599 PrevArgOp = ArgOp;
600 ArgOp = ArgOp->Asl.Next;
601 }
602
603 /* Divide() is the only weird case, it has two targets */
604
605 if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
606 {
607 if ((ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) &&
608 (PrevArgOp) &&
609 (PrevArgOp->Asl.ParseOpcode == PARSEOP_ZERO))
610 {
611 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
612 Op, Op->Asl.ExternalName);
613 }
614 }
615
616 else if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
617 {
618 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
619 Op, Op->Asl.ExternalName);
620 }
621 }
622 else
623 {
624 /*
625 * Has no target and the result is not used. Only a couple opcodes
626 * can have this combination.
627 */
628 switch (Op->Asl.ParseOpcode)
629 {
630 case PARSEOP_ACQUIRE:
631 case PARSEOP_WAIT:
632 case PARSEOP_LOADTABLE:
633
634 break;
635
636 default:
637
638 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
639 Op, Op->Asl.ExternalName);
640 break;
641 }
642 }
643 }
644
645 /*
646 * Semantic checks for individual ASL operators
647 */
648
649 switch (Op->Asl.ParseOpcode)
650 {
651 case PARSEOP_STORE:
652
653 if (AslGbl_DoTypechecking)
654 {
655 AnAnalyzeStoreOperator (Op);
656 }
657 break;
658
659
660 case PARSEOP_ACQUIRE:
661 case PARSEOP_WAIT:
662 /*
663 * Emit a warning if the timeout parameter for these operators is not
664 * ACPI_WAIT_FOREVER, and the result value from the operator is not
665 * checked, meaning that a timeout could happen, but the code
666 * would not know about it.
667 */
668
669 /* First child is the namepath, 2nd child is timeout */
670
671 ArgOp = Op->Asl.Child;
672 ArgOp = ArgOp->Asl.Next;
673
674 /*
675 * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
676 * 0xFFFF or greater
677 */
678 if (((ArgOp->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
679 (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)) &&
680 (ArgOp->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
681 {
682 break;
683 }
684
685 /*
686 * The operation could timeout. If the return value is not used
687 * (indicates timeout occurred), issue a warning
688 */
689 if (!AnIsResultUsed (Op))
690 {
691 AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgOp,
692 Op->Asl.ExternalName);
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: AnValidateCreateBufferField
784 *
785 * PARAMETERS: Op - A create buffer field operator
786 *
787 * RETURN: None
788 *
789 * DESCRIPTION: Check if a buffer index argument to a create buffer field
790 * operation is beyond the end of the target buffer.
791 *
792 * Validates these AML operators:
793 *
794 * AML_CREATE_FIELD_OP
795 * AML_CREATE_BIT_FIELD_OP
796 * AML_CREATE_BYTE_FIELD_OP
797 * AML_CREATE_WORD_FIELD_OP
798 * AML_CREATE_DWORD_FIELD_OP
799 * AML_CREATE_QWORD_FIELD_OP
800 *
801 * There are two conditions that must be satisfied in order to enable
802 * validation at compile time:
803 *
804 * 1) The length of the target buffer must be an integer constant
805 * 2) The index specified in the create* must be an integer constant
806 * 3) For CreateField, the bit length argument must be non-zero.
807 *
808 ******************************************************************************/
809
810 static void
AnValidateCreateBufferField(ACPI_PARSE_OBJECT * CreateBufferFieldOp)811 AnValidateCreateBufferField (
812 ACPI_PARSE_OBJECT *CreateBufferFieldOp)
813 {
814 ACPI_PARSE_OBJECT *TargetBufferOp;
815 ACPI_PARSE_OBJECT *ArgOp;
816 UINT32 TargetBufferLength;
817 UINT32 LastFieldByteIndex;
818
819
820 /*
821 * 1) Get the length of the target buffer
822 */
823 ArgOp = CreateBufferFieldOp->Asl.Child; /* Reference to target buffer */
824
825 /*
826 * If no attached Node, the target buffer may be something like an
827 * ArgX or LocalX and cannot be evaluated at compile time.
828 */
829 if (!ArgOp->Asl.Node)
830 {
831 return;
832 }
833
834 TargetBufferOp = ArgOp->Asl.Node->Op;
835 TargetBufferOp = TargetBufferOp->Asl.Child; /* Target buffer */
836 TargetBufferOp = TargetBufferOp->Asl.Next; /* "Buffer" keyword */
837 if (!TargetBufferOp)
838 {
839 /* Not a statement of the form NAME(XXXX, Buffer.... */
840
841 return;
842 }
843
844 /* Get the buffer length argument. It must be an integer constant */
845
846 ArgOp = TargetBufferOp->Asl.Child;
847 if (!AnIsValidBufferConstant (ArgOp))
848 {
849 return;
850 }
851
852 TargetBufferLength = (UINT32) ArgOp->Asl.Value.Integer;
853
854 /*
855 * 2) Get the value of the buffer index argument. It must be
856 * an integer constant.
857 */
858 ArgOp = CreateBufferFieldOp->Asl.Child; /* Reference to target buffer */
859 ArgOp = ArgOp->Asl.Next; /* Buffer Index argument*/
860 if (!AnIsValidBufferConstant (ArgOp))
861 {
862 return;
863 }
864
865 LastFieldByteIndex =
866 (UINT32) ArgOp->Asl.Value.Integer; /* Index can be in either bytes or bits */
867
868 /*
869 * 3) Get the length of the new buffer field, in bytes. Also,
870 * create the final target buffer index for the last byte of the field
871 */
872 switch (CreateBufferFieldOp->Asl.ParseOpcode)
873 {
874 case PARSEOP_CREATEBITFIELD: /* A one bit field */
875
876 LastFieldByteIndex = ACPI_ROUND_BITS_DOWN_TO_BYTES (LastFieldByteIndex);
877 break;
878
879 case PARSEOP_CREATEBYTEFIELD:
880 break;
881
882 case PARSEOP_CREATEWORDFIELD:
883
884 LastFieldByteIndex += (sizeof (UINT16) - 1);
885 break;
886
887 case PARSEOP_CREATEDWORDFIELD:
888
889 LastFieldByteIndex += (sizeof (UINT32) - 1);
890 break;
891
892 case PARSEOP_CREATEQWORDFIELD:
893
894 LastFieldByteIndex += (sizeof (UINT64) - 1);
895 break;
896
897 case PARSEOP_CREATEFIELD: /* Multi-bit field */
898
899 ArgOp = ArgOp->Asl.Next; /* Length argument, in bits */
900 if (!AnIsValidBufferConstant (ArgOp))
901 {
902 return;
903 }
904
905 /* The buffer field length is not allowed to be zero */
906
907 if (ArgOp->Asl.Value.Integer == 0)
908 {
909 AslError (ASL_WARNING, ASL_MSG_BUFFER_FIELD_LENGTH, ArgOp, NULL);
910 return;
911 }
912
913 LastFieldByteIndex +=
914 ((UINT32) ArgOp->Asl.Value.Integer - 1); /* Create final bit index */
915
916 /* Convert bit index to a byte index */
917
918 LastFieldByteIndex = ACPI_ROUND_BITS_DOWN_TO_BYTES (LastFieldByteIndex);
919 break;
920
921 default:
922 return;
923 }
924
925 /*
926 * 4) Check for an access (index) beyond the end of the target buffer,
927 * or a zero length target buffer.
928 */
929 if (!TargetBufferLength || (LastFieldByteIndex >= TargetBufferLength))
930 {
931 AslError (ASL_WARNING, ASL_MSG_BUFFER_FIELD_OVERFLOW, ArgOp, NULL);
932 }
933 }
934
935
936 /*******************************************************************************
937 *
938 * FUNCTION: AnIsValidBufferConstant
939 *
940 * PARAMETERS: Op - A buffer-related operand
941 *
942 * RETURN: TRUE if operand is valid constant, FALSE otherwise
943 *
944 * DESCRIPTION: Check if the input Op is valid constant that can be used
945 * in compile-time analysis.
946 *
947 ******************************************************************************/
948
949 static BOOLEAN
AnIsValidBufferConstant(ACPI_PARSE_OBJECT * Op)950 AnIsValidBufferConstant (
951 ACPI_PARSE_OBJECT *Op)
952 {
953 if (!Op)
954 {
955 return (FALSE);
956 }
957
958 if ((Op->Asl.ParseOpcode == PARSEOP_INTEGER) ||
959 (Op->Asl.ParseOpcode == PARSEOP_ZERO) ||
960 (Op->Asl.ParseOpcode == PARSEOP_ONE))
961 {
962 return (TRUE);
963 }
964
965 return (FALSE);
966 }
967
968
969 /*******************************************************************************
970 *
971 * FUNCTION: AnAnalyzeStoreOperator
972 *
973 * PARAMETERS: Op - Store() operator
974 *
975 * RETURN: None
976 *
977 * DESCRIPTION: Analyze a store operator. Mostly for stores to/from package
978 * objects where there are more restrictions than other data
979 * types.
980 *
981 ******************************************************************************/
982
983 static void
AnAnalyzeStoreOperator(ACPI_PARSE_OBJECT * Op)984 AnAnalyzeStoreOperator (
985 ACPI_PARSE_OBJECT *Op)
986 {
987 ACPI_NAMESPACE_NODE *SourceNode;
988 ACPI_NAMESPACE_NODE *TargetNode;
989 ACPI_PARSE_OBJECT *SourceOperandOp;
990 ACPI_PARSE_OBJECT *TargetOperandOp;
991 UINT32 SourceOperandBtype;
992 UINT32 TargetOperandBtype;
993
994
995 /* Extract the two operands for STORE */
996
997 SourceOperandOp = Op->Asl.Child;
998 TargetOperandOp = SourceOperandOp->Asl.Next;
999
1000 /*
1001 * Ignore these Source operand opcodes, they cannot be typechecked,
1002 * the actual result is unknown here.
1003 */
1004 switch (SourceOperandOp->Asl.ParseOpcode)
1005 {
1006 /* For these, type of the returned value is unknown at compile time */
1007
1008 case PARSEOP_DEREFOF:
1009 case PARSEOP_METHODCALL:
1010 case PARSEOP_STORE:
1011 case PARSEOP_COPYOBJECT:
1012
1013 return;
1014
1015 case PARSEOP_INDEX:
1016 case PARSEOP_REFOF:
1017
1018 if (!AslGbl_EnableReferenceTypechecking)
1019 {
1020 return;
1021 }
1022
1023 /*
1024 * These opcodes always return an object reference, and thus
1025 * the result can only be stored to a Local, Arg, or Debug.
1026 */
1027 if (TargetOperandOp->Asl.AmlOpcode == AML_DEBUG_OP)
1028 {
1029 return;
1030 }
1031
1032 if ((TargetOperandOp->Asl.AmlOpcode < AML_LOCAL0) ||
1033 (TargetOperandOp->Asl.AmlOpcode > AML_ARG6))
1034 {
1035 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, TargetOperandOp,
1036 "Source [Reference], Target must be [Local/Arg/Debug]");
1037 }
1038 return;
1039
1040 default:
1041 break;
1042 }
1043
1044 /*
1045 * Ignore these Target operand opcodes, they cannot be typechecked
1046 */
1047 switch (TargetOperandOp->Asl.ParseOpcode)
1048 {
1049 case PARSEOP_DEBUG:
1050 case PARSEOP_DEREFOF:
1051 case PARSEOP_REFOF:
1052 case PARSEOP_INDEX:
1053 case PARSEOP_STORE:
1054
1055 return;
1056
1057 default:
1058 break;
1059 }
1060
1061 /*
1062 * Ignore typecheck for External() operands of type "UnknownObj",
1063 * we don't know the actual type (source or target).
1064 */
1065 SourceNode = SourceOperandOp->Asl.Node;
1066 if (SourceNode &&
1067 (SourceNode->Flags & ANOBJ_IS_EXTERNAL) &&
1068 (SourceNode->Type == ACPI_TYPE_ANY))
1069 {
1070 return;
1071 }
1072
1073 TargetNode = TargetOperandOp->Asl.Node;
1074 if (TargetNode &&
1075 (TargetNode->Flags & ANOBJ_IS_EXTERNAL) &&
1076 (TargetNode->Type == ACPI_TYPE_ANY))
1077 {
1078 return;
1079 }
1080
1081 /*
1082 * A NULL node with a namepath AML opcode indicates non-existent
1083 * name. Just return, the error message is generated elsewhere.
1084 */
1085 if ((!SourceNode && (SourceOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)) ||
1086 (!TargetNode && (TargetOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)))
1087 {
1088 return;
1089 }
1090
1091 /*
1092 * Simple check for source same as target via NS node.
1093 * -- Could be expanded to locals and args.
1094 */
1095 if (SourceNode && TargetNode)
1096 {
1097 if (SourceNode == TargetNode)
1098 {
1099 AslError (ASL_WARNING, ASL_MSG_DUPLICATE_ITEM,
1100 TargetOperandOp, "Source is the same as Target");
1101 return;
1102 }
1103 }
1104
1105 /* Ignore typecheck if either source or target is a local or arg */
1106
1107 if ((SourceOperandOp->Asl.AmlOpcode >= AML_LOCAL0) &&
1108 (SourceOperandOp->Asl.AmlOpcode <= AML_ARG6))
1109 {
1110 return; /* Cannot type a local/arg at compile time */
1111 }
1112
1113 if ((TargetOperandOp->Asl.AmlOpcode >= AML_LOCAL0) &&
1114 (TargetOperandOp->Asl.AmlOpcode <= AML_ARG6))
1115 {
1116 return; /* Cannot type a local/arg at compile time */
1117 }
1118
1119 /*
1120 * Package objects are a special case because they cannot by implicitly
1121 * converted to/from anything. Check for these two illegal cases:
1122 *
1123 * Store (non-package, package)
1124 * Store (package, non-package)
1125 */
1126 SourceOperandBtype = AnGetBtype (SourceOperandOp);
1127 TargetOperandBtype = AnGetBtype (TargetOperandOp);
1128
1129 /* Check source first for (package, non-package) case */
1130
1131 if (SourceOperandBtype & ACPI_BTYPE_PACKAGE)
1132 {
1133 /* If Source is PACKAGE-->Target must be PACKAGE */
1134
1135 if (!(TargetOperandBtype & ACPI_BTYPE_PACKAGE))
1136 {
1137 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, TargetOperandOp,
1138 "Source is [Package], Target must be a package also");
1139 }
1140 }
1141
1142 /* Else check target for (non-package, package) case */
1143
1144 else if (TargetOperandBtype & ACPI_BTYPE_PACKAGE)
1145 {
1146 /* If Target is PACKAGE, Source must be PACKAGE */
1147
1148 if (!(SourceOperandBtype & ACPI_BTYPE_PACKAGE))
1149 {
1150 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, SourceOperandOp,
1151 "Target is [Package], Source must be a package also");
1152 }
1153 }
1154 }
1155