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