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