exconvrt.c revision 281075
1/******************************************************************************
2 *
3 * Module Name: exconvrt - Object conversion routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2015, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <contrib/dev/acpica/include/acpi.h>
45#include <contrib/dev/acpica/include/accommon.h>
46#include <contrib/dev/acpica/include/acinterp.h>
47#include <contrib/dev/acpica/include/amlcode.h>
48
49
50#define _COMPONENT          ACPI_EXECUTER
51        ACPI_MODULE_NAME    ("exconvrt")
52
53/* Local prototypes */
54
55static UINT32
56AcpiExConvertToAscii (
57    UINT64                  Integer,
58    UINT16                  Base,
59    UINT8                   *String,
60    UINT8                   MaxLength);
61
62
63/*******************************************************************************
64 *
65 * FUNCTION:    AcpiExConvertToInteger
66 *
67 * PARAMETERS:  ObjDesc         - Object to be converted. Must be an
68 *                                Integer, Buffer, or String
69 *              ResultDesc      - Where the new Integer object is returned
70 *              Flags           - Used for string conversion
71 *
72 * RETURN:      Status
73 *
74 * DESCRIPTION: Convert an ACPI Object to an integer.
75 *
76 ******************************************************************************/
77
78ACPI_STATUS
79AcpiExConvertToInteger (
80    ACPI_OPERAND_OBJECT     *ObjDesc,
81    ACPI_OPERAND_OBJECT     **ResultDesc,
82    UINT32                  Flags)
83{
84    ACPI_OPERAND_OBJECT     *ReturnDesc;
85    UINT8                   *Pointer;
86    UINT64                  Result;
87    UINT32                  i;
88    UINT32                  Count;
89    ACPI_STATUS             Status;
90
91
92    ACPI_FUNCTION_TRACE_PTR (ExConvertToInteger, ObjDesc);
93
94
95    switch (ObjDesc->Common.Type)
96    {
97    case ACPI_TYPE_INTEGER:
98
99        /* No conversion necessary */
100
101        *ResultDesc = ObjDesc;
102        return_ACPI_STATUS (AE_OK);
103
104    case ACPI_TYPE_BUFFER:
105    case ACPI_TYPE_STRING:
106
107        /* Note: Takes advantage of common buffer/string fields */
108
109        Pointer = ObjDesc->Buffer.Pointer;
110        Count   = ObjDesc->Buffer.Length;
111        break;
112
113    default:
114
115        return_ACPI_STATUS (AE_TYPE);
116    }
117
118    /*
119     * Convert the buffer/string to an integer. Note that both buffers and
120     * strings are treated as raw data - we don't convert ascii to hex for
121     * strings.
122     *
123     * There are two terminating conditions for the loop:
124     * 1) The size of an integer has been reached, or
125     * 2) The end of the buffer or string has been reached
126     */
127    Result = 0;
128
129    /* String conversion is different than Buffer conversion */
130
131    switch (ObjDesc->Common.Type)
132    {
133    case ACPI_TYPE_STRING:
134        /*
135         * Convert string to an integer - for most cases, the string must be
136         * hexadecimal as per the ACPI specification. The only exception (as
137         * of ACPI 3.0) is that the ToInteger() operator allows both decimal
138         * and hexadecimal strings (hex prefixed with "0x").
139         */
140        Status = AcpiUtStrtoul64 ((char *) Pointer, Flags, &Result);
141        if (ACPI_FAILURE (Status))
142        {
143            return_ACPI_STATUS (Status);
144        }
145        break;
146
147    case ACPI_TYPE_BUFFER:
148
149        /* Check for zero-length buffer */
150
151        if (!Count)
152        {
153            return_ACPI_STATUS (AE_AML_BUFFER_LIMIT);
154        }
155
156        /* Transfer no more than an integer's worth of data */
157
158        if (Count > AcpiGbl_IntegerByteWidth)
159        {
160            Count = AcpiGbl_IntegerByteWidth;
161        }
162
163        /*
164         * Convert buffer to an integer - we simply grab enough raw data
165         * from the buffer to fill an integer
166         */
167        for (i = 0; i < Count; i++)
168        {
169            /*
170             * Get next byte and shift it into the Result.
171             * Little endian is used, meaning that the first byte of the buffer
172             * is the LSB of the integer
173             */
174            Result |= (((UINT64) Pointer[i]) << (i * 8));
175        }
176        break;
177
178    default:
179
180        /* No other types can get here */
181
182        break;
183    }
184
185    /* Create a new integer */
186
187    ReturnDesc = AcpiUtCreateIntegerObject (Result);
188    if (!ReturnDesc)
189    {
190        return_ACPI_STATUS (AE_NO_MEMORY);
191    }
192
193    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n",
194        ACPI_FORMAT_UINT64 (Result)));
195
196    /* Save the Result */
197
198    (void) AcpiExTruncateFor32bitTable (ReturnDesc);
199    *ResultDesc = ReturnDesc;
200    return_ACPI_STATUS (AE_OK);
201}
202
203
204/*******************************************************************************
205 *
206 * FUNCTION:    AcpiExConvertToBuffer
207 *
208 * PARAMETERS:  ObjDesc         - Object to be converted. Must be an
209 *                                Integer, Buffer, or String
210 *              ResultDesc      - Where the new buffer object is returned
211 *
212 * RETURN:      Status
213 *
214 * DESCRIPTION: Convert an ACPI Object to a Buffer
215 *
216 ******************************************************************************/
217
218ACPI_STATUS
219AcpiExConvertToBuffer (
220    ACPI_OPERAND_OBJECT     *ObjDesc,
221    ACPI_OPERAND_OBJECT     **ResultDesc)
222{
223    ACPI_OPERAND_OBJECT     *ReturnDesc;
224    UINT8                   *NewBuf;
225
226
227    ACPI_FUNCTION_TRACE_PTR (ExConvertToBuffer, ObjDesc);
228
229
230    switch (ObjDesc->Common.Type)
231    {
232    case ACPI_TYPE_BUFFER:
233
234        /* No conversion necessary */
235
236        *ResultDesc = ObjDesc;
237        return_ACPI_STATUS (AE_OK);
238
239
240    case ACPI_TYPE_INTEGER:
241        /*
242         * Create a new Buffer object.
243         * Need enough space for one integer
244         */
245        ReturnDesc = AcpiUtCreateBufferObject (AcpiGbl_IntegerByteWidth);
246        if (!ReturnDesc)
247        {
248            return_ACPI_STATUS (AE_NO_MEMORY);
249        }
250
251        /* Copy the integer to the buffer, LSB first */
252
253        NewBuf = ReturnDesc->Buffer.Pointer;
254        ACPI_MEMCPY (NewBuf,
255                        &ObjDesc->Integer.Value,
256                        AcpiGbl_IntegerByteWidth);
257        break;
258
259    case ACPI_TYPE_STRING:
260        /*
261         * Create a new Buffer object
262         * Size will be the string length
263         *
264         * NOTE: Add one to the string length to include the null terminator.
265         * The ACPI spec is unclear on this subject, but there is existing
266         * ASL/AML code that depends on the null being transferred to the new
267         * buffer.
268         */
269        ReturnDesc = AcpiUtCreateBufferObject (
270                        (ACPI_SIZE) ObjDesc->String.Length + 1);
271        if (!ReturnDesc)
272        {
273            return_ACPI_STATUS (AE_NO_MEMORY);
274        }
275
276        /* Copy the string to the buffer */
277
278        NewBuf = ReturnDesc->Buffer.Pointer;
279        ACPI_STRNCPY ((char *) NewBuf, (char *) ObjDesc->String.Pointer,
280            ObjDesc->String.Length);
281        break;
282
283    default:
284
285        return_ACPI_STATUS (AE_TYPE);
286    }
287
288    /* Mark buffer initialized */
289
290    ReturnDesc->Common.Flags |= AOPOBJ_DATA_VALID;
291    *ResultDesc = ReturnDesc;
292    return_ACPI_STATUS (AE_OK);
293}
294
295
296/*******************************************************************************
297 *
298 * FUNCTION:    AcpiExConvertToAscii
299 *
300 * PARAMETERS:  Integer         - Value to be converted
301 *              Base            - ACPI_STRING_DECIMAL or ACPI_STRING_HEX
302 *              String          - Where the string is returned
303 *              DataWidth       - Size of data item to be converted, in bytes
304 *
305 * RETURN:      Actual string length
306 *
307 * DESCRIPTION: Convert an ACPI Integer to a hex or decimal string
308 *
309 ******************************************************************************/
310
311static UINT32
312AcpiExConvertToAscii (
313    UINT64                  Integer,
314    UINT16                  Base,
315    UINT8                   *String,
316    UINT8                   DataWidth)
317{
318    UINT64                  Digit;
319    UINT32                  i;
320    UINT32                  j;
321    UINT32                  k = 0;
322    UINT32                  HexLength;
323    UINT32                  DecimalLength;
324    UINT32                  Remainder;
325    BOOLEAN                 SupressZeros;
326
327
328    ACPI_FUNCTION_ENTRY ();
329
330
331    switch (Base)
332    {
333    case 10:
334
335        /* Setup max length for the decimal number */
336
337        switch (DataWidth)
338        {
339        case 1:
340
341            DecimalLength = ACPI_MAX8_DECIMAL_DIGITS;
342            break;
343
344        case 4:
345
346            DecimalLength = ACPI_MAX32_DECIMAL_DIGITS;
347            break;
348
349        case 8:
350        default:
351
352            DecimalLength = ACPI_MAX64_DECIMAL_DIGITS;
353            break;
354        }
355
356        SupressZeros = TRUE;     /* No leading zeros */
357        Remainder = 0;
358
359        for (i = DecimalLength; i > 0; i--)
360        {
361            /* Divide by nth factor of 10 */
362
363            Digit = Integer;
364            for (j = 0; j < i; j++)
365            {
366                (void) AcpiUtShortDivide (Digit, 10, &Digit, &Remainder);
367            }
368
369            /* Handle leading zeros */
370
371            if (Remainder != 0)
372            {
373                SupressZeros = FALSE;
374            }
375
376            if (!SupressZeros)
377            {
378                String[k] = (UINT8) (ACPI_ASCII_ZERO + Remainder);
379                k++;
380            }
381        }
382        break;
383
384    case 16:
385
386        /* HexLength: 2 ascii hex chars per data byte */
387
388        HexLength = ACPI_MUL_2 (DataWidth);
389        for (i = 0, j = (HexLength-1); i < HexLength; i++, j--)
390        {
391            /* Get one hex digit, most significant digits first */
392
393            String[k] = (UINT8) AcpiUtHexToAsciiChar (Integer, ACPI_MUL_4 (j));
394            k++;
395        }
396        break;
397
398    default:
399        return (0);
400    }
401
402    /*
403     * Since leading zeros are suppressed, we must check for the case where
404     * the integer equals 0
405     *
406     * Finally, null terminate the string and return the length
407     */
408    if (!k)
409    {
410        String [0] = ACPI_ASCII_ZERO;
411        k = 1;
412    }
413
414    String [k] = 0;
415    return ((UINT32) k);
416}
417
418
419/*******************************************************************************
420 *
421 * FUNCTION:    AcpiExConvertToString
422 *
423 * PARAMETERS:  ObjDesc         - Object to be converted. Must be an
424 *                                Integer, Buffer, or String
425 *              ResultDesc      - Where the string object is returned
426 *              Type            - String flags (base and conversion type)
427 *
428 * RETURN:      Status
429 *
430 * DESCRIPTION: Convert an ACPI Object to a string
431 *
432 ******************************************************************************/
433
434ACPI_STATUS
435AcpiExConvertToString (
436    ACPI_OPERAND_OBJECT     *ObjDesc,
437    ACPI_OPERAND_OBJECT     **ResultDesc,
438    UINT32                  Type)
439{
440    ACPI_OPERAND_OBJECT     *ReturnDesc;
441    UINT8                   *NewBuf;
442    UINT32                  i;
443    UINT32                  StringLength = 0;
444    UINT16                  Base = 16;
445    UINT8                   Separator = ',';
446
447
448    ACPI_FUNCTION_TRACE_PTR (ExConvertToString, ObjDesc);
449
450
451    switch (ObjDesc->Common.Type)
452    {
453    case ACPI_TYPE_STRING:
454
455        /* No conversion necessary */
456
457        *ResultDesc = ObjDesc;
458        return_ACPI_STATUS (AE_OK);
459
460    case ACPI_TYPE_INTEGER:
461
462        switch (Type)
463        {
464        case ACPI_EXPLICIT_CONVERT_DECIMAL:
465
466            /* Make room for maximum decimal number */
467
468            StringLength = ACPI_MAX_DECIMAL_DIGITS;
469            Base = 10;
470            break;
471
472        default:
473
474            /* Two hex string characters for each integer byte */
475
476            StringLength = ACPI_MUL_2 (AcpiGbl_IntegerByteWidth);
477            break;
478        }
479
480        /*
481         * Create a new String
482         * Need enough space for one ASCII integer (plus null terminator)
483         */
484        ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) StringLength);
485        if (!ReturnDesc)
486        {
487            return_ACPI_STATUS (AE_NO_MEMORY);
488        }
489
490        NewBuf = ReturnDesc->Buffer.Pointer;
491
492        /* Convert integer to string */
493
494        StringLength = AcpiExConvertToAscii (ObjDesc->Integer.Value, Base,
495                            NewBuf, AcpiGbl_IntegerByteWidth);
496
497        /* Null terminate at the correct place */
498
499        ReturnDesc->String.Length = StringLength;
500        NewBuf [StringLength] = 0;
501        break;
502
503    case ACPI_TYPE_BUFFER:
504
505        /* Setup string length, base, and separator */
506
507        switch (Type)
508        {
509        case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by ToDecimalString */
510            /*
511             * From ACPI: "If Data is a buffer, it is converted to a string of
512             * decimal values separated by commas."
513             */
514            Base = 10;
515
516            /*
517             * Calculate the final string length. Individual string values
518             * are variable length (include separator for each)
519             */
520            for (i = 0; i < ObjDesc->Buffer.Length; i++)
521            {
522                if (ObjDesc->Buffer.Pointer[i] >= 100)
523                {
524                    StringLength += 4;
525                }
526                else if (ObjDesc->Buffer.Pointer[i] >= 10)
527                {
528                    StringLength += 3;
529                }
530                else
531                {
532                    StringLength += 2;
533                }
534            }
535            break;
536
537        case ACPI_IMPLICIT_CONVERT_HEX:
538            /*
539             * From the ACPI spec:
540             *"The entire contents of the buffer are converted to a string of
541             * two-character hexadecimal numbers, each separated by a space."
542             */
543            Separator = ' ';
544            StringLength = (ObjDesc->Buffer.Length * 3);
545            break;
546
547        case ACPI_EXPLICIT_CONVERT_HEX:     /* Used by ToHexString */
548            /*
549             * From ACPI: "If Data is a buffer, it is converted to a string of
550             * hexadecimal values separated by commas."
551             */
552            StringLength = (ObjDesc->Buffer.Length * 3);
553            break;
554
555        default:
556            return_ACPI_STATUS (AE_BAD_PARAMETER);
557        }
558
559        /*
560         * Create a new string object and string buffer
561         * (-1 because of extra separator included in StringLength from above)
562         * Allow creation of zero-length strings from zero-length buffers.
563         */
564        if (StringLength)
565        {
566            StringLength--;
567        }
568
569        ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) StringLength);
570        if (!ReturnDesc)
571        {
572            return_ACPI_STATUS (AE_NO_MEMORY);
573        }
574
575        NewBuf = ReturnDesc->Buffer.Pointer;
576
577        /*
578         * Convert buffer bytes to hex or decimal values
579         * (separated by commas or spaces)
580         */
581        for (i = 0; i < ObjDesc->Buffer.Length; i++)
582        {
583            NewBuf += AcpiExConvertToAscii (
584                        (UINT64) ObjDesc->Buffer.Pointer[i], Base,
585                        NewBuf, 1);
586            *NewBuf++ = Separator; /* each separated by a comma or space */
587        }
588
589        /*
590         * Null terminate the string
591         * (overwrites final comma/space from above)
592         */
593        if (ObjDesc->Buffer.Length)
594        {
595            NewBuf--;
596        }
597        *NewBuf = 0;
598        break;
599
600    default:
601
602        return_ACPI_STATUS (AE_TYPE);
603    }
604
605    *ResultDesc = ReturnDesc;
606    return_ACPI_STATUS (AE_OK);
607}
608
609
610/*******************************************************************************
611 *
612 * FUNCTION:    AcpiExConvertToTargetType
613 *
614 * PARAMETERS:  DestinationType     - Current type of the destination
615 *              SourceDesc          - Source object to be converted.
616 *              ResultDesc          - Where the converted object is returned
617 *              WalkState           - Current method state
618 *
619 * RETURN:      Status
620 *
621 * DESCRIPTION: Implements "implicit conversion" rules for storing an object.
622 *
623 ******************************************************************************/
624
625ACPI_STATUS
626AcpiExConvertToTargetType (
627    ACPI_OBJECT_TYPE        DestinationType,
628    ACPI_OPERAND_OBJECT     *SourceDesc,
629    ACPI_OPERAND_OBJECT     **ResultDesc,
630    ACPI_WALK_STATE         *WalkState)
631{
632    ACPI_STATUS             Status = AE_OK;
633
634
635    ACPI_FUNCTION_TRACE (ExConvertToTargetType);
636
637
638    /* Default behavior */
639
640    *ResultDesc = SourceDesc;
641
642    /*
643     * If required by the target,
644     * perform implicit conversion on the source before we store it.
645     */
646    switch (GET_CURRENT_ARG_TYPE (WalkState->OpInfo->RuntimeArgs))
647    {
648    case ARGI_SIMPLE_TARGET:
649    case ARGI_FIXED_TARGET:
650    case ARGI_INTEGER_REF:      /* Handles Increment, Decrement cases */
651
652        switch (DestinationType)
653        {
654        case ACPI_TYPE_LOCAL_REGION_FIELD:
655            /*
656             * Named field can always handle conversions
657             */
658            break;
659
660        default:
661
662            /* No conversion allowed for these types */
663
664            if (DestinationType != SourceDesc->Common.Type)
665            {
666                ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
667                    "Explicit operator, will store (%s) over existing type (%s)\n",
668                    AcpiUtGetObjectTypeName (SourceDesc),
669                    AcpiUtGetTypeName (DestinationType)));
670                Status = AE_TYPE;
671            }
672        }
673        break;
674
675    case ARGI_TARGETREF:
676
677        switch (DestinationType)
678        {
679        case ACPI_TYPE_INTEGER:
680        case ACPI_TYPE_BUFFER_FIELD:
681        case ACPI_TYPE_LOCAL_BANK_FIELD:
682        case ACPI_TYPE_LOCAL_INDEX_FIELD:
683            /*
684             * These types require an Integer operand. We can convert
685             * a Buffer or a String to an Integer if necessary.
686             */
687            Status = AcpiExConvertToInteger (SourceDesc, ResultDesc,
688                        16);
689            break;
690
691        case ACPI_TYPE_STRING:
692            /*
693             * The operand must be a String. We can convert an
694             * Integer or Buffer if necessary
695             */
696            Status = AcpiExConvertToString (SourceDesc, ResultDesc,
697                        ACPI_IMPLICIT_CONVERT_HEX);
698            break;
699
700        case ACPI_TYPE_BUFFER:
701            /*
702             * The operand must be a Buffer. We can convert an
703             * Integer or String if necessary
704             */
705            Status = AcpiExConvertToBuffer (SourceDesc, ResultDesc);
706            break;
707
708        default:
709
710            ACPI_ERROR ((AE_INFO, "Bad destination type during conversion: 0x%X",
711                DestinationType));
712            Status = AE_AML_INTERNAL;
713            break;
714        }
715        break;
716
717    case ARGI_REFERENCE:
718        /*
719         * CreateXxxxField cases - we are storing the field object into the name
720         */
721        break;
722
723    default:
724
725        ACPI_ERROR ((AE_INFO,
726            "Unknown Target type ID 0x%X AmlOpcode 0x%X DestType %s",
727            GET_CURRENT_ARG_TYPE (WalkState->OpInfo->RuntimeArgs),
728            WalkState->Opcode, AcpiUtGetTypeName (DestinationType)));
729        Status = AE_AML_INTERNAL;
730    }
731
732    /*
733     * Source-to-Target conversion semantics:
734     *
735     * If conversion to the target type cannot be performed, then simply
736     * overwrite the target with the new object and type.
737     */
738    if (Status == AE_TYPE)
739    {
740        Status = AE_OK;
741    }
742
743    return_ACPI_STATUS (Status);
744}
745