exconvrt.c revision 1.1.1.2.4.2 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 "acpi.h"
48 #include "accommon.h"
49 #include "acinterp.h"
50 #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 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
222 ACPI_STATUS
223 AcpiExConvertToBuffer (
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
318 static UINT32
319 AcpiExConvertToAscii (
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
438 ACPI_STATUS
439 AcpiExConvertToString (
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
630 ACPI_STATUS
631 AcpiExConvertToTargetType (
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