1 /******************************************************************************
2  *
3  * Module Name: exconvrt - Object conversion routines
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2019, 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 "acpi.h"
45 #include "accommon.h"
46 #include "acinterp.h"
47 #include "amlcode.h"
48 
49 
50 #define _COMPONENT          ACPI_EXECUTER
51         ACPI_MODULE_NAME    ("exconvrt")
52 
53 /* Local prototypes */
54 
55 static UINT32
56 AcpiExConvertToAscii (
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  *              ImplicitConversion  - Used for string conversion
71  *
72  * RETURN:      Status
73  *
74  * DESCRIPTION: Convert an ACPI Object to an integer.
75  *
76  ******************************************************************************/
77 
78 ACPI_STATUS
79 AcpiExConvertToInteger (
80     ACPI_OPERAND_OBJECT     *ObjDesc,
81     ACPI_OPERAND_OBJECT     **ResultDesc,
82     UINT32                  ImplicitConversion)
83 {
84     ACPI_OPERAND_OBJECT     *ReturnDesc;
85     UINT8                   *Pointer;
86     UINT64                  Result;
87     UINT32                  i;
88     UINT32                  Count;
89 
90 
91     ACPI_FUNCTION_TRACE_PTR (ExConvertToInteger, ObjDesc);
92 
93 
94     switch (ObjDesc->Common.Type)
95     {
96     case ACPI_TYPE_INTEGER:
97 
98         /* No conversion necessary */
99 
100         *ResultDesc = ObjDesc;
101         return_ACPI_STATUS (AE_OK);
102 
103     case ACPI_TYPE_BUFFER:
104     case ACPI_TYPE_STRING:
105 
106         /* Note: Takes advantage of common buffer/string fields */
107 
108         Pointer = ObjDesc->Buffer.Pointer;
109         Count   = ObjDesc->Buffer.Length;
110         break;
111 
112     default:
113 
114         return_ACPI_STATUS (AE_TYPE);
115     }
116 
117     /*
118      * Convert the buffer/string to an integer. Note that both buffers and
119      * strings are treated as raw data - we don't convert ascii to hex for
120      * strings.
121      *
122      * There are two terminating conditions for the loop:
123      * 1) The size of an integer has been reached, or
124      * 2) The end of the buffer or string has been reached
125      */
126     Result = 0;
127 
128     /* String conversion is different than Buffer conversion */
129 
130     switch (ObjDesc->Common.Type)
131     {
132     case ACPI_TYPE_STRING:
133         /*
134          * Convert string to an integer - for most cases, the string must be
135          * hexadecimal as per the ACPI specification. The only exception (as
136          * of ACPI 3.0) is that the ToInteger() operator allows both decimal
137          * and hexadecimal strings (hex prefixed with "0x").
138          *
139          * Explicit conversion is used only by ToInteger.
140          * All other string-to-integer conversions are implicit conversions.
141          */
142         if (ImplicitConversion)
143         {
144             Result = AcpiUtImplicitStrtoul64 (ACPI_CAST_PTR (char, Pointer));
145         }
146         else
147         {
148             Result = AcpiUtExplicitStrtoul64 (ACPI_CAST_PTR (char, Pointer));
149         }
150         break;
151 
152     case ACPI_TYPE_BUFFER:
153 
154         /* Check for zero-length buffer */
155 
156         if (!Count)
157         {
158             return_ACPI_STATUS (AE_AML_BUFFER_LIMIT);
159         }
160 
161         /* Transfer no more than an integer's worth of data */
162 
163         if (Count > AcpiGbl_IntegerByteWidth)
164         {
165             Count = AcpiGbl_IntegerByteWidth;
166         }
167 
168         /*
169          * Convert buffer to an integer - we simply grab enough raw data
170          * from the buffer to fill an integer
171          */
172         for (i = 0; i < Count; i++)
173         {
174             /*
175              * Get next byte and shift it into the Result.
176              * Little endian is used, meaning that the first byte of the buffer
177              * is the LSB of the integer
178              */
179             Result |= (((UINT64) Pointer[i]) << (i * 8));
180         }
181         break;
182 
183     default:
184 
185         /* No other types can get here */
186 
187         break;
188     }
189 
190     /* Create a new integer */
191 
192     ReturnDesc = AcpiUtCreateIntegerObject (Result);
193     if (!ReturnDesc)
194     {
195         return_ACPI_STATUS (AE_NO_MEMORY);
196     }
197 
198     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n",
199         ACPI_FORMAT_UINT64 (Result)));
200 
201     /* Save the Result */
202 
203     (void) AcpiExTruncateFor32bitTable (ReturnDesc);
204     *ResultDesc = ReturnDesc;
205     return_ACPI_STATUS (AE_OK);
206 }
207 
208 
209 /*******************************************************************************
210  *
211  * FUNCTION:    AcpiExConvertToBuffer
212  *
213  * PARAMETERS:  ObjDesc         - Object to be converted. Must be an
214  *                                Integer, Buffer, or String
215  *              ResultDesc      - Where the new buffer object is returned
216  *
217  * RETURN:      Status
218  *
219  * DESCRIPTION: Convert an ACPI Object to a Buffer
220  *
221  ******************************************************************************/
222 
223 ACPI_STATUS
224 AcpiExConvertToBuffer (
225     ACPI_OPERAND_OBJECT     *ObjDesc,
226     ACPI_OPERAND_OBJECT     **ResultDesc)
227 {
228     ACPI_OPERAND_OBJECT     *ReturnDesc;
229     UINT8                   *NewBuf;
230 
231 
232     ACPI_FUNCTION_TRACE_PTR (ExConvertToBuffer, ObjDesc);
233 
234 
235     switch (ObjDesc->Common.Type)
236     {
237     case ACPI_TYPE_BUFFER:
238 
239         /* No conversion necessary */
240 
241         *ResultDesc = ObjDesc;
242         return_ACPI_STATUS (AE_OK);
243 
244 
245     case ACPI_TYPE_INTEGER:
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         memcpy (NewBuf, &ObjDesc->Integer.Value, 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 ((ACPI_SIZE)
273             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         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 
314 static UINT32
315 AcpiExConvertToAscii (
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 = (DataWidth * 2);
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)
397                 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. Supports both implicit
435  *              and explicit conversions and related rules.
436  *
437  ******************************************************************************/
438 
439 ACPI_STATUS
440 AcpiExConvertToString (
441     ACPI_OPERAND_OBJECT     *ObjDesc,
442     ACPI_OPERAND_OBJECT     **ResultDesc,
443     UINT32                  Type)
444 {
445     ACPI_OPERAND_OBJECT     *ReturnDesc;
446     UINT8                   *NewBuf;
447     UINT32                  i;
448     UINT32                  StringLength = 0;
449     UINT16                  Base = 16;
450     UINT8                   Separator = ',';
451 
452 
453     ACPI_FUNCTION_TRACE_PTR (ExConvertToString, ObjDesc);
454 
455 
456     switch (ObjDesc->Common.Type)
457     {
458     case ACPI_TYPE_STRING:
459 
460         /* No conversion necessary */
461 
462         *ResultDesc = ObjDesc;
463         return_ACPI_STATUS (AE_OK);
464 
465     case ACPI_TYPE_INTEGER:
466 
467         switch (Type)
468         {
469         case ACPI_EXPLICIT_CONVERT_DECIMAL:
470             /*
471              * From ToDecimalString, integer source.
472              *
473              * Make room for the maximum decimal number size
474              */
475             StringLength = ACPI_MAX_DECIMAL_DIGITS;
476             Base = 10;
477             break;
478 
479         default:
480 
481             /* Two hex string characters for each integer byte */
482 
483             StringLength = ACPI_MUL_2 (AcpiGbl_IntegerByteWidth);
484             break;
485         }
486 
487         /*
488          * Create a new String
489          * Need enough space for one ASCII integer (plus null terminator)
490          */
491         ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) StringLength);
492         if (!ReturnDesc)
493         {
494             return_ACPI_STATUS (AE_NO_MEMORY);
495         }
496 
497         NewBuf = ReturnDesc->Buffer.Pointer;
498 
499         /* Convert integer to string */
500 
501         StringLength = AcpiExConvertToAscii (
502             ObjDesc->Integer.Value, Base, NewBuf, AcpiGbl_IntegerByteWidth);
503 
504         /* Null terminate at the correct place */
505 
506         ReturnDesc->String.Length = StringLength;
507         NewBuf [StringLength] = 0;
508         break;
509 
510     case ACPI_TYPE_BUFFER:
511 
512         /* Setup string length, base, and separator */
513 
514         switch (Type)
515         {
516         case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by ToDecimalString */
517             /*
518              * Explicit conversion from the ToDecimalString ASL operator.
519              *
520              * From ACPI: "If the input is a buffer, it is converted to a
521              * a string of decimal values separated by commas."
522              */
523             Base = 10;
524 
525             /*
526              * Calculate the final string length. Individual string values
527              * are variable length (include separator for each)
528              */
529             for (i = 0; i < ObjDesc->Buffer.Length; i++)
530             {
531                 if (ObjDesc->Buffer.Pointer[i] >= 100)
532                 {
533                     StringLength += 4;
534                 }
535                 else if (ObjDesc->Buffer.Pointer[i] >= 10)
536                 {
537                     StringLength += 3;
538                 }
539                 else
540                 {
541                     StringLength += 2;
542                 }
543             }
544             break;
545 
546         case ACPI_IMPLICIT_CONVERT_HEX:
547             /*
548              * Implicit buffer-to-string conversion
549              *
550              * From the ACPI spec:
551              * "The entire contents of the buffer are converted to a string of
552              * two-character hexadecimal numbers, each separated by a space."
553              *
554              * Each hex number is prefixed with 0x (11/2018)
555              */
556             Separator = ' ';
557             StringLength = (ObjDesc->Buffer.Length * 5);
558             break;
559 
560         case ACPI_EXPLICIT_CONVERT_HEX:
561             /*
562              * Explicit conversion from the ToHexString ASL operator.
563              *
564              * From ACPI: "If Data is a buffer, it is converted to a string of
565              * hexadecimal values separated by commas."
566              *
567              * Each hex number is prefixed with 0x (11/2018)
568              */
569             Separator = ',';
570             StringLength = (ObjDesc->Buffer.Length * 5);
571             break;
572 
573         default:
574             return_ACPI_STATUS (AE_BAD_PARAMETER);
575         }
576 
577         /*
578          * Create a new string object and string buffer
579          * (-1 because of extra separator included in StringLength from above)
580          * Allow creation of zero-length strings from zero-length buffers.
581          */
582         if (StringLength)
583         {
584             StringLength--;
585         }
586 
587         ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) StringLength);
588         if (!ReturnDesc)
589         {
590             return_ACPI_STATUS (AE_NO_MEMORY);
591         }
592 
593         NewBuf = ReturnDesc->Buffer.Pointer;
594 
595         /*
596          * Convert buffer bytes to hex or decimal values
597          * (separated by commas or spaces)
598          */
599         for (i = 0; i < ObjDesc->Buffer.Length; i++)
600         {
601             if (Base == 16)
602             {
603                 /* Emit 0x prefix for explict/implicit hex conversion */
604 
605                 *NewBuf++ = '0';
606                 *NewBuf++ = 'x';
607             }
608 
609             NewBuf += AcpiExConvertToAscii (
610                 (UINT64) ObjDesc->Buffer.Pointer[i], Base, NewBuf, 1);
611 
612             /* Each digit is separated by either a comma or space */
613 
614             *NewBuf++ = Separator;
615         }
616 
617         /*
618          * Null terminate the string
619          * (overwrites final comma/space from above)
620          */
621         if (ObjDesc->Buffer.Length)
622         {
623             NewBuf--;
624         }
625         *NewBuf = 0;
626         break;
627 
628     default:
629 
630         return_ACPI_STATUS (AE_TYPE);
631     }
632 
633     *ResultDesc = ReturnDesc;
634     return_ACPI_STATUS (AE_OK);
635 }
636 
637 
638 /*******************************************************************************
639  *
640  * FUNCTION:    AcpiExConvertToTargetType
641  *
642  * PARAMETERS:  DestinationType     - Current type of the destination
643  *              SourceDesc          - Source object to be converted.
644  *              ResultDesc          - Where the converted object is returned
645  *              WalkState           - Current method state
646  *
647  * RETURN:      Status
648  *
649  * DESCRIPTION: Implements "implicit conversion" rules for storing an object.
650  *
651  ******************************************************************************/
652 
653 ACPI_STATUS
654 AcpiExConvertToTargetType (
655     ACPI_OBJECT_TYPE        DestinationType,
656     ACPI_OPERAND_OBJECT     *SourceDesc,
657     ACPI_OPERAND_OBJECT     **ResultDesc,
658     ACPI_WALK_STATE         *WalkState)
659 {
660     ACPI_STATUS             Status = AE_OK;
661 
662 
663     ACPI_FUNCTION_TRACE (ExConvertToTargetType);
664 
665 
666     /* Default behavior */
667 
668     *ResultDesc = SourceDesc;
669 
670     /*
671      * If required by the target,
672      * perform implicit conversion on the source before we store it.
673      */
674     switch (GET_CURRENT_ARG_TYPE (WalkState->OpInfo->RuntimeArgs))
675     {
676     case ARGI_SIMPLE_TARGET:
677     case ARGI_FIXED_TARGET:
678     case ARGI_INTEGER_REF:      /* Handles Increment, Decrement cases */
679 
680         switch (DestinationType)
681         {
682         case ACPI_TYPE_LOCAL_REGION_FIELD:
683             /*
684              * Named field can always handle conversions
685              */
686             break;
687 
688         default:
689 
690             /* No conversion allowed for these types */
691 
692             if (DestinationType != SourceDesc->Common.Type)
693             {
694                 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
695                     "Explicit operator, will store (%s) over existing type (%s)\n",
696                     AcpiUtGetObjectTypeName (SourceDesc),
697                     AcpiUtGetTypeName (DestinationType)));
698                 Status = AE_TYPE;
699             }
700         }
701         break;
702 
703     case ARGI_TARGETREF:
704     case ARGI_STORE_TARGET:
705 
706         switch (DestinationType)
707         {
708         case ACPI_TYPE_INTEGER:
709         case ACPI_TYPE_BUFFER_FIELD:
710         case ACPI_TYPE_LOCAL_BANK_FIELD:
711         case ACPI_TYPE_LOCAL_INDEX_FIELD:
712             /*
713              * These types require an Integer operand. We can convert
714              * a Buffer or a String to an Integer if necessary.
715              */
716             Status = AcpiExConvertToInteger (SourceDesc, ResultDesc,
717                 ACPI_IMPLICIT_CONVERSION);
718             break;
719 
720         case ACPI_TYPE_STRING:
721             /*
722              * The operand must be a String. We can convert an
723              * Integer or Buffer if necessary
724              */
725             Status = AcpiExConvertToString (SourceDesc, ResultDesc,
726                 ACPI_IMPLICIT_CONVERT_HEX);
727             break;
728 
729         case ACPI_TYPE_BUFFER:
730             /*
731              * The operand must be a Buffer. We can convert an
732              * Integer or String if necessary
733              */
734             Status = AcpiExConvertToBuffer (SourceDesc, ResultDesc);
735             break;
736 
737         default:
738 
739             ACPI_ERROR ((AE_INFO,
740                 "Bad destination type during conversion: 0x%X",
741                 DestinationType));
742             Status = AE_AML_INTERNAL;
743             break;
744         }
745         break;
746 
747     case ARGI_REFERENCE:
748         /*
749          * CreateXxxxField cases - we are storing the field object into the name
750          */
751         break;
752 
753     default:
754 
755         ACPI_ERROR ((AE_INFO,
756             "Unknown Target type ID 0x%X AmlOpcode 0x%X DestType %s",
757             GET_CURRENT_ARG_TYPE (WalkState->OpInfo->RuntimeArgs),
758             WalkState->Opcode, AcpiUtGetTypeName (DestinationType)));
759         Status = AE_AML_INTERNAL;
760     }
761 
762     /*
763      * Source-to-Target conversion semantics:
764      *
765      * If conversion to the target type cannot be performed, then simply
766      * overwrite the target with the new object and type.
767      */
768     if (Status == AE_TYPE)
769     {
770         Status = AE_OK;
771     }
772 
773     return_ACPI_STATUS (Status);
774 }
775