1c2c66affSColin Finck /****************************************************************************** 2c2c66affSColin Finck * 3c2c66affSColin Finck * Module Name: dswexec - Dispatcher method execution callbacks; 4c2c66affSColin Finck * dispatch to interpreter. 5c2c66affSColin Finck * 6c2c66affSColin Finck *****************************************************************************/ 7c2c66affSColin Finck 8c2c66affSColin Finck /* 92deb69c1SThomas Faber * Copyright (C) 2000 - 2018, Intel Corp. 10c2c66affSColin Finck * All rights reserved. 11c2c66affSColin Finck * 12c2c66affSColin Finck * Redistribution and use in source and binary forms, with or without 13c2c66affSColin Finck * modification, are permitted provided that the following conditions 14c2c66affSColin Finck * are met: 15c2c66affSColin Finck * 1. Redistributions of source code must retain the above copyright 16c2c66affSColin Finck * notice, this list of conditions, and the following disclaimer, 17c2c66affSColin Finck * without modification. 18c2c66affSColin Finck * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19c2c66affSColin Finck * substantially similar to the "NO WARRANTY" disclaimer below 20c2c66affSColin Finck * ("Disclaimer") and any redistribution must be conditioned upon 21c2c66affSColin Finck * including a substantially similar Disclaimer requirement for further 22c2c66affSColin Finck * binary redistribution. 23c2c66affSColin Finck * 3. Neither the names of the above-listed copyright holders nor the names 24c2c66affSColin Finck * of any contributors may be used to endorse or promote products derived 25c2c66affSColin Finck * from this software without specific prior written permission. 26c2c66affSColin Finck * 27c2c66affSColin Finck * Alternatively, this software may be distributed under the terms of the 28c2c66affSColin Finck * GNU General Public License ("GPL") version 2 as published by the Free 29c2c66affSColin Finck * Software Foundation. 30c2c66affSColin Finck * 31c2c66affSColin Finck * NO WARRANTY 32c2c66affSColin Finck * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33c2c66affSColin Finck * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34c2c66affSColin Finck * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35c2c66affSColin Finck * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36c2c66affSColin Finck * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37c2c66affSColin Finck * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38c2c66affSColin Finck * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39c2c66affSColin Finck * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40c2c66affSColin Finck * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41c2c66affSColin Finck * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42c2c66affSColin Finck * POSSIBILITY OF SUCH DAMAGES. 43c2c66affSColin Finck */ 44c2c66affSColin Finck 45c2c66affSColin Finck #include "acpi.h" 46c2c66affSColin Finck #include "accommon.h" 47c2c66affSColin Finck #include "acparser.h" 48c2c66affSColin Finck #include "amlcode.h" 49c2c66affSColin Finck #include "acdispat.h" 50c2c66affSColin Finck #include "acinterp.h" 51c2c66affSColin Finck #include "acnamesp.h" 52c2c66affSColin Finck #include "acdebug.h" 53c2c66affSColin Finck 54c2c66affSColin Finck 55c2c66affSColin Finck #define _COMPONENT ACPI_DISPATCHER 56c2c66affSColin Finck ACPI_MODULE_NAME ("dswexec") 57c2c66affSColin Finck 58c2c66affSColin Finck /* 59c2c66affSColin Finck * Dispatch table for opcode classes 60c2c66affSColin Finck */ 61c2c66affSColin Finck static ACPI_EXECUTE_OP AcpiGbl_OpTypeDispatch [] = 62c2c66affSColin Finck { 63c2c66affSColin Finck AcpiExOpcode_0A_0T_1R, 64c2c66affSColin Finck AcpiExOpcode_1A_0T_0R, 65c2c66affSColin Finck AcpiExOpcode_1A_0T_1R, 66c2c66affSColin Finck AcpiExOpcode_1A_1T_0R, 67c2c66affSColin Finck AcpiExOpcode_1A_1T_1R, 68c2c66affSColin Finck AcpiExOpcode_2A_0T_0R, 69c2c66affSColin Finck AcpiExOpcode_2A_0T_1R, 70c2c66affSColin Finck AcpiExOpcode_2A_1T_1R, 71c2c66affSColin Finck AcpiExOpcode_2A_2T_1R, 72c2c66affSColin Finck AcpiExOpcode_3A_0T_0R, 73c2c66affSColin Finck AcpiExOpcode_3A_1T_1R, 74c2c66affSColin Finck AcpiExOpcode_6A_0T_1R 75c2c66affSColin Finck }; 76c2c66affSColin Finck 77c2c66affSColin Finck 78c2c66affSColin Finck /***************************************************************************** 79c2c66affSColin Finck * 80c2c66affSColin Finck * FUNCTION: AcpiDsGetPredicateValue 81c2c66affSColin Finck * 82c2c66affSColin Finck * PARAMETERS: WalkState - Current state of the parse tree walk 83c2c66affSColin Finck * ResultObj - if non-zero, pop result from result stack 84c2c66affSColin Finck * 85c2c66affSColin Finck * RETURN: Status 86c2c66affSColin Finck * 87c2c66affSColin Finck * DESCRIPTION: Get the result of a predicate evaluation 88c2c66affSColin Finck * 89c2c66affSColin Finck ****************************************************************************/ 90c2c66affSColin Finck 91c2c66affSColin Finck ACPI_STATUS 92c2c66affSColin Finck AcpiDsGetPredicateValue ( 93c2c66affSColin Finck ACPI_WALK_STATE *WalkState, 94c2c66affSColin Finck ACPI_OPERAND_OBJECT *ResultObj) 95c2c66affSColin Finck { 96c2c66affSColin Finck ACPI_STATUS Status = AE_OK; 97c2c66affSColin Finck ACPI_OPERAND_OBJECT *ObjDesc; 98c2c66affSColin Finck ACPI_OPERAND_OBJECT *LocalObjDesc = NULL; 99c2c66affSColin Finck 100c2c66affSColin Finck 101c2c66affSColin Finck ACPI_FUNCTION_TRACE_PTR (DsGetPredicateValue, WalkState); 102c2c66affSColin Finck 103c2c66affSColin Finck 104c2c66affSColin Finck WalkState->ControlState->Common.State = 0; 105c2c66affSColin Finck 106c2c66affSColin Finck if (ResultObj) 107c2c66affSColin Finck { 108c2c66affSColin Finck Status = AcpiDsResultPop (&ObjDesc, WalkState); 109c2c66affSColin Finck if (ACPI_FAILURE (Status)) 110c2c66affSColin Finck { 111c2c66affSColin Finck ACPI_EXCEPTION ((AE_INFO, Status, 112c2c66affSColin Finck "Could not get result from predicate evaluation")); 113c2c66affSColin Finck 114c2c66affSColin Finck return_ACPI_STATUS (Status); 115c2c66affSColin Finck } 116c2c66affSColin Finck } 117c2c66affSColin Finck else 118c2c66affSColin Finck { 119c2c66affSColin Finck Status = AcpiDsCreateOperand (WalkState, WalkState->Op, 0); 120c2c66affSColin Finck if (ACPI_FAILURE (Status)) 121c2c66affSColin Finck { 122c2c66affSColin Finck return_ACPI_STATUS (Status); 123c2c66affSColin Finck } 124c2c66affSColin Finck 125c2c66affSColin Finck Status = AcpiExResolveToValue (&WalkState->Operands [0], WalkState); 126c2c66affSColin Finck if (ACPI_FAILURE (Status)) 127c2c66affSColin Finck { 128c2c66affSColin Finck return_ACPI_STATUS (Status); 129c2c66affSColin Finck } 130c2c66affSColin Finck 131c2c66affSColin Finck ObjDesc = WalkState->Operands [0]; 132c2c66affSColin Finck } 133c2c66affSColin Finck 134c2c66affSColin Finck if (!ObjDesc) 135c2c66affSColin Finck { 136c2c66affSColin Finck ACPI_ERROR ((AE_INFO, 137c2c66affSColin Finck "No predicate ObjDesc=%p State=%p", 138c2c66affSColin Finck ObjDesc, WalkState)); 139c2c66affSColin Finck 140c2c66affSColin Finck return_ACPI_STATUS (AE_AML_NO_OPERAND); 141c2c66affSColin Finck } 142c2c66affSColin Finck 143c2c66affSColin Finck /* 144c2c66affSColin Finck * Result of predicate evaluation must be an Integer 145c2c66affSColin Finck * object. Implicitly convert the argument if necessary. 146c2c66affSColin Finck */ 147c2c66affSColin Finck Status = AcpiExConvertToInteger (ObjDesc, &LocalObjDesc, 148ec55f0ebSThomas Faber ACPI_IMPLICIT_CONVERSION); 149c2c66affSColin Finck if (ACPI_FAILURE (Status)) 150c2c66affSColin Finck { 151c2c66affSColin Finck goto Cleanup; 152c2c66affSColin Finck } 153c2c66affSColin Finck 154c2c66affSColin Finck if (LocalObjDesc->Common.Type != ACPI_TYPE_INTEGER) 155c2c66affSColin Finck { 156c2c66affSColin Finck ACPI_ERROR ((AE_INFO, 157c2c66affSColin Finck "Bad predicate (not an integer) ObjDesc=%p State=%p Type=0x%X", 158c2c66affSColin Finck ObjDesc, WalkState, ObjDesc->Common.Type)); 159c2c66affSColin Finck 160c2c66affSColin Finck Status = AE_AML_OPERAND_TYPE; 161c2c66affSColin Finck goto Cleanup; 162c2c66affSColin Finck } 163c2c66affSColin Finck 164c2c66affSColin Finck /* Truncate the predicate to 32-bits if necessary */ 165c2c66affSColin Finck 166c2c66affSColin Finck (void) AcpiExTruncateFor32bitTable (LocalObjDesc); 167c2c66affSColin Finck 168c2c66affSColin Finck /* 169c2c66affSColin Finck * Save the result of the predicate evaluation on 170c2c66affSColin Finck * the control stack 171c2c66affSColin Finck */ 172c2c66affSColin Finck if (LocalObjDesc->Integer.Value) 173c2c66affSColin Finck { 174c2c66affSColin Finck WalkState->ControlState->Common.Value = TRUE; 175c2c66affSColin Finck } 176c2c66affSColin Finck else 177c2c66affSColin Finck { 178c2c66affSColin Finck /* 179c2c66affSColin Finck * Predicate is FALSE, we will just toss the 180c2c66affSColin Finck * rest of the package 181c2c66affSColin Finck */ 182c2c66affSColin Finck WalkState->ControlState->Common.Value = FALSE; 183c2c66affSColin Finck Status = AE_CTRL_FALSE; 184c2c66affSColin Finck } 185c2c66affSColin Finck 186c2c66affSColin Finck /* Predicate can be used for an implicit return value */ 187c2c66affSColin Finck 188c2c66affSColin Finck (void) AcpiDsDoImplicitReturn (LocalObjDesc, WalkState, TRUE); 189c2c66affSColin Finck 190c2c66affSColin Finck 191c2c66affSColin Finck Cleanup: 192c2c66affSColin Finck 193c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 194c2c66affSColin Finck "Completed a predicate eval=%X Op=%p\n", 195c2c66affSColin Finck WalkState->ControlState->Common.Value, WalkState->Op)); 196c2c66affSColin Finck 197c2c66affSColin Finck /* Break to debugger to display result */ 198c2c66affSColin Finck 199c2c66affSColin Finck AcpiDbDisplayResultObject (LocalObjDesc, WalkState); 200c2c66affSColin Finck 201c2c66affSColin Finck /* 202c2c66affSColin Finck * Delete the predicate result object (we know that 203c2c66affSColin Finck * we don't need it anymore) 204c2c66affSColin Finck */ 205c2c66affSColin Finck if (LocalObjDesc != ObjDesc) 206c2c66affSColin Finck { 207c2c66affSColin Finck AcpiUtRemoveReference (LocalObjDesc); 208c2c66affSColin Finck } 209c2c66affSColin Finck AcpiUtRemoveReference (ObjDesc); 210c2c66affSColin Finck 211c2c66affSColin Finck WalkState->ControlState->Common.State = ACPI_CONTROL_NORMAL; 212c2c66affSColin Finck return_ACPI_STATUS (Status); 213c2c66affSColin Finck } 214c2c66affSColin Finck 215c2c66affSColin Finck 216c2c66affSColin Finck /***************************************************************************** 217c2c66affSColin Finck * 218c2c66affSColin Finck * FUNCTION: AcpiDsExecBeginOp 219c2c66affSColin Finck * 220c2c66affSColin Finck * PARAMETERS: WalkState - Current state of the parse tree walk 221c2c66affSColin Finck * OutOp - Where to return op if a new one is created 222c2c66affSColin Finck * 223c2c66affSColin Finck * RETURN: Status 224c2c66affSColin Finck * 225c2c66affSColin Finck * DESCRIPTION: Descending callback used during the execution of control 226c2c66affSColin Finck * methods. This is where most operators and operands are 227c2c66affSColin Finck * dispatched to the interpreter. 228c2c66affSColin Finck * 229c2c66affSColin Finck ****************************************************************************/ 230c2c66affSColin Finck 231c2c66affSColin Finck ACPI_STATUS 232c2c66affSColin Finck AcpiDsExecBeginOp ( 233c2c66affSColin Finck ACPI_WALK_STATE *WalkState, 234c2c66affSColin Finck ACPI_PARSE_OBJECT **OutOp) 235c2c66affSColin Finck { 236c2c66affSColin Finck ACPI_PARSE_OBJECT *Op; 237c2c66affSColin Finck ACPI_STATUS Status = AE_OK; 238c2c66affSColin Finck UINT32 OpcodeClass; 239c2c66affSColin Finck 240c2c66affSColin Finck 241c2c66affSColin Finck ACPI_FUNCTION_TRACE_PTR (DsExecBeginOp, WalkState); 242c2c66affSColin Finck 243c2c66affSColin Finck 244c2c66affSColin Finck Op = WalkState->Op; 245c2c66affSColin Finck if (!Op) 246c2c66affSColin Finck { 247c2c66affSColin Finck Status = AcpiDsLoad2BeginOp (WalkState, OutOp); 248c2c66affSColin Finck if (ACPI_FAILURE (Status)) 249c2c66affSColin Finck { 250c2c66affSColin Finck goto ErrorExit; 251c2c66affSColin Finck } 252c2c66affSColin Finck 253c2c66affSColin Finck Op = *OutOp; 254c2c66affSColin Finck WalkState->Op = Op; 255c2c66affSColin Finck WalkState->Opcode = Op->Common.AmlOpcode; 256c2c66affSColin Finck WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 257c2c66affSColin Finck 258c2c66affSColin Finck if (AcpiNsOpensScope (WalkState->OpInfo->ObjectType)) 259c2c66affSColin Finck { 260c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 261c2c66affSColin Finck "(%s) Popping scope for Op %p\n", 262c2c66affSColin Finck AcpiUtGetTypeName (WalkState->OpInfo->ObjectType), Op)); 263c2c66affSColin Finck 264c2c66affSColin Finck Status = AcpiDsScopeStackPop (WalkState); 265c2c66affSColin Finck if (ACPI_FAILURE (Status)) 266c2c66affSColin Finck { 267c2c66affSColin Finck goto ErrorExit; 268c2c66affSColin Finck } 269c2c66affSColin Finck } 270c2c66affSColin Finck } 271c2c66affSColin Finck 272c2c66affSColin Finck if (Op == WalkState->Origin) 273c2c66affSColin Finck { 274c2c66affSColin Finck if (OutOp) 275c2c66affSColin Finck { 276c2c66affSColin Finck *OutOp = Op; 277c2c66affSColin Finck } 278c2c66affSColin Finck 279c2c66affSColin Finck return_ACPI_STATUS (AE_OK); 280c2c66affSColin Finck } 281c2c66affSColin Finck 282c2c66affSColin Finck /* 283c2c66affSColin Finck * If the previous opcode was a conditional, this opcode 284c2c66affSColin Finck * must be the beginning of the associated predicate. 285c2c66affSColin Finck * Save this knowledge in the current scope descriptor 286c2c66affSColin Finck */ 287c2c66affSColin Finck if ((WalkState->ControlState) && 288c2c66affSColin Finck (WalkState->ControlState->Common.State == 289c2c66affSColin Finck ACPI_CONTROL_CONDITIONAL_EXECUTING)) 290c2c66affSColin Finck { 291c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 292c2c66affSColin Finck "Exec predicate Op=%p State=%p\n", 293c2c66affSColin Finck Op, WalkState)); 294c2c66affSColin Finck 295c2c66affSColin Finck WalkState->ControlState->Common.State = 296c2c66affSColin Finck ACPI_CONTROL_PREDICATE_EXECUTING; 297c2c66affSColin Finck 298c2c66affSColin Finck /* Save start of predicate */ 299c2c66affSColin Finck 300c2c66affSColin Finck WalkState->ControlState->Control.PredicateOp = Op; 301c2c66affSColin Finck } 302c2c66affSColin Finck 303c2c66affSColin Finck 304c2c66affSColin Finck OpcodeClass = WalkState->OpInfo->Class; 305c2c66affSColin Finck 306c2c66affSColin Finck /* We want to send namepaths to the load code */ 307c2c66affSColin Finck 308c2c66affSColin Finck if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP) 309c2c66affSColin Finck { 310c2c66affSColin Finck OpcodeClass = AML_CLASS_NAMED_OBJECT; 311c2c66affSColin Finck } 312c2c66affSColin Finck 313c2c66affSColin Finck /* 314c2c66affSColin Finck * Handle the opcode based upon the opcode type 315c2c66affSColin Finck */ 316c2c66affSColin Finck switch (OpcodeClass) 317c2c66affSColin Finck { 318c2c66affSColin Finck case AML_CLASS_CONTROL: 319c2c66affSColin Finck 320c2c66affSColin Finck Status = AcpiDsExecBeginControlOp (WalkState, Op); 321c2c66affSColin Finck break; 322c2c66affSColin Finck 323c2c66affSColin Finck case AML_CLASS_NAMED_OBJECT: 324c2c66affSColin Finck 325c2c66affSColin Finck if (WalkState->WalkType & ACPI_WALK_METHOD) 326c2c66affSColin Finck { 327c2c66affSColin Finck /* 328c2c66affSColin Finck * Found a named object declaration during method execution; 329c2c66affSColin Finck * we must enter this object into the namespace. The created 330c2c66affSColin Finck * object is temporary and will be deleted upon completion of 331c2c66affSColin Finck * the execution of this method. 332c2c66affSColin Finck * 333c2c66affSColin Finck * Note 10/2010: Except for the Scope() op. This opcode does 334c2c66affSColin Finck * not actually create a new object, it refers to an existing 335c2c66affSColin Finck * object. However, for Scope(), we want to indeed open a 336c2c66affSColin Finck * new scope. 337c2c66affSColin Finck */ 338c2c66affSColin Finck if (Op->Common.AmlOpcode != AML_SCOPE_OP) 339c2c66affSColin Finck { 340c2c66affSColin Finck Status = AcpiDsLoad2BeginOp (WalkState, NULL); 341c2c66affSColin Finck } 342c2c66affSColin Finck else 343c2c66affSColin Finck { 344c2c66affSColin Finck Status = AcpiDsScopeStackPush ( 345c2c66affSColin Finck Op->Named.Node, Op->Named.Node->Type, WalkState); 346c2c66affSColin Finck if (ACPI_FAILURE (Status)) 347c2c66affSColin Finck { 348c2c66affSColin Finck return_ACPI_STATUS (Status); 349c2c66affSColin Finck } 350c2c66affSColin Finck } 351c2c66affSColin Finck } 352c2c66affSColin Finck break; 353c2c66affSColin Finck 354c2c66affSColin Finck case AML_CLASS_EXECUTE: 355c2c66affSColin Finck case AML_CLASS_CREATE: 356c2c66affSColin Finck 357c2c66affSColin Finck break; 358c2c66affSColin Finck 359c2c66affSColin Finck default: 360c2c66affSColin Finck 361c2c66affSColin Finck break; 362c2c66affSColin Finck } 363c2c66affSColin Finck 364c2c66affSColin Finck /* Nothing to do here during method execution */ 365c2c66affSColin Finck 366c2c66affSColin Finck return_ACPI_STATUS (Status); 367c2c66affSColin Finck 368c2c66affSColin Finck 369c2c66affSColin Finck ErrorExit: 370c2c66affSColin Finck Status = AcpiDsMethodError (Status, WalkState); 371c2c66affSColin Finck return_ACPI_STATUS (Status); 372c2c66affSColin Finck } 373c2c66affSColin Finck 374c2c66affSColin Finck 375c2c66affSColin Finck /***************************************************************************** 376c2c66affSColin Finck * 377c2c66affSColin Finck * FUNCTION: AcpiDsExecEndOp 378c2c66affSColin Finck * 379c2c66affSColin Finck * PARAMETERS: WalkState - Current state of the parse tree walk 380c2c66affSColin Finck * 381c2c66affSColin Finck * RETURN: Status 382c2c66affSColin Finck * 383c2c66affSColin Finck * DESCRIPTION: Ascending callback used during the execution of control 384c2c66affSColin Finck * methods. The only thing we really need to do here is to 385c2c66affSColin Finck * notice the beginning of IF, ELSE, and WHILE blocks. 386c2c66affSColin Finck * 387c2c66affSColin Finck ****************************************************************************/ 388c2c66affSColin Finck 389c2c66affSColin Finck ACPI_STATUS 390c2c66affSColin Finck AcpiDsExecEndOp ( 391c2c66affSColin Finck ACPI_WALK_STATE *WalkState) 392c2c66affSColin Finck { 393c2c66affSColin Finck ACPI_PARSE_OBJECT *Op; 394c2c66affSColin Finck ACPI_STATUS Status = AE_OK; 395c2c66affSColin Finck UINT32 OpType; 396c2c66affSColin Finck UINT32 OpClass; 397c2c66affSColin Finck ACPI_PARSE_OBJECT *NextOp; 398c2c66affSColin Finck ACPI_PARSE_OBJECT *FirstArg; 399c2c66affSColin Finck 400c2c66affSColin Finck 401c2c66affSColin Finck ACPI_FUNCTION_TRACE_PTR (DsExecEndOp, WalkState); 402c2c66affSColin Finck 403c2c66affSColin Finck 404c2c66affSColin Finck Op = WalkState->Op; 405c2c66affSColin Finck OpType = WalkState->OpInfo->Type; 406c2c66affSColin Finck OpClass = WalkState->OpInfo->Class; 407c2c66affSColin Finck 408c2c66affSColin Finck if (OpClass == AML_CLASS_UNKNOWN) 409c2c66affSColin Finck { 410c2c66affSColin Finck ACPI_ERROR ((AE_INFO, "Unknown opcode 0x%X", Op->Common.AmlOpcode)); 411c2c66affSColin Finck return_ACPI_STATUS (AE_NOT_IMPLEMENTED); 412c2c66affSColin Finck } 413c2c66affSColin Finck 414c2c66affSColin Finck FirstArg = Op->Common.Value.Arg; 415c2c66affSColin Finck 416c2c66affSColin Finck /* Init the walk state */ 417c2c66affSColin Finck 418c2c66affSColin Finck WalkState->NumOperands = 0; 419c2c66affSColin Finck WalkState->OperandIndex = 0; 420c2c66affSColin Finck WalkState->ReturnDesc = NULL; 421c2c66affSColin Finck WalkState->ResultObj = NULL; 422c2c66affSColin Finck 423c2c66affSColin Finck /* Call debugger for single step support (DEBUG build only) */ 424c2c66affSColin Finck 425c2c66affSColin Finck Status = AcpiDbSingleStep (WalkState, Op, OpClass); 426c2c66affSColin Finck if (ACPI_FAILURE (Status)) 427c2c66affSColin Finck { 428c2c66affSColin Finck return_ACPI_STATUS (Status); 429c2c66affSColin Finck } 430c2c66affSColin Finck 431c2c66affSColin Finck /* Decode the Opcode Class */ 432c2c66affSColin Finck 433c2c66affSColin Finck switch (OpClass) 434c2c66affSColin Finck { 435c2c66affSColin Finck case AML_CLASS_ARGUMENT: /* Constants, literals, etc. */ 436c2c66affSColin Finck 437c2c66affSColin Finck if (WalkState->Opcode == AML_INT_NAMEPATH_OP) 438c2c66affSColin Finck { 439c2c66affSColin Finck Status = AcpiDsEvaluateNamePath (WalkState); 440c2c66affSColin Finck if (ACPI_FAILURE (Status)) 441c2c66affSColin Finck { 442c2c66affSColin Finck goto Cleanup; 443c2c66affSColin Finck } 444c2c66affSColin Finck } 445c2c66affSColin Finck break; 446c2c66affSColin Finck 447c2c66affSColin Finck case AML_CLASS_EXECUTE: /* Most operators with arguments */ 448c2c66affSColin Finck 449c2c66affSColin Finck /* Build resolved operand stack */ 450c2c66affSColin Finck 451c2c66affSColin Finck Status = AcpiDsCreateOperands (WalkState, FirstArg); 452c2c66affSColin Finck if (ACPI_FAILURE (Status)) 453c2c66affSColin Finck { 454c2c66affSColin Finck goto Cleanup; 455c2c66affSColin Finck } 456c2c66affSColin Finck 457c2c66affSColin Finck /* 458c2c66affSColin Finck * All opcodes require operand resolution, with the only exceptions 459c2c66affSColin Finck * being the ObjectType and SizeOf operators. 460c2c66affSColin Finck */ 461c2c66affSColin Finck if (!(WalkState->OpInfo->Flags & AML_NO_OPERAND_RESOLVE)) 462c2c66affSColin Finck { 463c2c66affSColin Finck /* Resolve all operands */ 464c2c66affSColin Finck 465c2c66affSColin Finck Status = AcpiExResolveOperands (WalkState->Opcode, 466c2c66affSColin Finck &(WalkState->Operands [WalkState->NumOperands -1]), 467c2c66affSColin Finck WalkState); 468c2c66affSColin Finck } 469c2c66affSColin Finck 470c2c66affSColin Finck if (ACPI_SUCCESS (Status)) 471c2c66affSColin Finck { 472c2c66affSColin Finck /* 473c2c66affSColin Finck * Dispatch the request to the appropriate interpreter handler 474c2c66affSColin Finck * routine. There is one routine per opcode "type" based upon the 475c2c66affSColin Finck * number of opcode arguments and return type. 476c2c66affSColin Finck */ 477c2c66affSColin Finck Status = AcpiGbl_OpTypeDispatch[OpType] (WalkState); 478c2c66affSColin Finck } 479c2c66affSColin Finck else 480c2c66affSColin Finck { 481c2c66affSColin Finck /* 482c2c66affSColin Finck * Treat constructs of the form "Store(LocalX,LocalX)" as noops when the 483c2c66affSColin Finck * Local is uninitialized. 484c2c66affSColin Finck */ 485c2c66affSColin Finck if ((Status == AE_AML_UNINITIALIZED_LOCAL) && 486c2c66affSColin Finck (WalkState->Opcode == AML_STORE_OP) && 487c2c66affSColin Finck (WalkState->Operands[0]->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) && 488c2c66affSColin Finck (WalkState->Operands[1]->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) && 489c2c66affSColin Finck (WalkState->Operands[0]->Reference.Class == 490c2c66affSColin Finck WalkState->Operands[1]->Reference.Class) && 491c2c66affSColin Finck (WalkState->Operands[0]->Reference.Value == 492c2c66affSColin Finck WalkState->Operands[1]->Reference.Value)) 493c2c66affSColin Finck { 494c2c66affSColin Finck Status = AE_OK; 495c2c66affSColin Finck } 496c2c66affSColin Finck else 497c2c66affSColin Finck { 498c2c66affSColin Finck ACPI_EXCEPTION ((AE_INFO, Status, 499c2c66affSColin Finck "While resolving operands for [%s]", 500c2c66affSColin Finck AcpiPsGetOpcodeName (WalkState->Opcode))); 501c2c66affSColin Finck } 502c2c66affSColin Finck } 503c2c66affSColin Finck 504c2c66affSColin Finck /* Always delete the argument objects and clear the operand stack */ 505c2c66affSColin Finck 506c2c66affSColin Finck AcpiDsClearOperands (WalkState); 507c2c66affSColin Finck 508c2c66affSColin Finck /* 509c2c66affSColin Finck * If a result object was returned from above, push it on the 510c2c66affSColin Finck * current result stack 511c2c66affSColin Finck */ 512c2c66affSColin Finck if (ACPI_SUCCESS (Status) && 513c2c66affSColin Finck WalkState->ResultObj) 514c2c66affSColin Finck { 515c2c66affSColin Finck Status = AcpiDsResultPush (WalkState->ResultObj, WalkState); 516c2c66affSColin Finck } 517c2c66affSColin Finck break; 518c2c66affSColin Finck 519c2c66affSColin Finck default: 520c2c66affSColin Finck 521c2c66affSColin Finck switch (OpType) 522c2c66affSColin Finck { 523c2c66affSColin Finck case AML_TYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */ 524c2c66affSColin Finck 525c2c66affSColin Finck /* 1 Operand, 0 ExternalResult, 0 InternalResult */ 526c2c66affSColin Finck 527c2c66affSColin Finck Status = AcpiDsExecEndControlOp (WalkState, Op); 528c2c66affSColin Finck 529c2c66affSColin Finck break; 530c2c66affSColin Finck 531c2c66affSColin Finck case AML_TYPE_METHOD_CALL: 532c2c66affSColin Finck /* 533c2c66affSColin Finck * If the method is referenced from within a package 534c2c66affSColin Finck * declaration, it is not a invocation of the method, just 535c2c66affSColin Finck * a reference to it. 536c2c66affSColin Finck */ 537c2c66affSColin Finck if ((Op->Asl.Parent) && 538c2c66affSColin Finck ((Op->Asl.Parent->Asl.AmlOpcode == AML_PACKAGE_OP) || 539c2c66affSColin Finck (Op->Asl.Parent->Asl.AmlOpcode == AML_VARIABLE_PACKAGE_OP))) 540c2c66affSColin Finck { 541c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 542c2c66affSColin Finck "Method Reference in a Package, Op=%p\n", Op)); 543c2c66affSColin Finck 544c2c66affSColin Finck Op->Common.Node = (ACPI_NAMESPACE_NODE *) 545c2c66affSColin Finck Op->Asl.Value.Arg->Asl.Node; 546c2c66affSColin Finck AcpiUtAddReference (Op->Asl.Value.Arg->Asl.Node->Object); 547c2c66affSColin Finck return_ACPI_STATUS (AE_OK); 548c2c66affSColin Finck } 549c2c66affSColin Finck 550c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 551c2c66affSColin Finck "Method invocation, Op=%p\n", Op)); 552c2c66affSColin Finck 553c2c66affSColin Finck /* 554c2c66affSColin Finck * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains 555c2c66affSColin Finck * the method Node pointer 556c2c66affSColin Finck */ 557c2c66affSColin Finck /* NextOp points to the op that holds the method name */ 558c2c66affSColin Finck 559c2c66affSColin Finck NextOp = FirstArg; 560c2c66affSColin Finck 561c2c66affSColin Finck /* NextOp points to first argument op */ 562c2c66affSColin Finck 563c2c66affSColin Finck NextOp = NextOp->Common.Next; 564c2c66affSColin Finck 565c2c66affSColin Finck /* 566c2c66affSColin Finck * Get the method's arguments and put them on the operand stack 567c2c66affSColin Finck */ 568c2c66affSColin Finck Status = AcpiDsCreateOperands (WalkState, NextOp); 569c2c66affSColin Finck if (ACPI_FAILURE (Status)) 570c2c66affSColin Finck { 571c2c66affSColin Finck break; 572c2c66affSColin Finck } 573c2c66affSColin Finck 574c2c66affSColin Finck /* 575c2c66affSColin Finck * Since the operands will be passed to another control method, 576c2c66affSColin Finck * we must resolve all local references here (Local variables, 577c2c66affSColin Finck * arguments to *this* method, etc.) 578c2c66affSColin Finck */ 579c2c66affSColin Finck Status = AcpiDsResolveOperands (WalkState); 580c2c66affSColin Finck if (ACPI_FAILURE (Status)) 581c2c66affSColin Finck { 582c2c66affSColin Finck /* On error, clear all resolved operands */ 583c2c66affSColin Finck 584c2c66affSColin Finck AcpiDsClearOperands (WalkState); 585c2c66affSColin Finck break; 586c2c66affSColin Finck } 587c2c66affSColin Finck 588c2c66affSColin Finck /* 589c2c66affSColin Finck * Tell the walk loop to preempt this running method and 590c2c66affSColin Finck * execute the new method 591c2c66affSColin Finck */ 592c2c66affSColin Finck Status = AE_CTRL_TRANSFER; 593c2c66affSColin Finck 594c2c66affSColin Finck /* 595c2c66affSColin Finck * Return now; we don't want to disturb anything, 596c2c66affSColin Finck * especially the operand count! 597c2c66affSColin Finck */ 598c2c66affSColin Finck return_ACPI_STATUS (Status); 599c2c66affSColin Finck 600c2c66affSColin Finck case AML_TYPE_CREATE_FIELD: 601c2c66affSColin Finck 602c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 603c2c66affSColin Finck "Executing CreateField Buffer/Index Op=%p\n", Op)); 604c2c66affSColin Finck 605c2c66affSColin Finck Status = AcpiDsLoad2EndOp (WalkState); 606c2c66affSColin Finck if (ACPI_FAILURE (Status)) 607c2c66affSColin Finck { 608c2c66affSColin Finck break; 609c2c66affSColin Finck } 610c2c66affSColin Finck 611c2c66affSColin Finck Status = AcpiDsEvalBufferFieldOperands (WalkState, Op); 612c2c66affSColin Finck break; 613c2c66affSColin Finck 614c2c66affSColin Finck 615c2c66affSColin Finck case AML_TYPE_CREATE_OBJECT: 616c2c66affSColin Finck 617c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 618*6847cc3aSThomas Faber "Executing CreateObject (Buffer/Package) Op=%p Child=%p ParentOpcode=%4.4X\n", 619*6847cc3aSThomas Faber Op, Op->Named.Value.Arg, Op->Common.Parent->Common.AmlOpcode)); 620c2c66affSColin Finck 621c2c66affSColin Finck switch (Op->Common.Parent->Common.AmlOpcode) 622c2c66affSColin Finck { 623c2c66affSColin Finck case AML_NAME_OP: 624c2c66affSColin Finck /* 625c2c66affSColin Finck * Put the Node on the object stack (Contains the ACPI Name 626c2c66affSColin Finck * of this object) 627c2c66affSColin Finck */ 628c2c66affSColin Finck WalkState->Operands[0] = (void *) 629c2c66affSColin Finck Op->Common.Parent->Common.Node; 630c2c66affSColin Finck WalkState->NumOperands = 1; 631c2c66affSColin Finck 632c2c66affSColin Finck Status = AcpiDsCreateNode (WalkState, 633c2c66affSColin Finck Op->Common.Parent->Common.Node, Op->Common.Parent); 634c2c66affSColin Finck if (ACPI_FAILURE (Status)) 635c2c66affSColin Finck { 636c2c66affSColin Finck break; 637c2c66affSColin Finck } 638c2c66affSColin Finck 639c2c66affSColin Finck /* Fall through */ 640c2c66affSColin Finck /*lint -fallthrough */ 641c2c66affSColin Finck 642c2c66affSColin Finck case AML_INT_EVAL_SUBTREE_OP: 643c2c66affSColin Finck 644c2c66affSColin Finck Status = AcpiDsEvalDataObjectOperands (WalkState, Op, 645c2c66affSColin Finck AcpiNsGetAttachedObject (Op->Common.Parent->Common.Node)); 646c2c66affSColin Finck break; 647c2c66affSColin Finck 648c2c66affSColin Finck default: 649c2c66affSColin Finck 650c2c66affSColin Finck Status = AcpiDsEvalDataObjectOperands (WalkState, Op, NULL); 651c2c66affSColin Finck break; 652c2c66affSColin Finck } 653c2c66affSColin Finck 654c2c66affSColin Finck /* 655c2c66affSColin Finck * If a result object was returned from above, push it on the 656c2c66affSColin Finck * current result stack 657c2c66affSColin Finck */ 658c2c66affSColin Finck if (WalkState->ResultObj) 659c2c66affSColin Finck { 660c2c66affSColin Finck Status = AcpiDsResultPush (WalkState->ResultObj, WalkState); 661c2c66affSColin Finck } 662c2c66affSColin Finck break; 663c2c66affSColin Finck 664c2c66affSColin Finck case AML_TYPE_NAMED_FIELD: 665c2c66affSColin Finck case AML_TYPE_NAMED_COMPLEX: 666c2c66affSColin Finck case AML_TYPE_NAMED_SIMPLE: 667c2c66affSColin Finck case AML_TYPE_NAMED_NO_OBJ: 668c2c66affSColin Finck 669c2c66affSColin Finck Status = AcpiDsLoad2EndOp (WalkState); 670c2c66affSColin Finck if (ACPI_FAILURE (Status)) 671c2c66affSColin Finck { 672c2c66affSColin Finck break; 673c2c66affSColin Finck } 674c2c66affSColin Finck 675c2c66affSColin Finck if (Op->Common.AmlOpcode == AML_REGION_OP) 676c2c66affSColin Finck { 677c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 678c2c66affSColin Finck "Executing OpRegion Address/Length Op=%p\n", Op)); 679c2c66affSColin Finck 680c2c66affSColin Finck Status = AcpiDsEvalRegionOperands (WalkState, Op); 681c2c66affSColin Finck if (ACPI_FAILURE (Status)) 682c2c66affSColin Finck { 683c2c66affSColin Finck break; 684c2c66affSColin Finck } 685c2c66affSColin Finck } 686c2c66affSColin Finck else if (Op->Common.AmlOpcode == AML_DATA_REGION_OP) 687c2c66affSColin Finck { 688c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 689c2c66affSColin Finck "Executing DataTableRegion Strings Op=%p\n", Op)); 690c2c66affSColin Finck 691c2c66affSColin Finck Status = AcpiDsEvalTableRegionOperands (WalkState, Op); 692c2c66affSColin Finck if (ACPI_FAILURE (Status)) 693c2c66affSColin Finck { 694c2c66affSColin Finck break; 695c2c66affSColin Finck } 696c2c66affSColin Finck } 697c2c66affSColin Finck else if (Op->Common.AmlOpcode == AML_BANK_FIELD_OP) 698c2c66affSColin Finck { 699c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 700c2c66affSColin Finck "Executing BankField Op=%p\n", Op)); 701c2c66affSColin Finck 702c2c66affSColin Finck Status = AcpiDsEvalBankFieldOperands (WalkState, Op); 703c2c66affSColin Finck if (ACPI_FAILURE (Status)) 704c2c66affSColin Finck { 705c2c66affSColin Finck break; 706c2c66affSColin Finck } 707c2c66affSColin Finck } 708c2c66affSColin Finck break; 709c2c66affSColin Finck 710c2c66affSColin Finck case AML_TYPE_UNDEFINED: 711c2c66affSColin Finck 712c2c66affSColin Finck ACPI_ERROR ((AE_INFO, 713c2c66affSColin Finck "Undefined opcode type Op=%p", Op)); 714c2c66affSColin Finck return_ACPI_STATUS (AE_NOT_IMPLEMENTED); 715c2c66affSColin Finck 716c2c66affSColin Finck case AML_TYPE_BOGUS: 717c2c66affSColin Finck 718c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 719c2c66affSColin Finck "Internal opcode=%X type Op=%p\n", 720c2c66affSColin Finck WalkState->Opcode, Op)); 721c2c66affSColin Finck break; 722c2c66affSColin Finck 723c2c66affSColin Finck default: 724c2c66affSColin Finck 725c2c66affSColin Finck ACPI_ERROR ((AE_INFO, 726c2c66affSColin Finck "Unimplemented opcode, class=0x%X " 727c2c66affSColin Finck "type=0x%X Opcode=0x%X Op=%p", 728c2c66affSColin Finck OpClass, OpType, Op->Common.AmlOpcode, Op)); 729c2c66affSColin Finck 730c2c66affSColin Finck Status = AE_NOT_IMPLEMENTED; 731c2c66affSColin Finck break; 732c2c66affSColin Finck } 733c2c66affSColin Finck } 734c2c66affSColin Finck 735c2c66affSColin Finck /* 736c2c66affSColin Finck * ACPI 2.0 support for 64-bit integers: Truncate numeric 737c2c66affSColin Finck * result value if we are executing from a 32-bit ACPI table 738c2c66affSColin Finck */ 739c2c66affSColin Finck (void) AcpiExTruncateFor32bitTable (WalkState->ResultObj); 740c2c66affSColin Finck 741c2c66affSColin Finck /* 742c2c66affSColin Finck * Check if we just completed the evaluation of a 743c2c66affSColin Finck * conditional predicate 744c2c66affSColin Finck */ 745c2c66affSColin Finck if ((ACPI_SUCCESS (Status)) && 746c2c66affSColin Finck (WalkState->ControlState) && 747c2c66affSColin Finck (WalkState->ControlState->Common.State == 748c2c66affSColin Finck ACPI_CONTROL_PREDICATE_EXECUTING) && 749c2c66affSColin Finck (WalkState->ControlState->Control.PredicateOp == Op)) 750c2c66affSColin Finck { 751c2c66affSColin Finck Status = AcpiDsGetPredicateValue (WalkState, WalkState->ResultObj); 752c2c66affSColin Finck WalkState->ResultObj = NULL; 753c2c66affSColin Finck } 754c2c66affSColin Finck 755c2c66affSColin Finck 756c2c66affSColin Finck Cleanup: 757c2c66affSColin Finck 758c2c66affSColin Finck if (WalkState->ResultObj) 759c2c66affSColin Finck { 760c2c66affSColin Finck /* Break to debugger to display result */ 761c2c66affSColin Finck 762c2c66affSColin Finck AcpiDbDisplayResultObject (WalkState->ResultObj,WalkState); 763c2c66affSColin Finck 764c2c66affSColin Finck /* 765c2c66affSColin Finck * Delete the result op if and only if: 766c2c66affSColin Finck * Parent will not use the result -- such as any 767c2c66affSColin Finck * non-nested type2 op in a method (parent will be method) 768c2c66affSColin Finck */ 769c2c66affSColin Finck AcpiDsDeleteResultIfNotUsed (Op, WalkState->ResultObj, WalkState); 770c2c66affSColin Finck } 771c2c66affSColin Finck 772c2c66affSColin Finck #ifdef _UNDER_DEVELOPMENT 773c2c66affSColin Finck 774c2c66affSColin Finck if (WalkState->ParserState.Aml == WalkState->ParserState.AmlEnd) 775c2c66affSColin Finck { 776c2c66affSColin Finck AcpiDbMethodEnd (WalkState); 777c2c66affSColin Finck } 778c2c66affSColin Finck #endif 779c2c66affSColin Finck 780c2c66affSColin Finck /* Invoke exception handler on error */ 781c2c66affSColin Finck 782c2c66affSColin Finck if (ACPI_FAILURE (Status)) 783c2c66affSColin Finck { 784c2c66affSColin Finck Status = AcpiDsMethodError (Status, WalkState); 785c2c66affSColin Finck } 786c2c66affSColin Finck 787c2c66affSColin Finck /* Always clear the object stack */ 788c2c66affSColin Finck 789c2c66affSColin Finck WalkState->NumOperands = 0; 790c2c66affSColin Finck return_ACPI_STATUS (Status); 791c2c66affSColin Finck } 792