1218585Sjkim/****************************************************************************** 2218585Sjkim * 3245582Sjkim * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks 4218585Sjkim * 5218585Sjkim *****************************************************************************/ 6218585Sjkim 7218585Sjkim/* 8281075Sdim * Copyright (C) 2000 - 2015, 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 44218590Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 45218585Sjkim#include "aslcompiler.y.h" 46218590Sjkim#include <contrib/dev/acpica/include/acparser.h> 47218590Sjkim#include <contrib/dev/acpica/include/amlcode.h> 48218585Sjkim 49218585Sjkim 50218585Sjkim#define _COMPONENT ACPI_COMPILER 51218585Sjkim ACPI_MODULE_NAME ("aslwalks") 52218585Sjkim 53218585Sjkim 54218585Sjkim/******************************************************************************* 55218585Sjkim * 56218585Sjkim * FUNCTION: AnMethodTypingWalkEnd 57218585Sjkim * 58218585Sjkim * PARAMETERS: ASL_WALK_CALLBACK 59218585Sjkim * 60218585Sjkim * RETURN: Status 61218585Sjkim * 62218585Sjkim * DESCRIPTION: Ascending callback for typing walk. Complete the method 63218585Sjkim * return analysis. Check methods for: 64218585Sjkim * 1) Initialized local variables 65218585Sjkim * 2) Valid arguments 66218585Sjkim * 3) Return types 67218585Sjkim * 68218585Sjkim ******************************************************************************/ 69218585Sjkim 70218585SjkimACPI_STATUS 71218585SjkimAnMethodTypingWalkEnd ( 72218585Sjkim ACPI_PARSE_OBJECT *Op, 73218585Sjkim UINT32 Level, 74218585Sjkim void *Context) 75218585Sjkim{ 76218585Sjkim UINT32 ThisNodeBtype; 77218585Sjkim 78218585Sjkim 79218585Sjkim switch (Op->Asl.ParseOpcode) 80218585Sjkim { 81218585Sjkim case PARSEOP_METHOD: 82218585Sjkim 83218585Sjkim Op->Asl.CompileFlags |= NODE_METHOD_TYPED; 84218585Sjkim break; 85218585Sjkim 86218585Sjkim case PARSEOP_RETURN: 87218585Sjkim 88218585Sjkim if ((Op->Asl.Child) && 89218585Sjkim (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 90218585Sjkim { 91218585Sjkim ThisNodeBtype = AnGetBtype (Op->Asl.Child); 92218585Sjkim 93218585Sjkim if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) && 94218585Sjkim (ThisNodeBtype == (ACPI_UINT32_MAX -1))) 95218585Sjkim { 96218585Sjkim /* 97218585Sjkim * The called method is untyped at this time (typically a 98218585Sjkim * forward reference). 99218585Sjkim * 100218585Sjkim * Check for a recursive method call first. 101218585Sjkim */ 102218585Sjkim if (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op) 103218585Sjkim { 104218585Sjkim /* We must type the method here */ 105218585Sjkim 106218585Sjkim TrWalkParseTree (Op->Asl.Child->Asl.Node->Op, 107218585Sjkim ASL_WALK_VISIT_UPWARD, NULL, 108218585Sjkim AnMethodTypingWalkEnd, NULL); 109218585Sjkim 110218585Sjkim ThisNodeBtype = AnGetBtype (Op->Asl.Child); 111218585Sjkim } 112218585Sjkim } 113218585Sjkim 114218585Sjkim /* Returns a value, save the value type */ 115218585Sjkim 116218585Sjkim if (Op->Asl.ParentMethod) 117218585Sjkim { 118218585Sjkim Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype; 119218585Sjkim } 120218585Sjkim } 121218585Sjkim break; 122218585Sjkim 123218585Sjkim default: 124250838Sjkim 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: 179250838Sjkim 180218585Sjkim break; 181218585Sjkim } 182218585Sjkim 183218585Sjkim OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 184218585Sjkim if (!OpInfo) 185218585Sjkim { 186218585Sjkim return (AE_OK); 187218585Sjkim } 188218585Sjkim 189218585Sjkim ArgOp = Op->Asl.Child; 190218585Sjkim RuntimeArgTypes = OpInfo->RuntimeArgs; 191218585Sjkim OpcodeClass = OpInfo->Class; 192218585Sjkim 193218585Sjkim#ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE 194218585Sjkim /* 195218585Sjkim * Update 11/2008: In practice, we can't perform this check. A simple 196218585Sjkim * analysis is not sufficient. Also, it can cause errors when compiling 197218585Sjkim * disassembled code because of the way Switch operators are implemented 198218585Sjkim * (a While(One) loop with a named temp variable created within.) 199218585Sjkim */ 200218585Sjkim 201218585Sjkim /* 202218585Sjkim * If we are creating a named object, check if we are within a while loop 203218585Sjkim * by checking if the parent is a WHILE op. This is a simple analysis, but 204218585Sjkim * probably sufficient for many cases. 205218585Sjkim * 206218585Sjkim * Allow Scope(), Buffer(), and Package(). 207218585Sjkim */ 208218585Sjkim if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) || 209218585Sjkim ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE))) 210218585Sjkim { 211218585Sjkim if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP) 212218585Sjkim { 213218585Sjkim AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL); 214218585Sjkim } 215218585Sjkim } 216218585Sjkim#endif 217218585Sjkim 218218585Sjkim /* 219218585Sjkim * Special case for control opcodes IF/RETURN/WHILE since they 220218585Sjkim * have no runtime arg list (at this time) 221218585Sjkim */ 222218585Sjkim switch (Op->Asl.AmlOpcode) 223218585Sjkim { 224218585Sjkim case AML_IF_OP: 225218585Sjkim case AML_WHILE_OP: 226218585Sjkim case AML_RETURN_OP: 227218585Sjkim 228218585Sjkim if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) 229218585Sjkim { 230218585Sjkim /* Check for an internal method */ 231218585Sjkim 232218585Sjkim if (AnIsInternalMethod (ArgOp)) 233218585Sjkim { 234218585Sjkim return (AE_OK); 235218585Sjkim } 236218585Sjkim 237218585Sjkim /* The lone arg is a method call, check it */ 238218585Sjkim 239218585Sjkim RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER); 240218585Sjkim if (Op->Asl.AmlOpcode == AML_RETURN_OP) 241218585Sjkim { 242218585Sjkim RequiredBtypes = 0xFFFFFFFF; 243218585Sjkim } 244218585Sjkim 245218585Sjkim ThisNodeBtype = AnGetBtype (ArgOp); 246218585Sjkim if (ThisNodeBtype == ACPI_UINT32_MAX) 247218585Sjkim { 248218585Sjkim return (AE_OK); 249218585Sjkim } 250218585Sjkim AnCheckMethodReturnValue (Op, OpInfo, ArgOp, 251218585Sjkim RequiredBtypes, ThisNodeBtype); 252218585Sjkim } 253218585Sjkim return (AE_OK); 254218585Sjkim 255281687Sjkim case AML_EXTERNAL_OP: 256281687Sjkim /* 257281687Sjkim * Not really a "runtime" opcode since it used by disassembler only. 258281687Sjkim * The parser will find any issues with the operands. 259281687Sjkim */ 260281687Sjkim return (AE_OK); 261281687Sjkim 262218585Sjkim default: 263250838Sjkim 264218585Sjkim break; 265218585Sjkim } 266218585Sjkim 267218585Sjkim /* Ignore the non-executable opcodes */ 268218585Sjkim 269218585Sjkim if (RuntimeArgTypes == ARGI_INVALID_OPCODE) 270218585Sjkim { 271218585Sjkim return (AE_OK); 272218585Sjkim } 273218585Sjkim 274218585Sjkim switch (OpcodeClass) 275218585Sjkim { 276218585Sjkim case AML_CLASS_EXECUTE: 277218585Sjkim case AML_CLASS_CREATE: 278218585Sjkim case AML_CLASS_CONTROL: 279218585Sjkim case AML_CLASS_RETURN_VALUE: 280218585Sjkim 281218585Sjkim /* TBD: Change class or fix typechecking for these */ 282218585Sjkim 283218585Sjkim if ((Op->Asl.AmlOpcode == AML_BUFFER_OP) || 284218585Sjkim (Op->Asl.AmlOpcode == AML_PACKAGE_OP) || 285218585Sjkim (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP)) 286218585Sjkim { 287218585Sjkim break; 288218585Sjkim } 289218585Sjkim 290218585Sjkim /* Reverse the runtime argument list */ 291218585Sjkim 292218585Sjkim RuntimeArgTypes2 = 0; 293218585Sjkim while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes))) 294218585Sjkim { 295218585Sjkim RuntimeArgTypes2 <<= ARG_TYPE_WIDTH; 296218585Sjkim RuntimeArgTypes2 |= ArgType; 297218585Sjkim INCREMENT_ARG_LIST (RuntimeArgTypes); 298218585Sjkim } 299218585Sjkim 300218585Sjkim while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2))) 301218585Sjkim { 302218585Sjkim RequiredBtypes = AnMapArgTypeToBtype (ArgType); 303218585Sjkim 304281075Sdim if (!ArgOp) 305281075Sdim { 306281075Sdim AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, 307281075Sdim "Null ArgOp in argument loop"); 308281075Sdim AslAbort (); 309281075Sdim } 310281075Sdim 311218585Sjkim ThisNodeBtype = AnGetBtype (ArgOp); 312218585Sjkim if (ThisNodeBtype == ACPI_UINT32_MAX) 313218585Sjkim { 314218585Sjkim goto NextArgument; 315218585Sjkim } 316218585Sjkim 317218585Sjkim /* Examine the arg based on the required type of the arg */ 318218585Sjkim 319218585Sjkim switch (ArgType) 320218585Sjkim { 321218585Sjkim case ARGI_TARGETREF: 322218585Sjkim 323218585Sjkim if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) 324218585Sjkim { 325218585Sjkim /* ZERO is the placeholder for "don't store result" */ 326218585Sjkim 327218585Sjkim ThisNodeBtype = RequiredBtypes; 328218585Sjkim break; 329218585Sjkim } 330218585Sjkim 331218585Sjkim if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) 332218585Sjkim { 333218585Sjkim /* 334218585Sjkim * This is the case where an original reference to a resource 335218585Sjkim * descriptor field has been replaced by an (Integer) offset. 336218585Sjkim * These named fields are supported at compile-time only; 337218585Sjkim * the names are not passed to the interpreter (via the AML). 338218585Sjkim */ 339218585Sjkim if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || 340218585Sjkim (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) 341218585Sjkim { 342218585Sjkim AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL); 343218585Sjkim } 344218585Sjkim else 345218585Sjkim { 346218585Sjkim AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL); 347218585Sjkim } 348218585Sjkim break; 349218585Sjkim } 350218585Sjkim 351218585Sjkim if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) || 352218585Sjkim (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF)) 353218585Sjkim { 354218585Sjkim break; 355218585Sjkim } 356218585Sjkim 357218585Sjkim ThisNodeBtype = RequiredBtypes; 358218585Sjkim break; 359218585Sjkim 360218585Sjkim 361218585Sjkim case ARGI_REFERENCE: /* References */ 362218585Sjkim case ARGI_INTEGER_REF: 363218585Sjkim case ARGI_OBJECT_REF: 364218585Sjkim case ARGI_DEVICE_REF: 365218585Sjkim 366218585Sjkim switch (ArgOp->Asl.ParseOpcode) 367218585Sjkim { 368218585Sjkim case PARSEOP_LOCAL0: 369218585Sjkim case PARSEOP_LOCAL1: 370218585Sjkim case PARSEOP_LOCAL2: 371218585Sjkim case PARSEOP_LOCAL3: 372218585Sjkim case PARSEOP_LOCAL4: 373218585Sjkim case PARSEOP_LOCAL5: 374218585Sjkim case PARSEOP_LOCAL6: 375218585Sjkim case PARSEOP_LOCAL7: 376218585Sjkim 377218585Sjkim /* TBD: implement analysis of current value (type) of the local */ 378218585Sjkim /* For now, just treat any local as a typematch */ 379218585Sjkim 380218585Sjkim /*ThisNodeBtype = RequiredBtypes;*/ 381218585Sjkim break; 382218585Sjkim 383218585Sjkim case PARSEOP_ARG0: 384218585Sjkim case PARSEOP_ARG1: 385218585Sjkim case PARSEOP_ARG2: 386218585Sjkim case PARSEOP_ARG3: 387218585Sjkim case PARSEOP_ARG4: 388218585Sjkim case PARSEOP_ARG5: 389218585Sjkim case PARSEOP_ARG6: 390218585Sjkim 391218585Sjkim /* Hard to analyze argument types, sow we won't */ 392218585Sjkim /* For now, just treat any arg as a typematch */ 393218585Sjkim 394218585Sjkim /* ThisNodeBtype = RequiredBtypes; */ 395218585Sjkim break; 396218585Sjkim 397218585Sjkim case PARSEOP_DEBUG: 398218585Sjkim case PARSEOP_REFOF: 399218585Sjkim case PARSEOP_INDEX: 400218585Sjkim default: 401250838Sjkim 402218585Sjkim break; 403218585Sjkim 404218585Sjkim } 405218585Sjkim break; 406218585Sjkim 407218585Sjkim case ARGI_INTEGER: 408218585Sjkim default: 409250838Sjkim 410218585Sjkim break; 411218585Sjkim } 412218585Sjkim 413218585Sjkim 414218585Sjkim CommonBtypes = ThisNodeBtype & RequiredBtypes; 415218585Sjkim 416218585Sjkim if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) 417218585Sjkim { 418218585Sjkim if (AnIsInternalMethod (ArgOp)) 419218585Sjkim { 420218585Sjkim return (AE_OK); 421218585Sjkim } 422218585Sjkim 423218585Sjkim /* Check a method call for a valid return value */ 424218585Sjkim 425218585Sjkim AnCheckMethodReturnValue (Op, OpInfo, ArgOp, 426218585Sjkim RequiredBtypes, ThisNodeBtype); 427218585Sjkim } 428218585Sjkim 429218585Sjkim /* 430218585Sjkim * Now check if the actual type(s) match at least one 431218585Sjkim * bit to the required type 432218585Sjkim */ 433218585Sjkim else if (!CommonBtypes) 434218585Sjkim { 435218585Sjkim /* No match -- this is a type mismatch error */ 436218585Sjkim 437218585Sjkim AnFormatBtype (StringBuffer, ThisNodeBtype); 438218585Sjkim AnFormatBtype (StringBuffer2, RequiredBtypes); 439218585Sjkim 440218585Sjkim sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]", 441218585Sjkim StringBuffer, OpInfo->Name, StringBuffer2); 442218585Sjkim 443218585Sjkim AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer); 444218585Sjkim } 445218585Sjkim 446218585Sjkim NextArgument: 447218585Sjkim ArgOp = ArgOp->Asl.Next; 448218585Sjkim INCREMENT_ARG_LIST (RuntimeArgTypes2); 449218585Sjkim } 450218585Sjkim break; 451218585Sjkim 452218585Sjkim default: 453250838Sjkim 454218585Sjkim break; 455218585Sjkim } 456218585Sjkim 457218585Sjkim return (AE_OK); 458218585Sjkim} 459218585Sjkim 460218585Sjkim 461218585Sjkim/******************************************************************************* 462218585Sjkim * 463218585Sjkim * FUNCTION: AnOtherSemanticAnalysisWalkBegin 464218585Sjkim * 465218585Sjkim * PARAMETERS: ASL_WALK_CALLBACK 466218585Sjkim * 467218585Sjkim * RETURN: Status 468218585Sjkim * 469218585Sjkim * DESCRIPTION: Descending callback for the analysis walk. Checks for 470218585Sjkim * miscellaneous issues in the code. 471218585Sjkim * 472218585Sjkim ******************************************************************************/ 473218585Sjkim 474218585SjkimACPI_STATUS 475218585SjkimAnOtherSemanticAnalysisWalkBegin ( 476218585Sjkim ACPI_PARSE_OBJECT *Op, 477218585Sjkim UINT32 Level, 478218585Sjkim void *Context) 479218585Sjkim{ 480218585Sjkim ACPI_PARSE_OBJECT *ArgNode; 481218585Sjkim ACPI_PARSE_OBJECT *PrevArgNode = NULL; 482218585Sjkim const ACPI_OPCODE_INFO *OpInfo; 483228110Sjkim ACPI_NAMESPACE_NODE *Node; 484218585Sjkim 485218585Sjkim 486218585Sjkim OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 487218585Sjkim 488218585Sjkim /* 489218585Sjkim * Determine if an execution class operator actually does something by 490218585Sjkim * checking if it has a target and/or the function return value is used. 491218585Sjkim * (Target is optional, so a standalone statement can actually do nothing.) 492218585Sjkim */ 493218585Sjkim if ((OpInfo->Class == AML_CLASS_EXECUTE) && 494218585Sjkim (OpInfo->Flags & AML_HAS_RETVAL) && 495218585Sjkim (!AnIsResultUsed (Op))) 496218585Sjkim { 497218585Sjkim if (OpInfo->Flags & AML_HAS_TARGET) 498218585Sjkim { 499218585Sjkim /* 500218585Sjkim * Find the target node, it is always the last child. If the traget 501218585Sjkim * is not specified in the ASL, a default node of type Zero was 502218585Sjkim * created by the parser. 503218585Sjkim */ 504218585Sjkim ArgNode = Op->Asl.Child; 505218585Sjkim while (ArgNode->Asl.Next) 506218585Sjkim { 507218585Sjkim PrevArgNode = ArgNode; 508218585Sjkim ArgNode = ArgNode->Asl.Next; 509218585Sjkim } 510218585Sjkim 511218585Sjkim /* Divide() is the only weird case, it has two targets */ 512218585Sjkim 513218585Sjkim if (Op->Asl.AmlOpcode == AML_DIVIDE_OP) 514218585Sjkim { 515218585Sjkim if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) && 516218585Sjkim (PrevArgNode) && 517218585Sjkim (PrevArgNode->Asl.ParseOpcode == PARSEOP_ZERO)) 518218585Sjkim { 519249112Sjkim AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED, 520218585Sjkim Op, Op->Asl.ExternalName); 521218585Sjkim } 522218585Sjkim } 523218585Sjkim else if (ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) 524218585Sjkim { 525249112Sjkim AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED, 526218585Sjkim Op, Op->Asl.ExternalName); 527218585Sjkim } 528218585Sjkim } 529218585Sjkim else 530218585Sjkim { 531218585Sjkim /* 532218585Sjkim * Has no target and the result is not used. Only a couple opcodes 533218585Sjkim * can have this combination. 534218585Sjkim */ 535218585Sjkim switch (Op->Asl.ParseOpcode) 536218585Sjkim { 537218585Sjkim case PARSEOP_ACQUIRE: 538218585Sjkim case PARSEOP_WAIT: 539218585Sjkim case PARSEOP_LOADTABLE: 540250838Sjkim 541218585Sjkim break; 542218585Sjkim 543218585Sjkim default: 544250838Sjkim 545249112Sjkim AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED, 546218585Sjkim Op, Op->Asl.ExternalName); 547218585Sjkim break; 548218585Sjkim } 549218585Sjkim } 550218585Sjkim } 551218585Sjkim 552218585Sjkim 553218585Sjkim /* 554218585Sjkim * Semantic checks for individual ASL operators 555218585Sjkim */ 556218585Sjkim switch (Op->Asl.ParseOpcode) 557218585Sjkim { 558218585Sjkim case PARSEOP_ACQUIRE: 559218585Sjkim case PARSEOP_WAIT: 560218585Sjkim /* 561218585Sjkim * Emit a warning if the timeout parameter for these operators is not 562218585Sjkim * ACPI_WAIT_FOREVER, and the result value from the operator is not 563218585Sjkim * checked, meaning that a timeout could happen, but the code 564218585Sjkim * would not know about it. 565218585Sjkim */ 566218585Sjkim 567218585Sjkim /* First child is the namepath, 2nd child is timeout */ 568218585Sjkim 569218585Sjkim ArgNode = Op->Asl.Child; 570218585Sjkim ArgNode = ArgNode->Asl.Next; 571218585Sjkim 572218585Sjkim /* 573218585Sjkim * Check for the WAIT_FOREVER case - defined by the ACPI spec to be 574218585Sjkim * 0xFFFF or greater 575218585Sjkim */ 576218585Sjkim if (((ArgNode->Asl.ParseOpcode == PARSEOP_WORDCONST) || 577218585Sjkim (ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER)) && 578218585Sjkim (ArgNode->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER)) 579218585Sjkim { 580218585Sjkim break; 581218585Sjkim } 582218585Sjkim 583218585Sjkim /* 584218585Sjkim * The operation could timeout. If the return value is not used 585218585Sjkim * (indicates timeout occurred), issue a warning 586218585Sjkim */ 587218585Sjkim if (!AnIsResultUsed (Op)) 588218585Sjkim { 589218585Sjkim AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgNode, 590218585Sjkim Op->Asl.ExternalName); 591218585Sjkim } 592218585Sjkim break; 593218585Sjkim 594218585Sjkim case PARSEOP_CREATEFIELD: 595218585Sjkim /* 596218585Sjkim * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand 597218585Sjkim */ 598218585Sjkim ArgNode = Op->Asl.Child; 599218585Sjkim ArgNode = ArgNode->Asl.Next; 600218585Sjkim ArgNode = ArgNode->Asl.Next; 601218585Sjkim 602218585Sjkim if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) || 603218585Sjkim ((ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER) && 604218585Sjkim (ArgNode->Asl.Value.Integer == 0))) 605218585Sjkim { 606218585Sjkim AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgNode, NULL); 607218585Sjkim } 608218585Sjkim break; 609218585Sjkim 610228110Sjkim case PARSEOP_CONNECTION: 611228110Sjkim /* 612228110Sjkim * Ensure that the referenced operation region has the correct SPACE_ID. 613228110Sjkim * From the grammar/parser, we know the parent is a FIELD definition. 614228110Sjkim */ 615228110Sjkim ArgNode = Op->Asl.Parent; /* Field definition */ 616228110Sjkim ArgNode = ArgNode->Asl.Child; /* First child is the OpRegion Name */ 617228110Sjkim Node = ArgNode->Asl.Node; /* OpRegion namespace node */ 618281075Sdim if (!Node) 619281075Sdim { 620281075Sdim break; 621281075Sdim } 622228110Sjkim 623228110Sjkim ArgNode = Node->Op; /* OpRegion definition */ 624228110Sjkim ArgNode = ArgNode->Asl.Child; /* First child is the OpRegion Name */ 625228110Sjkim ArgNode = ArgNode->Asl.Next; /* Next peer is the SPACE_ID (what we want) */ 626228110Sjkim 627228110Sjkim /* 628228110Sjkim * The Connection() operator is only valid for the following operation 629228110Sjkim * region SpaceIds: GeneralPurposeIo and GenericSerialBus. 630228110Sjkim */ 631228110Sjkim if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) && 632228110Sjkim (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS)) 633228110Sjkim { 634228110Sjkim AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL); 635228110Sjkim } 636228110Sjkim break; 637228110Sjkim 638228110Sjkim case PARSEOP_FIELD: 639228110Sjkim /* 640228110Sjkim * Ensure that fields for GeneralPurposeIo and GenericSerialBus 641228110Sjkim * contain at least one Connection() operator 642228110Sjkim */ 643228110Sjkim ArgNode = Op->Asl.Child; /* 1st child is the OpRegion Name */ 644228110Sjkim Node = ArgNode->Asl.Node; /* OpRegion namespace node */ 645228110Sjkim if (!Node) 646228110Sjkim { 647228110Sjkim break; 648228110Sjkim } 649228110Sjkim 650228110Sjkim ArgNode = Node->Op; /* OpRegion definition */ 651228110Sjkim ArgNode = ArgNode->Asl.Child; /* First child is the OpRegion Name */ 652228110Sjkim ArgNode = ArgNode->Asl.Next; /* Next peer is the SPACE_ID (what we want) */ 653228110Sjkim 654228110Sjkim /* We are only interested in GeneralPurposeIo and GenericSerialBus */ 655228110Sjkim 656228110Sjkim if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) && 657228110Sjkim (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS)) 658228110Sjkim { 659228110Sjkim break; 660228110Sjkim } 661228110Sjkim 662228110Sjkim ArgNode = Op->Asl.Child; /* 1st child is the OpRegion Name */ 663228110Sjkim ArgNode = ArgNode->Asl.Next; /* AccessType */ 664228110Sjkim ArgNode = ArgNode->Asl.Next; /* LockRule */ 665228110Sjkim ArgNode = ArgNode->Asl.Next; /* UpdateRule */ 666228110Sjkim ArgNode = ArgNode->Asl.Next; /* Start of FieldUnitList */ 667228110Sjkim 668228110Sjkim /* Walk the FieldUnitList */ 669228110Sjkim 670228110Sjkim while (ArgNode) 671228110Sjkim { 672228110Sjkim if (ArgNode->Asl.ParseOpcode == PARSEOP_CONNECTION) 673228110Sjkim { 674228110Sjkim break; 675228110Sjkim } 676228110Sjkim else if (ArgNode->Asl.ParseOpcode == PARSEOP_NAMESEG) 677228110Sjkim { 678228110Sjkim AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgNode, NULL); 679228110Sjkim break; 680228110Sjkim } 681228110Sjkim 682228110Sjkim ArgNode = ArgNode->Asl.Next; 683228110Sjkim } 684228110Sjkim break; 685228110Sjkim 686218585Sjkim default: 687250838Sjkim 688218585Sjkim break; 689218585Sjkim } 690218585Sjkim 691218585Sjkim return (AE_OK); 692218585Sjkim} 693