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