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