xref: /freebsd/sys/contrib/dev/acpica/components/namespace/nsconvert.c (revision a98ff317388a00b992f1bf8404dee596f9383f5e)
1 /******************************************************************************
2  *
3  * Module Name: nsconvert - Object conversions for objects returned by
4  *                          predefined methods
5  *
6  *****************************************************************************/
7 
8 /*
9  * Copyright (C) 2000 - 2013, Intel Corp.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44 
45 #define __NSCONVERT_C__
46 
47 #include <contrib/dev/acpica/include/acpi.h>
48 #include <contrib/dev/acpica/include/accommon.h>
49 #include <contrib/dev/acpica/include/acnamesp.h>
50 #include <contrib/dev/acpica/include/acinterp.h>
51 #include <contrib/dev/acpica/include/acpredef.h>
52 #include <contrib/dev/acpica/include/amlresrc.h>
53 
54 #define _COMPONENT          ACPI_NAMESPACE
55         ACPI_MODULE_NAME    ("nsconvert")
56 
57 
58 /*******************************************************************************
59  *
60  * FUNCTION:    AcpiNsConvertToInteger
61  *
62  * PARAMETERS:  OriginalObject      - Object to be converted
63  *              ReturnObject        - Where the new converted object is returned
64  *
65  * RETURN:      Status. AE_OK if conversion was successful.
66  *
67  * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
68  *
69  ******************************************************************************/
70 
71 ACPI_STATUS
72 AcpiNsConvertToInteger (
73     ACPI_OPERAND_OBJECT     *OriginalObject,
74     ACPI_OPERAND_OBJECT     **ReturnObject)
75 {
76     ACPI_OPERAND_OBJECT     *NewObject;
77     ACPI_STATUS             Status;
78     UINT64                  Value = 0;
79     UINT32                  i;
80 
81 
82     switch (OriginalObject->Common.Type)
83     {
84     case ACPI_TYPE_STRING:
85 
86         /* String-to-Integer conversion */
87 
88         Status = AcpiUtStrtoul64 (OriginalObject->String.Pointer,
89                     ACPI_ANY_BASE, &Value);
90         if (ACPI_FAILURE (Status))
91         {
92             return (Status);
93         }
94         break;
95 
96     case ACPI_TYPE_BUFFER:
97 
98         /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
99 
100         if (OriginalObject->Buffer.Length > 8)
101         {
102             return (AE_AML_OPERAND_TYPE);
103         }
104 
105         /* Extract each buffer byte to create the integer */
106 
107         for (i = 0; i < OriginalObject->Buffer.Length; i++)
108         {
109             Value |= ((UINT64) OriginalObject->Buffer.Pointer[i] << (i * 8));
110         }
111         break;
112 
113     default:
114 
115         return (AE_AML_OPERAND_TYPE);
116     }
117 
118     NewObject = AcpiUtCreateIntegerObject (Value);
119     if (!NewObject)
120     {
121         return (AE_NO_MEMORY);
122     }
123 
124     *ReturnObject = NewObject;
125     return (AE_OK);
126 }
127 
128 
129 /*******************************************************************************
130  *
131  * FUNCTION:    AcpiNsConvertToString
132  *
133  * PARAMETERS:  OriginalObject      - Object to be converted
134  *              ReturnObject        - Where the new converted object is returned
135  *
136  * RETURN:      Status. AE_OK if conversion was successful.
137  *
138  * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
139  *
140  ******************************************************************************/
141 
142 ACPI_STATUS
143 AcpiNsConvertToString (
144     ACPI_OPERAND_OBJECT     *OriginalObject,
145     ACPI_OPERAND_OBJECT     **ReturnObject)
146 {
147     ACPI_OPERAND_OBJECT     *NewObject;
148     ACPI_SIZE               Length;
149     ACPI_STATUS             Status;
150 
151 
152     switch (OriginalObject->Common.Type)
153     {
154     case ACPI_TYPE_INTEGER:
155         /*
156          * Integer-to-String conversion. Commonly, convert
157          * an integer of value 0 to a NULL string. The last element of
158          * _BIF and _BIX packages occasionally need this fix.
159          */
160         if (OriginalObject->Integer.Value == 0)
161         {
162             /* Allocate a new NULL string object */
163 
164             NewObject = AcpiUtCreateStringObject (0);
165             if (!NewObject)
166             {
167                 return (AE_NO_MEMORY);
168             }
169         }
170         else
171         {
172             Status = AcpiExConvertToString (OriginalObject, &NewObject,
173                         ACPI_IMPLICIT_CONVERT_HEX);
174             if (ACPI_FAILURE (Status))
175             {
176                 return (Status);
177             }
178         }
179         break;
180 
181     case ACPI_TYPE_BUFFER:
182         /*
183          * Buffer-to-String conversion. Use a ToString
184          * conversion, no transform performed on the buffer data. The best
185          * example of this is the _BIF method, where the string data from
186          * the battery is often (incorrectly) returned as buffer object(s).
187          */
188         Length = 0;
189         while ((Length < OriginalObject->Buffer.Length) &&
190                 (OriginalObject->Buffer.Pointer[Length]))
191         {
192             Length++;
193         }
194 
195         /* Allocate a new string object */
196 
197         NewObject = AcpiUtCreateStringObject (Length);
198         if (!NewObject)
199         {
200             return (AE_NO_MEMORY);
201         }
202 
203         /*
204          * Copy the raw buffer data with no transform. String is already NULL
205          * terminated at Length+1.
206          */
207         ACPI_MEMCPY (NewObject->String.Pointer,
208             OriginalObject->Buffer.Pointer, Length);
209         break;
210 
211     default:
212 
213         return (AE_AML_OPERAND_TYPE);
214     }
215 
216     *ReturnObject = NewObject;
217     return (AE_OK);
218 }
219 
220 
221 /*******************************************************************************
222  *
223  * FUNCTION:    AcpiNsConvertToBuffer
224  *
225  * PARAMETERS:  OriginalObject      - Object to be converted
226  *              ReturnObject        - Where the new converted object is returned
227  *
228  * RETURN:      Status. AE_OK if conversion was successful.
229  *
230  * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
231  *
232  ******************************************************************************/
233 
234 ACPI_STATUS
235 AcpiNsConvertToBuffer (
236     ACPI_OPERAND_OBJECT     *OriginalObject,
237     ACPI_OPERAND_OBJECT     **ReturnObject)
238 {
239     ACPI_OPERAND_OBJECT     *NewObject;
240     ACPI_STATUS             Status;
241     ACPI_OPERAND_OBJECT     **Elements;
242     UINT32                  *DwordBuffer;
243     UINT32                  Count;
244     UINT32                  i;
245 
246 
247     switch (OriginalObject->Common.Type)
248     {
249     case ACPI_TYPE_INTEGER:
250         /*
251          * Integer-to-Buffer conversion.
252          * Convert the Integer to a packed-byte buffer. _MAT and other
253          * objects need this sometimes, if a read has been performed on a
254          * Field object that is less than or equal to the global integer
255          * size (32 or 64 bits).
256          */
257         Status = AcpiExConvertToBuffer (OriginalObject, &NewObject);
258         if (ACPI_FAILURE (Status))
259         {
260             return (Status);
261         }
262         break;
263 
264     case ACPI_TYPE_STRING:
265 
266         /* String-to-Buffer conversion. Simple data copy */
267 
268         NewObject = AcpiUtCreateBufferObject (OriginalObject->String.Length);
269         if (!NewObject)
270         {
271             return (AE_NO_MEMORY);
272         }
273 
274         ACPI_MEMCPY (NewObject->Buffer.Pointer,
275             OriginalObject->String.Pointer, OriginalObject->String.Length);
276         break;
277 
278     case ACPI_TYPE_PACKAGE:
279         /*
280          * This case is often seen for predefined names that must return a
281          * Buffer object with multiple DWORD integers within. For example,
282          * _FDE and _GTM. The Package can be converted to a Buffer.
283          */
284 
285         /* All elements of the Package must be integers */
286 
287         Elements = OriginalObject->Package.Elements;
288         Count = OriginalObject->Package.Count;
289 
290         for (i = 0; i < Count; i++)
291         {
292             if ((!*Elements) ||
293                 ((*Elements)->Common.Type != ACPI_TYPE_INTEGER))
294             {
295                 return (AE_AML_OPERAND_TYPE);
296             }
297             Elements++;
298         }
299 
300         /* Create the new buffer object to replace the Package */
301 
302         NewObject = AcpiUtCreateBufferObject (ACPI_MUL_4 (Count));
303         if (!NewObject)
304         {
305             return (AE_NO_MEMORY);
306         }
307 
308         /* Copy the package elements (integers) to the buffer as DWORDs */
309 
310         Elements = OriginalObject->Package.Elements;
311         DwordBuffer = ACPI_CAST_PTR (UINT32, NewObject->Buffer.Pointer);
312 
313         for (i = 0; i < Count; i++)
314         {
315             *DwordBuffer = (UINT32) (*Elements)->Integer.Value;
316             DwordBuffer++;
317             Elements++;
318         }
319         break;
320 
321     default:
322 
323         return (AE_AML_OPERAND_TYPE);
324     }
325 
326     *ReturnObject = NewObject;
327     return (AE_OK);
328 }
329 
330 
331 /*******************************************************************************
332  *
333  * FUNCTION:    AcpiNsConvertToUnicode
334  *
335  * PARAMETERS:  OriginalObject      - ASCII String Object to be converted
336  *              ReturnObject        - Where the new converted object is returned
337  *
338  * RETURN:      Status. AE_OK if conversion was successful.
339  *
340  * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer.
341  *
342  ******************************************************************************/
343 
344 ACPI_STATUS
345 AcpiNsConvertToUnicode (
346     ACPI_OPERAND_OBJECT     *OriginalObject,
347     ACPI_OPERAND_OBJECT     **ReturnObject)
348 {
349     ACPI_OPERAND_OBJECT     *NewObject;
350     char                    *AsciiString;
351     UINT16                  *UnicodeBuffer;
352     UINT32                  UnicodeLength;
353     UINT32                  i;
354 
355 
356     if (!OriginalObject)
357     {
358         return (AE_OK);
359     }
360 
361     /* If a Buffer was returned, it must be at least two bytes long */
362 
363     if (OriginalObject->Common.Type == ACPI_TYPE_BUFFER)
364     {
365         if (OriginalObject->Buffer.Length < 2)
366         {
367             return (AE_AML_OPERAND_VALUE);
368         }
369 
370         *ReturnObject = NULL;
371         return (AE_OK);
372     }
373 
374     /*
375      * The original object is an ASCII string. Convert this string to
376      * a unicode buffer.
377      */
378     AsciiString = OriginalObject->String.Pointer;
379     UnicodeLength = (OriginalObject->String.Length * 2) + 2;
380 
381     /* Create a new buffer object for the Unicode data */
382 
383     NewObject = AcpiUtCreateBufferObject (UnicodeLength);
384     if (!NewObject)
385     {
386         return (AE_NO_MEMORY);
387     }
388 
389     UnicodeBuffer = ACPI_CAST_PTR (UINT16, NewObject->Buffer.Pointer);
390 
391     /* Convert ASCII to Unicode */
392 
393     for (i = 0; i < OriginalObject->String.Length; i++)
394     {
395         UnicodeBuffer[i] = (UINT16) AsciiString[i];
396     }
397 
398     *ReturnObject = NewObject;
399     return (AE_OK);
400 }
401 
402 
403 /*******************************************************************************
404  *
405  * FUNCTION:    AcpiNsConvertToResource
406  *
407  * PARAMETERS:  OriginalObject      - Object to be converted
408  *              ReturnObject        - Where the new converted object is returned
409  *
410  * RETURN:      Status. AE_OK if conversion was successful
411  *
412  * DESCRIPTION: Attempt to convert a Integer object to a ResourceTemplate
413  *              Buffer.
414  *
415  ******************************************************************************/
416 
417 ACPI_STATUS
418 AcpiNsConvertToResource (
419     ACPI_OPERAND_OBJECT     *OriginalObject,
420     ACPI_OPERAND_OBJECT     **ReturnObject)
421 {
422     ACPI_OPERAND_OBJECT     *NewObject;
423     UINT8                   *Buffer;
424 
425 
426     /*
427      * We can fix the following cases for an expected resource template:
428      * 1. No return value (interpreter slack mode is disabled)
429      * 2. A "Return (Zero)" statement
430      * 3. A "Return empty buffer" statement
431      *
432      * We will return a buffer containing a single EndTag
433      * resource descriptor.
434      */
435     if (OriginalObject)
436     {
437         switch (OriginalObject->Common.Type)
438         {
439         case ACPI_TYPE_INTEGER:
440 
441             /* We can only repair an Integer==0 */
442 
443             if (OriginalObject->Integer.Value)
444             {
445                 return (AE_AML_OPERAND_TYPE);
446             }
447             break;
448 
449         case ACPI_TYPE_BUFFER:
450 
451             if (OriginalObject->Buffer.Length)
452             {
453                 /* Additional checks can be added in the future */
454 
455                 *ReturnObject = NULL;
456                 return (AE_OK);
457             }
458             break;
459 
460         case ACPI_TYPE_STRING:
461         default:
462 
463             return (AE_AML_OPERAND_TYPE);
464         }
465     }
466 
467     /* Create the new buffer object for the resource descriptor */
468 
469     NewObject = AcpiUtCreateBufferObject (2);
470     if (!NewObject)
471     {
472         return (AE_NO_MEMORY);
473     }
474 
475     Buffer = ACPI_CAST_PTR (UINT8, NewObject->Buffer.Pointer);
476 
477     /* Initialize the Buffer with a single EndTag descriptor */
478 
479     Buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);
480     Buffer[1] = 0x00;
481 
482     *ReturnObject = NewObject;
483     return (AE_OK);
484 }
485