1 /******************************************************************************
3 * Module Name: exconcat - Concatenate-type AML operators
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2018, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
50 #define _COMPONENT ACPI_EXECUTER
51 ACPI_MODULE_NAME ("exconcat")
53 /* Local Prototypes */
56 AcpiExConvertToObjectTypeString (
57 ACPI_OPERAND_OBJECT
*ObjDesc
,
58 ACPI_OPERAND_OBJECT
**ResultDesc
);
61 /*******************************************************************************
63 * FUNCTION: AcpiExDoConcatenate
65 * PARAMETERS: Operand0 - First source object
66 * Operand1 - Second source object
67 * ActualReturnDesc - Where to place the return object
68 * WalkState - Current walk state
72 * DESCRIPTION: Concatenate two objects with the ACPI-defined conversion
75 * Per the ACPI spec (up to 6.1), Concatenate only supports Integer,
76 * String, and Buffer objects. However, we support all objects here
77 * as an extension. This improves the usefulness of both Concatenate
78 * and the Printf/Fprintf macros. The extension returns a string
79 * describing the object type for the other objects.
82 ******************************************************************************/
86 ACPI_OPERAND_OBJECT
*Operand0
,
87 ACPI_OPERAND_OBJECT
*Operand1
,
88 ACPI_OPERAND_OBJECT
**ActualReturnDesc
,
89 ACPI_WALK_STATE
*WalkState
)
91 ACPI_OPERAND_OBJECT
*LocalOperand0
= Operand0
;
92 ACPI_OPERAND_OBJECT
*LocalOperand1
= Operand1
;
93 ACPI_OPERAND_OBJECT
*TempOperand1
= NULL
;
94 ACPI_OPERAND_OBJECT
*ReturnDesc
;
96 ACPI_OBJECT_TYPE Operand0Type
;
97 ACPI_OBJECT_TYPE Operand1Type
;
101 ACPI_FUNCTION_TRACE (ExDoConcatenate
);
104 /* Operand 0 preprocessing */
106 switch (Operand0
->Common
.Type
)
108 case ACPI_TYPE_INTEGER
:
109 case ACPI_TYPE_STRING
:
110 case ACPI_TYPE_BUFFER
:
112 Operand0Type
= Operand0
->Common
.Type
;
117 /* For all other types, get the "object type" string */
119 Status
= AcpiExConvertToObjectTypeString (
120 Operand0
, &LocalOperand0
);
121 if (ACPI_FAILURE (Status
))
126 Operand0Type
= ACPI_TYPE_STRING
;
130 /* Operand 1 preprocessing */
132 switch (Operand1
->Common
.Type
)
134 case ACPI_TYPE_INTEGER
:
135 case ACPI_TYPE_STRING
:
136 case ACPI_TYPE_BUFFER
:
138 Operand1Type
= Operand1
->Common
.Type
;
143 /* For all other types, get the "object type" string */
145 Status
= AcpiExConvertToObjectTypeString (
146 Operand1
, &LocalOperand1
);
147 if (ACPI_FAILURE (Status
))
152 Operand1Type
= ACPI_TYPE_STRING
;
157 * Convert the second operand if necessary. The first operand (0)
158 * determines the type of the second operand (1) (See the Data Types
159 * section of the ACPI specification). Both object types are
160 * guaranteed to be either Integer/String/Buffer by the operand
161 * resolution mechanism.
163 switch (Operand0Type
)
165 case ACPI_TYPE_INTEGER
:
167 Status
= AcpiExConvertToInteger (LocalOperand1
, &TempOperand1
,
168 ACPI_IMPLICIT_CONVERSION
);
171 case ACPI_TYPE_BUFFER
:
173 Status
= AcpiExConvertToBuffer (LocalOperand1
, &TempOperand1
);
176 case ACPI_TYPE_STRING
:
178 switch (Operand1Type
)
180 case ACPI_TYPE_INTEGER
:
181 case ACPI_TYPE_STRING
:
182 case ACPI_TYPE_BUFFER
:
184 /* Other types have already been converted to string */
186 Status
= AcpiExConvertToString (
187 LocalOperand1
, &TempOperand1
, ACPI_IMPLICIT_CONVERT_HEX
);
199 ACPI_ERROR ((AE_INFO
, "Invalid object type: 0x%X",
200 Operand0
->Common
.Type
));
201 Status
= AE_AML_INTERNAL
;
204 if (ACPI_FAILURE (Status
))
209 /* Take care with any newly created operand objects */
211 if ((LocalOperand1
!= Operand1
) &&
212 (LocalOperand1
!= TempOperand1
))
214 AcpiUtRemoveReference (LocalOperand1
);
217 LocalOperand1
= TempOperand1
;
220 * Both operands are now known to be the same object type
221 * (Both are Integer, String, or Buffer), and we can now perform
224 * There are three cases to handle, as per the ACPI spec:
226 * 1) Two Integers concatenated to produce a new Buffer
227 * 2) Two Strings concatenated to produce a new String
228 * 3) Two Buffers concatenated to produce a new Buffer
230 switch (Operand0Type
)
232 case ACPI_TYPE_INTEGER
:
234 /* Result of two Integers is a Buffer */
235 /* Need enough buffer space for two integers */
237 ReturnDesc
= AcpiUtCreateBufferObject (
238 (ACPI_SIZE
) ACPI_MUL_2 (AcpiGbl_IntegerByteWidth
));
241 Status
= AE_NO_MEMORY
;
245 Buffer
= (char *) ReturnDesc
->Buffer
.Pointer
;
247 /* Copy the first integer, LSB first */
249 memcpy (Buffer
, &Operand0
->Integer
.Value
,
250 AcpiGbl_IntegerByteWidth
);
252 /* Copy the second integer (LSB first) after the first */
254 memcpy (Buffer
+ AcpiGbl_IntegerByteWidth
,
255 &LocalOperand1
->Integer
.Value
, AcpiGbl_IntegerByteWidth
);
258 case ACPI_TYPE_STRING
:
260 /* Result of two Strings is a String */
262 ReturnDesc
= AcpiUtCreateStringObject (
263 ((ACPI_SIZE
) LocalOperand0
->String
.Length
+
264 LocalOperand1
->String
.Length
));
267 Status
= AE_NO_MEMORY
;
271 Buffer
= ReturnDesc
->String
.Pointer
;
273 /* Concatenate the strings */
275 strcpy (Buffer
, LocalOperand0
->String
.Pointer
);
276 strcat (Buffer
, LocalOperand1
->String
.Pointer
);
279 case ACPI_TYPE_BUFFER
:
281 /* Result of two Buffers is a Buffer */
283 ReturnDesc
= AcpiUtCreateBufferObject (
284 ((ACPI_SIZE
) Operand0
->Buffer
.Length
+
285 LocalOperand1
->Buffer
.Length
));
288 Status
= AE_NO_MEMORY
;
292 Buffer
= (char *) ReturnDesc
->Buffer
.Pointer
;
294 /* Concatenate the buffers */
296 memcpy (Buffer
, Operand0
->Buffer
.Pointer
,
297 Operand0
->Buffer
.Length
);
298 memcpy (Buffer
+ Operand0
->Buffer
.Length
,
299 LocalOperand1
->Buffer
.Pointer
,
300 LocalOperand1
->Buffer
.Length
);
305 /* Invalid object type, should not happen here */
307 ACPI_ERROR ((AE_INFO
, "Invalid object type: 0x%X",
308 Operand0
->Common
.Type
));
309 Status
= AE_AML_INTERNAL
;
313 *ActualReturnDesc
= ReturnDesc
;
316 if (LocalOperand0
!= Operand0
)
318 AcpiUtRemoveReference (LocalOperand0
);
321 if (LocalOperand1
!= Operand1
)
323 AcpiUtRemoveReference (LocalOperand1
);
326 return_ACPI_STATUS (Status
);
330 /*******************************************************************************
332 * FUNCTION: AcpiExConvertToObjectTypeString
334 * PARAMETERS: ObjDesc - Object to be converted
335 * ReturnDesc - Where to place the return object
339 * DESCRIPTION: Convert an object of arbitrary type to a string object that
340 * contains the namestring for the object. Used for the
341 * concatenate operator.
343 ******************************************************************************/
346 AcpiExConvertToObjectTypeString (
347 ACPI_OPERAND_OBJECT
*ObjDesc
,
348 ACPI_OPERAND_OBJECT
**ResultDesc
)
350 ACPI_OPERAND_OBJECT
*ReturnDesc
;
351 const char *TypeString
;
354 TypeString
= AcpiUtGetTypeName (ObjDesc
->Common
.Type
);
356 ReturnDesc
= AcpiUtCreateStringObject (
357 ((ACPI_SIZE
) strlen (TypeString
) + 9)); /* 9 For "[ Object]" */
360 return (AE_NO_MEMORY
);
363 strcpy (ReturnDesc
->String
.Pointer
, "[");
364 strcat (ReturnDesc
->String
.Pointer
, TypeString
);
365 strcat (ReturnDesc
->String
.Pointer
, " Object]");
367 *ResultDesc
= ReturnDesc
;
372 /*******************************************************************************
374 * FUNCTION: AcpiExConcatTemplate
376 * PARAMETERS: Operand0 - First source object
377 * Operand1 - Second source object
378 * ActualReturnDesc - Where to place the return object
379 * WalkState - Current walk state
383 * DESCRIPTION: Concatenate two resource templates
385 ******************************************************************************/
388 AcpiExConcatTemplate (
389 ACPI_OPERAND_OBJECT
*Operand0
,
390 ACPI_OPERAND_OBJECT
*Operand1
,
391 ACPI_OPERAND_OBJECT
**ActualReturnDesc
,
392 ACPI_WALK_STATE
*WalkState
)
395 ACPI_OPERAND_OBJECT
*ReturnDesc
;
403 ACPI_FUNCTION_TRACE (ExConcatTemplate
);
407 * Find the EndTag descriptor in each resource template.
408 * Note1: returned pointers point TO the EndTag, not past it.
409 * Note2: zero-length buffers are allowed; treated like one EndTag
412 /* Get the length of the first resource template */
414 Status
= AcpiUtGetResourceEndTag (Operand0
, &EndTag
);
415 if (ACPI_FAILURE (Status
))
417 return_ACPI_STATUS (Status
);
420 Length0
= ACPI_PTR_DIFF (EndTag
, Operand0
->Buffer
.Pointer
);
422 /* Get the length of the second resource template */
424 Status
= AcpiUtGetResourceEndTag (Operand1
, &EndTag
);
425 if (ACPI_FAILURE (Status
))
427 return_ACPI_STATUS (Status
);
430 Length1
= ACPI_PTR_DIFF (EndTag
, Operand1
->Buffer
.Pointer
);
432 /* Combine both lengths, minimum size will be 2 for EndTag */
434 NewLength
= Length0
+ Length1
+ sizeof (AML_RESOURCE_END_TAG
);
436 /* Create a new buffer object for the result (with one EndTag) */
438 ReturnDesc
= AcpiUtCreateBufferObject (NewLength
);
441 return_ACPI_STATUS (AE_NO_MEMORY
);
445 * Copy the templates to the new buffer, 0 first, then 1 follows. One
446 * EndTag descriptor is copied from Operand1.
448 NewBuf
= ReturnDesc
->Buffer
.Pointer
;
449 memcpy (NewBuf
, Operand0
->Buffer
.Pointer
, Length0
);
450 memcpy (NewBuf
+ Length0
, Operand1
->Buffer
.Pointer
, Length1
);
452 /* Insert EndTag and set the checksum to zero, means "ignore checksum" */
454 NewBuf
[NewLength
- 1] = 0;
455 NewBuf
[NewLength
- 2] = ACPI_RESOURCE_NAME_END_TAG
| 1;
457 /* Return the completed resource template */
459 *ActualReturnDesc
= ReturnDesc
;
460 return_ACPI_STATUS (AE_OK
);