adwalk.c revision 235945
1275970Scy/****************************************************************************** 2275970Scy * 3275970Scy * Module Name: adwalk - Application-level disassembler parse tree walk routines 4275970Scy * 5275970Scy *****************************************************************************/ 6275970Scy 7275970Scy/* 8275970Scy * Copyright (C) 2000 - 2012, Intel Corp. 9275970Scy * All rights reserved. 10275970Scy * 11275970Scy * Redistribution and use in source and binary forms, with or without 12275970Scy * modification, are permitted provided that the following conditions 13275970Scy * are met: 14275970Scy * 1. Redistributions of source code must retain the above copyright 15275970Scy * notice, this list of conditions, and the following disclaimer, 16275970Scy * without modification. 17275970Scy * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18275970Scy * substantially similar to the "NO WARRANTY" disclaimer below 19275970Scy * ("Disclaimer") and any redistribution must be conditioned upon 20275970Scy * including a substantially similar Disclaimer requirement for further 21275970Scy * binary redistribution. 22275970Scy * 3. Neither the names of the above-listed copyright holders nor the names 23275970Scy * of any contributors may be used to endorse or promote products derived 24275970Scy * from this software without specific prior written permission. 25275970Scy * 26275970Scy * Alternatively, this software may be distributed under the terms of the 27275970Scy * GNU General Public License ("GPL") version 2 as published by the Free 28275970Scy * Software Foundation. 29275970Scy * 30275970Scy * NO WARRANTY 31275970Scy * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32275970Scy * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33275970Scy * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34275970Scy * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35275970Scy * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36275970Scy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37275970Scy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38275970Scy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39275970Scy * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40275970Scy * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41275970Scy * POSSIBILITY OF SUCH DAMAGES. 42275970Scy */ 43275970Scy 44275970Scy 45275970Scy#include <contrib/dev/acpica/include/acpi.h> 46275970Scy#include <contrib/dev/acpica/include/accommon.h> 47275970Scy#include <contrib/dev/acpica/include/acparser.h> 48275970Scy#include <contrib/dev/acpica/include/amlcode.h> 49275970Scy#include <contrib/dev/acpica/include/acdisasm.h> 50275970Scy#include <contrib/dev/acpica/include/acdispat.h> 51275970Scy#include <contrib/dev/acpica/include/acnamesp.h> 52275970Scy#include <contrib/dev/acpica/include/acapps.h> 53275970Scy 54275970Scy 55275970Scy#define _COMPONENT ACPI_TOOLS 56275970Scy ACPI_MODULE_NAME ("adwalk") 57275970Scy 58275970Scy/* 59275970Scy * aslmap - opcode mappings and reserved method names 60275970Scy */ 61275970ScyACPI_OBJECT_TYPE 62275970ScyAslMapNamedOpcodeToDataType ( 63275970Scy UINT16 Opcode); 64275970Scy 65275970Scy/* Local prototypes */ 66275970Scy 67275970Scystatic ACPI_STATUS 68275970ScyAcpiDmFindOrphanDescending ( 69275970Scy ACPI_PARSE_OBJECT *Op, 70275970Scy UINT32 Level, 71275970Scy void *Context); 72275970Scy 73275970Scystatic ACPI_STATUS 74275970ScyAcpiDmDumpDescending ( 75275970Scy ACPI_PARSE_OBJECT *Op, 76275970Scy UINT32 Level, 77275970Scy void *Context); 78275970Scy 79275970Scystatic ACPI_STATUS 80275970ScyAcpiDmXrefDescendingOp ( 81275970Scy ACPI_PARSE_OBJECT *Op, 82275970Scy UINT32 Level, 83275970Scy void *Context); 84275970Scy 85275970Scystatic ACPI_STATUS 86275970ScyAcpiDmCommonAscendingOp ( 87275970Scy ACPI_PARSE_OBJECT *Op, 88275970Scy UINT32 Level, 89275970Scy void *Context); 90275970Scy 91275970Scystatic ACPI_STATUS 92275970ScyAcpiDmLoadDescendingOp ( 93275970Scy ACPI_PARSE_OBJECT *Op, 94275970Scy UINT32 Level, 95275970Scy void *Context); 96275970Scy 97275970Scystatic UINT32 98275970ScyAcpiDmInspectPossibleArgs ( 99275970Scy UINT32 CurrentOpArgCount, 100275970Scy UINT32 TargetCount, 101275970Scy ACPI_PARSE_OBJECT *Op); 102275970Scy 103275970Scystatic ACPI_STATUS 104275970ScyAcpiDmResourceDescendingOp ( 105275970Scy ACPI_PARSE_OBJECT *Op, 106275970Scy UINT32 Level, 107275970Scy void *Context); 108275970Scy 109275970Scy 110275970Scy/******************************************************************************* 111275970Scy * 112275970Scy * FUNCTION: AcpiDmDumpTree 113275970Scy * 114275970Scy * PARAMETERS: Origin - Starting object 115275970Scy * 116275970Scy * RETURN: None 117275970Scy * 118275970Scy * DESCRIPTION: Parse tree walk to format and output the nodes 119275970Scy * 120275970Scy ******************************************************************************/ 121275970Scy 122275970Scyvoid 123275970ScyAcpiDmDumpTree ( 124275970Scy ACPI_PARSE_OBJECT *Origin) 125275970Scy{ 126275970Scy ACPI_OP_WALK_INFO Info; 127275970Scy 128275970Scy 129275970Scy if (!Origin) 130275970Scy { 131275970Scy return; 132275970Scy } 133275970Scy 134275970Scy AcpiOsPrintf ("/*\nAML Parse Tree\n\n"); 135275970Scy Info.Flags = 0; 136275970Scy Info.Count = 0; 137275970Scy Info.Level = 0; 138275970Scy Info.WalkState = NULL; 139275970Scy AcpiDmWalkParseTree (Origin, AcpiDmDumpDescending, NULL, &Info); 140275970Scy AcpiOsPrintf ("*/\n\n"); 141275970Scy} 142275970Scy 143275970Scy 144275970Scy/******************************************************************************* 145275970Scy * 146275970Scy * FUNCTION: AcpiDmFindOrphanMethods 147275970Scy * 148275970Scy * PARAMETERS: Origin - Starting object 149275970Scy * 150275970Scy * RETURN: None 151275970Scy * 152275970Scy * DESCRIPTION: Parse tree walk to find "orphaned" method invocations -- methods 153275970Scy * that are not resolved in the namespace 154275970Scy * 155275970Scy ******************************************************************************/ 156275970Scy 157275970Scyvoid 158275970ScyAcpiDmFindOrphanMethods ( 159275970Scy ACPI_PARSE_OBJECT *Origin) 160275970Scy{ 161275970Scy ACPI_OP_WALK_INFO Info; 162275970Scy 163275970Scy 164275970Scy if (!Origin) 165275970Scy { 166275970Scy return; 167275970Scy } 168275970Scy 169275970Scy Info.Flags = 0; 170275970Scy Info.Level = 0; 171275970Scy Info.WalkState = NULL; 172275970Scy AcpiDmWalkParseTree (Origin, AcpiDmFindOrphanDescending, NULL, &Info); 173275970Scy} 174275970Scy 175275970Scy 176275970Scy/******************************************************************************* 177275970Scy * 178275970Scy * FUNCTION: AcpiDmFinishNamespaceLoad 179275970Scy * 180275970Scy * PARAMETERS: ParseTreeRoot - Root of the parse tree 181275970Scy * NamespaceRoot - Root of the internal namespace 182275970Scy * OwnerId - OwnerId of the table to be disassembled 183275970Scy * 184275970Scy * RETURN: None 185275970Scy * 186275970Scy * DESCRIPTION: Load all namespace items that are created within control 187275970Scy * methods. Used before namespace cross reference 188275970Scy * 189275970Scy ******************************************************************************/ 190275970Scy 191275970Scyvoid 192275970ScyAcpiDmFinishNamespaceLoad ( 193275970Scy ACPI_PARSE_OBJECT *ParseTreeRoot, 194275970Scy ACPI_NAMESPACE_NODE *NamespaceRoot, 195275970Scy ACPI_OWNER_ID OwnerId) 196275970Scy{ 197275970Scy ACPI_STATUS Status; 198275970Scy ACPI_OP_WALK_INFO Info; 199275970Scy ACPI_WALK_STATE *WalkState; 200275970Scy 201275970Scy 202275970Scy if (!ParseTreeRoot) 203275970Scy { 204275970Scy return; 205275970Scy } 206275970Scy 207275970Scy /* Create and initialize a new walk state */ 208275970Scy 209275970Scy WalkState = AcpiDsCreateWalkState (OwnerId, ParseTreeRoot, NULL, NULL); 210275970Scy if (!WalkState) 211275970Scy { 212275970Scy return; 213275970Scy } 214275970Scy 215275970Scy Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type, WalkState); 216275970Scy if (ACPI_FAILURE (Status)) 217275970Scy { 218275970Scy return; 219275970Scy } 220275970Scy 221275970Scy Info.Flags = 0; 222275970Scy Info.Level = 0; 223275970Scy Info.WalkState = WalkState; 224275970Scy AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmLoadDescendingOp, 225275970Scy AcpiDmCommonAscendingOp, &Info); 226275970Scy ACPI_FREE (WalkState); 227275970Scy} 228275970Scy 229275970Scy 230275970Scy/******************************************************************************* 231275970Scy * 232275970Scy * FUNCTION: AcpiDmCrossReferenceNamespace 233275970Scy * 234275970Scy * PARAMETERS: ParseTreeRoot - Root of the parse tree 235275970Scy * NamespaceRoot - Root of the internal namespace 236275970Scy * OwnerId - OwnerId of the table to be disassembled 237275970Scy * 238275970Scy * RETURN: None 239275970Scy * 240275970Scy * DESCRIPTION: Cross reference the namespace to create externals 241275970Scy * 242275970Scy ******************************************************************************/ 243275970Scy 244275970Scyvoid 245275970ScyAcpiDmCrossReferenceNamespace ( 246275970Scy ACPI_PARSE_OBJECT *ParseTreeRoot, 247275970Scy ACPI_NAMESPACE_NODE *NamespaceRoot, 248275970Scy ACPI_OWNER_ID OwnerId) 249275970Scy{ 250275970Scy ACPI_STATUS Status; 251275970Scy ACPI_OP_WALK_INFO Info; 252275970Scy ACPI_WALK_STATE *WalkState; 253275970Scy 254275970Scy 255275970Scy if (!ParseTreeRoot) 256275970Scy { 257275970Scy return; 258275970Scy } 259275970Scy 260275970Scy /* Create and initialize a new walk state */ 261275970Scy 262275970Scy WalkState = AcpiDsCreateWalkState (OwnerId, ParseTreeRoot, NULL, NULL); 263275970Scy if (!WalkState) 264275970Scy { 265275970Scy return; 266275970Scy } 267275970Scy 268275970Scy Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type, WalkState); 269275970Scy if (ACPI_FAILURE (Status)) 270275970Scy { 271275970Scy return; 272275970Scy } 273275970Scy 274275970Scy Info.Flags = 0; 275275970Scy Info.Level = 0; 276275970Scy Info.WalkState = WalkState; 277275970Scy AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmXrefDescendingOp, 278275970Scy AcpiDmCommonAscendingOp, &Info); 279275970Scy ACPI_FREE (WalkState); 280275970Scy} 281275970Scy 282275970Scy 283275970Scy/******************************************************************************* 284275970Scy * 285275970Scy * FUNCTION: AcpiDmConvertResourceIndexes 286275970Scy * 287275970Scy * PARAMETERS: ParseTreeRoot - Root of the parse tree 288275970Scy * NamespaceRoot - Root of the internal namespace 289275970Scy * 290275970Scy * RETURN: None 291275970Scy * 292275970Scy * DESCRIPTION: Convert fixed-offset references to resource descriptors to 293275970Scy * symbolic references. Should only be called after namespace has 294275970Scy * been cross referenced. 295275970Scy * 296275970Scy ******************************************************************************/ 297275970Scy 298275970Scyvoid 299275970ScyAcpiDmConvertResourceIndexes ( 300275970Scy ACPI_PARSE_OBJECT *ParseTreeRoot, 301275970Scy ACPI_NAMESPACE_NODE *NamespaceRoot) 302275970Scy{ 303275970Scy ACPI_STATUS Status; 304275970Scy ACPI_OP_WALK_INFO Info; 305275970Scy ACPI_WALK_STATE *WalkState; 306275970Scy 307275970Scy 308275970Scy if (!ParseTreeRoot) 309275970Scy { 310275970Scy return; 311275970Scy } 312275970Scy 313275970Scy /* Create and initialize a new walk state */ 314275970Scy 315275970Scy WalkState = AcpiDsCreateWalkState (0, ParseTreeRoot, NULL, NULL); 316275970Scy if (!WalkState) 317275970Scy { 318275970Scy return; 319275970Scy } 320275970Scy 321275970Scy Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type, WalkState); 322275970Scy if (ACPI_FAILURE (Status)) 323275970Scy { 324275970Scy return; 325275970Scy } 326275970Scy 327275970Scy Info.Flags = 0; 328275970Scy Info.Level = 0; 329275970Scy Info.WalkState = WalkState; 330275970Scy AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmResourceDescendingOp, 331275970Scy AcpiDmCommonAscendingOp, &Info); 332275970Scy ACPI_FREE (WalkState); 333275970Scy return; 334275970Scy} 335275970Scy 336275970Scy 337275970Scy/******************************************************************************* 338275970Scy * 339275970Scy * FUNCTION: AcpiDmDumpDescending 340275970Scy * 341275970Scy * PARAMETERS: ASL_WALK_CALLBACK 342275970Scy * 343275970Scy * RETURN: Status 344275970Scy * 345275970Scy * DESCRIPTION: Format and print contents of one parse Op. 346275970Scy * 347275970Scy ******************************************************************************/ 348275970Scy 349275970Scystatic ACPI_STATUS 350275970ScyAcpiDmDumpDescending ( 351275970Scy ACPI_PARSE_OBJECT *Op, 352275970Scy UINT32 Level, 353275970Scy void *Context) 354275970Scy{ 355275970Scy ACPI_OP_WALK_INFO *Info = Context; 356275970Scy char *Path; 357275970Scy 358275970Scy 359275970Scy if (!Op) 360275970Scy { 361275970Scy return (AE_OK); 362275970Scy } 363275970Scy 364275970Scy /* Most of the information (count, level, name) here */ 365275970Scy 366275970Scy Info->Count++; 367275970Scy AcpiOsPrintf ("% 5d [%2.2d] ", Info->Count, Level); 368275970Scy AcpiDmIndent (Level); 369275970Scy AcpiOsPrintf ("%-28s", AcpiPsGetOpcodeName (Op->Common.AmlOpcode)); 370275970Scy 371275970Scy /* Extra info is helpful */ 372275970Scy 373275970Scy switch (Op->Common.AmlOpcode) 374275970Scy { 375275970Scy case AML_BYTE_OP: 376275970Scy case AML_WORD_OP: 377275970Scy case AML_DWORD_OP: 378275970Scy AcpiOsPrintf ("%X", (UINT32) Op->Common.Value.Integer); 379275970Scy break; 380275970Scy 381275970Scy case AML_QWORD_OP: 382275970Scy AcpiOsPrintf ("%8.8X%8.8X", ACPI_FORMAT_UINT64 (Op->Common.Value.Integer)); 383275970Scy break; 384275970Scy 385275970Scy case AML_INT_NAMEPATH_OP: 386275970Scy if (Op->Common.Value.String) 387275970Scy { 388275970Scy AcpiNsExternalizeName (ACPI_UINT32_MAX, Op->Common.Value.String, 389275970Scy NULL, &Path); 390275970Scy AcpiOsPrintf ("%s %p", Path, Op->Common.Node); 391275970Scy ACPI_FREE (Path); 392275970Scy } 393275970Scy else 394275970Scy { 395275970Scy AcpiOsPrintf ("[NULL]"); 396275970Scy } 397275970Scy break; 398275970Scy 399275970Scy case AML_NAME_OP: 400275970Scy case AML_METHOD_OP: 401275970Scy case AML_DEVICE_OP: 402275970Scy case AML_INT_NAMEDFIELD_OP: 403275970Scy AcpiOsPrintf ("%4.4s", ACPI_CAST_PTR (char, &Op->Named.Name)); 404275970Scy break; 405275970Scy 406275970Scy default: 407275970Scy break; 408275970Scy } 409275970Scy 410275970Scy AcpiOsPrintf ("\n"); 411275970Scy return (AE_OK); 412275970Scy} 413275970Scy 414275970Scy 415275970Scy/******************************************************************************* 416275970Scy * 417275970Scy * FUNCTION: AcpiDmFindOrphanDescending 418275970Scy * 419275970Scy * PARAMETERS: ASL_WALK_CALLBACK 420275970Scy * 421275970Scy * RETURN: Status 422275970Scy * 423275970Scy * DESCRIPTION: Check namepath Ops for orphaned method invocations 424275970Scy * 425275970Scy * Note: Experimental. 426275970Scy * 427275970Scy ******************************************************************************/ 428275970Scy 429275970Scystatic ACPI_STATUS 430275970ScyAcpiDmFindOrphanDescending ( 431275970Scy ACPI_PARSE_OBJECT *Op, 432275970Scy UINT32 Level, 433275970Scy void *Context) 434275970Scy{ 435275970Scy const ACPI_OPCODE_INFO *OpInfo; 436275970Scy ACPI_PARSE_OBJECT *ChildOp; 437275970Scy ACPI_PARSE_OBJECT *NextOp; 438275970Scy ACPI_PARSE_OBJECT *ParentOp; 439275970Scy UINT32 ArgCount; 440275970Scy 441275970Scy 442275970Scy if (!Op) 443275970Scy { 444275970Scy return (AE_OK); 445275970Scy } 446275970Scy 447275970Scy OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 448275970Scy 449275970Scy switch (Op->Common.AmlOpcode) 450275970Scy { 451275970Scy#ifdef ACPI_UNDER_DEVELOPMENT 452275970Scy case AML_ADD_OP: 453275970Scy ChildOp = Op->Common.Value.Arg; 454275970Scy if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && 455275970Scy !ChildOp->Common.Node) 456275970Scy { 457275970Scy AcpiNsExternalizeName (ACPI_UINT32_MAX, ChildOp->Common.Value.String, 458275970Scy NULL, &Path); 459275970Scy AcpiOsPrintf ("/* %-16s A-NAMEPATH: %s */\n", Op->Common.AmlOpName, Path); 460275970Scy ACPI_FREE (Path); 461275970Scy 462275970Scy NextOp = Op->Common.Next; 463275970Scy if (!NextOp) 464275970Scy { 465275970Scy /* This NamePath has no args, assume it is an integer */ 466275970Scy 467275970Scy AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); 468275970Scy return (AE_OK); 469275970Scy } 470275970Scy 471275970Scy ArgCount = AcpiDmInspectPossibleArgs (3, 1, NextOp); 472275970Scy AcpiOsPrintf ("/* A-CHILDREN: %u Actual %u */\n", ArgCount, AcpiDmCountChildren (Op)); 473275970Scy 474275970Scy if (ArgCount < 1) 475275970Scy { 476275970Scy /* One Arg means this is just a Store(Name,Target) */ 477275970Scy 478275970Scy AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); 479275970Scy return (AE_OK); 480275970Scy } 481275970Scy 482275970Scy AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount); 483275970Scy } 484275970Scy break; 485275970Scy#endif 486275970Scy 487275970Scy case AML_STORE_OP: 488275970Scy 489275970Scy ChildOp = Op->Common.Value.Arg; 490275970Scy if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && 491275970Scy !ChildOp->Common.Node) 492275970Scy { 493275970Scy NextOp = Op->Common.Next; 494275970Scy if (!NextOp) 495275970Scy { 496275970Scy /* This NamePath has no args, assume it is an integer */ 497275970Scy 498275970Scy AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); 499275970Scy return (AE_OK); 500275970Scy } 501275970Scy 502275970Scy ArgCount = AcpiDmInspectPossibleArgs (2, 1, NextOp); 503275970Scy if (ArgCount <= 1) 504275970Scy { 505275970Scy /* One Arg means this is just a Store(Name,Target) */ 506275970Scy 507275970Scy AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); 508275970Scy return (AE_OK); 509275970Scy } 510275970Scy 511275970Scy AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount); 512275970Scy } 513275970Scy break; 514275970Scy 515275970Scy case AML_INT_NAMEPATH_OP: 516275970Scy 517275970Scy /* Must examine parent to see if this namepath is an argument */ 518275970Scy 519275970Scy ParentOp = Op->Common.Parent; 520275970Scy OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode); 521275970Scy 522275970Scy if ((OpInfo->Class != AML_CLASS_EXECUTE) && 523275970Scy (OpInfo->Class != AML_CLASS_CREATE) && 524275970Scy (OpInfo->ObjectType != ACPI_TYPE_LOCAL_ALIAS) && 525275970Scy (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) && 526275970Scy !Op->Common.Node) 527275970Scy { 528275970Scy ArgCount = AcpiDmInspectPossibleArgs (0, 0, Op->Common.Next); 529275970Scy 530275970Scy /* 531275970Scy * Check if namepath is a predicate for if/while or lone parameter to 532275970Scy * a return. 533275970Scy */ 534275970Scy if (ArgCount == 0) 535275970Scy { 536275970Scy if (((ParentOp->Common.AmlOpcode == AML_IF_OP) || 537275970Scy (ParentOp->Common.AmlOpcode == AML_WHILE_OP) || 538275970Scy (ParentOp->Common.AmlOpcode == AML_RETURN_OP)) && 539275970Scy 540275970Scy /* And namepath is the first argument */ 541275970Scy (ParentOp->Common.Value.Arg == Op)) 542275970Scy { 543275970Scy AcpiDmAddToExternalList (Op, Op->Common.Value.String, ACPI_TYPE_INTEGER, 0); 544275970Scy break; 545275970Scy } 546275970Scy } 547275970Scy 548275970Scy /* 549275970Scy * This is a standalone namestring (not a parameter to another 550275970Scy * operator) - it *must* be a method invocation, nothing else is 551275970Scy * grammatically possible. 552275970Scy */ 553275970Scy AcpiDmAddToExternalList (Op, Op->Common.Value.String, ACPI_TYPE_METHOD, ArgCount); 554275970Scy 555275970Scy } 556275970Scy break; 557275970Scy 558275970Scy default: 559275970Scy break; 560275970Scy } 561275970Scy 562275970Scy return (AE_OK); 563275970Scy} 564275970Scy 565275970Scy 566275970Scy/******************************************************************************* 567275970Scy * 568275970Scy * FUNCTION: AcpiDmLoadDescendingOp 569275970Scy * 570275970Scy * PARAMETERS: ASL_WALK_CALLBACK 571275970Scy * 572275970Scy * RETURN: Status 573275970Scy * 574275970Scy * DESCRIPTION: Descending handler for namespace control method object load 575275970Scy * 576275970Scy ******************************************************************************/ 577275970Scy 578275970Scystatic ACPI_STATUS 579275970ScyAcpiDmLoadDescendingOp ( 580275970Scy ACPI_PARSE_OBJECT *Op, 581275970Scy UINT32 Level, 582275970Scy void *Context) 583275970Scy{ 584275970Scy ACPI_OP_WALK_INFO *Info = Context; 585275970Scy const ACPI_OPCODE_INFO *OpInfo; 586275970Scy ACPI_WALK_STATE *WalkState; 587275970Scy ACPI_OBJECT_TYPE ObjectType; 588275970Scy ACPI_STATUS Status; 589275970Scy char *Path = NULL; 590275970Scy ACPI_PARSE_OBJECT *NextOp; 591275970Scy ACPI_NAMESPACE_NODE *Node; 592275970Scy char FieldPath[5]; 593275970Scy BOOLEAN PreDefined = FALSE; 594275970Scy UINT8 PreDefineIndex = 0; 595275970Scy 596275970Scy 597275970Scy WalkState = Info->WalkState; 598275970Scy OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 599275970Scy ObjectType = OpInfo->ObjectType; 600275970Scy ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 601275970Scy 602275970Scy /* Only interested in operators that create new names */ 603275970Scy 604275970Scy if (!(OpInfo->Flags & AML_NAMED) && 605275970Scy !(OpInfo->Flags & AML_CREATE)) 606275970Scy { 607275970Scy goto Exit; 608275970Scy } 609275970Scy 610275970Scy /* Get the NamePath from the appropriate place */ 611275970Scy 612275970Scy if (OpInfo->Flags & AML_NAMED) 613275970Scy { 614275970Scy /* For all named operators, get the new name */ 615275970Scy 616275970Scy Path = (char *) Op->Named.Path; 617275970Scy 618275970Scy if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP) 619275970Scy { 620275970Scy *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name; 621275970Scy FieldPath[4] = 0; 622275970Scy Path = FieldPath; 623275970Scy } 624275970Scy } 625275970Scy else if (OpInfo->Flags & AML_CREATE) 626275970Scy { 627275970Scy /* New name is the last child */ 628275970Scy 629275970Scy NextOp = Op->Common.Value.Arg; 630275970Scy 631275970Scy while (NextOp->Common.Next) 632275970Scy { 633275970Scy NextOp = NextOp->Common.Next; 634275970Scy } 635275970Scy Path = NextOp->Common.Value.String; 636275970Scy } 637275970Scy 638275970Scy if (!Path) 639275970Scy { 640275970Scy goto Exit; 641275970Scy } 642275970Scy 643275970Scy /* Insert the name into the namespace */ 644275970Scy 645275970Scy Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, 646275970Scy ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE, 647275970Scy WalkState, &Node); 648275970Scy 649275970Scy Op->Common.Node = Node; 650275970Scy 651275970Scy if (ACPI_SUCCESS (Status)) 652275970Scy { 653275970Scy /* Check if it's a predefined node */ 654275970Scy 655275970Scy while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name) 656275970Scy { 657275970Scy if (!ACPI_STRNCMP (Node->Name.Ascii, 658275970Scy AcpiGbl_PreDefinedNames[PreDefineIndex].Name, 4)) 659275970Scy { 660275970Scy PreDefined = TRUE; 661275970Scy break; 662275970Scy } 663275970Scy 664275970Scy PreDefineIndex++; 665275970Scy } 666275970Scy 667275970Scy /* 668275970Scy * Set node owner id if it satisfies all the following conditions: 669275970Scy * 1) Not a predefined node, _SB_ etc 670275970Scy * 2) Not the root node 671275970Scy * 3) Not a node created by Scope 672275970Scy */ 673275970Scy 674275970Scy if (!PreDefined && Node != AcpiGbl_RootNode && 675275970Scy Op->Common.AmlOpcode != AML_SCOPE_OP) 676275970Scy { 677275970Scy Node->OwnerId = WalkState->OwnerId; 678275970Scy } 679275970Scy } 680275970Scy 681275970Scy 682275970ScyExit: 683275970Scy 684275970Scy if (AcpiNsOpensScope (ObjectType)) 685275970Scy { 686275970Scy if (Op->Common.Node) 687275970Scy { 688275970Scy Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState); 689275970Scy if (ACPI_FAILURE (Status)) 690275970Scy { 691275970Scy return (Status); 692275970Scy } 693275970Scy } 694275970Scy } 695275970Scy 696275970Scy return (AE_OK); 697275970Scy} 698275970Scy 699275970Scy 700275970Scy/******************************************************************************* 701275970Scy * 702275970Scy * FUNCTION: AcpiDmXrefDescendingOp 703275970Scy * 704275970Scy * PARAMETERS: ASL_WALK_CALLBACK 705275970Scy * 706275970Scy * RETURN: Status 707275970Scy * 708275970Scy * DESCRIPTION: Descending handler for namespace cross reference 709275970Scy * 710275970Scy ******************************************************************************/ 711275970Scy 712275970Scystatic ACPI_STATUS 713275970ScyAcpiDmXrefDescendingOp ( 714275970Scy ACPI_PARSE_OBJECT *Op, 715275970Scy UINT32 Level, 716275970Scy void *Context) 717275970Scy{ 718275970Scy ACPI_OP_WALK_INFO *Info = Context; 719275970Scy const ACPI_OPCODE_INFO *OpInfo; 720275970Scy ACPI_WALK_STATE *WalkState; 721275970Scy ACPI_OBJECT_TYPE ObjectType; 722275970Scy ACPI_OBJECT_TYPE ObjectType2; 723275970Scy ACPI_STATUS Status; 724275970Scy char *Path = NULL; 725275970Scy ACPI_PARSE_OBJECT *NextOp; 726275970Scy ACPI_NAMESPACE_NODE *Node; 727275970Scy ACPI_OPERAND_OBJECT *Object; 728275970Scy UINT32 ParamCount = 0; 729275970Scy 730275970Scy 731275970Scy WalkState = Info->WalkState; 732275970Scy OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 733275970Scy ObjectType = OpInfo->ObjectType; 734275970Scy ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 735275970Scy 736275970Scy if ((!(OpInfo->Flags & AML_NAMED)) && 737275970Scy (!(OpInfo->Flags & AML_CREATE)) && 738275970Scy (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP)) 739275970Scy { 740275970Scy goto Exit; 741275970Scy } 742275970Scy 743275970Scy /* Get the NamePath from the appropriate place */ 744275970Scy 745275970Scy if (OpInfo->Flags & AML_NAMED) 746275970Scy { 747275970Scy /* 748275970Scy * Only these two operators (Alias, Scope) refer to an existing 749275970Scy * name, it is the first argument 750275970Scy */ 751275970Scy if (Op->Common.AmlOpcode == AML_ALIAS_OP) 752275970Scy { 753275970Scy ObjectType = ACPI_TYPE_ANY; 754275970Scy 755275970Scy NextOp = Op->Common.Value.Arg; 756275970Scy NextOp = NextOp->Common.Value.Arg; 757275970Scy if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) 758275970Scy { 759275970Scy Path = NextOp->Common.Value.String; 760275970Scy } 761275970Scy } 762275970Scy else if (Op->Common.AmlOpcode == AML_SCOPE_OP) 763275970Scy { 764275970Scy Path = (char *) Op->Named.Path; 765275970Scy } 766275970Scy } 767275970Scy else if (OpInfo->Flags & AML_CREATE) 768275970Scy { 769275970Scy /* Referenced Buffer Name is the first child */ 770275970Scy 771275970Scy ObjectType = ACPI_TYPE_BUFFER; /* Change from TYPE_BUFFER_FIELD */ 772275970Scy 773275970Scy NextOp = Op->Common.Value.Arg; 774275970Scy if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) 775275970Scy { 776275970Scy Path = NextOp->Common.Value.String; 777275970Scy } 778275970Scy } 779275970Scy else 780275970Scy { 781275970Scy Path = Op->Common.Value.String; 782275970Scy } 783275970Scy 784275970Scy if (!Path) 785275970Scy { 786275970Scy goto Exit; 787275970Scy } 788275970Scy 789275970Scy /* 790275970Scy * Lookup the name in the namespace. Name must exist at this point, or it 791275970Scy * is an invalid reference. 792275970Scy * 793275970Scy * The namespace is also used as a lookup table for references to resource 794275970Scy * descriptors and the fields within them. 795275970Scy */ 796275970Scy Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, 797275970Scy ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 798275970Scy WalkState, &Node); 799275970Scy if (ACPI_SUCCESS (Status) && (Node->Flags & ANOBJ_IS_EXTERNAL)) 800275970Scy { 801275970Scy Status = AE_NOT_FOUND; 802275970Scy } 803275970Scy 804275970Scy if (ACPI_FAILURE (Status)) 805275970Scy { 806275970Scy if (Status == AE_NOT_FOUND) 807275970Scy { 808275970Scy AcpiDmAddToExternalList (Op, Path, (UINT8) ObjectType, 0); 809275970Scy 810275970Scy /* 811275970Scy * We could install this into the namespace, but we catch duplicate 812275970Scy * externals when they are added to the list. 813275970Scy */ 814275970Scy#if 0 815275970Scy Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, 816275970Scy ACPI_IMODE_LOAD_PASS1, ACPI_NS_DONT_OPEN_SCOPE, 817275970Scy WalkState, &Node); 818275970Scy#endif 819275970Scy } 820275970Scy } 821275970Scy 822275970Scy /* 823275970Scy * Found the node in external table, add it to external list 824275970Scy * Node->OwnerId == 0 indicates built-in ACPI Names, _OS_ etc 825275970Scy */ 826275970Scy else if (Node->OwnerId && WalkState->OwnerId != Node->OwnerId) 827275970Scy { 828275970Scy ObjectType2 = ObjectType; 829275970Scy 830275970Scy Object = AcpiNsGetAttachedObject (Node); 831275970Scy if (Object) 832275970Scy { 833275970Scy ObjectType2 = Object->Common.Type; 834275970Scy if (ObjectType2 == ACPI_TYPE_METHOD) 835275970Scy { 836275970Scy ParamCount = Object->Method.ParamCount; 837275970Scy } 838275970Scy } 839275970Scy 840275970Scy AcpiDmAddToExternalList (Op, Path, (UINT8) ObjectType2, ParamCount); 841275970Scy Op->Common.Node = Node; 842275970Scy } 843275970Scy else 844275970Scy { 845275970Scy Op->Common.Node = Node; 846275970Scy } 847275970Scy 848275970Scy 849275970ScyExit: 850275970Scy /* Open new scope if necessary */ 851275970Scy 852275970Scy if (AcpiNsOpensScope (ObjectType)) 853275970Scy { 854275970Scy if (Op->Common.Node) 855275970Scy { 856275970Scy Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState); 857275970Scy if (ACPI_FAILURE (Status)) 858275970Scy { 859275970Scy return (Status); 860275970Scy } 861275970Scy } 862275970Scy } 863275970Scy 864275970Scy return (AE_OK); 865275970Scy} 866275970Scy 867275970Scy 868275970Scy/******************************************************************************* 869275970Scy * 870275970Scy * FUNCTION: AcpiDmResourceDescendingOp 871275970Scy * 872275970Scy * PARAMETERS: ASL_WALK_CALLBACK 873275970Scy * 874275970Scy * RETURN: None 875275970Scy * 876275970Scy * DESCRIPTION: Process one parse op during symbolic resource index conversion. 877275970Scy * 878275970Scy ******************************************************************************/ 879275970Scy 880275970Scystatic ACPI_STATUS 881275970ScyAcpiDmResourceDescendingOp ( 882275970Scy ACPI_PARSE_OBJECT *Op, 883275970Scy UINT32 Level, 884275970Scy void *Context) 885275970Scy{ 886275970Scy ACPI_OP_WALK_INFO *Info = Context; 887275970Scy const ACPI_OPCODE_INFO *OpInfo; 888275970Scy ACPI_WALK_STATE *WalkState; 889275970Scy ACPI_OBJECT_TYPE ObjectType; 890275970Scy ACPI_STATUS Status; 891275970Scy 892275970Scy 893275970Scy WalkState = Info->WalkState; 894275970Scy OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 895275970Scy 896275970Scy /* Open new scope if necessary */ 897275970Scy 898275970Scy ObjectType = OpInfo->ObjectType; 899275970Scy if (AcpiNsOpensScope (ObjectType)) 900275970Scy { 901275970Scy if (Op->Common.Node) 902275970Scy { 903275970Scy 904275970Scy Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState); 905275970Scy if (ACPI_FAILURE (Status)) 906275970Scy { 907275970Scy return (Status); 908275970Scy } 909275970Scy } 910275970Scy } 911275970Scy 912275970Scy /* 913275970Scy * Check if this operator contains a reference to a resource descriptor. 914275970Scy * If so, convert the reference into a symbolic reference. 915275970Scy */ 916275970Scy AcpiDmCheckResourceReference (Op, WalkState); 917275970Scy return (AE_OK); 918275970Scy} 919275970Scy 920275970Scy 921275970Scy/******************************************************************************* 922275970Scy * 923275970Scy * FUNCTION: AcpiDmCommonAscendingOp 924275970Scy * 925275970Scy * PARAMETERS: ASL_WALK_CALLBACK 926275970Scy * 927275970Scy * RETURN: None 928275970Scy * 929275970Scy * DESCRIPTION: Ascending handler for combined parse/namespace walks. Closes 930275970Scy * scope if necessary. 931275970Scy * 932275970Scy ******************************************************************************/ 933275970Scy 934275970Scystatic ACPI_STATUS 935275970ScyAcpiDmCommonAscendingOp ( 936275970Scy ACPI_PARSE_OBJECT *Op, 937275970Scy UINT32 Level, 938275970Scy void *Context) 939275970Scy{ 940275970Scy ACPI_OP_WALK_INFO *Info = Context; 941275970Scy const ACPI_OPCODE_INFO *OpInfo; 942275970Scy ACPI_OBJECT_TYPE ObjectType; 943275970Scy 944275970Scy 945275970Scy /* Close scope if necessary */ 946275970Scy 947275970Scy OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 948275970Scy ObjectType = OpInfo->ObjectType; 949275970Scy ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 950275970Scy 951275970Scy if (AcpiNsOpensScope (ObjectType)) 952275970Scy { 953275970Scy (void) AcpiDsScopeStackPop (Info->WalkState); 954275970Scy } 955275970Scy 956275970Scy return (AE_OK); 957275970Scy} 958275970Scy 959275970Scy 960275970Scy/******************************************************************************* 961275970Scy * 962275970Scy * FUNCTION: AcpiDmInspectPossibleArgs 963275970Scy * 964275970Scy * PARAMETERS: CurrentOpArgCount - Which arg of the current op was the 965275970Scy * possible method invocation found 966275970Scy * TargetCount - Number of targets (0,1,2) for this op 967275970Scy * Op - Parse op 968275970Scy * 969275970Scy * RETURN: Status 970275970Scy * 971275970Scy * DESCRIPTION: Examine following args and next ops for possible arguments 972275970Scy * for an unrecognized method invocation. 973275970Scy * 974275970Scy ******************************************************************************/ 975275970Scy 976275970Scystatic UINT32 977275970ScyAcpiDmInspectPossibleArgs ( 978275970Scy UINT32 CurrentOpArgCount, 979275970Scy UINT32 TargetCount, 980275970Scy ACPI_PARSE_OBJECT *Op) 981275970Scy{ 982275970Scy const ACPI_OPCODE_INFO *OpInfo; 983275970Scy UINT32 i; 984275970Scy UINT32 Last = 0; 985275970Scy UINT32 Lookahead; 986275970Scy 987275970Scy 988275970Scy Lookahead = (ACPI_METHOD_NUM_ARGS + TargetCount) - CurrentOpArgCount; 989275970Scy 990275970Scy /* Lookahead for the maximum number of possible arguments */ 991275970Scy 992275970Scy for (i = 0; i < Lookahead; i++) 993275970Scy { 994275970Scy if (!Op) 995275970Scy { 996275970Scy break; 997275970Scy } 998275970Scy 999275970Scy OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 1000275970Scy 1001275970Scy /* 1002275970Scy * Any one of these operators is "very probably" not a method arg 1003275970Scy */ 1004275970Scy if ((Op->Common.AmlOpcode == AML_STORE_OP) || 1005275970Scy (Op->Common.AmlOpcode == AML_NOTIFY_OP)) 1006275970Scy { 1007275970Scy break; 1008275970Scy } 1009275970Scy 1010 if ((OpInfo->Class != AML_CLASS_EXECUTE) && 1011 (OpInfo->Class != AML_CLASS_CONTROL)) 1012 { 1013 Last = i+1; 1014 } 1015 1016 Op = Op->Common.Next; 1017 } 1018 1019 return (Last); 1020} 1021 1022 1023