1118611Snjl/****************************************************************************** 2118611Snjl * 3218590Sjkim * Module Name: aslanalyze.c - Support functions for parse tree walks 4118611Snjl * 5118611Snjl *****************************************************************************/ 6118611Snjl 7217365Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp. 9118611Snjl * All rights reserved. 10118611Snjl * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 25118611Snjl * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 29118611Snjl * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 43118611Snjl 44151937Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 45118611Snjl#include "aslcompiler.y.h" 46218590Sjkim#include <string.h> 47118611Snjl 48218590Sjkim 49118611Snjl#define _COMPONENT ACPI_COMPILER 50118611Snjl ACPI_MODULE_NAME ("aslanalyze") 51118611Snjl 52118611Snjl 53306536Sjkim/* Local Prototypes */ 54306536Sjkim 55306536Sjkimstatic ACPI_STATUS 56306536SjkimApDeviceSubtreeWalk ( 57306536Sjkim ACPI_PARSE_OBJECT *Op, 58306536Sjkim UINT32 Level, 59306536Sjkim void *Context); 60306536Sjkim 61306536Sjkim 62118611Snjl/******************************************************************************* 63118611Snjl * 64167802Sjkim * FUNCTION: AnIsInternalMethod 65167802Sjkim * 66218590Sjkim * PARAMETERS: Op - Current op 67167802Sjkim * 68167802Sjkim * RETURN: Boolean 69167802Sjkim * 70167802Sjkim * DESCRIPTION: Check for an internal control method. 71167802Sjkim * 72167802Sjkim ******************************************************************************/ 73167802Sjkim 74218590SjkimBOOLEAN 75167802SjkimAnIsInternalMethod ( 76167802Sjkim ACPI_PARSE_OBJECT *Op) 77167802Sjkim{ 78167802Sjkim 79306536Sjkim if ((!strcmp (Op->Asl.ExternalName, "\\_OSI")) || 80306536Sjkim (!strcmp (Op->Asl.ExternalName, "_OSI"))) 81167802Sjkim { 82167802Sjkim return (TRUE); 83167802Sjkim } 84167802Sjkim 85167802Sjkim return (FALSE); 86167802Sjkim} 87167802Sjkim 88167802Sjkim 89167802Sjkim/******************************************************************************* 90167802Sjkim * 91167802Sjkim * FUNCTION: AnGetInternalMethodReturnType 92167802Sjkim * 93218590Sjkim * PARAMETERS: Op - Current op 94167802Sjkim * 95167802Sjkim * RETURN: Btype 96167802Sjkim * 97167802Sjkim * DESCRIPTION: Get the return type of an internal method 98167802Sjkim * 99167802Sjkim ******************************************************************************/ 100167802Sjkim 101218590SjkimUINT32 102167802SjkimAnGetInternalMethodReturnType ( 103167802Sjkim ACPI_PARSE_OBJECT *Op) 104167802Sjkim{ 105167802Sjkim 106306536Sjkim if ((!strcmp (Op->Asl.ExternalName, "\\_OSI")) || 107306536Sjkim (!strcmp (Op->Asl.ExternalName, "_OSI"))) 108167802Sjkim { 109167802Sjkim return (ACPI_BTYPE_STRING); 110167802Sjkim } 111167802Sjkim 112167802Sjkim return (0); 113167802Sjkim} 114167802Sjkim 115167802Sjkim 116167802Sjkim/******************************************************************************* 117167802Sjkim * 118213806Sjkim * FUNCTION: AnCheckId 119213806Sjkim * 120213806Sjkim * PARAMETERS: Op - Current parse op 121213806Sjkim * Type - HID or CID 122213806Sjkim * 123213806Sjkim * RETURN: None 124213806Sjkim * 125213806Sjkim * DESCRIPTION: Perform various checks on _HID and _CID strings. Only limited 126213806Sjkim * checks can be performed on _CID strings. 127213806Sjkim * 128213806Sjkim ******************************************************************************/ 129213806Sjkim 130218590Sjkimvoid 131213806SjkimAnCheckId ( 132213806Sjkim ACPI_PARSE_OBJECT *Op, 133213806Sjkim ACPI_NAME Type) 134213806Sjkim{ 135213806Sjkim UINT32 i; 136213806Sjkim ACPI_SIZE Length; 137213806Sjkim 138213806Sjkim 139216471Sjkim /* Only care about string versions of _HID/_CID (integers are legal) */ 140216471Sjkim 141213806Sjkim if (Op->Asl.ParseOpcode != PARSEOP_STRING_LITERAL) 142213806Sjkim { 143213806Sjkim return; 144213806Sjkim } 145213806Sjkim 146216471Sjkim /* For both _HID and _CID, the string must be non-null */ 147216471Sjkim 148213806Sjkim Length = strlen (Op->Asl.Value.String); 149216471Sjkim if (!Length) 150216471Sjkim { 151306536Sjkim AslError (ASL_ERROR, ASL_MSG_NULL_STRING, Op, NULL); 152216471Sjkim return; 153216471Sjkim } 154213806Sjkim 155213806Sjkim /* 156216471Sjkim * One of the things we want to catch here is the use of a leading 157216471Sjkim * asterisk in the string -- an odd construct that certain platform 158216471Sjkim * manufacturers are fond of. Technically, a leading asterisk is OK 159216471Sjkim * for _CID, but a valid use of this has not been seen. 160213806Sjkim */ 161216471Sjkim if (*Op->Asl.Value.String == '*') 162216471Sjkim { 163216471Sjkim AslError (ASL_ERROR, ASL_MSG_LEADING_ASTERISK, 164216471Sjkim Op, Op->Asl.Value.String); 165216471Sjkim return; 166216471Sjkim } 167216471Sjkim 168216471Sjkim /* _CID strings are bus-specific, no more checks can be performed */ 169216471Sjkim 170216471Sjkim if (Type == ASL_TYPE_CID) 171216471Sjkim { 172216471Sjkim return; 173216471Sjkim } 174216471Sjkim 175216471Sjkim /* For _HID, all characters must be alphanumeric */ 176216471Sjkim 177213806Sjkim for (i = 0; Op->Asl.Value.String[i]; i++) 178213806Sjkim { 179213806Sjkim if (!isalnum ((int) Op->Asl.Value.String[i])) 180213806Sjkim { 181213806Sjkim AslError (ASL_ERROR, ASL_MSG_ALPHANUMERIC_STRING, 182213806Sjkim Op, Op->Asl.Value.String); 183228110Sjkim return; 184213806Sjkim } 185213806Sjkim } 186213806Sjkim 187228110Sjkim /* 188228110Sjkim * _HID String must be one of these forms: 189228110Sjkim * 190228110Sjkim * "AAA####" A is an uppercase letter and # is a hex digit 191228110Sjkim * "ACPI####" # is a hex digit 192228110Sjkim * "NNNN####" N is an uppercase letter or decimal digit (0-9) 193228110Sjkim * # is a hex digit (ACPI 5.0) 194228110Sjkim */ 195213806Sjkim if ((Length < 7) || (Length > 8)) 196213806Sjkim { 197213806Sjkim AslError (ASL_ERROR, ASL_MSG_HID_LENGTH, 198213806Sjkim Op, Op->Asl.Value.String); 199213806Sjkim return; 200213806Sjkim } 201213806Sjkim 202306536Sjkim /* _HID Length is valid (7 or 8), now check prefix (first 3 or 4 chars) */ 203213806Sjkim 204228110Sjkim if (Length == 7) 205213806Sjkim { 206228110Sjkim /* AAA####: Ensure the alphabetic prefix is all uppercase */ 207228110Sjkim 208228110Sjkim for (i = 0; i < 3; i++) 209228110Sjkim { 210228110Sjkim if (!isupper ((int) Op->Asl.Value.String[i])) 211228110Sjkim { 212228110Sjkim AslError (ASL_ERROR, ASL_MSG_UPPER_CASE, 213228110Sjkim Op, &Op->Asl.Value.String[i]); 214228110Sjkim return; 215228110Sjkim } 216228110Sjkim } 217213806Sjkim } 218228110Sjkim else /* Length == 8 */ 219228110Sjkim { 220228110Sjkim /* 221228110Sjkim * ACPI#### or NNNN####: 222228110Sjkim * Ensure the prefix contains only uppercase alpha or decimal digits 223228110Sjkim */ 224228110Sjkim for (i = 0; i < 4; i++) 225228110Sjkim { 226228110Sjkim if (!isupper ((int) Op->Asl.Value.String[i]) && 227228110Sjkim !isdigit ((int) Op->Asl.Value.String[i])) 228228110Sjkim { 229228110Sjkim AslError (ASL_ERROR, ASL_MSG_HID_PREFIX, 230228110Sjkim Op, &Op->Asl.Value.String[i]); 231228110Sjkim return; 232228110Sjkim } 233228110Sjkim } 234228110Sjkim } 235213806Sjkim 236228110Sjkim /* Remaining characters (suffix) must be hex digits */ 237213806Sjkim 238228110Sjkim for (; i < Length; i++) 239213806Sjkim { 240228110Sjkim if (!isxdigit ((int) Op->Asl.Value.String[i])) 241213806Sjkim { 242306536Sjkim AslError (ASL_ERROR, ASL_MSG_HID_SUFFIX, 243306536Sjkim Op, &Op->Asl.Value.String[i]); 244213806Sjkim break; 245213806Sjkim } 246213806Sjkim } 247213806Sjkim} 248213806Sjkim 249213806Sjkim 250213806Sjkim/******************************************************************************* 251213806Sjkim * 252118611Snjl * FUNCTION: AnLastStatementIsReturn 253118611Snjl * 254218590Sjkim * PARAMETERS: Op - A method parse node 255118611Snjl * 256167802Sjkim * RETURN: TRUE if last statement is an ASL RETURN. False otherwise 257118611Snjl * 258118611Snjl * DESCRIPTION: Walk down the list of top level statements within a method 259167802Sjkim * to find the last one. Check if that last statement is in 260118611Snjl * fact a RETURN statement. 261118611Snjl * 262118611Snjl ******************************************************************************/ 263118611Snjl 264218590SjkimBOOLEAN 265118611SnjlAnLastStatementIsReturn ( 266118611Snjl ACPI_PARSE_OBJECT *Op) 267118611Snjl{ 268118611Snjl ACPI_PARSE_OBJECT *Next; 269118611Snjl 270118611Snjl 271218590Sjkim /* Check if last statement is a return */ 272218590Sjkim 273118611Snjl Next = ASL_GET_CHILD_NODE (Op); 274118611Snjl while (Next) 275118611Snjl { 276118611Snjl if ((!Next->Asl.Next) && 277118611Snjl (Next->Asl.ParseOpcode == PARSEOP_RETURN)) 278118611Snjl { 279218590Sjkim return (TRUE); 280118611Snjl } 281118611Snjl 282118611Snjl Next = ASL_GET_PEER_NODE (Next); 283118611Snjl } 284118611Snjl 285218590Sjkim return (FALSE); 286118611Snjl} 287118611Snjl 288118611Snjl 289118611Snjl/******************************************************************************* 290118611Snjl * 291118611Snjl * FUNCTION: AnCheckMethodReturnValue 292118611Snjl * 293118611Snjl * PARAMETERS: Op - Parent 294118611Snjl * OpInfo - Parent info 295118611Snjl * ArgOp - Method invocation op 296118611Snjl * RequiredBtypes - What caller requires 297118611Snjl * ThisNodeBtype - What this node returns (if anything) 298118611Snjl * 299118611Snjl * RETURN: None 300118611Snjl * 301118611Snjl * DESCRIPTION: Check a method invocation for 1) A return value and if it does 302118611Snjl * in fact return a value, 2) check the type of the return value. 303118611Snjl * 304118611Snjl ******************************************************************************/ 305118611Snjl 306218590Sjkimvoid 307118611SnjlAnCheckMethodReturnValue ( 308118611Snjl ACPI_PARSE_OBJECT *Op, 309118611Snjl const ACPI_OPCODE_INFO *OpInfo, 310118611Snjl ACPI_PARSE_OBJECT *ArgOp, 311118611Snjl UINT32 RequiredBtypes, 312118611Snjl UINT32 ThisNodeBtype) 313118611Snjl{ 314118611Snjl ACPI_PARSE_OBJECT *OwningOp; 315118611Snjl ACPI_NAMESPACE_NODE *Node; 316118611Snjl 317118611Snjl 318118611Snjl Node = ArgOp->Asl.Node; 319118611Snjl 320306536Sjkim if (!Node) 321306536Sjkim { 322306536Sjkim /* No error message, this can happen and is OK */ 323118611Snjl 324306536Sjkim return; 325306536Sjkim } 326306536Sjkim 327118611Snjl /* Examine the parent op of this method */ 328118611Snjl 329151937Sjkim OwningOp = Node->Op; 330118611Snjl if (OwningOp->Asl.CompileFlags & NODE_METHOD_NO_RETVAL) 331118611Snjl { 332151937Sjkim /* Method NEVER returns a value */ 333151937Sjkim 334118611Snjl AslError (ASL_ERROR, ASL_MSG_NO_RETVAL, Op, Op->Asl.ExternalName); 335118611Snjl } 336118611Snjl else if (OwningOp->Asl.CompileFlags & NODE_METHOD_SOME_NO_RETVAL) 337118611Snjl { 338151937Sjkim /* Method SOMETIMES returns a value, SOMETIMES not */ 339151937Sjkim 340306536Sjkim AslError (ASL_WARNING, ASL_MSG_SOME_NO_RETVAL, 341306536Sjkim Op, Op->Asl.ExternalName); 342118611Snjl } 343118611Snjl else if (!(ThisNodeBtype & RequiredBtypes)) 344118611Snjl { 345151937Sjkim /* Method returns a value, but the type is wrong */ 346151937Sjkim 347118611Snjl AnFormatBtype (StringBuffer, ThisNodeBtype); 348118611Snjl AnFormatBtype (StringBuffer2, RequiredBtypes); 349118611Snjl 350118611Snjl /* 351118611Snjl * The case where the method does not return any value at all 352118611Snjl * was already handled in the namespace cross reference 353118611Snjl * -- Only issue an error if the method in fact returns a value, 354118611Snjl * but it is of the wrong type 355118611Snjl */ 356118611Snjl if (ThisNodeBtype != 0) 357118611Snjl { 358151937Sjkim sprintf (MsgBuffer, 359151937Sjkim "Method returns [%s], %s operator requires [%s]", 360151937Sjkim StringBuffer, OpInfo->Name, StringBuffer2); 361118611Snjl 362118611Snjl AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer); 363118611Snjl } 364118611Snjl } 365118611Snjl} 366118611Snjl 367118611Snjl 368118611Snjl/******************************************************************************* 369118611Snjl * 370167802Sjkim * FUNCTION: AnIsResultUsed 371167802Sjkim * 372218590Sjkim * PARAMETERS: Op - Parent op for the operator 373167802Sjkim * 374167802Sjkim * RETURN: TRUE if result from this operation is actually consumed 375167802Sjkim * 376167802Sjkim * DESCRIPTION: Determine if the function result value from an operator is 377167802Sjkim * used. 378167802Sjkim * 379167802Sjkim ******************************************************************************/ 380167802Sjkim 381218590SjkimBOOLEAN 382167802SjkimAnIsResultUsed ( 383167802Sjkim ACPI_PARSE_OBJECT *Op) 384167802Sjkim{ 385167802Sjkim ACPI_PARSE_OBJECT *Parent; 386167802Sjkim 387167802Sjkim 388167802Sjkim switch (Op->Asl.ParseOpcode) 389167802Sjkim { 390167802Sjkim case PARSEOP_INCREMENT: 391167802Sjkim case PARSEOP_DECREMENT: 392167802Sjkim 393167802Sjkim /* These are standalone operators, no return value */ 394167802Sjkim 395167802Sjkim return (TRUE); 396167802Sjkim 397167802Sjkim default: 398250838Sjkim 399167802Sjkim break; 400167802Sjkim } 401167802Sjkim 402167802Sjkim /* Examine parent to determine if the return value is used */ 403167802Sjkim 404167802Sjkim Parent = Op->Asl.Parent; 405167802Sjkim switch (Parent->Asl.ParseOpcode) 406167802Sjkim { 407167802Sjkim /* If/While - check if the operator is the predicate */ 408167802Sjkim 409167802Sjkim case PARSEOP_IF: 410167802Sjkim case PARSEOP_WHILE: 411167802Sjkim 412167802Sjkim /* First child is the predicate */ 413167802Sjkim 414167802Sjkim if (Parent->Asl.Child == Op) 415167802Sjkim { 416167802Sjkim return (TRUE); 417167802Sjkim } 418306536Sjkim 419167802Sjkim return (FALSE); 420167802Sjkim 421167802Sjkim /* Not used if one of these is the parent */ 422167802Sjkim 423167802Sjkim case PARSEOP_METHOD: 424306536Sjkim case PARSEOP_DEFINITION_BLOCK: 425167802Sjkim case PARSEOP_ELSE: 426167802Sjkim 427167802Sjkim return (FALSE); 428167802Sjkim 429167802Sjkim default: 430250838Sjkim 431167802Sjkim /* Any other type of parent means that the result is used */ 432167802Sjkim 433167802Sjkim return (TRUE); 434167802Sjkim } 435167802Sjkim} 436167802Sjkim 437167802Sjkim 438167802Sjkim/******************************************************************************* 439167802Sjkim * 440218590Sjkim * FUNCTION: ApCheckForGpeNameConflict 441118611Snjl * 442218590Sjkim * PARAMETERS: Op - Current parse op 443118611Snjl * 444218590Sjkim * RETURN: None 445118611Snjl * 446218590Sjkim * DESCRIPTION: Check for a conflict between GPE names within this scope. 447218590Sjkim * Conflict means two GPE names with the same GPE number, but 448218590Sjkim * different types -- such as _L1C and _E1C. 449118611Snjl * 450118611Snjl ******************************************************************************/ 451118611Snjl 452218590Sjkimvoid 453218590SjkimApCheckForGpeNameConflict ( 454218590Sjkim ACPI_PARSE_OBJECT *Op) 455118611Snjl{ 456218590Sjkim ACPI_PARSE_OBJECT *NextOp; 457218590Sjkim UINT32 GpeNumber; 458218590Sjkim char Name[ACPI_NAME_SIZE + 1]; 459218590Sjkim char Target[ACPI_NAME_SIZE]; 460118611Snjl 461167802Sjkim 462218590Sjkim /* Need a null-terminated string version of NameSeg */ 463167802Sjkim 464218590Sjkim ACPI_MOVE_32_TO_32 (Name, &Op->Asl.NameSeg); 465218590Sjkim Name[ACPI_NAME_SIZE] = 0; 466218590Sjkim 467167802Sjkim /* 468218590Sjkim * For a GPE method: 469218590Sjkim * 1st char must be underscore 470218590Sjkim * 2nd char must be L or E 471218590Sjkim * 3rd/4th chars must be a hex number 472167802Sjkim */ 473218590Sjkim if ((Name[0] != '_') || 474218590Sjkim ((Name[1] != 'L') && (Name[1] != 'E'))) 475167802Sjkim { 476218590Sjkim return; 477218590Sjkim } 478167802Sjkim 479218590Sjkim /* Verify 3rd/4th chars are a valid hex value */ 480167802Sjkim 481306536Sjkim GpeNumber = strtoul (&Name[2], NULL, 16); 482218590Sjkim if (GpeNumber == ACPI_UINT32_MAX) 483218590Sjkim { 484218590Sjkim return; 485167802Sjkim } 486167802Sjkim 487167802Sjkim /* 488218590Sjkim * We are now sure we have an _Lxx or _Exx. 489218590Sjkim * Create the target name that would cause collision (Flip E/L) 490167802Sjkim */ 491218590Sjkim ACPI_MOVE_32_TO_32 (Target, Name); 492167802Sjkim 493218590Sjkim /* Inject opposite letter ("L" versus "E") */ 494167802Sjkim 495218590Sjkim if (Name[1] == 'L') 496218590Sjkim { 497218590Sjkim Target[1] = 'E'; 498218590Sjkim } 499218590Sjkim else /* Name[1] == 'E' */ 500218590Sjkim { 501218590Sjkim Target[1] = 'L'; 502218590Sjkim } 503167802Sjkim 504218590Sjkim /* Search all peers (objects within this scope) for target match */ 505167802Sjkim 506218590Sjkim NextOp = Op->Asl.Next; 507218590Sjkim while (NextOp) 508218590Sjkim { 509167802Sjkim /* 510218590Sjkim * We mostly care about methods, but check Name() constructs also, 511218590Sjkim * even though they will get another error for not being a method. 512218590Sjkim * All GPE names must be defined as control methods. 513167802Sjkim */ 514218590Sjkim if ((NextOp->Asl.ParseOpcode == PARSEOP_METHOD) || 515218590Sjkim (NextOp->Asl.ParseOpcode == PARSEOP_NAME)) 516167802Sjkim { 517218590Sjkim if (ACPI_COMPARE_NAME (Target, NextOp->Asl.NameSeg)) 518218590Sjkim { 519218590Sjkim /* Found both _Exy and _Lxy in the same scope, error */ 520167802Sjkim 521218590Sjkim AslError (ASL_ERROR, ASL_MSG_GPE_NAME_CONFLICT, NextOp, 522218590Sjkim Name); 523218590Sjkim return; 524218590Sjkim } 525167802Sjkim } 526167802Sjkim 527218590Sjkim NextOp = NextOp->Asl.Next; 528167802Sjkim } 529167802Sjkim 530218590Sjkim /* OK, no conflict found */ 531118611Snjl 532218590Sjkim return; 533118611Snjl} 534220663Sjkim 535220663Sjkim 536220663Sjkim/******************************************************************************* 537220663Sjkim * 538220663Sjkim * FUNCTION: ApCheckRegMethod 539220663Sjkim * 540220663Sjkim * PARAMETERS: Op - Current parse op 541220663Sjkim * 542220663Sjkim * RETURN: None 543220663Sjkim * 544220663Sjkim * DESCRIPTION: Ensure that a _REG method has a corresponding Operation 545220663Sjkim * Region declaration within the same scope. Note: _REG is defined 546220663Sjkim * to have two arguments and must therefore be defined as a 547220663Sjkim * control method. 548220663Sjkim * 549220663Sjkim ******************************************************************************/ 550220663Sjkim 551220663Sjkimvoid 552220663SjkimApCheckRegMethod ( 553220663Sjkim ACPI_PARSE_OBJECT *Op) 554220663Sjkim{ 555220663Sjkim ACPI_PARSE_OBJECT *Next; 556220663Sjkim ACPI_PARSE_OBJECT *Parent; 557220663Sjkim 558220663Sjkim 559220663Sjkim /* We are only interested in _REG methods */ 560220663Sjkim 561220663Sjkim if (!ACPI_COMPARE_NAME (METHOD_NAME__REG, &Op->Asl.NameSeg)) 562220663Sjkim { 563220663Sjkim return; 564220663Sjkim } 565220663Sjkim 566220663Sjkim /* Get the start of the current scope */ 567220663Sjkim 568220663Sjkim Parent = Op->Asl.Parent; 569220663Sjkim Next = Parent->Asl.Child; 570220663Sjkim 571220663Sjkim /* Search entire scope for an operation region declaration */ 572220663Sjkim 573220663Sjkim while (Next) 574220663Sjkim { 575220663Sjkim if (Next->Asl.ParseOpcode == PARSEOP_OPERATIONREGION) 576220663Sjkim { 577220663Sjkim return; /* Found region, OK */ 578220663Sjkim } 579220663Sjkim 580220663Sjkim Next = Next->Asl.Next; 581220663Sjkim } 582220663Sjkim 583220663Sjkim /* No region found, issue warning */ 584220663Sjkim 585220663Sjkim AslError (ASL_WARNING, ASL_MSG_NO_REGION, Op, NULL); 586220663Sjkim} 587281075Sdim 588281075Sdim 589281075Sdim/******************************************************************************* 590281075Sdim * 591306536Sjkim * FUNCTION: ApFindNameInDeviceTree 592306536Sjkim * 593306536Sjkim * PARAMETERS: Name - Name to search for 594306536Sjkim * Op - Current parse op 595306536Sjkim * 596306536Sjkim * RETURN: TRUE if name found in the same scope as Op. 597306536Sjkim * 598306536Sjkim * DESCRIPTION: Determine if a name appears in the same scope as Op, as either 599306536Sjkim * a Method() or a Name(). "Same scope" can mean under an If or 600306536Sjkim * Else statement. 601306536Sjkim * 602306536Sjkim * NOTE: Detects _HID/_ADR in this type of construct (legal in ACPI 6.1+) 603306536Sjkim * 604306536Sjkim * Scope (\_SB.PCI0) 605306536Sjkim * { 606306536Sjkim * Device (I2C0) 607306536Sjkim * { 608306536Sjkim * If (SMD0 != 4) { 609306536Sjkim * Name (_HID, "INT3442") 610306536Sjkim * } Else { 611306536Sjkim * Name (_ADR, 0x400) 612306536Sjkim * } 613306536Sjkim * } 614306536Sjkim * } 615306536Sjkim ******************************************************************************/ 616306536Sjkim 617306536SjkimBOOLEAN 618306536SjkimApFindNameInDeviceTree ( 619306536Sjkim char *Name, 620306536Sjkim ACPI_PARSE_OBJECT *Op) 621306536Sjkim{ 622306536Sjkim ACPI_STATUS Status; 623306536Sjkim 624306536Sjkim 625306536Sjkim Status = TrWalkParseTree (Op, ASL_WALK_VISIT_DOWNWARD, 626306536Sjkim ApDeviceSubtreeWalk, NULL, Name); 627306536Sjkim 628306536Sjkim if (Status == AE_CTRL_TRUE) 629306536Sjkim { 630306536Sjkim return (TRUE); /* Found a match */ 631306536Sjkim } 632306536Sjkim 633306536Sjkim return (FALSE); 634306536Sjkim} 635306536Sjkim 636306536Sjkim 637306536Sjkim/* Callback function for interface above */ 638306536Sjkim 639306536Sjkimstatic ACPI_STATUS 640306536SjkimApDeviceSubtreeWalk ( 641306536Sjkim ACPI_PARSE_OBJECT *Op, 642306536Sjkim UINT32 Level, 643306536Sjkim void *Context) 644306536Sjkim{ 645306536Sjkim char *Name = ACPI_CAST_PTR (char, Context); 646306536Sjkim 647306536Sjkim 648306536Sjkim switch (Op->Asl.ParseOpcode) 649306536Sjkim { 650306536Sjkim case PARSEOP_DEVICE: 651306536Sjkim 652306536Sjkim /* Level 0 is the starting device, ignore it */ 653306536Sjkim 654306536Sjkim if (Level > 0) 655306536Sjkim { 656306536Sjkim /* Ignore sub-devices */ 657306536Sjkim 658306536Sjkim return (AE_CTRL_DEPTH); 659306536Sjkim } 660306536Sjkim break; 661306536Sjkim 662306536Sjkim case PARSEOP_NAME: 663306536Sjkim case PARSEOP_METHOD: 664306536Sjkim 665306536Sjkim /* These are what we are looking for */ 666306536Sjkim 667306536Sjkim if (ACPI_COMPARE_NAME (Name, Op->Asl.NameSeg)) 668306536Sjkim { 669306536Sjkim return (AE_CTRL_TRUE); 670306536Sjkim } 671306536Sjkim return (AE_CTRL_DEPTH); 672306536Sjkim 673306536Sjkim case PARSEOP_SCOPE: 674306536Sjkim case PARSEOP_FIELD: 675306536Sjkim case PARSEOP_OPERATIONREGION: 676306536Sjkim 677306536Sjkim /* 678306536Sjkim * We want to ignore these, because either they can be large 679306536Sjkim * subtrees or open a scope to somewhere else. 680306536Sjkim */ 681306536Sjkim return (AE_CTRL_DEPTH); 682306536Sjkim 683306536Sjkim default: 684306536Sjkim break; 685306536Sjkim } 686306536Sjkim 687306536Sjkim return (AE_OK); 688306536Sjkim} 689306536Sjkim 690306536Sjkim 691306536Sjkim/******************************************************************************* 692306536Sjkim * 693281075Sdim * FUNCTION: ApFindNameInScope 694281075Sdim * 695281075Sdim * PARAMETERS: Name - Name to search for 696281075Sdim * Op - Current parse op 697281075Sdim * 698281075Sdim * RETURN: TRUE if name found in the same scope as Op. 699281075Sdim * 700281075Sdim * DESCRIPTION: Determine if a name appears in the same scope as Op, as either 701281075Sdim * a Method() or a Name(). 702281075Sdim * 703281075Sdim ******************************************************************************/ 704281075Sdim 705281075SdimBOOLEAN 706281075SdimApFindNameInScope ( 707281075Sdim char *Name, 708281075Sdim ACPI_PARSE_OBJECT *Op) 709281075Sdim{ 710281075Sdim ACPI_PARSE_OBJECT *Next; 711281075Sdim ACPI_PARSE_OBJECT *Parent; 712281075Sdim 713281075Sdim 714281075Sdim /* Get the start of the current scope */ 715281075Sdim 716281075Sdim Parent = Op->Asl.Parent; 717281075Sdim Next = Parent->Asl.Child; 718281075Sdim 719281075Sdim /* Search entire scope for a match to the name */ 720281075Sdim 721281075Sdim while (Next) 722281075Sdim { 723281075Sdim if ((Next->Asl.ParseOpcode == PARSEOP_METHOD) || 724281075Sdim (Next->Asl.ParseOpcode == PARSEOP_NAME)) 725281075Sdim { 726281075Sdim if (ACPI_COMPARE_NAME (Name, Next->Asl.NameSeg)) 727281075Sdim { 728281075Sdim return (TRUE); 729281075Sdim } 730281075Sdim } 731281075Sdim 732281075Sdim Next = Next->Asl.Next; 733281075Sdim } 734281075Sdim 735281075Sdim return (FALSE); 736281075Sdim} 737