xref: /titanic_44/usr/src/uts/intel/io/acpica/namespace/nsconvert.c (revision 940c61f284366ef6845abe1c4002504280d7f0f2)
1 /******************************************************************************
2  *
3  * Module Name: nsconvert - Object conversions for objects returned by
4  *                          predefined methods
5  *
6  *****************************************************************************/
7 
8 /*
9  * Copyright (C) 2000 - 2016, 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 #include "acpi.h"
46 #include "accommon.h"
47 #include "acnamesp.h"
48 #include "acinterp.h"
49 #include "acpredef.h"
50 #include "amlresrc.h"
51 
52 #define _COMPONENT          ACPI_NAMESPACE
53         ACPI_MODULE_NAME    ("nsconvert")
54 
55 
56 /*******************************************************************************
57  *
58  * FUNCTION:    AcpiNsConvertToInteger
59  *
60  * PARAMETERS:  OriginalObject      - Object to be converted
61  *              ReturnObject        - Where the new converted object is returned
62  *
63  * RETURN:      Status. AE_OK if conversion was successful.
64  *
65  * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
66  *
67  ******************************************************************************/
68 
69 ACPI_STATUS
70 AcpiNsConvertToInteger (
71     ACPI_OPERAND_OBJECT     *OriginalObject,
72     ACPI_OPERAND_OBJECT     **ReturnObject)
73 {
74     ACPI_OPERAND_OBJECT     *NewObject;
75     ACPI_STATUS             Status;
76     UINT64                  Value = 0;
77     UINT32                  i;
78 
79 
80     switch (OriginalObject->Common.Type)
81     {
82     case ACPI_TYPE_STRING:
83 
84         /* String-to-Integer conversion */
85 
86         Status = AcpiUtStrtoul64 (OriginalObject->String.Pointer,
87             ACPI_ANY_BASE, AcpiGbl_IntegerByteWidth, &Value);
88         if (ACPI_FAILURE (Status))
89         {
90             return (Status);
91         }
92         break;
93 
94     case ACPI_TYPE_BUFFER:
95 
96         /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
97 
98         if (OriginalObject->Buffer.Length > 8)
99         {
100             return (AE_AML_OPERAND_TYPE);
101         }
102 
103         /* Extract each buffer byte to create the integer */
104 
105         for (i = 0; i < OriginalObject->Buffer.Length; i++)
106         {
107             Value |= ((UINT64)
108                 OriginalObject->Buffer.Pointer[i] << (i * 8));
109         }
110         break;
111 
112     default:
113 
114         return (AE_AML_OPERAND_TYPE);
115     }
116 
117     NewObject = AcpiUtCreateIntegerObject (Value);
118     if (!NewObject)
119     {
120         return (AE_NO_MEMORY);
121     }
122 
123     *ReturnObject = NewObject;
124     return (AE_OK);
125 }
126 
127 
128 /*******************************************************************************
129  *
130  * FUNCTION:    AcpiNsConvertToString
131  *
132  * PARAMETERS:  OriginalObject      - Object to be converted
133  *              ReturnObject        - Where the new converted object is returned
134  *
135  * RETURN:      Status. AE_OK if conversion was successful.
136  *
137  * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
138  *
139  ******************************************************************************/
140 
141 ACPI_STATUS
142 AcpiNsConvertToString (
143     ACPI_OPERAND_OBJECT     *OriginalObject,
144     ACPI_OPERAND_OBJECT     **ReturnObject)
145 {
146     ACPI_OPERAND_OBJECT     *NewObject;
147     ACPI_SIZE               Length;
148     ACPI_STATUS             Status;
149 
150 
151     switch (OriginalObject->Common.Type)
152     {
153     case ACPI_TYPE_INTEGER:
154         /*
155          * Integer-to-String conversion. Commonly, convert
156          * an integer of value 0 to a NULL string. The last element of
157          * _BIF and _BIX packages occasionally need this fix.
158          */
159         if (OriginalObject->Integer.Value == 0)
160         {
161             /* Allocate a new NULL string object */
162 
163             NewObject = AcpiUtCreateStringObject (0);
164             if (!NewObject)
165             {
166                 return (AE_NO_MEMORY);
167             }
168         }
169         else
170         {
171             Status = AcpiExConvertToString (OriginalObject,
172                 &NewObject, ACPI_IMPLICIT_CONVERT_HEX);
173             if (ACPI_FAILURE (Status))
174             {
175                 return (Status);
176             }
177         }
178         break;
179 
180     case ACPI_TYPE_BUFFER:
181         /*
182          * Buffer-to-String conversion. Use a ToString
183          * conversion, no transform performed on the buffer data. The best
184          * example of this is the _BIF method, where the string data from
185          * the battery is often (incorrectly) returned as buffer object(s).
186          */
187         Length = 0;
188         while ((Length < OriginalObject->Buffer.Length) &&
189                 (OriginalObject->Buffer.Pointer[Length]))
190         {
191             Length++;
192         }
193 
194         /* Allocate a new string object */
195 
196         NewObject = AcpiUtCreateStringObject (Length);
197         if (!NewObject)
198         {
199             return (AE_NO_MEMORY);
200         }
201 
202         /*
203          * Copy the raw buffer data with no transform. String is already NULL
204          * terminated at Length+1.
205          */
206         memcpy (NewObject->String.Pointer,
207             OriginalObject->Buffer.Pointer, Length);
208         break;
209 
210     default:
211 
212         return (AE_AML_OPERAND_TYPE);
213     }
214 
215     *ReturnObject = NewObject;
216     return (AE_OK);
217 }
218 
219 
220 /*******************************************************************************
221  *
222  * FUNCTION:    AcpiNsConvertToBuffer
223  *
224  * PARAMETERS:  OriginalObject      - Object to be converted
225  *              ReturnObject        - Where the new converted object is returned
226  *
227  * RETURN:      Status. AE_OK if conversion was successful.
228  *
229  * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
230  *
231  ******************************************************************************/
232 
233 ACPI_STATUS
234 AcpiNsConvertToBuffer (
235     ACPI_OPERAND_OBJECT     *OriginalObject,
236     ACPI_OPERAND_OBJECT     **ReturnObject)
237 {
238     ACPI_OPERAND_OBJECT     *NewObject;
239     ACPI_STATUS             Status;
240     ACPI_OPERAND_OBJECT     **Elements;
241     UINT32                  *DwordBuffer;
242     UINT32                  Count;
243     UINT32                  i;
244 
245 
246     switch (OriginalObject->Common.Type)
247     {
248     case ACPI_TYPE_INTEGER:
249         /*
250          * Integer-to-Buffer conversion.
251          * Convert the Integer to a packed-byte buffer. _MAT and other
252          * objects need this sometimes, if a read has been performed on a
253          * Field object that is less than or equal to the global integer
254          * size (32 or 64 bits).
255          */
256         Status = AcpiExConvertToBuffer (OriginalObject, &NewObject);
257         if (ACPI_FAILURE (Status))
258         {
259             return (Status);
260         }
261         break;
262 
263     case ACPI_TYPE_STRING:
264 
265         /* String-to-Buffer conversion. Simple data copy */
266 
267         NewObject = AcpiUtCreateBufferObject
268             (OriginalObject->String.Length);
269         if (!NewObject)
270         {
271             return (AE_NO_MEMORY);
272         }
273 
274         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:  Scope               - Namespace node for the method/object
336  *              OriginalObject      - ASCII String Object to be converted
337  *              ReturnObject        - Where the new converted object is returned
338  *
339  * RETURN:      Status. AE_OK if conversion was successful.
340  *
341  * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer.
342  *
343  ******************************************************************************/
344 
345 ACPI_STATUS
346 AcpiNsConvertToUnicode (
347     ACPI_NAMESPACE_NODE     *Scope,
348     ACPI_OPERAND_OBJECT     *OriginalObject,
349     ACPI_OPERAND_OBJECT     **ReturnObject)
350 {
351     ACPI_OPERAND_OBJECT     *NewObject;
352     char                    *AsciiString;
353     UINT16                  *UnicodeBuffer;
354     UINT32                  UnicodeLength;
355     UINT32                  i;
356 
357 
358     if (!OriginalObject)
359     {
360         return (AE_OK);
361     }
362 
363     /* If a Buffer was returned, it must be at least two bytes long */
364 
365     if (OriginalObject->Common.Type == ACPI_TYPE_BUFFER)
366     {
367         if (OriginalObject->Buffer.Length < 2)
368         {
369             return (AE_AML_OPERAND_VALUE);
370         }
371 
372         *ReturnObject = NULL;
373         return (AE_OK);
374     }
375 
376     /*
377      * The original object is an ASCII string. Convert this string to
378      * a unicode buffer.
379      */
380     AsciiString = OriginalObject->String.Pointer;
381     UnicodeLength = (OriginalObject->String.Length * 2) + 2;
382 
383     /* Create a new buffer object for the Unicode data */
384 
385     NewObject = AcpiUtCreateBufferObject (UnicodeLength);
386     if (!NewObject)
387     {
388         return (AE_NO_MEMORY);
389     }
390 
391     UnicodeBuffer = ACPI_CAST_PTR (UINT16, NewObject->Buffer.Pointer);
392 
393     /* Convert ASCII to Unicode */
394 
395     for (i = 0; i < OriginalObject->String.Length; i++)
396     {
397         UnicodeBuffer[i] = (UINT16) AsciiString[i];
398     }
399 
400     *ReturnObject = NewObject;
401     return (AE_OK);
402 }
403 
404 
405 /*******************************************************************************
406  *
407  * FUNCTION:    AcpiNsConvertToResource
408  *
409  * PARAMETERS:  Scope               - Namespace node for the method/object
410  *              OriginalObject      - Object to be converted
411  *              ReturnObject        - Where the new converted object is returned
412  *
413  * RETURN:      Status. AE_OK if conversion was successful
414  *
415  * DESCRIPTION: Attempt to convert a Integer object to a ResourceTemplate
416  *              Buffer.
417  *
418  ******************************************************************************/
419 
420 ACPI_STATUS
421 AcpiNsConvertToResource (
422     ACPI_NAMESPACE_NODE     *Scope,
423     ACPI_OPERAND_OBJECT     *OriginalObject,
424     ACPI_OPERAND_OBJECT     **ReturnObject)
425 {
426     ACPI_OPERAND_OBJECT     *NewObject;
427     UINT8                   *Buffer;
428 
429 
430     /*
431      * We can fix the following cases for an expected resource template:
432      * 1. No return value (interpreter slack mode is disabled)
433      * 2. A "Return (Zero)" statement
434      * 3. A "Return empty buffer" statement
435      *
436      * We will return a buffer containing a single EndTag
437      * resource descriptor.
438      */
439     if (OriginalObject)
440     {
441         switch (OriginalObject->Common.Type)
442         {
443         case ACPI_TYPE_INTEGER:
444 
445             /* We can only repair an Integer==0 */
446 
447             if (OriginalObject->Integer.Value)
448             {
449                 return (AE_AML_OPERAND_TYPE);
450             }
451             break;
452 
453         case ACPI_TYPE_BUFFER:
454 
455             if (OriginalObject->Buffer.Length)
456             {
457                 /* Additional checks can be added in the future */
458 
459                 *ReturnObject = NULL;
460                 return (AE_OK);
461             }
462             break;
463 
464         case ACPI_TYPE_STRING:
465         default:
466 
467             return (AE_AML_OPERAND_TYPE);
468         }
469     }
470 
471     /* Create the new buffer object for the resource descriptor */
472 
473     NewObject = AcpiUtCreateBufferObject (2);
474     if (!NewObject)
475     {
476         return (AE_NO_MEMORY);
477     }
478 
479     Buffer = ACPI_CAST_PTR (UINT8, NewObject->Buffer.Pointer);
480 
481     /* Initialize the Buffer with a single EndTag descriptor */
482 
483     Buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);
484     Buffer[1] = 0x00;
485 
486     *ReturnObject = NewObject;
487     return (AE_OK);
488 }
489 
490 
491 /*******************************************************************************
492  *
493  * FUNCTION:    AcpiNsConvertToReference
494  *
495  * PARAMETERS:  Scope               - Namespace node for the method/object
496  *              OriginalObject      - Object to be converted
497  *              ReturnObject        - Where the new converted object is returned
498  *
499  * RETURN:      Status. AE_OK if conversion was successful
500  *
501  * DESCRIPTION: Attempt to convert a Integer object to a ObjectReference.
502  *              Buffer.
503  *
504  ******************************************************************************/
505 
506 ACPI_STATUS
507 AcpiNsConvertToReference (
508     ACPI_NAMESPACE_NODE     *Scope,
509     ACPI_OPERAND_OBJECT     *OriginalObject,
510     ACPI_OPERAND_OBJECT     **ReturnObject)
511 {
512     ACPI_OPERAND_OBJECT     *NewObject = NULL;
513     ACPI_STATUS             Status;
514     ACPI_NAMESPACE_NODE     *Node;
515     ACPI_GENERIC_STATE      ScopeInfo;
516     char                    *Name;
517 
518 
519     ACPI_FUNCTION_NAME (NsConvertToReference);
520 
521 
522     /* Convert path into internal presentation */
523 
524     Status = AcpiNsInternalizeName (OriginalObject->String.Pointer, &Name);
525     if (ACPI_FAILURE (Status))
526     {
527         return_ACPI_STATUS (Status);
528     }
529 
530     /* Find the namespace node */
531 
532     ScopeInfo.Scope.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Scope);
533     Status = AcpiNsLookup (&ScopeInfo, Name,
534         ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
535         ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, &Node);
536     if (ACPI_FAILURE (Status))
537     {
538         /* Check if we are resolving a named reference within a package */
539 
540         ACPI_ERROR_NAMESPACE (OriginalObject->String.Pointer, Status);
541         goto ErrorExit;
542     }
543 
544     /* Create and init a new internal ACPI object */
545 
546     NewObject = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
547     if (!NewObject)
548     {
549         Status = AE_NO_MEMORY;
550         goto ErrorExit;
551     }
552     NewObject->Reference.Node = Node;
553     NewObject->Reference.Object = Node->Object;
554     NewObject->Reference.Class = ACPI_REFCLASS_NAME;
555 
556     /*
557      * Increase reference of the object if needed (the object is likely a
558      * null for device nodes).
559      */
560     AcpiUtAddReference (Node->Object);
561 
562 ErrorExit:
563     ACPI_FREE (Name);
564     *ReturnObject = NewObject;
565     return (AE_OK);
566 }
567