Path: blob/main/sys/contrib/dev/acpica/components/executer/exmisc.c
48521 views
/******************************************************************************1*2* Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes3*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 ANY8586* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY87* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A88* PARTICULAR PURPOSE.89*90* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES91* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR92* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,93* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY94* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL95* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS96* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY97* LIMITED REMEDY.98*99* 4.3. Licensee shall not export, either directly or indirectly, any of this100* software or system incorporating such software without first obtaining any101* required license or other approval from the U. S. Department of Commerce or102* any other agency or department of the United States Government. In the103* event Licensee exports any such software from the United States or104* re-exports any such software from a foreign destination, Licensee shall105* ensure that the distribution and export/re-export of the software is in106* compliance with all laws, regulations, orders, or other restrictions of the107* U.S. Export Administration Regulations. Licensee agrees that neither it nor108* any of its subsidiaries will export/re-export any technical data, process,109* software, or service, directly or indirectly, to any country for which the110* United States government or any agency thereof requires an export license,111* other governmental approval, or letter of assurance, without first obtaining112* such license, approval or letter.113*114*****************************************************************************115*116* Alternatively, you may choose to be licensed under the terms of the117* following license:118*119* Redistribution and use in source and binary forms, with or without120* modification, are permitted provided that the following conditions121* are met:122* 1. Redistributions of source code must retain the above copyright123* notice, this list of conditions, and the following disclaimer,124* without modification.125* 2. Redistributions in binary form must reproduce at minimum a disclaimer126* substantially similar to the "NO WARRANTY" disclaimer below127* ("Disclaimer") and any redistribution must be conditioned upon128* including a substantially similar Disclaimer requirement for further129* binary redistribution.130* 3. Neither the names of the above-listed copyright holders nor the names131* of any contributors may be used to endorse or promote products derived132* from this software without specific prior written permission.133*134* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS135* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT136* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR137* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT138* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,139* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT140* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,141* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY142* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT143* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE144* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.145*146* Alternatively, you may choose to be licensed under the terms of the147* GNU General Public License ("GPL") version 2 as published by the Free148* Software Foundation.149*150*****************************************************************************/151152#include <contrib/dev/acpica/include/acpi.h>153#include <contrib/dev/acpica/include/accommon.h>154#include <contrib/dev/acpica/include/acinterp.h>155#include <contrib/dev/acpica/include/amlcode.h>156157158#define _COMPONENT ACPI_EXECUTER159ACPI_MODULE_NAME ("exmisc")160161162/*******************************************************************************163*164* FUNCTION: AcpiExGetObjectReference165*166* PARAMETERS: ObjDesc - Create a reference to this object167* ReturnDesc - Where to store the reference168* WalkState - Current state169*170* RETURN: Status171*172* DESCRIPTION: Obtain and return a "reference" to the target object173* Common code for the RefOfOp and the CondRefOfOp.174*175******************************************************************************/176177ACPI_STATUS178AcpiExGetObjectReference (179ACPI_OPERAND_OBJECT *ObjDesc,180ACPI_OPERAND_OBJECT **ReturnDesc,181ACPI_WALK_STATE *WalkState)182{183ACPI_OPERAND_OBJECT *ReferenceObj;184ACPI_OPERAND_OBJECT *ReferencedObj;185186187ACPI_FUNCTION_TRACE_PTR (ExGetObjectReference, ObjDesc);188189190*ReturnDesc = NULL;191192switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))193{194case ACPI_DESC_TYPE_OPERAND:195196if (ObjDesc->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)197{198return_ACPI_STATUS (AE_AML_OPERAND_TYPE);199}200201/*202* Must be a reference to a Local or Arg203*/204switch (ObjDesc->Reference.Class)205{206case ACPI_REFCLASS_LOCAL:207case ACPI_REFCLASS_ARG:208case ACPI_REFCLASS_DEBUG:209210/* The referenced object is the pseudo-node for the local/arg */211212ReferencedObj = ObjDesc->Reference.Object;213break;214215default:216217ACPI_ERROR ((AE_INFO, "Invalid Reference Class 0x%2.2X",218ObjDesc->Reference.Class));219return_ACPI_STATUS (AE_AML_OPERAND_TYPE);220}221break;222223case ACPI_DESC_TYPE_NAMED:224/*225* A named reference that has already been resolved to a Node226*/227ReferencedObj = ObjDesc;228break;229230default:231232ACPI_ERROR ((AE_INFO, "Invalid descriptor type 0x%X",233ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)));234return_ACPI_STATUS (AE_TYPE);235}236237238/* Create a new reference object */239240ReferenceObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);241if (!ReferenceObj)242{243return_ACPI_STATUS (AE_NO_MEMORY);244}245246ReferenceObj->Reference.Class = ACPI_REFCLASS_REFOF;247ReferenceObj->Reference.Object = ReferencedObj;248*ReturnDesc = ReferenceObj;249250ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,251"Object %p Type [%s], returning Reference %p\n",252ObjDesc, AcpiUtGetObjectTypeName (ObjDesc), *ReturnDesc));253254return_ACPI_STATUS (AE_OK);255}256257258/*******************************************************************************259*260* FUNCTION: AcpiExDoMathOp261*262* PARAMETERS: Opcode - AML opcode263* Integer0 - Integer operand #0264* Integer1 - Integer operand #1265*266* RETURN: Integer result of the operation267*268* DESCRIPTION: Execute a math AML opcode. The purpose of having all of the269* math functions here is to prevent a lot of pointer dereferencing270* to obtain the operands.271*272******************************************************************************/273274UINT64275AcpiExDoMathOp (276UINT16 Opcode,277UINT64 Integer0,278UINT64 Integer1)279{280281ACPI_FUNCTION_ENTRY ();282283284switch (Opcode)285{286case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */287288return (Integer0 + Integer1);289290case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */291292return (Integer0 & Integer1);293294case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */295296return (~(Integer0 & Integer1));297298case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */299300return (Integer0 | Integer1);301302case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */303304return (~(Integer0 | Integer1));305306case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */307308return (Integer0 ^ Integer1);309310case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */311312return (Integer0 * Integer1);313314case AML_SHIFT_LEFT_OP: /* ShiftLeft (Operand, ShiftCount, Result)*/315316/*317* We need to check if the shiftcount is larger than the integer bit318* width since the behavior of this is not well-defined in the C language.319*/320if (Integer1 >= AcpiGbl_IntegerBitWidth)321{322return (0);323}324return (Integer0 << Integer1);325326case AML_SHIFT_RIGHT_OP: /* ShiftRight (Operand, ShiftCount, Result) */327328/*329* We need to check if the shiftcount is larger than the integer bit330* width since the behavior of this is not well-defined in the C language.331*/332if (Integer1 >= AcpiGbl_IntegerBitWidth)333{334return (0);335}336return (Integer0 >> Integer1);337338case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */339340return (Integer0 - Integer1);341342default:343344return (0);345}346}347348349/*******************************************************************************350*351* FUNCTION: AcpiExDoLogicalNumericOp352*353* PARAMETERS: Opcode - AML opcode354* Integer0 - Integer operand #0355* Integer1 - Integer operand #1356* LogicalResult - TRUE/FALSE result of the operation357*358* RETURN: Status359*360* DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric361* operators (LAnd and LOr), both operands must be integers.362*363* Note: cleanest machine code seems to be produced by the code364* below, rather than using statements of the form:365* Result = (Integer0 && Integer1);366*367******************************************************************************/368369ACPI_STATUS370AcpiExDoLogicalNumericOp (371UINT16 Opcode,372UINT64 Integer0,373UINT64 Integer1,374BOOLEAN *LogicalResult)375{376ACPI_STATUS Status = AE_OK;377BOOLEAN LocalResult = FALSE;378379380ACPI_FUNCTION_TRACE (ExDoLogicalNumericOp);381382383switch (Opcode)384{385case AML_LOGICAL_AND_OP: /* LAnd (Integer0, Integer1) */386387if (Integer0 && Integer1)388{389LocalResult = TRUE;390}391break;392393case AML_LOGICAL_OR_OP: /* LOr (Integer0, Integer1) */394395if (Integer0 || Integer1)396{397LocalResult = TRUE;398}399break;400401default:402403ACPI_ERROR ((AE_INFO,404"Invalid numeric logical opcode: %X", Opcode));405Status = AE_AML_INTERNAL;406break;407}408409/* Return the logical result and status */410411*LogicalResult = LocalResult;412return_ACPI_STATUS (Status);413}414415416/*******************************************************************************417*418* FUNCTION: AcpiExDoLogicalOp419*420* PARAMETERS: Opcode - AML opcode421* Operand0 - operand #0422* Operand1 - operand #1423* LogicalResult - TRUE/FALSE result of the operation424*425* RETURN: Status426*427* DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the428* functions here is to prevent a lot of pointer dereferencing429* to obtain the operands and to simplify the generation of the430* logical value. For the Numeric operators (LAnd and LOr), both431* operands must be integers. For the other logical operators,432* operands can be any combination of Integer/String/Buffer. The433* first operand determines the type to which the second operand434* will be converted.435*436* Note: cleanest machine code seems to be produced by the code437* below, rather than using statements of the form:438* Result = (Operand0 == Operand1);439*440******************************************************************************/441442ACPI_STATUS443AcpiExDoLogicalOp (444UINT16 Opcode,445ACPI_OPERAND_OBJECT *Operand0,446ACPI_OPERAND_OBJECT *Operand1,447BOOLEAN *LogicalResult)448{449ACPI_OPERAND_OBJECT *LocalOperand1 = Operand1;450UINT64 Integer0;451UINT64 Integer1;452UINT32 Length0;453UINT32 Length1;454ACPI_STATUS Status = AE_OK;455BOOLEAN LocalResult = FALSE;456int Compare;457458459ACPI_FUNCTION_TRACE (ExDoLogicalOp);460461462/*463* Convert the second operand if necessary. The first operand464* determines the type of the second operand, (See the Data Types465* section of the ACPI 3.0+ specification.) Both object types are466* guaranteed to be either Integer/String/Buffer by the operand467* resolution mechanism.468*/469switch (Operand0->Common.Type)470{471case ACPI_TYPE_INTEGER:472473Status = AcpiExConvertToInteger (Operand1, &LocalOperand1,474ACPI_IMPLICIT_CONVERSION);475break;476477case ACPI_TYPE_STRING:478479Status = AcpiExConvertToString (480Operand1, &LocalOperand1, ACPI_IMPLICIT_CONVERT_HEX);481break;482483case ACPI_TYPE_BUFFER:484485Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);486break;487488default:489490ACPI_ERROR ((AE_INFO,491"Invalid object type for logical operator: %X",492Operand0->Common.Type));493Status = AE_AML_INTERNAL;494break;495}496497if (ACPI_FAILURE (Status))498{499goto Cleanup;500}501502/*503* Two cases: 1) Both Integers, 2) Both Strings or Buffers504*/505if (Operand0->Common.Type == ACPI_TYPE_INTEGER)506{507/*508* 1) Both operands are of type integer509* Note: LocalOperand1 may have changed above510*/511Integer0 = Operand0->Integer.Value;512Integer1 = LocalOperand1->Integer.Value;513514switch (Opcode)515{516case AML_LOGICAL_EQUAL_OP: /* LEqual (Operand0, Operand1) */517518if (Integer0 == Integer1)519{520LocalResult = TRUE;521}522break;523524case AML_LOGICAL_GREATER_OP: /* LGreater (Operand0, Operand1) */525526if (Integer0 > Integer1)527{528LocalResult = TRUE;529}530break;531532case AML_LOGICAL_LESS_OP: /* LLess (Operand0, Operand1) */533534if (Integer0 < Integer1)535{536LocalResult = TRUE;537}538break;539540default:541542ACPI_ERROR ((AE_INFO,543"Invalid comparison opcode: %X", Opcode));544Status = AE_AML_INTERNAL;545break;546}547}548else549{550/*551* 2) Both operands are Strings or both are Buffers552* Note: Code below takes advantage of common Buffer/String553* object fields. LocalOperand1 may have changed above. Use554* memcmp to handle nulls in buffers.555*/556Length0 = Operand0->Buffer.Length;557Length1 = LocalOperand1->Buffer.Length;558559/* Lexicographic compare: compare the data bytes */560561Compare = memcmp (Operand0->Buffer.Pointer,562LocalOperand1->Buffer.Pointer,563(Length0 > Length1) ? Length1 : Length0);564565switch (Opcode)566{567case AML_LOGICAL_EQUAL_OP: /* LEqual (Operand0, Operand1) */568569/* Length and all bytes must be equal */570571if ((Length0 == Length1) &&572(Compare == 0))573{574/* Length and all bytes match ==> TRUE */575576LocalResult = TRUE;577}578break;579580case AML_LOGICAL_GREATER_OP: /* LGreater (Operand0, Operand1) */581582if (Compare > 0)583{584LocalResult = TRUE;585goto Cleanup; /* TRUE */586}587if (Compare < 0)588{589goto Cleanup; /* FALSE */590}591592/* Bytes match (to shortest length), compare lengths */593594if (Length0 > Length1)595{596LocalResult = TRUE;597}598break;599600case AML_LOGICAL_LESS_OP: /* LLess (Operand0, Operand1) */601602if (Compare > 0)603{604goto Cleanup; /* FALSE */605}606if (Compare < 0)607{608LocalResult = TRUE;609goto Cleanup; /* TRUE */610}611612/* Bytes match (to shortest length), compare lengths */613614if (Length0 < Length1)615{616LocalResult = TRUE;617}618break;619620default:621622ACPI_ERROR ((AE_INFO,623"Invalid comparison opcode: %X", Opcode));624Status = AE_AML_INTERNAL;625break;626}627}628629Cleanup:630631/* New object was created if implicit conversion performed - delete */632633if (LocalOperand1 != Operand1)634{635AcpiUtRemoveReference (LocalOperand1);636}637638/* Return the logical result and status */639640*LogicalResult = LocalResult;641return_ACPI_STATUS (Status);642}643644645