xref: /titanic_53/usr/src/uts/intel/io/acpica/executer/exconcat.c (revision 385cc6b4ad1792caef3f84eb61eed3f27085801f)
1*385cc6b4SJerry Jelinek /******************************************************************************
2*385cc6b4SJerry Jelinek  *
3*385cc6b4SJerry Jelinek  * Module Name: exconcat - Concatenate-type AML operators
4*385cc6b4SJerry Jelinek  *
5*385cc6b4SJerry Jelinek  *****************************************************************************/
6*385cc6b4SJerry Jelinek 
7*385cc6b4SJerry Jelinek /*
8*385cc6b4SJerry Jelinek  * Copyright (C) 2000 - 2016, Intel Corp.
9*385cc6b4SJerry Jelinek  * All rights reserved.
10*385cc6b4SJerry Jelinek  *
11*385cc6b4SJerry Jelinek  * Redistribution and use in source and binary forms, with or without
12*385cc6b4SJerry Jelinek  * modification, are permitted provided that the following conditions
13*385cc6b4SJerry Jelinek  * are met:
14*385cc6b4SJerry Jelinek  * 1. Redistributions of source code must retain the above copyright
15*385cc6b4SJerry Jelinek  *    notice, this list of conditions, and the following disclaimer,
16*385cc6b4SJerry Jelinek  *    without modification.
17*385cc6b4SJerry Jelinek  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18*385cc6b4SJerry Jelinek  *    substantially similar to the "NO WARRANTY" disclaimer below
19*385cc6b4SJerry Jelinek  *    ("Disclaimer") and any redistribution must be conditioned upon
20*385cc6b4SJerry Jelinek  *    including a substantially similar Disclaimer requirement for further
21*385cc6b4SJerry Jelinek  *    binary redistribution.
22*385cc6b4SJerry Jelinek  * 3. Neither the names of the above-listed copyright holders nor the names
23*385cc6b4SJerry Jelinek  *    of any contributors may be used to endorse or promote products derived
24*385cc6b4SJerry Jelinek  *    from this software without specific prior written permission.
25*385cc6b4SJerry Jelinek  *
26*385cc6b4SJerry Jelinek  * Alternatively, this software may be distributed under the terms of the
27*385cc6b4SJerry Jelinek  * GNU General Public License ("GPL") version 2 as published by the Free
28*385cc6b4SJerry Jelinek  * Software Foundation.
29*385cc6b4SJerry Jelinek  *
30*385cc6b4SJerry Jelinek  * NO WARRANTY
31*385cc6b4SJerry Jelinek  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32*385cc6b4SJerry Jelinek  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33*385cc6b4SJerry Jelinek  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34*385cc6b4SJerry Jelinek  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35*385cc6b4SJerry Jelinek  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36*385cc6b4SJerry Jelinek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37*385cc6b4SJerry Jelinek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38*385cc6b4SJerry Jelinek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39*385cc6b4SJerry Jelinek  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40*385cc6b4SJerry Jelinek  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41*385cc6b4SJerry Jelinek  * POSSIBILITY OF SUCH DAMAGES.
42*385cc6b4SJerry Jelinek  */
43*385cc6b4SJerry Jelinek 
44*385cc6b4SJerry Jelinek #include "acpi.h"
45*385cc6b4SJerry Jelinek #include "accommon.h"
46*385cc6b4SJerry Jelinek #include "acinterp.h"
47*385cc6b4SJerry Jelinek #include "amlresrc.h"
48*385cc6b4SJerry Jelinek 
49*385cc6b4SJerry Jelinek 
50*385cc6b4SJerry Jelinek #define _COMPONENT          ACPI_EXECUTER
51*385cc6b4SJerry Jelinek         ACPI_MODULE_NAME    ("exconcat")
52*385cc6b4SJerry Jelinek 
53*385cc6b4SJerry Jelinek /* Local Prototypes */
54*385cc6b4SJerry Jelinek 
55*385cc6b4SJerry Jelinek static ACPI_STATUS
56*385cc6b4SJerry Jelinek AcpiExConvertToObjectTypeString (
57*385cc6b4SJerry Jelinek     ACPI_OPERAND_OBJECT     *ObjDesc,
58*385cc6b4SJerry Jelinek     ACPI_OPERAND_OBJECT     **ResultDesc);
59*385cc6b4SJerry Jelinek 
60*385cc6b4SJerry Jelinek 
61*385cc6b4SJerry Jelinek /*******************************************************************************
62*385cc6b4SJerry Jelinek  *
63*385cc6b4SJerry Jelinek  * FUNCTION:    AcpiExDoConcatenate
64*385cc6b4SJerry Jelinek  *
65*385cc6b4SJerry Jelinek  * PARAMETERS:  Operand0            - First source object
66*385cc6b4SJerry Jelinek  *              Operand1            - Second source object
67*385cc6b4SJerry Jelinek  *              ActualReturnDesc    - Where to place the return object
68*385cc6b4SJerry Jelinek  *              WalkState           - Current walk state
69*385cc6b4SJerry Jelinek  *
70*385cc6b4SJerry Jelinek  * RETURN:      Status
71*385cc6b4SJerry Jelinek  *
72*385cc6b4SJerry Jelinek  * DESCRIPTION: Concatenate two objects with the ACPI-defined conversion
73*385cc6b4SJerry Jelinek  *              rules as necessary.
74*385cc6b4SJerry Jelinek  * NOTE:
75*385cc6b4SJerry Jelinek  * Per the ACPI spec (up to 6.1), Concatenate only supports Integer,
76*385cc6b4SJerry Jelinek  * String, and Buffer objects. However, we support all objects here
77*385cc6b4SJerry Jelinek  * as an extension. This improves the usefulness of both Concatenate
78*385cc6b4SJerry Jelinek  * and the Printf/Fprintf macros. The extension returns a string
79*385cc6b4SJerry Jelinek  * describing the object type for the other objects.
80*385cc6b4SJerry Jelinek  * 02/2016.
81*385cc6b4SJerry Jelinek  *
82*385cc6b4SJerry Jelinek  ******************************************************************************/
83*385cc6b4SJerry Jelinek 
84*385cc6b4SJerry Jelinek ACPI_STATUS
AcpiExDoConcatenate(ACPI_OPERAND_OBJECT * Operand0,ACPI_OPERAND_OBJECT * Operand1,ACPI_OPERAND_OBJECT ** ActualReturnDesc,ACPI_WALK_STATE * WalkState)85*385cc6b4SJerry Jelinek AcpiExDoConcatenate (
86*385cc6b4SJerry Jelinek     ACPI_OPERAND_OBJECT     *Operand0,
87*385cc6b4SJerry Jelinek     ACPI_OPERAND_OBJECT     *Operand1,
88*385cc6b4SJerry Jelinek     ACPI_OPERAND_OBJECT     **ActualReturnDesc,
89*385cc6b4SJerry Jelinek     ACPI_WALK_STATE         *WalkState)
90*385cc6b4SJerry Jelinek {
91*385cc6b4SJerry Jelinek     ACPI_OPERAND_OBJECT     *LocalOperand0 = Operand0;
92*385cc6b4SJerry Jelinek     ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
93*385cc6b4SJerry Jelinek     ACPI_OPERAND_OBJECT     *TempOperand1 = NULL;
94*385cc6b4SJerry Jelinek     ACPI_OPERAND_OBJECT     *ReturnDesc;
95*385cc6b4SJerry Jelinek     char                    *Buffer;
96*385cc6b4SJerry Jelinek     ACPI_OBJECT_TYPE        Operand0Type;
97*385cc6b4SJerry Jelinek     ACPI_OBJECT_TYPE        Operand1Type;
98*385cc6b4SJerry Jelinek     ACPI_STATUS             Status;
99*385cc6b4SJerry Jelinek 
100*385cc6b4SJerry Jelinek 
101*385cc6b4SJerry Jelinek     ACPI_FUNCTION_TRACE (ExDoConcatenate);
102*385cc6b4SJerry Jelinek 
103*385cc6b4SJerry Jelinek 
104*385cc6b4SJerry Jelinek     /* Operand 0 preprocessing */
105*385cc6b4SJerry Jelinek 
106*385cc6b4SJerry Jelinek     switch (Operand0->Common.Type)
107*385cc6b4SJerry Jelinek     {
108*385cc6b4SJerry Jelinek     case ACPI_TYPE_INTEGER:
109*385cc6b4SJerry Jelinek     case ACPI_TYPE_STRING:
110*385cc6b4SJerry Jelinek     case ACPI_TYPE_BUFFER:
111*385cc6b4SJerry Jelinek 
112*385cc6b4SJerry Jelinek         Operand0Type = Operand0->Common.Type;
113*385cc6b4SJerry Jelinek         break;
114*385cc6b4SJerry Jelinek 
115*385cc6b4SJerry Jelinek     default:
116*385cc6b4SJerry Jelinek 
117*385cc6b4SJerry Jelinek         /* For all other types, get the "object type" string */
118*385cc6b4SJerry Jelinek 
119*385cc6b4SJerry Jelinek         Status = AcpiExConvertToObjectTypeString (
120*385cc6b4SJerry Jelinek             Operand0, &LocalOperand0);
121*385cc6b4SJerry Jelinek         if (ACPI_FAILURE (Status))
122*385cc6b4SJerry Jelinek         {
123*385cc6b4SJerry Jelinek             goto Cleanup;
124*385cc6b4SJerry Jelinek         }
125*385cc6b4SJerry Jelinek 
126*385cc6b4SJerry Jelinek         Operand0Type = ACPI_TYPE_STRING;
127*385cc6b4SJerry Jelinek         break;
128*385cc6b4SJerry Jelinek     }
129*385cc6b4SJerry Jelinek 
130*385cc6b4SJerry Jelinek     /* Operand 1 preprocessing */
131*385cc6b4SJerry Jelinek 
132*385cc6b4SJerry Jelinek     switch (Operand1->Common.Type)
133*385cc6b4SJerry Jelinek     {
134*385cc6b4SJerry Jelinek     case ACPI_TYPE_INTEGER:
135*385cc6b4SJerry Jelinek     case ACPI_TYPE_STRING:
136*385cc6b4SJerry Jelinek     case ACPI_TYPE_BUFFER:
137*385cc6b4SJerry Jelinek 
138*385cc6b4SJerry Jelinek         Operand1Type = Operand1->Common.Type;
139*385cc6b4SJerry Jelinek         break;
140*385cc6b4SJerry Jelinek 
141*385cc6b4SJerry Jelinek     default:
142*385cc6b4SJerry Jelinek 
143*385cc6b4SJerry Jelinek         /* For all other types, get the "object type" string */
144*385cc6b4SJerry Jelinek 
145*385cc6b4SJerry Jelinek         Status = AcpiExConvertToObjectTypeString (
146*385cc6b4SJerry Jelinek             Operand1, &LocalOperand1);
147*385cc6b4SJerry Jelinek         if (ACPI_FAILURE (Status))
148*385cc6b4SJerry Jelinek         {
149*385cc6b4SJerry Jelinek             goto Cleanup;
150*385cc6b4SJerry Jelinek         }
151*385cc6b4SJerry Jelinek 
152*385cc6b4SJerry Jelinek         Operand1Type = ACPI_TYPE_STRING;
153*385cc6b4SJerry Jelinek         break;
154*385cc6b4SJerry Jelinek     }
155*385cc6b4SJerry Jelinek 
156*385cc6b4SJerry Jelinek     /*
157*385cc6b4SJerry Jelinek      * Convert the second operand if necessary. The first operand (0)
158*385cc6b4SJerry Jelinek      * determines the type of the second operand (1) (See the Data Types
159*385cc6b4SJerry Jelinek      * section of the ACPI specification). Both object types are
160*385cc6b4SJerry Jelinek      * guaranteed to be either Integer/String/Buffer by the operand
161*385cc6b4SJerry Jelinek      * resolution mechanism.
162*385cc6b4SJerry Jelinek      */
163*385cc6b4SJerry Jelinek     switch (Operand0Type)
164*385cc6b4SJerry Jelinek     {
165*385cc6b4SJerry Jelinek     case ACPI_TYPE_INTEGER:
166*385cc6b4SJerry Jelinek 
167*385cc6b4SJerry Jelinek         Status = AcpiExConvertToInteger (LocalOperand1, &TempOperand1, 16);
168*385cc6b4SJerry Jelinek         break;
169*385cc6b4SJerry Jelinek 
170*385cc6b4SJerry Jelinek     case ACPI_TYPE_BUFFER:
171*385cc6b4SJerry Jelinek 
172*385cc6b4SJerry Jelinek         Status = AcpiExConvertToBuffer (LocalOperand1, &TempOperand1);
173*385cc6b4SJerry Jelinek         break;
174*385cc6b4SJerry Jelinek 
175*385cc6b4SJerry Jelinek     case ACPI_TYPE_STRING:
176*385cc6b4SJerry Jelinek 
177*385cc6b4SJerry Jelinek         switch (Operand1Type)
178*385cc6b4SJerry Jelinek         {
179*385cc6b4SJerry Jelinek         case ACPI_TYPE_INTEGER:
180*385cc6b4SJerry Jelinek         case ACPI_TYPE_STRING:
181*385cc6b4SJerry Jelinek         case ACPI_TYPE_BUFFER:
182*385cc6b4SJerry Jelinek 
183*385cc6b4SJerry Jelinek             /* Other types have already been converted to string */
184*385cc6b4SJerry Jelinek 
185*385cc6b4SJerry Jelinek             Status = AcpiExConvertToString (
186*385cc6b4SJerry Jelinek                 LocalOperand1, &TempOperand1, ACPI_IMPLICIT_CONVERT_HEX);
187*385cc6b4SJerry Jelinek             break;
188*385cc6b4SJerry Jelinek 
189*385cc6b4SJerry Jelinek         default:
190*385cc6b4SJerry Jelinek 
191*385cc6b4SJerry Jelinek             Status = AE_OK;
192*385cc6b4SJerry Jelinek             break;
193*385cc6b4SJerry Jelinek         }
194*385cc6b4SJerry Jelinek         break;
195*385cc6b4SJerry Jelinek 
196*385cc6b4SJerry Jelinek     default:
197*385cc6b4SJerry Jelinek 
198*385cc6b4SJerry Jelinek         ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X",
199*385cc6b4SJerry Jelinek             Operand0->Common.Type));
200*385cc6b4SJerry Jelinek         Status = AE_AML_INTERNAL;
201*385cc6b4SJerry Jelinek     }
202*385cc6b4SJerry Jelinek 
203*385cc6b4SJerry Jelinek     if (ACPI_FAILURE (Status))
204*385cc6b4SJerry Jelinek     {
205*385cc6b4SJerry Jelinek         goto Cleanup;
206*385cc6b4SJerry Jelinek     }
207*385cc6b4SJerry Jelinek 
208*385cc6b4SJerry Jelinek     /* Take care with any newly created operand objects */
209*385cc6b4SJerry Jelinek 
210*385cc6b4SJerry Jelinek     if ((LocalOperand1 != Operand1) &&
211*385cc6b4SJerry Jelinek         (LocalOperand1 != TempOperand1))
212*385cc6b4SJerry Jelinek     {
213*385cc6b4SJerry Jelinek         AcpiUtRemoveReference (LocalOperand1);
214*385cc6b4SJerry Jelinek     }
215*385cc6b4SJerry Jelinek 
216*385cc6b4SJerry Jelinek     LocalOperand1 = TempOperand1;
217*385cc6b4SJerry Jelinek 
218*385cc6b4SJerry Jelinek     /*
219*385cc6b4SJerry Jelinek      * Both operands are now known to be the same object type
220*385cc6b4SJerry Jelinek      * (Both are Integer, String, or Buffer), and we can now perform
221*385cc6b4SJerry Jelinek      * the concatenation.
222*385cc6b4SJerry Jelinek      *
223*385cc6b4SJerry Jelinek      * There are three cases to handle, as per the ACPI spec:
224*385cc6b4SJerry Jelinek      *
225*385cc6b4SJerry Jelinek      * 1) Two Integers concatenated to produce a new Buffer
226*385cc6b4SJerry Jelinek      * 2) Two Strings concatenated to produce a new String
227*385cc6b4SJerry Jelinek      * 3) Two Buffers concatenated to produce a new Buffer
228*385cc6b4SJerry Jelinek      */
229*385cc6b4SJerry Jelinek     switch (Operand0Type)
230*385cc6b4SJerry Jelinek     {
231*385cc6b4SJerry Jelinek     case ACPI_TYPE_INTEGER:
232*385cc6b4SJerry Jelinek 
233*385cc6b4SJerry Jelinek         /* Result of two Integers is a Buffer */
234*385cc6b4SJerry Jelinek         /* Need enough buffer space for two integers */
235*385cc6b4SJerry Jelinek 
236*385cc6b4SJerry Jelinek         ReturnDesc = AcpiUtCreateBufferObject (
237*385cc6b4SJerry Jelinek             (ACPI_SIZE) ACPI_MUL_2 (AcpiGbl_IntegerByteWidth));
238*385cc6b4SJerry Jelinek         if (!ReturnDesc)
239*385cc6b4SJerry Jelinek         {
240*385cc6b4SJerry Jelinek             Status = AE_NO_MEMORY;
241*385cc6b4SJerry Jelinek             goto Cleanup;
242*385cc6b4SJerry Jelinek         }
243*385cc6b4SJerry Jelinek 
244*385cc6b4SJerry Jelinek         Buffer = (char *) ReturnDesc->Buffer.Pointer;
245*385cc6b4SJerry Jelinek 
246*385cc6b4SJerry Jelinek         /* Copy the first integer, LSB first */
247*385cc6b4SJerry Jelinek 
248*385cc6b4SJerry Jelinek         memcpy (Buffer, &Operand0->Integer.Value,
249*385cc6b4SJerry Jelinek             AcpiGbl_IntegerByteWidth);
250*385cc6b4SJerry Jelinek 
251*385cc6b4SJerry Jelinek         /* Copy the second integer (LSB first) after the first */
252*385cc6b4SJerry Jelinek 
253*385cc6b4SJerry Jelinek         memcpy (Buffer + AcpiGbl_IntegerByteWidth,
254*385cc6b4SJerry Jelinek             &LocalOperand1->Integer.Value, AcpiGbl_IntegerByteWidth);
255*385cc6b4SJerry Jelinek         break;
256*385cc6b4SJerry Jelinek 
257*385cc6b4SJerry Jelinek     case ACPI_TYPE_STRING:
258*385cc6b4SJerry Jelinek 
259*385cc6b4SJerry Jelinek         /* Result of two Strings is a String */
260*385cc6b4SJerry Jelinek 
261*385cc6b4SJerry Jelinek         ReturnDesc = AcpiUtCreateStringObject (
262*385cc6b4SJerry Jelinek             ((ACPI_SIZE) LocalOperand0->String.Length +
263*385cc6b4SJerry Jelinek             LocalOperand1->String.Length));
264*385cc6b4SJerry Jelinek         if (!ReturnDesc)
265*385cc6b4SJerry Jelinek         {
266*385cc6b4SJerry Jelinek             Status = AE_NO_MEMORY;
267*385cc6b4SJerry Jelinek             goto Cleanup;
268*385cc6b4SJerry Jelinek         }
269*385cc6b4SJerry Jelinek 
270*385cc6b4SJerry Jelinek         Buffer = ReturnDesc->String.Pointer;
271*385cc6b4SJerry Jelinek 
272*385cc6b4SJerry Jelinek         /* Concatenate the strings */
273*385cc6b4SJerry Jelinek 
274*385cc6b4SJerry Jelinek         strcpy (Buffer, LocalOperand0->String.Pointer);
275*385cc6b4SJerry Jelinek         strcat (Buffer, LocalOperand1->String.Pointer);
276*385cc6b4SJerry Jelinek         break;
277*385cc6b4SJerry Jelinek 
278*385cc6b4SJerry Jelinek     case ACPI_TYPE_BUFFER:
279*385cc6b4SJerry Jelinek 
280*385cc6b4SJerry Jelinek         /* Result of two Buffers is a Buffer */
281*385cc6b4SJerry Jelinek 
282*385cc6b4SJerry Jelinek         ReturnDesc = AcpiUtCreateBufferObject (
283*385cc6b4SJerry Jelinek             ((ACPI_SIZE) Operand0->Buffer.Length +
284*385cc6b4SJerry Jelinek             LocalOperand1->Buffer.Length));
285*385cc6b4SJerry Jelinek         if (!ReturnDesc)
286*385cc6b4SJerry Jelinek         {
287*385cc6b4SJerry Jelinek             Status = AE_NO_MEMORY;
288*385cc6b4SJerry Jelinek             goto Cleanup;
289*385cc6b4SJerry Jelinek         }
290*385cc6b4SJerry Jelinek 
291*385cc6b4SJerry Jelinek         Buffer = (char *) ReturnDesc->Buffer.Pointer;
292*385cc6b4SJerry Jelinek 
293*385cc6b4SJerry Jelinek         /* Concatenate the buffers */
294*385cc6b4SJerry Jelinek 
295*385cc6b4SJerry Jelinek         memcpy (Buffer, Operand0->Buffer.Pointer,
296*385cc6b4SJerry Jelinek             Operand0->Buffer.Length);
297*385cc6b4SJerry Jelinek         memcpy (Buffer + Operand0->Buffer.Length,
298*385cc6b4SJerry Jelinek             LocalOperand1->Buffer.Pointer,
299*385cc6b4SJerry Jelinek             LocalOperand1->Buffer.Length);
300*385cc6b4SJerry Jelinek         break;
301*385cc6b4SJerry Jelinek 
302*385cc6b4SJerry Jelinek     default:
303*385cc6b4SJerry Jelinek 
304*385cc6b4SJerry Jelinek         /* Invalid object type, should not happen here */
305*385cc6b4SJerry Jelinek 
306*385cc6b4SJerry Jelinek         ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X",
307*385cc6b4SJerry Jelinek             Operand0->Common.Type));
308*385cc6b4SJerry Jelinek         Status = AE_AML_INTERNAL;
309*385cc6b4SJerry Jelinek         goto Cleanup;
310*385cc6b4SJerry Jelinek     }
311*385cc6b4SJerry Jelinek 
312*385cc6b4SJerry Jelinek     *ActualReturnDesc = ReturnDesc;
313*385cc6b4SJerry Jelinek 
314*385cc6b4SJerry Jelinek Cleanup:
315*385cc6b4SJerry Jelinek     if (LocalOperand0 != Operand0)
316*385cc6b4SJerry Jelinek     {
317*385cc6b4SJerry Jelinek         AcpiUtRemoveReference (LocalOperand0);
318*385cc6b4SJerry Jelinek     }
319*385cc6b4SJerry Jelinek 
320*385cc6b4SJerry Jelinek     if (LocalOperand1 != Operand1)
321*385cc6b4SJerry Jelinek     {
322*385cc6b4SJerry Jelinek         AcpiUtRemoveReference (LocalOperand1);
323*385cc6b4SJerry Jelinek     }
324*385cc6b4SJerry Jelinek 
325*385cc6b4SJerry Jelinek     return_ACPI_STATUS (Status);
326*385cc6b4SJerry Jelinek }
327*385cc6b4SJerry Jelinek 
328*385cc6b4SJerry Jelinek 
329*385cc6b4SJerry Jelinek /*******************************************************************************
330*385cc6b4SJerry Jelinek  *
331*385cc6b4SJerry Jelinek  * FUNCTION:    AcpiExConvertToObjectTypeString
332*385cc6b4SJerry Jelinek  *
333*385cc6b4SJerry Jelinek  * PARAMETERS:  ObjDesc             - Object to be converted
334*385cc6b4SJerry Jelinek  *              ReturnDesc          - Where to place the return object
335*385cc6b4SJerry Jelinek  *
336*385cc6b4SJerry Jelinek  * RETURN:      Status
337*385cc6b4SJerry Jelinek  *
338*385cc6b4SJerry Jelinek  * DESCRIPTION: Convert an object of arbitrary type to a string object that
339*385cc6b4SJerry Jelinek  *              contains the namestring for the object. Used for the
340*385cc6b4SJerry Jelinek  *              concatenate operator.
341*385cc6b4SJerry Jelinek  *
342*385cc6b4SJerry Jelinek  ******************************************************************************/
343*385cc6b4SJerry Jelinek 
344*385cc6b4SJerry Jelinek static ACPI_STATUS
AcpiExConvertToObjectTypeString(ACPI_OPERAND_OBJECT * ObjDesc,ACPI_OPERAND_OBJECT ** ResultDesc)345*385cc6b4SJerry Jelinek AcpiExConvertToObjectTypeString (
346*385cc6b4SJerry Jelinek     ACPI_OPERAND_OBJECT     *ObjDesc,
347*385cc6b4SJerry Jelinek     ACPI_OPERAND_OBJECT     **ResultDesc)
348*385cc6b4SJerry Jelinek {
349*385cc6b4SJerry Jelinek     ACPI_OPERAND_OBJECT     *ReturnDesc;
350*385cc6b4SJerry Jelinek     const char              *TypeString;
351*385cc6b4SJerry Jelinek 
352*385cc6b4SJerry Jelinek 
353*385cc6b4SJerry Jelinek     TypeString = AcpiUtGetTypeName (ObjDesc->Common.Type);
354*385cc6b4SJerry Jelinek 
355*385cc6b4SJerry Jelinek     ReturnDesc = AcpiUtCreateStringObject (
356*385cc6b4SJerry Jelinek         ((ACPI_SIZE) strlen (TypeString) + 9)); /* 9 For "[ Object]" */
357*385cc6b4SJerry Jelinek     if (!ReturnDesc)
358*385cc6b4SJerry Jelinek     {
359*385cc6b4SJerry Jelinek         return (AE_NO_MEMORY);
360*385cc6b4SJerry Jelinek     }
361*385cc6b4SJerry Jelinek 
362*385cc6b4SJerry Jelinek     strcpy (ReturnDesc->String.Pointer, "[");
363*385cc6b4SJerry Jelinek     strcat (ReturnDesc->String.Pointer, TypeString);
364*385cc6b4SJerry Jelinek     strcat (ReturnDesc->String.Pointer, " Object]");
365*385cc6b4SJerry Jelinek 
366*385cc6b4SJerry Jelinek     *ResultDesc = ReturnDesc;
367*385cc6b4SJerry Jelinek     return (AE_OK);
368*385cc6b4SJerry Jelinek }
369*385cc6b4SJerry Jelinek 
370*385cc6b4SJerry Jelinek 
371*385cc6b4SJerry Jelinek /*******************************************************************************
372*385cc6b4SJerry Jelinek  *
373*385cc6b4SJerry Jelinek  * FUNCTION:    AcpiExConcatTemplate
374*385cc6b4SJerry Jelinek  *
375*385cc6b4SJerry Jelinek  * PARAMETERS:  Operand0            - First source object
376*385cc6b4SJerry Jelinek  *              Operand1            - Second source object
377*385cc6b4SJerry Jelinek  *              ActualReturnDesc    - Where to place the return object
378*385cc6b4SJerry Jelinek  *              WalkState           - Current walk state
379*385cc6b4SJerry Jelinek  *
380*385cc6b4SJerry Jelinek  * RETURN:      Status
381*385cc6b4SJerry Jelinek  *
382*385cc6b4SJerry Jelinek  * DESCRIPTION: Concatenate two resource templates
383*385cc6b4SJerry Jelinek  *
384*385cc6b4SJerry Jelinek  ******************************************************************************/
385*385cc6b4SJerry Jelinek 
386*385cc6b4SJerry Jelinek ACPI_STATUS
AcpiExConcatTemplate(ACPI_OPERAND_OBJECT * Operand0,ACPI_OPERAND_OBJECT * Operand1,ACPI_OPERAND_OBJECT ** ActualReturnDesc,ACPI_WALK_STATE * WalkState)387*385cc6b4SJerry Jelinek AcpiExConcatTemplate (
388*385cc6b4SJerry Jelinek     ACPI_OPERAND_OBJECT     *Operand0,
389*385cc6b4SJerry Jelinek     ACPI_OPERAND_OBJECT     *Operand1,
390*385cc6b4SJerry Jelinek     ACPI_OPERAND_OBJECT     **ActualReturnDesc,
391*385cc6b4SJerry Jelinek     ACPI_WALK_STATE         *WalkState)
392*385cc6b4SJerry Jelinek {
393*385cc6b4SJerry Jelinek     ACPI_STATUS             Status;
394*385cc6b4SJerry Jelinek     ACPI_OPERAND_OBJECT     *ReturnDesc;
395*385cc6b4SJerry Jelinek     UINT8                   *NewBuf;
396*385cc6b4SJerry Jelinek     UINT8                   *EndTag;
397*385cc6b4SJerry Jelinek     ACPI_SIZE               Length0;
398*385cc6b4SJerry Jelinek     ACPI_SIZE               Length1;
399*385cc6b4SJerry Jelinek     ACPI_SIZE               NewLength;
400*385cc6b4SJerry Jelinek 
401*385cc6b4SJerry Jelinek 
402*385cc6b4SJerry Jelinek     ACPI_FUNCTION_TRACE (ExConcatTemplate);
403*385cc6b4SJerry Jelinek 
404*385cc6b4SJerry Jelinek 
405*385cc6b4SJerry Jelinek     /*
406*385cc6b4SJerry Jelinek      * Find the EndTag descriptor in each resource template.
407*385cc6b4SJerry Jelinek      * Note1: returned pointers point TO the EndTag, not past it.
408*385cc6b4SJerry Jelinek      * Note2: zero-length buffers are allowed; treated like one EndTag
409*385cc6b4SJerry Jelinek      */
410*385cc6b4SJerry Jelinek 
411*385cc6b4SJerry Jelinek     /* Get the length of the first resource template */
412*385cc6b4SJerry Jelinek 
413*385cc6b4SJerry Jelinek     Status = AcpiUtGetResourceEndTag (Operand0, &EndTag);
414*385cc6b4SJerry Jelinek     if (ACPI_FAILURE (Status))
415*385cc6b4SJerry Jelinek     {
416*385cc6b4SJerry Jelinek         return_ACPI_STATUS (Status);
417*385cc6b4SJerry Jelinek     }
418*385cc6b4SJerry Jelinek 
419*385cc6b4SJerry Jelinek     Length0 = ACPI_PTR_DIFF (EndTag, Operand0->Buffer.Pointer);
420*385cc6b4SJerry Jelinek 
421*385cc6b4SJerry Jelinek     /* Get the length of the second resource template */
422*385cc6b4SJerry Jelinek 
423*385cc6b4SJerry Jelinek     Status = AcpiUtGetResourceEndTag (Operand1, &EndTag);
424*385cc6b4SJerry Jelinek     if (ACPI_FAILURE (Status))
425*385cc6b4SJerry Jelinek     {
426*385cc6b4SJerry Jelinek         return_ACPI_STATUS (Status);
427*385cc6b4SJerry Jelinek     }
428*385cc6b4SJerry Jelinek 
429*385cc6b4SJerry Jelinek     Length1 = ACPI_PTR_DIFF (EndTag, Operand1->Buffer.Pointer);
430*385cc6b4SJerry Jelinek 
431*385cc6b4SJerry Jelinek     /* Combine both lengths, minimum size will be 2 for EndTag */
432*385cc6b4SJerry Jelinek 
433*385cc6b4SJerry Jelinek     NewLength = Length0 + Length1 + sizeof (AML_RESOURCE_END_TAG);
434*385cc6b4SJerry Jelinek 
435*385cc6b4SJerry Jelinek     /* Create a new buffer object for the result (with one EndTag) */
436*385cc6b4SJerry Jelinek 
437*385cc6b4SJerry Jelinek     ReturnDesc = AcpiUtCreateBufferObject (NewLength);
438*385cc6b4SJerry Jelinek     if (!ReturnDesc)
439*385cc6b4SJerry Jelinek     {
440*385cc6b4SJerry Jelinek         return_ACPI_STATUS (AE_NO_MEMORY);
441*385cc6b4SJerry Jelinek     }
442*385cc6b4SJerry Jelinek 
443*385cc6b4SJerry Jelinek     /*
444*385cc6b4SJerry Jelinek      * Copy the templates to the new buffer, 0 first, then 1 follows. One
445*385cc6b4SJerry Jelinek      * EndTag descriptor is copied from Operand1.
446*385cc6b4SJerry Jelinek      */
447*385cc6b4SJerry Jelinek     NewBuf = ReturnDesc->Buffer.Pointer;
448*385cc6b4SJerry Jelinek     memcpy (NewBuf, Operand0->Buffer.Pointer, Length0);
449*385cc6b4SJerry Jelinek     memcpy (NewBuf + Length0, Operand1->Buffer.Pointer, Length1);
450*385cc6b4SJerry Jelinek 
451*385cc6b4SJerry Jelinek     /* Insert EndTag and set the checksum to zero, means "ignore checksum" */
452*385cc6b4SJerry Jelinek 
453*385cc6b4SJerry Jelinek     NewBuf[NewLength - 1] = 0;
454*385cc6b4SJerry Jelinek     NewBuf[NewLength - 2] = ACPI_RESOURCE_NAME_END_TAG | 1;
455*385cc6b4SJerry Jelinek 
456*385cc6b4SJerry Jelinek     /* Return the completed resource template */
457*385cc6b4SJerry Jelinek 
458*385cc6b4SJerry Jelinek     *ActualReturnDesc = ReturnDesc;
459*385cc6b4SJerry Jelinek     return_ACPI_STATUS (AE_OK);
460*385cc6b4SJerry Jelinek }
461