1db2bae30SDana Myers /****************************************************************************** 2db2bae30SDana Myers * 3db2bae30SDana Myers * Module Name: exoparg2 - AML execution - opcodes with 2 arguments 4db2bae30SDana Myers * 5db2bae30SDana Myers *****************************************************************************/ 6db2bae30SDana Myers 726f3cdf0SGordon Ross /* 8*385cc6b4SJerry Jelinek * Copyright (C) 2000 - 2016, Intel Corp. 9db2bae30SDana Myers * All rights reserved. 10db2bae30SDana Myers * 1126f3cdf0SGordon Ross * Redistribution and use in source and binary forms, with or without 1226f3cdf0SGordon Ross * modification, are permitted provided that the following conditions 1326f3cdf0SGordon Ross * are met: 1426f3cdf0SGordon Ross * 1. Redistributions of source code must retain the above copyright 1526f3cdf0SGordon Ross * notice, this list of conditions, and the following disclaimer, 1626f3cdf0SGordon Ross * without modification. 1726f3cdf0SGordon Ross * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1826f3cdf0SGordon Ross * substantially similar to the "NO WARRANTY" disclaimer below 1926f3cdf0SGordon Ross * ("Disclaimer") and any redistribution must be conditioned upon 2026f3cdf0SGordon Ross * including a substantially similar Disclaimer requirement for further 2126f3cdf0SGordon Ross * binary redistribution. 2226f3cdf0SGordon Ross * 3. Neither the names of the above-listed copyright holders nor the names 2326f3cdf0SGordon Ross * of any contributors may be used to endorse or promote products derived 2426f3cdf0SGordon Ross * from this software without specific prior written permission. 25db2bae30SDana Myers * 2626f3cdf0SGordon Ross * Alternatively, this software may be distributed under the terms of the 2726f3cdf0SGordon Ross * GNU General Public License ("GPL") version 2 as published by the Free 2826f3cdf0SGordon Ross * Software Foundation. 29db2bae30SDana Myers * 3026f3cdf0SGordon Ross * NO WARRANTY 3126f3cdf0SGordon Ross * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3226f3cdf0SGordon Ross * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3326f3cdf0SGordon Ross * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3426f3cdf0SGordon Ross * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3526f3cdf0SGordon Ross * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3626f3cdf0SGordon Ross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3726f3cdf0SGordon Ross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3826f3cdf0SGordon Ross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3926f3cdf0SGordon Ross * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4026f3cdf0SGordon Ross * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4126f3cdf0SGordon Ross * POSSIBILITY OF SUCH DAMAGES. 4226f3cdf0SGordon Ross */ 43db2bae30SDana Myers 44db2bae30SDana Myers #include "acpi.h" 45aa2aa9a6SDana Myers #include "accommon.h" 46db2bae30SDana Myers #include "acparser.h" 47db2bae30SDana Myers #include "acinterp.h" 48db2bae30SDana Myers #include "acevents.h" 49db2bae30SDana Myers #include "amlcode.h" 50db2bae30SDana Myers 51db2bae30SDana Myers 52db2bae30SDana Myers #define _COMPONENT ACPI_EXECUTER 53db2bae30SDana Myers ACPI_MODULE_NAME ("exoparg2") 54db2bae30SDana Myers 55db2bae30SDana Myers 56db2bae30SDana Myers /*! 57db2bae30SDana Myers * Naming convention for AML interpreter execution routines. 58db2bae30SDana Myers * 59db2bae30SDana Myers * The routines that begin execution of AML opcodes are named with a common 60db2bae30SDana Myers * convention based upon the number of arguments, the number of target operands, 61db2bae30SDana Myers * and whether or not a value is returned: 62db2bae30SDana Myers * 63db2bae30SDana Myers * AcpiExOpcode_xA_yT_zR 64db2bae30SDana Myers * 65db2bae30SDana Myers * Where: 66db2bae30SDana Myers * 67db2bae30SDana Myers * xA - ARGUMENTS: The number of arguments (input operands) that are 68db2bae30SDana Myers * required for this opcode type (1 through 6 args). 69db2bae30SDana Myers * yT - TARGETS: The number of targets (output operands) that are required 70db2bae30SDana Myers * for this opcode type (0, 1, or 2 targets). 71db2bae30SDana Myers * zR - RETURN VALUE: Indicates whether this opcode type returns a value 72db2bae30SDana Myers * as the function return (0 or 1). 73db2bae30SDana Myers * 74db2bae30SDana Myers * The AcpiExOpcode* functions are called via the Dispatcher component with 75db2bae30SDana Myers * fully resolved operands. 76db2bae30SDana Myers !*/ 77db2bae30SDana Myers 78db2bae30SDana Myers 79db2bae30SDana Myers /******************************************************************************* 80db2bae30SDana Myers * 81db2bae30SDana Myers * FUNCTION: AcpiExOpcode_2A_0T_0R 82db2bae30SDana Myers * 83db2bae30SDana Myers * PARAMETERS: WalkState - Current walk state 84db2bae30SDana Myers * 85db2bae30SDana Myers * RETURN: Status 86db2bae30SDana Myers * 87db2bae30SDana Myers * DESCRIPTION: Execute opcode with two arguments, no target, and no return 88db2bae30SDana Myers * value. 89db2bae30SDana Myers * 90db2bae30SDana Myers * ALLOCATION: Deletes both operands 91db2bae30SDana Myers * 92db2bae30SDana Myers ******************************************************************************/ 93db2bae30SDana Myers 94db2bae30SDana Myers ACPI_STATUS 95db2bae30SDana Myers AcpiExOpcode_2A_0T_0R ( 96db2bae30SDana Myers ACPI_WALK_STATE *WalkState) 97db2bae30SDana Myers { 98db2bae30SDana Myers ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 99db2bae30SDana Myers ACPI_NAMESPACE_NODE *Node; 100db2bae30SDana Myers UINT32 Value; 101db2bae30SDana Myers ACPI_STATUS Status = AE_OK; 102db2bae30SDana Myers 103db2bae30SDana Myers 104db2bae30SDana Myers ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_0T_0R, 105db2bae30SDana Myers AcpiPsGetOpcodeName (WalkState->Opcode)); 106db2bae30SDana Myers 107db2bae30SDana Myers 108db2bae30SDana Myers /* Examine the opcode */ 109db2bae30SDana Myers 110db2bae30SDana Myers switch (WalkState->Opcode) 111db2bae30SDana Myers { 112db2bae30SDana Myers case AML_NOTIFY_OP: /* Notify (NotifyObject, NotifyValue) */ 113db2bae30SDana Myers 114db2bae30SDana Myers /* The first operand is a namespace node */ 115db2bae30SDana Myers 116db2bae30SDana Myers Node = (ACPI_NAMESPACE_NODE *) Operand[0]; 117db2bae30SDana Myers 118db2bae30SDana Myers /* Second value is the notify value */ 119db2bae30SDana Myers 120db2bae30SDana Myers Value = (UINT32) Operand[1]->Integer.Value; 121db2bae30SDana Myers 122db2bae30SDana Myers /* Are notifies allowed on this object? */ 123db2bae30SDana Myers 124db2bae30SDana Myers if (!AcpiEvIsNotifyObject (Node)) 125db2bae30SDana Myers { 126db2bae30SDana Myers ACPI_ERROR ((AE_INFO, 127db2bae30SDana Myers "Unexpected notify object type [%s]", 128db2bae30SDana Myers AcpiUtGetTypeName (Node->Type))); 129db2bae30SDana Myers 130db2bae30SDana Myers Status = AE_AML_OPERAND_TYPE; 131db2bae30SDana Myers break; 132db2bae30SDana Myers } 133db2bae30SDana Myers 134db2bae30SDana Myers /* 135db2bae30SDana Myers * Dispatch the notify to the appropriate handler 136db2bae30SDana Myers * NOTE: the request is queued for execution after this method 137db2bae30SDana Myers * completes. The notify handlers are NOT invoked synchronously 138db2bae30SDana Myers * from this thread -- because handlers may in turn run other 139db2bae30SDana Myers * control methods. 140db2bae30SDana Myers */ 141db2bae30SDana Myers Status = AcpiEvQueueNotifyRequest (Node, Value); 142db2bae30SDana Myers break; 143db2bae30SDana Myers 144db2bae30SDana Myers default: 145db2bae30SDana Myers 14626f3cdf0SGordon Ross ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", 147db2bae30SDana Myers WalkState->Opcode)); 148db2bae30SDana Myers Status = AE_AML_BAD_OPCODE; 149db2bae30SDana Myers } 150db2bae30SDana Myers 151db2bae30SDana Myers return_ACPI_STATUS (Status); 152db2bae30SDana Myers } 153db2bae30SDana Myers 154db2bae30SDana Myers 155db2bae30SDana Myers /******************************************************************************* 156db2bae30SDana Myers * 157db2bae30SDana Myers * FUNCTION: AcpiExOpcode_2A_2T_1R 158db2bae30SDana Myers * 159db2bae30SDana Myers * PARAMETERS: WalkState - Current walk state 160db2bae30SDana Myers * 161db2bae30SDana Myers * RETURN: Status 162db2bae30SDana Myers * 163db2bae30SDana Myers * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets 164db2bae30SDana Myers * and one implicit return value. 165db2bae30SDana Myers * 166db2bae30SDana Myers ******************************************************************************/ 167db2bae30SDana Myers 168db2bae30SDana Myers ACPI_STATUS 169db2bae30SDana Myers AcpiExOpcode_2A_2T_1R ( 170db2bae30SDana Myers ACPI_WALK_STATE *WalkState) 171db2bae30SDana Myers { 172db2bae30SDana Myers ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 173db2bae30SDana Myers ACPI_OPERAND_OBJECT *ReturnDesc1 = NULL; 174db2bae30SDana Myers ACPI_OPERAND_OBJECT *ReturnDesc2 = NULL; 175db2bae30SDana Myers ACPI_STATUS Status; 176db2bae30SDana Myers 177db2bae30SDana Myers 178db2bae30SDana Myers ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_2T_1R, 179db2bae30SDana Myers AcpiPsGetOpcodeName (WalkState->Opcode)); 180db2bae30SDana Myers 181db2bae30SDana Myers 182db2bae30SDana Myers /* Execute the opcode */ 183db2bae30SDana Myers 184db2bae30SDana Myers switch (WalkState->Opcode) 185db2bae30SDana Myers { 186db2bae30SDana Myers case AML_DIVIDE_OP: 187db2bae30SDana Myers 188db2bae30SDana Myers /* Divide (Dividend, Divisor, RemainderResult QuotientResult) */ 189db2bae30SDana Myers 190db2bae30SDana Myers ReturnDesc1 = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 191db2bae30SDana Myers if (!ReturnDesc1) 192db2bae30SDana Myers { 193db2bae30SDana Myers Status = AE_NO_MEMORY; 194db2bae30SDana Myers goto Cleanup; 195db2bae30SDana Myers } 196db2bae30SDana Myers 197db2bae30SDana Myers ReturnDesc2 = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 198db2bae30SDana Myers if (!ReturnDesc2) 199db2bae30SDana Myers { 200db2bae30SDana Myers Status = AE_NO_MEMORY; 201db2bae30SDana Myers goto Cleanup; 202db2bae30SDana Myers } 203db2bae30SDana Myers 204db2bae30SDana Myers /* Quotient to ReturnDesc1, remainder to ReturnDesc2 */ 205db2bae30SDana Myers 206*385cc6b4SJerry Jelinek Status = AcpiUtDivide ( 207*385cc6b4SJerry Jelinek Operand[0]->Integer.Value, 208db2bae30SDana Myers Operand[1]->Integer.Value, 209db2bae30SDana Myers &ReturnDesc1->Integer.Value, 210db2bae30SDana Myers &ReturnDesc2->Integer.Value); 211db2bae30SDana Myers if (ACPI_FAILURE (Status)) 212db2bae30SDana Myers { 213db2bae30SDana Myers goto Cleanup; 214db2bae30SDana Myers } 215db2bae30SDana Myers break; 216db2bae30SDana Myers 217db2bae30SDana Myers default: 218db2bae30SDana Myers 21926f3cdf0SGordon Ross ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", 220db2bae30SDana Myers WalkState->Opcode)); 221*385cc6b4SJerry Jelinek 222db2bae30SDana Myers Status = AE_AML_BAD_OPCODE; 223db2bae30SDana Myers goto Cleanup; 224db2bae30SDana Myers } 225db2bae30SDana Myers 226db2bae30SDana Myers /* Store the results to the target reference operands */ 227db2bae30SDana Myers 228db2bae30SDana Myers Status = AcpiExStore (ReturnDesc2, Operand[2], WalkState); 229db2bae30SDana Myers if (ACPI_FAILURE (Status)) 230db2bae30SDana Myers { 231db2bae30SDana Myers goto Cleanup; 232db2bae30SDana Myers } 233db2bae30SDana Myers 234db2bae30SDana Myers Status = AcpiExStore (ReturnDesc1, Operand[3], WalkState); 235db2bae30SDana Myers if (ACPI_FAILURE (Status)) 236db2bae30SDana Myers { 237db2bae30SDana Myers goto Cleanup; 238db2bae30SDana Myers } 239db2bae30SDana Myers 240db2bae30SDana Myers Cleanup: 241db2bae30SDana Myers /* 242db2bae30SDana Myers * Since the remainder is not returned indirectly, remove a reference to 243db2bae30SDana Myers * it. Only the quotient is returned indirectly. 244db2bae30SDana Myers */ 245db2bae30SDana Myers AcpiUtRemoveReference (ReturnDesc2); 246db2bae30SDana Myers 247db2bae30SDana Myers if (ACPI_FAILURE (Status)) 248db2bae30SDana Myers { 249db2bae30SDana Myers /* Delete the return object */ 250db2bae30SDana Myers 251db2bae30SDana Myers AcpiUtRemoveReference (ReturnDesc1); 252db2bae30SDana Myers } 253db2bae30SDana Myers 254db2bae30SDana Myers /* Save return object (the remainder) on success */ 255db2bae30SDana Myers 256db2bae30SDana Myers else 257db2bae30SDana Myers { 258db2bae30SDana Myers WalkState->ResultObj = ReturnDesc1; 259db2bae30SDana Myers } 260db2bae30SDana Myers 261db2bae30SDana Myers return_ACPI_STATUS (Status); 262db2bae30SDana Myers } 263db2bae30SDana Myers 264db2bae30SDana Myers 265db2bae30SDana Myers /******************************************************************************* 266db2bae30SDana Myers * 267db2bae30SDana Myers * FUNCTION: AcpiExOpcode_2A_1T_1R 268db2bae30SDana Myers * 269db2bae30SDana Myers * PARAMETERS: WalkState - Current walk state 270db2bae30SDana Myers * 271db2bae30SDana Myers * RETURN: Status 272db2bae30SDana Myers * 273db2bae30SDana Myers * DESCRIPTION: Execute opcode with two arguments, one target, and a return 274db2bae30SDana Myers * value. 275db2bae30SDana Myers * 276db2bae30SDana Myers ******************************************************************************/ 277db2bae30SDana Myers 278db2bae30SDana Myers ACPI_STATUS 279db2bae30SDana Myers AcpiExOpcode_2A_1T_1R ( 280db2bae30SDana Myers ACPI_WALK_STATE *WalkState) 281db2bae30SDana Myers { 282db2bae30SDana Myers ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 283db2bae30SDana Myers ACPI_OPERAND_OBJECT *ReturnDesc = NULL; 28426f3cdf0SGordon Ross UINT64 Index; 285db2bae30SDana Myers ACPI_STATUS Status = AE_OK; 286*385cc6b4SJerry Jelinek ACPI_SIZE Length = 0; 287db2bae30SDana Myers 288db2bae30SDana Myers 289db2bae30SDana Myers ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_1T_1R, 290db2bae30SDana Myers AcpiPsGetOpcodeName (WalkState->Opcode)); 291db2bae30SDana Myers 292db2bae30SDana Myers 293db2bae30SDana Myers /* Execute the opcode */ 294db2bae30SDana Myers 295db2bae30SDana Myers if (WalkState->OpInfo->Flags & AML_MATH) 296db2bae30SDana Myers { 297db2bae30SDana Myers /* All simple math opcodes (add, etc.) */ 298db2bae30SDana Myers 299db2bae30SDana Myers ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 300db2bae30SDana Myers if (!ReturnDesc) 301db2bae30SDana Myers { 302db2bae30SDana Myers Status = AE_NO_MEMORY; 303db2bae30SDana Myers goto Cleanup; 304db2bae30SDana Myers } 305db2bae30SDana Myers 306*385cc6b4SJerry Jelinek ReturnDesc->Integer.Value = AcpiExDoMathOp ( 307*385cc6b4SJerry Jelinek WalkState->Opcode, 308db2bae30SDana Myers Operand[0]->Integer.Value, 309db2bae30SDana Myers Operand[1]->Integer.Value); 310db2bae30SDana Myers goto StoreResultToTarget; 311db2bae30SDana Myers } 312db2bae30SDana Myers 313db2bae30SDana Myers switch (WalkState->Opcode) 314db2bae30SDana Myers { 315db2bae30SDana Myers case AML_MOD_OP: /* Mod (Dividend, Divisor, RemainderResult (ACPI 2.0) */ 316db2bae30SDana Myers 317db2bae30SDana Myers ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 318db2bae30SDana Myers if (!ReturnDesc) 319db2bae30SDana Myers { 320db2bae30SDana Myers Status = AE_NO_MEMORY; 321db2bae30SDana Myers goto Cleanup; 322db2bae30SDana Myers } 323db2bae30SDana Myers 324db2bae30SDana Myers /* ReturnDesc will contain the remainder */ 325db2bae30SDana Myers 326*385cc6b4SJerry Jelinek Status = AcpiUtDivide ( 327*385cc6b4SJerry Jelinek Operand[0]->Integer.Value, 328db2bae30SDana Myers Operand[1]->Integer.Value, 329db2bae30SDana Myers NULL, 330db2bae30SDana Myers &ReturnDesc->Integer.Value); 331db2bae30SDana Myers break; 332db2bae30SDana Myers 333db2bae30SDana Myers case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */ 334db2bae30SDana Myers 335*385cc6b4SJerry Jelinek Status = AcpiExDoConcatenate ( 336*385cc6b4SJerry Jelinek Operand[0], Operand[1], &ReturnDesc, WalkState); 337db2bae30SDana Myers break; 338db2bae30SDana Myers 339db2bae30SDana Myers case AML_TO_STRING_OP: /* ToString (Buffer, Length, Result) (ACPI 2.0) */ 340db2bae30SDana Myers /* 341db2bae30SDana Myers * Input object is guaranteed to be a buffer at this point (it may have 342db2bae30SDana Myers * been converted.) Copy the raw buffer data to a new object of 343db2bae30SDana Myers * type String. 344db2bae30SDana Myers */ 345db2bae30SDana Myers 346db2bae30SDana Myers /* 347db2bae30SDana Myers * Get the length of the new string. It is the smallest of: 348db2bae30SDana Myers * 1) Length of the input buffer 349db2bae30SDana Myers * 2) Max length as specified in the ToString operator 350db2bae30SDana Myers * 3) Length of input buffer up to a zero byte (null terminator) 351db2bae30SDana Myers * 352db2bae30SDana Myers * NOTE: A length of zero is ok, and will create a zero-length, null 353db2bae30SDana Myers * terminated string. 354db2bae30SDana Myers */ 355db2bae30SDana Myers while ((Length < Operand[0]->Buffer.Length) && 356db2bae30SDana Myers (Length < Operand[1]->Integer.Value) && 357db2bae30SDana Myers (Operand[0]->Buffer.Pointer[Length])) 358db2bae30SDana Myers { 359db2bae30SDana Myers Length++; 360db2bae30SDana Myers } 361db2bae30SDana Myers 362db2bae30SDana Myers /* Allocate a new string object */ 363db2bae30SDana Myers 364db2bae30SDana Myers ReturnDesc = AcpiUtCreateStringObject (Length); 365db2bae30SDana Myers if (!ReturnDesc) 366db2bae30SDana Myers { 367db2bae30SDana Myers Status = AE_NO_MEMORY; 368db2bae30SDana Myers goto Cleanup; 369db2bae30SDana Myers } 370db2bae30SDana Myers 371db2bae30SDana Myers /* 372db2bae30SDana Myers * Copy the raw buffer data with no transform. 373db2bae30SDana Myers * (NULL terminated already) 374db2bae30SDana Myers */ 375*385cc6b4SJerry Jelinek memcpy (ReturnDesc->String.Pointer, 376db2bae30SDana Myers Operand[0]->Buffer.Pointer, Length); 377db2bae30SDana Myers break; 378db2bae30SDana Myers 379db2bae30SDana Myers case AML_CONCAT_RES_OP: 380db2bae30SDana Myers 381db2bae30SDana Myers /* ConcatenateResTemplate (Buffer, Buffer, Result) (ACPI 2.0) */ 382db2bae30SDana Myers 383*385cc6b4SJerry Jelinek Status = AcpiExConcatTemplate ( 384*385cc6b4SJerry Jelinek Operand[0], Operand[1], &ReturnDesc, WalkState); 385db2bae30SDana Myers break; 386db2bae30SDana Myers 387db2bae30SDana Myers case AML_INDEX_OP: /* Index (Source Index Result) */ 388db2bae30SDana Myers 389db2bae30SDana Myers /* Create the internal return object */ 390db2bae30SDana Myers 391db2bae30SDana Myers ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); 392db2bae30SDana Myers if (!ReturnDesc) 393db2bae30SDana Myers { 394db2bae30SDana Myers Status = AE_NO_MEMORY; 395db2bae30SDana Myers goto Cleanup; 396db2bae30SDana Myers } 397db2bae30SDana Myers 398db2bae30SDana Myers /* Initialize the Index reference object */ 399db2bae30SDana Myers 400db2bae30SDana Myers Index = Operand[1]->Integer.Value; 401db2bae30SDana Myers ReturnDesc->Reference.Value = (UINT32) Index; 402db2bae30SDana Myers ReturnDesc->Reference.Class = ACPI_REFCLASS_INDEX; 403db2bae30SDana Myers 404db2bae30SDana Myers /* 405db2bae30SDana Myers * At this point, the Source operand is a String, Buffer, or Package. 406db2bae30SDana Myers * Verify that the index is within range. 407db2bae30SDana Myers */ 408aa2aa9a6SDana Myers switch ((Operand[0])->Common.Type) 409db2bae30SDana Myers { 410db2bae30SDana Myers case ACPI_TYPE_STRING: 411db2bae30SDana Myers 412db2bae30SDana Myers if (Index >= Operand[0]->String.Length) 413db2bae30SDana Myers { 414*385cc6b4SJerry Jelinek Length = Operand[0]->String.Length; 415db2bae30SDana Myers Status = AE_AML_STRING_LIMIT; 416db2bae30SDana Myers } 417db2bae30SDana Myers 418db2bae30SDana Myers ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD; 419*385cc6b4SJerry Jelinek ReturnDesc->Reference.IndexPointer = 420*385cc6b4SJerry Jelinek &(Operand[0]->Buffer.Pointer [Index]); 421db2bae30SDana Myers break; 422db2bae30SDana Myers 423db2bae30SDana Myers case ACPI_TYPE_BUFFER: 424db2bae30SDana Myers 425db2bae30SDana Myers if (Index >= Operand[0]->Buffer.Length) 426db2bae30SDana Myers { 427*385cc6b4SJerry Jelinek Length = Operand[0]->Buffer.Length; 428db2bae30SDana Myers Status = AE_AML_BUFFER_LIMIT; 429db2bae30SDana Myers } 430db2bae30SDana Myers 431db2bae30SDana Myers ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD; 432*385cc6b4SJerry Jelinek ReturnDesc->Reference.IndexPointer = 433*385cc6b4SJerry Jelinek &(Operand[0]->Buffer.Pointer [Index]); 434db2bae30SDana Myers break; 435db2bae30SDana Myers 436db2bae30SDana Myers case ACPI_TYPE_PACKAGE: 437db2bae30SDana Myers 438db2bae30SDana Myers if (Index >= Operand[0]->Package.Count) 439db2bae30SDana Myers { 440*385cc6b4SJerry Jelinek Length = Operand[0]->Package.Count; 441db2bae30SDana Myers Status = AE_AML_PACKAGE_LIMIT; 442db2bae30SDana Myers } 443db2bae30SDana Myers 444db2bae30SDana Myers ReturnDesc->Reference.TargetType = ACPI_TYPE_PACKAGE; 445*385cc6b4SJerry Jelinek ReturnDesc->Reference.Where = 446*385cc6b4SJerry Jelinek &Operand[0]->Package.Elements [Index]; 447db2bae30SDana Myers break; 448db2bae30SDana Myers 449db2bae30SDana Myers default: 450db2bae30SDana Myers 451db2bae30SDana Myers Status = AE_AML_INTERNAL; 452db2bae30SDana Myers goto Cleanup; 453db2bae30SDana Myers } 454db2bae30SDana Myers 455db2bae30SDana Myers /* Failure means that the Index was beyond the end of the object */ 456db2bae30SDana Myers 457db2bae30SDana Myers if (ACPI_FAILURE (Status)) 458db2bae30SDana Myers { 459db2bae30SDana Myers ACPI_EXCEPTION ((AE_INFO, Status, 460*385cc6b4SJerry Jelinek "Index (0x%X%8.8X) is beyond end of object (length 0x%X)", 461*385cc6b4SJerry Jelinek ACPI_FORMAT_UINT64 (Index), (UINT32) Length)); 462db2bae30SDana Myers goto Cleanup; 463db2bae30SDana Myers } 464db2bae30SDana Myers 465db2bae30SDana Myers /* 466db2bae30SDana Myers * Save the target object and add a reference to it for the life 467db2bae30SDana Myers * of the index 468db2bae30SDana Myers */ 469db2bae30SDana Myers ReturnDesc->Reference.Object = Operand[0]; 470db2bae30SDana Myers AcpiUtAddReference (Operand[0]); 471db2bae30SDana Myers 472db2bae30SDana Myers /* Store the reference to the Target */ 473db2bae30SDana Myers 474db2bae30SDana Myers Status = AcpiExStore (ReturnDesc, Operand[2], WalkState); 475db2bae30SDana Myers 476db2bae30SDana Myers /* Return the reference */ 477db2bae30SDana Myers 478db2bae30SDana Myers WalkState->ResultObj = ReturnDesc; 479db2bae30SDana Myers goto Cleanup; 480db2bae30SDana Myers 481db2bae30SDana Myers default: 482db2bae30SDana Myers 48326f3cdf0SGordon Ross ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", 484db2bae30SDana Myers WalkState->Opcode)); 485db2bae30SDana Myers Status = AE_AML_BAD_OPCODE; 486db2bae30SDana Myers break; 487db2bae30SDana Myers } 488db2bae30SDana Myers 489db2bae30SDana Myers 490db2bae30SDana Myers StoreResultToTarget: 491db2bae30SDana Myers 492db2bae30SDana Myers if (ACPI_SUCCESS (Status)) 493db2bae30SDana Myers { 494db2bae30SDana Myers /* 495db2bae30SDana Myers * Store the result of the operation (which is now in ReturnDesc) into 496db2bae30SDana Myers * the Target descriptor. 497db2bae30SDana Myers */ 498db2bae30SDana Myers Status = AcpiExStore (ReturnDesc, Operand[2], WalkState); 499db2bae30SDana Myers if (ACPI_FAILURE (Status)) 500db2bae30SDana Myers { 501db2bae30SDana Myers goto Cleanup; 502db2bae30SDana Myers } 503db2bae30SDana Myers 504db2bae30SDana Myers if (!WalkState->ResultObj) 505db2bae30SDana Myers { 506db2bae30SDana Myers WalkState->ResultObj = ReturnDesc; 507db2bae30SDana Myers } 508db2bae30SDana Myers } 509db2bae30SDana Myers 510db2bae30SDana Myers 511db2bae30SDana Myers Cleanup: 512db2bae30SDana Myers 513db2bae30SDana Myers /* Delete return object on error */ 514db2bae30SDana Myers 515db2bae30SDana Myers if (ACPI_FAILURE (Status)) 516db2bae30SDana Myers { 517db2bae30SDana Myers AcpiUtRemoveReference (ReturnDesc); 518db2bae30SDana Myers WalkState->ResultObj = NULL; 519db2bae30SDana Myers } 520db2bae30SDana Myers 521db2bae30SDana Myers return_ACPI_STATUS (Status); 522db2bae30SDana Myers } 523db2bae30SDana Myers 524db2bae30SDana Myers 525db2bae30SDana Myers /******************************************************************************* 526db2bae30SDana Myers * 527db2bae30SDana Myers * FUNCTION: AcpiExOpcode_2A_0T_1R 528db2bae30SDana Myers * 529db2bae30SDana Myers * PARAMETERS: WalkState - Current walk state 530db2bae30SDana Myers * 531db2bae30SDana Myers * RETURN: Status 532db2bae30SDana Myers * 533db2bae30SDana Myers * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value 534db2bae30SDana Myers * 535db2bae30SDana Myers ******************************************************************************/ 536db2bae30SDana Myers 537db2bae30SDana Myers ACPI_STATUS 538db2bae30SDana Myers AcpiExOpcode_2A_0T_1R ( 539db2bae30SDana Myers ACPI_WALK_STATE *WalkState) 540db2bae30SDana Myers { 541db2bae30SDana Myers ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 542db2bae30SDana Myers ACPI_OPERAND_OBJECT *ReturnDesc = NULL; 543db2bae30SDana Myers ACPI_STATUS Status = AE_OK; 544db2bae30SDana Myers BOOLEAN LogicalResult = FALSE; 545db2bae30SDana Myers 546db2bae30SDana Myers 547db2bae30SDana Myers ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_0T_1R, 548db2bae30SDana Myers AcpiPsGetOpcodeName (WalkState->Opcode)); 549db2bae30SDana Myers 550db2bae30SDana Myers 551db2bae30SDana Myers /* Create the internal return object */ 552db2bae30SDana Myers 553db2bae30SDana Myers ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 554db2bae30SDana Myers if (!ReturnDesc) 555db2bae30SDana Myers { 556db2bae30SDana Myers Status = AE_NO_MEMORY; 557db2bae30SDana Myers goto Cleanup; 558db2bae30SDana Myers } 559db2bae30SDana Myers 560db2bae30SDana Myers /* Execute the Opcode */ 561db2bae30SDana Myers 562db2bae30SDana Myers if (WalkState->OpInfo->Flags & AML_LOGICAL_NUMERIC) 563db2bae30SDana Myers { 564db2bae30SDana Myers /* LogicalOp (Operand0, Operand1) */ 565db2bae30SDana Myers 566db2bae30SDana Myers Status = AcpiExDoLogicalNumericOp (WalkState->Opcode, 567db2bae30SDana Myers Operand[0]->Integer.Value, Operand[1]->Integer.Value, 568db2bae30SDana Myers &LogicalResult); 569db2bae30SDana Myers goto StoreLogicalResult; 570db2bae30SDana Myers } 571db2bae30SDana Myers else if (WalkState->OpInfo->Flags & AML_LOGICAL) 572db2bae30SDana Myers { 573db2bae30SDana Myers /* LogicalOp (Operand0, Operand1) */ 574db2bae30SDana Myers 575db2bae30SDana Myers Status = AcpiExDoLogicalOp (WalkState->Opcode, Operand[0], 576db2bae30SDana Myers Operand[1], &LogicalResult); 577db2bae30SDana Myers goto StoreLogicalResult; 578db2bae30SDana Myers } 579db2bae30SDana Myers 580db2bae30SDana Myers switch (WalkState->Opcode) 581db2bae30SDana Myers { 582db2bae30SDana Myers case AML_ACQUIRE_OP: /* Acquire (MutexObject, Timeout) */ 583db2bae30SDana Myers 584db2bae30SDana Myers Status = AcpiExAcquireMutex (Operand[1], Operand[0], WalkState); 585db2bae30SDana Myers if (Status == AE_TIME) 586db2bae30SDana Myers { 587db2bae30SDana Myers LogicalResult = TRUE; /* TRUE = Acquire timed out */ 588db2bae30SDana Myers Status = AE_OK; 589db2bae30SDana Myers } 590db2bae30SDana Myers break; 591db2bae30SDana Myers 592db2bae30SDana Myers 593db2bae30SDana Myers case AML_WAIT_OP: /* Wait (EventObject, Timeout) */ 594db2bae30SDana Myers 595db2bae30SDana Myers Status = AcpiExSystemWaitEvent (Operand[1], Operand[0]); 596db2bae30SDana Myers if (Status == AE_TIME) 597db2bae30SDana Myers { 598db2bae30SDana Myers LogicalResult = TRUE; /* TRUE, Wait timed out */ 599db2bae30SDana Myers Status = AE_OK; 600db2bae30SDana Myers } 601db2bae30SDana Myers break; 602db2bae30SDana Myers 603db2bae30SDana Myers default: 604db2bae30SDana Myers 60526f3cdf0SGordon Ross ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", 606db2bae30SDana Myers WalkState->Opcode)); 607*385cc6b4SJerry Jelinek 608db2bae30SDana Myers Status = AE_AML_BAD_OPCODE; 609db2bae30SDana Myers goto Cleanup; 610db2bae30SDana Myers } 611db2bae30SDana Myers 612db2bae30SDana Myers 613db2bae30SDana Myers StoreLogicalResult: 614db2bae30SDana Myers /* 615db2bae30SDana Myers * Set return value to according to LogicalResult. logical TRUE (all ones) 616db2bae30SDana Myers * Default is FALSE (zero) 617db2bae30SDana Myers */ 618db2bae30SDana Myers if (LogicalResult) 619db2bae30SDana Myers { 62026f3cdf0SGordon Ross ReturnDesc->Integer.Value = ACPI_UINT64_MAX; 621db2bae30SDana Myers } 622db2bae30SDana Myers 623db2bae30SDana Myers Cleanup: 624db2bae30SDana Myers 625db2bae30SDana Myers /* Delete return object on error */ 626db2bae30SDana Myers 627db2bae30SDana Myers if (ACPI_FAILURE (Status)) 628db2bae30SDana Myers { 629db2bae30SDana Myers AcpiUtRemoveReference (ReturnDesc); 630db2bae30SDana Myers } 631db2bae30SDana Myers 632db2bae30SDana Myers /* Save return object on success */ 633db2bae30SDana Myers 634db2bae30SDana Myers else 635db2bae30SDana Myers { 636db2bae30SDana Myers WalkState->ResultObj = ReturnDesc; 637db2bae30SDana Myers } 638db2bae30SDana Myers 639db2bae30SDana Myers return_ACPI_STATUS (Status); 640db2bae30SDana Myers } 641