exconvrt.c revision 1.1.1.3 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 "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
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