xref: /freebsd/sys/contrib/dev/acpica/components/executer/exconvrt.c (revision a98ff317388a00b992f1bf8404dee596f9383f5e)
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 
58 static UINT32
59 AcpiExConvertToAscii (
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 
81 ACPI_STATUS
82 AcpiExConvertToInteger (
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 
221 ACPI_STATUS
222 AcpiExConvertToBuffer (
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 
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 = 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 
437 ACPI_STATUS
438 AcpiExConvertToString (
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 
628 ACPI_STATUS
629 AcpiExConvertToTargetType (
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