1 /******************************************************************************
2 *
3 * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks
4 *
5 *****************************************************************************/
6
7 /******************************************************************************
8 *
9 * 1. Copyright Notice
10 *
11 * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
12 * All rights reserved.
13 *
14 * 2. License
15 *
16 * 2.1. This is your license from Intel Corp. under its intellectual property
17 * rights. You may have additional license terms from the party that provided
18 * you this software, covering your right to use that party's intellectual
19 * property rights.
20 *
21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22 * copy of the source code appearing in this file ("Covered Code") an
23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24 * base code distributed originally by Intel ("Original Intel Code") to copy,
25 * make derivatives, distribute, use and display any portion of the Covered
26 * Code in any form, with the right to sublicense such rights; and
27 *
28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29 * license (with the right to sublicense), under only those claims of Intel
30 * patents that are infringed by the Original Intel Code, to make, use, sell,
31 * offer to sell, and import the Covered Code and derivative works thereof
32 * solely to the minimum extent necessary to exercise the above copyright
33 * license, and in no event shall the patent license extend to any additions
34 * to or modifications of the Original Intel Code. No other license or right
35 * is granted directly or by implication, estoppel or otherwise;
36 *
37 * The above copyright and patent license is granted only if the following
38 * conditions are met:
39 *
40 * 3. Conditions
41 *
42 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43 * Redistribution of source code of any substantial portion of the Covered
44 * Code or modification with rights to further distribute source must include
45 * the above Copyright Notice, the above License, this list of Conditions,
46 * and the following Disclaimer and Export Compliance provision. In addition,
47 * Licensee must cause all Covered Code to which Licensee contributes to
48 * contain a file documenting the changes Licensee made to create that Covered
49 * Code and the date of any change. Licensee must include in that file the
50 * documentation of any changes made by any predecessor Licensee. Licensee
51 * must include a prominent statement that the modification is derived,
52 * directly or indirectly, from Original Intel Code.
53 *
54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55 * Redistribution of source code of any substantial portion of the Covered
56 * Code or modification without rights to further distribute source must
57 * include the following Disclaimer and Export Compliance provision in the
58 * documentation and/or other materials provided with distribution. In
59 * addition, Licensee may not authorize further sublicense of source of any
60 * portion of the Covered Code, and must include terms to the effect that the
61 * license from Licensee to its licensee is limited to the intellectual
62 * property embodied in the software Licensee provides to its licensee, and
63 * not to intellectual property embodied in modifications its licensee may
64 * make.
65 *
66 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67 * substantial portion of the Covered Code or modification must reproduce the
68 * above Copyright Notice, and the following Disclaimer and Export Compliance
69 * provision in the documentation and/or other materials provided with the
70 * distribution.
71 *
72 * 3.4. Intel retains all right, title, and interest in and to the Original
73 * Intel Code.
74 *
75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76 * Intel shall be used in advertising or otherwise to promote the sale, use or
77 * other dealings in products derived from or relating to the Covered Code
78 * without prior written authorization from Intel.
79 *
80 * 4. Disclaimer and Export Compliance
81 *
82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88 * PARTICULAR PURPOSE.
89 *
90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97 * LIMITED REMEDY.
98 *
99 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100 * software or system incorporating such software without first obtaining any
101 * required license or other approval from the U. S. Department of Commerce or
102 * any other agency or department of the United States Government. In the
103 * event Licensee exports any such software from the United States or
104 * re-exports any such software from a foreign destination, Licensee shall
105 * ensure that the distribution and export/re-export of the software is in
106 * compliance with all laws, regulations, orders, or other restrictions of the
107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108 * any of its subsidiaries will export/re-export any technical data, process,
109 * software, or service, directly or indirectly, to any country for which the
110 * United States government or any agency thereof requires an export license,
111 * other governmental approval, or letter of assurance, without first obtaining
112 * such license, approval or letter.
113 *
114 *****************************************************************************
115 *
116 * Alternatively, you may choose to be licensed under the terms of the
117 * following license:
118 *
119 * Redistribution and use in source and binary forms, with or without
120 * modification, are permitted provided that the following conditions
121 * are met:
122 * 1. Redistributions of source code must retain the above copyright
123 * notice, this list of conditions, and the following disclaimer,
124 * without modification.
125 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126 * substantially similar to the "NO WARRANTY" disclaimer below
127 * ("Disclaimer") and any redistribution must be conditioned upon
128 * including a substantially similar Disclaimer requirement for further
129 * binary redistribution.
130 * 3. Neither the names of the above-listed copyright holders nor the names
131 * of any contributors may be used to endorse or promote products derived
132 * from this software without specific prior written permission.
133 *
134 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145 *
146 * Alternatively, you may choose to be licensed under the terms of the
147 * GNU General Public License ("GPL") version 2 as published by the Free
148 * Software Foundation.
149 *
150 *****************************************************************************/
151
152 #include <contrib/dev/acpica/compiler/aslcompiler.h>
153 #include "aslcompiler.y.h"
154 #include <contrib/dev/acpica/include/acparser.h>
155 #include <contrib/dev/acpica/include/amlcode.h>
156
157
158 #define _COMPONENT ACPI_COMPILER
159 ACPI_MODULE_NAME ("aslwalks")
160
161
162 /* Local prototypes */
163
164 static void
165 AnAnalyzeStoreOperator (
166 ACPI_PARSE_OBJECT *Op);
167
168 static BOOLEAN
169 AnIsValidBufferConstant (
170 ACPI_PARSE_OBJECT *Op);
171
172 static void
173 AnValidateCreateBufferField (
174 ACPI_PARSE_OBJECT *CreateBufferFieldOp);
175
176
177 /*******************************************************************************
178 *
179 * FUNCTION: AnMethodTypingWalkEnd
180 *
181 * PARAMETERS: ASL_WALK_CALLBACK
182 *
183 * RETURN: Status
184 *
185 * DESCRIPTION: Ascending callback for typing walk. Complete the method
186 * return analysis. Check methods for:
187 * 1) Initialized local variables
188 * 2) Valid arguments
189 * 3) Return types
190 *
191 ******************************************************************************/
192
193 ACPI_STATUS
AnMethodTypingWalkEnd(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)194 AnMethodTypingWalkEnd (
195 ACPI_PARSE_OBJECT *Op,
196 UINT32 Level,
197 void *Context)
198 {
199 UINT32 ThisOpBtype;
200 ACPI_PARSE_OBJECT *TargetMethodOp;
201
202
203 switch (Op->Asl.ParseOpcode)
204 {
205 case PARSEOP_METHOD:
206
207 Op->Asl.CompileFlags |= OP_METHOD_TYPED;
208 break;
209
210 case PARSEOP_RETURN:
211
212 if ((Op->Asl.Child) &&
213 (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
214 {
215 ThisOpBtype = AnGetBtype (Op->Asl.Child);
216
217 if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
218 (ThisOpBtype == (ACPI_UINT32_MAX -1)))
219 {
220 /*
221 * The called method is untyped at this time (typically a
222 * forward reference).
223 *
224 * Check for a recursive method call first. Note: the
225 * Child->Node will be null if the method has not been
226 * resolved.
227 */
228 if (Op->Asl.Child->Asl.Node &&
229 (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op))
230 {
231 TargetMethodOp = Op->Asl.Child->Asl.Node->Op;
232
233 /* Break mutual-recursion loops during typing */
234 if (TargetMethodOp->Asl.CompileFlags & OP_VISITED)
235 {
236 break;
237 }
238
239 TargetMethodOp->Asl.CompileFlags |= OP_VISITED;
240
241 /* We must type the method here */
242
243 TrWalkParseTree (TargetMethodOp,
244 ASL_WALK_VISIT_UPWARD, NULL,
245 AnMethodTypingWalkEnd, NULL);
246
247 TargetMethodOp->Asl.CompileFlags &= ~OP_VISITED;
248
249 ThisOpBtype = AnGetBtype (Op->Asl.Child);
250 }
251 }
252
253 /* Returns a value, save the value type */
254
255 if (Op->Asl.ParentMethod)
256 {
257 Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisOpBtype;
258 }
259 }
260 break;
261
262 default:
263
264 break;
265 }
266
267 return (AE_OK);
268 }
269
270
271 /*******************************************************************************
272 *
273 * FUNCTION: AnOperandTypecheckWalkEnd
274 *
275 * PARAMETERS: ASL_WALK_CALLBACK
276 *
277 * RETURN: Status
278 *
279 * DESCRIPTION: Ascending callback for analysis walk. Complete method
280 * return analysis.
281 *
282 ******************************************************************************/
283
284 ACPI_STATUS
AnOperandTypecheckWalkEnd(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)285 AnOperandTypecheckWalkEnd (
286 ACPI_PARSE_OBJECT *Op,
287 UINT32 Level,
288 void *Context)
289 {
290 const ACPI_OPCODE_INFO *OpInfo;
291 UINT32 RuntimeArgTypes;
292 UINT32 RuntimeArgTypes2;
293 UINT32 RequiredBtypes;
294 UINT32 ThisNodeBtype;
295 UINT32 CommonBtypes;
296 UINT32 OpcodeClass;
297 ACPI_PARSE_OBJECT *ArgOp;
298 UINT32 ArgType;
299
300
301 switch (Op->Asl.AmlOpcode)
302 {
303 case AML_RAW_DATA_BYTE:
304 case AML_RAW_DATA_WORD:
305 case AML_RAW_DATA_DWORD:
306 case AML_RAW_DATA_QWORD:
307 case AML_RAW_DATA_BUFFER:
308 case AML_RAW_DATA_CHAIN:
309 case AML_PACKAGE_LENGTH:
310 case AML_UNASSIGNED_OPCODE:
311 case AML_DEFAULT_ARG_OP:
312
313 /* Ignore the internal (compiler-only) AML opcodes */
314
315 return (AE_OK);
316
317 default:
318
319 break;
320 }
321
322 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
323 if (!OpInfo)
324 {
325 return (AE_OK);
326 }
327
328 ArgOp = Op->Asl.Child;
329 OpcodeClass = OpInfo->Class;
330 RuntimeArgTypes = OpInfo->RuntimeArgs;
331
332 #ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
333 /*
334 * Update 11/2008: In practice, we can't perform this check. A simple
335 * analysis is not sufficient. Also, it can cause errors when compiling
336 * disassembled code because of the way Switch operators are implemented
337 * (a While(One) loop with a named temp variable created within.)
338 */
339
340 /*
341 * If we are creating a named object, check if we are within a while loop
342 * by checking if the parent is a WHILE op. This is a simple analysis, but
343 * probably sufficient for many cases.
344 *
345 * Allow Scope(), Buffer(), and Package().
346 */
347 if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) ||
348 ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE)))
349 {
350 if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP)
351 {
352 AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL);
353 }
354 }
355 #endif
356
357 /*
358 * Special case for control opcodes IF/RETURN/WHILE since they
359 * have no runtime arg list (at this time)
360 */
361 switch (Op->Asl.AmlOpcode)
362 {
363 case AML_IF_OP:
364 case AML_WHILE_OP:
365 case AML_RETURN_OP:
366
367 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
368 {
369 /* Check for an internal method */
370
371 if (AnIsInternalMethod (ArgOp))
372 {
373 return (AE_OK);
374 }
375
376 /* The lone arg is a method call, check it */
377
378 RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
379 if (Op->Asl.AmlOpcode == AML_RETURN_OP)
380 {
381 RequiredBtypes = 0xFFFFFFFF;
382 }
383
384 ThisNodeBtype = AnGetBtype (ArgOp);
385 if (ThisNodeBtype == ACPI_UINT32_MAX)
386 {
387 return (AE_OK);
388 }
389
390 AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
391 RequiredBtypes, ThisNodeBtype);
392 }
393 return (AE_OK);
394
395 case AML_EXTERNAL_OP:
396 /*
397 * Not really a "runtime" opcode since it used by disassembler only.
398 * The parser will find any issues with the operands.
399 */
400 return (AE_OK);
401
402 default:
403
404 break;
405 }
406
407 /* Ignore the non-executable opcodes */
408
409 if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
410 {
411 return (AE_OK);
412 }
413
414 /*
415 * Special handling for certain opcodes.
416 */
417 switch (Op->Asl.AmlOpcode)
418 {
419 /* BankField has one TermArg */
420
421 case AML_BANK_FIELD_OP:
422
423 OpcodeClass = AML_CLASS_EXECUTE;
424 ArgOp = ArgOp->Asl.Next;
425 ArgOp = ArgOp->Asl.Next;
426 break;
427
428 /* Operation Region has 2 TermArgs */
429
430 case AML_REGION_OP:
431
432 OpcodeClass = AML_CLASS_EXECUTE;
433 ArgOp = ArgOp->Asl.Next;
434 ArgOp = ArgOp->Asl.Next;
435 break;
436
437 /* DataTableRegion has 3 TermArgs */
438
439 case AML_DATA_REGION_OP:
440
441 OpcodeClass = AML_CLASS_EXECUTE;
442 ArgOp = ArgOp->Asl.Next;
443 break;
444
445 /* Buffers/Packages have a length that is a TermArg */
446
447 case AML_BUFFER_OP:
448 case AML_PACKAGE_OP:
449 case AML_VARIABLE_PACKAGE_OP:
450
451 /* If length is a constant, we are done */
452
453 if ((ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) ||
454 (ArgOp->Asl.ParseOpcode == PARSEOP_RAW_DATA))
455 {
456 return (AE_OK);
457 }
458 break;
459
460 /* Store can write any object to the Debug object */
461
462 case AML_STORE_OP:
463 /*
464 * If this is a Store() to the Debug object, we don't need
465 * to perform any further validation -- because a Store of
466 * any object to Debug is permitted and supported.
467 */
468 if (ArgOp->Asl.Next->Asl.AmlOpcode == AML_DEBUG_OP)
469 {
470 return (AE_OK);
471 }
472 break;
473
474 default:
475 break;
476 }
477
478 switch (OpcodeClass)
479 {
480 case AML_CLASS_EXECUTE:
481 case AML_CLASS_CREATE:
482 case AML_CLASS_CONTROL:
483 case AML_CLASS_RETURN_VALUE:
484
485 /* Reverse the runtime argument list */
486
487 RuntimeArgTypes2 = 0;
488 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
489 {
490 RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
491 RuntimeArgTypes2 |= ArgType;
492 INCREMENT_ARG_LIST (RuntimeArgTypes);
493 }
494
495 /* Typecheck each argument */
496
497 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
498 {
499 /* Get the required type(s) for the argument */
500
501 RequiredBtypes = AnMapArgTypeToBtype (ArgType);
502
503 if (!ArgOp)
504 {
505 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
506 "Null ArgOp in argument loop");
507 AslAbort ();
508 }
509
510 /* Get the actual type of the argument */
511
512 ThisNodeBtype = AnGetBtype (ArgOp);
513 if (ThisNodeBtype == ACPI_UINT32_MAX)
514 {
515 goto NextArgument;
516 }
517
518 /* Examine the arg based on the required type of the arg */
519
520 switch (ArgType)
521 {
522 case ARGI_TARGETREF:
523
524 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
525 {
526 /* ZERO is the placeholder for "don't store result" */
527
528 ThisNodeBtype = RequiredBtypes;
529 break;
530 }
531
532 ACPI_FALLTHROUGH;
533
534 case ARGI_STORE_TARGET:
535
536 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
537 {
538 /*
539 * This is the case where an original reference to a resource
540 * descriptor field has been replaced by an (Integer) offset.
541 * These named fields are supported at compile-time only;
542 * the names are not passed to the interpreter (via the AML).
543 */
544 if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
545 (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
546 {
547 AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD,
548 ArgOp, NULL);
549 }
550 else
551 {
552 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE,
553 ArgOp, NULL);
554 }
555 }
556 break;
557
558
559 #ifdef __FUTURE_IMPLEMENTATION
560 /*
561 * Possible future typechecking support
562 */
563 case ARGI_REFERENCE: /* References */
564 case ARGI_INTEGER_REF:
565 case ARGI_OBJECT_REF:
566 case ARGI_DEVICE_REF:
567
568 switch (ArgOp->Asl.ParseOpcode)
569 {
570 case PARSEOP_LOCAL0:
571 case PARSEOP_LOCAL1:
572 case PARSEOP_LOCAL2:
573 case PARSEOP_LOCAL3:
574 case PARSEOP_LOCAL4:
575 case PARSEOP_LOCAL5:
576 case PARSEOP_LOCAL6:
577 case PARSEOP_LOCAL7:
578
579 /* TBD: implement analysis of current value (type) of the local */
580 /* For now, just treat any local as a typematch */
581
582 /*ThisNodeBtype = RequiredBtypes;*/
583 break;
584
585 case PARSEOP_ARG0:
586 case PARSEOP_ARG1:
587 case PARSEOP_ARG2:
588 case PARSEOP_ARG3:
589 case PARSEOP_ARG4:
590 case PARSEOP_ARG5:
591 case PARSEOP_ARG6:
592
593 /* Hard to analyze argument types, so we won't */
594 /* for now. Just treat any arg as a typematch */
595
596 /* ThisNodeBtype = RequiredBtypes; */
597 break;
598
599 case PARSEOP_DEBUG:
600 case PARSEOP_REFOF:
601 case PARSEOP_INDEX:
602 default:
603
604 break;
605 }
606 break;
607 #endif
608 case ARGI_INTEGER:
609 default:
610
611 break;
612 }
613
614
615 /* Check for a type mismatch (required versus actual) */
616
617 CommonBtypes = ThisNodeBtype & RequiredBtypes;
618
619 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
620 {
621 if (AnIsInternalMethod (ArgOp))
622 {
623 return (AE_OK);
624 }
625
626 /* Check a method call for a valid return value */
627
628 AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
629 RequiredBtypes, ThisNodeBtype);
630 }
631
632 /*
633 * Now check if the actual type(s) match at least one
634 * bit to the required type
635 */
636 else if (!CommonBtypes)
637 {
638 /* No match -- this is a type mismatch error */
639
640 AnFormatBtype (AslGbl_StringBuffer, ThisNodeBtype);
641 AnFormatBtype (AslGbl_StringBuffer2, RequiredBtypes);
642
643 sprintf (AslGbl_MsgBuffer, "[%s] found, %s operator requires [%s]",
644 AslGbl_StringBuffer, OpInfo->Name, AslGbl_StringBuffer2);
645
646 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE,
647 ArgOp, AslGbl_MsgBuffer);
648 }
649
650 NextArgument:
651 ArgOp = ArgOp->Asl.Next;
652 INCREMENT_ARG_LIST (RuntimeArgTypes2);
653 }
654 break;
655
656 default:
657
658 break;
659 }
660
661 return (AE_OK);
662 }
663
664
665 /*******************************************************************************
666 *
667 * FUNCTION: AnOtherSemanticAnalysisWalkBegin
668 *
669 * PARAMETERS: ASL_WALK_CALLBACK
670 *
671 * RETURN: Status
672 *
673 * DESCRIPTION: Descending callback for the analysis walk. Checks for
674 * miscellaneous issues in the code.
675 *
676 ******************************************************************************/
677
678 ACPI_STATUS
AnOtherSemanticAnalysisWalkBegin(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)679 AnOtherSemanticAnalysisWalkBegin (
680 ACPI_PARSE_OBJECT *Op,
681 UINT32 Level,
682 void *Context)
683 {
684 ACPI_PARSE_OBJECT *ArgOp;
685 ACPI_PARSE_OBJECT *PrevArgOp = NULL;
686 const ACPI_OPCODE_INFO *OpInfo;
687 ACPI_NAMESPACE_NODE *Node;
688
689
690 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
691
692
693 if (OpInfo->Flags & AML_CREATE)
694 {
695 /* This group contains all of the Create Buffer Field operators */
696
697 AnValidateCreateBufferField (Op);
698 return (AE_OK);
699 }
700
701 /*
702 * Determine if an execution class operator actually does something by
703 * checking if it has a target and/or the function return value is used.
704 * (Target is optional, so a standalone statement can actually do nothing.)
705 */
706 if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
707 (OpInfo->Flags & AML_HAS_RETVAL) &&
708 (!AnIsResultUsed (Op)))
709 {
710 if (OpInfo->Flags & AML_HAS_TARGET)
711 {
712 /*
713 * Find the target node, it is always the last child. If the target
714 * is not specified in the ASL, a default node of type Zero was
715 * created by the parser.
716 */
717 ArgOp = Op->Asl.Child;
718 while (ArgOp->Asl.Next)
719 {
720 PrevArgOp = ArgOp;
721 ArgOp = ArgOp->Asl.Next;
722 }
723
724 /* Divide() is the only weird case, it has two targets */
725
726 if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
727 {
728 if ((ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) &&
729 (PrevArgOp) &&
730 (PrevArgOp->Asl.ParseOpcode == PARSEOP_ZERO))
731 {
732 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
733 Op, Op->Asl.ExternalName);
734 }
735 }
736
737 else if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
738 {
739 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
740 Op, Op->Asl.ExternalName);
741 }
742 }
743 else
744 {
745 /*
746 * Has no target and the result is not used. Only a couple opcodes
747 * can have this combination.
748 */
749 switch (Op->Asl.ParseOpcode)
750 {
751 case PARSEOP_ACQUIRE:
752 case PARSEOP_WAIT:
753 case PARSEOP_LOADTABLE:
754
755 break;
756
757 default:
758
759 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
760 Op, Op->Asl.ExternalName);
761 break;
762 }
763 }
764 }
765
766 /*
767 * Semantic checks for individual ASL operators
768 */
769
770 switch (Op->Asl.ParseOpcode)
771 {
772 case PARSEOP_STORE:
773
774 if (AslGbl_DoTypechecking)
775 {
776 AnAnalyzeStoreOperator (Op);
777 }
778 break;
779
780
781 case PARSEOP_ACQUIRE:
782 case PARSEOP_WAIT:
783 /*
784 * Emit a warning if the timeout parameter for these operators is not
785 * ACPI_WAIT_FOREVER, and the result value from the operator is not
786 * checked, meaning that a timeout could happen, but the code
787 * would not know about it.
788 */
789
790 /* First child is the namepath, 2nd child is timeout */
791
792 ArgOp = Op->Asl.Child;
793 ArgOp = ArgOp->Asl.Next;
794
795 /*
796 * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
797 * 0xFFFF or greater
798 */
799 if (((ArgOp->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
800 (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)) &&
801 (ArgOp->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
802 {
803 break;
804 }
805
806 /*
807 * The operation could timeout. If the return value is not used
808 * (indicates timeout occurred), issue a warning
809 */
810 if (!AnIsResultUsed (Op))
811 {
812 AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgOp,
813 Op->Asl.ExternalName);
814 }
815 break;
816
817 case PARSEOP_CONNECTION:
818 /*
819 * Ensure that the referenced operation region has the correct SPACE_ID.
820 * From the grammar/parser, we know the parent is a FIELD definition.
821 */
822 ArgOp = Op->Asl.Parent; /* Field definition */
823 ArgOp = ArgOp->Asl.Child; /* First child is the OpRegion Name */
824 Node = ArgOp->Asl.Node; /* OpRegion namespace node */
825 if (!Node)
826 {
827 break;
828 }
829
830 ArgOp = Node->Op; /* OpRegion definition */
831 ArgOp = ArgOp->Asl.Child; /* First child is the OpRegion Name */
832 ArgOp = ArgOp->Asl.Next; /* Next peer is the SPACE_ID (what we want) */
833
834 /*
835 * The Connection() operator is only valid for the following operation
836 * region SpaceIds: GeneralPurposeIo and GenericSerialBus.
837 */
838 if ((ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
839 (ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
840 {
841 AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL);
842 }
843 break;
844
845 case PARSEOP_FIELD:
846 /*
847 * Ensure that fields for GeneralPurposeIo and GenericSerialBus
848 * contain at least one Connection() operator
849 */
850 ArgOp = Op->Asl.Child; /* 1st child is the OpRegion Name */
851 Node = ArgOp->Asl.Node; /* OpRegion namespace node */
852 if (!Node)
853 {
854 break;
855 }
856
857 ArgOp = Node->Op; /* OpRegion definition */
858 ArgOp = ArgOp->Asl.Child; /* First child is the OpRegion Name */
859 ArgOp = ArgOp->Asl.Next; /* Next peer is the SPACE_ID (what we want) */
860
861 /* We are only interested in GeneralPurposeIo and GenericSerialBus */
862
863 if ((ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
864 (ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
865 {
866 break;
867 }
868
869 ArgOp = Op->Asl.Child; /* 1st child is the OpRegion Name */
870 ArgOp = ArgOp->Asl.Next; /* AccessType */
871 ArgOp = ArgOp->Asl.Next; /* LockRule */
872 ArgOp = ArgOp->Asl.Next; /* UpdateRule */
873 ArgOp = ArgOp->Asl.Next; /* Start of FieldUnitList */
874
875 /* Walk the FieldUnitList */
876
877 while (ArgOp)
878 {
879 if (ArgOp->Asl.ParseOpcode == PARSEOP_CONNECTION)
880 {
881 break;
882 }
883 else if (ArgOp->Asl.ParseOpcode == PARSEOP_NAMESEG)
884 {
885 AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgOp, NULL);
886 break;
887 }
888
889 ArgOp = ArgOp->Asl.Next;
890 }
891 break;
892
893 default:
894
895 break;
896 }
897
898 return (AE_OK);
899 }
900
901
902 /*******************************************************************************
903 *
904 * FUNCTION: AnValidateCreateBufferField
905 *
906 * PARAMETERS: Op - A create buffer field operator
907 *
908 * RETURN: None
909 *
910 * DESCRIPTION: Check if a buffer index argument to a create buffer field
911 * operation is beyond the end of the target buffer.
912 *
913 * Validates these AML operators:
914 *
915 * AML_CREATE_FIELD_OP
916 * AML_CREATE_BIT_FIELD_OP
917 * AML_CREATE_BYTE_FIELD_OP
918 * AML_CREATE_WORD_FIELD_OP
919 * AML_CREATE_DWORD_FIELD_OP
920 * AML_CREATE_QWORD_FIELD_OP
921 *
922 * There are two conditions that must be satisfied in order to enable
923 * validation at compile time:
924 *
925 * 1) The length of the target buffer must be an integer constant
926 * 2) The index specified in the create* must be an integer constant
927 * 3) For CreateField, the bit length argument must be non-zero.
928 *
929 ******************************************************************************/
930
931 static void
AnValidateCreateBufferField(ACPI_PARSE_OBJECT * CreateBufferFieldOp)932 AnValidateCreateBufferField (
933 ACPI_PARSE_OBJECT *CreateBufferFieldOp)
934 {
935 ACPI_PARSE_OBJECT *TargetBufferOp;
936 ACPI_PARSE_OBJECT *ArgOp;
937 UINT32 TargetBufferLength;
938 UINT32 LastFieldByteIndex;
939
940
941 /*
942 * 1) Get the length of the target buffer
943 */
944 ArgOp = CreateBufferFieldOp->Asl.Child; /* Reference to target buffer */
945
946 /*
947 * If no attached Node, the target buffer may be something like an
948 * ArgX or LocalX and cannot be evaluated at compile time.
949 */
950 if (!ArgOp->Asl.Node)
951 {
952 return;
953 }
954
955 TargetBufferOp = ArgOp->Asl.Node->Op;
956 TargetBufferOp = TargetBufferOp->Asl.Child; /* Target buffer */
957 TargetBufferOp = TargetBufferOp->Asl.Next; /* "Buffer" keyword */
958 if (!TargetBufferOp)
959 {
960 /* Not a statement of the form NAME(XXXX, Buffer.... */
961
962 return;
963 }
964
965 /* Get the buffer length argument. It must be an integer constant */
966
967 ArgOp = TargetBufferOp->Asl.Child;
968 if (!AnIsValidBufferConstant (ArgOp))
969 {
970 return;
971 }
972
973 TargetBufferLength = (UINT32) ArgOp->Asl.Value.Integer;
974
975 /*
976 * 2) Get the value of the buffer index argument. It must be
977 * an integer constant.
978 */
979 ArgOp = CreateBufferFieldOp->Asl.Child; /* Reference to target buffer */
980 ArgOp = ArgOp->Asl.Next; /* Buffer Index argument*/
981 if (!AnIsValidBufferConstant (ArgOp))
982 {
983 return;
984 }
985
986 LastFieldByteIndex =
987 (UINT32) ArgOp->Asl.Value.Integer; /* Index can be in either bytes or bits */
988
989 /*
990 * 3) Get the length of the new buffer field, in bytes. Also,
991 * create the final target buffer index for the last byte of the field
992 */
993 switch (CreateBufferFieldOp->Asl.ParseOpcode)
994 {
995 case PARSEOP_CREATEBITFIELD: /* A one bit field */
996
997 LastFieldByteIndex = ACPI_ROUND_BITS_DOWN_TO_BYTES (LastFieldByteIndex);
998 break;
999
1000 case PARSEOP_CREATEBYTEFIELD:
1001 break;
1002
1003 case PARSEOP_CREATEWORDFIELD:
1004
1005 LastFieldByteIndex += (sizeof (UINT16) - 1);
1006 break;
1007
1008 case PARSEOP_CREATEDWORDFIELD:
1009
1010 LastFieldByteIndex += (sizeof (UINT32) - 1);
1011 break;
1012
1013 case PARSEOP_CREATEQWORDFIELD:
1014
1015 LastFieldByteIndex += (sizeof (UINT64) - 1);
1016 break;
1017
1018 case PARSEOP_CREATEFIELD: /* Multi-bit field */
1019
1020 ArgOp = ArgOp->Asl.Next; /* Length argument, in bits */
1021 if (!AnIsValidBufferConstant (ArgOp))
1022 {
1023 return;
1024 }
1025
1026 /* The buffer field length is not allowed to be zero */
1027
1028 if (ArgOp->Asl.Value.Integer == 0)
1029 {
1030 AslError (ASL_WARNING, ASL_MSG_BUFFER_FIELD_LENGTH, ArgOp, NULL);
1031 return;
1032 }
1033
1034 LastFieldByteIndex +=
1035 ((UINT32) ArgOp->Asl.Value.Integer - 1); /* Create final bit index */
1036
1037 /* Convert bit index to a byte index */
1038
1039 LastFieldByteIndex = ACPI_ROUND_BITS_DOWN_TO_BYTES (LastFieldByteIndex);
1040 break;
1041
1042 default:
1043 return;
1044 }
1045
1046 /*
1047 * 4) Check for an access (index) beyond the end of the target buffer,
1048 * or a zero length target buffer.
1049 */
1050 if (!TargetBufferLength || (LastFieldByteIndex >= TargetBufferLength))
1051 {
1052 AslError (ASL_WARNING, ASL_MSG_BUFFER_FIELD_OVERFLOW, ArgOp, NULL);
1053 }
1054 }
1055
1056
1057 /*******************************************************************************
1058 *
1059 * FUNCTION: AnIsValidBufferConstant
1060 *
1061 * PARAMETERS: Op - A buffer-related operand
1062 *
1063 * RETURN: TRUE if operand is valid constant, FALSE otherwise
1064 *
1065 * DESCRIPTION: Check if the input Op is valid constant that can be used
1066 * in compile-time analysis.
1067 *
1068 ******************************************************************************/
1069
1070 static BOOLEAN
AnIsValidBufferConstant(ACPI_PARSE_OBJECT * Op)1071 AnIsValidBufferConstant (
1072 ACPI_PARSE_OBJECT *Op)
1073 {
1074 if (!Op)
1075 {
1076 return (FALSE);
1077 }
1078
1079 if ((Op->Asl.ParseOpcode == PARSEOP_INTEGER) ||
1080 (Op->Asl.ParseOpcode == PARSEOP_ZERO) ||
1081 (Op->Asl.ParseOpcode == PARSEOP_ONE))
1082 {
1083 return (TRUE);
1084 }
1085
1086 return (FALSE);
1087 }
1088
1089
1090 /*******************************************************************************
1091 *
1092 * FUNCTION: AnAnalyzeStoreOperator
1093 *
1094 * PARAMETERS: Op - Store() operator
1095 *
1096 * RETURN: None
1097 *
1098 * DESCRIPTION: Analyze a store operator. Mostly for stores to/from package
1099 * objects where there are more restrictions than other data
1100 * types.
1101 *
1102 ******************************************************************************/
1103
1104 static void
AnAnalyzeStoreOperator(ACPI_PARSE_OBJECT * Op)1105 AnAnalyzeStoreOperator (
1106 ACPI_PARSE_OBJECT *Op)
1107 {
1108 ACPI_NAMESPACE_NODE *SourceNode;
1109 ACPI_NAMESPACE_NODE *TargetNode;
1110 ACPI_PARSE_OBJECT *SourceOperandOp;
1111 ACPI_PARSE_OBJECT *TargetOperandOp;
1112 UINT32 SourceOperandBtype;
1113 UINT32 TargetOperandBtype;
1114
1115
1116 /* Extract the two operands for STORE */
1117
1118 SourceOperandOp = Op->Asl.Child;
1119 TargetOperandOp = SourceOperandOp->Asl.Next;
1120
1121 /*
1122 * Ignore these Source operand opcodes, they cannot be typechecked,
1123 * the actual result is unknown here.
1124 */
1125 switch (SourceOperandOp->Asl.ParseOpcode)
1126 {
1127 /* For these, type of the returned value is unknown at compile time */
1128
1129 case PARSEOP_DEREFOF:
1130 case PARSEOP_METHODCALL:
1131 case PARSEOP_STORE:
1132 case PARSEOP_COPYOBJECT:
1133
1134 return;
1135
1136 case PARSEOP_INDEX:
1137 case PARSEOP_REFOF:
1138
1139 if (!AslGbl_EnableReferenceTypechecking)
1140 {
1141 return;
1142 }
1143
1144 /*
1145 * These opcodes always return an object reference, and thus
1146 * the result can only be stored to a Local, Arg, or Debug.
1147 */
1148 if (TargetOperandOp->Asl.AmlOpcode == AML_DEBUG_OP)
1149 {
1150 return;
1151 }
1152
1153 if ((TargetOperandOp->Asl.AmlOpcode < AML_LOCAL0) ||
1154 (TargetOperandOp->Asl.AmlOpcode > AML_ARG6))
1155 {
1156 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, TargetOperandOp,
1157 "Source [Reference], Target must be [Local/Arg/Debug]");
1158 }
1159 return;
1160
1161 default:
1162 break;
1163 }
1164
1165 /*
1166 * Ignore these Target operand opcodes, they cannot be typechecked
1167 */
1168 switch (TargetOperandOp->Asl.ParseOpcode)
1169 {
1170 case PARSEOP_DEBUG:
1171 case PARSEOP_DEREFOF:
1172 case PARSEOP_REFOF:
1173 case PARSEOP_INDEX:
1174 case PARSEOP_STORE:
1175
1176 return;
1177
1178 default:
1179 break;
1180 }
1181
1182 /*
1183 * Ignore typecheck for External() operands of type "UnknownObj",
1184 * we don't know the actual type (source or target).
1185 */
1186 SourceNode = SourceOperandOp->Asl.Node;
1187 if (SourceNode &&
1188 (SourceNode->Flags & ANOBJ_IS_EXTERNAL) &&
1189 (SourceNode->Type == ACPI_TYPE_ANY))
1190 {
1191 return;
1192 }
1193
1194 TargetNode = TargetOperandOp->Asl.Node;
1195 if (TargetNode &&
1196 (TargetNode->Flags & ANOBJ_IS_EXTERNAL) &&
1197 (TargetNode->Type == ACPI_TYPE_ANY))
1198 {
1199 return;
1200 }
1201
1202 /*
1203 * A NULL node with a namepath AML opcode indicates non-existent
1204 * name. Just return, the error message is generated elsewhere.
1205 */
1206 if ((!SourceNode && (SourceOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)) ||
1207 (!TargetNode && (TargetOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)))
1208 {
1209 return;
1210 }
1211
1212 /*
1213 * Simple check for source same as target via NS node.
1214 * -- Could be expanded to locals and args.
1215 */
1216 if (SourceNode && TargetNode)
1217 {
1218 if (SourceNode == TargetNode)
1219 {
1220 AslError (ASL_WARNING, ASL_MSG_DUPLICATE_ITEM,
1221 TargetOperandOp, "Source is the same as Target");
1222 return;
1223 }
1224 }
1225
1226 /* Ignore typecheck if either source or target is a local or arg */
1227
1228 if ((SourceOperandOp->Asl.AmlOpcode >= AML_LOCAL0) &&
1229 (SourceOperandOp->Asl.AmlOpcode <= AML_ARG6))
1230 {
1231 return; /* Cannot type a local/arg at compile time */
1232 }
1233
1234 if ((TargetOperandOp->Asl.AmlOpcode >= AML_LOCAL0) &&
1235 (TargetOperandOp->Asl.AmlOpcode <= AML_ARG6))
1236 {
1237 return; /* Cannot type a local/arg at compile time */
1238 }
1239
1240 /*
1241 * Package objects are a special case because they cannot by implicitly
1242 * converted to/from anything. Check for these two illegal cases:
1243 *
1244 * Store (non-package, package)
1245 * Store (package, non-package)
1246 */
1247 SourceOperandBtype = AnGetBtype (SourceOperandOp);
1248 TargetOperandBtype = AnGetBtype (TargetOperandOp);
1249
1250 /* Check source first for (package, non-package) case */
1251
1252 if (SourceOperandBtype & ACPI_BTYPE_PACKAGE)
1253 {
1254 /* If Source is PACKAGE-->Target must be PACKAGE */
1255
1256 if (!(TargetOperandBtype & ACPI_BTYPE_PACKAGE))
1257 {
1258 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, TargetOperandOp,
1259 "Source is [Package], Target must be a package also");
1260 }
1261 }
1262
1263 /* Else check target for (non-package, package) case */
1264
1265 else if (TargetOperandBtype & ACPI_BTYPE_PACKAGE)
1266 {
1267 /* If Target is PACKAGE, Source must be PACKAGE */
1268
1269 if (!(SourceOperandBtype & ACPI_BTYPE_PACKAGE))
1270 {
1271 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, SourceOperandOp,
1272 "Target is [Package], Source must be a package also");
1273 }
1274 }
1275 }
1276