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 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 (void) 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