1149703c7Sjruoho /****************************************************************************** 2149703c7Sjruoho * 3149703c7Sjruoho * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes 4149703c7Sjruoho * 5149703c7Sjruoho *****************************************************************************/ 6149703c7Sjruoho 768471b32Sjruoho /* 8*73d4e80bSchristos * Copyright (C) 2000 - 2013, Intel Corp. 9149703c7Sjruoho * All rights reserved. 10149703c7Sjruoho * 1168471b32Sjruoho * Redistribution and use in source and binary forms, with or without 1268471b32Sjruoho * modification, are permitted provided that the following conditions 1368471b32Sjruoho * are met: 1468471b32Sjruoho * 1. Redistributions of source code must retain the above copyright 1568471b32Sjruoho * notice, this list of conditions, and the following disclaimer, 1668471b32Sjruoho * without modification. 1768471b32Sjruoho * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1868471b32Sjruoho * substantially similar to the "NO WARRANTY" disclaimer below 1968471b32Sjruoho * ("Disclaimer") and any redistribution must be conditioned upon 2068471b32Sjruoho * including a substantially similar Disclaimer requirement for further 2168471b32Sjruoho * binary redistribution. 2268471b32Sjruoho * 3. Neither the names of the above-listed copyright holders nor the names 2368471b32Sjruoho * of any contributors may be used to endorse or promote products derived 2468471b32Sjruoho * from this software without specific prior written permission. 25149703c7Sjruoho * 2668471b32Sjruoho * Alternatively, this software may be distributed under the terms of the 2768471b32Sjruoho * GNU General Public License ("GPL") version 2 as published by the Free 2868471b32Sjruoho * Software Foundation. 29149703c7Sjruoho * 3068471b32Sjruoho * NO WARRANTY 3168471b32Sjruoho * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3268471b32Sjruoho * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3368471b32Sjruoho * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3468471b32Sjruoho * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3568471b32Sjruoho * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3668471b32Sjruoho * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3768471b32Sjruoho * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3868471b32Sjruoho * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3968471b32Sjruoho * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4068471b32Sjruoho * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4168471b32Sjruoho * POSSIBILITY OF SUCH DAMAGES. 4268471b32Sjruoho */ 43149703c7Sjruoho 44149703c7Sjruoho #define __EXMISC_C__ 45149703c7Sjruoho 46149703c7Sjruoho #include "acpi.h" 47149703c7Sjruoho #include "accommon.h" 48149703c7Sjruoho #include "acinterp.h" 49149703c7Sjruoho #include "amlcode.h" 50149703c7Sjruoho #include "amlresrc.h" 51149703c7Sjruoho 52149703c7Sjruoho 53149703c7Sjruoho #define _COMPONENT ACPI_EXECUTER 54149703c7Sjruoho ACPI_MODULE_NAME ("exmisc") 55149703c7Sjruoho 56149703c7Sjruoho 57149703c7Sjruoho /******************************************************************************* 58149703c7Sjruoho * 59149703c7Sjruoho * FUNCTION: AcpiExGetObjectReference 60149703c7Sjruoho * 61149703c7Sjruoho * PARAMETERS: ObjDesc - Create a reference to this object 62149703c7Sjruoho * ReturnDesc - Where to store the reference 63149703c7Sjruoho * WalkState - Current state 64149703c7Sjruoho * 65149703c7Sjruoho * RETURN: Status 66149703c7Sjruoho * 67149703c7Sjruoho * DESCRIPTION: Obtain and return a "reference" to the target object 68149703c7Sjruoho * Common code for the RefOfOp and the CondRefOfOp. 69149703c7Sjruoho * 70149703c7Sjruoho ******************************************************************************/ 71149703c7Sjruoho 72149703c7Sjruoho ACPI_STATUS 73149703c7Sjruoho AcpiExGetObjectReference ( 74149703c7Sjruoho ACPI_OPERAND_OBJECT *ObjDesc, 75149703c7Sjruoho ACPI_OPERAND_OBJECT **ReturnDesc, 76149703c7Sjruoho ACPI_WALK_STATE *WalkState) 77149703c7Sjruoho { 78149703c7Sjruoho ACPI_OPERAND_OBJECT *ReferenceObj; 79149703c7Sjruoho ACPI_OPERAND_OBJECT *ReferencedObj; 80149703c7Sjruoho 81149703c7Sjruoho 82149703c7Sjruoho ACPI_FUNCTION_TRACE_PTR (ExGetObjectReference, ObjDesc); 83149703c7Sjruoho 84149703c7Sjruoho 85149703c7Sjruoho *ReturnDesc = NULL; 86149703c7Sjruoho 87149703c7Sjruoho switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)) 88149703c7Sjruoho { 89149703c7Sjruoho case ACPI_DESC_TYPE_OPERAND: 90149703c7Sjruoho 91149703c7Sjruoho if (ObjDesc->Common.Type != ACPI_TYPE_LOCAL_REFERENCE) 92149703c7Sjruoho { 93149703c7Sjruoho return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 94149703c7Sjruoho } 95149703c7Sjruoho 96149703c7Sjruoho /* 97149703c7Sjruoho * Must be a reference to a Local or Arg 98149703c7Sjruoho */ 99149703c7Sjruoho switch (ObjDesc->Reference.Class) 100149703c7Sjruoho { 101149703c7Sjruoho case ACPI_REFCLASS_LOCAL: 102149703c7Sjruoho case ACPI_REFCLASS_ARG: 103149703c7Sjruoho case ACPI_REFCLASS_DEBUG: 104149703c7Sjruoho 105149703c7Sjruoho /* The referenced object is the pseudo-node for the local/arg */ 106149703c7Sjruoho 107149703c7Sjruoho ReferencedObj = ObjDesc->Reference.Object; 108149703c7Sjruoho break; 109149703c7Sjruoho 110149703c7Sjruoho default: 111149703c7Sjruoho 112149703c7Sjruoho ACPI_ERROR ((AE_INFO, "Unknown Reference Class 0x%2.2X", 113149703c7Sjruoho ObjDesc->Reference.Class)); 114149703c7Sjruoho return_ACPI_STATUS (AE_AML_INTERNAL); 115149703c7Sjruoho } 116149703c7Sjruoho break; 117149703c7Sjruoho 118149703c7Sjruoho case ACPI_DESC_TYPE_NAMED: 119149703c7Sjruoho /* 120149703c7Sjruoho * A named reference that has already been resolved to a Node 121149703c7Sjruoho */ 122149703c7Sjruoho ReferencedObj = ObjDesc; 123149703c7Sjruoho break; 124149703c7Sjruoho 125149703c7Sjruoho default: 126149703c7Sjruoho 127149703c7Sjruoho ACPI_ERROR ((AE_INFO, "Invalid descriptor type 0x%X", 128149703c7Sjruoho ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))); 129149703c7Sjruoho return_ACPI_STATUS (AE_TYPE); 130149703c7Sjruoho } 131149703c7Sjruoho 132149703c7Sjruoho 133149703c7Sjruoho /* Create a new reference object */ 134149703c7Sjruoho 135149703c7Sjruoho ReferenceObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); 136149703c7Sjruoho if (!ReferenceObj) 137149703c7Sjruoho { 138149703c7Sjruoho return_ACPI_STATUS (AE_NO_MEMORY); 139149703c7Sjruoho } 140149703c7Sjruoho 141149703c7Sjruoho ReferenceObj->Reference.Class = ACPI_REFCLASS_REFOF; 142149703c7Sjruoho ReferenceObj->Reference.Object = ReferencedObj; 143149703c7Sjruoho *ReturnDesc = ReferenceObj; 144149703c7Sjruoho 145149703c7Sjruoho ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 146149703c7Sjruoho "Object %p Type [%s], returning Reference %p\n", 147149703c7Sjruoho ObjDesc, AcpiUtGetObjectTypeName (ObjDesc), *ReturnDesc)); 148149703c7Sjruoho 149149703c7Sjruoho return_ACPI_STATUS (AE_OK); 150149703c7Sjruoho } 151149703c7Sjruoho 152149703c7Sjruoho 153149703c7Sjruoho /******************************************************************************* 154149703c7Sjruoho * 155149703c7Sjruoho * FUNCTION: AcpiExConcatTemplate 156149703c7Sjruoho * 157149703c7Sjruoho * PARAMETERS: Operand0 - First source object 158149703c7Sjruoho * Operand1 - Second source object 159149703c7Sjruoho * ActualReturnDesc - Where to place the return object 160149703c7Sjruoho * WalkState - Current walk state 161149703c7Sjruoho * 162149703c7Sjruoho * RETURN: Status 163149703c7Sjruoho * 164149703c7Sjruoho * DESCRIPTION: Concatenate two resource templates 165149703c7Sjruoho * 166149703c7Sjruoho ******************************************************************************/ 167149703c7Sjruoho 168149703c7Sjruoho ACPI_STATUS 169149703c7Sjruoho AcpiExConcatTemplate ( 170149703c7Sjruoho ACPI_OPERAND_OBJECT *Operand0, 171149703c7Sjruoho ACPI_OPERAND_OBJECT *Operand1, 172149703c7Sjruoho ACPI_OPERAND_OBJECT **ActualReturnDesc, 173149703c7Sjruoho ACPI_WALK_STATE *WalkState) 174149703c7Sjruoho { 175149703c7Sjruoho ACPI_STATUS Status; 176149703c7Sjruoho ACPI_OPERAND_OBJECT *ReturnDesc; 177149703c7Sjruoho UINT8 *NewBuf; 178149703c7Sjruoho UINT8 *EndTag; 179149703c7Sjruoho ACPI_SIZE Length0; 180149703c7Sjruoho ACPI_SIZE Length1; 181149703c7Sjruoho ACPI_SIZE NewLength; 182149703c7Sjruoho 183149703c7Sjruoho 184149703c7Sjruoho ACPI_FUNCTION_TRACE (ExConcatTemplate); 185149703c7Sjruoho 186149703c7Sjruoho 187149703c7Sjruoho /* 188149703c7Sjruoho * Find the EndTag descriptor in each resource template. 189149703c7Sjruoho * Note1: returned pointers point TO the EndTag, not past it. 190149703c7Sjruoho * Note2: zero-length buffers are allowed; treated like one EndTag 191149703c7Sjruoho */ 192149703c7Sjruoho 193149703c7Sjruoho /* Get the length of the first resource template */ 194149703c7Sjruoho 195149703c7Sjruoho Status = AcpiUtGetResourceEndTag (Operand0, &EndTag); 196149703c7Sjruoho if (ACPI_FAILURE (Status)) 197149703c7Sjruoho { 198149703c7Sjruoho return_ACPI_STATUS (Status); 199149703c7Sjruoho } 200149703c7Sjruoho 201149703c7Sjruoho Length0 = ACPI_PTR_DIFF (EndTag, Operand0->Buffer.Pointer); 202149703c7Sjruoho 203149703c7Sjruoho /* Get the length of the second resource template */ 204149703c7Sjruoho 205149703c7Sjruoho Status = AcpiUtGetResourceEndTag (Operand1, &EndTag); 206149703c7Sjruoho if (ACPI_FAILURE (Status)) 207149703c7Sjruoho { 208149703c7Sjruoho return_ACPI_STATUS (Status); 209149703c7Sjruoho } 210149703c7Sjruoho 211149703c7Sjruoho Length1 = ACPI_PTR_DIFF (EndTag, Operand1->Buffer.Pointer); 212149703c7Sjruoho 213149703c7Sjruoho /* Combine both lengths, minimum size will be 2 for EndTag */ 214149703c7Sjruoho 215149703c7Sjruoho NewLength = Length0 + Length1 + sizeof (AML_RESOURCE_END_TAG); 216149703c7Sjruoho 217149703c7Sjruoho /* Create a new buffer object for the result (with one EndTag) */ 218149703c7Sjruoho 219149703c7Sjruoho ReturnDesc = AcpiUtCreateBufferObject (NewLength); 220149703c7Sjruoho if (!ReturnDesc) 221149703c7Sjruoho { 222149703c7Sjruoho return_ACPI_STATUS (AE_NO_MEMORY); 223149703c7Sjruoho } 224149703c7Sjruoho 225149703c7Sjruoho /* 226149703c7Sjruoho * Copy the templates to the new buffer, 0 first, then 1 follows. One 227149703c7Sjruoho * EndTag descriptor is copied from Operand1. 228149703c7Sjruoho */ 229149703c7Sjruoho NewBuf = ReturnDesc->Buffer.Pointer; 230149703c7Sjruoho ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, Length0); 231149703c7Sjruoho ACPI_MEMCPY (NewBuf + Length0, Operand1->Buffer.Pointer, Length1); 232149703c7Sjruoho 233149703c7Sjruoho /* Insert EndTag and set the checksum to zero, means "ignore checksum" */ 234149703c7Sjruoho 235149703c7Sjruoho NewBuf[NewLength - 1] = 0; 236149703c7Sjruoho NewBuf[NewLength - 2] = ACPI_RESOURCE_NAME_END_TAG | 1; 237149703c7Sjruoho 238149703c7Sjruoho /* Return the completed resource template */ 239149703c7Sjruoho 240149703c7Sjruoho *ActualReturnDesc = ReturnDesc; 241149703c7Sjruoho return_ACPI_STATUS (AE_OK); 242149703c7Sjruoho } 243149703c7Sjruoho 244149703c7Sjruoho 245149703c7Sjruoho /******************************************************************************* 246149703c7Sjruoho * 247149703c7Sjruoho * FUNCTION: AcpiExDoConcatenate 248149703c7Sjruoho * 249149703c7Sjruoho * PARAMETERS: Operand0 - First source object 250149703c7Sjruoho * Operand1 - Second source object 251149703c7Sjruoho * ActualReturnDesc - Where to place the return object 252149703c7Sjruoho * WalkState - Current walk state 253149703c7Sjruoho * 254149703c7Sjruoho * RETURN: Status 255149703c7Sjruoho * 256149703c7Sjruoho * DESCRIPTION: Concatenate two objects OF THE SAME TYPE. 257149703c7Sjruoho * 258149703c7Sjruoho ******************************************************************************/ 259149703c7Sjruoho 260149703c7Sjruoho ACPI_STATUS 261149703c7Sjruoho AcpiExDoConcatenate ( 262149703c7Sjruoho ACPI_OPERAND_OBJECT *Operand0, 263149703c7Sjruoho ACPI_OPERAND_OBJECT *Operand1, 264149703c7Sjruoho ACPI_OPERAND_OBJECT **ActualReturnDesc, 265149703c7Sjruoho ACPI_WALK_STATE *WalkState) 266149703c7Sjruoho { 267149703c7Sjruoho ACPI_OPERAND_OBJECT *LocalOperand1 = Operand1; 268149703c7Sjruoho ACPI_OPERAND_OBJECT *ReturnDesc; 269149703c7Sjruoho char *NewBuf; 270149703c7Sjruoho ACPI_STATUS Status; 271149703c7Sjruoho 272149703c7Sjruoho 273149703c7Sjruoho ACPI_FUNCTION_TRACE (ExDoConcatenate); 274149703c7Sjruoho 275149703c7Sjruoho 276149703c7Sjruoho /* 277149703c7Sjruoho * Convert the second operand if necessary. The first operand 278149703c7Sjruoho * determines the type of the second operand, (See the Data Types 279149703c7Sjruoho * section of the ACPI specification.) Both object types are 280149703c7Sjruoho * guaranteed to be either Integer/String/Buffer by the operand 281149703c7Sjruoho * resolution mechanism. 282149703c7Sjruoho */ 283149703c7Sjruoho switch (Operand0->Common.Type) 284149703c7Sjruoho { 285149703c7Sjruoho case ACPI_TYPE_INTEGER: 286*73d4e80bSchristos 287149703c7Sjruoho Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16); 288149703c7Sjruoho break; 289149703c7Sjruoho 290149703c7Sjruoho case ACPI_TYPE_STRING: 291*73d4e80bSchristos 292149703c7Sjruoho Status = AcpiExConvertToString (Operand1, &LocalOperand1, 293149703c7Sjruoho ACPI_IMPLICIT_CONVERT_HEX); 294149703c7Sjruoho break; 295149703c7Sjruoho 296149703c7Sjruoho case ACPI_TYPE_BUFFER: 297*73d4e80bSchristos 298149703c7Sjruoho Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1); 299149703c7Sjruoho break; 300149703c7Sjruoho 301149703c7Sjruoho default: 302*73d4e80bSchristos 303149703c7Sjruoho ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X", 304149703c7Sjruoho Operand0->Common.Type)); 305149703c7Sjruoho Status = AE_AML_INTERNAL; 306149703c7Sjruoho } 307149703c7Sjruoho 308149703c7Sjruoho if (ACPI_FAILURE (Status)) 309149703c7Sjruoho { 310149703c7Sjruoho goto Cleanup; 311149703c7Sjruoho } 312149703c7Sjruoho 313149703c7Sjruoho /* 314149703c7Sjruoho * Both operands are now known to be the same object type 315149703c7Sjruoho * (Both are Integer, String, or Buffer), and we can now perform the 316149703c7Sjruoho * concatenation. 317149703c7Sjruoho */ 318149703c7Sjruoho 319149703c7Sjruoho /* 320149703c7Sjruoho * There are three cases to handle: 321149703c7Sjruoho * 322149703c7Sjruoho * 1) Two Integers concatenated to produce a new Buffer 323149703c7Sjruoho * 2) Two Strings concatenated to produce a new String 324149703c7Sjruoho * 3) Two Buffers concatenated to produce a new Buffer 325149703c7Sjruoho */ 326149703c7Sjruoho switch (Operand0->Common.Type) 327149703c7Sjruoho { 328149703c7Sjruoho case ACPI_TYPE_INTEGER: 329149703c7Sjruoho 330149703c7Sjruoho /* Result of two Integers is a Buffer */ 331149703c7Sjruoho /* Need enough buffer space for two integers */ 332149703c7Sjruoho 333149703c7Sjruoho ReturnDesc = AcpiUtCreateBufferObject ((ACPI_SIZE) 334149703c7Sjruoho ACPI_MUL_2 (AcpiGbl_IntegerByteWidth)); 335149703c7Sjruoho if (!ReturnDesc) 336149703c7Sjruoho { 337149703c7Sjruoho Status = AE_NO_MEMORY; 338149703c7Sjruoho goto Cleanup; 339149703c7Sjruoho } 340149703c7Sjruoho 341149703c7Sjruoho NewBuf = (char *) ReturnDesc->Buffer.Pointer; 342149703c7Sjruoho 343149703c7Sjruoho /* Copy the first integer, LSB first */ 344149703c7Sjruoho 345149703c7Sjruoho ACPI_MEMCPY (NewBuf, &Operand0->Integer.Value, 346149703c7Sjruoho AcpiGbl_IntegerByteWidth); 347149703c7Sjruoho 348149703c7Sjruoho /* Copy the second integer (LSB first) after the first */ 349149703c7Sjruoho 350149703c7Sjruoho ACPI_MEMCPY (NewBuf + AcpiGbl_IntegerByteWidth, 351149703c7Sjruoho &LocalOperand1->Integer.Value, 352149703c7Sjruoho AcpiGbl_IntegerByteWidth); 353149703c7Sjruoho break; 354149703c7Sjruoho 355149703c7Sjruoho case ACPI_TYPE_STRING: 356149703c7Sjruoho 357149703c7Sjruoho /* Result of two Strings is a String */ 358149703c7Sjruoho 359149703c7Sjruoho ReturnDesc = AcpiUtCreateStringObject ( 360149703c7Sjruoho ((ACPI_SIZE) Operand0->String.Length + 361149703c7Sjruoho LocalOperand1->String.Length)); 362149703c7Sjruoho if (!ReturnDesc) 363149703c7Sjruoho { 364149703c7Sjruoho Status = AE_NO_MEMORY; 365149703c7Sjruoho goto Cleanup; 366149703c7Sjruoho } 367149703c7Sjruoho 368149703c7Sjruoho NewBuf = ReturnDesc->String.Pointer; 369149703c7Sjruoho 370149703c7Sjruoho /* Concatenate the strings */ 371149703c7Sjruoho 372149703c7Sjruoho ACPI_STRCPY (NewBuf, Operand0->String.Pointer); 373149703c7Sjruoho ACPI_STRCPY (NewBuf + Operand0->String.Length, 374149703c7Sjruoho LocalOperand1->String.Pointer); 375149703c7Sjruoho break; 376149703c7Sjruoho 377149703c7Sjruoho case ACPI_TYPE_BUFFER: 378149703c7Sjruoho 379149703c7Sjruoho /* Result of two Buffers is a Buffer */ 380149703c7Sjruoho 381149703c7Sjruoho ReturnDesc = AcpiUtCreateBufferObject ( 382149703c7Sjruoho ((ACPI_SIZE) Operand0->Buffer.Length + 383149703c7Sjruoho LocalOperand1->Buffer.Length)); 384149703c7Sjruoho if (!ReturnDesc) 385149703c7Sjruoho { 386149703c7Sjruoho Status = AE_NO_MEMORY; 387149703c7Sjruoho goto Cleanup; 388149703c7Sjruoho } 389149703c7Sjruoho 390149703c7Sjruoho NewBuf = (char *) ReturnDesc->Buffer.Pointer; 391149703c7Sjruoho 392149703c7Sjruoho /* Concatenate the buffers */ 393149703c7Sjruoho 394149703c7Sjruoho ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, 395149703c7Sjruoho Operand0->Buffer.Length); 396149703c7Sjruoho ACPI_MEMCPY (NewBuf + Operand0->Buffer.Length, 397149703c7Sjruoho LocalOperand1->Buffer.Pointer, 398149703c7Sjruoho LocalOperand1->Buffer.Length); 399149703c7Sjruoho break; 400149703c7Sjruoho 401149703c7Sjruoho default: 402149703c7Sjruoho 403149703c7Sjruoho /* Invalid object type, should not happen here */ 404149703c7Sjruoho 405149703c7Sjruoho ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X", 406149703c7Sjruoho Operand0->Common.Type)); 407149703c7Sjruoho Status =AE_AML_INTERNAL; 408149703c7Sjruoho goto Cleanup; 409149703c7Sjruoho } 410149703c7Sjruoho 411149703c7Sjruoho *ActualReturnDesc = ReturnDesc; 412149703c7Sjruoho 413149703c7Sjruoho Cleanup: 414149703c7Sjruoho if (LocalOperand1 != Operand1) 415149703c7Sjruoho { 416149703c7Sjruoho AcpiUtRemoveReference (LocalOperand1); 417149703c7Sjruoho } 418149703c7Sjruoho return_ACPI_STATUS (Status); 419149703c7Sjruoho } 420149703c7Sjruoho 421149703c7Sjruoho 422149703c7Sjruoho /******************************************************************************* 423149703c7Sjruoho * 424149703c7Sjruoho * FUNCTION: AcpiExDoMathOp 425149703c7Sjruoho * 426149703c7Sjruoho * PARAMETERS: Opcode - AML opcode 427149703c7Sjruoho * Integer0 - Integer operand #0 428149703c7Sjruoho * Integer1 - Integer operand #1 429149703c7Sjruoho * 430149703c7Sjruoho * RETURN: Integer result of the operation 431149703c7Sjruoho * 432149703c7Sjruoho * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the 433149703c7Sjruoho * math functions here is to prevent a lot of pointer dereferencing 434149703c7Sjruoho * to obtain the operands. 435149703c7Sjruoho * 436149703c7Sjruoho ******************************************************************************/ 437149703c7Sjruoho 438149703c7Sjruoho UINT64 439149703c7Sjruoho AcpiExDoMathOp ( 440149703c7Sjruoho UINT16 Opcode, 441149703c7Sjruoho UINT64 Integer0, 442149703c7Sjruoho UINT64 Integer1) 443149703c7Sjruoho { 444149703c7Sjruoho 445149703c7Sjruoho ACPI_FUNCTION_ENTRY (); 446149703c7Sjruoho 447149703c7Sjruoho 448149703c7Sjruoho switch (Opcode) 449149703c7Sjruoho { 450149703c7Sjruoho case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */ 451149703c7Sjruoho 452149703c7Sjruoho return (Integer0 + Integer1); 453149703c7Sjruoho 454149703c7Sjruoho case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */ 455149703c7Sjruoho 456149703c7Sjruoho return (Integer0 & Integer1); 457149703c7Sjruoho 458149703c7Sjruoho case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */ 459149703c7Sjruoho 460149703c7Sjruoho return (~(Integer0 & Integer1)); 461149703c7Sjruoho 462149703c7Sjruoho case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */ 463149703c7Sjruoho 464149703c7Sjruoho return (Integer0 | Integer1); 465149703c7Sjruoho 466149703c7Sjruoho case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */ 467149703c7Sjruoho 468149703c7Sjruoho return (~(Integer0 | Integer1)); 469149703c7Sjruoho 470149703c7Sjruoho case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */ 471149703c7Sjruoho 472149703c7Sjruoho return (Integer0 ^ Integer1); 473149703c7Sjruoho 474149703c7Sjruoho case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */ 475149703c7Sjruoho 476149703c7Sjruoho return (Integer0 * Integer1); 477149703c7Sjruoho 478149703c7Sjruoho case AML_SHIFT_LEFT_OP: /* ShiftLeft (Operand, ShiftCount, Result)*/ 479149703c7Sjruoho 480149703c7Sjruoho /* 481149703c7Sjruoho * We need to check if the shiftcount is larger than the integer bit 482149703c7Sjruoho * width since the behavior of this is not well-defined in the C language. 483149703c7Sjruoho */ 484149703c7Sjruoho if (Integer1 >= AcpiGbl_IntegerBitWidth) 485149703c7Sjruoho { 486149703c7Sjruoho return (0); 487149703c7Sjruoho } 488149703c7Sjruoho return (Integer0 << Integer1); 489149703c7Sjruoho 490149703c7Sjruoho case AML_SHIFT_RIGHT_OP: /* ShiftRight (Operand, ShiftCount, Result) */ 491149703c7Sjruoho 492149703c7Sjruoho /* 493149703c7Sjruoho * We need to check if the shiftcount is larger than the integer bit 494149703c7Sjruoho * width since the behavior of this is not well-defined in the C language. 495149703c7Sjruoho */ 496149703c7Sjruoho if (Integer1 >= AcpiGbl_IntegerBitWidth) 497149703c7Sjruoho { 498149703c7Sjruoho return (0); 499149703c7Sjruoho } 500149703c7Sjruoho return (Integer0 >> Integer1); 501149703c7Sjruoho 502149703c7Sjruoho case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */ 503149703c7Sjruoho 504149703c7Sjruoho return (Integer0 - Integer1); 505149703c7Sjruoho 506149703c7Sjruoho default: 507149703c7Sjruoho 508149703c7Sjruoho return (0); 509149703c7Sjruoho } 510149703c7Sjruoho } 511149703c7Sjruoho 512149703c7Sjruoho 513149703c7Sjruoho /******************************************************************************* 514149703c7Sjruoho * 515149703c7Sjruoho * FUNCTION: AcpiExDoLogicalNumericOp 516149703c7Sjruoho * 517149703c7Sjruoho * PARAMETERS: Opcode - AML opcode 518149703c7Sjruoho * Integer0 - Integer operand #0 519149703c7Sjruoho * Integer1 - Integer operand #1 520149703c7Sjruoho * LogicalResult - TRUE/FALSE result of the operation 521149703c7Sjruoho * 522149703c7Sjruoho * RETURN: Status 523149703c7Sjruoho * 524149703c7Sjruoho * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric 525149703c7Sjruoho * operators (LAnd and LOr), both operands must be integers. 526149703c7Sjruoho * 527149703c7Sjruoho * Note: cleanest machine code seems to be produced by the code 528149703c7Sjruoho * below, rather than using statements of the form: 529149703c7Sjruoho * Result = (Integer0 && Integer1); 530149703c7Sjruoho * 531149703c7Sjruoho ******************************************************************************/ 532149703c7Sjruoho 533149703c7Sjruoho ACPI_STATUS 534149703c7Sjruoho AcpiExDoLogicalNumericOp ( 535149703c7Sjruoho UINT16 Opcode, 536149703c7Sjruoho UINT64 Integer0, 537149703c7Sjruoho UINT64 Integer1, 538149703c7Sjruoho BOOLEAN *LogicalResult) 539149703c7Sjruoho { 540149703c7Sjruoho ACPI_STATUS Status = AE_OK; 541149703c7Sjruoho BOOLEAN LocalResult = FALSE; 542149703c7Sjruoho 543149703c7Sjruoho 544149703c7Sjruoho ACPI_FUNCTION_TRACE (ExDoLogicalNumericOp); 545149703c7Sjruoho 546149703c7Sjruoho 547149703c7Sjruoho switch (Opcode) 548149703c7Sjruoho { 549149703c7Sjruoho case AML_LAND_OP: /* LAnd (Integer0, Integer1) */ 550149703c7Sjruoho 551149703c7Sjruoho if (Integer0 && Integer1) 552149703c7Sjruoho { 553149703c7Sjruoho LocalResult = TRUE; 554149703c7Sjruoho } 555149703c7Sjruoho break; 556149703c7Sjruoho 557149703c7Sjruoho case AML_LOR_OP: /* LOr (Integer0, Integer1) */ 558149703c7Sjruoho 559149703c7Sjruoho if (Integer0 || Integer1) 560149703c7Sjruoho { 561149703c7Sjruoho LocalResult = TRUE; 562149703c7Sjruoho } 563149703c7Sjruoho break; 564149703c7Sjruoho 565149703c7Sjruoho default: 566*73d4e80bSchristos 567149703c7Sjruoho Status = AE_AML_INTERNAL; 568149703c7Sjruoho break; 569149703c7Sjruoho } 570149703c7Sjruoho 571149703c7Sjruoho /* Return the logical result and status */ 572149703c7Sjruoho 573149703c7Sjruoho *LogicalResult = LocalResult; 574149703c7Sjruoho return_ACPI_STATUS (Status); 575149703c7Sjruoho } 576149703c7Sjruoho 577149703c7Sjruoho 578149703c7Sjruoho /******************************************************************************* 579149703c7Sjruoho * 580149703c7Sjruoho * FUNCTION: AcpiExDoLogicalOp 581149703c7Sjruoho * 582149703c7Sjruoho * PARAMETERS: Opcode - AML opcode 583149703c7Sjruoho * Operand0 - operand #0 584149703c7Sjruoho * Operand1 - operand #1 585149703c7Sjruoho * LogicalResult - TRUE/FALSE result of the operation 586149703c7Sjruoho * 587149703c7Sjruoho * RETURN: Status 588149703c7Sjruoho * 589149703c7Sjruoho * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the 590149703c7Sjruoho * functions here is to prevent a lot of pointer dereferencing 591149703c7Sjruoho * to obtain the operands and to simplify the generation of the 592149703c7Sjruoho * logical value. For the Numeric operators (LAnd and LOr), both 593149703c7Sjruoho * operands must be integers. For the other logical operators, 594149703c7Sjruoho * operands can be any combination of Integer/String/Buffer. The 595149703c7Sjruoho * first operand determines the type to which the second operand 596149703c7Sjruoho * will be converted. 597149703c7Sjruoho * 598149703c7Sjruoho * Note: cleanest machine code seems to be produced by the code 599149703c7Sjruoho * below, rather than using statements of the form: 600149703c7Sjruoho * Result = (Operand0 == Operand1); 601149703c7Sjruoho * 602149703c7Sjruoho ******************************************************************************/ 603149703c7Sjruoho 604149703c7Sjruoho ACPI_STATUS 605149703c7Sjruoho AcpiExDoLogicalOp ( 606149703c7Sjruoho UINT16 Opcode, 607149703c7Sjruoho ACPI_OPERAND_OBJECT *Operand0, 608149703c7Sjruoho ACPI_OPERAND_OBJECT *Operand1, 609149703c7Sjruoho BOOLEAN *LogicalResult) 610149703c7Sjruoho { 611149703c7Sjruoho ACPI_OPERAND_OBJECT *LocalOperand1 = Operand1; 612149703c7Sjruoho UINT64 Integer0; 613149703c7Sjruoho UINT64 Integer1; 614149703c7Sjruoho UINT32 Length0; 615149703c7Sjruoho UINT32 Length1; 616149703c7Sjruoho ACPI_STATUS Status = AE_OK; 617149703c7Sjruoho BOOLEAN LocalResult = FALSE; 618149703c7Sjruoho int Compare; 619149703c7Sjruoho 620149703c7Sjruoho 621149703c7Sjruoho ACPI_FUNCTION_TRACE (ExDoLogicalOp); 622149703c7Sjruoho 623149703c7Sjruoho 624149703c7Sjruoho /* 625149703c7Sjruoho * Convert the second operand if necessary. The first operand 626149703c7Sjruoho * determines the type of the second operand, (See the Data Types 627149703c7Sjruoho * section of the ACPI 3.0+ specification.) Both object types are 628149703c7Sjruoho * guaranteed to be either Integer/String/Buffer by the operand 629149703c7Sjruoho * resolution mechanism. 630149703c7Sjruoho */ 631149703c7Sjruoho switch (Operand0->Common.Type) 632149703c7Sjruoho { 633149703c7Sjruoho case ACPI_TYPE_INTEGER: 634*73d4e80bSchristos 635149703c7Sjruoho Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16); 636149703c7Sjruoho break; 637149703c7Sjruoho 638149703c7Sjruoho case ACPI_TYPE_STRING: 639*73d4e80bSchristos 640149703c7Sjruoho Status = AcpiExConvertToString (Operand1, &LocalOperand1, 641149703c7Sjruoho ACPI_IMPLICIT_CONVERT_HEX); 642149703c7Sjruoho break; 643149703c7Sjruoho 644149703c7Sjruoho case ACPI_TYPE_BUFFER: 645*73d4e80bSchristos 646149703c7Sjruoho Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1); 647149703c7Sjruoho break; 648149703c7Sjruoho 649149703c7Sjruoho default: 650*73d4e80bSchristos 651149703c7Sjruoho Status = AE_AML_INTERNAL; 652149703c7Sjruoho break; 653149703c7Sjruoho } 654149703c7Sjruoho 655149703c7Sjruoho if (ACPI_FAILURE (Status)) 656149703c7Sjruoho { 657149703c7Sjruoho goto Cleanup; 658149703c7Sjruoho } 659149703c7Sjruoho 660149703c7Sjruoho /* 661149703c7Sjruoho * Two cases: 1) Both Integers, 2) Both Strings or Buffers 662149703c7Sjruoho */ 663149703c7Sjruoho if (Operand0->Common.Type == ACPI_TYPE_INTEGER) 664149703c7Sjruoho { 665149703c7Sjruoho /* 666149703c7Sjruoho * 1) Both operands are of type integer 667149703c7Sjruoho * Note: LocalOperand1 may have changed above 668149703c7Sjruoho */ 669149703c7Sjruoho Integer0 = Operand0->Integer.Value; 670149703c7Sjruoho Integer1 = LocalOperand1->Integer.Value; 671149703c7Sjruoho 672149703c7Sjruoho switch (Opcode) 673149703c7Sjruoho { 674149703c7Sjruoho case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ 675149703c7Sjruoho 676149703c7Sjruoho if (Integer0 == Integer1) 677149703c7Sjruoho { 678149703c7Sjruoho LocalResult = TRUE; 679149703c7Sjruoho } 680149703c7Sjruoho break; 681149703c7Sjruoho 682149703c7Sjruoho case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ 683149703c7Sjruoho 684149703c7Sjruoho if (Integer0 > Integer1) 685149703c7Sjruoho { 686149703c7Sjruoho LocalResult = TRUE; 687149703c7Sjruoho } 688149703c7Sjruoho break; 689149703c7Sjruoho 690149703c7Sjruoho case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ 691149703c7Sjruoho 692149703c7Sjruoho if (Integer0 < Integer1) 693149703c7Sjruoho { 694149703c7Sjruoho LocalResult = TRUE; 695149703c7Sjruoho } 696149703c7Sjruoho break; 697149703c7Sjruoho 698149703c7Sjruoho default: 699*73d4e80bSchristos 700149703c7Sjruoho Status = AE_AML_INTERNAL; 701149703c7Sjruoho break; 702149703c7Sjruoho } 703149703c7Sjruoho } 704149703c7Sjruoho else 705149703c7Sjruoho { 706149703c7Sjruoho /* 707149703c7Sjruoho * 2) Both operands are Strings or both are Buffers 708149703c7Sjruoho * Note: Code below takes advantage of common Buffer/String 709149703c7Sjruoho * object fields. LocalOperand1 may have changed above. Use 710149703c7Sjruoho * memcmp to handle nulls in buffers. 711149703c7Sjruoho */ 712149703c7Sjruoho Length0 = Operand0->Buffer.Length; 713149703c7Sjruoho Length1 = LocalOperand1->Buffer.Length; 714149703c7Sjruoho 715149703c7Sjruoho /* Lexicographic compare: compare the data bytes */ 716149703c7Sjruoho 717149703c7Sjruoho Compare = ACPI_MEMCMP (Operand0->Buffer.Pointer, 718149703c7Sjruoho LocalOperand1->Buffer.Pointer, 719149703c7Sjruoho (Length0 > Length1) ? Length1 : Length0); 720149703c7Sjruoho 721149703c7Sjruoho switch (Opcode) 722149703c7Sjruoho { 723149703c7Sjruoho case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ 724149703c7Sjruoho 725149703c7Sjruoho /* Length and all bytes must be equal */ 726149703c7Sjruoho 727149703c7Sjruoho if ((Length0 == Length1) && 728149703c7Sjruoho (Compare == 0)) 729149703c7Sjruoho { 730149703c7Sjruoho /* Length and all bytes match ==> TRUE */ 731149703c7Sjruoho 732149703c7Sjruoho LocalResult = TRUE; 733149703c7Sjruoho } 734149703c7Sjruoho break; 735149703c7Sjruoho 736149703c7Sjruoho case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ 737149703c7Sjruoho 738149703c7Sjruoho if (Compare > 0) 739149703c7Sjruoho { 740149703c7Sjruoho LocalResult = TRUE; 741149703c7Sjruoho goto Cleanup; /* TRUE */ 742149703c7Sjruoho } 743149703c7Sjruoho if (Compare < 0) 744149703c7Sjruoho { 745149703c7Sjruoho goto Cleanup; /* FALSE */ 746149703c7Sjruoho } 747149703c7Sjruoho 748149703c7Sjruoho /* Bytes match (to shortest length), compare lengths */ 749149703c7Sjruoho 750149703c7Sjruoho if (Length0 > Length1) 751149703c7Sjruoho { 752149703c7Sjruoho LocalResult = TRUE; 753149703c7Sjruoho } 754149703c7Sjruoho break; 755149703c7Sjruoho 756149703c7Sjruoho case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ 757149703c7Sjruoho 758149703c7Sjruoho if (Compare > 0) 759149703c7Sjruoho { 760149703c7Sjruoho goto Cleanup; /* FALSE */ 761149703c7Sjruoho } 762149703c7Sjruoho if (Compare < 0) 763149703c7Sjruoho { 764149703c7Sjruoho LocalResult = TRUE; 765149703c7Sjruoho goto Cleanup; /* TRUE */ 766149703c7Sjruoho } 767149703c7Sjruoho 768149703c7Sjruoho /* Bytes match (to shortest length), compare lengths */ 769149703c7Sjruoho 770149703c7Sjruoho if (Length0 < Length1) 771149703c7Sjruoho { 772149703c7Sjruoho LocalResult = TRUE; 773149703c7Sjruoho } 774149703c7Sjruoho break; 775149703c7Sjruoho 776149703c7Sjruoho default: 777*73d4e80bSchristos 778149703c7Sjruoho Status = AE_AML_INTERNAL; 779149703c7Sjruoho break; 780149703c7Sjruoho } 781149703c7Sjruoho } 782149703c7Sjruoho 783149703c7Sjruoho Cleanup: 784149703c7Sjruoho 785149703c7Sjruoho /* New object was created if implicit conversion performed - delete */ 786149703c7Sjruoho 787149703c7Sjruoho if (LocalOperand1 != Operand1) 788149703c7Sjruoho { 789149703c7Sjruoho AcpiUtRemoveReference (LocalOperand1); 790149703c7Sjruoho } 791149703c7Sjruoho 792149703c7Sjruoho /* Return the logical result and status */ 793149703c7Sjruoho 794149703c7Sjruoho *LogicalResult = LocalResult; 795149703c7Sjruoho return_ACPI_STATUS (Status); 796149703c7Sjruoho } 797