nsconvert.c revision 281075
1/******************************************************************************
2 *
3 * Module Name: nsconvert - Object conversions for objects returned by
4 *                          predefined methods
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2015, 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 <contrib/dev/acpica/include/acpi.h>
46#include <contrib/dev/acpica/include/accommon.h>
47#include <contrib/dev/acpica/include/acnamesp.h>
48#include <contrib/dev/acpica/include/acinterp.h>
49#include <contrib/dev/acpica/include/acpredef.h>
50#include <contrib/dev/acpica/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
69ACPI_STATUS
70AcpiNsConvertToInteger (
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, &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) OriginalObject->Buffer.Pointer[i] << (i * 8));
108        }
109        break;
110
111    default:
112
113        return (AE_AML_OPERAND_TYPE);
114    }
115
116    NewObject = AcpiUtCreateIntegerObject (Value);
117    if (!NewObject)
118    {
119        return (AE_NO_MEMORY);
120    }
121
122    *ReturnObject = NewObject;
123    return (AE_OK);
124}
125
126
127/*******************************************************************************
128 *
129 * FUNCTION:    AcpiNsConvertToString
130 *
131 * PARAMETERS:  OriginalObject      - Object to be converted
132 *              ReturnObject        - Where the new converted object is returned
133 *
134 * RETURN:      Status. AE_OK if conversion was successful.
135 *
136 * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
137 *
138 ******************************************************************************/
139
140ACPI_STATUS
141AcpiNsConvertToString (
142    ACPI_OPERAND_OBJECT     *OriginalObject,
143    ACPI_OPERAND_OBJECT     **ReturnObject)
144{
145    ACPI_OPERAND_OBJECT     *NewObject;
146    ACPI_SIZE               Length;
147    ACPI_STATUS             Status;
148
149
150    switch (OriginalObject->Common.Type)
151    {
152    case ACPI_TYPE_INTEGER:
153        /*
154         * Integer-to-String conversion. Commonly, convert
155         * an integer of value 0 to a NULL string. The last element of
156         * _BIF and _BIX packages occasionally need this fix.
157         */
158        if (OriginalObject->Integer.Value == 0)
159        {
160            /* Allocate a new NULL string object */
161
162            NewObject = AcpiUtCreateStringObject (0);
163            if (!NewObject)
164            {
165                return (AE_NO_MEMORY);
166            }
167        }
168        else
169        {
170            Status = AcpiExConvertToString (OriginalObject, &NewObject,
171                        ACPI_IMPLICIT_CONVERT_HEX);
172            if (ACPI_FAILURE (Status))
173            {
174                return (Status);
175            }
176        }
177        break;
178
179    case ACPI_TYPE_BUFFER:
180        /*
181         * Buffer-to-String conversion. Use a ToString
182         * conversion, no transform performed on the buffer data. The best
183         * example of this is the _BIF method, where the string data from
184         * the battery is often (incorrectly) returned as buffer object(s).
185         */
186        Length = 0;
187        while ((Length < OriginalObject->Buffer.Length) &&
188                (OriginalObject->Buffer.Pointer[Length]))
189        {
190            Length++;
191        }
192
193        /* Allocate a new string object */
194
195        NewObject = AcpiUtCreateStringObject (Length);
196        if (!NewObject)
197        {
198            return (AE_NO_MEMORY);
199        }
200
201        /*
202         * Copy the raw buffer data with no transform. String is already NULL
203         * terminated at Length+1.
204         */
205        ACPI_MEMCPY (NewObject->String.Pointer,
206            OriginalObject->Buffer.Pointer, Length);
207        break;
208
209    default:
210
211        return (AE_AML_OPERAND_TYPE);
212    }
213
214    *ReturnObject = NewObject;
215    return (AE_OK);
216}
217
218
219/*******************************************************************************
220 *
221 * FUNCTION:    AcpiNsConvertToBuffer
222 *
223 * PARAMETERS:  OriginalObject      - Object to be converted
224 *              ReturnObject        - Where the new converted object is returned
225 *
226 * RETURN:      Status. AE_OK if conversion was successful.
227 *
228 * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
229 *
230 ******************************************************************************/
231
232ACPI_STATUS
233AcpiNsConvertToBuffer (
234    ACPI_OPERAND_OBJECT     *OriginalObject,
235    ACPI_OPERAND_OBJECT     **ReturnObject)
236{
237    ACPI_OPERAND_OBJECT     *NewObject;
238    ACPI_STATUS             Status;
239    ACPI_OPERAND_OBJECT     **Elements;
240    UINT32                  *DwordBuffer;
241    UINT32                  Count;
242    UINT32                  i;
243
244
245    switch (OriginalObject->Common.Type)
246    {
247    case ACPI_TYPE_INTEGER:
248        /*
249         * Integer-to-Buffer conversion.
250         * Convert the Integer to a packed-byte buffer. _MAT and other
251         * objects need this sometimes, if a read has been performed on a
252         * Field object that is less than or equal to the global integer
253         * size (32 or 64 bits).
254         */
255        Status = AcpiExConvertToBuffer (OriginalObject, &NewObject);
256        if (ACPI_FAILURE (Status))
257        {
258            return (Status);
259        }
260        break;
261
262    case ACPI_TYPE_STRING:
263
264        /* String-to-Buffer conversion. Simple data copy */
265
266        NewObject = AcpiUtCreateBufferObject (OriginalObject->String.Length);
267        if (!NewObject)
268        {
269            return (AE_NO_MEMORY);
270        }
271
272        ACPI_MEMCPY (NewObject->Buffer.Pointer,
273            OriginalObject->String.Pointer, OriginalObject->String.Length);
274        break;
275
276    case ACPI_TYPE_PACKAGE:
277        /*
278         * This case is often seen for predefined names that must return a
279         * Buffer object with multiple DWORD integers within. For example,
280         * _FDE and _GTM. The Package can be converted to a Buffer.
281         */
282
283        /* All elements of the Package must be integers */
284
285        Elements = OriginalObject->Package.Elements;
286        Count = OriginalObject->Package.Count;
287
288        for (i = 0; i < Count; i++)
289        {
290            if ((!*Elements) ||
291                ((*Elements)->Common.Type != ACPI_TYPE_INTEGER))
292            {
293                return (AE_AML_OPERAND_TYPE);
294            }
295            Elements++;
296        }
297
298        /* Create the new buffer object to replace the Package */
299
300        NewObject = AcpiUtCreateBufferObject (ACPI_MUL_4 (Count));
301        if (!NewObject)
302        {
303            return (AE_NO_MEMORY);
304        }
305
306        /* Copy the package elements (integers) to the buffer as DWORDs */
307
308        Elements = OriginalObject->Package.Elements;
309        DwordBuffer = ACPI_CAST_PTR (UINT32, NewObject->Buffer.Pointer);
310
311        for (i = 0; i < Count; i++)
312        {
313            *DwordBuffer = (UINT32) (*Elements)->Integer.Value;
314            DwordBuffer++;
315            Elements++;
316        }
317        break;
318
319    default:
320
321        return (AE_AML_OPERAND_TYPE);
322    }
323
324    *ReturnObject = NewObject;
325    return (AE_OK);
326}
327
328
329/*******************************************************************************
330 *
331 * FUNCTION:    AcpiNsConvertToUnicode
332 *
333 * PARAMETERS:  OriginalObject      - ASCII String Object to be converted
334 *              ReturnObject        - Where the new converted object is returned
335 *
336 * RETURN:      Status. AE_OK if conversion was successful.
337 *
338 * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer.
339 *
340 ******************************************************************************/
341
342ACPI_STATUS
343AcpiNsConvertToUnicode (
344    ACPI_OPERAND_OBJECT     *OriginalObject,
345    ACPI_OPERAND_OBJECT     **ReturnObject)
346{
347    ACPI_OPERAND_OBJECT     *NewObject;
348    char                    *AsciiString;
349    UINT16                  *UnicodeBuffer;
350    UINT32                  UnicodeLength;
351    UINT32                  i;
352
353
354    if (!OriginalObject)
355    {
356        return (AE_OK);
357    }
358
359    /* If a Buffer was returned, it must be at least two bytes long */
360
361    if (OriginalObject->Common.Type == ACPI_TYPE_BUFFER)
362    {
363        if (OriginalObject->Buffer.Length < 2)
364        {
365            return (AE_AML_OPERAND_VALUE);
366        }
367
368        *ReturnObject = NULL;
369        return (AE_OK);
370    }
371
372    /*
373     * The original object is an ASCII string. Convert this string to
374     * a unicode buffer.
375     */
376    AsciiString = OriginalObject->String.Pointer;
377    UnicodeLength = (OriginalObject->String.Length * 2) + 2;
378
379    /* Create a new buffer object for the Unicode data */
380
381    NewObject = AcpiUtCreateBufferObject (UnicodeLength);
382    if (!NewObject)
383    {
384        return (AE_NO_MEMORY);
385    }
386
387    UnicodeBuffer = ACPI_CAST_PTR (UINT16, NewObject->Buffer.Pointer);
388
389    /* Convert ASCII to Unicode */
390
391    for (i = 0; i < OriginalObject->String.Length; i++)
392    {
393        UnicodeBuffer[i] = (UINT16) AsciiString[i];
394    }
395
396    *ReturnObject = NewObject;
397    return (AE_OK);
398}
399
400
401/*******************************************************************************
402 *
403 * FUNCTION:    AcpiNsConvertToResource
404 *
405 * PARAMETERS:  OriginalObject      - Object to be converted
406 *              ReturnObject        - Where the new converted object is returned
407 *
408 * RETURN:      Status. AE_OK if conversion was successful
409 *
410 * DESCRIPTION: Attempt to convert a Integer object to a ResourceTemplate
411 *              Buffer.
412 *
413 ******************************************************************************/
414
415ACPI_STATUS
416AcpiNsConvertToResource (
417    ACPI_OPERAND_OBJECT     *OriginalObject,
418    ACPI_OPERAND_OBJECT     **ReturnObject)
419{
420    ACPI_OPERAND_OBJECT     *NewObject;
421    UINT8                   *Buffer;
422
423
424    /*
425     * We can fix the following cases for an expected resource template:
426     * 1. No return value (interpreter slack mode is disabled)
427     * 2. A "Return (Zero)" statement
428     * 3. A "Return empty buffer" statement
429     *
430     * We will return a buffer containing a single EndTag
431     * resource descriptor.
432     */
433    if (OriginalObject)
434    {
435        switch (OriginalObject->Common.Type)
436        {
437        case ACPI_TYPE_INTEGER:
438
439            /* We can only repair an Integer==0 */
440
441            if (OriginalObject->Integer.Value)
442            {
443                return (AE_AML_OPERAND_TYPE);
444            }
445            break;
446
447        case ACPI_TYPE_BUFFER:
448
449            if (OriginalObject->Buffer.Length)
450            {
451                /* Additional checks can be added in the future */
452
453                *ReturnObject = NULL;
454                return (AE_OK);
455            }
456            break;
457
458        case ACPI_TYPE_STRING:
459        default:
460
461            return (AE_AML_OPERAND_TYPE);
462        }
463    }
464
465    /* Create the new buffer object for the resource descriptor */
466
467    NewObject = AcpiUtCreateBufferObject (2);
468    if (!NewObject)
469    {
470        return (AE_NO_MEMORY);
471    }
472
473    Buffer = ACPI_CAST_PTR (UINT8, NewObject->Buffer.Pointer);
474
475    /* Initialize the Buffer with a single EndTag descriptor */
476
477    Buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);
478    Buffer[1] = 0x00;
479
480    *ReturnObject = NewObject;
481    return (AE_OK);
482}
483