Path: blob/main/sys/contrib/dev/acpica/components/executer/exoparg1.c
48521 views
/******************************************************************************1*2* Module Name: exoparg1 - AML execution - opcodes with 1 argument3*4*****************************************************************************/56/******************************************************************************7*8* 1. Copyright Notice9*10* Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.11* All rights reserved.12*13* 2. License14*15* 2.1. This is your license from Intel Corp. under its intellectual property16* rights. You may have additional license terms from the party that provided17* you this software, covering your right to use that party's intellectual18* property rights.19*20* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a21* copy of the source code appearing in this file ("Covered Code") an22* irrevocable, perpetual, worldwide license under Intel's copyrights in the23* base code distributed originally by Intel ("Original Intel Code") to copy,24* make derivatives, distribute, use and display any portion of the Covered25* Code in any form, with the right to sublicense such rights; and26*27* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent28* license (with the right to sublicense), under only those claims of Intel29* patents that are infringed by the Original Intel Code, to make, use, sell,30* offer to sell, and import the Covered Code and derivative works thereof31* solely to the minimum extent necessary to exercise the above copyright32* license, and in no event shall the patent license extend to any additions33* to or modifications of the Original Intel Code. No other license or right34* is granted directly or by implication, estoppel or otherwise;35*36* The above copyright and patent license is granted only if the following37* conditions are met:38*39* 3. Conditions40*41* 3.1. Redistribution of Source with Rights to Further Distribute Source.42* Redistribution of source code of any substantial portion of the Covered43* Code or modification with rights to further distribute source must include44* the above Copyright Notice, the above License, this list of Conditions,45* and the following Disclaimer and Export Compliance provision. In addition,46* Licensee must cause all Covered Code to which Licensee contributes to47* contain a file documenting the changes Licensee made to create that Covered48* Code and the date of any change. Licensee must include in that file the49* documentation of any changes made by any predecessor Licensee. Licensee50* must include a prominent statement that the modification is derived,51* directly or indirectly, from Original Intel Code.52*53* 3.2. Redistribution of Source with no Rights to Further Distribute Source.54* Redistribution of source code of any substantial portion of the Covered55* Code or modification without rights to further distribute source must56* include the following Disclaimer and Export Compliance provision in the57* documentation and/or other materials provided with distribution. In58* addition, Licensee may not authorize further sublicense of source of any59* portion of the Covered Code, and must include terms to the effect that the60* license from Licensee to its licensee is limited to the intellectual61* property embodied in the software Licensee provides to its licensee, and62* not to intellectual property embodied in modifications its licensee may63* make.64*65* 3.3. Redistribution of Executable. Redistribution in executable form of any66* substantial portion of the Covered Code or modification must reproduce the67* above Copyright Notice, and the following Disclaimer and Export Compliance68* provision in the documentation and/or other materials provided with the69* distribution.70*71* 3.4. Intel retains all right, title, and interest in and to the Original72* Intel Code.73*74* 3.5. Neither the name Intel nor any other trademark owned or controlled by75* Intel shall be used in advertising or otherwise to promote the sale, use or76* other dealings in products derived from or relating to the Covered Code77* without prior written authorization from Intel.78*79* 4. Disclaimer and Export Compliance80*81* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED82* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE83* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,84* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY85* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY86* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A87* PARTICULAR PURPOSE.88*89* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES90* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR91* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,92* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY93* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL94* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS95* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY96* LIMITED REMEDY.97*98* 4.3. Licensee shall not export, either directly or indirectly, any of this99* software or system incorporating such software without first obtaining any100* required license or other approval from the U. S. Department of Commerce or101* any other agency or department of the United States Government. In the102* event Licensee exports any such software from the United States or103* re-exports any such software from a foreign destination, Licensee shall104* ensure that the distribution and export/re-export of the software is in105* compliance with all laws, regulations, orders, or other restrictions of the106* U.S. Export Administration Regulations. Licensee agrees that neither it nor107* any of its subsidiaries will export/re-export any technical data, process,108* software, or service, directly or indirectly, to any country for which the109* United States government or any agency thereof requires an export license,110* other governmental approval, or letter of assurance, without first obtaining111* such license, approval or letter.112*113*****************************************************************************114*115* Alternatively, you may choose to be licensed under the terms of the116* following license:117*118* Redistribution and use in source and binary forms, with or without119* modification, are permitted provided that the following conditions120* are met:121* 1. Redistributions of source code must retain the above copyright122* notice, this list of conditions, and the following disclaimer,123* without modification.124* 2. Redistributions in binary form must reproduce at minimum a disclaimer125* substantially similar to the "NO WARRANTY" disclaimer below126* ("Disclaimer") and any redistribution must be conditioned upon127* including a substantially similar Disclaimer requirement for further128* binary redistribution.129* 3. Neither the names of the above-listed copyright holders nor the names130* of any contributors may be used to endorse or promote products derived131* from this software without specific prior written permission.132*133* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS134* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT135* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR136* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT137* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,138* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT139* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,140* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY141* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT142* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE143* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.144*145* Alternatively, you may choose to be licensed under the terms of the146* GNU General Public License ("GPL") version 2 as published by the Free147* Software Foundation.148*149*****************************************************************************/150151#include <contrib/dev/acpica/include/acpi.h>152#include <contrib/dev/acpica/include/accommon.h>153#include <contrib/dev/acpica/include/acparser.h>154#include <contrib/dev/acpica/include/acdispat.h>155#include <contrib/dev/acpica/include/acinterp.h>156#include <contrib/dev/acpica/include/amlcode.h>157#include <contrib/dev/acpica/include/acnamesp.h>158159160#define _COMPONENT ACPI_EXECUTER161ACPI_MODULE_NAME ("exoparg1")162163164/*!165* Naming convention for AML interpreter execution routines.166*167* The routines that begin execution of AML opcodes are named with a common168* convention based upon the number of arguments, the number of target operands,169* and whether or not a value is returned:170*171* AcpiExOpcode_xA_yT_zR172*173* Where:174*175* xA - ARGUMENTS: The number of arguments (input operands) that are176* required for this opcode type (0 through 6 args).177* yT - TARGETS: The number of targets (output operands) that are required178* for this opcode type (0, 1, or 2 targets).179* zR - RETURN VALUE: Indicates whether this opcode type returns a value180* as the function return (0 or 1).181*182* The AcpiExOpcode* functions are called via the Dispatcher component with183* fully resolved operands.184!*/185186/*******************************************************************************187*188* FUNCTION: AcpiExOpcode_0A_0T_1R189*190* PARAMETERS: WalkState - Current state (contains AML opcode)191*192* RETURN: Status193*194* DESCRIPTION: Execute operator with no operands, one return value195*196******************************************************************************/197198ACPI_STATUS199AcpiExOpcode_0A_0T_1R (200ACPI_WALK_STATE *WalkState)201{202ACPI_STATUS Status = AE_OK;203ACPI_OPERAND_OBJECT *ReturnDesc = NULL;204205206ACPI_FUNCTION_TRACE_STR (ExOpcode_0A_0T_1R,207AcpiPsGetOpcodeName (WalkState->Opcode));208209210/* Examine the AML opcode */211212switch (WalkState->Opcode)213{214case AML_TIMER_OP: /* Timer () */215216/* Create a return object of type Integer */217218ReturnDesc = AcpiUtCreateIntegerObject (AcpiOsGetTimer ());219if (!ReturnDesc)220{221Status = AE_NO_MEMORY;222goto Cleanup;223}224break;225226default: /* Unknown opcode */227228ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",229WalkState->Opcode));230Status = AE_AML_BAD_OPCODE;231break;232}233234Cleanup:235236/* Delete return object on error */237238if ((ACPI_FAILURE (Status)) || WalkState->ResultObj)239{240AcpiUtRemoveReference (ReturnDesc);241WalkState->ResultObj = NULL;242}243else244{245/* Save the return value */246247WalkState->ResultObj = ReturnDesc;248}249250return_ACPI_STATUS (Status);251}252253254/*******************************************************************************255*256* FUNCTION: AcpiExOpcode_1A_0T_0R257*258* PARAMETERS: WalkState - Current state (contains AML opcode)259*260* RETURN: Status261*262* DESCRIPTION: Execute Type 1 monadic operator with numeric operand on263* object stack264*265******************************************************************************/266267ACPI_STATUS268AcpiExOpcode_1A_0T_0R (269ACPI_WALK_STATE *WalkState)270{271ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0];272ACPI_STATUS Status = AE_OK;273274275ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_0T_0R,276AcpiPsGetOpcodeName (WalkState->Opcode));277278279/* Examine the AML opcode */280281switch (WalkState->Opcode)282{283case AML_RELEASE_OP: /* Release (MutexObject) */284285Status = AcpiExReleaseMutex (Operand[0], WalkState);286break;287288case AML_RESET_OP: /* Reset (EventObject) */289290Status = AcpiExSystemResetEvent (Operand[0]);291break;292293case AML_SIGNAL_OP: /* Signal (EventObject) */294295Status = AcpiExSystemSignalEvent (Operand[0]);296break;297298case AML_SLEEP_OP: /* Sleep (MsecTime) */299300Status = AcpiExSystemDoSleep (Operand[0]->Integer.Value);301break;302303case AML_STALL_OP: /* Stall (UsecTime) */304305Status = AcpiExSystemDoStall ((UINT32) Operand[0]->Integer.Value);306break;307308case AML_UNLOAD_OP: /* Unload (Handle) */309310Status = AcpiExUnloadTable (Operand[0]);311break;312313default: /* Unknown opcode */314315ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",316WalkState->Opcode));317Status = AE_AML_BAD_OPCODE;318break;319}320321return_ACPI_STATUS (Status);322}323324325#ifdef _OBSOLETE_CODE /* Was originally used for Load() operator */326/*******************************************************************************327*328* FUNCTION: AcpiExOpcode_1A_1T_0R329*330* PARAMETERS: WalkState - Current state (contains AML opcode)331*332* RETURN: Status333*334* DESCRIPTION: Execute opcode with one argument, one target, and no335* return value.336*337******************************************************************************/338339ACPI_STATUS340AcpiExOpcode_1A_1T_0R (341ACPI_WALK_STATE *WalkState)342{343ACPI_STATUS Status = AE_OK;344ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0];345346347ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_1T_0R,348AcpiPsGetOpcodeName (WalkState->Opcode));349350351/* Examine the AML opcode */352353switch (WalkState->Opcode)354{355#ifdef _OBSOLETE_CODE356case AML_LOAD_OP:357358Status = AcpiExLoadOp (Operand[0], Operand[1], WalkState);359break;360#endif361362default: /* Unknown opcode */363364ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",365WalkState->Opcode));366Status = AE_AML_BAD_OPCODE;367goto Cleanup;368}369370371Cleanup:372373return_ACPI_STATUS (Status);374}375#endif376377/*******************************************************************************378*379* FUNCTION: AcpiExOpcode_1A_1T_1R380*381* PARAMETERS: WalkState - Current state (contains AML opcode)382*383* RETURN: Status384*385* DESCRIPTION: Execute opcode with one argument, one target, and a386* return value.387* January 2022: Added Load operator, with new ACPI 6.4388* semantics.389*390******************************************************************************/391392ACPI_STATUS393AcpiExOpcode_1A_1T_1R (394ACPI_WALK_STATE *WalkState)395{396ACPI_STATUS Status = AE_OK;397ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0];398ACPI_OPERAND_OBJECT *ReturnDesc = NULL;399ACPI_OPERAND_OBJECT *ReturnDesc2 = NULL;400UINT32 Temp32;401UINT32 i;402UINT64 PowerOfTen;403UINT64 Digit;404405406ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_1T_1R,407AcpiPsGetOpcodeName (WalkState->Opcode));408409410/* Examine the AML opcode */411412switch (WalkState->Opcode)413{414case AML_BIT_NOT_OP:415case AML_FIND_SET_LEFT_BIT_OP:416case AML_FIND_SET_RIGHT_BIT_OP:417case AML_FROM_BCD_OP:418case AML_LOAD_OP:419case AML_TO_BCD_OP:420case AML_CONDITIONAL_REF_OF_OP:421422/* Create a return object of type Integer for these opcodes */423424ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);425if (!ReturnDesc)426{427Status = AE_NO_MEMORY;428goto Cleanup;429}430431switch (WalkState->Opcode)432{433case AML_BIT_NOT_OP: /* Not (Operand, Result) */434435ReturnDesc->Integer.Value = ~Operand[0]->Integer.Value;436break;437438case AML_FIND_SET_LEFT_BIT_OP: /* FindSetLeftBit (Operand, Result) */439440ReturnDesc->Integer.Value = Operand[0]->Integer.Value;441442/*443* Acpi specification describes Integer type as a little444* endian unsigned value, so this boundary condition is valid.445*/446for (Temp32 = 0; ReturnDesc->Integer.Value &&447Temp32 < ACPI_INTEGER_BIT_SIZE; ++Temp32)448{449ReturnDesc->Integer.Value >>= 1;450}451452ReturnDesc->Integer.Value = Temp32;453break;454455case AML_FIND_SET_RIGHT_BIT_OP: /* FindSetRightBit (Operand, Result) */456457ReturnDesc->Integer.Value = Operand[0]->Integer.Value;458459/*460* The Acpi specification describes Integer type as a little461* endian unsigned value, so this boundary condition is valid.462*/463for (Temp32 = 0; ReturnDesc->Integer.Value &&464Temp32 < ACPI_INTEGER_BIT_SIZE; ++Temp32)465{466ReturnDesc->Integer.Value <<= 1;467}468469/* Since the bit position is one-based, subtract from 33 (65) */470471ReturnDesc->Integer.Value =472Temp32 == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - Temp32;473break;474475case AML_FROM_BCD_OP: /* FromBcd (BCDValue, Result) */476/*477* The 64-bit ACPI integer can hold 16 4-bit BCD characters478* (if table is 32-bit, integer can hold 8 BCD characters)479* Convert each 4-bit BCD value480*/481PowerOfTen = 1;482ReturnDesc->Integer.Value = 0;483Digit = Operand[0]->Integer.Value;484485/* Convert each BCD digit (each is one nybble wide) */486487for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++)488{489/* Get the least significant 4-bit BCD digit */490491Temp32 = ((UINT32) Digit) & 0xF;492493/* Check the range of the digit */494495if (Temp32 > 9)496{497ACPI_ERROR ((AE_INFO,498"BCD digit too large (not decimal): 0x%X",499Temp32));500501Status = AE_AML_NUMERIC_OVERFLOW;502goto Cleanup;503}504505/* Sum the digit into the result with the current power of 10 */506507ReturnDesc->Integer.Value +=508(((UINT64) Temp32) * PowerOfTen);509510/* Shift to next BCD digit */511512Digit >>= 4;513514/* Next power of 10 */515516PowerOfTen *= 10;517}518break;519520case AML_LOAD_OP: /* Result1 = Load (Operand[0], Result1) */521522ReturnDesc->Integer.Value = 0;523Status = AcpiExLoadOp (Operand[0], ReturnDesc, WalkState);524if (ACPI_SUCCESS (Status))525{526/* Return -1 (non-zero) indicates success */527528ReturnDesc->Integer.Value = 0xFFFFFFFFFFFFFFFF;529}530break;531532case AML_TO_BCD_OP: /* ToBcd (Operand, Result) */533534ReturnDesc->Integer.Value = 0;535Digit = Operand[0]->Integer.Value;536537/* Each BCD digit is one nybble wide */538539for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++)540{541(void) AcpiUtShortDivide (Digit, 10, &Digit, &Temp32);542543/*544* Insert the BCD digit that resides in the545* remainder from above546*/547ReturnDesc->Integer.Value |=548(((UINT64) Temp32) << ACPI_MUL_4 (i));549}550551/* Overflow if there is any data left in Digit */552553if (Digit > 0)554{555ACPI_ERROR ((AE_INFO,556"Integer too large to convert to BCD: 0x%8.8X%8.8X",557ACPI_FORMAT_UINT64 (Operand[0]->Integer.Value)));558Status = AE_AML_NUMERIC_OVERFLOW;559goto Cleanup;560}561break;562563case AML_CONDITIONAL_REF_OF_OP: /* CondRefOf (SourceObject, Result) */564/*565* This op is a little strange because the internal return value is566* different than the return value stored in the result descriptor567* (There are really two return values)568*/569if ((ACPI_NAMESPACE_NODE *) Operand[0] == AcpiGbl_RootNode)570{571/*572* This means that the object does not exist in the namespace,573* return FALSE574*/575ReturnDesc->Integer.Value = 0;576goto Cleanup;577}578579/* Get the object reference, store it, and remove our reference */580581Status = AcpiExGetObjectReference (Operand[0],582&ReturnDesc2, WalkState);583if (ACPI_FAILURE (Status))584{585goto Cleanup;586}587588Status = AcpiExStore (ReturnDesc2, Operand[1], WalkState);589AcpiUtRemoveReference (ReturnDesc2);590591/* The object exists in the namespace, return TRUE */592593ReturnDesc->Integer.Value = ACPI_UINT64_MAX;594goto Cleanup;595596597default:598599/* No other opcodes get here */600601break;602}603break;604605case AML_STORE_OP: /* Store (Source, Target) */606/*607* A store operand is typically a number, string, buffer or lvalue608* Be careful about deleting the source object,609* since the object itself may have been stored.610*/611Status = AcpiExStore (Operand[0], Operand[1], WalkState);612if (ACPI_FAILURE (Status))613{614return_ACPI_STATUS (Status);615}616617/* It is possible that the Store already produced a return object */618619if (!WalkState->ResultObj)620{621/*622* Normally, we would remove a reference on the Operand[0]623* parameter; But since it is being used as the internal return624* object (meaning we would normally increment it), the two625* cancel out, and we simply don't do anything.626*/627WalkState->ResultObj = Operand[0];628WalkState->Operands[0] = NULL; /* Prevent deletion */629}630return_ACPI_STATUS (Status);631632/*633* ACPI 2.0 Opcodes634*/635case AML_COPY_OBJECT_OP: /* CopyObject (Source, Target) */636637Status = AcpiUtCopyIobjectToIobject (638Operand[0], &ReturnDesc, WalkState);639break;640641case AML_TO_DECIMAL_STRING_OP: /* ToDecimalString (Data, Result) */642643Status = AcpiExConvertToString (644Operand[0], &ReturnDesc, ACPI_EXPLICIT_CONVERT_DECIMAL);645if (ReturnDesc == Operand[0])646{647/* No conversion performed, add ref to handle return value */648649AcpiUtAddReference (ReturnDesc);650}651break;652653case AML_TO_HEX_STRING_OP: /* ToHexString (Data, Result) */654655Status = AcpiExConvertToString (656Operand[0], &ReturnDesc, ACPI_EXPLICIT_CONVERT_HEX);657if (ReturnDesc == Operand[0])658{659/* No conversion performed, add ref to handle return value */660661AcpiUtAddReference (ReturnDesc);662}663break;664665case AML_TO_BUFFER_OP: /* ToBuffer (Data, Result) */666667Status = AcpiExConvertToBuffer (Operand[0], &ReturnDesc);668if (ReturnDesc == Operand[0])669{670/* No conversion performed, add ref to handle return value */671672AcpiUtAddReference (ReturnDesc);673}674break;675676case AML_TO_INTEGER_OP: /* ToInteger (Data, Result) */677678/* Perform "explicit" conversion */679680Status = AcpiExConvertToInteger (Operand[0], &ReturnDesc, 0);681if (ReturnDesc == Operand[0])682{683/* No conversion performed, add ref to handle return value */684685AcpiUtAddReference (ReturnDesc);686}687break;688689case AML_SHIFT_LEFT_BIT_OP: /* ShiftLeftBit (Source, BitNum) */690case AML_SHIFT_RIGHT_BIT_OP: /* ShiftRightBit (Source, BitNum) */691692/* These are two obsolete opcodes */693694ACPI_ERROR ((AE_INFO,695"%s is obsolete and not implemented",696AcpiPsGetOpcodeName (WalkState->Opcode)));697Status = AE_SUPPORT;698goto Cleanup;699700default: /* Unknown opcode */701702ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",703WalkState->Opcode));704Status = AE_AML_BAD_OPCODE;705goto Cleanup;706}707708if (ACPI_SUCCESS (Status))709{710/* Store the return value computed above into the target object */711712Status = AcpiExStore (ReturnDesc, Operand[1], WalkState);713}714715716Cleanup:717718/* Delete return object on error */719720if (ACPI_FAILURE (Status))721{722AcpiUtRemoveReference (ReturnDesc);723}724725/* Save return object on success */726727else if (!WalkState->ResultObj)728{729WalkState->ResultObj = ReturnDesc;730}731732return_ACPI_STATUS (Status);733}734735736/*******************************************************************************737*738* FUNCTION: AcpiExOpcode_1A_0T_1R739*740* PARAMETERS: WalkState - Current state (contains AML opcode)741*742* RETURN: Status743*744* DESCRIPTION: Execute opcode with one argument, no target, and a return value745*746******************************************************************************/747748ACPI_STATUS749AcpiExOpcode_1A_0T_1R (750ACPI_WALK_STATE *WalkState)751{752ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0];753ACPI_OPERAND_OBJECT *TempDesc;754ACPI_OPERAND_OBJECT *ReturnDesc = NULL;755ACPI_STATUS Status = AE_OK;756UINT32 Type;757UINT64 Value;758759760ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_0T_1R,761AcpiPsGetOpcodeName (WalkState->Opcode));762763764/* Examine the AML opcode */765766switch (WalkState->Opcode)767{768case AML_LOGICAL_NOT_OP: /* LNot (Operand) */769770ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) 0);771if (!ReturnDesc)772{773Status = AE_NO_MEMORY;774goto Cleanup;775}776777/*778* Set result to ONES (TRUE) if Value == 0. Note:779* ReturnDesc->Integer.Value is initially == 0 (FALSE) from above.780*/781if (!Operand[0]->Integer.Value)782{783ReturnDesc->Integer.Value = ACPI_UINT64_MAX;784}785break;786787case AML_DECREMENT_OP: /* Decrement (Operand) */788case AML_INCREMENT_OP: /* Increment (Operand) */789/*790* Create a new integer. Can't just get the base integer and791* increment it because it may be an Arg or Field.792*/793ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);794if (!ReturnDesc)795{796Status = AE_NO_MEMORY;797goto Cleanup;798}799800/*801* Since we are expecting a Reference operand, it can be either a802* NS Node or an internal object.803*/804TempDesc = Operand[0];805if (ACPI_GET_DESCRIPTOR_TYPE (TempDesc) == ACPI_DESC_TYPE_OPERAND)806{807/* Internal reference object - prevent deletion */808809AcpiUtAddReference (TempDesc);810}811812/*813* Convert the Reference operand to an Integer (This removes a814* reference on the Operand[0] object)815*816* NOTE: We use LNOT_OP here in order to force resolution of the817* reference operand to an actual integer.818*/819Status = AcpiExResolveOperands (AML_LOGICAL_NOT_OP,820&TempDesc, WalkState);821if (ACPI_FAILURE (Status))822{823ACPI_EXCEPTION ((AE_INFO, Status,824"While resolving operands for [%s]",825AcpiPsGetOpcodeName (WalkState->Opcode)));826827goto Cleanup;828}829830/*831* TempDesc is now guaranteed to be an Integer object --832* Perform the actual increment or decrement833*/834if (WalkState->Opcode == AML_INCREMENT_OP)835{836ReturnDesc->Integer.Value = TempDesc->Integer.Value + 1;837}838else839{840ReturnDesc->Integer.Value = TempDesc->Integer.Value - 1;841}842843/* Finished with this Integer object */844845AcpiUtRemoveReference (TempDesc);846847/*848* Store the result back (indirectly) through the original849* Reference object850*/851Status = AcpiExStore (ReturnDesc, Operand[0], WalkState);852break;853854case AML_OBJECT_TYPE_OP: /* ObjectType (SourceObject) */855/*856* Note: The operand is not resolved at this point because we want to857* get the associated object, not its value. For example, we don't858* want to resolve a FieldUnit to its value, we want the actual859* FieldUnit object.860*/861862/* Get the type of the base object */863864Status = AcpiExResolveMultiple (WalkState, Operand[0], &Type, NULL);865if (ACPI_FAILURE (Status))866{867goto Cleanup;868}869870/* Allocate a descriptor to hold the type. */871872ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) Type);873if (!ReturnDesc)874{875Status = AE_NO_MEMORY;876goto Cleanup;877}878break;879880case AML_SIZE_OF_OP: /* SizeOf (SourceObject) */881/*882* Note: The operand is not resolved at this point because we want to883* get the associated object, not its value.884*/885886/* Get the base object */887888Status = AcpiExResolveMultiple (889WalkState, Operand[0], &Type, &TempDesc);890if (ACPI_FAILURE (Status))891{892goto Cleanup;893}894895/*896* The type of the base object must be integer, buffer, string, or897* package. All others are not supported.898*899* NOTE: Integer is not specifically supported by the ACPI spec,900* but is supported implicitly via implicit operand conversion.901* rather than bother with conversion, we just use the byte width902* global (4 or 8 bytes).903*/904switch (Type)905{906case ACPI_TYPE_INTEGER:907908Value = AcpiGbl_IntegerByteWidth;909break;910911case ACPI_TYPE_STRING:912913Value = TempDesc->String.Length;914break;915916case ACPI_TYPE_BUFFER:917918/* Buffer arguments may not be evaluated at this point */919920Status = AcpiDsGetBufferArguments (TempDesc);921Value = TempDesc->Buffer.Length;922break;923924case ACPI_TYPE_PACKAGE:925926/* Package arguments may not be evaluated at this point */927928Status = AcpiDsGetPackageArguments (TempDesc);929Value = TempDesc->Package.Count;930break;931932default:933934ACPI_ERROR ((AE_INFO,935"Operand must be Buffer/Integer/String/Package"936" - found type %s",937AcpiUtGetTypeName (Type)));938939Status = AE_AML_OPERAND_TYPE;940goto Cleanup;941}942943if (ACPI_FAILURE (Status))944{945goto Cleanup;946}947948/*949* Now that we have the size of the object, create a result950* object to hold the value951*/952ReturnDesc = AcpiUtCreateIntegerObject (Value);953if (!ReturnDesc)954{955Status = AE_NO_MEMORY;956goto Cleanup;957}958break;959960961case AML_REF_OF_OP: /* RefOf (SourceObject) */962963Status = AcpiExGetObjectReference (964Operand[0], &ReturnDesc, WalkState);965if (ACPI_FAILURE (Status))966{967goto Cleanup;968}969break;970971972case AML_DEREF_OF_OP: /* DerefOf (ObjReference | String) */973974/* Check for a method local or argument, or standalone String */975976if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED)977{978TempDesc = AcpiNsGetAttachedObject (979(ACPI_NAMESPACE_NODE *) Operand[0]);980if (TempDesc &&981((TempDesc->Common.Type == ACPI_TYPE_STRING) ||982(TempDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE)))983{984Operand[0] = TempDesc;985AcpiUtAddReference (TempDesc);986}987else988{989Status = AE_AML_OPERAND_TYPE;990goto Cleanup;991}992}993else994{995switch ((Operand[0])->Common.Type)996{997case ACPI_TYPE_LOCAL_REFERENCE:998/*999* This is a DerefOf (LocalX | ArgX)1000*1001* Must resolve/dereference the local/arg reference first1002*/1003switch (Operand[0]->Reference.Class)1004{1005case ACPI_REFCLASS_LOCAL:1006case ACPI_REFCLASS_ARG:10071008/* Set Operand[0] to the value of the local/arg */10091010Status = AcpiDsMethodDataGetValue (1011Operand[0]->Reference.Class,1012Operand[0]->Reference.Value,1013WalkState, &TempDesc);1014if (ACPI_FAILURE (Status))1015{1016goto Cleanup;1017}10181019/*1020* Delete our reference to the input object and1021* point to the object just retrieved1022*/1023AcpiUtRemoveReference (Operand[0]);1024Operand[0] = TempDesc;1025break;10261027case ACPI_REFCLASS_REFOF:10281029/* Get the object to which the reference refers */10301031TempDesc = Operand[0]->Reference.Object;1032AcpiUtRemoveReference (Operand[0]);1033Operand[0] = TempDesc;1034break;10351036default:10371038/* Must be an Index op - handled below */1039break;1040}1041break;10421043case ACPI_TYPE_STRING:10441045break;10461047default:10481049Status = AE_AML_OPERAND_TYPE;1050goto Cleanup;1051}1052}10531054if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) != ACPI_DESC_TYPE_NAMED)1055{1056if ((Operand[0])->Common.Type == ACPI_TYPE_STRING)1057{1058/*1059* This is a DerefOf (String). The string is a reference1060* to a named ACPI object.1061*1062* 1) Find the owning Node1063* 2) Dereference the node to an actual object. Could be a1064* Field, so we need to resolve the node to a value.1065*/1066Status = AcpiNsGetNodeUnlocked (WalkState->ScopeInfo->Scope.Node,1067Operand[0]->String.Pointer,1068ACPI_NS_SEARCH_PARENT,1069ACPI_CAST_INDIRECT_PTR (1070ACPI_NAMESPACE_NODE, &ReturnDesc));1071if (ACPI_FAILURE (Status))1072{1073goto Cleanup;1074}10751076Status = AcpiExResolveNodeToValue (1077ACPI_CAST_INDIRECT_PTR (1078ACPI_NAMESPACE_NODE, &ReturnDesc),1079WalkState);1080goto Cleanup;1081}1082}10831084/* Operand[0] may have changed from the code above */10851086if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED)1087{1088/*1089* This is a DerefOf (ObjectReference)1090* Get the actual object from the Node (This is the dereference).1091* This case may only happen when a LocalX or ArgX is1092* dereferenced above, or for references to device and1093* thermal objects.1094*/1095switch (((ACPI_NAMESPACE_NODE *) Operand[0])->Type)1096{1097case ACPI_TYPE_DEVICE:1098case ACPI_TYPE_THERMAL:10991100/* These types have no node subobject, return the NS node */11011102ReturnDesc = Operand[0];1103break;11041105default:1106/* For most types, get the object attached to the node */11071108ReturnDesc = AcpiNsGetAttachedObject (1109(ACPI_NAMESPACE_NODE *) Operand[0]);1110AcpiUtAddReference (ReturnDesc);1111break;1112}1113}1114else1115{1116/*1117* This must be a reference object produced by either the1118* Index() or RefOf() operator1119*/1120switch (Operand[0]->Reference.Class)1121{1122case ACPI_REFCLASS_INDEX:1123/*1124* The target type for the Index operator must be1125* either a Buffer or a Package1126*/1127switch (Operand[0]->Reference.TargetType)1128{1129case ACPI_TYPE_BUFFER_FIELD:11301131TempDesc = Operand[0]->Reference.Object;11321133/*1134* Create a new object that contains one element of the1135* buffer -- the element pointed to by the index.1136*1137* NOTE: index into a buffer is NOT a pointer to a1138* sub-buffer of the main buffer, it is only a pointer to a1139* single element (byte) of the buffer!1140*1141* Since we are returning the value of the buffer at the1142* indexed location, we don't need to add an additional1143* reference to the buffer itself.1144*/1145ReturnDesc = AcpiUtCreateIntegerObject ((UINT64)1146TempDesc->Buffer.Pointer[Operand[0]->Reference.Value]);1147if (!ReturnDesc)1148{1149Status = AE_NO_MEMORY;1150goto Cleanup;1151}1152break;11531154case ACPI_TYPE_PACKAGE:1155/*1156* Return the referenced element of the package. We must1157* add another reference to the referenced object, however.1158*/1159ReturnDesc = *(Operand[0]->Reference.Where);1160if (!ReturnDesc)1161{1162/*1163* Element is NULL, do not allow the dereference.1164* This provides compatibility with other ACPI1165* implementations.1166*/1167return_ACPI_STATUS (AE_AML_UNINITIALIZED_ELEMENT);1168}11691170AcpiUtAddReference (ReturnDesc);1171break;11721173default:11741175ACPI_ERROR ((AE_INFO,1176"Unknown Index TargetType 0x%X in reference object %p",1177Operand[0]->Reference.TargetType, Operand[0]));11781179Status = AE_AML_OPERAND_TYPE;1180goto Cleanup;1181}1182break;11831184case ACPI_REFCLASS_REFOF:11851186ReturnDesc = Operand[0]->Reference.Object;11871188if (ACPI_GET_DESCRIPTOR_TYPE (ReturnDesc) ==1189ACPI_DESC_TYPE_NAMED)1190{1191ReturnDesc = AcpiNsGetAttachedObject (1192(ACPI_NAMESPACE_NODE *) ReturnDesc);1193if (!ReturnDesc)1194{1195break;1196}11971198/*1199* June 2013:1200* BufferFields/FieldUnits require additional resolution1201*/1202switch (ReturnDesc->Common.Type)1203{1204case ACPI_TYPE_BUFFER_FIELD:1205case ACPI_TYPE_LOCAL_REGION_FIELD:1206case ACPI_TYPE_LOCAL_BANK_FIELD:1207case ACPI_TYPE_LOCAL_INDEX_FIELD:12081209Status = AcpiExReadDataFromField (1210WalkState, ReturnDesc, &TempDesc);1211if (ACPI_FAILURE (Status))1212{1213return_ACPI_STATUS (Status);1214}12151216ReturnDesc = TempDesc;1217break;12181219default:12201221/* Add another reference to the object */12221223AcpiUtAddReference (ReturnDesc);1224break;1225}1226}1227break;12281229default:12301231ACPI_ERROR ((AE_INFO,1232"Unknown class in reference(%p) - 0x%2.2X",1233Operand[0], Operand[0]->Reference.Class));12341235Status = AE_TYPE;1236goto Cleanup;1237}1238}1239break;12401241default:12421243ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",1244WalkState->Opcode));12451246Status = AE_AML_BAD_OPCODE;1247goto Cleanup;1248}124912501251Cleanup:12521253/* Delete return object on error */12541255if (ACPI_FAILURE (Status))1256{1257AcpiUtRemoveReference (ReturnDesc);1258}12591260/* Save return object on success */12611262else1263{1264WalkState->ResultObj = ReturnDesc;1265}12661267return_ACPI_STATUS (Status);1268}126912701271