1167802Sjkim/****************************************************************************** 2167802Sjkim * 3167802Sjkim * Module Name: adwalk - Application-level disassembler parse tree walk routines 4167802Sjkim * 5167802Sjkim *****************************************************************************/ 6167802Sjkim 7217365Sjkim/* 8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp. 9167802Sjkim * All rights reserved. 10167802Sjkim * 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. 25167802Sjkim * 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. 29167802Sjkim * 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 */ 43167802Sjkim 44167802Sjkim 45193529Sjkim#include <contrib/dev/acpica/include/acpi.h> 46193529Sjkim#include <contrib/dev/acpica/include/accommon.h> 47193529Sjkim#include <contrib/dev/acpica/include/acparser.h> 48193529Sjkim#include <contrib/dev/acpica/include/amlcode.h> 49193529Sjkim#include <contrib/dev/acpica/include/acdisasm.h> 50193529Sjkim#include <contrib/dev/acpica/include/acdispat.h> 51193529Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 52193529Sjkim#include <contrib/dev/acpica/include/acapps.h> 53167802Sjkim 54167802Sjkim 55167802Sjkim#define _COMPONENT ACPI_TOOLS 56167802Sjkim ACPI_MODULE_NAME ("adwalk") 57167802Sjkim 58167802Sjkim/* 59167802Sjkim * aslmap - opcode mappings and reserved method names 60167802Sjkim */ 61167802SjkimACPI_OBJECT_TYPE 62167802SjkimAslMapNamedOpcodeToDataType ( 63167802Sjkim UINT16 Opcode); 64167802Sjkim 65167802Sjkim/* Local prototypes */ 66167802Sjkim 67167802Sjkimstatic ACPI_STATUS 68167802SjkimAcpiDmFindOrphanDescending ( 69167802Sjkim ACPI_PARSE_OBJECT *Op, 70167802Sjkim UINT32 Level, 71167802Sjkim void *Context); 72167802Sjkim 73167802Sjkimstatic ACPI_STATUS 74167802SjkimAcpiDmDumpDescending ( 75167802Sjkim ACPI_PARSE_OBJECT *Op, 76167802Sjkim UINT32 Level, 77167802Sjkim void *Context); 78167802Sjkim 79167802Sjkimstatic ACPI_STATUS 80167802SjkimAcpiDmXrefDescendingOp ( 81167802Sjkim ACPI_PARSE_OBJECT *Op, 82167802Sjkim UINT32 Level, 83167802Sjkim void *Context); 84167802Sjkim 85167802Sjkimstatic ACPI_STATUS 86167802SjkimAcpiDmCommonAscendingOp ( 87167802Sjkim ACPI_PARSE_OBJECT *Op, 88167802Sjkim UINT32 Level, 89167802Sjkim void *Context); 90167802Sjkim 91167802Sjkimstatic ACPI_STATUS 92167802SjkimAcpiDmLoadDescendingOp ( 93167802Sjkim ACPI_PARSE_OBJECT *Op, 94167802Sjkim UINT32 Level, 95167802Sjkim void *Context); 96167802Sjkim 97167802Sjkimstatic UINT32 98167802SjkimAcpiDmInspectPossibleArgs ( 99167802Sjkim UINT32 CurrentOpArgCount, 100167802Sjkim UINT32 TargetCount, 101167802Sjkim ACPI_PARSE_OBJECT *Op); 102167802Sjkim 103167802Sjkimstatic ACPI_STATUS 104167802SjkimAcpiDmResourceDescendingOp ( 105167802Sjkim ACPI_PARSE_OBJECT *Op, 106167802Sjkim UINT32 Level, 107167802Sjkim void *Context); 108167802Sjkim 109167802Sjkim 110167802Sjkim/******************************************************************************* 111167802Sjkim * 112167802Sjkim * FUNCTION: AcpiDmDumpTree 113167802Sjkim * 114198237Sjkim * PARAMETERS: Origin - Starting object 115167802Sjkim * 116167802Sjkim * RETURN: None 117167802Sjkim * 118167802Sjkim * DESCRIPTION: Parse tree walk to format and output the nodes 119167802Sjkim * 120167802Sjkim ******************************************************************************/ 121167802Sjkim 122167802Sjkimvoid 123167802SjkimAcpiDmDumpTree ( 124167802Sjkim ACPI_PARSE_OBJECT *Origin) 125167802Sjkim{ 126167802Sjkim ACPI_OP_WALK_INFO Info; 127167802Sjkim 128167802Sjkim 129167802Sjkim if (!Origin) 130167802Sjkim { 131167802Sjkim return; 132167802Sjkim } 133167802Sjkim 134167802Sjkim AcpiOsPrintf ("/*\nAML Parse Tree\n\n"); 135167802Sjkim Info.Flags = 0; 136167802Sjkim Info.Count = 0; 137167802Sjkim Info.Level = 0; 138167802Sjkim Info.WalkState = NULL; 139167802Sjkim AcpiDmWalkParseTree (Origin, AcpiDmDumpDescending, NULL, &Info); 140167802Sjkim AcpiOsPrintf ("*/\n\n"); 141167802Sjkim} 142167802Sjkim 143167802Sjkim 144167802Sjkim/******************************************************************************* 145167802Sjkim * 146167802Sjkim * FUNCTION: AcpiDmFindOrphanMethods 147167802Sjkim * 148198237Sjkim * PARAMETERS: Origin - Starting object 149167802Sjkim * 150167802Sjkim * RETURN: None 151167802Sjkim * 152167802Sjkim * DESCRIPTION: Parse tree walk to find "orphaned" method invocations -- methods 153167802Sjkim * that are not resolved in the namespace 154167802Sjkim * 155167802Sjkim ******************************************************************************/ 156167802Sjkim 157167802Sjkimvoid 158167802SjkimAcpiDmFindOrphanMethods ( 159167802Sjkim ACPI_PARSE_OBJECT *Origin) 160167802Sjkim{ 161167802Sjkim ACPI_OP_WALK_INFO Info; 162167802Sjkim 163167802Sjkim 164167802Sjkim if (!Origin) 165167802Sjkim { 166167802Sjkim return; 167167802Sjkim } 168167802Sjkim 169167802Sjkim Info.Flags = 0; 170167802Sjkim Info.Level = 0; 171167802Sjkim Info.WalkState = NULL; 172167802Sjkim AcpiDmWalkParseTree (Origin, AcpiDmFindOrphanDescending, NULL, &Info); 173167802Sjkim} 174167802Sjkim 175167802Sjkim 176167802Sjkim/******************************************************************************* 177167802Sjkim * 178167802Sjkim * FUNCTION: AcpiDmFinishNamespaceLoad 179167802Sjkim * 180167802Sjkim * PARAMETERS: ParseTreeRoot - Root of the parse tree 181167802Sjkim * NamespaceRoot - Root of the internal namespace 182193529Sjkim * OwnerId - OwnerId of the table to be disassembled 183167802Sjkim * 184167802Sjkim * RETURN: None 185167802Sjkim * 186167802Sjkim * DESCRIPTION: Load all namespace items that are created within control 187167802Sjkim * methods. Used before namespace cross reference 188167802Sjkim * 189167802Sjkim ******************************************************************************/ 190167802Sjkim 191167802Sjkimvoid 192167802SjkimAcpiDmFinishNamespaceLoad ( 193167802Sjkim ACPI_PARSE_OBJECT *ParseTreeRoot, 194193529Sjkim ACPI_NAMESPACE_NODE *NamespaceRoot, 195193529Sjkim ACPI_OWNER_ID OwnerId) 196167802Sjkim{ 197167802Sjkim ACPI_STATUS Status; 198167802Sjkim ACPI_OP_WALK_INFO Info; 199167802Sjkim ACPI_WALK_STATE *WalkState; 200167802Sjkim 201167802Sjkim 202167802Sjkim if (!ParseTreeRoot) 203167802Sjkim { 204167802Sjkim return; 205167802Sjkim } 206167802Sjkim 207167802Sjkim /* Create and initialize a new walk state */ 208167802Sjkim 209193529Sjkim WalkState = AcpiDsCreateWalkState (OwnerId, ParseTreeRoot, NULL, NULL); 210167802Sjkim if (!WalkState) 211167802Sjkim { 212167802Sjkim return; 213167802Sjkim } 214167802Sjkim 215167802Sjkim Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type, WalkState); 216167802Sjkim if (ACPI_FAILURE (Status)) 217167802Sjkim { 218167802Sjkim return; 219167802Sjkim } 220167802Sjkim 221167802Sjkim Info.Flags = 0; 222167802Sjkim Info.Level = 0; 223167802Sjkim Info.WalkState = WalkState; 224167802Sjkim AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmLoadDescendingOp, 225167802Sjkim AcpiDmCommonAscendingOp, &Info); 226167802Sjkim ACPI_FREE (WalkState); 227167802Sjkim} 228167802Sjkim 229167802Sjkim 230167802Sjkim/******************************************************************************* 231167802Sjkim * 232167802Sjkim * FUNCTION: AcpiDmCrossReferenceNamespace 233167802Sjkim * 234167802Sjkim * PARAMETERS: ParseTreeRoot - Root of the parse tree 235167802Sjkim * NamespaceRoot - Root of the internal namespace 236193529Sjkim * OwnerId - OwnerId of the table to be disassembled 237167802Sjkim * 238167802Sjkim * RETURN: None 239167802Sjkim * 240167802Sjkim * DESCRIPTION: Cross reference the namespace to create externals 241167802Sjkim * 242167802Sjkim ******************************************************************************/ 243167802Sjkim 244167802Sjkimvoid 245167802SjkimAcpiDmCrossReferenceNamespace ( 246167802Sjkim ACPI_PARSE_OBJECT *ParseTreeRoot, 247193529Sjkim ACPI_NAMESPACE_NODE *NamespaceRoot, 248193529Sjkim ACPI_OWNER_ID OwnerId) 249167802Sjkim{ 250167802Sjkim ACPI_STATUS Status; 251167802Sjkim ACPI_OP_WALK_INFO Info; 252167802Sjkim ACPI_WALK_STATE *WalkState; 253167802Sjkim 254167802Sjkim 255167802Sjkim if (!ParseTreeRoot) 256167802Sjkim { 257167802Sjkim return; 258167802Sjkim } 259167802Sjkim 260167802Sjkim /* Create and initialize a new walk state */ 261167802Sjkim 262193529Sjkim WalkState = AcpiDsCreateWalkState (OwnerId, ParseTreeRoot, NULL, NULL); 263167802Sjkim if (!WalkState) 264167802Sjkim { 265167802Sjkim return; 266167802Sjkim } 267167802Sjkim 268167802Sjkim Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type, WalkState); 269167802Sjkim if (ACPI_FAILURE (Status)) 270167802Sjkim { 271167802Sjkim return; 272167802Sjkim } 273167802Sjkim 274167802Sjkim Info.Flags = 0; 275167802Sjkim Info.Level = 0; 276167802Sjkim Info.WalkState = WalkState; 277167802Sjkim AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmXrefDescendingOp, 278167802Sjkim AcpiDmCommonAscendingOp, &Info); 279167802Sjkim ACPI_FREE (WalkState); 280167802Sjkim} 281167802Sjkim 282167802Sjkim 283167802Sjkim/******************************************************************************* 284167802Sjkim * 285167802Sjkim * FUNCTION: AcpiDmConvertResourceIndexes 286167802Sjkim * 287167802Sjkim * PARAMETERS: ParseTreeRoot - Root of the parse tree 288167802Sjkim * NamespaceRoot - Root of the internal namespace 289167802Sjkim * 290167802Sjkim * RETURN: None 291167802Sjkim * 292167802Sjkim * DESCRIPTION: Convert fixed-offset references to resource descriptors to 293167802Sjkim * symbolic references. Should only be called after namespace has 294167802Sjkim * been cross referenced. 295167802Sjkim * 296167802Sjkim ******************************************************************************/ 297167802Sjkim 298167802Sjkimvoid 299167802SjkimAcpiDmConvertResourceIndexes ( 300167802Sjkim ACPI_PARSE_OBJECT *ParseTreeRoot, 301167802Sjkim ACPI_NAMESPACE_NODE *NamespaceRoot) 302167802Sjkim{ 303167802Sjkim ACPI_STATUS Status; 304167802Sjkim ACPI_OP_WALK_INFO Info; 305167802Sjkim ACPI_WALK_STATE *WalkState; 306167802Sjkim 307167802Sjkim 308167802Sjkim if (!ParseTreeRoot) 309167802Sjkim { 310167802Sjkim return; 311167802Sjkim } 312167802Sjkim 313167802Sjkim /* Create and initialize a new walk state */ 314167802Sjkim 315167802Sjkim WalkState = AcpiDsCreateWalkState (0, ParseTreeRoot, NULL, NULL); 316167802Sjkim if (!WalkState) 317167802Sjkim { 318167802Sjkim return; 319167802Sjkim } 320167802Sjkim 321167802Sjkim Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type, WalkState); 322167802Sjkim if (ACPI_FAILURE (Status)) 323167802Sjkim { 324167802Sjkim return; 325167802Sjkim } 326167802Sjkim 327167802Sjkim Info.Flags = 0; 328167802Sjkim Info.Level = 0; 329167802Sjkim Info.WalkState = WalkState; 330167802Sjkim AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmResourceDescendingOp, 331167802Sjkim AcpiDmCommonAscendingOp, &Info); 332167802Sjkim ACPI_FREE (WalkState); 333167802Sjkim return; 334167802Sjkim} 335167802Sjkim 336167802Sjkim 337167802Sjkim/******************************************************************************* 338167802Sjkim * 339167802Sjkim * FUNCTION: AcpiDmDumpDescending 340167802Sjkim * 341167802Sjkim * PARAMETERS: ASL_WALK_CALLBACK 342167802Sjkim * 343167802Sjkim * RETURN: Status 344167802Sjkim * 345167802Sjkim * DESCRIPTION: Format and print contents of one parse Op. 346167802Sjkim * 347167802Sjkim ******************************************************************************/ 348167802Sjkim 349167802Sjkimstatic ACPI_STATUS 350167802SjkimAcpiDmDumpDescending ( 351167802Sjkim ACPI_PARSE_OBJECT *Op, 352167802Sjkim UINT32 Level, 353167802Sjkim void *Context) 354167802Sjkim{ 355167802Sjkim ACPI_OP_WALK_INFO *Info = Context; 356167802Sjkim char *Path; 357167802Sjkim 358167802Sjkim 359167802Sjkim if (!Op) 360167802Sjkim { 361167802Sjkim return (AE_OK); 362167802Sjkim } 363167802Sjkim 364167802Sjkim /* Most of the information (count, level, name) here */ 365167802Sjkim 366198237Sjkim Info->Count++; 367167802Sjkim AcpiOsPrintf ("% 5d [%2.2d] ", Info->Count, Level); 368167802Sjkim AcpiDmIndent (Level); 369167802Sjkim AcpiOsPrintf ("%-28s", AcpiPsGetOpcodeName (Op->Common.AmlOpcode)); 370167802Sjkim 371167802Sjkim /* Extra info is helpful */ 372167802Sjkim 373167802Sjkim switch (Op->Common.AmlOpcode) 374167802Sjkim { 375167802Sjkim case AML_BYTE_OP: 376254745Sjkim 377254745Sjkim AcpiOsPrintf ("%2.2X", (UINT32) Op->Common.Value.Integer); 378254745Sjkim break; 379254745Sjkim 380167802Sjkim case AML_WORD_OP: 381254745Sjkim 382254745Sjkim AcpiOsPrintf ("%4.4X", (UINT32) Op->Common.Value.Integer); 383254745Sjkim break; 384254745Sjkim 385167802Sjkim case AML_DWORD_OP: 386250838Sjkim 387254745Sjkim AcpiOsPrintf ("%8.8X", (UINT32) Op->Common.Value.Integer); 388167802Sjkim break; 389167802Sjkim 390228110Sjkim case AML_QWORD_OP: 391250838Sjkim 392228110Sjkim AcpiOsPrintf ("%8.8X%8.8X", ACPI_FORMAT_UINT64 (Op->Common.Value.Integer)); 393228110Sjkim break; 394228110Sjkim 395167802Sjkim case AML_INT_NAMEPATH_OP: 396250838Sjkim 397167802Sjkim if (Op->Common.Value.String) 398167802Sjkim { 399167802Sjkim AcpiNsExternalizeName (ACPI_UINT32_MAX, Op->Common.Value.String, 400167802Sjkim NULL, &Path); 401167802Sjkim AcpiOsPrintf ("%s %p", Path, Op->Common.Node); 402167802Sjkim ACPI_FREE (Path); 403167802Sjkim } 404167802Sjkim else 405167802Sjkim { 406167802Sjkim AcpiOsPrintf ("[NULL]"); 407167802Sjkim } 408167802Sjkim break; 409167802Sjkim 410167802Sjkim case AML_NAME_OP: 411167802Sjkim case AML_METHOD_OP: 412167802Sjkim case AML_DEVICE_OP: 413167802Sjkim case AML_INT_NAMEDFIELD_OP: 414250838Sjkim 415198237Sjkim AcpiOsPrintf ("%4.4s", ACPI_CAST_PTR (char, &Op->Named.Name)); 416167802Sjkim break; 417193529Sjkim 418193529Sjkim default: 419250838Sjkim 420193529Sjkim break; 421167802Sjkim } 422167802Sjkim 423167802Sjkim AcpiOsPrintf ("\n"); 424167802Sjkim return (AE_OK); 425167802Sjkim} 426167802Sjkim 427167802Sjkim 428167802Sjkim/******************************************************************************* 429167802Sjkim * 430167802Sjkim * FUNCTION: AcpiDmFindOrphanDescending 431167802Sjkim * 432167802Sjkim * PARAMETERS: ASL_WALK_CALLBACK 433167802Sjkim * 434167802Sjkim * RETURN: Status 435167802Sjkim * 436167802Sjkim * DESCRIPTION: Check namepath Ops for orphaned method invocations 437167802Sjkim * 438167802Sjkim * Note: Experimental. 439167802Sjkim * 440167802Sjkim ******************************************************************************/ 441167802Sjkim 442167802Sjkimstatic ACPI_STATUS 443167802SjkimAcpiDmFindOrphanDescending ( 444167802Sjkim ACPI_PARSE_OBJECT *Op, 445167802Sjkim UINT32 Level, 446167802Sjkim void *Context) 447167802Sjkim{ 448167802Sjkim const ACPI_OPCODE_INFO *OpInfo; 449167802Sjkim ACPI_PARSE_OBJECT *ChildOp; 450167802Sjkim ACPI_PARSE_OBJECT *NextOp; 451167802Sjkim ACPI_PARSE_OBJECT *ParentOp; 452167802Sjkim UINT32 ArgCount; 453167802Sjkim 454167802Sjkim 455167802Sjkim if (!Op) 456167802Sjkim { 457167802Sjkim return (AE_OK); 458167802Sjkim } 459167802Sjkim 460167802Sjkim OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 461167802Sjkim 462167802Sjkim switch (Op->Common.AmlOpcode) 463167802Sjkim { 464167802Sjkim#ifdef ACPI_UNDER_DEVELOPMENT 465167802Sjkim case AML_ADD_OP: 466250838Sjkim 467167802Sjkim ChildOp = Op->Common.Value.Arg; 468167802Sjkim if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && 469167802Sjkim !ChildOp->Common.Node) 470167802Sjkim { 471167802Sjkim AcpiNsExternalizeName (ACPI_UINT32_MAX, ChildOp->Common.Value.String, 472167802Sjkim NULL, &Path); 473167802Sjkim AcpiOsPrintf ("/* %-16s A-NAMEPATH: %s */\n", Op->Common.AmlOpName, Path); 474167802Sjkim ACPI_FREE (Path); 475167802Sjkim 476167802Sjkim NextOp = Op->Common.Next; 477167802Sjkim if (!NextOp) 478167802Sjkim { 479167802Sjkim /* This NamePath has no args, assume it is an integer */ 480167802Sjkim 481198237Sjkim AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); 482167802Sjkim return (AE_OK); 483167802Sjkim } 484167802Sjkim 485167802Sjkim ArgCount = AcpiDmInspectPossibleArgs (3, 1, NextOp); 486209746Sjkim AcpiOsPrintf ("/* A-CHILDREN: %u Actual %u */\n", ArgCount, AcpiDmCountChildren (Op)); 487167802Sjkim 488167802Sjkim if (ArgCount < 1) 489167802Sjkim { 490167802Sjkim /* One Arg means this is just a Store(Name,Target) */ 491167802Sjkim 492198237Sjkim AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); 493167802Sjkim return (AE_OK); 494167802Sjkim } 495167802Sjkim 496198237Sjkim AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount); 497167802Sjkim } 498167802Sjkim break; 499167802Sjkim#endif 500167802Sjkim 501167802Sjkim case AML_STORE_OP: 502167802Sjkim 503167802Sjkim ChildOp = Op->Common.Value.Arg; 504167802Sjkim if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && 505167802Sjkim !ChildOp->Common.Node) 506167802Sjkim { 507167802Sjkim NextOp = Op->Common.Next; 508167802Sjkim if (!NextOp) 509167802Sjkim { 510167802Sjkim /* This NamePath has no args, assume it is an integer */ 511167802Sjkim 512198237Sjkim AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); 513167802Sjkim return (AE_OK); 514167802Sjkim } 515167802Sjkim 516167802Sjkim ArgCount = AcpiDmInspectPossibleArgs (2, 1, NextOp); 517167802Sjkim if (ArgCount <= 1) 518167802Sjkim { 519167802Sjkim /* One Arg means this is just a Store(Name,Target) */ 520167802Sjkim 521198237Sjkim AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); 522167802Sjkim return (AE_OK); 523167802Sjkim } 524167802Sjkim 525198237Sjkim AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount); 526167802Sjkim } 527167802Sjkim break; 528167802Sjkim 529167802Sjkim case AML_INT_NAMEPATH_OP: 530167802Sjkim 531167802Sjkim /* Must examine parent to see if this namepath is an argument */ 532167802Sjkim 533167802Sjkim ParentOp = Op->Common.Parent; 534167802Sjkim OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode); 535167802Sjkim 536167802Sjkim if ((OpInfo->Class != AML_CLASS_EXECUTE) && 537167802Sjkim (OpInfo->Class != AML_CLASS_CREATE) && 538235945Sjkim (OpInfo->ObjectType != ACPI_TYPE_LOCAL_ALIAS) && 539167802Sjkim (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) && 540167802Sjkim !Op->Common.Node) 541167802Sjkim { 542167802Sjkim ArgCount = AcpiDmInspectPossibleArgs (0, 0, Op->Common.Next); 543167802Sjkim 544167802Sjkim /* 545167802Sjkim * Check if namepath is a predicate for if/while or lone parameter to 546167802Sjkim * a return. 547167802Sjkim */ 548167802Sjkim if (ArgCount == 0) 549167802Sjkim { 550167802Sjkim if (((ParentOp->Common.AmlOpcode == AML_IF_OP) || 551167802Sjkim (ParentOp->Common.AmlOpcode == AML_WHILE_OP) || 552167802Sjkim (ParentOp->Common.AmlOpcode == AML_RETURN_OP)) && 553167802Sjkim 554167802Sjkim /* And namepath is the first argument */ 555167802Sjkim (ParentOp->Common.Value.Arg == Op)) 556167802Sjkim { 557198237Sjkim AcpiDmAddToExternalList (Op, Op->Common.Value.String, ACPI_TYPE_INTEGER, 0); 558167802Sjkim break; 559167802Sjkim } 560167802Sjkim } 561167802Sjkim 562167802Sjkim /* 563167802Sjkim * This is a standalone namestring (not a parameter to another 564167802Sjkim * operator) - it *must* be a method invocation, nothing else is 565167802Sjkim * grammatically possible. 566167802Sjkim */ 567198237Sjkim AcpiDmAddToExternalList (Op, Op->Common.Value.String, ACPI_TYPE_METHOD, ArgCount); 568167802Sjkim 569167802Sjkim } 570167802Sjkim break; 571193529Sjkim 572193529Sjkim default: 573250838Sjkim 574193529Sjkim break; 575167802Sjkim } 576167802Sjkim 577167802Sjkim return (AE_OK); 578167802Sjkim} 579167802Sjkim 580167802Sjkim 581167802Sjkim/******************************************************************************* 582167802Sjkim * 583167802Sjkim * FUNCTION: AcpiDmLoadDescendingOp 584167802Sjkim * 585167802Sjkim * PARAMETERS: ASL_WALK_CALLBACK 586167802Sjkim * 587167802Sjkim * RETURN: Status 588167802Sjkim * 589167802Sjkim * DESCRIPTION: Descending handler for namespace control method object load 590167802Sjkim * 591167802Sjkim ******************************************************************************/ 592167802Sjkim 593167802Sjkimstatic ACPI_STATUS 594167802SjkimAcpiDmLoadDescendingOp ( 595167802Sjkim ACPI_PARSE_OBJECT *Op, 596167802Sjkim UINT32 Level, 597167802Sjkim void *Context) 598167802Sjkim{ 599167802Sjkim ACPI_OP_WALK_INFO *Info = Context; 600167802Sjkim const ACPI_OPCODE_INFO *OpInfo; 601167802Sjkim ACPI_WALK_STATE *WalkState; 602167802Sjkim ACPI_OBJECT_TYPE ObjectType; 603167802Sjkim ACPI_STATUS Status; 604167802Sjkim char *Path = NULL; 605167802Sjkim ACPI_PARSE_OBJECT *NextOp; 606167802Sjkim ACPI_NAMESPACE_NODE *Node; 607193529Sjkim char FieldPath[5]; 608193529Sjkim BOOLEAN PreDefined = FALSE; 609193529Sjkim UINT8 PreDefineIndex = 0; 610167802Sjkim 611167802Sjkim 612167802Sjkim WalkState = Info->WalkState; 613167802Sjkim OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 614167802Sjkim ObjectType = OpInfo->ObjectType; 615167802Sjkim ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 616167802Sjkim 617167802Sjkim /* Only interested in operators that create new names */ 618167802Sjkim 619167802Sjkim if (!(OpInfo->Flags & AML_NAMED) && 620167802Sjkim !(OpInfo->Flags & AML_CREATE)) 621167802Sjkim { 622167802Sjkim goto Exit; 623167802Sjkim } 624167802Sjkim 625167802Sjkim /* Get the NamePath from the appropriate place */ 626167802Sjkim 627167802Sjkim if (OpInfo->Flags & AML_NAMED) 628167802Sjkim { 629167802Sjkim /* For all named operators, get the new name */ 630167802Sjkim 631167802Sjkim Path = (char *) Op->Named.Path; 632193529Sjkim 633193529Sjkim if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP) 634193529Sjkim { 635193529Sjkim *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name; 636193529Sjkim FieldPath[4] = 0; 637193529Sjkim Path = FieldPath; 638193529Sjkim } 639167802Sjkim } 640167802Sjkim else if (OpInfo->Flags & AML_CREATE) 641167802Sjkim { 642167802Sjkim /* New name is the last child */ 643167802Sjkim 644167802Sjkim NextOp = Op->Common.Value.Arg; 645167802Sjkim 646167802Sjkim while (NextOp->Common.Next) 647167802Sjkim { 648167802Sjkim NextOp = NextOp->Common.Next; 649167802Sjkim } 650167802Sjkim Path = NextOp->Common.Value.String; 651167802Sjkim } 652167802Sjkim 653167802Sjkim if (!Path) 654167802Sjkim { 655167802Sjkim goto Exit; 656167802Sjkim } 657167802Sjkim 658167802Sjkim /* Insert the name into the namespace */ 659167802Sjkim 660167802Sjkim Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, 661167802Sjkim ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE, 662167802Sjkim WalkState, &Node); 663167802Sjkim 664167802Sjkim Op->Common.Node = Node; 665167802Sjkim 666193529Sjkim if (ACPI_SUCCESS (Status)) 667193529Sjkim { 668193529Sjkim /* Check if it's a predefined node */ 669167802Sjkim 670193529Sjkim while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name) 671193529Sjkim { 672241973Sjkim if (ACPI_COMPARE_NAME (Node->Name.Ascii, 673241973Sjkim AcpiGbl_PreDefinedNames[PreDefineIndex].Name)) 674193529Sjkim { 675193529Sjkim PreDefined = TRUE; 676193529Sjkim break; 677193529Sjkim } 678193529Sjkim 679193529Sjkim PreDefineIndex++; 680193529Sjkim } 681193529Sjkim 682193529Sjkim /* 683193529Sjkim * Set node owner id if it satisfies all the following conditions: 684193529Sjkim * 1) Not a predefined node, _SB_ etc 685193529Sjkim * 2) Not the root node 686193529Sjkim * 3) Not a node created by Scope 687193529Sjkim */ 688193529Sjkim 689193529Sjkim if (!PreDefined && Node != AcpiGbl_RootNode && 690193529Sjkim Op->Common.AmlOpcode != AML_SCOPE_OP) 691193529Sjkim { 692193529Sjkim Node->OwnerId = WalkState->OwnerId; 693193529Sjkim } 694193529Sjkim } 695193529Sjkim 696193529Sjkim 697167802SjkimExit: 698167802Sjkim 699167802Sjkim if (AcpiNsOpensScope (ObjectType)) 700167802Sjkim { 701167802Sjkim if (Op->Common.Node) 702167802Sjkim { 703167802Sjkim Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState); 704167802Sjkim if (ACPI_FAILURE (Status)) 705167802Sjkim { 706167802Sjkim return (Status); 707167802Sjkim } 708167802Sjkim } 709167802Sjkim } 710167802Sjkim 711167802Sjkim return (AE_OK); 712167802Sjkim} 713167802Sjkim 714167802Sjkim 715167802Sjkim/******************************************************************************* 716167802Sjkim * 717167802Sjkim * FUNCTION: AcpiDmXrefDescendingOp 718167802Sjkim * 719167802Sjkim * PARAMETERS: ASL_WALK_CALLBACK 720167802Sjkim * 721167802Sjkim * RETURN: Status 722167802Sjkim * 723167802Sjkim * DESCRIPTION: Descending handler for namespace cross reference 724167802Sjkim * 725167802Sjkim ******************************************************************************/ 726167802Sjkim 727167802Sjkimstatic ACPI_STATUS 728167802SjkimAcpiDmXrefDescendingOp ( 729167802Sjkim ACPI_PARSE_OBJECT *Op, 730167802Sjkim UINT32 Level, 731167802Sjkim void *Context) 732167802Sjkim{ 733167802Sjkim ACPI_OP_WALK_INFO *Info = Context; 734167802Sjkim const ACPI_OPCODE_INFO *OpInfo; 735167802Sjkim ACPI_WALK_STATE *WalkState; 736167802Sjkim ACPI_OBJECT_TYPE ObjectType; 737193529Sjkim ACPI_OBJECT_TYPE ObjectType2; 738167802Sjkim ACPI_STATUS Status; 739167802Sjkim char *Path = NULL; 740167802Sjkim ACPI_PARSE_OBJECT *NextOp; 741167802Sjkim ACPI_NAMESPACE_NODE *Node; 742193529Sjkim ACPI_OPERAND_OBJECT *Object; 743212761Sjkim UINT32 ParamCount = 0; 744167802Sjkim 745167802Sjkim 746167802Sjkim WalkState = Info->WalkState; 747167802Sjkim OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 748167802Sjkim ObjectType = OpInfo->ObjectType; 749167802Sjkim ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 750167802Sjkim 751167802Sjkim if ((!(OpInfo->Flags & AML_NAMED)) && 752167802Sjkim (!(OpInfo->Flags & AML_CREATE)) && 753167802Sjkim (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP)) 754167802Sjkim { 755167802Sjkim goto Exit; 756167802Sjkim } 757167802Sjkim 758167802Sjkim /* Get the NamePath from the appropriate place */ 759167802Sjkim 760167802Sjkim if (OpInfo->Flags & AML_NAMED) 761167802Sjkim { 762235945Sjkim /* 763235945Sjkim * Only these two operators (Alias, Scope) refer to an existing 764235945Sjkim * name, it is the first argument 765235945Sjkim */ 766235945Sjkim if (Op->Common.AmlOpcode == AML_ALIAS_OP) 767167802Sjkim { 768235945Sjkim ObjectType = ACPI_TYPE_ANY; 769235945Sjkim 770235945Sjkim NextOp = Op->Common.Value.Arg; 771235945Sjkim NextOp = NextOp->Common.Value.Arg; 772235945Sjkim if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) 773235945Sjkim { 774235945Sjkim Path = NextOp->Common.Value.String; 775235945Sjkim } 776235945Sjkim } 777235945Sjkim else if (Op->Common.AmlOpcode == AML_SCOPE_OP) 778235945Sjkim { 779167802Sjkim Path = (char *) Op->Named.Path; 780167802Sjkim } 781167802Sjkim } 782167802Sjkim else if (OpInfo->Flags & AML_CREATE) 783167802Sjkim { 784167802Sjkim /* Referenced Buffer Name is the first child */ 785167802Sjkim 786235945Sjkim ObjectType = ACPI_TYPE_BUFFER; /* Change from TYPE_BUFFER_FIELD */ 787235945Sjkim 788167802Sjkim NextOp = Op->Common.Value.Arg; 789167802Sjkim if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) 790167802Sjkim { 791167802Sjkim Path = NextOp->Common.Value.String; 792167802Sjkim } 793167802Sjkim } 794167802Sjkim else 795167802Sjkim { 796167802Sjkim Path = Op->Common.Value.String; 797167802Sjkim } 798167802Sjkim 799167802Sjkim if (!Path) 800167802Sjkim { 801167802Sjkim goto Exit; 802167802Sjkim } 803167802Sjkim 804167802Sjkim /* 805241973Sjkim * Lookup the name in the namespace. Name must exist at this point, or it 806167802Sjkim * is an invalid reference. 807167802Sjkim * 808167802Sjkim * The namespace is also used as a lookup table for references to resource 809167802Sjkim * descriptors and the fields within them. 810167802Sjkim */ 811167802Sjkim Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, 812167802Sjkim ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 813167802Sjkim WalkState, &Node); 814235945Sjkim if (ACPI_SUCCESS (Status) && (Node->Flags & ANOBJ_IS_EXTERNAL)) 815235945Sjkim { 816235945Sjkim Status = AE_NOT_FOUND; 817235945Sjkim } 818235945Sjkim 819167802Sjkim if (ACPI_FAILURE (Status)) 820167802Sjkim { 821167802Sjkim if (Status == AE_NOT_FOUND) 822167802Sjkim { 823198237Sjkim AcpiDmAddToExternalList (Op, Path, (UINT8) ObjectType, 0); 824167802Sjkim 825167802Sjkim /* 826167802Sjkim * We could install this into the namespace, but we catch duplicate 827167802Sjkim * externals when they are added to the list. 828167802Sjkim */ 829167802Sjkim#if 0 830167802Sjkim Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, 831167802Sjkim ACPI_IMODE_LOAD_PASS1, ACPI_NS_DONT_OPEN_SCOPE, 832167802Sjkim WalkState, &Node); 833167802Sjkim#endif 834167802Sjkim } 835167802Sjkim } 836193529Sjkim 837193529Sjkim /* 838193529Sjkim * Found the node in external table, add it to external list 839193529Sjkim * Node->OwnerId == 0 indicates built-in ACPI Names, _OS_ etc 840193529Sjkim */ 841193529Sjkim else if (Node->OwnerId && WalkState->OwnerId != Node->OwnerId) 842193529Sjkim { 843193529Sjkim ObjectType2 = ObjectType; 844193529Sjkim 845193529Sjkim Object = AcpiNsGetAttachedObject (Node); 846193529Sjkim if (Object) 847193529Sjkim { 848193529Sjkim ObjectType2 = Object->Common.Type; 849212761Sjkim if (ObjectType2 == ACPI_TYPE_METHOD) 850212761Sjkim { 851212761Sjkim ParamCount = Object->Method.ParamCount; 852212761Sjkim } 853193529Sjkim } 854193529Sjkim 855246849Sjkim AcpiDmAddToExternalList (Op, Path, (UINT8) ObjectType2, ParamCount | 0x80); 856193529Sjkim Op->Common.Node = Node; 857193529Sjkim } 858167802Sjkim else 859167802Sjkim { 860167802Sjkim Op->Common.Node = Node; 861167802Sjkim } 862167802Sjkim 863167802Sjkim 864167802SjkimExit: 865167802Sjkim /* Open new scope if necessary */ 866167802Sjkim 867167802Sjkim if (AcpiNsOpensScope (ObjectType)) 868167802Sjkim { 869167802Sjkim if (Op->Common.Node) 870167802Sjkim { 871167802Sjkim Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState); 872167802Sjkim if (ACPI_FAILURE (Status)) 873167802Sjkim { 874167802Sjkim return (Status); 875167802Sjkim } 876167802Sjkim } 877167802Sjkim } 878167802Sjkim 879167802Sjkim return (AE_OK); 880167802Sjkim} 881167802Sjkim 882167802Sjkim 883167802Sjkim/******************************************************************************* 884167802Sjkim * 885167802Sjkim * FUNCTION: AcpiDmResourceDescendingOp 886167802Sjkim * 887167802Sjkim * PARAMETERS: ASL_WALK_CALLBACK 888167802Sjkim * 889167802Sjkim * RETURN: None 890167802Sjkim * 891167802Sjkim * DESCRIPTION: Process one parse op during symbolic resource index conversion. 892167802Sjkim * 893167802Sjkim ******************************************************************************/ 894167802Sjkim 895167802Sjkimstatic ACPI_STATUS 896167802SjkimAcpiDmResourceDescendingOp ( 897167802Sjkim ACPI_PARSE_OBJECT *Op, 898167802Sjkim UINT32 Level, 899167802Sjkim void *Context) 900167802Sjkim{ 901167802Sjkim ACPI_OP_WALK_INFO *Info = Context; 902167802Sjkim const ACPI_OPCODE_INFO *OpInfo; 903167802Sjkim ACPI_WALK_STATE *WalkState; 904167802Sjkim ACPI_OBJECT_TYPE ObjectType; 905167802Sjkim ACPI_STATUS Status; 906167802Sjkim 907167802Sjkim 908167802Sjkim WalkState = Info->WalkState; 909167802Sjkim OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 910167802Sjkim 911167802Sjkim /* Open new scope if necessary */ 912167802Sjkim 913167802Sjkim ObjectType = OpInfo->ObjectType; 914167802Sjkim if (AcpiNsOpensScope (ObjectType)) 915167802Sjkim { 916167802Sjkim if (Op->Common.Node) 917167802Sjkim { 918167802Sjkim 919167802Sjkim Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState); 920167802Sjkim if (ACPI_FAILURE (Status)) 921167802Sjkim { 922167802Sjkim return (Status); 923167802Sjkim } 924167802Sjkim } 925167802Sjkim } 926167802Sjkim 927167802Sjkim /* 928167802Sjkim * Check if this operator contains a reference to a resource descriptor. 929167802Sjkim * If so, convert the reference into a symbolic reference. 930167802Sjkim */ 931167802Sjkim AcpiDmCheckResourceReference (Op, WalkState); 932167802Sjkim return (AE_OK); 933167802Sjkim} 934167802Sjkim 935167802Sjkim 936167802Sjkim/******************************************************************************* 937167802Sjkim * 938167802Sjkim * FUNCTION: AcpiDmCommonAscendingOp 939167802Sjkim * 940167802Sjkim * PARAMETERS: ASL_WALK_CALLBACK 941167802Sjkim * 942167802Sjkim * RETURN: None 943167802Sjkim * 944167802Sjkim * DESCRIPTION: Ascending handler for combined parse/namespace walks. Closes 945167802Sjkim * scope if necessary. 946167802Sjkim * 947167802Sjkim ******************************************************************************/ 948167802Sjkim 949167802Sjkimstatic ACPI_STATUS 950167802SjkimAcpiDmCommonAscendingOp ( 951167802Sjkim ACPI_PARSE_OBJECT *Op, 952167802Sjkim UINT32 Level, 953167802Sjkim void *Context) 954167802Sjkim{ 955167802Sjkim ACPI_OP_WALK_INFO *Info = Context; 956167802Sjkim const ACPI_OPCODE_INFO *OpInfo; 957167802Sjkim ACPI_OBJECT_TYPE ObjectType; 958167802Sjkim 959167802Sjkim 960167802Sjkim /* Close scope if necessary */ 961167802Sjkim 962167802Sjkim OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 963167802Sjkim ObjectType = OpInfo->ObjectType; 964167802Sjkim ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); 965167802Sjkim 966167802Sjkim if (AcpiNsOpensScope (ObjectType)) 967167802Sjkim { 968167802Sjkim (void) AcpiDsScopeStackPop (Info->WalkState); 969167802Sjkim } 970167802Sjkim 971167802Sjkim return (AE_OK); 972167802Sjkim} 973167802Sjkim 974167802Sjkim 975167802Sjkim/******************************************************************************* 976167802Sjkim * 977167802Sjkim * FUNCTION: AcpiDmInspectPossibleArgs 978167802Sjkim * 979167802Sjkim * PARAMETERS: CurrentOpArgCount - Which arg of the current op was the 980167802Sjkim * possible method invocation found 981167802Sjkim * TargetCount - Number of targets (0,1,2) for this op 982167802Sjkim * Op - Parse op 983167802Sjkim * 984167802Sjkim * RETURN: Status 985167802Sjkim * 986167802Sjkim * DESCRIPTION: Examine following args and next ops for possible arguments 987167802Sjkim * for an unrecognized method invocation. 988167802Sjkim * 989167802Sjkim ******************************************************************************/ 990167802Sjkim 991167802Sjkimstatic UINT32 992167802SjkimAcpiDmInspectPossibleArgs ( 993167802Sjkim UINT32 CurrentOpArgCount, 994167802Sjkim UINT32 TargetCount, 995167802Sjkim ACPI_PARSE_OBJECT *Op) 996167802Sjkim{ 997167802Sjkim const ACPI_OPCODE_INFO *OpInfo; 998167802Sjkim UINT32 i; 999167802Sjkim UINT32 Last = 0; 1000167802Sjkim UINT32 Lookahead; 1001167802Sjkim 1002167802Sjkim 1003167802Sjkim Lookahead = (ACPI_METHOD_NUM_ARGS + TargetCount) - CurrentOpArgCount; 1004167802Sjkim 1005167802Sjkim /* Lookahead for the maximum number of possible arguments */ 1006167802Sjkim 1007167802Sjkim for (i = 0; i < Lookahead; i++) 1008167802Sjkim { 1009167802Sjkim if (!Op) 1010167802Sjkim { 1011167802Sjkim break; 1012167802Sjkim } 1013167802Sjkim 1014167802Sjkim OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 1015167802Sjkim 1016167802Sjkim /* 1017167802Sjkim * Any one of these operators is "very probably" not a method arg 1018167802Sjkim */ 1019167802Sjkim if ((Op->Common.AmlOpcode == AML_STORE_OP) || 1020167802Sjkim (Op->Common.AmlOpcode == AML_NOTIFY_OP)) 1021167802Sjkim { 1022167802Sjkim break; 1023167802Sjkim } 1024167802Sjkim 1025167802Sjkim if ((OpInfo->Class != AML_CLASS_EXECUTE) && 1026167802Sjkim (OpInfo->Class != AML_CLASS_CONTROL)) 1027167802Sjkim { 1028167802Sjkim Last = i+1; 1029167802Sjkim } 1030167802Sjkim 1031167802Sjkim Op = Op->Common.Next; 1032167802Sjkim } 1033167802Sjkim 1034167802Sjkim return (Last); 1035167802Sjkim} 1036