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