aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/dev/acpica/compiler/aslwalks.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/dev/acpica/compiler/aslwalks.c')
-rw-r--r--sys/contrib/dev/acpica/compiler/aslwalks.c1262
1 files changed, 1262 insertions, 0 deletions
diff --git a/sys/contrib/dev/acpica/compiler/aslwalks.c b/sys/contrib/dev/acpica/compiler/aslwalks.c
new file mode 100644
index 000000000000..09bf205f5f8d
--- /dev/null
+++ b/sys/contrib/dev/acpica/compiler/aslwalks.c
@@ -0,0 +1,1262 @@
+/******************************************************************************
+ *
+ * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ *
+ * 1. Copyright Notice
+ *
+ * Some or all of this work - Copyright (c) 1999 - 2020, Intel Corp.
+ * All rights reserved.
+ *
+ * 2. License
+ *
+ * 2.1. This is your license from Intel Corp. under its intellectual property
+ * rights. You may have additional license terms from the party that provided
+ * you this software, covering your right to use that party's intellectual
+ * property rights.
+ *
+ * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
+ * copy of the source code appearing in this file ("Covered Code") an
+ * irrevocable, perpetual, worldwide license under Intel's copyrights in the
+ * base code distributed originally by Intel ("Original Intel Code") to copy,
+ * make derivatives, distribute, use and display any portion of the Covered
+ * Code in any form, with the right to sublicense such rights; and
+ *
+ * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
+ * license (with the right to sublicense), under only those claims of Intel
+ * patents that are infringed by the Original Intel Code, to make, use, sell,
+ * offer to sell, and import the Covered Code and derivative works thereof
+ * solely to the minimum extent necessary to exercise the above copyright
+ * license, and in no event shall the patent license extend to any additions
+ * to or modifications of the Original Intel Code. No other license or right
+ * is granted directly or by implication, estoppel or otherwise;
+ *
+ * The above copyright and patent license is granted only if the following
+ * conditions are met:
+ *
+ * 3. Conditions
+ *
+ * 3.1. Redistribution of Source with Rights to Further Distribute Source.
+ * Redistribution of source code of any substantial portion of the Covered
+ * Code or modification with rights to further distribute source must include
+ * the above Copyright Notice, the above License, this list of Conditions,
+ * and the following Disclaimer and Export Compliance provision. In addition,
+ * Licensee must cause all Covered Code to which Licensee contributes to
+ * contain a file documenting the changes Licensee made to create that Covered
+ * Code and the date of any change. Licensee must include in that file the
+ * documentation of any changes made by any predecessor Licensee. Licensee
+ * must include a prominent statement that the modification is derived,
+ * directly or indirectly, from Original Intel Code.
+ *
+ * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
+ * Redistribution of source code of any substantial portion of the Covered
+ * Code or modification without rights to further distribute source must
+ * include the following Disclaimer and Export Compliance provision in the
+ * documentation and/or other materials provided with distribution. In
+ * addition, Licensee may not authorize further sublicense of source of any
+ * portion of the Covered Code, and must include terms to the effect that the
+ * license from Licensee to its licensee is limited to the intellectual
+ * property embodied in the software Licensee provides to its licensee, and
+ * not to intellectual property embodied in modifications its licensee may
+ * make.
+ *
+ * 3.3. Redistribution of Executable. Redistribution in executable form of any
+ * substantial portion of the Covered Code or modification must reproduce the
+ * above Copyright Notice, and the following Disclaimer and Export Compliance
+ * provision in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3.4. Intel retains all right, title, and interest in and to the Original
+ * Intel Code.
+ *
+ * 3.5. Neither the name Intel nor any other trademark owned or controlled by
+ * Intel shall be used in advertising or otherwise to promote the sale, use or
+ * other dealings in products derived from or relating to the Covered Code
+ * without prior written authorization from Intel.
+ *
+ * 4. Disclaimer and Export Compliance
+ *
+ * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
+ * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
+ * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
+ * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
+ * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
+ * PARTICULAR PURPOSE.
+ *
+ * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
+ * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
+ * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
+ * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
+ * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
+ * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
+ * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
+ * LIMITED REMEDY.
+ *
+ * 4.3. Licensee shall not export, either directly or indirectly, any of this
+ * software or system incorporating such software without first obtaining any
+ * required license or other approval from the U. S. Department of Commerce or
+ * any other agency or department of the United States Government. In the
+ * event Licensee exports any such software from the United States or
+ * re-exports any such software from a foreign destination, Licensee shall
+ * ensure that the distribution and export/re-export of the software is in
+ * compliance with all laws, regulations, orders, or other restrictions of the
+ * U.S. Export Administration Regulations. Licensee agrees that neither it nor
+ * any of its subsidiaries will export/re-export any technical data, process,
+ * software, or service, directly or indirectly, to any country for which the
+ * United States government or any agency thereof requires an export license,
+ * other governmental approval, or letter of assurance, without first obtaining
+ * such license, approval or letter.
+ *
+ *****************************************************************************
+ *
+ * Alternatively, you may choose to be licensed under the terms of the
+ * following license:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Alternatively, you may choose to be licensed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ *****************************************************************************/
+
+#include <contrib/dev/acpica/compiler/aslcompiler.h>
+#include "aslcompiler.y.h"
+#include <contrib/dev/acpica/include/acparser.h>
+#include <contrib/dev/acpica/include/amlcode.h>
+
+
+#define _COMPONENT ACPI_COMPILER
+ ACPI_MODULE_NAME ("aslwalks")
+
+
+/* Local prototypes */
+
+static void
+AnAnalyzeStoreOperator (
+ ACPI_PARSE_OBJECT *Op);
+
+static BOOLEAN
+AnIsValidBufferConstant (
+ ACPI_PARSE_OBJECT *Op);
+
+static void
+AnValidateCreateBufferField (
+ ACPI_PARSE_OBJECT *CreateBufferFieldOp);
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AnMethodTypingWalkEnd
+ *
+ * PARAMETERS: ASL_WALK_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Ascending callback for typing walk. Complete the method
+ * return analysis. Check methods for:
+ * 1) Initialized local variables
+ * 2) Valid arguments
+ * 3) Return types
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AnMethodTypingWalkEnd (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 Level,
+ void *Context)
+{
+ UINT32 ThisOpBtype;
+
+
+ switch (Op->Asl.ParseOpcode)
+ {
+ case PARSEOP_METHOD:
+
+ Op->Asl.CompileFlags |= OP_METHOD_TYPED;
+ break;
+
+ case PARSEOP_RETURN:
+
+ if ((Op->Asl.Child) &&
+ (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
+ {
+ ThisOpBtype = AnGetBtype (Op->Asl.Child);
+
+ if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
+ (ThisOpBtype == (ACPI_UINT32_MAX -1)))
+ {
+ /*
+ * The called method is untyped at this time (typically a
+ * forward reference).
+ *
+ * Check for a recursive method call first. Note: the
+ * Child->Node will be null if the method has not been
+ * resolved.
+ */
+ if (Op->Asl.Child->Asl.Node &&
+ (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op))
+ {
+ /* We must type the method here */
+
+ TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
+ ASL_WALK_VISIT_UPWARD, NULL,
+ AnMethodTypingWalkEnd, NULL);
+
+ ThisOpBtype = AnGetBtype (Op->Asl.Child);
+ }
+ }
+
+ /* Returns a value, save the value type */
+
+ if (Op->Asl.ParentMethod)
+ {
+ Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisOpBtype;
+ }
+ }
+ break;
+
+ default:
+
+ break;
+ }
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AnOperandTypecheckWalkEnd
+ *
+ * PARAMETERS: ASL_WALK_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Ascending callback for analysis walk. Complete method
+ * return analysis.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AnOperandTypecheckWalkEnd (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 Level,
+ void *Context)
+{
+ const ACPI_OPCODE_INFO *OpInfo;
+ UINT32 RuntimeArgTypes;
+ UINT32 RuntimeArgTypes2;
+ UINT32 RequiredBtypes;
+ UINT32 ThisNodeBtype;
+ UINT32 CommonBtypes;
+ UINT32 OpcodeClass;
+ ACPI_PARSE_OBJECT *ArgOp;
+ UINT32 ArgType;
+
+
+ switch (Op->Asl.AmlOpcode)
+ {
+ case AML_RAW_DATA_BYTE:
+ case AML_RAW_DATA_WORD:
+ case AML_RAW_DATA_DWORD:
+ case AML_RAW_DATA_QWORD:
+ case AML_RAW_DATA_BUFFER:
+ case AML_RAW_DATA_CHAIN:
+ case AML_PACKAGE_LENGTH:
+ case AML_UNASSIGNED_OPCODE:
+ case AML_DEFAULT_ARG_OP:
+
+ /* Ignore the internal (compiler-only) AML opcodes */
+
+ return (AE_OK);
+
+ default:
+
+ break;
+ }
+
+ OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
+ if (!OpInfo)
+ {
+ return (AE_OK);
+ }
+
+ ArgOp = Op->Asl.Child;
+ OpcodeClass = OpInfo->Class;
+ RuntimeArgTypes = OpInfo->RuntimeArgs;
+
+#ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
+ /*
+ * Update 11/2008: In practice, we can't perform this check. A simple
+ * analysis is not sufficient. Also, it can cause errors when compiling
+ * disassembled code because of the way Switch operators are implemented
+ * (a While(One) loop with a named temp variable created within.)
+ */
+
+ /*
+ * If we are creating a named object, check if we are within a while loop
+ * by checking if the parent is a WHILE op. This is a simple analysis, but
+ * probably sufficient for many cases.
+ *
+ * Allow Scope(), Buffer(), and Package().
+ */
+ if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) ||
+ ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE)))
+ {
+ if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP)
+ {
+ AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL);
+ }
+ }
+#endif
+
+ /*
+ * Special case for control opcodes IF/RETURN/WHILE since they
+ * have no runtime arg list (at this time)
+ */
+ switch (Op->Asl.AmlOpcode)
+ {
+ case AML_IF_OP:
+ case AML_WHILE_OP:
+ case AML_RETURN_OP:
+
+ if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
+ {
+ /* Check for an internal method */
+
+ if (AnIsInternalMethod (ArgOp))
+ {
+ return (AE_OK);
+ }
+
+ /* The lone arg is a method call, check it */
+
+ RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
+ if (Op->Asl.AmlOpcode == AML_RETURN_OP)
+ {
+ RequiredBtypes = 0xFFFFFFFF;
+ }
+
+ ThisNodeBtype = AnGetBtype (ArgOp);
+ if (ThisNodeBtype == ACPI_UINT32_MAX)
+ {
+ return (AE_OK);
+ }
+
+ AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
+ RequiredBtypes, ThisNodeBtype);
+ }
+ return (AE_OK);
+
+ case AML_EXTERNAL_OP:
+ /*
+ * Not really a "runtime" opcode since it used by disassembler only.
+ * The parser will find any issues with the operands.
+ */
+ return (AE_OK);
+
+ default:
+
+ break;
+ }
+
+ /* Ignore the non-executable opcodes */
+
+ if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
+ {
+ return (AE_OK);
+ }
+
+ /*
+ * Special handling for certain opcodes.
+ */
+ switch (Op->Asl.AmlOpcode)
+ {
+ /* BankField has one TermArg */
+
+ case AML_BANK_FIELD_OP:
+
+ OpcodeClass = AML_CLASS_EXECUTE;
+ ArgOp = ArgOp->Asl.Next;
+ ArgOp = ArgOp->Asl.Next;
+ break;
+
+ /* Operation Region has 2 TermArgs */
+
+ case AML_REGION_OP:
+
+ OpcodeClass = AML_CLASS_EXECUTE;
+ ArgOp = ArgOp->Asl.Next;
+ ArgOp = ArgOp->Asl.Next;
+ break;
+
+ /* DataTableRegion has 3 TermArgs */
+
+ case AML_DATA_REGION_OP:
+
+ OpcodeClass = AML_CLASS_EXECUTE;
+ ArgOp = ArgOp->Asl.Next;
+ break;
+
+ /* Buffers/Packages have a length that is a TermArg */
+
+ case AML_BUFFER_OP:
+ case AML_PACKAGE_OP:
+ case AML_VARIABLE_PACKAGE_OP:
+
+ /* If length is a constant, we are done */
+
+ if ((ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) ||
+ (ArgOp->Asl.ParseOpcode == PARSEOP_RAW_DATA))
+ {
+ return (AE_OK);
+ }
+ break;
+
+ /* Store can write any object to the Debug object */
+
+ case AML_STORE_OP:
+ /*
+ * If this is a Store() to the Debug object, we don't need
+ * to perform any further validation -- because a Store of
+ * any object to Debug is permitted and supported.
+ */
+ if (ArgOp->Asl.Next->Asl.AmlOpcode == AML_DEBUG_OP)
+ {
+ return (AE_OK);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ switch (OpcodeClass)
+ {
+ case AML_CLASS_EXECUTE:
+ case AML_CLASS_CREATE:
+ case AML_CLASS_CONTROL:
+ case AML_CLASS_RETURN_VALUE:
+
+ /* Reverse the runtime argument list */
+
+ RuntimeArgTypes2 = 0;
+ while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
+ {
+ RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
+ RuntimeArgTypes2 |= ArgType;
+ INCREMENT_ARG_LIST (RuntimeArgTypes);
+ }
+
+ /* Typecheck each argument */
+
+ while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
+ {
+ /* Get the required type(s) for the argument */
+
+ RequiredBtypes = AnMapArgTypeToBtype (ArgType);
+
+ if (!ArgOp)
+ {
+ AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
+ "Null ArgOp in argument loop");
+ AslAbort ();
+ }
+
+ /* Get the actual type of the argument */
+
+ ThisNodeBtype = AnGetBtype (ArgOp);
+ if (ThisNodeBtype == ACPI_UINT32_MAX)
+ {
+ goto NextArgument;
+ }
+
+ /* Examine the arg based on the required type of the arg */
+
+ switch (ArgType)
+ {
+ case ARGI_TARGETREF:
+
+ if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
+ {
+ /* ZERO is the placeholder for "don't store result" */
+
+ ThisNodeBtype = RequiredBtypes;
+ break;
+ }
+
+ /* Fallthrough */
+
+ case ARGI_STORE_TARGET:
+
+ if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
+ {
+ /*
+ * This is the case where an original reference to a resource
+ * descriptor field has been replaced by an (Integer) offset.
+ * These named fields are supported at compile-time only;
+ * the names are not passed to the interpreter (via the AML).
+ */
+ if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
+ (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD,
+ ArgOp, NULL);
+ }
+ else
+ {
+ AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE,
+ ArgOp, NULL);
+ }
+ }
+ break;
+
+
+#ifdef __FUTURE_IMPLEMENTATION
+/*
+ * Possible future typechecking support
+ */
+ case ARGI_REFERENCE: /* References */
+ case ARGI_INTEGER_REF:
+ case ARGI_OBJECT_REF:
+ case ARGI_DEVICE_REF:
+
+ switch (ArgOp->Asl.ParseOpcode)
+ {
+ case PARSEOP_LOCAL0:
+ case PARSEOP_LOCAL1:
+ case PARSEOP_LOCAL2:
+ case PARSEOP_LOCAL3:
+ case PARSEOP_LOCAL4:
+ case PARSEOP_LOCAL5:
+ case PARSEOP_LOCAL6:
+ case PARSEOP_LOCAL7:
+
+ /* TBD: implement analysis of current value (type) of the local */
+ /* For now, just treat any local as a typematch */
+
+ /*ThisNodeBtype = RequiredBtypes;*/
+ break;
+
+ case PARSEOP_ARG0:
+ case PARSEOP_ARG1:
+ case PARSEOP_ARG2:
+ case PARSEOP_ARG3:
+ case PARSEOP_ARG4:
+ case PARSEOP_ARG5:
+ case PARSEOP_ARG6:
+
+ /* Hard to analyze argument types, so we won't */
+ /* for now. Just treat any arg as a typematch */
+
+ /* ThisNodeBtype = RequiredBtypes; */
+ break;
+
+ case PARSEOP_DEBUG:
+ case PARSEOP_REFOF:
+ case PARSEOP_INDEX:
+ default:
+
+ break;
+ }
+ break;
+#endif
+ case ARGI_INTEGER:
+ default:
+
+ break;
+ }
+
+
+ /* Check for a type mismatch (required versus actual) */
+
+ CommonBtypes = ThisNodeBtype & RequiredBtypes;
+
+ if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
+ {
+ if (AnIsInternalMethod (ArgOp))
+ {
+ return (AE_OK);
+ }
+
+ /* Check a method call for a valid return value */
+
+ AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
+ RequiredBtypes, ThisNodeBtype);
+ }
+
+ /*
+ * Now check if the actual type(s) match at least one
+ * bit to the required type
+ */
+ else if (!CommonBtypes)
+ {
+ /* No match -- this is a type mismatch error */
+
+ AnFormatBtype (AslGbl_StringBuffer, ThisNodeBtype);
+ AnFormatBtype (AslGbl_StringBuffer2, RequiredBtypes);
+
+ sprintf (AslGbl_MsgBuffer, "[%s] found, %s operator requires [%s]",
+ AslGbl_StringBuffer, OpInfo->Name, AslGbl_StringBuffer2);
+
+ AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE,
+ ArgOp, AslGbl_MsgBuffer);
+ }
+
+ NextArgument:
+ ArgOp = ArgOp->Asl.Next;
+ INCREMENT_ARG_LIST (RuntimeArgTypes2);
+ }
+ break;
+
+ default:
+
+ break;
+ }
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AnOtherSemanticAnalysisWalkBegin
+ *
+ * PARAMETERS: ASL_WALK_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Descending callback for the analysis walk. Checks for
+ * miscellaneous issues in the code.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AnOtherSemanticAnalysisWalkBegin (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 Level,
+ void *Context)
+{
+ ACPI_PARSE_OBJECT *ArgOp;
+ ACPI_PARSE_OBJECT *PrevArgOp = NULL;
+ const ACPI_OPCODE_INFO *OpInfo;
+ ACPI_NAMESPACE_NODE *Node;
+
+
+ OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
+
+
+ if (OpInfo->Flags & AML_CREATE)
+ {
+ /* This group contains all of the Create Buffer Field operators */
+
+ AnValidateCreateBufferField (Op);
+ return (AE_OK);
+ }
+
+ /*
+ * Determine if an execution class operator actually does something by
+ * checking if it has a target and/or the function return value is used.
+ * (Target is optional, so a standalone statement can actually do nothing.)
+ */
+ if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
+ (OpInfo->Flags & AML_HAS_RETVAL) &&
+ (!AnIsResultUsed (Op)))
+ {
+ if (OpInfo->Flags & AML_HAS_TARGET)
+ {
+ /*
+ * Find the target node, it is always the last child. If the target
+ * is not specified in the ASL, a default node of type Zero was
+ * created by the parser.
+ */
+ ArgOp = Op->Asl.Child;
+ while (ArgOp->Asl.Next)
+ {
+ PrevArgOp = ArgOp;
+ ArgOp = ArgOp->Asl.Next;
+ }
+
+ /* Divide() is the only weird case, it has two targets */
+
+ if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
+ {
+ if ((ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) &&
+ (PrevArgOp) &&
+ (PrevArgOp->Asl.ParseOpcode == PARSEOP_ZERO))
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
+ Op, Op->Asl.ExternalName);
+ }
+ }
+
+ else if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
+ Op, Op->Asl.ExternalName);
+ }
+ }
+ else
+ {
+ /*
+ * Has no target and the result is not used. Only a couple opcodes
+ * can have this combination.
+ */
+ switch (Op->Asl.ParseOpcode)
+ {
+ case PARSEOP_ACQUIRE:
+ case PARSEOP_WAIT:
+ case PARSEOP_LOADTABLE:
+
+ break;
+
+ default:
+
+ AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
+ Op, Op->Asl.ExternalName);
+ break;
+ }
+ }
+ }
+
+ /*
+ * Semantic checks for individual ASL operators
+ */
+
+ switch (Op->Asl.ParseOpcode)
+ {
+ case PARSEOP_STORE:
+
+ if (AslGbl_DoTypechecking)
+ {
+ AnAnalyzeStoreOperator (Op);
+ }
+ break;
+
+
+ case PARSEOP_ACQUIRE:
+ case PARSEOP_WAIT:
+ /*
+ * Emit a warning if the timeout parameter for these operators is not
+ * ACPI_WAIT_FOREVER, and the result value from the operator is not
+ * checked, meaning that a timeout could happen, but the code
+ * would not know about it.
+ */
+
+ /* First child is the namepath, 2nd child is timeout */
+
+ ArgOp = Op->Asl.Child;
+ ArgOp = ArgOp->Asl.Next;
+
+ /*
+ * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
+ * 0xFFFF or greater
+ */
+ if (((ArgOp->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
+ (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)) &&
+ (ArgOp->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
+ {
+ break;
+ }
+
+ /*
+ * The operation could timeout. If the return value is not used
+ * (indicates timeout occurred), issue a warning
+ */
+ if (!AnIsResultUsed (Op))
+ {
+ AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgOp,
+ Op->Asl.ExternalName);
+ }
+ break;
+
+ case PARSEOP_CONNECTION:
+ /*
+ * Ensure that the referenced operation region has the correct SPACE_ID.
+ * From the grammar/parser, we know the parent is a FIELD definition.
+ */
+ ArgOp = Op->Asl.Parent; /* Field definition */
+ ArgOp = ArgOp->Asl.Child; /* First child is the OpRegion Name */
+ Node = ArgOp->Asl.Node; /* OpRegion namespace node */
+ if (!Node)
+ {
+ break;
+ }
+
+ ArgOp = Node->Op; /* OpRegion definition */
+ ArgOp = ArgOp->Asl.Child; /* First child is the OpRegion Name */
+ ArgOp = ArgOp->Asl.Next; /* Next peer is the SPACE_ID (what we want) */
+
+ /*
+ * The Connection() operator is only valid for the following operation
+ * region SpaceIds: GeneralPurposeIo and GenericSerialBus.
+ */
+ if ((ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
+ (ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
+ {
+ AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL);
+ }
+ break;
+
+ case PARSEOP_FIELD:
+ /*
+ * Ensure that fields for GeneralPurposeIo and GenericSerialBus
+ * contain at least one Connection() operator
+ */
+ ArgOp = Op->Asl.Child; /* 1st child is the OpRegion Name */
+ Node = ArgOp->Asl.Node; /* OpRegion namespace node */
+ if (!Node)
+ {
+ break;
+ }
+
+ ArgOp = Node->Op; /* OpRegion definition */
+ ArgOp = ArgOp->Asl.Child; /* First child is the OpRegion Name */
+ ArgOp = ArgOp->Asl.Next; /* Next peer is the SPACE_ID (what we want) */
+
+ /* We are only interested in GeneralPurposeIo and GenericSerialBus */
+
+ if ((ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
+ (ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
+ {
+ break;
+ }
+
+ ArgOp = Op->Asl.Child; /* 1st child is the OpRegion Name */
+ ArgOp = ArgOp->Asl.Next; /* AccessType */
+ ArgOp = ArgOp->Asl.Next; /* LockRule */
+ ArgOp = ArgOp->Asl.Next; /* UpdateRule */
+ ArgOp = ArgOp->Asl.Next; /* Start of FieldUnitList */
+
+ /* Walk the FieldUnitList */
+
+ while (ArgOp)
+ {
+ if (ArgOp->Asl.ParseOpcode == PARSEOP_CONNECTION)
+ {
+ break;
+ }
+ else if (ArgOp->Asl.ParseOpcode == PARSEOP_NAMESEG)
+ {
+ AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgOp, NULL);
+ break;
+ }
+
+ ArgOp = ArgOp->Asl.Next;
+ }
+ break;
+
+ default:
+
+ break;
+ }
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AnValidateCreateBufferField
+ *
+ * PARAMETERS: Op - A create buffer field operator
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Check if a buffer index argument to a create buffer field
+ * operation is beyond the end of the target buffer.
+ *
+ * Validates these AML operators:
+ *
+ * AML_CREATE_FIELD_OP
+ * AML_CREATE_BIT_FIELD_OP
+ * AML_CREATE_BYTE_FIELD_OP
+ * AML_CREATE_WORD_FIELD_OP
+ * AML_CREATE_DWORD_FIELD_OP
+ * AML_CREATE_QWORD_FIELD_OP
+ *
+ * There are two conditions that must be satisfied in order to enable
+ * validation at compile time:
+ *
+ * 1) The length of the target buffer must be an integer constant
+ * 2) The index specified in the create* must be an integer constant
+ * 3) For CreateField, the bit length argument must be non-zero.
+ *
+ ******************************************************************************/
+
+static void
+AnValidateCreateBufferField (
+ ACPI_PARSE_OBJECT *CreateBufferFieldOp)
+{
+ ACPI_PARSE_OBJECT *TargetBufferOp;
+ ACPI_PARSE_OBJECT *ArgOp;
+ UINT32 TargetBufferLength;
+ UINT32 LastFieldByteIndex;
+
+
+ /*
+ * 1) Get the length of the target buffer
+ */
+ ArgOp = CreateBufferFieldOp->Asl.Child; /* Reference to target buffer */
+
+ /*
+ * If no attached Node, the target buffer may be something like an
+ * ArgX or LocalX and cannot be evaluated at compile time.
+ */
+ if (!ArgOp->Asl.Node)
+ {
+ return;
+ }
+
+ TargetBufferOp = ArgOp->Asl.Node->Op;
+ TargetBufferOp = TargetBufferOp->Asl.Child; /* Target buffer */
+ TargetBufferOp = TargetBufferOp->Asl.Next; /* "Buffer" keyword */
+ if (!TargetBufferOp)
+ {
+ /* Not a statement of the form NAME(XXXX, Buffer.... */
+
+ return;
+ }
+
+ /* Get the buffer length argument. It must be an integer constant */
+
+ ArgOp = TargetBufferOp->Asl.Child;
+ if (!AnIsValidBufferConstant (ArgOp))
+ {
+ return;
+ }
+
+ TargetBufferLength = (UINT32) ArgOp->Asl.Value.Integer;
+
+ /*
+ * 2) Get the value of the buffer index argument. It must be
+ * an integer constant.
+ */
+ ArgOp = CreateBufferFieldOp->Asl.Child; /* Reference to target buffer */
+ ArgOp = ArgOp->Asl.Next; /* Buffer Index argument*/
+ if (!AnIsValidBufferConstant (ArgOp))
+ {
+ return;
+ }
+
+ LastFieldByteIndex =
+ (UINT32) ArgOp->Asl.Value.Integer; /* Index can be in either bytes or bits */
+
+ /*
+ * 3) Get the length of the new buffer field, in bytes. Also,
+ * create the final target buffer index for the last byte of the field
+ */
+ switch (CreateBufferFieldOp->Asl.ParseOpcode)
+ {
+ case PARSEOP_CREATEBITFIELD: /* A one bit field */
+
+ LastFieldByteIndex = ACPI_ROUND_BITS_DOWN_TO_BYTES (LastFieldByteIndex);
+ break;
+
+ case PARSEOP_CREATEBYTEFIELD:
+ break;
+
+ case PARSEOP_CREATEWORDFIELD:
+
+ LastFieldByteIndex += (sizeof (UINT16) - 1);
+ break;
+
+ case PARSEOP_CREATEDWORDFIELD:
+
+ LastFieldByteIndex += (sizeof (UINT32) - 1);
+ break;
+
+ case PARSEOP_CREATEQWORDFIELD:
+
+ LastFieldByteIndex += (sizeof (UINT64) - 1);
+ break;
+
+ case PARSEOP_CREATEFIELD: /* Multi-bit field */
+
+ ArgOp = ArgOp->Asl.Next; /* Length argument, in bits */
+ if (!AnIsValidBufferConstant (ArgOp))
+ {
+ return;
+ }
+
+ /* The buffer field length is not allowed to be zero */
+
+ if (ArgOp->Asl.Value.Integer == 0)
+ {
+ AslError (ASL_WARNING, ASL_MSG_BUFFER_FIELD_LENGTH, ArgOp, NULL);
+ return;
+ }
+
+ LastFieldByteIndex +=
+ ((UINT32) ArgOp->Asl.Value.Integer - 1); /* Create final bit index */
+
+ /* Convert bit index to a byte index */
+
+ LastFieldByteIndex = ACPI_ROUND_BITS_DOWN_TO_BYTES (LastFieldByteIndex);
+ break;
+
+ default:
+ return;
+ }
+
+ /*
+ * 4) Check for an access (index) beyond the end of the target buffer,
+ * or a zero length target buffer.
+ */
+ if (!TargetBufferLength || (LastFieldByteIndex >= TargetBufferLength))
+ {
+ AslError (ASL_WARNING, ASL_MSG_BUFFER_FIELD_OVERFLOW, ArgOp, NULL);
+ }
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AnIsValidBufferConstant
+ *
+ * PARAMETERS: Op - A buffer-related operand
+ *
+ * RETURN: TRUE if operand is valid constant, FALSE otherwise
+ *
+ * DESCRIPTION: Check if the input Op is valid constant that can be used
+ * in compile-time analysis.
+ *
+ ******************************************************************************/
+
+static BOOLEAN
+AnIsValidBufferConstant (
+ ACPI_PARSE_OBJECT *Op)
+{
+ if (!Op)
+ {
+ return (FALSE);
+ }
+
+ if ((Op->Asl.ParseOpcode == PARSEOP_INTEGER) ||
+ (Op->Asl.ParseOpcode == PARSEOP_ZERO) ||
+ (Op->Asl.ParseOpcode == PARSEOP_ONE))
+ {
+ return (TRUE);
+ }
+
+ return (FALSE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AnAnalyzeStoreOperator
+ *
+ * PARAMETERS: Op - Store() operator
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Analyze a store operator. Mostly for stores to/from package
+ * objects where there are more restrictions than other data
+ * types.
+ *
+ ******************************************************************************/
+
+static void
+AnAnalyzeStoreOperator (
+ ACPI_PARSE_OBJECT *Op)
+{
+ ACPI_NAMESPACE_NODE *SourceNode;
+ ACPI_NAMESPACE_NODE *TargetNode;
+ ACPI_PARSE_OBJECT *SourceOperandOp;
+ ACPI_PARSE_OBJECT *TargetOperandOp;
+ UINT32 SourceOperandBtype;
+ UINT32 TargetOperandBtype;
+
+
+ /* Extract the two operands for STORE */
+
+ SourceOperandOp = Op->Asl.Child;
+ TargetOperandOp = SourceOperandOp->Asl.Next;
+
+ /*
+ * Ignore these Source operand opcodes, they cannot be typechecked,
+ * the actual result is unknown here.
+ */
+ switch (SourceOperandOp->Asl.ParseOpcode)
+ {
+ /* For these, type of the returned value is unknown at compile time */
+
+ case PARSEOP_DEREFOF:
+ case PARSEOP_METHODCALL:
+ case PARSEOP_STORE:
+ case PARSEOP_COPYOBJECT:
+
+ return;
+
+ case PARSEOP_INDEX:
+ case PARSEOP_REFOF:
+
+ if (!AslGbl_EnableReferenceTypechecking)
+ {
+ return;
+ }
+
+ /*
+ * These opcodes always return an object reference, and thus
+ * the result can only be stored to a Local, Arg, or Debug.
+ */
+ if (TargetOperandOp->Asl.AmlOpcode == AML_DEBUG_OP)
+ {
+ return;
+ }
+
+ if ((TargetOperandOp->Asl.AmlOpcode < AML_LOCAL0) ||
+ (TargetOperandOp->Asl.AmlOpcode > AML_ARG6))
+ {
+ AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, TargetOperandOp,
+ "Source [Reference], Target must be [Local/Arg/Debug]");
+ }
+ return;
+
+ default:
+ break;
+ }
+
+ /*
+ * Ignore these Target operand opcodes, they cannot be typechecked
+ */
+ switch (TargetOperandOp->Asl.ParseOpcode)
+ {
+ case PARSEOP_DEBUG:
+ case PARSEOP_DEREFOF:
+ case PARSEOP_REFOF:
+ case PARSEOP_INDEX:
+ case PARSEOP_STORE:
+
+ return;
+
+ default:
+ break;
+ }
+
+ /*
+ * Ignore typecheck for External() operands of type "UnknownObj",
+ * we don't know the actual type (source or target).
+ */
+ SourceNode = SourceOperandOp->Asl.Node;
+ if (SourceNode &&
+ (SourceNode->Flags & ANOBJ_IS_EXTERNAL) &&
+ (SourceNode->Type == ACPI_TYPE_ANY))
+ {
+ return;
+ }
+
+ TargetNode = TargetOperandOp->Asl.Node;
+ if (TargetNode &&
+ (TargetNode->Flags & ANOBJ_IS_EXTERNAL) &&
+ (TargetNode->Type == ACPI_TYPE_ANY))
+ {
+ return;
+ }
+
+ /*
+ * A NULL node with a namepath AML opcode indicates non-existent
+ * name. Just return, the error message is generated elsewhere.
+ */
+ if ((!SourceNode && (SourceOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)) ||
+ (!TargetNode && (TargetOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)))
+ {
+ return;
+ }
+
+ /*
+ * Simple check for source same as target via NS node.
+ * -- Could be expanded to locals and args.
+ */
+ if (SourceNode && TargetNode)
+ {
+ if (SourceNode == TargetNode)
+ {
+ AslError (ASL_WARNING, ASL_MSG_DUPLICATE_ITEM,
+ TargetOperandOp, "Source is the same as Target");
+ return;
+ }
+ }
+
+ /* Ignore typecheck if either source or target is a local or arg */
+
+ if ((SourceOperandOp->Asl.AmlOpcode >= AML_LOCAL0) &&
+ (SourceOperandOp->Asl.AmlOpcode <= AML_ARG6))
+ {
+ return; /* Cannot type a local/arg at compile time */
+ }
+
+ if ((TargetOperandOp->Asl.AmlOpcode >= AML_LOCAL0) &&
+ (TargetOperandOp->Asl.AmlOpcode <= AML_ARG6))
+ {
+ return; /* Cannot type a local/arg at compile time */
+ }
+
+ /*
+ * Package objects are a special case because they cannot by implicitly
+ * converted to/from anything. Check for these two illegal cases:
+ *
+ * Store (non-package, package)
+ * Store (package, non-package)
+ */
+ SourceOperandBtype = AnGetBtype (SourceOperandOp);
+ TargetOperandBtype = AnGetBtype (TargetOperandOp);
+
+ /* Check source first for (package, non-package) case */
+
+ if (SourceOperandBtype & ACPI_BTYPE_PACKAGE)
+ {
+ /* If Source is PACKAGE-->Target must be PACKAGE */
+
+ if (!(TargetOperandBtype & ACPI_BTYPE_PACKAGE))
+ {
+ AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, TargetOperandOp,
+ "Source is [Package], Target must be a package also");
+ }
+ }
+
+ /* Else check target for (non-package, package) case */
+
+ else if (TargetOperandBtype & ACPI_BTYPE_PACKAGE)
+ {
+ /* If Target is PACKAGE, Source must be PACKAGE */
+
+ if (!(SourceOperandBtype & ACPI_BTYPE_PACKAGE))
+ {
+ AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, SourceOperandOp,
+ "Target is [Package], Source must be a package also");
+ }
+ }
+}