1118611Snjl/****************************************************************************** 2118611Snjl * 3118611Snjl * Module Name: asltree - parse tree management 4118611Snjl * 5118611Snjl *****************************************************************************/ 6118611Snjl 7217365Sjkim/* 8245582Sjkim * Copyright (C) 2000 - 2013, 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 44118611Snjl 45151937Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 46118611Snjl#include "aslcompiler.y.h" 47228110Sjkim#include <contrib/dev/acpica/include/acapps.h> 48218590Sjkim#include <time.h> 49118611Snjl 50118611Snjl#define _COMPONENT ACPI_COMPILER 51118611Snjl ACPI_MODULE_NAME ("asltree") 52118611Snjl 53151937Sjkim/* Local prototypes */ 54118611Snjl 55151937Sjkimstatic ACPI_PARSE_OBJECT * 56151937SjkimTrGetNextNode ( 57151937Sjkim void); 58151937Sjkim 59151937Sjkimstatic char * 60151937SjkimTrGetNodeFlagName ( 61151937Sjkim UINT32 Flags); 62151937Sjkim 63151937Sjkim 64118611Snjl/******************************************************************************* 65118611Snjl * 66118611Snjl * FUNCTION: TrGetNextNode 67118611Snjl * 68118611Snjl * PARAMETERS: None 69118611Snjl * 70239340Sjkim * RETURN: New parse node. Aborts on allocation failure 71118611Snjl * 72239340Sjkim * DESCRIPTION: Allocate a new parse node for the parse tree. Bypass the local 73118611Snjl * dynamic memory manager for performance reasons (This has a 74118611Snjl * major impact on the speed of the compiler.) 75118611Snjl * 76118611Snjl ******************************************************************************/ 77118611Snjl 78151937Sjkimstatic ACPI_PARSE_OBJECT * 79151937SjkimTrGetNextNode ( 80151937Sjkim void) 81118611Snjl{ 82118611Snjl 83118611Snjl if (Gbl_NodeCacheNext >= Gbl_NodeCacheLast) 84118611Snjl { 85151937Sjkim Gbl_NodeCacheNext = UtLocalCalloc (sizeof (ACPI_PARSE_OBJECT) * 86151937Sjkim ASL_NODE_CACHE_SIZE); 87118611Snjl Gbl_NodeCacheLast = Gbl_NodeCacheNext + ASL_NODE_CACHE_SIZE; 88118611Snjl } 89118611Snjl 90118611Snjl return (Gbl_NodeCacheNext++); 91118611Snjl} 92118611Snjl 93118611Snjl 94118611Snjl/******************************************************************************* 95118611Snjl * 96118611Snjl * FUNCTION: TrAllocateNode 97118611Snjl * 98118611Snjl * PARAMETERS: ParseOpcode - Opcode to be assigned to the node 99118611Snjl * 100239340Sjkim * RETURN: New parse node. Aborts on allocation failure 101118611Snjl * 102118611Snjl * DESCRIPTION: Allocate and initialize a new parse node for the parse tree 103118611Snjl * 104118611Snjl ******************************************************************************/ 105118611Snjl 106118611SnjlACPI_PARSE_OBJECT * 107118611SnjlTrAllocateNode ( 108118611Snjl UINT32 ParseOpcode) 109118611Snjl{ 110118611Snjl ACPI_PARSE_OBJECT *Op; 111118611Snjl 112118611Snjl 113118611Snjl Op = TrGetNextNode (); 114118611Snjl 115118611Snjl Op->Asl.ParseOpcode = (UINT16) ParseOpcode; 116118611Snjl Op->Asl.Filename = Gbl_Files[ASL_FILE_INPUT].Filename; 117118611Snjl Op->Asl.LineNumber = Gbl_CurrentLineNumber; 118118611Snjl Op->Asl.LogicalLineNumber = Gbl_LogicalLineNumber; 119118611Snjl Op->Asl.LogicalByteOffset = Gbl_CurrentLineOffset; 120118611Snjl Op->Asl.Column = Gbl_CurrentColumn; 121118611Snjl 122118611Snjl UtSetParseOpName (Op); 123241973Sjkim return (Op); 124118611Snjl} 125118611Snjl 126118611Snjl 127118611Snjl/******************************************************************************* 128118611Snjl * 129118611Snjl * FUNCTION: TrReleaseNode 130118611Snjl * 131118611Snjl * PARAMETERS: Op - Op to be released 132118611Snjl * 133118611Snjl * RETURN: None 134118611Snjl * 135239340Sjkim * DESCRIPTION: "release" a node. In truth, nothing is done since the node 136118611Snjl * is part of a larger buffer 137118611Snjl * 138118611Snjl ******************************************************************************/ 139118611Snjl 140118611Snjlvoid 141118611SnjlTrReleaseNode ( 142118611Snjl ACPI_PARSE_OBJECT *Op) 143118611Snjl{ 144118611Snjl 145118611Snjl return; 146118611Snjl} 147118611Snjl 148118611Snjl 149118611Snjl/******************************************************************************* 150118611Snjl * 151118611Snjl * FUNCTION: TrUpdateNode 152118611Snjl * 153118611Snjl * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 154118611Snjl * Op - An existing parse node 155118611Snjl * 156118611Snjl * RETURN: The updated node 157118611Snjl * 158239340Sjkim * DESCRIPTION: Change the parse opcode assigned to a node. Usually used to 159118611Snjl * change an opcode to DEFAULT_ARG so that the node is ignored 160239340Sjkim * during the code generation. Also used to set generic integers 161118611Snjl * to a specific size (8, 16, 32, or 64 bits) 162118611Snjl * 163118611Snjl ******************************************************************************/ 164118611Snjl 165118611SnjlACPI_PARSE_OBJECT * 166118611SnjlTrUpdateNode ( 167118611Snjl UINT32 ParseOpcode, 168118611Snjl ACPI_PARSE_OBJECT *Op) 169118611Snjl{ 170118611Snjl 171118611Snjl if (!Op) 172118611Snjl { 173241973Sjkim return (NULL); 174118611Snjl } 175118611Snjl 176118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 177118611Snjl "\nUpdateNode: Old - %s, New - %s\n\n", 178118611Snjl UtGetOpName (Op->Asl.ParseOpcode), 179118611Snjl UtGetOpName (ParseOpcode)); 180118611Snjl 181118611Snjl /* Assign new opcode and name */ 182118611Snjl 183118611Snjl if (Op->Asl.ParseOpcode == PARSEOP_ONES) 184118611Snjl { 185118611Snjl switch (ParseOpcode) 186118611Snjl { 187118611Snjl case PARSEOP_BYTECONST: 188250838Sjkim 189239340Sjkim Op->Asl.Value.Integer = ACPI_UINT8_MAX; 190118611Snjl break; 191118611Snjl 192118611Snjl case PARSEOP_WORDCONST: 193250838Sjkim 194239340Sjkim Op->Asl.Value.Integer = ACPI_UINT16_MAX; 195118611Snjl break; 196118611Snjl 197118611Snjl case PARSEOP_DWORDCONST: 198250838Sjkim 199239340Sjkim Op->Asl.Value.Integer = ACPI_UINT32_MAX; 200118611Snjl break; 201118611Snjl 202239340Sjkim /* Don't need to do the QWORD case */ 203239340Sjkim 204118611Snjl default: 205250838Sjkim 206239340Sjkim /* Don't care about others */ 207118611Snjl break; 208118611Snjl } 209118611Snjl } 210118611Snjl 211118611Snjl Op->Asl.ParseOpcode = (UINT16) ParseOpcode; 212118611Snjl UtSetParseOpName (Op); 213118611Snjl 214118611Snjl /* 215118611Snjl * For the BYTE, WORD, and DWORD constants, make sure that the integer 216118611Snjl * that was passed in will actually fit into the data type 217118611Snjl */ 218118611Snjl switch (ParseOpcode) 219118611Snjl { 220118611Snjl case PARSEOP_BYTECONST: 221250838Sjkim 222239340Sjkim UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX); 223239340Sjkim Op->Asl.Value.Integer &= ACPI_UINT8_MAX; 224118611Snjl break; 225118611Snjl 226118611Snjl case PARSEOP_WORDCONST: 227250838Sjkim 228239340Sjkim UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX); 229239340Sjkim Op->Asl.Value.Integer &= ACPI_UINT16_MAX; 230118611Snjl break; 231118611Snjl 232118611Snjl case PARSEOP_DWORDCONST: 233250838Sjkim 234239340Sjkim UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX); 235239340Sjkim Op->Asl.Value.Integer &= ACPI_UINT32_MAX; 236118611Snjl break; 237118611Snjl 238118611Snjl default: 239250838Sjkim 240118611Snjl /* Don't care about others, don't need to check QWORD */ 241250838Sjkim 242118611Snjl break; 243118611Snjl } 244118611Snjl 245241973Sjkim return (Op); 246118611Snjl} 247118611Snjl 248118611Snjl 249118611Snjl/******************************************************************************* 250118611Snjl * 251118611Snjl * FUNCTION: TrGetNodeFlagName 252118611Snjl * 253118611Snjl * PARAMETERS: Flags - Flags word to be decoded 254118611Snjl * 255151937Sjkim * RETURN: Name string. Always returns a valid string pointer. 256118611Snjl * 257118611Snjl * DESCRIPTION: Decode a flags word 258118611Snjl * 259118611Snjl ******************************************************************************/ 260118611Snjl 261151937Sjkimstatic char * 262118611SnjlTrGetNodeFlagName ( 263118611Snjl UINT32 Flags) 264118611Snjl{ 265118611Snjl 266118611Snjl switch (Flags) 267118611Snjl { 268118611Snjl case NODE_VISITED: 269250838Sjkim 270118611Snjl return ("NODE_VISITED"); 271118611Snjl 272118611Snjl case NODE_AML_PACKAGE: 273250838Sjkim 274118611Snjl return ("NODE_AML_PACKAGE"); 275118611Snjl 276118611Snjl case NODE_IS_TARGET: 277250838Sjkim 278118611Snjl return ("NODE_IS_TARGET"); 279118611Snjl 280118611Snjl case NODE_IS_RESOURCE_DESC: 281250838Sjkim 282118611Snjl return ("NODE_IS_RESOURCE_DESC"); 283118611Snjl 284118611Snjl case NODE_IS_RESOURCE_FIELD: 285250838Sjkim 286118611Snjl return ("NODE_IS_RESOURCE_FIELD"); 287118611Snjl 288118611Snjl case NODE_HAS_NO_EXIT: 289250838Sjkim 290118611Snjl return ("NODE_HAS_NO_EXIT"); 291118611Snjl 292118611Snjl case NODE_IF_HAS_NO_EXIT: 293250838Sjkim 294118611Snjl return ("NODE_IF_HAS_NO_EXIT"); 295118611Snjl 296118611Snjl case NODE_NAME_INTERNALIZED: 297250838Sjkim 298118611Snjl return ("NODE_NAME_INTERNALIZED"); 299118611Snjl 300118611Snjl case NODE_METHOD_NO_RETVAL: 301250838Sjkim 302118611Snjl return ("NODE_METHOD_NO_RETVAL"); 303118611Snjl 304118611Snjl case NODE_METHOD_SOME_NO_RETVAL: 305250838Sjkim 306118611Snjl return ("NODE_METHOD_SOME_NO_RETVAL"); 307118611Snjl 308118611Snjl case NODE_RESULT_NOT_USED: 309250838Sjkim 310118611Snjl return ("NODE_RESULT_NOT_USED"); 311118611Snjl 312118611Snjl case NODE_METHOD_TYPED: 313250838Sjkim 314118611Snjl return ("NODE_METHOD_TYPED"); 315118611Snjl 316118611Snjl case NODE_COMPILE_TIME_CONST: 317250838Sjkim 318118611Snjl return ("NODE_COMPILE_TIME_CONST"); 319118611Snjl 320118611Snjl case NODE_IS_TERM_ARG: 321250838Sjkim 322118611Snjl return ("NODE_IS_TERM_ARG"); 323118611Snjl 324118611Snjl case NODE_WAS_ONES_OP: 325250838Sjkim 326118611Snjl return ("NODE_WAS_ONES_OP"); 327118611Snjl 328118611Snjl case NODE_IS_NAME_DECLARATION: 329250838Sjkim 330118611Snjl return ("NODE_IS_NAME_DECLARATION"); 331118611Snjl 332118611Snjl default: 333250838Sjkim 334118611Snjl return ("Multiple Flags (or unknown flag) set"); 335118611Snjl } 336118611Snjl} 337118611Snjl 338118611Snjl 339118611Snjl/******************************************************************************* 340118611Snjl * 341118611Snjl * FUNCTION: TrSetNodeFlags 342118611Snjl * 343151937Sjkim * PARAMETERS: Op - An existing parse node 344118611Snjl * Flags - New flags word 345118611Snjl * 346151937Sjkim * RETURN: The updated parser op 347118611Snjl * 348239340Sjkim * DESCRIPTION: Set bits in the node flags word. Will not clear bits, only set 349118611Snjl * 350118611Snjl ******************************************************************************/ 351118611Snjl 352118611SnjlACPI_PARSE_OBJECT * 353118611SnjlTrSetNodeFlags ( 354118611Snjl ACPI_PARSE_OBJECT *Op, 355118611Snjl UINT32 Flags) 356118611Snjl{ 357118611Snjl 358118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 359151937Sjkim "\nSetNodeFlags: Op %p, %8.8X %s\n\n", Op, Flags, 360151937Sjkim TrGetNodeFlagName (Flags)); 361118611Snjl 362118611Snjl if (!Op) 363118611Snjl { 364241973Sjkim return (NULL); 365118611Snjl } 366118611Snjl 367118611Snjl Op->Asl.CompileFlags |= Flags; 368239340Sjkim return (Op); 369239340Sjkim} 370118611Snjl 371239340Sjkim 372239340Sjkim/******************************************************************************* 373239340Sjkim * 374239340Sjkim * FUNCTION: TrSetNodeAmlLength 375239340Sjkim * 376239340Sjkim * PARAMETERS: Op - An existing parse node 377239340Sjkim * Length - AML Length 378239340Sjkim * 379239340Sjkim * RETURN: The updated parser op 380239340Sjkim * 381239340Sjkim * DESCRIPTION: Set the AML Length in a node. Used by the parser to indicate 382239340Sjkim * the presence of a node that must be reduced to a fixed length 383239340Sjkim * constant. 384239340Sjkim * 385239340Sjkim ******************************************************************************/ 386239340Sjkim 387239340SjkimACPI_PARSE_OBJECT * 388239340SjkimTrSetNodeAmlLength ( 389239340Sjkim ACPI_PARSE_OBJECT *Op, 390239340Sjkim UINT32 Length) 391239340Sjkim{ 392239340Sjkim 393239340Sjkim DbgPrint (ASL_PARSE_OUTPUT, 394239340Sjkim "\nSetNodeAmlLength: Op %p, %8.8X\n", Op, Length); 395239340Sjkim 396239340Sjkim if (!Op) 397239340Sjkim { 398241973Sjkim return (NULL); 399239340Sjkim } 400239340Sjkim 401239340Sjkim Op->Asl.AmlLength = Length; 402239340Sjkim return (Op); 403118611Snjl} 404118611Snjl 405118611Snjl 406118611Snjl/******************************************************************************* 407118611Snjl * 408118611Snjl * FUNCTION: TrSetEndLineNumber 409118611Snjl * 410118611Snjl * PARAMETERS: Op - An existing parse node 411118611Snjl * 412118611Snjl * RETURN: None. 413118611Snjl * 414118611Snjl * DESCRIPTION: Set the ending line numbers (file line and logical line) of a 415118611Snjl * parse node to the current line numbers. 416118611Snjl * 417118611Snjl ******************************************************************************/ 418118611Snjl 419118611Snjlvoid 420118611SnjlTrSetEndLineNumber ( 421118611Snjl ACPI_PARSE_OBJECT *Op) 422118611Snjl{ 423118611Snjl 424118611Snjl /* If the end line # is already set, just return */ 425118611Snjl 426118611Snjl if (Op->Asl.EndLine) 427118611Snjl { 428118611Snjl return; 429118611Snjl } 430118611Snjl 431118611Snjl Op->Asl.EndLine = Gbl_CurrentLineNumber; 432118611Snjl Op->Asl.EndLogicalLine = Gbl_LogicalLineNumber; 433118611Snjl} 434118611Snjl 435118611Snjl 436118611Snjl/******************************************************************************* 437118611Snjl * 438118611Snjl * FUNCTION: TrCreateLeafNode 439118611Snjl * 440118611Snjl * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 441118611Snjl * 442239340Sjkim * RETURN: Pointer to the new node. Aborts on allocation failure 443118611Snjl * 444118611Snjl * DESCRIPTION: Create a simple leaf node (no children or peers, and no value 445118611Snjl * assigned to the node) 446118611Snjl * 447118611Snjl ******************************************************************************/ 448118611Snjl 449118611SnjlACPI_PARSE_OBJECT * 450118611SnjlTrCreateLeafNode ( 451118611Snjl UINT32 ParseOpcode) 452118611Snjl{ 453118611Snjl ACPI_PARSE_OBJECT *Op; 454118611Snjl 455118611Snjl 456118611Snjl Op = TrAllocateNode (ParseOpcode); 457118611Snjl 458118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 459209746Sjkim "\nCreateLeafNode Ln/Col %u/%u NewNode %p Op %s\n\n", 460167802Sjkim Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode)); 461118611Snjl 462241973Sjkim return (Op); 463118611Snjl} 464118611Snjl 465118611Snjl 466118611Snjl/******************************************************************************* 467118611Snjl * 468218590Sjkim * FUNCTION: TrCreateConstantLeafNode 469218590Sjkim * 470218590Sjkim * PARAMETERS: ParseOpcode - The constant opcode 471218590Sjkim * 472239340Sjkim * RETURN: Pointer to the new node. Aborts on allocation failure 473218590Sjkim * 474218590Sjkim * DESCRIPTION: Create a leaf node (no children or peers) for one of the 475218590Sjkim * special constants - __LINE__, __FILE__, and __DATE__. 476218590Sjkim * 477218590Sjkim * Note: An implemenation of __FUNC__ cannot happen here because we don't 478218590Sjkim * have a full parse tree at this time and cannot find the parent control 479218590Sjkim * method. If it is ever needed, __FUNC__ must be implemented later, after 480218590Sjkim * the parse tree has been fully constructed. 481218590Sjkim * 482218590Sjkim ******************************************************************************/ 483218590Sjkim 484218590SjkimACPI_PARSE_OBJECT * 485218590SjkimTrCreateConstantLeafNode ( 486218590Sjkim UINT32 ParseOpcode) 487218590Sjkim{ 488218590Sjkim ACPI_PARSE_OBJECT *Op = NULL; 489218590Sjkim time_t CurrentTime; 490218590Sjkim char *StaticTimeString; 491218590Sjkim char *TimeString; 492228110Sjkim char *Path; 493228110Sjkim char *Filename; 494218590Sjkim 495218590Sjkim 496218590Sjkim switch (ParseOpcode) 497218590Sjkim { 498218590Sjkim case PARSEOP___LINE__: 499250838Sjkim 500218590Sjkim Op = TrAllocateNode (PARSEOP_INTEGER); 501218590Sjkim Op->Asl.Value.Integer = Op->Asl.LineNumber; 502218590Sjkim break; 503218590Sjkim 504228110Sjkim case PARSEOP___PATH__: 505250838Sjkim 506218590Sjkim Op = TrAllocateNode (PARSEOP_STRING_LITERAL); 507218590Sjkim 508218590Sjkim /* Op.Asl.Filename contains the full pathname to the file */ 509218590Sjkim 510218590Sjkim Op->Asl.Value.String = Op->Asl.Filename; 511218590Sjkim break; 512218590Sjkim 513228110Sjkim case PARSEOP___FILE__: 514250838Sjkim 515218590Sjkim Op = TrAllocateNode (PARSEOP_STRING_LITERAL); 516218590Sjkim 517228110Sjkim /* Get the simple filename from the full path */ 518228110Sjkim 519228110Sjkim FlSplitInputPathname (Op->Asl.Filename, &Path, &Filename); 520228110Sjkim ACPI_FREE (Path); 521228110Sjkim Op->Asl.Value.String = Filename; 522228110Sjkim break; 523228110Sjkim 524228110Sjkim case PARSEOP___DATE__: 525250838Sjkim 526228110Sjkim Op = TrAllocateNode (PARSEOP_STRING_LITERAL); 527228110Sjkim 528218590Sjkim /* Get a copy of the current time */ 529218590Sjkim 530218590Sjkim CurrentTime = time (NULL); 531218590Sjkim StaticTimeString = ctime (&CurrentTime); 532218590Sjkim TimeString = UtLocalCalloc (strlen (StaticTimeString) + 1); 533218590Sjkim strcpy (TimeString, StaticTimeString); 534218590Sjkim 535218590Sjkim TimeString[strlen(TimeString) -1] = 0; /* Remove trailing newline */ 536218590Sjkim Op->Asl.Value.String = TimeString; 537218590Sjkim break; 538218590Sjkim 539218590Sjkim default: /* This would be an internal error */ 540250838Sjkim 541218590Sjkim return (NULL); 542218590Sjkim } 543218590Sjkim 544218590Sjkim DbgPrint (ASL_PARSE_OUTPUT, 545218590Sjkim "\nCreateConstantLeafNode Ln/Col %u/%u NewNode %p Op %s Value %8.8X%8.8X ", 546218590Sjkim Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode), 547218590Sjkim ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer)); 548218590Sjkim return (Op); 549218590Sjkim} 550218590Sjkim 551218590Sjkim 552218590Sjkim/******************************************************************************* 553218590Sjkim * 554118611Snjl * FUNCTION: TrCreateValuedLeafNode 555118611Snjl * 556118611Snjl * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 557118611Snjl * Value - Value to be assigned to the node 558118611Snjl * 559239340Sjkim * RETURN: Pointer to the new node. Aborts on allocation failure 560118611Snjl * 561118611Snjl * DESCRIPTION: Create a leaf node (no children or peers) with a value 562118611Snjl * assigned to it 563118611Snjl * 564118611Snjl ******************************************************************************/ 565118611Snjl 566118611SnjlACPI_PARSE_OBJECT * 567118611SnjlTrCreateValuedLeafNode ( 568118611Snjl UINT32 ParseOpcode, 569202771Sjkim UINT64 Value) 570118611Snjl{ 571118611Snjl ACPI_PARSE_OBJECT *Op; 572118611Snjl 573118611Snjl 574118611Snjl Op = TrAllocateNode (ParseOpcode); 575118611Snjl 576118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 577209746Sjkim "\nCreateValuedLeafNode Ln/Col %u/%u NewNode %p Op %s Value %8.8X%8.8X ", 578167802Sjkim Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode), 579123315Snjl ACPI_FORMAT_UINT64 (Value)); 580118611Snjl Op->Asl.Value.Integer = Value; 581118611Snjl 582118611Snjl switch (ParseOpcode) 583118611Snjl { 584118611Snjl case PARSEOP_STRING_LITERAL: 585250838Sjkim 586118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value); 587118611Snjl break; 588118611Snjl 589118611Snjl case PARSEOP_NAMESEG: 590250838Sjkim 591118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value); 592118611Snjl break; 593118611Snjl 594118611Snjl case PARSEOP_NAMESTRING: 595250838Sjkim 596118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value); 597118611Snjl break; 598118611Snjl 599118611Snjl case PARSEOP_EISAID: 600250838Sjkim 601118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value); 602118611Snjl break; 603118611Snjl 604118611Snjl case PARSEOP_METHOD: 605250838Sjkim 606118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "METHOD"); 607118611Snjl break; 608118611Snjl 609118611Snjl case PARSEOP_INTEGER: 610250838Sjkim 611118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "INTEGER"); 612118611Snjl break; 613118611Snjl 614118611Snjl default: 615250838Sjkim 616118611Snjl break; 617118611Snjl } 618118611Snjl 619118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 620241973Sjkim return (Op); 621118611Snjl} 622118611Snjl 623118611Snjl 624118611Snjl/******************************************************************************* 625118611Snjl * 626118611Snjl * FUNCTION: TrCreateNode 627118611Snjl * 628118611Snjl * PARAMETERS: ParseOpcode - Opcode to be assigned to the node 629118611Snjl * NumChildren - Number of children to follow 630118611Snjl * ... - A list of child nodes to link to the new 631239340Sjkim * node. NumChildren long. 632118611Snjl * 633239340Sjkim * RETURN: Pointer to the new node. Aborts on allocation failure 634118611Snjl * 635118611Snjl * DESCRIPTION: Create a new parse node and link together a list of child 636118611Snjl * nodes underneath the new node. 637118611Snjl * 638118611Snjl ******************************************************************************/ 639118611Snjl 640118611SnjlACPI_PARSE_OBJECT * 641118611SnjlTrCreateNode ( 642118611Snjl UINT32 ParseOpcode, 643118611Snjl UINT32 NumChildren, 644118611Snjl ...) 645118611Snjl{ 646118611Snjl ACPI_PARSE_OBJECT *Op; 647118611Snjl ACPI_PARSE_OBJECT *Child; 648118611Snjl ACPI_PARSE_OBJECT *PrevChild; 649118611Snjl va_list ap; 650118611Snjl UINT32 i; 651118611Snjl BOOLEAN FirstChild; 652118611Snjl 653118611Snjl 654118611Snjl va_start (ap, NumChildren); 655118611Snjl 656118611Snjl /* Allocate one new node */ 657118611Snjl 658118611Snjl Op = TrAllocateNode (ParseOpcode); 659118611Snjl 660118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 661209746Sjkim "\nCreateNode Ln/Col %u/%u NewParent %p Child %u Op %s ", 662167802Sjkim Op->Asl.LineNumber, Op->Asl.Column, Op, NumChildren, UtGetOpName(ParseOpcode)); 663118611Snjl 664118611Snjl /* Some extra debug output based on the parse opcode */ 665118611Snjl 666118611Snjl switch (ParseOpcode) 667118611Snjl { 668118611Snjl case PARSEOP_DEFINITIONBLOCK: 669250838Sjkim 670118611Snjl RootNode = Op; 671118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->"); 672118611Snjl break; 673118611Snjl 674118611Snjl case PARSEOP_OPERATIONREGION: 675250838Sjkim 676118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->"); 677118611Snjl break; 678118611Snjl 679118611Snjl case PARSEOP_OR: 680250838Sjkim 681118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OR->"); 682118611Snjl break; 683118611Snjl 684118611Snjl default: 685250838Sjkim 686118611Snjl /* Nothing to do for other opcodes */ 687250838Sjkim 688118611Snjl break; 689118611Snjl } 690118611Snjl 691118611Snjl /* Link the new node to its children */ 692118611Snjl 693118611Snjl PrevChild = NULL; 694118611Snjl FirstChild = TRUE; 695118611Snjl for (i = 0; i < NumChildren; i++) 696118611Snjl { 697118611Snjl /* Get the next child */ 698118611Snjl 699118611Snjl Child = va_arg (ap, ACPI_PARSE_OBJECT *); 700118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child); 701118611Snjl 702118611Snjl /* 703118611Snjl * If child is NULL, this means that an optional argument 704239340Sjkim * was omitted. We must create a placeholder with a special 705118611Snjl * opcode (DEFAULT_ARG) so that the code generator will know 706118611Snjl * that it must emit the correct default for this argument 707118611Snjl */ 708118611Snjl if (!Child) 709118611Snjl { 710118611Snjl Child = TrAllocateNode (PARSEOP_DEFAULT_ARG); 711118611Snjl } 712118611Snjl 713118611Snjl /* Link first child to parent */ 714118611Snjl 715118611Snjl if (FirstChild) 716118611Snjl { 717118611Snjl FirstChild = FALSE; 718118611Snjl Op->Asl.Child = Child; 719118611Snjl } 720118611Snjl 721118611Snjl /* Point all children to parent */ 722118611Snjl 723118611Snjl Child->Asl.Parent = Op; 724118611Snjl 725118611Snjl /* Link children in a peer list */ 726118611Snjl 727118611Snjl if (PrevChild) 728118611Snjl { 729118611Snjl PrevChild->Asl.Next = Child; 730118611Snjl }; 731118611Snjl 732118611Snjl /* 733118611Snjl * This child might be a list, point all nodes in the list 734118611Snjl * to the same parent 735118611Snjl */ 736118611Snjl while (Child->Asl.Next) 737118611Snjl { 738118611Snjl Child = Child->Asl.Next; 739118611Snjl Child->Asl.Parent = Op; 740118611Snjl } 741118611Snjl 742118611Snjl PrevChild = Child; 743118611Snjl } 744118611Snjl va_end(ap); 745118611Snjl 746118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 747241973Sjkim return (Op); 748118611Snjl} 749118611Snjl 750118611Snjl 751118611Snjl/******************************************************************************* 752118611Snjl * 753118611Snjl * FUNCTION: TrLinkChildren 754118611Snjl * 755118611Snjl * PARAMETERS: Op - An existing parse node 756118611Snjl * NumChildren - Number of children to follow 757118611Snjl * ... - A list of child nodes to link to the new 758239340Sjkim * node. NumChildren long. 759118611Snjl * 760118611Snjl * RETURN: The updated (linked) node 761118611Snjl * 762118611Snjl * DESCRIPTION: Link a group of nodes to an existing parse node 763118611Snjl * 764118611Snjl ******************************************************************************/ 765118611Snjl 766118611SnjlACPI_PARSE_OBJECT * 767118611SnjlTrLinkChildren ( 768118611Snjl ACPI_PARSE_OBJECT *Op, 769118611Snjl UINT32 NumChildren, 770118611Snjl ...) 771118611Snjl{ 772118611Snjl ACPI_PARSE_OBJECT *Child; 773118611Snjl ACPI_PARSE_OBJECT *PrevChild; 774118611Snjl va_list ap; 775118611Snjl UINT32 i; 776118611Snjl BOOLEAN FirstChild; 777118611Snjl 778118611Snjl 779118611Snjl va_start (ap, NumChildren); 780118611Snjl 781118611Snjl 782118611Snjl TrSetEndLineNumber (Op); 783118611Snjl 784118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 785209746Sjkim "\nLinkChildren Line [%u to %u] NewParent %p Child %u Op %s ", 786118611Snjl Op->Asl.LineNumber, Op->Asl.EndLine, 787118611Snjl Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode)); 788118611Snjl 789118611Snjl switch (Op->Asl.ParseOpcode) 790118611Snjl { 791118611Snjl case PARSEOP_DEFINITIONBLOCK: 792250838Sjkim 793118611Snjl RootNode = Op; 794118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->"); 795118611Snjl break; 796118611Snjl 797118611Snjl case PARSEOP_OPERATIONREGION: 798250838Sjkim 799118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->"); 800118611Snjl break; 801118611Snjl 802118611Snjl case PARSEOP_OR: 803250838Sjkim 804118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OR->"); 805118611Snjl break; 806118611Snjl 807118611Snjl default: 808250838Sjkim 809118611Snjl /* Nothing to do for other opcodes */ 810250838Sjkim 811118611Snjl break; 812118611Snjl } 813118611Snjl 814118611Snjl /* Link the new node to it's children */ 815118611Snjl 816118611Snjl PrevChild = NULL; 817118611Snjl FirstChild = TRUE; 818118611Snjl for (i = 0; i < NumChildren; i++) 819118611Snjl { 820118611Snjl Child = va_arg (ap, ACPI_PARSE_OBJECT *); 821118611Snjl 822118611Snjl if ((Child == PrevChild) && (Child != NULL)) 823118611Snjl { 824151937Sjkim AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child, 825151937Sjkim "Child node list invalid"); 826252279Sjkim va_end(ap); 827241973Sjkim return (Op); 828118611Snjl } 829118611Snjl 830118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child); 831118611Snjl 832118611Snjl /* 833118611Snjl * If child is NULL, this means that an optional argument 834239340Sjkim * was omitted. We must create a placeholder with a special 835118611Snjl * opcode (DEFAULT_ARG) so that the code generator will know 836118611Snjl * that it must emit the correct default for this argument 837118611Snjl */ 838118611Snjl if (!Child) 839118611Snjl { 840118611Snjl Child = TrAllocateNode (PARSEOP_DEFAULT_ARG); 841118611Snjl } 842118611Snjl 843118611Snjl /* Link first child to parent */ 844118611Snjl 845118611Snjl if (FirstChild) 846118611Snjl { 847118611Snjl FirstChild = FALSE; 848118611Snjl Op->Asl.Child = Child; 849118611Snjl } 850118611Snjl 851118611Snjl /* Point all children to parent */ 852118611Snjl 853118611Snjl Child->Asl.Parent = Op; 854118611Snjl 855118611Snjl /* Link children in a peer list */ 856118611Snjl 857118611Snjl if (PrevChild) 858118611Snjl { 859118611Snjl PrevChild->Asl.Next = Child; 860118611Snjl }; 861118611Snjl 862118611Snjl /* 863118611Snjl * This child might be a list, point all nodes in the list 864118611Snjl * to the same parent 865118611Snjl */ 866118611Snjl while (Child->Asl.Next) 867118611Snjl { 868118611Snjl Child = Child->Asl.Next; 869118611Snjl Child->Asl.Parent = Op; 870118611Snjl } 871118611Snjl PrevChild = Child; 872118611Snjl } 873252279Sjkim 874118611Snjl va_end(ap); 875118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 876241973Sjkim return (Op); 877118611Snjl} 878118611Snjl 879118611Snjl 880118611Snjl/******************************************************************************* 881118611Snjl * 882118611Snjl * FUNCTION: TrLinkPeerNode 883118611Snjl * 884118611Snjl * PARAMETERS: Op1 - First peer 885118611Snjl * Op2 - Second peer 886118611Snjl * 887118611Snjl * RETURN: Op1 or the non-null node. 888118611Snjl * 889239340Sjkim * DESCRIPTION: Link two nodes as peers. Handles cases where one peer is null. 890118611Snjl * 891118611Snjl ******************************************************************************/ 892118611Snjl 893118611SnjlACPI_PARSE_OBJECT * 894118611SnjlTrLinkPeerNode ( 895118611Snjl ACPI_PARSE_OBJECT *Op1, 896118611Snjl ACPI_PARSE_OBJECT *Op2) 897118611Snjl{ 898118611Snjl ACPI_PARSE_OBJECT *Next; 899118611Snjl 900118611Snjl 901118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 902118611Snjl "\nLinkPeerNode: 1=%p (%s), 2=%p (%s)\n\n", 903118611Snjl Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode) : NULL, 904118611Snjl Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode) : NULL); 905118611Snjl 906118611Snjl 907118611Snjl if ((!Op1) && (!Op2)) 908118611Snjl { 909118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null nodes!\n"); 910241973Sjkim return (Op1); 911118611Snjl } 912118611Snjl 913118611Snjl /* If one of the nodes is null, just return the non-null node */ 914118611Snjl 915118611Snjl if (!Op2) 916118611Snjl { 917241973Sjkim return (Op1); 918118611Snjl } 919118611Snjl 920118611Snjl if (!Op1) 921118611Snjl { 922241973Sjkim return (Op2); 923118611Snjl } 924118611Snjl 925118611Snjl if (Op1 == Op2) 926118611Snjl { 927118611Snjl DbgPrint (ASL_DEBUG_OUTPUT, 928151937Sjkim "\n\n************* Internal error, linking node to itself %p\n\n\n", 929151937Sjkim Op1); 930151937Sjkim AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1, 931151937Sjkim "Linking node to itself"); 932241973Sjkim return (Op1); 933118611Snjl } 934118611Snjl 935118611Snjl Op1->Asl.Parent = Op2->Asl.Parent; 936118611Snjl 937118611Snjl /* 938118611Snjl * Op 1 may already have a peer list (such as an IF/ELSE pair), 939118611Snjl * so we must walk to the end of the list and attach the new 940118611Snjl * peer at the end 941118611Snjl */ 942118611Snjl Next = Op1; 943118611Snjl while (Next->Asl.Next) 944118611Snjl { 945118611Snjl Next = Next->Asl.Next; 946118611Snjl } 947118611Snjl 948118611Snjl Next->Asl.Next = Op2; 949241973Sjkim return (Op1); 950118611Snjl} 951118611Snjl 952118611Snjl 953118611Snjl/******************************************************************************* 954118611Snjl * 955118611Snjl * FUNCTION: TrLinkPeerNodes 956118611Snjl * 957118611Snjl * PARAMETERS: NumPeers - The number of nodes in the list to follow 958118611Snjl * ... - A list of nodes to link together as peers 959118611Snjl * 960118611Snjl * RETURN: The first node in the list (head of the peer list) 961118611Snjl * 962118611Snjl * DESCRIPTION: Link together an arbitrary number of peer nodes. 963118611Snjl * 964118611Snjl ******************************************************************************/ 965118611Snjl 966118611SnjlACPI_PARSE_OBJECT * 967118611SnjlTrLinkPeerNodes ( 968118611Snjl UINT32 NumPeers, 969118611Snjl ...) 970118611Snjl{ 971118611Snjl ACPI_PARSE_OBJECT *This; 972118611Snjl ACPI_PARSE_OBJECT *Next; 973118611Snjl va_list ap; 974118611Snjl UINT32 i; 975118611Snjl ACPI_PARSE_OBJECT *Start; 976118611Snjl 977118611Snjl 978118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 979209746Sjkim "\nLinkPeerNodes: (%u) ", NumPeers); 980118611Snjl 981118611Snjl va_start (ap, NumPeers); 982118611Snjl This = va_arg (ap, ACPI_PARSE_OBJECT *); 983118611Snjl Start = This; 984118611Snjl 985118611Snjl /* 986118611Snjl * Link all peers 987118611Snjl */ 988118611Snjl for (i = 0; i < (NumPeers -1); i++) 989118611Snjl { 990209746Sjkim DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This); 991118611Snjl 992118611Snjl while (This->Asl.Next) 993118611Snjl { 994118611Snjl This = This->Asl.Next; 995118611Snjl } 996118611Snjl 997118611Snjl /* Get another peer node */ 998118611Snjl 999118611Snjl Next = va_arg (ap, ACPI_PARSE_OBJECT *); 1000118611Snjl if (!Next) 1001118611Snjl { 1002118611Snjl Next = TrAllocateNode (PARSEOP_DEFAULT_ARG); 1003118611Snjl } 1004118611Snjl 1005118611Snjl /* link new node to the current node */ 1006118611Snjl 1007118611Snjl This->Asl.Next = Next; 1008118611Snjl This = Next; 1009118611Snjl } 1010193529Sjkim va_end (ap); 1011118611Snjl 1012118611Snjl DbgPrint (ASL_PARSE_OUTPUT,"\n\n"); 1013118611Snjl return (Start); 1014118611Snjl} 1015118611Snjl 1016118611Snjl 1017118611Snjl/******************************************************************************* 1018118611Snjl * 1019118611Snjl * FUNCTION: TrLinkChildNode 1020118611Snjl * 1021118611Snjl * PARAMETERS: Op1 - Parent node 1022118611Snjl * Op2 - Op to become a child 1023118611Snjl * 1024118611Snjl * RETURN: The parent node 1025118611Snjl * 1026118611Snjl * DESCRIPTION: Link two nodes together as a parent and child 1027118611Snjl * 1028118611Snjl ******************************************************************************/ 1029118611Snjl 1030118611SnjlACPI_PARSE_OBJECT * 1031118611SnjlTrLinkChildNode ( 1032118611Snjl ACPI_PARSE_OBJECT *Op1, 1033118611Snjl ACPI_PARSE_OBJECT *Op2) 1034118611Snjl{ 1035118611Snjl ACPI_PARSE_OBJECT *Next; 1036118611Snjl 1037118611Snjl 1038118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 1039118611Snjl "\nLinkChildNode: Parent=%p (%s), Child=%p (%s)\n\n", 1040118611Snjl Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode): NULL, 1041118611Snjl Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode): NULL); 1042118611Snjl 1043118611Snjl if (!Op1 || !Op2) 1044118611Snjl { 1045241973Sjkim return (Op1); 1046118611Snjl } 1047118611Snjl 1048118611Snjl Op1->Asl.Child = Op2; 1049118611Snjl 1050118611Snjl /* Set the child and all peers of the child to point to the parent */ 1051118611Snjl 1052118611Snjl Next = Op2; 1053118611Snjl while (Next) 1054118611Snjl { 1055118611Snjl Next->Asl.Parent = Op1; 1056118611Snjl Next = Next->Asl.Next; 1057118611Snjl } 1058118611Snjl 1059241973Sjkim return (Op1); 1060118611Snjl} 1061118611Snjl 1062118611Snjl 1063118611Snjl/******************************************************************************* 1064118611Snjl * 1065118611Snjl * FUNCTION: TrWalkParseTree 1066118611Snjl * 1067118611Snjl * PARAMETERS: Visitation - Type of walk 1068118611Snjl * DescendingCallback - Called during tree descent 1069118611Snjl * AscendingCallback - Called during tree ascent 1070118611Snjl * Context - To be passed to the callbacks 1071118611Snjl * 1072118611Snjl * RETURN: Status from callback(s) 1073118611Snjl * 1074118611Snjl * DESCRIPTION: Walk the entire parse tree. 1075118611Snjl * 1076118611Snjl ******************************************************************************/ 1077118611Snjl 1078118611SnjlACPI_STATUS 1079118611SnjlTrWalkParseTree ( 1080118611Snjl ACPI_PARSE_OBJECT *Op, 1081118611Snjl UINT32 Visitation, 1082118611Snjl ASL_WALK_CALLBACK DescendingCallback, 1083118611Snjl ASL_WALK_CALLBACK AscendingCallback, 1084118611Snjl void *Context) 1085118611Snjl{ 1086118611Snjl UINT32 Level; 1087118611Snjl BOOLEAN NodePreviouslyVisited; 1088118611Snjl ACPI_PARSE_OBJECT *StartOp = Op; 1089118611Snjl ACPI_STATUS Status; 1090118611Snjl 1091118611Snjl 1092118611Snjl if (!RootNode) 1093118611Snjl { 1094118611Snjl return (AE_OK); 1095118611Snjl } 1096118611Snjl 1097118611Snjl Level = 0; 1098118611Snjl NodePreviouslyVisited = FALSE; 1099118611Snjl 1100118611Snjl switch (Visitation) 1101118611Snjl { 1102118611Snjl case ASL_WALK_VISIT_DOWNWARD: 1103118611Snjl 1104118611Snjl while (Op) 1105118611Snjl { 1106118611Snjl if (!NodePreviouslyVisited) 1107118611Snjl { 1108151937Sjkim /* Let the callback process the node. */ 1109151937Sjkim 1110118611Snjl Status = DescendingCallback (Op, Level, Context); 1111118611Snjl if (ACPI_SUCCESS (Status)) 1112118611Snjl { 1113118611Snjl /* Visit children first, once */ 1114118611Snjl 1115118611Snjl if (Op->Asl.Child) 1116118611Snjl { 1117118611Snjl Level++; 1118118611Snjl Op = Op->Asl.Child; 1119118611Snjl continue; 1120118611Snjl } 1121118611Snjl } 1122118611Snjl else if (Status != AE_CTRL_DEPTH) 1123118611Snjl { 1124118611Snjl /* Exit immediately on any error */ 1125118611Snjl 1126118611Snjl return (Status); 1127118611Snjl } 1128118611Snjl } 1129118611Snjl 1130118611Snjl /* Terminate walk at start op */ 1131118611Snjl 1132118611Snjl if (Op == StartOp) 1133118611Snjl { 1134118611Snjl break; 1135118611Snjl } 1136118611Snjl 1137118611Snjl /* No more children, visit peers */ 1138118611Snjl 1139118611Snjl if (Op->Asl.Next) 1140118611Snjl { 1141118611Snjl Op = Op->Asl.Next; 1142118611Snjl NodePreviouslyVisited = FALSE; 1143118611Snjl } 1144118611Snjl else 1145118611Snjl { 1146118611Snjl /* No children or peers, re-visit parent */ 1147118611Snjl 1148118611Snjl if (Level != 0 ) 1149118611Snjl { 1150118611Snjl Level--; 1151118611Snjl } 1152118611Snjl Op = Op->Asl.Parent; 1153118611Snjl NodePreviouslyVisited = TRUE; 1154118611Snjl } 1155118611Snjl } 1156118611Snjl break; 1157118611Snjl 1158118611Snjl case ASL_WALK_VISIT_UPWARD: 1159118611Snjl 1160118611Snjl while (Op) 1161118611Snjl { 1162118611Snjl /* Visit leaf node (no children) or parent node on return trip */ 1163118611Snjl 1164118611Snjl if ((!Op->Asl.Child) || 1165118611Snjl (NodePreviouslyVisited)) 1166118611Snjl { 1167151937Sjkim /* Let the callback process the node. */ 1168151937Sjkim 1169118611Snjl Status = AscendingCallback (Op, Level, Context); 1170118611Snjl if (ACPI_FAILURE (Status)) 1171118611Snjl { 1172118611Snjl return (Status); 1173118611Snjl } 1174118611Snjl } 1175118611Snjl else 1176118611Snjl { 1177118611Snjl /* Visit children first, once */ 1178118611Snjl 1179118611Snjl Level++; 1180118611Snjl Op = Op->Asl.Child; 1181118611Snjl continue; 1182118611Snjl } 1183118611Snjl 1184118611Snjl /* Terminate walk at start op */ 1185118611Snjl 1186118611Snjl if (Op == StartOp) 1187118611Snjl { 1188118611Snjl break; 1189118611Snjl } 1190118611Snjl 1191118611Snjl /* No more children, visit peers */ 1192118611Snjl 1193118611Snjl if (Op->Asl.Next) 1194118611Snjl { 1195118611Snjl Op = Op->Asl.Next; 1196118611Snjl NodePreviouslyVisited = FALSE; 1197118611Snjl } 1198118611Snjl else 1199118611Snjl { 1200118611Snjl /* No children or peers, re-visit parent */ 1201118611Snjl 1202118611Snjl if (Level != 0 ) 1203118611Snjl { 1204118611Snjl Level--; 1205118611Snjl } 1206118611Snjl Op = Op->Asl.Parent; 1207118611Snjl NodePreviouslyVisited = TRUE; 1208118611Snjl } 1209118611Snjl } 1210118611Snjl break; 1211118611Snjl 1212118611Snjl case ASL_WALK_VISIT_TWICE: 1213118611Snjl 1214118611Snjl while (Op) 1215118611Snjl { 1216118611Snjl if (NodePreviouslyVisited) 1217118611Snjl { 1218118611Snjl Status = AscendingCallback (Op, Level, Context); 1219118611Snjl if (ACPI_FAILURE (Status)) 1220118611Snjl { 1221118611Snjl return (Status); 1222118611Snjl } 1223118611Snjl } 1224118611Snjl else 1225118611Snjl { 1226151937Sjkim /* Let the callback process the node. */ 1227151937Sjkim 1228118611Snjl Status = DescendingCallback (Op, Level, Context); 1229118611Snjl if (ACPI_SUCCESS (Status)) 1230118611Snjl { 1231118611Snjl /* Visit children first, once */ 1232118611Snjl 1233118611Snjl if (Op->Asl.Child) 1234118611Snjl { 1235118611Snjl Level++; 1236118611Snjl Op = Op->Asl.Child; 1237118611Snjl continue; 1238118611Snjl } 1239118611Snjl } 1240118611Snjl else if (Status != AE_CTRL_DEPTH) 1241118611Snjl { 1242118611Snjl /* Exit immediately on any error */ 1243118611Snjl 1244118611Snjl return (Status); 1245118611Snjl } 1246118611Snjl } 1247118611Snjl 1248118611Snjl /* Terminate walk at start op */ 1249118611Snjl 1250118611Snjl if (Op == StartOp) 1251118611Snjl { 1252118611Snjl break; 1253118611Snjl } 1254118611Snjl 1255118611Snjl /* No more children, visit peers */ 1256118611Snjl 1257118611Snjl if (Op->Asl.Next) 1258118611Snjl { 1259118611Snjl Op = Op->Asl.Next; 1260118611Snjl NodePreviouslyVisited = FALSE; 1261118611Snjl } 1262118611Snjl else 1263118611Snjl { 1264118611Snjl /* No children or peers, re-visit parent */ 1265118611Snjl 1266118611Snjl if (Level != 0 ) 1267118611Snjl { 1268118611Snjl Level--; 1269118611Snjl } 1270118611Snjl Op = Op->Asl.Parent; 1271118611Snjl NodePreviouslyVisited = TRUE; 1272118611Snjl } 1273118611Snjl } 1274118611Snjl break; 1275118611Snjl 1276118611Snjl default: 1277118611Snjl /* No other types supported */ 1278118611Snjl break; 1279118611Snjl } 1280118611Snjl 1281118611Snjl /* If we get here, the walk completed with no errors */ 1282118611Snjl 1283118611Snjl return (AE_OK); 1284118611Snjl} 1285