171867Smsmith/******************************************************************************
271867Smsmith *
377424Smsmith * Module Name: exconvrt - Object conversion routines
471867Smsmith *
571867Smsmith *****************************************************************************/
671867Smsmith
7217365Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
971867Smsmith * All rights reserved.
1071867Smsmith *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
2571867Smsmith *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
2971867Smsmith *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
4371867Smsmith
44193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
45193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
46193341Sjkim#include <contrib/dev/acpica/include/acinterp.h>
47193341Sjkim#include <contrib/dev/acpica/include/amlcode.h>
4871867Smsmith
4971867Smsmith
5077424Smsmith#define _COMPONENT          ACPI_EXECUTER
5191116Smsmith        ACPI_MODULE_NAME    ("exconvrt")
5271867Smsmith
53151937Sjkim/* Local prototypes */
5471867Smsmith
55151937Sjkimstatic UINT32
56151937SjkimAcpiExConvertToAscii (
57202771Sjkim    UINT64                  Integer,
58151937Sjkim    UINT16                  Base,
59151937Sjkim    UINT8                   *String,
60151937Sjkim    UINT8                   MaxLength);
61151937Sjkim
62151937Sjkim
6371867Smsmith/*******************************************************************************
6471867Smsmith *
6577424Smsmith * FUNCTION:    AcpiExConvertToInteger
6671867Smsmith *
67193267Sjkim * PARAMETERS:  ObjDesc         - Object to be converted. Must be an
6871867Smsmith *                                Integer, Buffer, or String
69126372Snjl *              ResultDesc      - Where the new Integer object is returned
70138287Smarks *              Flags           - Used for string conversion
7171867Smsmith *
7271867Smsmith * RETURN:      Status
7371867Smsmith *
7471867Smsmith * DESCRIPTION: Convert an ACPI Object to an integer.
7571867Smsmith *
7671867Smsmith ******************************************************************************/
7771867Smsmith
7871867SmsmithACPI_STATUS
7977424SmsmithAcpiExConvertToInteger (
8080062Smsmith    ACPI_OPERAND_OBJECT     *ObjDesc,
8180062Smsmith    ACPI_OPERAND_OBJECT     **ResultDesc,
82138287Smarks    UINT32                  Flags)
8371867Smsmith{
84138287Smarks    ACPI_OPERAND_OBJECT     *ReturnDesc;
85138287Smarks    UINT8                   *Pointer;
86202771Sjkim    UINT64                  Result;
8771867Smsmith    UINT32                  i;
8871867Smsmith    UINT32                  Count;
8999679Siwasaki    ACPI_STATUS             Status;
9071867Smsmith
9171867Smsmith
92167802Sjkim    ACPI_FUNCTION_TRACE_PTR (ExConvertToInteger, ObjDesc);
9383174Smsmith
9483174Smsmith
95193267Sjkim    switch (ObjDesc->Common.Type)
9671867Smsmith    {
9771867Smsmith    case ACPI_TYPE_INTEGER:
98138287Smarks
99138287Smarks        /* No conversion necessary */
100138287Smarks
10180062Smsmith        *ResultDesc = ObjDesc;
10291116Smsmith        return_ACPI_STATUS (AE_OK);
10371867Smsmith
104138287Smarks    case ACPI_TYPE_BUFFER:
10571867Smsmith    case ACPI_TYPE_STRING:
10671867Smsmith
107138287Smarks        /* Note: Takes advantage of common buffer/string fields */
108138287Smarks
10999679Siwasaki        Pointer = ObjDesc->Buffer.Pointer;
11080062Smsmith        Count   = ObjDesc->Buffer.Length;
11171867Smsmith        break;
11271867Smsmith
11371867Smsmith    default:
114250838Sjkim
11591116Smsmith        return_ACPI_STATUS (AE_TYPE);
11671867Smsmith    }
11771867Smsmith
11871867Smsmith    /*
119193267Sjkim     * Convert the buffer/string to an integer. Note that both buffers and
12071867Smsmith     * strings are treated as raw data - we don't convert ascii to hex for
12171867Smsmith     * strings.
12271867Smsmith     *
12371867Smsmith     * There are two terminating conditions for the loop:
12471867Smsmith     * 1) The size of an integer has been reached, or
12571867Smsmith     * 2) The end of the buffer or string has been reached
12671867Smsmith     */
12771867Smsmith    Result = 0;
12871867Smsmith
129151937Sjkim    /* String conversion is different than Buffer conversion */
130151937Sjkim
131193267Sjkim    switch (ObjDesc->Common.Type)
13271867Smsmith    {
13371867Smsmith    case ACPI_TYPE_STRING:
13471867Smsmith        /*
135138287Smarks         * Convert string to an integer - for most cases, the string must be
136193267Sjkim         * hexadecimal as per the ACPI specification. The only exception (as
137138287Smarks         * of ACPI 3.0) is that the ToInteger() operator allows both decimal
138138287Smarks         * and hexadecimal strings (hex prefixed with "0x").
13971867Smsmith         */
140306536Sjkim        Status = AcpiUtStrtoul64 ((char *) Pointer, Flags,
141306536Sjkim            AcpiGbl_IntegerByteWidth, &Result);
14299679Siwasaki        if (ACPI_FAILURE (Status))
14399679Siwasaki        {
14499679Siwasaki            return_ACPI_STATUS (Status);
14599679Siwasaki        }
14671867Smsmith        break;
14771867Smsmith
14871867Smsmith    case ACPI_TYPE_BUFFER:
14971867Smsmith
150151937Sjkim        /* Check for zero-length buffer */
151151937Sjkim
152151937Sjkim        if (!Count)
153151937Sjkim        {
154151937Sjkim            return_ACPI_STATUS (AE_AML_BUFFER_LIMIT);
155151937Sjkim        }
156151937Sjkim
157138287Smarks        /* Transfer no more than an integer's worth of data */
158138287Smarks
159138287Smarks        if (Count > AcpiGbl_IntegerByteWidth)
160138287Smarks        {
161138287Smarks            Count = AcpiGbl_IntegerByteWidth;
162138287Smarks        }
163138287Smarks
16471867Smsmith        /*
165138287Smarks         * Convert buffer to an integer - we simply grab enough raw data
166138287Smarks         * from the buffer to fill an integer
16771867Smsmith         */
16871867Smsmith        for (i = 0; i < Count; i++)
16971867Smsmith        {
17071867Smsmith            /*
17171867Smsmith             * Get next byte and shift it into the Result.
17271867Smsmith             * Little endian is used, meaning that the first byte of the buffer
17371867Smsmith             * is the LSB of the integer
17471867Smsmith             */
175202771Sjkim            Result |= (((UINT64) Pointer[i]) << (i * 8));
17671867Smsmith        }
17771867Smsmith        break;
17899679Siwasaki
17999679Siwasaki    default:
180193267Sjkim
18199679Siwasaki        /* No other types can get here */
182250838Sjkim
18399679Siwasaki        break;
18471867Smsmith    }
18571867Smsmith
186151937Sjkim    /* Create a new integer */
187151937Sjkim
188199337Sjkim    ReturnDesc = AcpiUtCreateIntegerObject (Result);
189138287Smarks    if (!ReturnDesc)
19099679Siwasaki    {
19199679Siwasaki        return_ACPI_STATUS (AE_NO_MEMORY);
19299679Siwasaki    }
19399679Siwasaki
194167802Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n",
195167802Sjkim        ACPI_FORMAT_UINT64 (Result)));
196167802Sjkim
197107325Siwasaki    /* Save the Result */
19871867Smsmith
199245582Sjkim    (void) AcpiExTruncateFor32bitTable (ReturnDesc);
200138287Smarks    *ResultDesc = ReturnDesc;
20191116Smsmith    return_ACPI_STATUS (AE_OK);
20271867Smsmith}
20371867Smsmith
20471867Smsmith
20571867Smsmith/*******************************************************************************
20671867Smsmith *
20777424Smsmith * FUNCTION:    AcpiExConvertToBuffer
20871867Smsmith *
209193267Sjkim * PARAMETERS:  ObjDesc         - Object to be converted. Must be an
21071867Smsmith *                                Integer, Buffer, or String
211126372Snjl *              ResultDesc      - Where the new buffer object is returned
21271867Smsmith *
21371867Smsmith * RETURN:      Status
21471867Smsmith *
215104470Siwasaki * DESCRIPTION: Convert an ACPI Object to a Buffer
21671867Smsmith *
21771867Smsmith ******************************************************************************/
21871867Smsmith
21971867SmsmithACPI_STATUS
22077424SmsmithAcpiExConvertToBuffer (
22180062Smsmith    ACPI_OPERAND_OBJECT     *ObjDesc,
222138287Smarks    ACPI_OPERAND_OBJECT     **ResultDesc)
22371867Smsmith{
224138287Smarks    ACPI_OPERAND_OBJECT     *ReturnDesc;
22571867Smsmith    UINT8                   *NewBuf;
22671867Smsmith
22771867Smsmith
228167802Sjkim    ACPI_FUNCTION_TRACE_PTR (ExConvertToBuffer, ObjDesc);
22983174Smsmith
23083174Smsmith
231193267Sjkim    switch (ObjDesc->Common.Type)
23271867Smsmith    {
233107325Siwasaki    case ACPI_TYPE_BUFFER:
234107325Siwasaki
235107325Siwasaki        /* No conversion necessary */
236107325Siwasaki
237107325Siwasaki        *ResultDesc = ObjDesc;
238107325Siwasaki        return_ACPI_STATUS (AE_OK);
239107325Siwasaki
240107325Siwasaki
24171867Smsmith    case ACPI_TYPE_INTEGER:
24271867Smsmith        /*
243107325Siwasaki         * Create a new Buffer object.
244114237Snjl         * Need enough space for one integer
24571867Smsmith         */
246138287Smarks        ReturnDesc = AcpiUtCreateBufferObject (AcpiGbl_IntegerByteWidth);
247138287Smarks        if (!ReturnDesc)
24871867Smsmith        {
24991116Smsmith            return_ACPI_STATUS (AE_NO_MEMORY);
25071867Smsmith        }
25171867Smsmith
252138287Smarks        /* Copy the integer to the buffer, LSB first */
25371867Smsmith
254138287Smarks        NewBuf = ReturnDesc->Buffer.Pointer;
255306536Sjkim        memcpy (NewBuf, &ObjDesc->Integer.Value, AcpiGbl_IntegerByteWidth);
25671867Smsmith        break;
25771867Smsmith
25871867Smsmith    case ACPI_TYPE_STRING:
259104470Siwasaki        /*
260104470Siwasaki         * Create a new Buffer object
261107325Siwasaki         * Size will be the string length
262151937Sjkim         *
263151937Sjkim         * NOTE: Add one to the string length to include the null terminator.
264151937Sjkim         * The ACPI spec is unclear on this subject, but there is existing
265151937Sjkim         * ASL/AML code that depends on the null being transferred to the new
266151937Sjkim         * buffer.
267104470Siwasaki         */
268306536Sjkim        ReturnDesc = AcpiUtCreateBufferObject ((ACPI_SIZE)
269306536Sjkim            ObjDesc->String.Length + 1);
270138287Smarks        if (!ReturnDesc)
271104470Siwasaki        {
272104470Siwasaki            return_ACPI_STATUS (AE_NO_MEMORY);
273104470Siwasaki        }
274104470Siwasaki
275107325Siwasaki        /* Copy the string to the buffer */
276104470Siwasaki
277138287Smarks        NewBuf = ReturnDesc->Buffer.Pointer;
278306536Sjkim        strncpy ((char *) NewBuf, (char *) ObjDesc->String.Pointer,
279107325Siwasaki            ObjDesc->String.Length);
28071867Smsmith        break;
28171867Smsmith
282250838Sjkim    default:
28371867Smsmith
28491116Smsmith        return_ACPI_STATUS (AE_TYPE);
28591116Smsmith    }
28671867Smsmith
28799146Siwasaki    /* Mark buffer initialized */
28899146Siwasaki
289138287Smarks    ReturnDesc->Common.Flags |= AOPOBJ_DATA_VALID;
290138287Smarks    *ResultDesc = ReturnDesc;
29191116Smsmith    return_ACPI_STATUS (AE_OK);
29271867Smsmith}
29371867Smsmith
29471867Smsmith
29571867Smsmith/*******************************************************************************
29671867Smsmith *
297138287Smarks * FUNCTION:    AcpiExConvertToAscii
29882367Smsmith *
299104470Siwasaki * PARAMETERS:  Integer         - Value to be converted
300138287Smarks *              Base            - ACPI_STRING_DECIMAL or ACPI_STRING_HEX
301104470Siwasaki *              String          - Where the string is returned
302138287Smarks *              DataWidth       - Size of data item to be converted, in bytes
30382367Smsmith *
30482367Smsmith * RETURN:      Actual string length
30582367Smsmith *
306104470Siwasaki * DESCRIPTION: Convert an ACPI Integer to a hex or decimal string
30782367Smsmith *
30882367Smsmith ******************************************************************************/
30982367Smsmith
310151937Sjkimstatic UINT32
31182367SmsmithAcpiExConvertToAscii (
312202771Sjkim    UINT64                  Integer,
313138287Smarks    UINT16                  Base,
314114237Snjl    UINT8                   *String,
315114237Snjl    UINT8                   DataWidth)
31682367Smsmith{
317202771Sjkim    UINT64                  Digit;
318193267Sjkim    UINT32                  i;
319193267Sjkim    UINT32                  j;
320193267Sjkim    UINT32                  k = 0;
321193267Sjkim    UINT32                  HexLength;
322193267Sjkim    UINT32                  DecimalLength;
32384491Smsmith    UINT32                  Remainder;
324138287Smarks    BOOLEAN                 SupressZeros;
32582367Smsmith
32682367Smsmith
32791116Smsmith    ACPI_FUNCTION_ENTRY ();
32882367Smsmith
329126372Snjl
33082367Smsmith    switch (Base)
33182367Smsmith    {
33282367Smsmith    case 10:
33382367Smsmith
334138287Smarks        /* Setup max length for the decimal number */
335138287Smarks
336138287Smarks        switch (DataWidth)
337138287Smarks        {
338138287Smarks        case 1:
339250838Sjkim
340138287Smarks            DecimalLength = ACPI_MAX8_DECIMAL_DIGITS;
341138287Smarks            break;
342138287Smarks
343138287Smarks        case 4:
344250838Sjkim
345138287Smarks            DecimalLength = ACPI_MAX32_DECIMAL_DIGITS;
346138287Smarks            break;
347138287Smarks
348138287Smarks        case 8:
349138287Smarks        default:
350250838Sjkim
351138287Smarks            DecimalLength = ACPI_MAX64_DECIMAL_DIGITS;
352138287Smarks            break;
353138287Smarks        }
354138287Smarks
355138287Smarks        SupressZeros = TRUE;     /* No leading zeros */
35684491Smsmith        Remainder = 0;
357138287Smarks
358138287Smarks        for (i = DecimalLength; i > 0; i--)
35982367Smsmith        {
36082367Smsmith            /* Divide by nth factor of 10 */
36182367Smsmith
36282367Smsmith            Digit = Integer;
363126372Snjl            for (j = 0; j < i; j++)
36482367Smsmith            {
365138287Smarks                (void) AcpiUtShortDivide (Digit, 10, &Digit, &Remainder);
36682367Smsmith            }
36782367Smsmith
368138287Smarks            /* Handle leading zeros */
36982367Smsmith
370126372Snjl            if (Remainder != 0)
37182367Smsmith            {
372138287Smarks                SupressZeros = FALSE;
37382367Smsmith            }
37482367Smsmith
375138287Smarks            if (!SupressZeros)
37682367Smsmith            {
37791116Smsmith                String[k] = (UINT8) (ACPI_ASCII_ZERO + Remainder);
37882367Smsmith                k++;
37982367Smsmith            }
38082367Smsmith        }
38182367Smsmith        break;
38282367Smsmith
38382367Smsmith    case 16:
38482367Smsmith
385151937Sjkim        /* HexLength: 2 ascii hex chars per data byte */
38682367Smsmith
387193267Sjkim        HexLength = ACPI_MUL_2 (DataWidth);
388138287Smarks        for (i = 0, j = (HexLength-1); i < HexLength; i++, j--)
38982367Smsmith        {
390138287Smarks            /* Get one hex digit, most significant digits first */
39182367Smsmith
392306536Sjkim            String[k] = (UINT8)
393306536Sjkim                AcpiUtHexToAsciiChar (Integer, ACPI_MUL_4 (j));
394138287Smarks            k++;
39582367Smsmith        }
39682367Smsmith        break;
39782367Smsmith
39882367Smsmith    default:
399138287Smarks        return (0);
40082367Smsmith    }
40182367Smsmith
40282367Smsmith    /*
403193267Sjkim     * Since leading zeros are suppressed, we must check for the case where
404126372Snjl     * the integer equals 0
40582367Smsmith     *
40682367Smsmith     * Finally, null terminate the string and return the length
40782367Smsmith     */
40882367Smsmith    if (!k)
40982367Smsmith    {
41091116Smsmith        String [0] = ACPI_ASCII_ZERO;
41182367Smsmith        k = 1;
41282367Smsmith    }
413114237Snjl
41482367Smsmith    String [k] = 0;
415138287Smarks    return ((UINT32) k);
41682367Smsmith}
41782367Smsmith
41882367Smsmith
41982367Smsmith/*******************************************************************************
42082367Smsmith *
42177424Smsmith * FUNCTION:    AcpiExConvertToString
42271867Smsmith *
423193267Sjkim * PARAMETERS:  ObjDesc         - Object to be converted. Must be an
424138287Smarks *                                Integer, Buffer, or String
425126372Snjl *              ResultDesc      - Where the string object is returned
426138287Smarks *              Type            - String flags (base and conversion type)
42771867Smsmith *
42871867Smsmith * RETURN:      Status
42971867Smsmith *
43071867Smsmith * DESCRIPTION: Convert an ACPI Object to a string
43171867Smsmith *
43271867Smsmith ******************************************************************************/
43371867Smsmith
43471867SmsmithACPI_STATUS
43577424SmsmithAcpiExConvertToString (
43680062Smsmith    ACPI_OPERAND_OBJECT     *ObjDesc,
43780062Smsmith    ACPI_OPERAND_OBJECT     **ResultDesc,
438138287Smarks    UINT32                  Type)
43971867Smsmith{
440138287Smarks    ACPI_OPERAND_OBJECT     *ReturnDesc;
44171867Smsmith    UINT8                   *NewBuf;
442151937Sjkim    UINT32                  i;
443138287Smarks    UINT32                  StringLength = 0;
444138287Smarks    UINT16                  Base = 16;
445138287Smarks    UINT8                   Separator = ',';
44671867Smsmith
44771867Smsmith
448167802Sjkim    ACPI_FUNCTION_TRACE_PTR (ExConvertToString, ObjDesc);
44980062Smsmith
45083174Smsmith
451193267Sjkim    switch (ObjDesc->Common.Type)
45271867Smsmith    {
453107325Siwasaki    case ACPI_TYPE_STRING:
454107325Siwasaki
455138287Smarks        /* No conversion necessary */
456107325Siwasaki
457138287Smarks        *ResultDesc = ObjDesc;
458138287Smarks        return_ACPI_STATUS (AE_OK);
459107325Siwasaki
46071867Smsmith    case ACPI_TYPE_INTEGER:
46171867Smsmith
462138287Smarks        switch (Type)
46382367Smsmith        {
464138287Smarks        case ACPI_EXPLICIT_CONVERT_DECIMAL:
465138287Smarks
466138287Smarks            /* Make room for maximum decimal number */
467138287Smarks
46882367Smsmith            StringLength = ACPI_MAX_DECIMAL_DIGITS;
469138287Smarks            Base = 10;
470138287Smarks            break;
471138287Smarks
472138287Smarks        default:
473138287Smarks
474138287Smarks            /* Two hex string characters for each integer byte */
475138287Smarks
476138287Smarks            StringLength = ACPI_MUL_2 (AcpiGbl_IntegerByteWidth);
477138287Smarks            break;
47882367Smsmith        }
47982367Smsmith
48082367Smsmith        /*
48182367Smsmith         * Create a new String
482138287Smarks         * Need enough space for one ASCII integer (plus null terminator)
48382367Smsmith         */
484138287Smarks        ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) StringLength);
485138287Smarks        if (!ReturnDesc)
48682367Smsmith        {
48791116Smsmith            return_ACPI_STATUS (AE_NO_MEMORY);
48882367Smsmith        }
48982367Smsmith
490138287Smarks        NewBuf = ReturnDesc->Buffer.Pointer;
49171867Smsmith
492138287Smarks        /* Convert integer to string */
49371867Smsmith
494306536Sjkim        StringLength = AcpiExConvertToAscii (
495306536Sjkim            ObjDesc->Integer.Value, Base, NewBuf, AcpiGbl_IntegerByteWidth);
49671867Smsmith
49780062Smsmith        /* Null terminate at the correct place */
49871867Smsmith
499138287Smarks        ReturnDesc->String.Length = StringLength;
500138287Smarks        NewBuf [StringLength] = 0;
50180062Smsmith        break;
50271867Smsmith
50371867Smsmith    case ACPI_TYPE_BUFFER:
50471867Smsmith
505151937Sjkim        /* Setup string length, base, and separator */
506151937Sjkim
507138287Smarks        switch (Type)
50882367Smsmith        {
509151937Sjkim        case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by ToDecimalString */
510138287Smarks            /*
511138287Smarks             * From ACPI: "If Data is a buffer, it is converted to a string of
512138287Smarks             * decimal values separated by commas."
513138287Smarks             */
514138287Smarks            Base = 10;
515114237Snjl
516151937Sjkim            /*
517193267Sjkim             * Calculate the final string length. Individual string values
518151937Sjkim             * are variable length (include separator for each)
519151937Sjkim             */
520151937Sjkim            for (i = 0; i < ObjDesc->Buffer.Length; i++)
521151937Sjkim            {
522151937Sjkim                if (ObjDesc->Buffer.Pointer[i] >= 100)
523151937Sjkim                {
524151937Sjkim                    StringLength += 4;
525151937Sjkim                }
526151937Sjkim                else if (ObjDesc->Buffer.Pointer[i] >= 10)
527151937Sjkim                {
528151937Sjkim                    StringLength += 3;
529151937Sjkim                }
530151937Sjkim                else
531151937Sjkim                {
532151937Sjkim                    StringLength += 2;
533151937Sjkim                }
534151937Sjkim            }
535151937Sjkim            break;
536138287Smarks
537138287Smarks        case ACPI_IMPLICIT_CONVERT_HEX:
538138287Smarks            /*
539138287Smarks             * From the ACPI spec:
540138287Smarks             *"The entire contents of the buffer are converted to a string of
541138287Smarks             * two-character hexadecimal numbers, each separated by a space."
542138287Smarks             */
543151937Sjkim            Separator = ' ';
544151937Sjkim            StringLength = (ObjDesc->Buffer.Length * 3);
545151937Sjkim            break;
54680062Smsmith
547151937Sjkim        case ACPI_EXPLICIT_CONVERT_HEX:     /* Used by ToHexString */
548138287Smarks            /*
549138287Smarks             * From ACPI: "If Data is a buffer, it is converted to a string of
550138287Smarks             * hexadecimal values separated by commas."
551138287Smarks             */
552151937Sjkim            StringLength = (ObjDesc->Buffer.Length * 3);
553151937Sjkim            break;
55471867Smsmith
555151937Sjkim        default:
556151937Sjkim            return_ACPI_STATUS (AE_BAD_PARAMETER);
557151937Sjkim        }
55871867Smsmith
559151937Sjkim        /*
560167802Sjkim         * Create a new string object and string buffer
561151937Sjkim         * (-1 because of extra separator included in StringLength from above)
562193267Sjkim         * Allow creation of zero-length strings from zero-length buffers.
563151937Sjkim         */
564193267Sjkim        if (StringLength)
565193267Sjkim        {
566193267Sjkim            StringLength--;
567193267Sjkim        }
568193267Sjkim
569193267Sjkim        ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) StringLength);
570151937Sjkim        if (!ReturnDesc)
571151937Sjkim        {
572151937Sjkim            return_ACPI_STATUS (AE_NO_MEMORY);
573151937Sjkim        }
57471867Smsmith
575151937Sjkim        NewBuf = ReturnDesc->Buffer.Pointer;
57682367Smsmith
577151937Sjkim        /*
578151937Sjkim         * Convert buffer bytes to hex or decimal values
579151937Sjkim         * (separated by commas or spaces)
580151937Sjkim         */
581151937Sjkim        for (i = 0; i < ObjDesc->Buffer.Length; i++)
582151937Sjkim        {
583151937Sjkim            NewBuf += AcpiExConvertToAscii (
584306536Sjkim                (UINT64) ObjDesc->Buffer.Pointer[i], Base, NewBuf, 1);
585151937Sjkim            *NewBuf++ = Separator; /* each separated by a comma or space */
586151937Sjkim        }
58771867Smsmith
588151937Sjkim        /*
589151937Sjkim         * Null terminate the string
590151937Sjkim         * (overwrites final comma/space from above)
591151937Sjkim         */
592193267Sjkim        if (ObjDesc->Buffer.Length)
593193267Sjkim        {
594193267Sjkim            NewBuf--;
595193267Sjkim        }
596151937Sjkim        *NewBuf = 0;
59771867Smsmith        break;
59871867Smsmith
599107325Siwasaki    default:
600250838Sjkim
601107325Siwasaki        return_ACPI_STATUS (AE_TYPE);
602107325Siwasaki    }
60380062Smsmith
604138287Smarks    *ResultDesc = ReturnDesc;
60591116Smsmith    return_ACPI_STATUS (AE_OK);
60671867Smsmith}
60771867Smsmith
60871867Smsmith
60977424Smsmith/*******************************************************************************
61077424Smsmith *
61177424Smsmith * FUNCTION:    AcpiExConvertToTargetType
61277424Smsmith *
61391116Smsmith * PARAMETERS:  DestinationType     - Current type of the destination
61491116Smsmith *              SourceDesc          - Source object to be converted.
615126372Snjl *              ResultDesc          - Where the converted object is returned
61691116Smsmith *              WalkState           - Current method state
61777424Smsmith *
61877424Smsmith * RETURN:      Status
61977424Smsmith *
62091116Smsmith * DESCRIPTION: Implements "implicit conversion" rules for storing an object.
62177424Smsmith *
62277424Smsmith ******************************************************************************/
62377424Smsmith
62477424SmsmithACPI_STATUS
62577424SmsmithAcpiExConvertToTargetType (
62691116Smsmith    ACPI_OBJECT_TYPE        DestinationType,
62791116Smsmith    ACPI_OPERAND_OBJECT     *SourceDesc,
62891116Smsmith    ACPI_OPERAND_OBJECT     **ResultDesc,
62977424Smsmith    ACPI_WALK_STATE         *WalkState)
63077424Smsmith{
63177424Smsmith    ACPI_STATUS             Status = AE_OK;
63277424Smsmith
63377424Smsmith
634167802Sjkim    ACPI_FUNCTION_TRACE (ExConvertToTargetType);
63577424Smsmith
63677424Smsmith
63791116Smsmith    /* Default behavior */
63891116Smsmith
63991116Smsmith    *ResultDesc = SourceDesc;
64091116Smsmith
64177424Smsmith    /*
64277424Smsmith     * If required by the target,
64377424Smsmith     * perform implicit conversion on the source before we store it.
64477424Smsmith     */
64577424Smsmith    switch (GET_CURRENT_ARG_TYPE (WalkState->OpInfo->RuntimeArgs))
64677424Smsmith    {
64777424Smsmith    case ARGI_SIMPLE_TARGET:
64877424Smsmith    case ARGI_FIXED_TARGET:
64977424Smsmith    case ARGI_INTEGER_REF:      /* Handles Increment, Decrement cases */
65077424Smsmith
65177424Smsmith        switch (DestinationType)
65277424Smsmith        {
653107325Siwasaki        case ACPI_TYPE_LOCAL_REGION_FIELD:
65477424Smsmith            /*
65577424Smsmith             * Named field can always handle conversions
65677424Smsmith             */
65777424Smsmith            break;
65877424Smsmith
65977424Smsmith        default:
660250838Sjkim
66177424Smsmith            /* No conversion allowed for these types */
66277424Smsmith
663193267Sjkim            if (DestinationType != SourceDesc->Common.Type)
66477424Smsmith            {
665104470Siwasaki                ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
666104470Siwasaki                    "Explicit operator, will store (%s) over existing type (%s)\n",
66799679Siwasaki                    AcpiUtGetObjectTypeName (SourceDesc),
66877424Smsmith                    AcpiUtGetTypeName (DestinationType)));
66977424Smsmith                Status = AE_TYPE;
67077424Smsmith            }
67177424Smsmith        }
67277424Smsmith        break;
67377424Smsmith
67477424Smsmith    case ARGI_TARGETREF:
675306536Sjkim    case ARGI_STORE_TARGET:
67677424Smsmith
67777424Smsmith        switch (DestinationType)
67877424Smsmith        {
67977424Smsmith        case ACPI_TYPE_INTEGER:
68077424Smsmith        case ACPI_TYPE_BUFFER_FIELD:
681107325Siwasaki        case ACPI_TYPE_LOCAL_BANK_FIELD:
682107325Siwasaki        case ACPI_TYPE_LOCAL_INDEX_FIELD:
68377424Smsmith            /*
684193267Sjkim             * These types require an Integer operand. We can convert
68577424Smsmith             * a Buffer or a String to an Integer if necessary.
68677424Smsmith             */
687306536Sjkim            Status = AcpiExConvertToInteger (SourceDesc, ResultDesc, 16);
68877424Smsmith            break;
68977424Smsmith
69077424Smsmith        case ACPI_TYPE_STRING:
69177424Smsmith            /*
692193267Sjkim             * The operand must be a String. We can convert an
69377424Smsmith             * Integer or Buffer if necessary
69477424Smsmith             */
695138287Smarks            Status = AcpiExConvertToString (SourceDesc, ResultDesc,
696306536Sjkim                ACPI_IMPLICIT_CONVERT_HEX);
69777424Smsmith            break;
69877424Smsmith
69977424Smsmith        case ACPI_TYPE_BUFFER:
70077424Smsmith            /*
701193267Sjkim             * The operand must be a Buffer. We can convert an
70291116Smsmith             * Integer or String if necessary
70377424Smsmith             */
704138287Smarks            Status = AcpiExConvertToBuffer (SourceDesc, ResultDesc);
70577424Smsmith            break;
70699679Siwasaki
707250838Sjkim        default:
70899679Siwasaki
709306536Sjkim            ACPI_ERROR ((AE_INFO,
710306536Sjkim                "Bad destination type during conversion: 0x%X",
711126372Snjl                DestinationType));
71299679Siwasaki            Status = AE_AML_INTERNAL;
71399679Siwasaki            break;
71477424Smsmith        }
71577424Smsmith        break;
71677424Smsmith
71777424Smsmith    case ARGI_REFERENCE:
71877424Smsmith        /*
71977424Smsmith         * CreateXxxxField cases - we are storing the field object into the name
72077424Smsmith         */
72177424Smsmith        break;
72277424Smsmith
723250838Sjkim    default:
72477424Smsmith
725167802Sjkim        ACPI_ERROR ((AE_INFO,
726204773Sjkim            "Unknown Target type ID 0x%X AmlOpcode 0x%X DestType %s",
72777424Smsmith            GET_CURRENT_ARG_TYPE (WalkState->OpInfo->RuntimeArgs),
728167802Sjkim            WalkState->Opcode, AcpiUtGetTypeName (DestinationType)));
72977424Smsmith        Status = AE_AML_INTERNAL;
73077424Smsmith    }
73177424Smsmith
73277424Smsmith    /*
73377424Smsmith     * Source-to-Target conversion semantics:
73477424Smsmith     *
73577424Smsmith     * If conversion to the target type cannot be performed, then simply
73677424Smsmith     * overwrite the target with the new object and type.
73777424Smsmith     */
73877424Smsmith    if (Status == AE_TYPE)
73977424Smsmith    {
74077424Smsmith        Status = AE_OK;
74177424Smsmith    }
74277424Smsmith
74377424Smsmith    return_ACPI_STATUS (Status);
74477424Smsmith}
745