1 /****************************************************************************** 2 * 3 * Module Name: exconvrt - Object conversion routines 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2020, 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 #include "acpi.h" 45 #include "accommon.h" 46 #include "acinterp.h" 47 #include "amlcode.h" 48 49 50 #define _COMPONENT ACPI_EXECUTER 51 ACPI_MODULE_NAME ("exconvrt") 52 53 /* Local prototypes */ 54 55 static UINT32 56 AcpiExConvertToAscii ( 57 UINT64 Integer, 58 UINT16 Base, 59 UINT8 *String, 60 UINT8 MaxLength); 61 62 63 /******************************************************************************* 64 * 65 * FUNCTION: AcpiExConvertToInteger 66 * 67 * PARAMETERS: ObjDesc - Object to be converted. Must be an 68 * Integer, Buffer, or String 69 * ResultDesc - Where the new Integer object is returned 70 * ImplicitConversion - Used for string conversion 71 * 72 * RETURN: Status 73 * 74 * DESCRIPTION: Convert an ACPI Object to an integer. 75 * 76 ******************************************************************************/ 77 78 ACPI_STATUS 79 AcpiExConvertToInteger ( 80 ACPI_OPERAND_OBJECT *ObjDesc, 81 ACPI_OPERAND_OBJECT **ResultDesc, 82 UINT32 ImplicitConversion) 83 { 84 ACPI_OPERAND_OBJECT *ReturnDesc; 85 UINT8 *Pointer; 86 UINT64 Result; 87 UINT32 i; 88 UINT32 Count; 89 90 91 ACPI_FUNCTION_TRACE_PTR (ExConvertToInteger, ObjDesc); 92 93 94 switch (ObjDesc->Common.Type) 95 { 96 case ACPI_TYPE_INTEGER: 97 98 /* No conversion necessary */ 99 100 *ResultDesc = ObjDesc; 101 return_ACPI_STATUS (AE_OK); 102 103 case ACPI_TYPE_BUFFER: 104 case ACPI_TYPE_STRING: 105 106 /* Note: Takes advantage of common buffer/string fields */ 107 108 Pointer = ObjDesc->Buffer.Pointer; 109 Count = ObjDesc->Buffer.Length; 110 break; 111 112 default: 113 114 return_ACPI_STATUS (AE_TYPE); 115 } 116 117 /* 118 * Convert the buffer/string to an integer. Note that both buffers and 119 * strings are treated as raw data - we don't convert ascii to hex for 120 * strings. 121 * 122 * There are two terminating conditions for the loop: 123 * 1) The size of an integer has been reached, or 124 * 2) The end of the buffer or string has been reached 125 */ 126 Result = 0; 127 128 /* String conversion is different than Buffer conversion */ 129 130 switch (ObjDesc->Common.Type) 131 { 132 case ACPI_TYPE_STRING: 133 /* 134 * Convert string to an integer - for most cases, the string must be 135 * hexadecimal as per the ACPI specification. The only exception (as 136 * of ACPI 3.0) is that the ToInteger() operator allows both decimal 137 * and hexadecimal strings (hex prefixed with "0x"). 138 * 139 * Explicit conversion is used only by ToInteger. 140 * All other string-to-integer conversions are implicit conversions. 141 */ 142 if (ImplicitConversion) 143 { 144 Result = AcpiUtImplicitStrtoul64 (ACPI_CAST_PTR (char, Pointer)); 145 } 146 else 147 { 148 Result = AcpiUtExplicitStrtoul64 (ACPI_CAST_PTR (char, Pointer)); 149 } 150 break; 151 152 case ACPI_TYPE_BUFFER: 153 154 /* Check for zero-length buffer */ 155 156 if (!Count) 157 { 158 return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); 159 } 160 161 /* Transfer no more than an integer's worth of data */ 162 163 if (Count > AcpiGbl_IntegerByteWidth) 164 { 165 Count = AcpiGbl_IntegerByteWidth; 166 } 167 168 /* 169 * Convert buffer to an integer - we simply grab enough raw data 170 * from the buffer to fill an integer 171 */ 172 for (i = 0; i < Count; i++) 173 { 174 /* 175 * Get next byte and shift it into the Result. 176 * Little endian is used, meaning that the first byte of the buffer 177 * is the LSB of the integer 178 */ 179 Result |= (((UINT64) Pointer[i]) << (i * 8)); 180 } 181 break; 182 183 default: 184 185 /* No other types can get here */ 186 187 break; 188 } 189 190 /* Create a new integer */ 191 192 ReturnDesc = AcpiUtCreateIntegerObject (Result); 193 if (!ReturnDesc) 194 { 195 return_ACPI_STATUS (AE_NO_MEMORY); 196 } 197 198 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", 199 ACPI_FORMAT_UINT64 (Result))); 200 201 /* Save the Result */ 202 203 (void) AcpiExTruncateFor32bitTable (ReturnDesc); 204 *ResultDesc = ReturnDesc; 205 return_ACPI_STATUS (AE_OK); 206 } 207 208 209 /******************************************************************************* 210 * 211 * FUNCTION: AcpiExConvertToBuffer 212 * 213 * PARAMETERS: ObjDesc - Object to be converted. Must be an 214 * Integer, Buffer, or String 215 * ResultDesc - Where the new buffer object is returned 216 * 217 * RETURN: Status 218 * 219 * DESCRIPTION: Convert an ACPI Object to a Buffer 220 * 221 ******************************************************************************/ 222 223 ACPI_STATUS 224 AcpiExConvertToBuffer ( 225 ACPI_OPERAND_OBJECT *ObjDesc, 226 ACPI_OPERAND_OBJECT **ResultDesc) 227 { 228 ACPI_OPERAND_OBJECT *ReturnDesc; 229 UINT8 *NewBuf; 230 231 232 ACPI_FUNCTION_TRACE_PTR (ExConvertToBuffer, ObjDesc); 233 234 235 switch (ObjDesc->Common.Type) 236 { 237 case ACPI_TYPE_BUFFER: 238 239 /* No conversion necessary */ 240 241 *ResultDesc = ObjDesc; 242 return_ACPI_STATUS (AE_OK); 243 244 245 case ACPI_TYPE_INTEGER: 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 memcpy (NewBuf, &ObjDesc->Integer.Value, 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 ((ACPI_SIZE) 273 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 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 = (DataWidth * 2); 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) 397 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. Supports both implicit 435 * and explicit conversions and related rules. 436 * 437 ******************************************************************************/ 438 439 ACPI_STATUS 440 AcpiExConvertToString ( 441 ACPI_OPERAND_OBJECT *ObjDesc, 442 ACPI_OPERAND_OBJECT **ResultDesc, 443 UINT32 Type) 444 { 445 ACPI_OPERAND_OBJECT *ReturnDesc; 446 UINT8 *NewBuf; 447 UINT32 i; 448 UINT32 StringLength = 0; 449 UINT16 Base = 16; 450 UINT8 Separator = ','; 451 452 453 ACPI_FUNCTION_TRACE_PTR (ExConvertToString, ObjDesc); 454 455 456 switch (ObjDesc->Common.Type) 457 { 458 case ACPI_TYPE_STRING: 459 460 /* No conversion necessary */ 461 462 *ResultDesc = ObjDesc; 463 return_ACPI_STATUS (AE_OK); 464 465 case ACPI_TYPE_INTEGER: 466 467 switch (Type) 468 { 469 case ACPI_EXPLICIT_CONVERT_DECIMAL: 470 /* 471 * From ToDecimalString, integer source. 472 * 473 * Make room for the maximum decimal number size 474 */ 475 StringLength = ACPI_MAX_DECIMAL_DIGITS; 476 Base = 10; 477 break; 478 479 default: 480 481 /* Two hex string characters for each integer byte */ 482 483 StringLength = ACPI_MUL_2 (AcpiGbl_IntegerByteWidth); 484 break; 485 } 486 487 /* 488 * Create a new String 489 * Need enough space for one ASCII integer (plus null terminator) 490 */ 491 ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) StringLength); 492 if (!ReturnDesc) 493 { 494 return_ACPI_STATUS (AE_NO_MEMORY); 495 } 496 497 NewBuf = ReturnDesc->Buffer.Pointer; 498 499 /* Convert integer to string */ 500 501 StringLength = AcpiExConvertToAscii ( 502 ObjDesc->Integer.Value, Base, NewBuf, AcpiGbl_IntegerByteWidth); 503 504 /* Null terminate at the correct place */ 505 506 ReturnDesc->String.Length = StringLength; 507 NewBuf [StringLength] = 0; 508 break; 509 510 case ACPI_TYPE_BUFFER: 511 512 /* Setup string length, base, and separator */ 513 514 switch (Type) 515 { 516 case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by ToDecimalString */ 517 /* 518 * Explicit conversion from the ToDecimalString ASL operator. 519 * 520 * From ACPI: "If the input is a buffer, it is converted to a 521 * a string of decimal values separated by commas." 522 */ 523 Base = 10; 524 525 /* 526 * Calculate the final string length. Individual string values 527 * are variable length (include separator for each) 528 */ 529 for (i = 0; i < ObjDesc->Buffer.Length; i++) 530 { 531 if (ObjDesc->Buffer.Pointer[i] >= 100) 532 { 533 StringLength += 4; 534 } 535 else if (ObjDesc->Buffer.Pointer[i] >= 10) 536 { 537 StringLength += 3; 538 } 539 else 540 { 541 StringLength += 2; 542 } 543 } 544 break; 545 546 case ACPI_IMPLICIT_CONVERT_HEX: 547 /* 548 * Implicit buffer-to-string conversion 549 * 550 * From the ACPI spec: 551 * "The entire contents of the buffer are converted to a string of 552 * two-character hexadecimal numbers, each separated by a space." 553 * 554 * Each hex number is prefixed with 0x (11/2018) 555 */ 556 Separator = ' '; 557 StringLength = (ObjDesc->Buffer.Length * 5); 558 break; 559 560 case ACPI_EXPLICIT_CONVERT_HEX: 561 /* 562 * Explicit conversion from the ToHexString ASL operator. 563 * 564 * From ACPI: "If Data is a buffer, it is converted to a string of 565 * hexadecimal values separated by commas." 566 * 567 * Each hex number is prefixed with 0x (11/2018) 568 */ 569 Separator = ','; 570 StringLength = (ObjDesc->Buffer.Length * 5); 571 break; 572 573 default: 574 return_ACPI_STATUS (AE_BAD_PARAMETER); 575 } 576 577 /* 578 * Create a new string object and string buffer 579 * (-1 because of extra separator included in StringLength from above) 580 * Allow creation of zero-length strings from zero-length buffers. 581 */ 582 if (StringLength) 583 { 584 StringLength--; 585 } 586 587 ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) StringLength); 588 if (!ReturnDesc) 589 { 590 return_ACPI_STATUS (AE_NO_MEMORY); 591 } 592 593 NewBuf = ReturnDesc->Buffer.Pointer; 594 595 /* 596 * Convert buffer bytes to hex or decimal values 597 * (separated by commas or spaces) 598 */ 599 for (i = 0; i < ObjDesc->Buffer.Length; i++) 600 { 601 if (Base == 16) 602 { 603 /* Emit 0x prefix for explicit/implicit hex conversion */ 604 605 *NewBuf++ = '0'; 606 *NewBuf++ = 'x'; 607 } 608 609 NewBuf += AcpiExConvertToAscii ( 610 (UINT64) ObjDesc->Buffer.Pointer[i], Base, NewBuf, 1); 611 612 /* Each digit is separated by either a comma or space */ 613 614 *NewBuf++ = Separator; 615 } 616 617 /* 618 * Null terminate the string 619 * (overwrites final comma/space from above) 620 */ 621 if (ObjDesc->Buffer.Length) 622 { 623 NewBuf--; 624 } 625 *NewBuf = 0; 626 break; 627 628 default: 629 630 return_ACPI_STATUS (AE_TYPE); 631 } 632 633 *ResultDesc = ReturnDesc; 634 return_ACPI_STATUS (AE_OK); 635 } 636 637 638 /******************************************************************************* 639 * 640 * FUNCTION: AcpiExConvertToTargetType 641 * 642 * PARAMETERS: DestinationType - Current type of the destination 643 * SourceDesc - Source object to be converted. 644 * ResultDesc - Where the converted object is returned 645 * WalkState - Current method state 646 * 647 * RETURN: Status 648 * 649 * DESCRIPTION: Implements "implicit conversion" rules for storing an object. 650 * 651 ******************************************************************************/ 652 653 ACPI_STATUS 654 AcpiExConvertToTargetType ( 655 ACPI_OBJECT_TYPE DestinationType, 656 ACPI_OPERAND_OBJECT *SourceDesc, 657 ACPI_OPERAND_OBJECT **ResultDesc, 658 ACPI_WALK_STATE *WalkState) 659 { 660 ACPI_STATUS Status = AE_OK; 661 662 663 ACPI_FUNCTION_TRACE (ExConvertToTargetType); 664 665 666 /* Default behavior */ 667 668 *ResultDesc = SourceDesc; 669 670 /* 671 * If required by the target, 672 * perform implicit conversion on the source before we store it. 673 */ 674 switch (GET_CURRENT_ARG_TYPE (WalkState->OpInfo->RuntimeArgs)) 675 { 676 case ARGI_SIMPLE_TARGET: 677 case ARGI_FIXED_TARGET: 678 case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */ 679 680 switch (DestinationType) 681 { 682 case ACPI_TYPE_LOCAL_REGION_FIELD: 683 /* 684 * Named field can always handle conversions 685 */ 686 break; 687 688 default: 689 690 /* No conversion allowed for these types */ 691 692 if (DestinationType != SourceDesc->Common.Type) 693 { 694 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 695 "Explicit operator, will store (%s) over existing type (%s)\n", 696 AcpiUtGetObjectTypeName (SourceDesc), 697 AcpiUtGetTypeName (DestinationType))); 698 Status = AE_TYPE; 699 } 700 } 701 break; 702 703 case ARGI_TARGETREF: 704 case ARGI_STORE_TARGET: 705 706 switch (DestinationType) 707 { 708 case ACPI_TYPE_INTEGER: 709 case ACPI_TYPE_BUFFER_FIELD: 710 case ACPI_TYPE_LOCAL_BANK_FIELD: 711 case ACPI_TYPE_LOCAL_INDEX_FIELD: 712 /* 713 * These types require an Integer operand. We can convert 714 * a Buffer or a String to an Integer if necessary. 715 */ 716 Status = AcpiExConvertToInteger (SourceDesc, ResultDesc, 717 ACPI_IMPLICIT_CONVERSION); 718 break; 719 720 case ACPI_TYPE_STRING: 721 /* 722 * The operand must be a String. We can convert an 723 * Integer or Buffer if necessary 724 */ 725 Status = AcpiExConvertToString (SourceDesc, ResultDesc, 726 ACPI_IMPLICIT_CONVERT_HEX); 727 break; 728 729 case ACPI_TYPE_BUFFER: 730 /* 731 * The operand must be a Buffer. We can convert an 732 * Integer or String if necessary 733 */ 734 Status = AcpiExConvertToBuffer (SourceDesc, ResultDesc); 735 break; 736 737 default: 738 739 ACPI_ERROR ((AE_INFO, 740 "Bad destination type during conversion: 0x%X", 741 DestinationType)); 742 Status = AE_AML_INTERNAL; 743 break; 744 } 745 break; 746 747 case ARGI_REFERENCE: 748 /* 749 * CreateXxxxField cases - we are storing the field object into the name 750 */ 751 break; 752 753 default: 754 755 ACPI_ERROR ((AE_INFO, 756 "Unknown Target type ID 0x%X AmlOpcode 0x%X DestType %s", 757 GET_CURRENT_ARG_TYPE (WalkState->OpInfo->RuntimeArgs), 758 WalkState->Opcode, AcpiUtGetTypeName (DestinationType))); 759 Status = AE_AML_INTERNAL; 760 } 761 762 /* 763 * Source-to-Target conversion semantics: 764 * 765 * If conversion to the target type cannot be performed, then simply 766 * overwrite the target with the new object and type. 767 */ 768 if (Status == AE_TYPE) 769 { 770 Status = AE_OK; 771 } 772 773 return_ACPI_STATUS (Status); 774 } 775