aslwalks.c revision 249112
1218585Sjkim/****************************************************************************** 2218585Sjkim * 3245582Sjkim * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks 4218585Sjkim * 5218585Sjkim *****************************************************************************/ 6218585Sjkim 7218585Sjkim/* 8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp. 9218585Sjkim * All rights reserved. 10218585Sjkim * 11218585Sjkim * Redistribution and use in source and binary forms, with or without 12218585Sjkim * modification, are permitted provided that the following conditions 13218585Sjkim * are met: 14218585Sjkim * 1. Redistributions of source code must retain the above copyright 15218585Sjkim * notice, this list of conditions, and the following disclaimer, 16218585Sjkim * without modification. 17218585Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18218585Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19218585Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20218585Sjkim * including a substantially similar Disclaimer requirement for further 21218585Sjkim * binary redistribution. 22218585Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23218585Sjkim * of any contributors may be used to endorse or promote products derived 24218585Sjkim * from this software without specific prior written permission. 25218585Sjkim * 26218585Sjkim * Alternatively, this software may be distributed under the terms of the 27218585Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28218585Sjkim * Software Foundation. 29218585Sjkim * 30218585Sjkim * NO WARRANTY 31218585Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32218585Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33218585Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34218585Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35218585Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36218585Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37218585Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38218585Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39218585Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40218585Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41218585Sjkim * POSSIBILITY OF SUCH DAMAGES. 42218585Sjkim */ 43218585Sjkim 44218585Sjkim 45218590Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 46218585Sjkim#include "aslcompiler.y.h" 47218590Sjkim#include <contrib/dev/acpica/include/acparser.h> 48218590Sjkim#include <contrib/dev/acpica/include/amlcode.h> 49218585Sjkim 50218585Sjkim 51218585Sjkim#define _COMPONENT ACPI_COMPILER 52218585Sjkim ACPI_MODULE_NAME ("aslwalks") 53218585Sjkim 54218585Sjkim 55218585Sjkim/******************************************************************************* 56218585Sjkim * 57218585Sjkim * FUNCTION: AnMethodTypingWalkEnd 58218585Sjkim * 59218585Sjkim * PARAMETERS: ASL_WALK_CALLBACK 60218585Sjkim * 61218585Sjkim * RETURN: Status 62218585Sjkim * 63218585Sjkim * DESCRIPTION: Ascending callback for typing walk. Complete the method 64218585Sjkim * return analysis. Check methods for: 65218585Sjkim * 1) Initialized local variables 66218585Sjkim * 2) Valid arguments 67218585Sjkim * 3) Return types 68218585Sjkim * 69218585Sjkim ******************************************************************************/ 70218585Sjkim 71218585SjkimACPI_STATUS 72218585SjkimAnMethodTypingWalkEnd ( 73218585Sjkim ACPI_PARSE_OBJECT *Op, 74218585Sjkim UINT32 Level, 75218585Sjkim void *Context) 76218585Sjkim{ 77218585Sjkim UINT32 ThisNodeBtype; 78218585Sjkim 79218585Sjkim 80218585Sjkim switch (Op->Asl.ParseOpcode) 81218585Sjkim { 82218585Sjkim case PARSEOP_METHOD: 83218585Sjkim 84218585Sjkim Op->Asl.CompileFlags |= NODE_METHOD_TYPED; 85218585Sjkim break; 86218585Sjkim 87218585Sjkim case PARSEOP_RETURN: 88218585Sjkim 89218585Sjkim if ((Op->Asl.Child) && 90218585Sjkim (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 91218585Sjkim { 92218585Sjkim ThisNodeBtype = AnGetBtype (Op->Asl.Child); 93218585Sjkim 94218585Sjkim if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) && 95218585Sjkim (ThisNodeBtype == (ACPI_UINT32_MAX -1))) 96218585Sjkim { 97218585Sjkim /* 98218585Sjkim * The called method is untyped at this time (typically a 99218585Sjkim * forward reference). 100218585Sjkim * 101218585Sjkim * Check for a recursive method call first. 102218585Sjkim */ 103218585Sjkim if (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op) 104218585Sjkim { 105218585Sjkim /* We must type the method here */ 106218585Sjkim 107218585Sjkim TrWalkParseTree (Op->Asl.Child->Asl.Node->Op, 108218585Sjkim ASL_WALK_VISIT_UPWARD, NULL, 109218585Sjkim AnMethodTypingWalkEnd, NULL); 110218585Sjkim 111218585Sjkim ThisNodeBtype = AnGetBtype (Op->Asl.Child); 112218585Sjkim } 113218585Sjkim } 114218585Sjkim 115218585Sjkim /* Returns a value, save the value type */ 116218585Sjkim 117218585Sjkim if (Op->Asl.ParentMethod) 118218585Sjkim { 119218585Sjkim Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype; 120218585Sjkim } 121218585Sjkim } 122218585Sjkim break; 123218585Sjkim 124218585Sjkim default: 125218585Sjkim break; 126218585Sjkim } 127218585Sjkim 128218585Sjkim return (AE_OK); 129218585Sjkim} 130218585Sjkim 131218585Sjkim 132218585Sjkim/******************************************************************************* 133218585Sjkim * 134218585Sjkim * FUNCTION: AnOperandTypecheckWalkEnd 135218585Sjkim * 136218585Sjkim * PARAMETERS: ASL_WALK_CALLBACK 137218585Sjkim * 138218585Sjkim * RETURN: Status 139218585Sjkim * 140218585Sjkim * DESCRIPTION: Ascending callback for analysis walk. Complete method 141218585Sjkim * return analysis. 142218585Sjkim * 143218585Sjkim ******************************************************************************/ 144218585Sjkim 145218585SjkimACPI_STATUS 146218585SjkimAnOperandTypecheckWalkEnd ( 147218585Sjkim ACPI_PARSE_OBJECT *Op, 148218585Sjkim UINT32 Level, 149218585Sjkim void *Context) 150218585Sjkim{ 151218585Sjkim const ACPI_OPCODE_INFO *OpInfo; 152218585Sjkim UINT32 RuntimeArgTypes; 153218585Sjkim UINT32 RuntimeArgTypes2; 154218585Sjkim UINT32 RequiredBtypes; 155218585Sjkim UINT32 ThisNodeBtype; 156218585Sjkim UINT32 CommonBtypes; 157218585Sjkim UINT32 OpcodeClass; 158218585Sjkim ACPI_PARSE_OBJECT *ArgOp; 159218585Sjkim UINT32 ArgType; 160218585Sjkim 161218585Sjkim 162218585Sjkim switch (Op->Asl.AmlOpcode) 163218585Sjkim { 164218585Sjkim case AML_RAW_DATA_BYTE: 165218585Sjkim case AML_RAW_DATA_WORD: 166218585Sjkim case AML_RAW_DATA_DWORD: 167218585Sjkim case AML_RAW_DATA_QWORD: 168218585Sjkim case AML_RAW_DATA_BUFFER: 169218585Sjkim case AML_RAW_DATA_CHAIN: 170218585Sjkim case AML_PACKAGE_LENGTH: 171218585Sjkim case AML_UNASSIGNED_OPCODE: 172218585Sjkim case AML_DEFAULT_ARG_OP: 173218585Sjkim 174218585Sjkim /* Ignore the internal (compiler-only) AML opcodes */ 175218585Sjkim 176218585Sjkim return (AE_OK); 177218585Sjkim 178218585Sjkim default: 179218585Sjkim break; 180218585Sjkim } 181218585Sjkim 182218585Sjkim OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 183218585Sjkim if (!OpInfo) 184218585Sjkim { 185218585Sjkim return (AE_OK); 186218585Sjkim } 187218585Sjkim 188218585Sjkim ArgOp = Op->Asl.Child; 189218585Sjkim RuntimeArgTypes = OpInfo->RuntimeArgs; 190218585Sjkim OpcodeClass = OpInfo->Class; 191218585Sjkim 192218585Sjkim#ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE 193218585Sjkim /* 194218585Sjkim * Update 11/2008: In practice, we can't perform this check. A simple 195218585Sjkim * analysis is not sufficient. Also, it can cause errors when compiling 196218585Sjkim * disassembled code because of the way Switch operators are implemented 197218585Sjkim * (a While(One) loop with a named temp variable created within.) 198218585Sjkim */ 199218585Sjkim 200218585Sjkim /* 201218585Sjkim * If we are creating a named object, check if we are within a while loop 202218585Sjkim * by checking if the parent is a WHILE op. This is a simple analysis, but 203218585Sjkim * probably sufficient for many cases. 204218585Sjkim * 205218585Sjkim * Allow Scope(), Buffer(), and Package(). 206218585Sjkim */ 207218585Sjkim if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) || 208218585Sjkim ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE))) 209218585Sjkim { 210218585Sjkim if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP) 211218585Sjkim { 212218585Sjkim AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL); 213218585Sjkim } 214218585Sjkim } 215218585Sjkim#endif 216218585Sjkim 217218585Sjkim /* 218218585Sjkim * Special case for control opcodes IF/RETURN/WHILE since they 219218585Sjkim * have no runtime arg list (at this time) 220218585Sjkim */ 221218585Sjkim switch (Op->Asl.AmlOpcode) 222218585Sjkim { 223218585Sjkim case AML_IF_OP: 224218585Sjkim case AML_WHILE_OP: 225218585Sjkim case AML_RETURN_OP: 226218585Sjkim 227218585Sjkim if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) 228218585Sjkim { 229218585Sjkim /* Check for an internal method */ 230218585Sjkim 231218585Sjkim if (AnIsInternalMethod (ArgOp)) 232218585Sjkim { 233218585Sjkim return (AE_OK); 234218585Sjkim } 235218585Sjkim 236218585Sjkim /* The lone arg is a method call, check it */ 237218585Sjkim 238218585Sjkim RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER); 239218585Sjkim if (Op->Asl.AmlOpcode == AML_RETURN_OP) 240218585Sjkim { 241218585Sjkim RequiredBtypes = 0xFFFFFFFF; 242218585Sjkim } 243218585Sjkim 244218585Sjkim ThisNodeBtype = AnGetBtype (ArgOp); 245218585Sjkim if (ThisNodeBtype == ACPI_UINT32_MAX) 246218585Sjkim { 247218585Sjkim return (AE_OK); 248218585Sjkim } 249218585Sjkim AnCheckMethodReturnValue (Op, OpInfo, ArgOp, 250218585Sjkim RequiredBtypes, ThisNodeBtype); 251218585Sjkim } 252218585Sjkim return (AE_OK); 253218585Sjkim 254218585Sjkim default: 255218585Sjkim break; 256218585Sjkim } 257218585Sjkim 258218585Sjkim /* Ignore the non-executable opcodes */ 259218585Sjkim 260218585Sjkim if (RuntimeArgTypes == ARGI_INVALID_OPCODE) 261218585Sjkim { 262218585Sjkim return (AE_OK); 263218585Sjkim } 264218585Sjkim 265218585Sjkim switch (OpcodeClass) 266218585Sjkim { 267218585Sjkim case AML_CLASS_EXECUTE: 268218585Sjkim case AML_CLASS_CREATE: 269218585Sjkim case AML_CLASS_CONTROL: 270218585Sjkim case AML_CLASS_RETURN_VALUE: 271218585Sjkim 272218585Sjkim /* TBD: Change class or fix typechecking for these */ 273218585Sjkim 274218585Sjkim if ((Op->Asl.AmlOpcode == AML_BUFFER_OP) || 275218585Sjkim (Op->Asl.AmlOpcode == AML_PACKAGE_OP) || 276218585Sjkim (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP)) 277218585Sjkim { 278218585Sjkim break; 279218585Sjkim } 280218585Sjkim 281218585Sjkim /* Reverse the runtime argument list */ 282218585Sjkim 283218585Sjkim RuntimeArgTypes2 = 0; 284218585Sjkim while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes))) 285218585Sjkim { 286218585Sjkim RuntimeArgTypes2 <<= ARG_TYPE_WIDTH; 287218585Sjkim RuntimeArgTypes2 |= ArgType; 288218585Sjkim INCREMENT_ARG_LIST (RuntimeArgTypes); 289218585Sjkim } 290218585Sjkim 291218585Sjkim while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2))) 292218585Sjkim { 293218585Sjkim RequiredBtypes = AnMapArgTypeToBtype (ArgType); 294218585Sjkim 295218585Sjkim ThisNodeBtype = AnGetBtype (ArgOp); 296218585Sjkim if (ThisNodeBtype == ACPI_UINT32_MAX) 297218585Sjkim { 298218585Sjkim goto NextArgument; 299218585Sjkim } 300218585Sjkim 301218585Sjkim /* Examine the arg based on the required type of the arg */ 302218585Sjkim 303218585Sjkim switch (ArgType) 304218585Sjkim { 305218585Sjkim case ARGI_TARGETREF: 306218585Sjkim 307218585Sjkim if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) 308218585Sjkim { 309218585Sjkim /* ZERO is the placeholder for "don't store result" */ 310218585Sjkim 311218585Sjkim ThisNodeBtype = RequiredBtypes; 312218585Sjkim break; 313218585Sjkim } 314218585Sjkim 315218585Sjkim if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) 316218585Sjkim { 317218585Sjkim /* 318218585Sjkim * This is the case where an original reference to a resource 319218585Sjkim * descriptor field has been replaced by an (Integer) offset. 320218585Sjkim * These named fields are supported at compile-time only; 321218585Sjkim * the names are not passed to the interpreter (via the AML). 322218585Sjkim */ 323218585Sjkim if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || 324218585Sjkim (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) 325218585Sjkim { 326218585Sjkim AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL); 327218585Sjkim } 328218585Sjkim else 329218585Sjkim { 330218585Sjkim AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL); 331218585Sjkim } 332218585Sjkim break; 333218585Sjkim } 334218585Sjkim 335218585Sjkim if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) || 336218585Sjkim (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF)) 337218585Sjkim { 338218585Sjkim break; 339218585Sjkim } 340218585Sjkim 341218585Sjkim ThisNodeBtype = RequiredBtypes; 342218585Sjkim break; 343218585Sjkim 344218585Sjkim 345218585Sjkim case ARGI_REFERENCE: /* References */ 346218585Sjkim case ARGI_INTEGER_REF: 347218585Sjkim case ARGI_OBJECT_REF: 348218585Sjkim case ARGI_DEVICE_REF: 349218585Sjkim 350218585Sjkim switch (ArgOp->Asl.ParseOpcode) 351218585Sjkim { 352218585Sjkim case PARSEOP_LOCAL0: 353218585Sjkim case PARSEOP_LOCAL1: 354218585Sjkim case PARSEOP_LOCAL2: 355218585Sjkim case PARSEOP_LOCAL3: 356218585Sjkim case PARSEOP_LOCAL4: 357218585Sjkim case PARSEOP_LOCAL5: 358218585Sjkim case PARSEOP_LOCAL6: 359218585Sjkim case PARSEOP_LOCAL7: 360218585Sjkim 361218585Sjkim /* TBD: implement analysis of current value (type) of the local */ 362218585Sjkim /* For now, just treat any local as a typematch */ 363218585Sjkim 364218585Sjkim /*ThisNodeBtype = RequiredBtypes;*/ 365218585Sjkim break; 366218585Sjkim 367218585Sjkim case PARSEOP_ARG0: 368218585Sjkim case PARSEOP_ARG1: 369218585Sjkim case PARSEOP_ARG2: 370218585Sjkim case PARSEOP_ARG3: 371218585Sjkim case PARSEOP_ARG4: 372218585Sjkim case PARSEOP_ARG5: 373218585Sjkim case PARSEOP_ARG6: 374218585Sjkim 375218585Sjkim /* Hard to analyze argument types, sow we won't */ 376218585Sjkim /* For now, just treat any arg as a typematch */ 377218585Sjkim 378218585Sjkim /* ThisNodeBtype = RequiredBtypes; */ 379218585Sjkim break; 380218585Sjkim 381218585Sjkim case PARSEOP_DEBUG: 382218585Sjkim break; 383218585Sjkim 384218585Sjkim case PARSEOP_REFOF: 385218585Sjkim case PARSEOP_INDEX: 386218585Sjkim default: 387218585Sjkim break; 388218585Sjkim 389218585Sjkim } 390218585Sjkim break; 391218585Sjkim 392218585Sjkim case ARGI_INTEGER: 393218585Sjkim default: 394218585Sjkim break; 395218585Sjkim } 396218585Sjkim 397218585Sjkim 398218585Sjkim CommonBtypes = ThisNodeBtype & RequiredBtypes; 399218585Sjkim 400218585Sjkim if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) 401218585Sjkim { 402218585Sjkim if (AnIsInternalMethod (ArgOp)) 403218585Sjkim { 404218585Sjkim return (AE_OK); 405218585Sjkim } 406218585Sjkim 407218585Sjkim /* Check a method call for a valid return value */ 408218585Sjkim 409218585Sjkim AnCheckMethodReturnValue (Op, OpInfo, ArgOp, 410218585Sjkim RequiredBtypes, ThisNodeBtype); 411218585Sjkim } 412218585Sjkim 413218585Sjkim /* 414218585Sjkim * Now check if the actual type(s) match at least one 415218585Sjkim * bit to the required type 416218585Sjkim */ 417218585Sjkim else if (!CommonBtypes) 418218585Sjkim { 419218585Sjkim /* No match -- this is a type mismatch error */ 420218585Sjkim 421218585Sjkim AnFormatBtype (StringBuffer, ThisNodeBtype); 422218585Sjkim AnFormatBtype (StringBuffer2, RequiredBtypes); 423218585Sjkim 424218585Sjkim sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]", 425218585Sjkim StringBuffer, OpInfo->Name, StringBuffer2); 426218585Sjkim 427218585Sjkim AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer); 428218585Sjkim } 429218585Sjkim 430218585Sjkim NextArgument: 431218585Sjkim ArgOp = ArgOp->Asl.Next; 432218585Sjkim INCREMENT_ARG_LIST (RuntimeArgTypes2); 433218585Sjkim } 434218585Sjkim break; 435218585Sjkim 436218585Sjkim default: 437218585Sjkim break; 438218585Sjkim } 439218585Sjkim 440218585Sjkim return (AE_OK); 441218585Sjkim} 442218585Sjkim 443218585Sjkim 444218585Sjkim/******************************************************************************* 445218585Sjkim * 446218585Sjkim * FUNCTION: AnOtherSemanticAnalysisWalkBegin 447218585Sjkim * 448218585Sjkim * PARAMETERS: ASL_WALK_CALLBACK 449218585Sjkim * 450218585Sjkim * RETURN: Status 451218585Sjkim * 452218585Sjkim * DESCRIPTION: Descending callback for the analysis walk. Checks for 453218585Sjkim * miscellaneous issues in the code. 454218585Sjkim * 455218585Sjkim ******************************************************************************/ 456218585Sjkim 457218585SjkimACPI_STATUS 458218585SjkimAnOtherSemanticAnalysisWalkBegin ( 459218585Sjkim ACPI_PARSE_OBJECT *Op, 460218585Sjkim UINT32 Level, 461218585Sjkim void *Context) 462218585Sjkim{ 463218585Sjkim ACPI_PARSE_OBJECT *ArgNode; 464218585Sjkim ACPI_PARSE_OBJECT *PrevArgNode = NULL; 465218585Sjkim const ACPI_OPCODE_INFO *OpInfo; 466228110Sjkim ACPI_NAMESPACE_NODE *Node; 467218585Sjkim 468218585Sjkim 469218585Sjkim OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 470218585Sjkim 471218585Sjkim /* 472218585Sjkim * Determine if an execution class operator actually does something by 473218585Sjkim * checking if it has a target and/or the function return value is used. 474218585Sjkim * (Target is optional, so a standalone statement can actually do nothing.) 475218585Sjkim */ 476218585Sjkim if ((OpInfo->Class == AML_CLASS_EXECUTE) && 477218585Sjkim (OpInfo->Flags & AML_HAS_RETVAL) && 478218585Sjkim (!AnIsResultUsed (Op))) 479218585Sjkim { 480218585Sjkim if (OpInfo->Flags & AML_HAS_TARGET) 481218585Sjkim { 482218585Sjkim /* 483218585Sjkim * Find the target node, it is always the last child. If the traget 484218585Sjkim * is not specified in the ASL, a default node of type Zero was 485218585Sjkim * created by the parser. 486218585Sjkim */ 487218585Sjkim ArgNode = Op->Asl.Child; 488218585Sjkim while (ArgNode->Asl.Next) 489218585Sjkim { 490218585Sjkim PrevArgNode = ArgNode; 491218585Sjkim ArgNode = ArgNode->Asl.Next; 492218585Sjkim } 493218585Sjkim 494218585Sjkim /* Divide() is the only weird case, it has two targets */ 495218585Sjkim 496218585Sjkim if (Op->Asl.AmlOpcode == AML_DIVIDE_OP) 497218585Sjkim { 498218585Sjkim if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) && 499218585Sjkim (PrevArgNode) && 500218585Sjkim (PrevArgNode->Asl.ParseOpcode == PARSEOP_ZERO)) 501218585Sjkim { 502249112Sjkim AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED, 503218585Sjkim Op, Op->Asl.ExternalName); 504218585Sjkim } 505218585Sjkim } 506218585Sjkim else if (ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) 507218585Sjkim { 508249112Sjkim AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED, 509218585Sjkim Op, Op->Asl.ExternalName); 510218585Sjkim } 511218585Sjkim } 512218585Sjkim else 513218585Sjkim { 514218585Sjkim /* 515218585Sjkim * Has no target and the result is not used. Only a couple opcodes 516218585Sjkim * can have this combination. 517218585Sjkim */ 518218585Sjkim switch (Op->Asl.ParseOpcode) 519218585Sjkim { 520218585Sjkim case PARSEOP_ACQUIRE: 521218585Sjkim case PARSEOP_WAIT: 522218585Sjkim case PARSEOP_LOADTABLE: 523218585Sjkim break; 524218585Sjkim 525218585Sjkim default: 526249112Sjkim AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED, 527218585Sjkim Op, Op->Asl.ExternalName); 528218585Sjkim break; 529218585Sjkim } 530218585Sjkim } 531218585Sjkim } 532218585Sjkim 533218585Sjkim 534218585Sjkim /* 535218585Sjkim * Semantic checks for individual ASL operators 536218585Sjkim */ 537218585Sjkim switch (Op->Asl.ParseOpcode) 538218585Sjkim { 539218585Sjkim case PARSEOP_ACQUIRE: 540218585Sjkim case PARSEOP_WAIT: 541218585Sjkim /* 542218585Sjkim * Emit a warning if the timeout parameter for these operators is not 543218585Sjkim * ACPI_WAIT_FOREVER, and the result value from the operator is not 544218585Sjkim * checked, meaning that a timeout could happen, but the code 545218585Sjkim * would not know about it. 546218585Sjkim */ 547218585Sjkim 548218585Sjkim /* First child is the namepath, 2nd child is timeout */ 549218585Sjkim 550218585Sjkim ArgNode = Op->Asl.Child; 551218585Sjkim ArgNode = ArgNode->Asl.Next; 552218585Sjkim 553218585Sjkim /* 554218585Sjkim * Check for the WAIT_FOREVER case - defined by the ACPI spec to be 555218585Sjkim * 0xFFFF or greater 556218585Sjkim */ 557218585Sjkim if (((ArgNode->Asl.ParseOpcode == PARSEOP_WORDCONST) || 558218585Sjkim (ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER)) && 559218585Sjkim (ArgNode->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER)) 560218585Sjkim { 561218585Sjkim break; 562218585Sjkim } 563218585Sjkim 564218585Sjkim /* 565218585Sjkim * The operation could timeout. If the return value is not used 566218585Sjkim * (indicates timeout occurred), issue a warning 567218585Sjkim */ 568218585Sjkim if (!AnIsResultUsed (Op)) 569218585Sjkim { 570218585Sjkim AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgNode, 571218585Sjkim Op->Asl.ExternalName); 572218585Sjkim } 573218585Sjkim break; 574218585Sjkim 575218585Sjkim case PARSEOP_CREATEFIELD: 576218585Sjkim /* 577218585Sjkim * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand 578218585Sjkim */ 579218585Sjkim ArgNode = Op->Asl.Child; 580218585Sjkim ArgNode = ArgNode->Asl.Next; 581218585Sjkim ArgNode = ArgNode->Asl.Next; 582218585Sjkim 583218585Sjkim if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) || 584218585Sjkim ((ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER) && 585218585Sjkim (ArgNode->Asl.Value.Integer == 0))) 586218585Sjkim { 587218585Sjkim AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgNode, NULL); 588218585Sjkim } 589218585Sjkim break; 590218585Sjkim 591228110Sjkim case PARSEOP_CONNECTION: 592228110Sjkim /* 593228110Sjkim * Ensure that the referenced operation region has the correct SPACE_ID. 594228110Sjkim * From the grammar/parser, we know the parent is a FIELD definition. 595228110Sjkim */ 596228110Sjkim ArgNode = Op->Asl.Parent; /* Field definition */ 597228110Sjkim ArgNode = ArgNode->Asl.Child; /* First child is the OpRegion Name */ 598228110Sjkim Node = ArgNode->Asl.Node; /* OpRegion namespace node */ 599228110Sjkim 600228110Sjkim ArgNode = Node->Op; /* OpRegion definition */ 601228110Sjkim ArgNode = ArgNode->Asl.Child; /* First child is the OpRegion Name */ 602228110Sjkim ArgNode = ArgNode->Asl.Next; /* Next peer is the SPACE_ID (what we want) */ 603228110Sjkim 604228110Sjkim /* 605228110Sjkim * The Connection() operator is only valid for the following operation 606228110Sjkim * region SpaceIds: GeneralPurposeIo and GenericSerialBus. 607228110Sjkim */ 608228110Sjkim if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) && 609228110Sjkim (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS)) 610228110Sjkim { 611228110Sjkim AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL); 612228110Sjkim } 613228110Sjkim break; 614228110Sjkim 615228110Sjkim case PARSEOP_FIELD: 616228110Sjkim /* 617228110Sjkim * Ensure that fields for GeneralPurposeIo and GenericSerialBus 618228110Sjkim * contain at least one Connection() operator 619228110Sjkim */ 620228110Sjkim ArgNode = Op->Asl.Child; /* 1st child is the OpRegion Name */ 621228110Sjkim Node = ArgNode->Asl.Node; /* OpRegion namespace node */ 622228110Sjkim if (!Node) 623228110Sjkim { 624228110Sjkim break; 625228110Sjkim } 626228110Sjkim 627228110Sjkim ArgNode = Node->Op; /* OpRegion definition */ 628228110Sjkim ArgNode = ArgNode->Asl.Child; /* First child is the OpRegion Name */ 629228110Sjkim ArgNode = ArgNode->Asl.Next; /* Next peer is the SPACE_ID (what we want) */ 630228110Sjkim 631228110Sjkim /* We are only interested in GeneralPurposeIo and GenericSerialBus */ 632228110Sjkim 633228110Sjkim if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) && 634228110Sjkim (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS)) 635228110Sjkim { 636228110Sjkim break; 637228110Sjkim } 638228110Sjkim 639228110Sjkim ArgNode = Op->Asl.Child; /* 1st child is the OpRegion Name */ 640228110Sjkim ArgNode = ArgNode->Asl.Next; /* AccessType */ 641228110Sjkim ArgNode = ArgNode->Asl.Next; /* LockRule */ 642228110Sjkim ArgNode = ArgNode->Asl.Next; /* UpdateRule */ 643228110Sjkim ArgNode = ArgNode->Asl.Next; /* Start of FieldUnitList */ 644228110Sjkim 645228110Sjkim /* Walk the FieldUnitList */ 646228110Sjkim 647228110Sjkim while (ArgNode) 648228110Sjkim { 649228110Sjkim if (ArgNode->Asl.ParseOpcode == PARSEOP_CONNECTION) 650228110Sjkim { 651228110Sjkim break; 652228110Sjkim } 653228110Sjkim else if (ArgNode->Asl.ParseOpcode == PARSEOP_NAMESEG) 654228110Sjkim { 655228110Sjkim AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgNode, NULL); 656228110Sjkim break; 657228110Sjkim } 658228110Sjkim 659228110Sjkim ArgNode = ArgNode->Asl.Next; 660228110Sjkim } 661228110Sjkim break; 662228110Sjkim 663218585Sjkim default: 664218585Sjkim break; 665218585Sjkim } 666218585Sjkim 667218585Sjkim return (AE_OK); 668218585Sjkim} 669