1db2bae30SDana Myers /****************************************************************************** 2db2bae30SDana Myers * 3db2bae30SDana Myers * Module Name: exoparg3 - AML execution - opcodes with 3 arguments 4db2bae30SDana Myers * 5db2bae30SDana Myers *****************************************************************************/ 6db2bae30SDana Myers 726f3cdf0SGordon Ross /* 8*385cc6b4SJerry Jelinek * Copyright (C) 2000 - 2016, Intel Corp. 9db2bae30SDana Myers * All rights reserved. 10db2bae30SDana Myers * 1126f3cdf0SGordon Ross * Redistribution and use in source and binary forms, with or without 1226f3cdf0SGordon Ross * modification, are permitted provided that the following conditions 1326f3cdf0SGordon Ross * are met: 1426f3cdf0SGordon Ross * 1. Redistributions of source code must retain the above copyright 1526f3cdf0SGordon Ross * notice, this list of conditions, and the following disclaimer, 1626f3cdf0SGordon Ross * without modification. 1726f3cdf0SGordon Ross * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1826f3cdf0SGordon Ross * substantially similar to the "NO WARRANTY" disclaimer below 1926f3cdf0SGordon Ross * ("Disclaimer") and any redistribution must be conditioned upon 2026f3cdf0SGordon Ross * including a substantially similar Disclaimer requirement for further 2126f3cdf0SGordon Ross * binary redistribution. 2226f3cdf0SGordon Ross * 3. Neither the names of the above-listed copyright holders nor the names 2326f3cdf0SGordon Ross * of any contributors may be used to endorse or promote products derived 2426f3cdf0SGordon Ross * from this software without specific prior written permission. 25db2bae30SDana Myers * 2626f3cdf0SGordon Ross * Alternatively, this software may be distributed under the terms of the 2726f3cdf0SGordon Ross * GNU General Public License ("GPL") version 2 as published by the Free 2826f3cdf0SGordon Ross * Software Foundation. 29db2bae30SDana Myers * 3026f3cdf0SGordon Ross * NO WARRANTY 3126f3cdf0SGordon Ross * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3226f3cdf0SGordon Ross * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3326f3cdf0SGordon Ross * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3426f3cdf0SGordon Ross * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3526f3cdf0SGordon Ross * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3626f3cdf0SGordon Ross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3726f3cdf0SGordon Ross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3826f3cdf0SGordon Ross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3926f3cdf0SGordon Ross * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4026f3cdf0SGordon Ross * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4126f3cdf0SGordon Ross * POSSIBILITY OF SUCH DAMAGES. 4226f3cdf0SGordon Ross */ 43db2bae30SDana Myers 44db2bae30SDana Myers #include "acpi.h" 45aa2aa9a6SDana Myers #include "accommon.h" 46db2bae30SDana Myers #include "acinterp.h" 47db2bae30SDana Myers #include "acparser.h" 48db2bae30SDana Myers #include "amlcode.h" 49db2bae30SDana Myers 50db2bae30SDana Myers 51db2bae30SDana Myers #define _COMPONENT ACPI_EXECUTER 52db2bae30SDana Myers ACPI_MODULE_NAME ("exoparg3") 53db2bae30SDana Myers 54db2bae30SDana Myers 55db2bae30SDana Myers /*! 56db2bae30SDana Myers * Naming convention for AML interpreter execution routines. 57db2bae30SDana Myers * 58db2bae30SDana Myers * The routines that begin execution of AML opcodes are named with a common 59db2bae30SDana Myers * convention based upon the number of arguments, the number of target operands, 60db2bae30SDana Myers * and whether or not a value is returned: 61db2bae30SDana Myers * 62db2bae30SDana Myers * AcpiExOpcode_xA_yT_zR 63db2bae30SDana Myers * 64db2bae30SDana Myers * Where: 65db2bae30SDana Myers * 66db2bae30SDana Myers * xA - ARGUMENTS: The number of arguments (input operands) that are 67db2bae30SDana Myers * required for this opcode type (1 through 6 args). 68db2bae30SDana Myers * yT - TARGETS: The number of targets (output operands) that are required 69db2bae30SDana Myers * for this opcode type (0, 1, or 2 targets). 70db2bae30SDana Myers * zR - RETURN VALUE: Indicates whether this opcode type returns a value 71db2bae30SDana Myers * as the function return (0 or 1). 72db2bae30SDana Myers * 73db2bae30SDana Myers * The AcpiExOpcode* functions are called via the Dispatcher component with 74db2bae30SDana Myers * fully resolved operands. 75db2bae30SDana Myers !*/ 76db2bae30SDana Myers 77db2bae30SDana Myers 78db2bae30SDana Myers /******************************************************************************* 79db2bae30SDana Myers * 80db2bae30SDana Myers * FUNCTION: AcpiExOpcode_3A_0T_0R 81db2bae30SDana Myers * 82db2bae30SDana Myers * PARAMETERS: WalkState - Current walk state 83db2bae30SDana Myers * 84db2bae30SDana Myers * RETURN: Status 85db2bae30SDana Myers * 86db2bae30SDana Myers * DESCRIPTION: Execute Triadic operator (3 operands) 87db2bae30SDana Myers * 88db2bae30SDana Myers ******************************************************************************/ 89db2bae30SDana Myers 90db2bae30SDana Myers ACPI_STATUS 91db2bae30SDana Myers AcpiExOpcode_3A_0T_0R ( 92db2bae30SDana Myers ACPI_WALK_STATE *WalkState) 93db2bae30SDana Myers { 94db2bae30SDana Myers ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 95db2bae30SDana Myers ACPI_SIGNAL_FATAL_INFO *Fatal; 96db2bae30SDana Myers ACPI_STATUS Status = AE_OK; 97db2bae30SDana Myers 98db2bae30SDana Myers 99db2bae30SDana Myers ACPI_FUNCTION_TRACE_STR (ExOpcode_3A_0T_0R, 100db2bae30SDana Myers AcpiPsGetOpcodeName (WalkState->Opcode)); 101db2bae30SDana Myers 102db2bae30SDana Myers 103db2bae30SDana Myers switch (WalkState->Opcode) 104db2bae30SDana Myers { 105db2bae30SDana Myers case AML_FATAL_OP: /* Fatal (FatalType FatalCode FatalArg) */ 106db2bae30SDana Myers 107db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 108*385cc6b4SJerry Jelinek "FatalOp: Type %X Code %X Arg %X " 109*385cc6b4SJerry Jelinek "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", 110db2bae30SDana Myers (UINT32) Operand[0]->Integer.Value, 111db2bae30SDana Myers (UINT32) Operand[1]->Integer.Value, 112db2bae30SDana Myers (UINT32) Operand[2]->Integer.Value)); 113db2bae30SDana Myers 114db2bae30SDana Myers Fatal = ACPI_ALLOCATE (sizeof (ACPI_SIGNAL_FATAL_INFO)); 115db2bae30SDana Myers if (Fatal) 116db2bae30SDana Myers { 117db2bae30SDana Myers Fatal->Type = (UINT32) Operand[0]->Integer.Value; 118db2bae30SDana Myers Fatal->Code = (UINT32) Operand[1]->Integer.Value; 119db2bae30SDana Myers Fatal->Argument = (UINT32) Operand[2]->Integer.Value; 120db2bae30SDana Myers } 121db2bae30SDana Myers 122db2bae30SDana Myers /* Always signal the OS! */ 123db2bae30SDana Myers 124db2bae30SDana Myers Status = AcpiOsSignal (ACPI_SIGNAL_FATAL, Fatal); 125db2bae30SDana Myers 126db2bae30SDana Myers /* Might return while OS is shutting down, just continue */ 127db2bae30SDana Myers 128db2bae30SDana Myers ACPI_FREE (Fatal); 129*385cc6b4SJerry Jelinek goto Cleanup; 130db2bae30SDana Myers 131*385cc6b4SJerry Jelinek case AML_EXTERNAL_OP: 132*385cc6b4SJerry Jelinek /* 133*385cc6b4SJerry Jelinek * If the interpreter sees this opcode, just ignore it. The External 134*385cc6b4SJerry Jelinek * op is intended for use by disassemblers in order to properly 135*385cc6b4SJerry Jelinek * disassemble control method invocations. The opcode or group of 136*385cc6b4SJerry Jelinek * opcodes should be surrounded by an "if (0)" clause to ensure that 137*385cc6b4SJerry Jelinek * AML interpreters never see the opcode. Thus, something is 138*385cc6b4SJerry Jelinek * wrong if an external opcode ever gets here. 139*385cc6b4SJerry Jelinek */ 140*385cc6b4SJerry Jelinek ACPI_ERROR ((AE_INFO, "Executed External Op")); 141*385cc6b4SJerry Jelinek Status = AE_OK; 142*385cc6b4SJerry Jelinek goto Cleanup; 143db2bae30SDana Myers 144db2bae30SDana Myers default: 145db2bae30SDana Myers 14626f3cdf0SGordon Ross ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", 147db2bae30SDana Myers WalkState->Opcode)); 148*385cc6b4SJerry Jelinek 149db2bae30SDana Myers Status = AE_AML_BAD_OPCODE; 150db2bae30SDana Myers goto Cleanup; 151db2bae30SDana Myers } 152db2bae30SDana Myers 153db2bae30SDana Myers 154db2bae30SDana Myers Cleanup: 155db2bae30SDana Myers 156db2bae30SDana Myers return_ACPI_STATUS (Status); 157db2bae30SDana Myers } 158db2bae30SDana Myers 159db2bae30SDana Myers 160db2bae30SDana Myers /******************************************************************************* 161db2bae30SDana Myers * 162db2bae30SDana Myers * FUNCTION: AcpiExOpcode_3A_1T_1R 163db2bae30SDana Myers * 164db2bae30SDana Myers * PARAMETERS: WalkState - Current walk state 165db2bae30SDana Myers * 166db2bae30SDana Myers * RETURN: Status 167db2bae30SDana Myers * 168db2bae30SDana Myers * DESCRIPTION: Execute Triadic operator (3 operands) 169db2bae30SDana Myers * 170db2bae30SDana Myers ******************************************************************************/ 171db2bae30SDana Myers 172db2bae30SDana Myers ACPI_STATUS 173db2bae30SDana Myers AcpiExOpcode_3A_1T_1R ( 174db2bae30SDana Myers ACPI_WALK_STATE *WalkState) 175db2bae30SDana Myers { 176db2bae30SDana Myers ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 177db2bae30SDana Myers ACPI_OPERAND_OBJECT *ReturnDesc = NULL; 178db2bae30SDana Myers char *Buffer = NULL; 179db2bae30SDana Myers ACPI_STATUS Status = AE_OK; 18026f3cdf0SGordon Ross UINT64 Index; 181db2bae30SDana Myers ACPI_SIZE Length; 182db2bae30SDana Myers 183db2bae30SDana Myers 184db2bae30SDana Myers ACPI_FUNCTION_TRACE_STR (ExOpcode_3A_1T_1R, 185db2bae30SDana Myers AcpiPsGetOpcodeName (WalkState->Opcode)); 186db2bae30SDana Myers 187db2bae30SDana Myers 188db2bae30SDana Myers switch (WalkState->Opcode) 189db2bae30SDana Myers { 190db2bae30SDana Myers case AML_MID_OP: /* Mid (Source[0], Index[1], Length[2], Result[3]) */ 191db2bae30SDana Myers /* 192db2bae30SDana Myers * Create the return object. The Source operand is guaranteed to be 193db2bae30SDana Myers * either a String or a Buffer, so just use its type. 194db2bae30SDana Myers */ 195db2bae30SDana Myers ReturnDesc = AcpiUtCreateInternalObject ( 196aa2aa9a6SDana Myers (Operand[0])->Common.Type); 197db2bae30SDana Myers if (!ReturnDesc) 198db2bae30SDana Myers { 199db2bae30SDana Myers Status = AE_NO_MEMORY; 200db2bae30SDana Myers goto Cleanup; 201db2bae30SDana Myers } 202db2bae30SDana Myers 203db2bae30SDana Myers /* Get the Integer values from the objects */ 204db2bae30SDana Myers 205db2bae30SDana Myers Index = Operand[1]->Integer.Value; 206db2bae30SDana Myers Length = (ACPI_SIZE) Operand[2]->Integer.Value; 207db2bae30SDana Myers 208db2bae30SDana Myers /* 209db2bae30SDana Myers * If the index is beyond the length of the String/Buffer, or if the 210db2bae30SDana Myers * requested length is zero, return a zero-length String/Buffer 211db2bae30SDana Myers */ 212db2bae30SDana Myers if (Index >= Operand[0]->String.Length) 213db2bae30SDana Myers { 214db2bae30SDana Myers Length = 0; 215db2bae30SDana Myers } 216db2bae30SDana Myers 217db2bae30SDana Myers /* Truncate request if larger than the actual String/Buffer */ 218db2bae30SDana Myers 219db2bae30SDana Myers else if ((Index + Length) > Operand[0]->String.Length) 220db2bae30SDana Myers { 221*385cc6b4SJerry Jelinek Length = 222*385cc6b4SJerry Jelinek (ACPI_SIZE) Operand[0]->String.Length - (ACPI_SIZE) Index; 223db2bae30SDana Myers } 224db2bae30SDana Myers 225db2bae30SDana Myers /* Strings always have a sub-pointer, not so for buffers */ 226db2bae30SDana Myers 227aa2aa9a6SDana Myers switch ((Operand[0])->Common.Type) 228db2bae30SDana Myers { 229db2bae30SDana Myers case ACPI_TYPE_STRING: 230db2bae30SDana Myers 231db2bae30SDana Myers /* Always allocate a new buffer for the String */ 232db2bae30SDana Myers 233db2bae30SDana Myers Buffer = ACPI_ALLOCATE_ZEROED ((ACPI_SIZE) Length + 1); 234db2bae30SDana Myers if (!Buffer) 235db2bae30SDana Myers { 236db2bae30SDana Myers Status = AE_NO_MEMORY; 237db2bae30SDana Myers goto Cleanup; 238db2bae30SDana Myers } 239db2bae30SDana Myers break; 240db2bae30SDana Myers 241db2bae30SDana Myers case ACPI_TYPE_BUFFER: 242db2bae30SDana Myers 243db2bae30SDana Myers /* If the requested length is zero, don't allocate a buffer */ 244db2bae30SDana Myers 245db2bae30SDana Myers if (Length > 0) 246db2bae30SDana Myers { 247db2bae30SDana Myers /* Allocate a new buffer for the Buffer */ 248db2bae30SDana Myers 249db2bae30SDana Myers Buffer = ACPI_ALLOCATE_ZEROED (Length); 250db2bae30SDana Myers if (!Buffer) 251db2bae30SDana Myers { 252db2bae30SDana Myers Status = AE_NO_MEMORY; 253db2bae30SDana Myers goto Cleanup; 254db2bae30SDana Myers } 255db2bae30SDana Myers } 256db2bae30SDana Myers break; 257db2bae30SDana Myers 258db2bae30SDana Myers default: /* Should not happen */ 259db2bae30SDana Myers 260db2bae30SDana Myers Status = AE_AML_OPERAND_TYPE; 261db2bae30SDana Myers goto Cleanup; 262db2bae30SDana Myers } 263db2bae30SDana Myers 264db2bae30SDana Myers if (Buffer) 265db2bae30SDana Myers { 266db2bae30SDana Myers /* We have a buffer, copy the portion requested */ 267db2bae30SDana Myers 268*385cc6b4SJerry Jelinek memcpy (Buffer, 269*385cc6b4SJerry Jelinek Operand[0]->String.Pointer + Index, Length); 270db2bae30SDana Myers } 271db2bae30SDana Myers 272db2bae30SDana Myers /* Set the length of the new String/Buffer */ 273db2bae30SDana Myers 274db2bae30SDana Myers ReturnDesc->String.Pointer = Buffer; 275db2bae30SDana Myers ReturnDesc->String.Length = (UINT32) Length; 276db2bae30SDana Myers 277db2bae30SDana Myers /* Mark buffer initialized */ 278db2bae30SDana Myers 279db2bae30SDana Myers ReturnDesc->Buffer.Flags |= AOPOBJ_DATA_VALID; 280db2bae30SDana Myers break; 281db2bae30SDana Myers 282db2bae30SDana Myers default: 283db2bae30SDana Myers 28426f3cdf0SGordon Ross ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", 285db2bae30SDana Myers WalkState->Opcode)); 286*385cc6b4SJerry Jelinek 287db2bae30SDana Myers Status = AE_AML_BAD_OPCODE; 288db2bae30SDana Myers goto Cleanup; 289db2bae30SDana Myers } 290db2bae30SDana Myers 291db2bae30SDana Myers /* Store the result in the target */ 292db2bae30SDana Myers 293db2bae30SDana Myers Status = AcpiExStore (ReturnDesc, Operand[3], WalkState); 294db2bae30SDana Myers 295db2bae30SDana Myers Cleanup: 296db2bae30SDana Myers 297db2bae30SDana Myers /* Delete return object on error */ 298db2bae30SDana Myers 299db2bae30SDana Myers if (ACPI_FAILURE (Status) || WalkState->ResultObj) 300db2bae30SDana Myers { 301db2bae30SDana Myers AcpiUtRemoveReference (ReturnDesc); 302db2bae30SDana Myers WalkState->ResultObj = NULL; 303db2bae30SDana Myers } 304db2bae30SDana Myers else 305db2bae30SDana Myers { 306*385cc6b4SJerry Jelinek /* Set the return object and exit */ 307*385cc6b4SJerry Jelinek 308db2bae30SDana Myers WalkState->ResultObj = ReturnDesc; 309db2bae30SDana Myers } 310*385cc6b4SJerry Jelinek 311db2bae30SDana Myers return_ACPI_STATUS (Status); 312db2bae30SDana Myers } 313