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