1a159c266SJung-uk Kim /****************************************************************************** 2a159c266SJung-uk Kim * 3a159c266SJung-uk Kim * Module Name: exoparg1 - AML execution - opcodes with 1 argument 4a159c266SJung-uk Kim * 5a159c266SJung-uk Kim *****************************************************************************/ 6a159c266SJung-uk Kim 7a159c266SJung-uk Kim /* 8f8146b88SJung-uk Kim * Copyright (C) 2000 - 2016, Intel Corp. 9a159c266SJung-uk Kim * All rights reserved. 10a159c266SJung-uk Kim * 11a159c266SJung-uk Kim * Redistribution and use in source and binary forms, with or without 12a159c266SJung-uk Kim * modification, are permitted provided that the following conditions 13a159c266SJung-uk Kim * are met: 14a159c266SJung-uk Kim * 1. Redistributions of source code must retain the above copyright 15a159c266SJung-uk Kim * notice, this list of conditions, and the following disclaimer, 16a159c266SJung-uk Kim * without modification. 17a159c266SJung-uk Kim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18a159c266SJung-uk Kim * substantially similar to the "NO WARRANTY" disclaimer below 19a159c266SJung-uk Kim * ("Disclaimer") and any redistribution must be conditioned upon 20a159c266SJung-uk Kim * including a substantially similar Disclaimer requirement for further 21a159c266SJung-uk Kim * binary redistribution. 22a159c266SJung-uk Kim * 3. Neither the names of the above-listed copyright holders nor the names 23a159c266SJung-uk Kim * of any contributors may be used to endorse or promote products derived 24a159c266SJung-uk Kim * from this software without specific prior written permission. 25a159c266SJung-uk Kim * 26a159c266SJung-uk Kim * Alternatively, this software may be distributed under the terms of the 27a159c266SJung-uk Kim * GNU General Public License ("GPL") version 2 as published by the Free 28a159c266SJung-uk Kim * Software Foundation. 29a159c266SJung-uk Kim * 30a159c266SJung-uk Kim * NO WARRANTY 31a159c266SJung-uk Kim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32a159c266SJung-uk Kim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33a159c266SJung-uk Kim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34a159c266SJung-uk Kim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35a159c266SJung-uk Kim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36a159c266SJung-uk Kim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37a159c266SJung-uk Kim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38a159c266SJung-uk Kim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39a159c266SJung-uk Kim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40a159c266SJung-uk Kim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41a159c266SJung-uk Kim * POSSIBILITY OF SUCH DAMAGES. 42a159c266SJung-uk Kim */ 43a159c266SJung-uk Kim 44a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acpi.h> 45a159c266SJung-uk Kim #include <contrib/dev/acpica/include/accommon.h> 46a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acparser.h> 47a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acdispat.h> 48a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acinterp.h> 49a159c266SJung-uk Kim #include <contrib/dev/acpica/include/amlcode.h> 50a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acnamesp.h> 51a159c266SJung-uk Kim 52a159c266SJung-uk Kim 53a159c266SJung-uk Kim #define _COMPONENT ACPI_EXECUTER 54a159c266SJung-uk Kim ACPI_MODULE_NAME ("exoparg1") 55a159c266SJung-uk Kim 56a159c266SJung-uk Kim 57a159c266SJung-uk Kim /*! 58a159c266SJung-uk Kim * Naming convention for AML interpreter execution routines. 59a159c266SJung-uk Kim * 60a159c266SJung-uk Kim * The routines that begin execution of AML opcodes are named with a common 61a159c266SJung-uk Kim * convention based upon the number of arguments, the number of target operands, 62a159c266SJung-uk Kim * and whether or not a value is returned: 63a159c266SJung-uk Kim * 64a159c266SJung-uk Kim * AcpiExOpcode_xA_yT_zR 65a159c266SJung-uk Kim * 66a159c266SJung-uk Kim * Where: 67a159c266SJung-uk Kim * 68a159c266SJung-uk Kim * xA - ARGUMENTS: The number of arguments (input operands) that are 69a159c266SJung-uk Kim * required for this opcode type (0 through 6 args). 70a159c266SJung-uk Kim * yT - TARGETS: The number of targets (output operands) that are required 71a159c266SJung-uk Kim * for this opcode type (0, 1, or 2 targets). 72a159c266SJung-uk Kim * zR - RETURN VALUE: Indicates whether this opcode type returns a value 73a159c266SJung-uk Kim * as the function return (0 or 1). 74a159c266SJung-uk Kim * 75a159c266SJung-uk Kim * The AcpiExOpcode* functions are called via the Dispatcher component with 76a159c266SJung-uk Kim * fully resolved operands. 77a159c266SJung-uk Kim !*/ 78a159c266SJung-uk Kim 79a159c266SJung-uk Kim /******************************************************************************* 80a159c266SJung-uk Kim * 81a159c266SJung-uk Kim * FUNCTION: AcpiExOpcode_0A_0T_1R 82a159c266SJung-uk Kim * 83a159c266SJung-uk Kim * PARAMETERS: WalkState - Current state (contains AML opcode) 84a159c266SJung-uk Kim * 85a159c266SJung-uk Kim * RETURN: Status 86a159c266SJung-uk Kim * 87a159c266SJung-uk Kim * DESCRIPTION: Execute operator with no operands, one return value 88a159c266SJung-uk Kim * 89a159c266SJung-uk Kim ******************************************************************************/ 90a159c266SJung-uk Kim 91a159c266SJung-uk Kim ACPI_STATUS 92a159c266SJung-uk Kim AcpiExOpcode_0A_0T_1R ( 93a159c266SJung-uk Kim ACPI_WALK_STATE *WalkState) 94a159c266SJung-uk Kim { 95a159c266SJung-uk Kim ACPI_STATUS Status = AE_OK; 96a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *ReturnDesc = NULL; 97a159c266SJung-uk Kim 98a159c266SJung-uk Kim 99a159c266SJung-uk Kim ACPI_FUNCTION_TRACE_STR (ExOpcode_0A_0T_1R, 100a159c266SJung-uk Kim AcpiPsGetOpcodeName (WalkState->Opcode)); 101a159c266SJung-uk Kim 102a159c266SJung-uk Kim 103a159c266SJung-uk Kim /* Examine the AML opcode */ 104a159c266SJung-uk Kim 105a159c266SJung-uk Kim switch (WalkState->Opcode) 106a159c266SJung-uk Kim { 107a159c266SJung-uk Kim case AML_TIMER_OP: /* Timer () */ 108a159c266SJung-uk Kim 109a159c266SJung-uk Kim /* Create a return object of type Integer */ 110a159c266SJung-uk Kim 111a159c266SJung-uk Kim ReturnDesc = AcpiUtCreateIntegerObject (AcpiOsGetTimer ()); 112a159c266SJung-uk Kim if (!ReturnDesc) 113a159c266SJung-uk Kim { 114a159c266SJung-uk Kim Status = AE_NO_MEMORY; 115a159c266SJung-uk Kim goto Cleanup; 116a159c266SJung-uk Kim } 117a159c266SJung-uk Kim break; 118a159c266SJung-uk Kim 119a159c266SJung-uk Kim default: /* Unknown opcode */ 120a159c266SJung-uk Kim 121a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", 122a159c266SJung-uk Kim WalkState->Opcode)); 123a159c266SJung-uk Kim Status = AE_AML_BAD_OPCODE; 124a159c266SJung-uk Kim break; 125a159c266SJung-uk Kim } 126a159c266SJung-uk Kim 127a159c266SJung-uk Kim Cleanup: 128a159c266SJung-uk Kim 129a159c266SJung-uk Kim /* Delete return object on error */ 130a159c266SJung-uk Kim 131a159c266SJung-uk Kim if ((ACPI_FAILURE (Status)) || WalkState->ResultObj) 132a159c266SJung-uk Kim { 133a159c266SJung-uk Kim AcpiUtRemoveReference (ReturnDesc); 134a159c266SJung-uk Kim WalkState->ResultObj = NULL; 135a159c266SJung-uk Kim } 136a159c266SJung-uk Kim else 137a159c266SJung-uk Kim { 138a159c266SJung-uk Kim /* Save the return value */ 139a159c266SJung-uk Kim 140a159c266SJung-uk Kim WalkState->ResultObj = ReturnDesc; 141a159c266SJung-uk Kim } 142a159c266SJung-uk Kim 143a159c266SJung-uk Kim return_ACPI_STATUS (Status); 144a159c266SJung-uk Kim } 145a159c266SJung-uk Kim 146a159c266SJung-uk Kim 147a159c266SJung-uk Kim /******************************************************************************* 148a159c266SJung-uk Kim * 149a159c266SJung-uk Kim * FUNCTION: AcpiExOpcode_1A_0T_0R 150a159c266SJung-uk Kim * 151a159c266SJung-uk Kim * PARAMETERS: WalkState - Current state (contains AML opcode) 152a159c266SJung-uk Kim * 153a159c266SJung-uk Kim * RETURN: Status 154a159c266SJung-uk Kim * 155a159c266SJung-uk Kim * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on 156a159c266SJung-uk Kim * object stack 157a159c266SJung-uk Kim * 158a159c266SJung-uk Kim ******************************************************************************/ 159a159c266SJung-uk Kim 160a159c266SJung-uk Kim ACPI_STATUS 161a159c266SJung-uk Kim AcpiExOpcode_1A_0T_0R ( 162a159c266SJung-uk Kim ACPI_WALK_STATE *WalkState) 163a159c266SJung-uk Kim { 164a159c266SJung-uk Kim ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 165a159c266SJung-uk Kim ACPI_STATUS Status = AE_OK; 166a159c266SJung-uk Kim 167a159c266SJung-uk Kim 168a159c266SJung-uk Kim ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_0T_0R, 169a159c266SJung-uk Kim AcpiPsGetOpcodeName (WalkState->Opcode)); 170a159c266SJung-uk Kim 171a159c266SJung-uk Kim 172a159c266SJung-uk Kim /* Examine the AML opcode */ 173a159c266SJung-uk Kim 174a159c266SJung-uk Kim switch (WalkState->Opcode) 175a159c266SJung-uk Kim { 176a159c266SJung-uk Kim case AML_RELEASE_OP: /* Release (MutexObject) */ 177a159c266SJung-uk Kim 178a159c266SJung-uk Kim Status = AcpiExReleaseMutex (Operand[0], WalkState); 179a159c266SJung-uk Kim break; 180a159c266SJung-uk Kim 181a159c266SJung-uk Kim case AML_RESET_OP: /* Reset (EventObject) */ 182a159c266SJung-uk Kim 183a159c266SJung-uk Kim Status = AcpiExSystemResetEvent (Operand[0]); 184a159c266SJung-uk Kim break; 185a159c266SJung-uk Kim 186a159c266SJung-uk Kim case AML_SIGNAL_OP: /* Signal (EventObject) */ 187a159c266SJung-uk Kim 188a159c266SJung-uk Kim Status = AcpiExSystemSignalEvent (Operand[0]); 189a159c266SJung-uk Kim break; 190a159c266SJung-uk Kim 191a159c266SJung-uk Kim case AML_SLEEP_OP: /* Sleep (MsecTime) */ 192a159c266SJung-uk Kim 193a159c266SJung-uk Kim Status = AcpiExSystemDoSleep (Operand[0]->Integer.Value); 194a159c266SJung-uk Kim break; 195a159c266SJung-uk Kim 196a159c266SJung-uk Kim case AML_STALL_OP: /* Stall (UsecTime) */ 197a159c266SJung-uk Kim 198a159c266SJung-uk Kim Status = AcpiExSystemDoStall ((UINT32) Operand[0]->Integer.Value); 199a159c266SJung-uk Kim break; 200a159c266SJung-uk Kim 201a159c266SJung-uk Kim case AML_UNLOAD_OP: /* Unload (Handle) */ 202a159c266SJung-uk Kim 203a159c266SJung-uk Kim Status = AcpiExUnloadTable (Operand[0]); 204a159c266SJung-uk Kim break; 205a159c266SJung-uk Kim 206a159c266SJung-uk Kim default: /* Unknown opcode */ 207a159c266SJung-uk Kim 208a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", 209a159c266SJung-uk Kim WalkState->Opcode)); 210a159c266SJung-uk Kim Status = AE_AML_BAD_OPCODE; 211a159c266SJung-uk Kim break; 212a159c266SJung-uk Kim } 213a159c266SJung-uk Kim 214a159c266SJung-uk Kim return_ACPI_STATUS (Status); 215a159c266SJung-uk Kim } 216a159c266SJung-uk Kim 217a159c266SJung-uk Kim 218a159c266SJung-uk Kim /******************************************************************************* 219a159c266SJung-uk Kim * 220a159c266SJung-uk Kim * FUNCTION: AcpiExOpcode_1A_1T_0R 221a159c266SJung-uk Kim * 222a159c266SJung-uk Kim * PARAMETERS: WalkState - Current state (contains AML opcode) 223a159c266SJung-uk Kim * 224a159c266SJung-uk Kim * RETURN: Status 225a159c266SJung-uk Kim * 226a159c266SJung-uk Kim * DESCRIPTION: Execute opcode with one argument, one target, and no 227a159c266SJung-uk Kim * return value. 228a159c266SJung-uk Kim * 229a159c266SJung-uk Kim ******************************************************************************/ 230a159c266SJung-uk Kim 231a159c266SJung-uk Kim ACPI_STATUS 232a159c266SJung-uk Kim AcpiExOpcode_1A_1T_0R ( 233a159c266SJung-uk Kim ACPI_WALK_STATE *WalkState) 234a159c266SJung-uk Kim { 235a159c266SJung-uk Kim ACPI_STATUS Status = AE_OK; 236a159c266SJung-uk Kim ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 237a159c266SJung-uk Kim 238a159c266SJung-uk Kim 239a159c266SJung-uk Kim ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_1T_0R, 240a159c266SJung-uk Kim AcpiPsGetOpcodeName (WalkState->Opcode)); 241a159c266SJung-uk Kim 242a159c266SJung-uk Kim 243a159c266SJung-uk Kim /* Examine the AML opcode */ 244a159c266SJung-uk Kim 245a159c266SJung-uk Kim switch (WalkState->Opcode) 246a159c266SJung-uk Kim { 247a159c266SJung-uk Kim case AML_LOAD_OP: 248a159c266SJung-uk Kim 249a159c266SJung-uk Kim Status = AcpiExLoadOp (Operand[0], Operand[1], WalkState); 250a159c266SJung-uk Kim break; 251a159c266SJung-uk Kim 252a159c266SJung-uk Kim default: /* Unknown opcode */ 253a159c266SJung-uk Kim 254a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", 255a159c266SJung-uk Kim WalkState->Opcode)); 256a159c266SJung-uk Kim Status = AE_AML_BAD_OPCODE; 257a159c266SJung-uk Kim goto Cleanup; 258a159c266SJung-uk Kim } 259a159c266SJung-uk Kim 260a159c266SJung-uk Kim 261a159c266SJung-uk Kim Cleanup: 262a159c266SJung-uk Kim 263a159c266SJung-uk Kim return_ACPI_STATUS (Status); 264a159c266SJung-uk Kim } 265a159c266SJung-uk Kim 266a159c266SJung-uk Kim 267a159c266SJung-uk Kim /******************************************************************************* 268a159c266SJung-uk Kim * 269a159c266SJung-uk Kim * FUNCTION: AcpiExOpcode_1A_1T_1R 270a159c266SJung-uk Kim * 271a159c266SJung-uk Kim * PARAMETERS: WalkState - Current state (contains AML opcode) 272a159c266SJung-uk Kim * 273a159c266SJung-uk Kim * RETURN: Status 274a159c266SJung-uk Kim * 275a159c266SJung-uk Kim * DESCRIPTION: Execute opcode with one argument, one target, and a 276a159c266SJung-uk Kim * return value. 277a159c266SJung-uk Kim * 278a159c266SJung-uk Kim ******************************************************************************/ 279a159c266SJung-uk Kim 280a159c266SJung-uk Kim ACPI_STATUS 281a159c266SJung-uk Kim AcpiExOpcode_1A_1T_1R ( 282a159c266SJung-uk Kim ACPI_WALK_STATE *WalkState) 283a159c266SJung-uk Kim { 284a159c266SJung-uk Kim ACPI_STATUS Status = AE_OK; 285a159c266SJung-uk Kim ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 286a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *ReturnDesc = NULL; 287a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *ReturnDesc2 = NULL; 288a159c266SJung-uk Kim UINT32 Temp32; 289a159c266SJung-uk Kim UINT32 i; 290a159c266SJung-uk Kim UINT64 PowerOfTen; 291a159c266SJung-uk Kim UINT64 Digit; 292a159c266SJung-uk Kim 293a159c266SJung-uk Kim 294a159c266SJung-uk Kim ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_1T_1R, 295a159c266SJung-uk Kim AcpiPsGetOpcodeName (WalkState->Opcode)); 296a159c266SJung-uk Kim 297a159c266SJung-uk Kim 298a159c266SJung-uk Kim /* Examine the AML opcode */ 299a159c266SJung-uk Kim 300a159c266SJung-uk Kim switch (WalkState->Opcode) 301a159c266SJung-uk Kim { 302a159c266SJung-uk Kim case AML_BIT_NOT_OP: 303a159c266SJung-uk Kim case AML_FIND_SET_LEFT_BIT_OP: 304a159c266SJung-uk Kim case AML_FIND_SET_RIGHT_BIT_OP: 305a159c266SJung-uk Kim case AML_FROM_BCD_OP: 306a159c266SJung-uk Kim case AML_TO_BCD_OP: 307a159c266SJung-uk Kim case AML_COND_REF_OF_OP: 308a159c266SJung-uk Kim 309a159c266SJung-uk Kim /* Create a return object of type Integer for these opcodes */ 310a159c266SJung-uk Kim 311a159c266SJung-uk Kim ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 312a159c266SJung-uk Kim if (!ReturnDesc) 313a159c266SJung-uk Kim { 314a159c266SJung-uk Kim Status = AE_NO_MEMORY; 315a159c266SJung-uk Kim goto Cleanup; 316a159c266SJung-uk Kim } 317a159c266SJung-uk Kim 318a159c266SJung-uk Kim switch (WalkState->Opcode) 319a159c266SJung-uk Kim { 320a159c266SJung-uk Kim case AML_BIT_NOT_OP: /* Not (Operand, Result) */ 321a159c266SJung-uk Kim 322a159c266SJung-uk Kim ReturnDesc->Integer.Value = ~Operand[0]->Integer.Value; 323a159c266SJung-uk Kim break; 324a159c266SJung-uk Kim 325a159c266SJung-uk Kim case AML_FIND_SET_LEFT_BIT_OP: /* FindSetLeftBit (Operand, Result) */ 326a159c266SJung-uk Kim 327a159c266SJung-uk Kim ReturnDesc->Integer.Value = Operand[0]->Integer.Value; 328a159c266SJung-uk Kim 329a159c266SJung-uk Kim /* 330a159c266SJung-uk Kim * Acpi specification describes Integer type as a little 331a159c266SJung-uk Kim * endian unsigned value, so this boundary condition is valid. 332a159c266SJung-uk Kim */ 333a159c266SJung-uk Kim for (Temp32 = 0; ReturnDesc->Integer.Value && 334a159c266SJung-uk Kim Temp32 < ACPI_INTEGER_BIT_SIZE; ++Temp32) 335a159c266SJung-uk Kim { 336a159c266SJung-uk Kim ReturnDesc->Integer.Value >>= 1; 337a159c266SJung-uk Kim } 338a159c266SJung-uk Kim 339a159c266SJung-uk Kim ReturnDesc->Integer.Value = Temp32; 340a159c266SJung-uk Kim break; 341a159c266SJung-uk Kim 342a159c266SJung-uk Kim case AML_FIND_SET_RIGHT_BIT_OP: /* FindSetRightBit (Operand, Result) */ 343a159c266SJung-uk Kim 344a159c266SJung-uk Kim ReturnDesc->Integer.Value = Operand[0]->Integer.Value; 345a159c266SJung-uk Kim 346a159c266SJung-uk Kim /* 347a159c266SJung-uk Kim * The Acpi specification describes Integer type as a little 348a159c266SJung-uk Kim * endian unsigned value, so this boundary condition is valid. 349a159c266SJung-uk Kim */ 350a159c266SJung-uk Kim for (Temp32 = 0; ReturnDesc->Integer.Value && 351a159c266SJung-uk Kim Temp32 < ACPI_INTEGER_BIT_SIZE; ++Temp32) 352a159c266SJung-uk Kim { 353a159c266SJung-uk Kim ReturnDesc->Integer.Value <<= 1; 354a159c266SJung-uk Kim } 355a159c266SJung-uk Kim 356a159c266SJung-uk Kim /* Since the bit position is one-based, subtract from 33 (65) */ 357a159c266SJung-uk Kim 358a159c266SJung-uk Kim ReturnDesc->Integer.Value = 359a159c266SJung-uk Kim Temp32 == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - Temp32; 360a159c266SJung-uk Kim break; 361a159c266SJung-uk Kim 362a159c266SJung-uk Kim case AML_FROM_BCD_OP: /* FromBcd (BCDValue, Result) */ 363a159c266SJung-uk Kim /* 364a159c266SJung-uk Kim * The 64-bit ACPI integer can hold 16 4-bit BCD characters 365a159c266SJung-uk Kim * (if table is 32-bit, integer can hold 8 BCD characters) 366a159c266SJung-uk Kim * Convert each 4-bit BCD value 367a159c266SJung-uk Kim */ 368a159c266SJung-uk Kim PowerOfTen = 1; 369a159c266SJung-uk Kim ReturnDesc->Integer.Value = 0; 370a159c266SJung-uk Kim Digit = Operand[0]->Integer.Value; 371a159c266SJung-uk Kim 372a159c266SJung-uk Kim /* Convert each BCD digit (each is one nybble wide) */ 373a159c266SJung-uk Kim 374a159c266SJung-uk Kim for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++) 375a159c266SJung-uk Kim { 376a159c266SJung-uk Kim /* Get the least significant 4-bit BCD digit */ 377a159c266SJung-uk Kim 378a159c266SJung-uk Kim Temp32 = ((UINT32) Digit) & 0xF; 379a159c266SJung-uk Kim 380a159c266SJung-uk Kim /* Check the range of the digit */ 381a159c266SJung-uk Kim 382a159c266SJung-uk Kim if (Temp32 > 9) 383a159c266SJung-uk Kim { 384a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, 385a159c266SJung-uk Kim "BCD digit too large (not decimal): 0x%X", 386a159c266SJung-uk Kim Temp32)); 387a159c266SJung-uk Kim 388a159c266SJung-uk Kim Status = AE_AML_NUMERIC_OVERFLOW; 389a159c266SJung-uk Kim goto Cleanup; 390a159c266SJung-uk Kim } 391a159c266SJung-uk Kim 392a159c266SJung-uk Kim /* Sum the digit into the result with the current power of 10 */ 393a159c266SJung-uk Kim 394a159c266SJung-uk Kim ReturnDesc->Integer.Value += 395a159c266SJung-uk Kim (((UINT64) Temp32) * PowerOfTen); 396a159c266SJung-uk Kim 397a159c266SJung-uk Kim /* Shift to next BCD digit */ 398a159c266SJung-uk Kim 399a159c266SJung-uk Kim Digit >>= 4; 400a159c266SJung-uk Kim 401a159c266SJung-uk Kim /* Next power of 10 */ 402a159c266SJung-uk Kim 403a159c266SJung-uk Kim PowerOfTen *= 10; 404a159c266SJung-uk Kim } 405a159c266SJung-uk Kim break; 406a159c266SJung-uk Kim 407a159c266SJung-uk Kim case AML_TO_BCD_OP: /* ToBcd (Operand, Result) */ 408a159c266SJung-uk Kim 409a159c266SJung-uk Kim ReturnDesc->Integer.Value = 0; 410a159c266SJung-uk Kim Digit = Operand[0]->Integer.Value; 411a159c266SJung-uk Kim 412a159c266SJung-uk Kim /* Each BCD digit is one nybble wide */ 413a159c266SJung-uk Kim 414a159c266SJung-uk Kim for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++) 415a159c266SJung-uk Kim { 416a159c266SJung-uk Kim (void) AcpiUtShortDivide (Digit, 10, &Digit, &Temp32); 417a159c266SJung-uk Kim 418a159c266SJung-uk Kim /* 419a159c266SJung-uk Kim * Insert the BCD digit that resides in the 420a159c266SJung-uk Kim * remainder from above 421a159c266SJung-uk Kim */ 422a159c266SJung-uk Kim ReturnDesc->Integer.Value |= 423a159c266SJung-uk Kim (((UINT64) Temp32) << ACPI_MUL_4 (i)); 424a159c266SJung-uk Kim } 425a159c266SJung-uk Kim 426a159c266SJung-uk Kim /* Overflow if there is any data left in Digit */ 427a159c266SJung-uk Kim 428a159c266SJung-uk Kim if (Digit > 0) 429a159c266SJung-uk Kim { 430a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, 431a159c266SJung-uk Kim "Integer too large to convert to BCD: 0x%8.8X%8.8X", 432a159c266SJung-uk Kim ACPI_FORMAT_UINT64 (Operand[0]->Integer.Value))); 433a159c266SJung-uk Kim Status = AE_AML_NUMERIC_OVERFLOW; 434a159c266SJung-uk Kim goto Cleanup; 435a159c266SJung-uk Kim } 436a159c266SJung-uk Kim break; 437a159c266SJung-uk Kim 438a159c266SJung-uk Kim case AML_COND_REF_OF_OP: /* CondRefOf (SourceObject, Result) */ 439a159c266SJung-uk Kim /* 440a159c266SJung-uk Kim * This op is a little strange because the internal return value is 441a159c266SJung-uk Kim * different than the return value stored in the result descriptor 442a159c266SJung-uk Kim * (There are really two return values) 443a159c266SJung-uk Kim */ 444a159c266SJung-uk Kim if ((ACPI_NAMESPACE_NODE *) Operand[0] == AcpiGbl_RootNode) 445a159c266SJung-uk Kim { 446a159c266SJung-uk Kim /* 447a159c266SJung-uk Kim * This means that the object does not exist in the namespace, 448a159c266SJung-uk Kim * return FALSE 449a159c266SJung-uk Kim */ 450a159c266SJung-uk Kim ReturnDesc->Integer.Value = 0; 451a159c266SJung-uk Kim goto Cleanup; 452a159c266SJung-uk Kim } 453a159c266SJung-uk Kim 454a159c266SJung-uk Kim /* Get the object reference, store it, and remove our reference */ 455a159c266SJung-uk Kim 456a159c266SJung-uk Kim Status = AcpiExGetObjectReference (Operand[0], 457a159c266SJung-uk Kim &ReturnDesc2, WalkState); 458a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 459a159c266SJung-uk Kim { 460a159c266SJung-uk Kim goto Cleanup; 461a159c266SJung-uk Kim } 462a159c266SJung-uk Kim 463a159c266SJung-uk Kim Status = AcpiExStore (ReturnDesc2, Operand[1], WalkState); 464a159c266SJung-uk Kim AcpiUtRemoveReference (ReturnDesc2); 465a159c266SJung-uk Kim 466a159c266SJung-uk Kim /* The object exists in the namespace, return TRUE */ 467a159c266SJung-uk Kim 468a159c266SJung-uk Kim ReturnDesc->Integer.Value = ACPI_UINT64_MAX; 469a159c266SJung-uk Kim goto Cleanup; 470a159c266SJung-uk Kim 471a159c266SJung-uk Kim 472a159c266SJung-uk Kim default: 473a9d8d09cSJung-uk Kim 474a159c266SJung-uk Kim /* No other opcodes get here */ 475a9d8d09cSJung-uk Kim 476a159c266SJung-uk Kim break; 477a159c266SJung-uk Kim } 478a159c266SJung-uk Kim break; 479a159c266SJung-uk Kim 480a159c266SJung-uk Kim case AML_STORE_OP: /* Store (Source, Target) */ 481a159c266SJung-uk Kim /* 482a159c266SJung-uk Kim * A store operand is typically a number, string, buffer or lvalue 483a159c266SJung-uk Kim * Be careful about deleting the source object, 484a159c266SJung-uk Kim * since the object itself may have been stored. 485a159c266SJung-uk Kim */ 486a159c266SJung-uk Kim Status = AcpiExStore (Operand[0], Operand[1], WalkState); 487a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 488a159c266SJung-uk Kim { 489a159c266SJung-uk Kim return_ACPI_STATUS (Status); 490a159c266SJung-uk Kim } 491a159c266SJung-uk Kim 492a159c266SJung-uk Kim /* It is possible that the Store already produced a return object */ 493a159c266SJung-uk Kim 494a159c266SJung-uk Kim if (!WalkState->ResultObj) 495a159c266SJung-uk Kim { 496a159c266SJung-uk Kim /* 497a159c266SJung-uk Kim * Normally, we would remove a reference on the Operand[0] 498a159c266SJung-uk Kim * parameter; But since it is being used as the internal return 499a159c266SJung-uk Kim * object (meaning we would normally increment it), the two 500a159c266SJung-uk Kim * cancel out, and we simply don't do anything. 501a159c266SJung-uk Kim */ 502a159c266SJung-uk Kim WalkState->ResultObj = Operand[0]; 503a159c266SJung-uk Kim WalkState->Operands[0] = NULL; /* Prevent deletion */ 504a159c266SJung-uk Kim } 505a159c266SJung-uk Kim return_ACPI_STATUS (Status); 506a159c266SJung-uk Kim 507a159c266SJung-uk Kim /* 508a159c266SJung-uk Kim * ACPI 2.0 Opcodes 509a159c266SJung-uk Kim */ 510a159c266SJung-uk Kim case AML_COPY_OP: /* Copy (Source, Target) */ 511a159c266SJung-uk Kim 512f8146b88SJung-uk Kim Status = AcpiUtCopyIobjectToIobject ( 513f8146b88SJung-uk Kim Operand[0], &ReturnDesc, WalkState); 514a159c266SJung-uk Kim break; 515a159c266SJung-uk Kim 516a159c266SJung-uk Kim case AML_TO_DECSTRING_OP: /* ToDecimalString (Data, Result) */ 517a159c266SJung-uk Kim 518f8146b88SJung-uk Kim Status = AcpiExConvertToString ( 519f8146b88SJung-uk Kim Operand[0], &ReturnDesc, ACPI_EXPLICIT_CONVERT_DECIMAL); 520a159c266SJung-uk Kim if (ReturnDesc == Operand[0]) 521a159c266SJung-uk Kim { 522a159c266SJung-uk Kim /* No conversion performed, add ref to handle return value */ 523f8146b88SJung-uk Kim 524a159c266SJung-uk Kim AcpiUtAddReference (ReturnDesc); 525a159c266SJung-uk Kim } 526a159c266SJung-uk Kim break; 527a159c266SJung-uk Kim 528a159c266SJung-uk Kim case AML_TO_HEXSTRING_OP: /* ToHexString (Data, Result) */ 529a159c266SJung-uk Kim 530f8146b88SJung-uk Kim Status = AcpiExConvertToString ( 531f8146b88SJung-uk Kim Operand[0], &ReturnDesc, ACPI_EXPLICIT_CONVERT_HEX); 532a159c266SJung-uk Kim if (ReturnDesc == Operand[0]) 533a159c266SJung-uk Kim { 534a159c266SJung-uk Kim /* No conversion performed, add ref to handle return value */ 535f8146b88SJung-uk Kim 536a159c266SJung-uk Kim AcpiUtAddReference (ReturnDesc); 537a159c266SJung-uk Kim } 538a159c266SJung-uk Kim break; 539a159c266SJung-uk Kim 540a159c266SJung-uk Kim case AML_TO_BUFFER_OP: /* ToBuffer (Data, Result) */ 541a159c266SJung-uk Kim 542a159c266SJung-uk Kim Status = AcpiExConvertToBuffer (Operand[0], &ReturnDesc); 543a159c266SJung-uk Kim if (ReturnDesc == Operand[0]) 544a159c266SJung-uk Kim { 545a159c266SJung-uk Kim /* No conversion performed, add ref to handle return value */ 546f8146b88SJung-uk Kim 547a159c266SJung-uk Kim AcpiUtAddReference (ReturnDesc); 548a159c266SJung-uk Kim } 549a159c266SJung-uk Kim break; 550a159c266SJung-uk Kim 551a159c266SJung-uk Kim case AML_TO_INTEGER_OP: /* ToInteger (Data, Result) */ 552a159c266SJung-uk Kim 553f8146b88SJung-uk Kim Status = AcpiExConvertToInteger ( 554f8146b88SJung-uk Kim Operand[0], &ReturnDesc, ACPI_ANY_BASE); 555a159c266SJung-uk Kim if (ReturnDesc == Operand[0]) 556a159c266SJung-uk Kim { 557a159c266SJung-uk Kim /* No conversion performed, add ref to handle return value */ 558f8146b88SJung-uk Kim 559a159c266SJung-uk Kim AcpiUtAddReference (ReturnDesc); 560a159c266SJung-uk Kim } 561a159c266SJung-uk Kim break; 562a159c266SJung-uk Kim 563a159c266SJung-uk Kim case AML_SHIFT_LEFT_BIT_OP: /* ShiftLeftBit (Source, BitNum) */ 564a159c266SJung-uk Kim case AML_SHIFT_RIGHT_BIT_OP: /* ShiftRightBit (Source, BitNum) */ 565a159c266SJung-uk Kim 566a159c266SJung-uk Kim /* These are two obsolete opcodes */ 567a159c266SJung-uk Kim 568a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, 569a159c266SJung-uk Kim "%s is obsolete and not implemented", 570a159c266SJung-uk Kim AcpiPsGetOpcodeName (WalkState->Opcode))); 571a159c266SJung-uk Kim Status = AE_SUPPORT; 572a159c266SJung-uk Kim goto Cleanup; 573a159c266SJung-uk Kim 574a159c266SJung-uk Kim default: /* Unknown opcode */ 575a159c266SJung-uk Kim 576a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", 577a159c266SJung-uk Kim WalkState->Opcode)); 578a159c266SJung-uk Kim Status = AE_AML_BAD_OPCODE; 579a159c266SJung-uk Kim goto Cleanup; 580a159c266SJung-uk Kim } 581a159c266SJung-uk Kim 582a159c266SJung-uk Kim if (ACPI_SUCCESS (Status)) 583a159c266SJung-uk Kim { 584a159c266SJung-uk Kim /* Store the return value computed above into the target object */ 585a159c266SJung-uk Kim 586a159c266SJung-uk Kim Status = AcpiExStore (ReturnDesc, Operand[1], WalkState); 587a159c266SJung-uk Kim } 588a159c266SJung-uk Kim 589a159c266SJung-uk Kim 590a159c266SJung-uk Kim Cleanup: 591a159c266SJung-uk Kim 592a159c266SJung-uk Kim /* Delete return object on error */ 593a159c266SJung-uk Kim 594a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 595a159c266SJung-uk Kim { 596a159c266SJung-uk Kim AcpiUtRemoveReference (ReturnDesc); 597a159c266SJung-uk Kim } 598a159c266SJung-uk Kim 599a159c266SJung-uk Kim /* Save return object on success */ 600a159c266SJung-uk Kim 601a159c266SJung-uk Kim else if (!WalkState->ResultObj) 602a159c266SJung-uk Kim { 603a159c266SJung-uk Kim WalkState->ResultObj = ReturnDesc; 604a159c266SJung-uk Kim } 605a159c266SJung-uk Kim 606a159c266SJung-uk Kim return_ACPI_STATUS (Status); 607a159c266SJung-uk Kim } 608a159c266SJung-uk Kim 609a159c266SJung-uk Kim 610a159c266SJung-uk Kim /******************************************************************************* 611a159c266SJung-uk Kim * 612a159c266SJung-uk Kim * FUNCTION: AcpiExOpcode_1A_0T_1R 613a159c266SJung-uk Kim * 614a159c266SJung-uk Kim * PARAMETERS: WalkState - Current state (contains AML opcode) 615a159c266SJung-uk Kim * 616a159c266SJung-uk Kim * RETURN: Status 617a159c266SJung-uk Kim * 618a159c266SJung-uk Kim * DESCRIPTION: Execute opcode with one argument, no target, and a return value 619a159c266SJung-uk Kim * 620a159c266SJung-uk Kim ******************************************************************************/ 621a159c266SJung-uk Kim 622a159c266SJung-uk Kim ACPI_STATUS 623a159c266SJung-uk Kim AcpiExOpcode_1A_0T_1R ( 624a159c266SJung-uk Kim ACPI_WALK_STATE *WalkState) 625a159c266SJung-uk Kim { 626a159c266SJung-uk Kim ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 627a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *TempDesc; 628a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *ReturnDesc = NULL; 629a159c266SJung-uk Kim ACPI_STATUS Status = AE_OK; 630a159c266SJung-uk Kim UINT32 Type; 631a159c266SJung-uk Kim UINT64 Value; 632a159c266SJung-uk Kim 633a159c266SJung-uk Kim 634a159c266SJung-uk Kim ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_0T_1R, 635a159c266SJung-uk Kim AcpiPsGetOpcodeName (WalkState->Opcode)); 636a159c266SJung-uk Kim 637a159c266SJung-uk Kim 638a159c266SJung-uk Kim /* Examine the AML opcode */ 639a159c266SJung-uk Kim 640a159c266SJung-uk Kim switch (WalkState->Opcode) 641a159c266SJung-uk Kim { 642a159c266SJung-uk Kim case AML_LNOT_OP: /* LNot (Operand) */ 643a159c266SJung-uk Kim 644a159c266SJung-uk Kim ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) 0); 645a159c266SJung-uk Kim if (!ReturnDesc) 646a159c266SJung-uk Kim { 647a159c266SJung-uk Kim Status = AE_NO_MEMORY; 648a159c266SJung-uk Kim goto Cleanup; 649a159c266SJung-uk Kim } 650a159c266SJung-uk Kim 651a159c266SJung-uk Kim /* 652a159c266SJung-uk Kim * Set result to ONES (TRUE) if Value == 0. Note: 653a159c266SJung-uk Kim * ReturnDesc->Integer.Value is initially == 0 (FALSE) from above. 654a159c266SJung-uk Kim */ 655a159c266SJung-uk Kim if (!Operand[0]->Integer.Value) 656a159c266SJung-uk Kim { 657a159c266SJung-uk Kim ReturnDesc->Integer.Value = ACPI_UINT64_MAX; 658a159c266SJung-uk Kim } 659a159c266SJung-uk Kim break; 660a159c266SJung-uk Kim 661a159c266SJung-uk Kim case AML_DECREMENT_OP: /* Decrement (Operand) */ 662a159c266SJung-uk Kim case AML_INCREMENT_OP: /* Increment (Operand) */ 663a159c266SJung-uk Kim /* 664a159c266SJung-uk Kim * Create a new integer. Can't just get the base integer and 665a159c266SJung-uk Kim * increment it because it may be an Arg or Field. 666a159c266SJung-uk Kim */ 667a159c266SJung-uk Kim ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 668a159c266SJung-uk Kim if (!ReturnDesc) 669a159c266SJung-uk Kim { 670a159c266SJung-uk Kim Status = AE_NO_MEMORY; 671a159c266SJung-uk Kim goto Cleanup; 672a159c266SJung-uk Kim } 673a159c266SJung-uk Kim 674a159c266SJung-uk Kim /* 675a159c266SJung-uk Kim * Since we are expecting a Reference operand, it can be either a 676a159c266SJung-uk Kim * NS Node or an internal object. 677a159c266SJung-uk Kim */ 678a159c266SJung-uk Kim TempDesc = Operand[0]; 679a159c266SJung-uk Kim if (ACPI_GET_DESCRIPTOR_TYPE (TempDesc) == ACPI_DESC_TYPE_OPERAND) 680a159c266SJung-uk Kim { 681a159c266SJung-uk Kim /* Internal reference object - prevent deletion */ 682a159c266SJung-uk Kim 683a159c266SJung-uk Kim AcpiUtAddReference (TempDesc); 684a159c266SJung-uk Kim } 685a159c266SJung-uk Kim 686a159c266SJung-uk Kim /* 687a159c266SJung-uk Kim * Convert the Reference operand to an Integer (This removes a 688a159c266SJung-uk Kim * reference on the Operand[0] object) 689a159c266SJung-uk Kim * 690a159c266SJung-uk Kim * NOTE: We use LNOT_OP here in order to force resolution of the 691a159c266SJung-uk Kim * reference operand to an actual integer. 692a159c266SJung-uk Kim */ 693a159c266SJung-uk Kim Status = AcpiExResolveOperands (AML_LNOT_OP, &TempDesc, WalkState); 694a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 695a159c266SJung-uk Kim { 696a159c266SJung-uk Kim ACPI_EXCEPTION ((AE_INFO, Status, 697a159c266SJung-uk Kim "While resolving operands for [%s]", 698a159c266SJung-uk Kim AcpiPsGetOpcodeName (WalkState->Opcode))); 699a159c266SJung-uk Kim 700a159c266SJung-uk Kim goto Cleanup; 701a159c266SJung-uk Kim } 702a159c266SJung-uk Kim 703a159c266SJung-uk Kim /* 704a159c266SJung-uk Kim * TempDesc is now guaranteed to be an Integer object -- 705a159c266SJung-uk Kim * Perform the actual increment or decrement 706a159c266SJung-uk Kim */ 707a159c266SJung-uk Kim if (WalkState->Opcode == AML_INCREMENT_OP) 708a159c266SJung-uk Kim { 709a159c266SJung-uk Kim ReturnDesc->Integer.Value = TempDesc->Integer.Value + 1; 710a159c266SJung-uk Kim } 711a159c266SJung-uk Kim else 712a159c266SJung-uk Kim { 713a159c266SJung-uk Kim ReturnDesc->Integer.Value = TempDesc->Integer.Value - 1; 714a159c266SJung-uk Kim } 715a159c266SJung-uk Kim 716a159c266SJung-uk Kim /* Finished with this Integer object */ 717a159c266SJung-uk Kim 718a159c266SJung-uk Kim AcpiUtRemoveReference (TempDesc); 719a159c266SJung-uk Kim 720a159c266SJung-uk Kim /* 721a159c266SJung-uk Kim * Store the result back (indirectly) through the original 722a159c266SJung-uk Kim * Reference object 723a159c266SJung-uk Kim */ 724a159c266SJung-uk Kim Status = AcpiExStore (ReturnDesc, Operand[0], WalkState); 725a159c266SJung-uk Kim break; 726a159c266SJung-uk Kim 727f8146b88SJung-uk Kim case AML_OBJECT_TYPE_OP: /* ObjectType (SourceObject) */ 728a159c266SJung-uk Kim /* 729a159c266SJung-uk Kim * Note: The operand is not resolved at this point because we want to 730a159c266SJung-uk Kim * get the associated object, not its value. For example, we don't 731a159c266SJung-uk Kim * want to resolve a FieldUnit to its value, we want the actual 732a159c266SJung-uk Kim * FieldUnit object. 733a159c266SJung-uk Kim */ 734a159c266SJung-uk Kim 735a159c266SJung-uk Kim /* Get the type of the base object */ 736a159c266SJung-uk Kim 737a159c266SJung-uk Kim Status = AcpiExResolveMultiple (WalkState, Operand[0], &Type, NULL); 738a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 739a159c266SJung-uk Kim { 740a159c266SJung-uk Kim goto Cleanup; 741a159c266SJung-uk Kim } 742a159c266SJung-uk Kim 743a159c266SJung-uk Kim /* Allocate a descriptor to hold the type. */ 744a159c266SJung-uk Kim 745a159c266SJung-uk Kim ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) Type); 746a159c266SJung-uk Kim if (!ReturnDesc) 747a159c266SJung-uk Kim { 748a159c266SJung-uk Kim Status = AE_NO_MEMORY; 749a159c266SJung-uk Kim goto Cleanup; 750a159c266SJung-uk Kim } 751a159c266SJung-uk Kim break; 752a159c266SJung-uk Kim 753a159c266SJung-uk Kim case AML_SIZE_OF_OP: /* SizeOf (SourceObject) */ 754a159c266SJung-uk Kim /* 755a159c266SJung-uk Kim * Note: The operand is not resolved at this point because we want to 756a159c266SJung-uk Kim * get the associated object, not its value. 757a159c266SJung-uk Kim */ 758a159c266SJung-uk Kim 759a159c266SJung-uk Kim /* Get the base object */ 760a159c266SJung-uk Kim 761f8146b88SJung-uk Kim Status = AcpiExResolveMultiple ( 762f8146b88SJung-uk Kim WalkState, Operand[0], &Type, &TempDesc); 763a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 764a159c266SJung-uk Kim { 765a159c266SJung-uk Kim goto Cleanup; 766a159c266SJung-uk Kim } 767a159c266SJung-uk Kim 768a159c266SJung-uk Kim /* 769a159c266SJung-uk Kim * The type of the base object must be integer, buffer, string, or 770a159c266SJung-uk Kim * package. All others are not supported. 771a159c266SJung-uk Kim * 772a159c266SJung-uk Kim * NOTE: Integer is not specifically supported by the ACPI spec, 773a159c266SJung-uk Kim * but is supported implicitly via implicit operand conversion. 774a159c266SJung-uk Kim * rather than bother with conversion, we just use the byte width 775a159c266SJung-uk Kim * global (4 or 8 bytes). 776a159c266SJung-uk Kim */ 777a159c266SJung-uk Kim switch (Type) 778a159c266SJung-uk Kim { 779a159c266SJung-uk Kim case ACPI_TYPE_INTEGER: 780a9d8d09cSJung-uk Kim 781a159c266SJung-uk Kim Value = AcpiGbl_IntegerByteWidth; 782a159c266SJung-uk Kim break; 783a159c266SJung-uk Kim 784a159c266SJung-uk Kim case ACPI_TYPE_STRING: 785a9d8d09cSJung-uk Kim 786a159c266SJung-uk Kim Value = TempDesc->String.Length; 787a159c266SJung-uk Kim break; 788a159c266SJung-uk Kim 789a159c266SJung-uk Kim case ACPI_TYPE_BUFFER: 790a159c266SJung-uk Kim 791a159c266SJung-uk Kim /* Buffer arguments may not be evaluated at this point */ 792a159c266SJung-uk Kim 793a159c266SJung-uk Kim Status = AcpiDsGetBufferArguments (TempDesc); 794a159c266SJung-uk Kim Value = TempDesc->Buffer.Length; 795a159c266SJung-uk Kim break; 796a159c266SJung-uk Kim 797a159c266SJung-uk Kim case ACPI_TYPE_PACKAGE: 798a159c266SJung-uk Kim 799a159c266SJung-uk Kim /* Package arguments may not be evaluated at this point */ 800a159c266SJung-uk Kim 801a159c266SJung-uk Kim Status = AcpiDsGetPackageArguments (TempDesc); 802a159c266SJung-uk Kim Value = TempDesc->Package.Count; 803a159c266SJung-uk Kim break; 804a159c266SJung-uk Kim 805a159c266SJung-uk Kim default: 806a9d8d09cSJung-uk Kim 807a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, 808f8146b88SJung-uk Kim "Operand must be Buffer/Integer/String/Package" 809f8146b88SJung-uk Kim " - found type %s", 810a159c266SJung-uk Kim AcpiUtGetTypeName (Type))); 811f8146b88SJung-uk Kim 812a159c266SJung-uk Kim Status = AE_AML_OPERAND_TYPE; 813a159c266SJung-uk Kim goto Cleanup; 814a159c266SJung-uk Kim } 815a159c266SJung-uk Kim 816a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 817a159c266SJung-uk Kim { 818a159c266SJung-uk Kim goto Cleanup; 819a159c266SJung-uk Kim } 820a159c266SJung-uk Kim 821a159c266SJung-uk Kim /* 822a159c266SJung-uk Kim * Now that we have the size of the object, create a result 823a159c266SJung-uk Kim * object to hold the value 824a159c266SJung-uk Kim */ 825a159c266SJung-uk Kim ReturnDesc = AcpiUtCreateIntegerObject (Value); 826a159c266SJung-uk Kim if (!ReturnDesc) 827a159c266SJung-uk Kim { 828a159c266SJung-uk Kim Status = AE_NO_MEMORY; 829a159c266SJung-uk Kim goto Cleanup; 830a159c266SJung-uk Kim } 831a159c266SJung-uk Kim break; 832a159c266SJung-uk Kim 833a159c266SJung-uk Kim 834a159c266SJung-uk Kim case AML_REF_OF_OP: /* RefOf (SourceObject) */ 835a159c266SJung-uk Kim 836f8146b88SJung-uk Kim Status = AcpiExGetObjectReference ( 837f8146b88SJung-uk Kim Operand[0], &ReturnDesc, WalkState); 838a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 839a159c266SJung-uk Kim { 840a159c266SJung-uk Kim goto Cleanup; 841a159c266SJung-uk Kim } 842a159c266SJung-uk Kim break; 843a159c266SJung-uk Kim 844a159c266SJung-uk Kim 845a159c266SJung-uk Kim case AML_DEREF_OF_OP: /* DerefOf (ObjReference | String) */ 846a159c266SJung-uk Kim 847a159c266SJung-uk Kim /* Check for a method local or argument, or standalone String */ 848a159c266SJung-uk Kim 849a159c266SJung-uk Kim if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED) 850a159c266SJung-uk Kim { 851a159c266SJung-uk Kim TempDesc = AcpiNsGetAttachedObject ( 852a159c266SJung-uk Kim (ACPI_NAMESPACE_NODE *) Operand[0]); 853a159c266SJung-uk Kim if (TempDesc && 854a159c266SJung-uk Kim ((TempDesc->Common.Type == ACPI_TYPE_STRING) || 855a159c266SJung-uk Kim (TempDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE))) 856a159c266SJung-uk Kim { 857a159c266SJung-uk Kim Operand[0] = TempDesc; 858a159c266SJung-uk Kim AcpiUtAddReference (TempDesc); 859a159c266SJung-uk Kim } 860a159c266SJung-uk Kim else 861a159c266SJung-uk Kim { 862a159c266SJung-uk Kim Status = AE_AML_OPERAND_TYPE; 863a159c266SJung-uk Kim goto Cleanup; 864a159c266SJung-uk Kim } 865a159c266SJung-uk Kim } 866a159c266SJung-uk Kim else 867a159c266SJung-uk Kim { 868a159c266SJung-uk Kim switch ((Operand[0])->Common.Type) 869a159c266SJung-uk Kim { 870a159c266SJung-uk Kim case ACPI_TYPE_LOCAL_REFERENCE: 871a159c266SJung-uk Kim /* 872a159c266SJung-uk Kim * This is a DerefOf (LocalX | ArgX) 873a159c266SJung-uk Kim * 874a159c266SJung-uk Kim * Must resolve/dereference the local/arg reference first 875a159c266SJung-uk Kim */ 876a159c266SJung-uk Kim switch (Operand[0]->Reference.Class) 877a159c266SJung-uk Kim { 878a159c266SJung-uk Kim case ACPI_REFCLASS_LOCAL: 879a159c266SJung-uk Kim case ACPI_REFCLASS_ARG: 880a159c266SJung-uk Kim 881a159c266SJung-uk Kim /* Set Operand[0] to the value of the local/arg */ 882a159c266SJung-uk Kim 883a159c266SJung-uk Kim Status = AcpiDsMethodDataGetValue ( 884a159c266SJung-uk Kim Operand[0]->Reference.Class, 885a159c266SJung-uk Kim Operand[0]->Reference.Value, 886a159c266SJung-uk Kim WalkState, &TempDesc); 887a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 888a159c266SJung-uk Kim { 889a159c266SJung-uk Kim goto Cleanup; 890a159c266SJung-uk Kim } 891a159c266SJung-uk Kim 892a159c266SJung-uk Kim /* 893a159c266SJung-uk Kim * Delete our reference to the input object and 894a159c266SJung-uk Kim * point to the object just retrieved 895a159c266SJung-uk Kim */ 896a159c266SJung-uk Kim AcpiUtRemoveReference (Operand[0]); 897a159c266SJung-uk Kim Operand[0] = TempDesc; 898a159c266SJung-uk Kim break; 899a159c266SJung-uk Kim 900a159c266SJung-uk Kim case ACPI_REFCLASS_REFOF: 901a159c266SJung-uk Kim 902a159c266SJung-uk Kim /* Get the object to which the reference refers */ 903a159c266SJung-uk Kim 904a159c266SJung-uk Kim TempDesc = Operand[0]->Reference.Object; 905a159c266SJung-uk Kim AcpiUtRemoveReference (Operand[0]); 906a159c266SJung-uk Kim Operand[0] = TempDesc; 907a159c266SJung-uk Kim break; 908a159c266SJung-uk Kim 909a159c266SJung-uk Kim default: 910a159c266SJung-uk Kim 911a159c266SJung-uk Kim /* Must be an Index op - handled below */ 912a159c266SJung-uk Kim break; 913a159c266SJung-uk Kim } 914a159c266SJung-uk Kim break; 915a159c266SJung-uk Kim 916a159c266SJung-uk Kim case ACPI_TYPE_STRING: 917a9d8d09cSJung-uk Kim 918a159c266SJung-uk Kim break; 919a159c266SJung-uk Kim 920a159c266SJung-uk Kim default: 921a9d8d09cSJung-uk Kim 922a159c266SJung-uk Kim Status = AE_AML_OPERAND_TYPE; 923a159c266SJung-uk Kim goto Cleanup; 924a159c266SJung-uk Kim } 925a159c266SJung-uk Kim } 926a159c266SJung-uk Kim 927a159c266SJung-uk Kim if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) != ACPI_DESC_TYPE_NAMED) 928a159c266SJung-uk Kim { 929a159c266SJung-uk Kim if ((Operand[0])->Common.Type == ACPI_TYPE_STRING) 930a159c266SJung-uk Kim { 931a159c266SJung-uk Kim /* 932a159c266SJung-uk Kim * This is a DerefOf (String). The string is a reference 933a159c266SJung-uk Kim * to a named ACPI object. 934a159c266SJung-uk Kim * 935a159c266SJung-uk Kim * 1) Find the owning Node 936a159c266SJung-uk Kim * 2) Dereference the node to an actual object. Could be a 937a159c266SJung-uk Kim * Field, so we need to resolve the node to a value. 938a159c266SJung-uk Kim */ 939a159c266SJung-uk Kim Status = AcpiNsGetNode (WalkState->ScopeInfo->Scope.Node, 940a159c266SJung-uk Kim Operand[0]->String.Pointer, 941a159c266SJung-uk Kim ACPI_NS_SEARCH_PARENT, 942a159c266SJung-uk Kim ACPI_CAST_INDIRECT_PTR ( 943a159c266SJung-uk Kim ACPI_NAMESPACE_NODE, &ReturnDesc)); 944a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 945a159c266SJung-uk Kim { 946a159c266SJung-uk Kim goto Cleanup; 947a159c266SJung-uk Kim } 948a159c266SJung-uk Kim 949a159c266SJung-uk Kim Status = AcpiExResolveNodeToValue ( 950a159c266SJung-uk Kim ACPI_CAST_INDIRECT_PTR ( 951a159c266SJung-uk Kim ACPI_NAMESPACE_NODE, &ReturnDesc), 952a159c266SJung-uk Kim WalkState); 953a159c266SJung-uk Kim goto Cleanup; 954a159c266SJung-uk Kim } 955a159c266SJung-uk Kim } 956a159c266SJung-uk Kim 957a159c266SJung-uk Kim /* Operand[0] may have changed from the code above */ 958a159c266SJung-uk Kim 959a159c266SJung-uk Kim if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED) 960a159c266SJung-uk Kim { 961a159c266SJung-uk Kim /* 962a159c266SJung-uk Kim * This is a DerefOf (ObjectReference) 963a159c266SJung-uk Kim * Get the actual object from the Node (This is the dereference). 964a159c266SJung-uk Kim * This case may only happen when a LocalX or ArgX is 965a159c266SJung-uk Kim * dereferenced above. 966a159c266SJung-uk Kim */ 967a159c266SJung-uk Kim ReturnDesc = AcpiNsGetAttachedObject ( 968a159c266SJung-uk Kim (ACPI_NAMESPACE_NODE *) Operand[0]); 969a159c266SJung-uk Kim AcpiUtAddReference (ReturnDesc); 970a159c266SJung-uk Kim } 971a159c266SJung-uk Kim else 972a159c266SJung-uk Kim { 973a159c266SJung-uk Kim /* 974a159c266SJung-uk Kim * This must be a reference object produced by either the 975a159c266SJung-uk Kim * Index() or RefOf() operator 976a159c266SJung-uk Kim */ 977a159c266SJung-uk Kim switch (Operand[0]->Reference.Class) 978a159c266SJung-uk Kim { 979a159c266SJung-uk Kim case ACPI_REFCLASS_INDEX: 980a159c266SJung-uk Kim /* 981a159c266SJung-uk Kim * The target type for the Index operator must be 982a159c266SJung-uk Kim * either a Buffer or a Package 983a159c266SJung-uk Kim */ 984a159c266SJung-uk Kim switch (Operand[0]->Reference.TargetType) 985a159c266SJung-uk Kim { 986a159c266SJung-uk Kim case ACPI_TYPE_BUFFER_FIELD: 987a159c266SJung-uk Kim 988a159c266SJung-uk Kim TempDesc = Operand[0]->Reference.Object; 989a159c266SJung-uk Kim 990a159c266SJung-uk Kim /* 991a159c266SJung-uk Kim * Create a new object that contains one element of the 992a159c266SJung-uk Kim * buffer -- the element pointed to by the index. 993a159c266SJung-uk Kim * 994a159c266SJung-uk Kim * NOTE: index into a buffer is NOT a pointer to a 995a159c266SJung-uk Kim * sub-buffer of the main buffer, it is only a pointer to a 996a159c266SJung-uk Kim * single element (byte) of the buffer! 997a159c266SJung-uk Kim * 998a159c266SJung-uk Kim * Since we are returning the value of the buffer at the 999a159c266SJung-uk Kim * indexed location, we don't need to add an additional 1000a159c266SJung-uk Kim * reference to the buffer itself. 1001a159c266SJung-uk Kim */ 1002a159c266SJung-uk Kim ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) 1003a159c266SJung-uk Kim TempDesc->Buffer.Pointer[Operand[0]->Reference.Value]); 1004a159c266SJung-uk Kim if (!ReturnDesc) 1005a159c266SJung-uk Kim { 1006a159c266SJung-uk Kim Status = AE_NO_MEMORY; 1007a159c266SJung-uk Kim goto Cleanup; 1008a159c266SJung-uk Kim } 1009a159c266SJung-uk Kim break; 1010a159c266SJung-uk Kim 1011a159c266SJung-uk Kim case ACPI_TYPE_PACKAGE: 1012a159c266SJung-uk Kim /* 1013a159c266SJung-uk Kim * Return the referenced element of the package. We must 1014a159c266SJung-uk Kim * add another reference to the referenced object, however. 1015a159c266SJung-uk Kim */ 1016a159c266SJung-uk Kim ReturnDesc = *(Operand[0]->Reference.Where); 1017bf6fac21SJung-uk Kim if (!ReturnDesc) 1018a159c266SJung-uk Kim { 1019bf6fac21SJung-uk Kim /* 1020bf6fac21SJung-uk Kim * Element is NULL, do not allow the dereference. 1021bf6fac21SJung-uk Kim * This provides compatibility with other ACPI 1022bf6fac21SJung-uk Kim * implementations. 1023bf6fac21SJung-uk Kim */ 1024bf6fac21SJung-uk Kim return_ACPI_STATUS (AE_AML_UNINITIALIZED_ELEMENT); 1025a159c266SJung-uk Kim } 1026bf6fac21SJung-uk Kim 1027bf6fac21SJung-uk Kim AcpiUtAddReference (ReturnDesc); 1028a159c266SJung-uk Kim break; 1029a159c266SJung-uk Kim 1030a159c266SJung-uk Kim default: 1031a159c266SJung-uk Kim 1032a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, 1033a159c266SJung-uk Kim "Unknown Index TargetType 0x%X in reference object %p", 1034a159c266SJung-uk Kim Operand[0]->Reference.TargetType, Operand[0])); 1035f8146b88SJung-uk Kim 1036a159c266SJung-uk Kim Status = AE_AML_OPERAND_TYPE; 1037a159c266SJung-uk Kim goto Cleanup; 1038a159c266SJung-uk Kim } 1039a159c266SJung-uk Kim break; 1040a159c266SJung-uk Kim 1041a159c266SJung-uk Kim case ACPI_REFCLASS_REFOF: 1042a159c266SJung-uk Kim 1043a159c266SJung-uk Kim ReturnDesc = Operand[0]->Reference.Object; 1044a159c266SJung-uk Kim 1045a159c266SJung-uk Kim if (ACPI_GET_DESCRIPTOR_TYPE (ReturnDesc) == 1046a159c266SJung-uk Kim ACPI_DESC_TYPE_NAMED) 1047a159c266SJung-uk Kim { 1048a159c266SJung-uk Kim ReturnDesc = AcpiNsGetAttachedObject ( 1049a159c266SJung-uk Kim (ACPI_NAMESPACE_NODE *) ReturnDesc); 1050bf6fac21SJung-uk Kim if (!ReturnDesc) 1051bf6fac21SJung-uk Kim { 1052bf6fac21SJung-uk Kim break; 1053a159c266SJung-uk Kim } 1054a159c266SJung-uk Kim 1055bf6fac21SJung-uk Kim /* 1056bf6fac21SJung-uk Kim * June 2013: 1057bf6fac21SJung-uk Kim * BufferFields/FieldUnits require additional resolution 1058bf6fac21SJung-uk Kim */ 1059bf6fac21SJung-uk Kim switch (ReturnDesc->Common.Type) 1060bf6fac21SJung-uk Kim { 1061bf6fac21SJung-uk Kim case ACPI_TYPE_BUFFER_FIELD: 1062bf6fac21SJung-uk Kim case ACPI_TYPE_LOCAL_REGION_FIELD: 1063bf6fac21SJung-uk Kim case ACPI_TYPE_LOCAL_BANK_FIELD: 1064bf6fac21SJung-uk Kim case ACPI_TYPE_LOCAL_INDEX_FIELD: 1065bf6fac21SJung-uk Kim 1066f8146b88SJung-uk Kim Status = AcpiExReadDataFromField ( 1067f8146b88SJung-uk Kim WalkState, ReturnDesc, &TempDesc); 1068bf6fac21SJung-uk Kim if (ACPI_FAILURE (Status)) 1069bf6fac21SJung-uk Kim { 1070bf6fac21SJung-uk Kim goto Cleanup; 1071bf6fac21SJung-uk Kim } 1072bf6fac21SJung-uk Kim 1073bf6fac21SJung-uk Kim ReturnDesc = TempDesc; 1074bf6fac21SJung-uk Kim break; 1075bf6fac21SJung-uk Kim 1076bf6fac21SJung-uk Kim default: 1077bf6fac21SJung-uk Kim 1078bf6fac21SJung-uk Kim /* Add another reference to the object */ 1079a159c266SJung-uk Kim 1080a159c266SJung-uk Kim AcpiUtAddReference (ReturnDesc); 1081a159c266SJung-uk Kim break; 1082bf6fac21SJung-uk Kim } 1083bf6fac21SJung-uk Kim } 1084bf6fac21SJung-uk Kim break; 1085a159c266SJung-uk Kim 1086a159c266SJung-uk Kim default: 1087a9d8d09cSJung-uk Kim 1088a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, 1089a159c266SJung-uk Kim "Unknown class in reference(%p) - 0x%2.2X", 1090a159c266SJung-uk Kim Operand[0], Operand[0]->Reference.Class)); 1091a159c266SJung-uk Kim 1092a159c266SJung-uk Kim Status = AE_TYPE; 1093a159c266SJung-uk Kim goto Cleanup; 1094a159c266SJung-uk Kim } 1095a159c266SJung-uk Kim } 1096a159c266SJung-uk Kim break; 1097a159c266SJung-uk Kim 1098a159c266SJung-uk Kim default: 1099a159c266SJung-uk Kim 1100a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", 1101a159c266SJung-uk Kim WalkState->Opcode)); 1102f8146b88SJung-uk Kim 1103a159c266SJung-uk Kim Status = AE_AML_BAD_OPCODE; 1104a159c266SJung-uk Kim goto Cleanup; 1105a159c266SJung-uk Kim } 1106a159c266SJung-uk Kim 1107a159c266SJung-uk Kim 1108a159c266SJung-uk Kim Cleanup: 1109a159c266SJung-uk Kim 1110a159c266SJung-uk Kim /* Delete return object on error */ 1111a159c266SJung-uk Kim 1112a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 1113a159c266SJung-uk Kim { 1114a159c266SJung-uk Kim AcpiUtRemoveReference (ReturnDesc); 1115a159c266SJung-uk Kim } 1116a159c266SJung-uk Kim 1117a159c266SJung-uk Kim /* Save return object on success */ 1118a159c266SJung-uk Kim 1119a159c266SJung-uk Kim else 1120a159c266SJung-uk Kim { 1121a159c266SJung-uk Kim WalkState->ResultObj = ReturnDesc; 1122a159c266SJung-uk Kim } 1123a159c266SJung-uk Kim 1124a159c266SJung-uk Kim return_ACPI_STATUS (Status); 1125a159c266SJung-uk Kim } 1126