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