xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/executer/exconcat.c (revision 8a6724a0ee3803f1e9f487d8111bb3f6cb8d16db)
1 /******************************************************************************
2  *
3  * Module Name: exconcat - Concatenate-type AML operators
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2016, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86 
87  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89  * PARTICULAR PURPOSE.
90  *
91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98  * LIMITED REMEDY.
99  *
100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
101  * software or system incorporating such software without first obtaining any
102  * required license or other approval from the U. S. Department of Commerce or
103  * any other agency or department of the United States Government. In the
104  * event Licensee exports any such software from the United States or
105  * re-exports any such software from a foreign destination, Licensee shall
106  * ensure that the distribution and export/re-export of the software is in
107  * compliance with all laws, regulations, orders, or other restrictions of the
108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109  * any of its subsidiaries will export/re-export any technical data, process,
110  * software, or service, directly or indirectly, to any country for which the
111  * United States government or any agency thereof requires an export license,
112  * other governmental approval, or letter of assurance, without first obtaining
113  * such license, approval or letter.
114  *
115  *****************************************************************************/
116 
117 #include "acpi.h"
118 #include "accommon.h"
119 #include "acinterp.h"
120 #include "amlresrc.h"
121 
122 
123 #define _COMPONENT          ACPI_EXECUTER
124         ACPI_MODULE_NAME    ("exconcat")
125 
126 /* Local Prototypes */
127 
128 static ACPI_STATUS
129 AcpiExConvertToObjectTypeString (
130     ACPI_OPERAND_OBJECT     *ObjDesc,
131     ACPI_OPERAND_OBJECT     **ResultDesc);
132 
133 
134 /*******************************************************************************
135  *
136  * FUNCTION:    AcpiExDoConcatenate
137  *
138  * PARAMETERS:  Operand0            - First source object
139  *              Operand1            - Second source object
140  *              ActualReturnDesc    - Where to place the return object
141  *              WalkState           - Current walk state
142  *
143  * RETURN:      Status
144  *
145  * DESCRIPTION: Concatenate two objects with the ACPI-defined conversion
146  *              rules as necessary.
147  * NOTE:
148  * Per the ACPI spec (up to 6.1), Concatenate only supports Integer,
149  * String, and Buffer objects. However, we support all objects here
150  * as an extension. This improves the usefulness of both Concatenate
151  * and the Printf/Fprintf macros. The extension returns a string
152  * describing the object type for the other objects.
153  * 02/2016.
154  *
155  ******************************************************************************/
156 
157 ACPI_STATUS
158 AcpiExDoConcatenate (
159     ACPI_OPERAND_OBJECT     *Operand0,
160     ACPI_OPERAND_OBJECT     *Operand1,
161     ACPI_OPERAND_OBJECT     **ActualReturnDesc,
162     ACPI_WALK_STATE         *WalkState)
163 {
164     ACPI_OPERAND_OBJECT     *LocalOperand0 = Operand0;
165     ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
166     ACPI_OPERAND_OBJECT     *TempOperand1 = NULL;
167     ACPI_OPERAND_OBJECT     *ReturnDesc;
168     char                    *Buffer;
169     ACPI_OBJECT_TYPE        Operand0Type;
170     ACPI_OBJECT_TYPE        Operand1Type;
171     ACPI_STATUS             Status;
172 
173 
174     ACPI_FUNCTION_TRACE (ExDoConcatenate);
175 
176 
177     /* Operand 0 preprocessing */
178 
179     switch (Operand0->Common.Type)
180     {
181     case ACPI_TYPE_INTEGER:
182     case ACPI_TYPE_STRING:
183     case ACPI_TYPE_BUFFER:
184 
185         Operand0Type = Operand0->Common.Type;
186         break;
187 
188     default:
189 
190         /* For all other types, get the "object type" string */
191 
192         Status = AcpiExConvertToObjectTypeString (
193             Operand0, &LocalOperand0);
194         if (ACPI_FAILURE (Status))
195         {
196             goto Cleanup;
197         }
198 
199         Operand0Type = ACPI_TYPE_STRING;
200         break;
201     }
202 
203     /* Operand 1 preprocessing */
204 
205     switch (Operand1->Common.Type)
206     {
207     case ACPI_TYPE_INTEGER:
208     case ACPI_TYPE_STRING:
209     case ACPI_TYPE_BUFFER:
210 
211         Operand1Type = Operand1->Common.Type;
212         break;
213 
214     default:
215 
216         /* For all other types, get the "object type" string */
217 
218         Status = AcpiExConvertToObjectTypeString (
219             Operand1, &LocalOperand1);
220         if (ACPI_FAILURE (Status))
221         {
222             goto Cleanup;
223         }
224 
225         Operand1Type = ACPI_TYPE_STRING;
226         break;
227     }
228 
229     /*
230      * Convert the second operand if necessary. The first operand (0)
231      * determines the type of the second operand (1) (See the Data Types
232      * section of the ACPI specification). Both object types are
233      * guaranteed to be either Integer/String/Buffer by the operand
234      * resolution mechanism.
235      */
236     switch (Operand0Type)
237     {
238     case ACPI_TYPE_INTEGER:
239 
240         Status = AcpiExConvertToInteger (LocalOperand1, &TempOperand1, 16);
241         break;
242 
243     case ACPI_TYPE_BUFFER:
244 
245         Status = AcpiExConvertToBuffer (LocalOperand1, &TempOperand1);
246         break;
247 
248     case ACPI_TYPE_STRING:
249 
250         switch (Operand1Type)
251         {
252         case ACPI_TYPE_INTEGER:
253         case ACPI_TYPE_STRING:
254         case ACPI_TYPE_BUFFER:
255 
256             /* Other types have already been converted to string */
257 
258             Status = AcpiExConvertToString (
259                 LocalOperand1, &TempOperand1, ACPI_IMPLICIT_CONVERT_HEX);
260             break;
261 
262         default:
263 
264             Status = AE_OK;
265             break;
266         }
267         break;
268 
269     default:
270 
271         ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X",
272             Operand0->Common.Type));
273         Status = AE_AML_INTERNAL;
274     }
275 
276     if (ACPI_FAILURE (Status))
277     {
278         goto Cleanup;
279     }
280 
281     /* Take care with any newly created operand objects */
282 
283     if ((LocalOperand1 != Operand1) &&
284         (LocalOperand1 != TempOperand1))
285     {
286         AcpiUtRemoveReference (LocalOperand1);
287     }
288 
289     LocalOperand1 = TempOperand1;
290 
291     /*
292      * Both operands are now known to be the same object type
293      * (Both are Integer, String, or Buffer), and we can now perform
294      * the concatenation.
295      *
296      * There are three cases to handle, as per the ACPI spec:
297      *
298      * 1) Two Integers concatenated to produce a new Buffer
299      * 2) Two Strings concatenated to produce a new String
300      * 3) Two Buffers concatenated to produce a new Buffer
301      */
302     switch (Operand0Type)
303     {
304     case ACPI_TYPE_INTEGER:
305 
306         /* Result of two Integers is a Buffer */
307         /* Need enough buffer space for two integers */
308 
309         ReturnDesc = AcpiUtCreateBufferObject (
310             (ACPI_SIZE) ACPI_MUL_2 (AcpiGbl_IntegerByteWidth));
311         if (!ReturnDesc)
312         {
313             Status = AE_NO_MEMORY;
314             goto Cleanup;
315         }
316 
317         Buffer = (char *) ReturnDesc->Buffer.Pointer;
318 
319         /* Copy the first integer, LSB first */
320 
321         memcpy (Buffer, &Operand0->Integer.Value,
322             AcpiGbl_IntegerByteWidth);
323 
324         /* Copy the second integer (LSB first) after the first */
325 
326         memcpy (Buffer + AcpiGbl_IntegerByteWidth,
327             &LocalOperand1->Integer.Value, AcpiGbl_IntegerByteWidth);
328         break;
329 
330     case ACPI_TYPE_STRING:
331 
332         /* Result of two Strings is a String */
333 
334         ReturnDesc = AcpiUtCreateStringObject (
335             ((ACPI_SIZE) LocalOperand0->String.Length +
336             LocalOperand1->String.Length));
337         if (!ReturnDesc)
338         {
339             Status = AE_NO_MEMORY;
340             goto Cleanup;
341         }
342 
343         Buffer = ReturnDesc->String.Pointer;
344 
345         /* Concatenate the strings */
346 
347         strcpy (Buffer, LocalOperand0->String.Pointer);
348         strcat (Buffer, LocalOperand1->String.Pointer);
349         break;
350 
351     case ACPI_TYPE_BUFFER:
352 
353         /* Result of two Buffers is a Buffer */
354 
355         ReturnDesc = AcpiUtCreateBufferObject (
356             ((ACPI_SIZE) Operand0->Buffer.Length +
357             LocalOperand1->Buffer.Length));
358         if (!ReturnDesc)
359         {
360             Status = AE_NO_MEMORY;
361             goto Cleanup;
362         }
363 
364         Buffer = (char *) ReturnDesc->Buffer.Pointer;
365 
366         /* Concatenate the buffers */
367 
368         memcpy (Buffer, Operand0->Buffer.Pointer,
369             Operand0->Buffer.Length);
370         memcpy (Buffer + Operand0->Buffer.Length,
371             LocalOperand1->Buffer.Pointer,
372             LocalOperand1->Buffer.Length);
373         break;
374 
375     default:
376 
377         /* Invalid object type, should not happen here */
378 
379         ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X",
380             Operand0->Common.Type));
381         Status = AE_AML_INTERNAL;
382         goto Cleanup;
383     }
384 
385     *ActualReturnDesc = ReturnDesc;
386 
387 Cleanup:
388     if (LocalOperand0 != Operand0)
389     {
390         AcpiUtRemoveReference (LocalOperand0);
391     }
392 
393     if (LocalOperand1 != Operand1)
394     {
395         AcpiUtRemoveReference (LocalOperand1);
396     }
397 
398     return_ACPI_STATUS (Status);
399 }
400 
401 
402 /*******************************************************************************
403  *
404  * FUNCTION:    AcpiExConvertToObjectTypeString
405  *
406  * PARAMETERS:  ObjDesc             - Object to be converted
407  *              ReturnDesc          - Where to place the return object
408  *
409  * RETURN:      Status
410  *
411  * DESCRIPTION: Convert an object of arbitrary type to a string object that
412  *              contains the namestring for the object. Used for the
413  *              concatenate operator.
414  *
415  ******************************************************************************/
416 
417 static ACPI_STATUS
418 AcpiExConvertToObjectTypeString (
419     ACPI_OPERAND_OBJECT     *ObjDesc,
420     ACPI_OPERAND_OBJECT     **ResultDesc)
421 {
422     ACPI_OPERAND_OBJECT     *ReturnDesc;
423     const char              *TypeString;
424 
425 
426     TypeString = AcpiUtGetTypeName (ObjDesc->Common.Type);
427 
428     ReturnDesc = AcpiUtCreateStringObject (
429         ((ACPI_SIZE) strlen (TypeString) + 9)); /* 9 For "[ Object]" */
430     if (!ReturnDesc)
431     {
432         return (AE_NO_MEMORY);
433     }
434 
435     strcpy (ReturnDesc->String.Pointer, "[");
436     strcat (ReturnDesc->String.Pointer, TypeString);
437     strcat (ReturnDesc->String.Pointer, " Object]");
438 
439     *ResultDesc = ReturnDesc;
440     return (AE_OK);
441 }
442 
443 
444 /*******************************************************************************
445  *
446  * FUNCTION:    AcpiExConcatTemplate
447  *
448  * PARAMETERS:  Operand0            - First source object
449  *              Operand1            - Second source object
450  *              ActualReturnDesc    - Where to place the return object
451  *              WalkState           - Current walk state
452  *
453  * RETURN:      Status
454  *
455  * DESCRIPTION: Concatenate two resource templates
456  *
457  ******************************************************************************/
458 
459 ACPI_STATUS
460 AcpiExConcatTemplate (
461     ACPI_OPERAND_OBJECT     *Operand0,
462     ACPI_OPERAND_OBJECT     *Operand1,
463     ACPI_OPERAND_OBJECT     **ActualReturnDesc,
464     ACPI_WALK_STATE         *WalkState)
465 {
466     ACPI_STATUS             Status;
467     ACPI_OPERAND_OBJECT     *ReturnDesc;
468     UINT8                   *NewBuf;
469     UINT8                   *EndTag;
470     ACPI_SIZE               Length0;
471     ACPI_SIZE               Length1;
472     ACPI_SIZE               NewLength;
473 
474 
475     ACPI_FUNCTION_TRACE (ExConcatTemplate);
476 
477 
478     /*
479      * Find the EndTag descriptor in each resource template.
480      * Note1: returned pointers point TO the EndTag, not past it.
481      * Note2: zero-length buffers are allowed; treated like one EndTag
482      */
483 
484     /* Get the length of the first resource template */
485 
486     Status = AcpiUtGetResourceEndTag (Operand0, &EndTag);
487     if (ACPI_FAILURE (Status))
488     {
489         return_ACPI_STATUS (Status);
490     }
491 
492     Length0 = ACPI_PTR_DIFF (EndTag, Operand0->Buffer.Pointer);
493 
494     /* Get the length of the second resource template */
495 
496     Status = AcpiUtGetResourceEndTag (Operand1, &EndTag);
497     if (ACPI_FAILURE (Status))
498     {
499         return_ACPI_STATUS (Status);
500     }
501 
502     Length1 = ACPI_PTR_DIFF (EndTag, Operand1->Buffer.Pointer);
503 
504     /* Combine both lengths, minimum size will be 2 for EndTag */
505 
506     NewLength = Length0 + Length1 + sizeof (AML_RESOURCE_END_TAG);
507 
508     /* Create a new buffer object for the result (with one EndTag) */
509 
510     ReturnDesc = AcpiUtCreateBufferObject (NewLength);
511     if (!ReturnDesc)
512     {
513         return_ACPI_STATUS (AE_NO_MEMORY);
514     }
515 
516     /*
517      * Copy the templates to the new buffer, 0 first, then 1 follows. One
518      * EndTag descriptor is copied from Operand1.
519      */
520     NewBuf = ReturnDesc->Buffer.Pointer;
521     memcpy (NewBuf, Operand0->Buffer.Pointer, Length0);
522     memcpy (NewBuf + Length0, Operand1->Buffer.Pointer, Length1);
523 
524     /* Insert EndTag and set the checksum to zero, means "ignore checksum" */
525 
526     NewBuf[NewLength - 1] = 0;
527     NewBuf[NewLength - 2] = ACPI_RESOURCE_NAME_END_TAG | 1;
528 
529     /* Return the completed resource template */
530 
531     *ActualReturnDesc = ReturnDesc;
532     return_ACPI_STATUS (AE_OK);
533 }
534