1 /****************************************************************************** 2 * 3 * Module Name: exconvrt - Object conversion routines 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 * Flags - 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 Flags) 83 { 84 ACPI_OPERAND_OBJECT *ReturnDesc; 85 UINT8 *Pointer; 86 UINT64 Result; 87 UINT32 i; 88 UINT32 Count; 89 ACPI_STATUS Status; 90 91 92 ACPI_FUNCTION_TRACE_PTR (ExConvertToInteger, ObjDesc); 93 94 95 switch (ObjDesc->Common.Type) 96 { 97 case ACPI_TYPE_INTEGER: 98 99 /* No conversion necessary */ 100 101 *ResultDesc = ObjDesc; 102 return_ACPI_STATUS (AE_OK); 103 104 case ACPI_TYPE_BUFFER: 105 case ACPI_TYPE_STRING: 106 107 /* Note: Takes advantage of common buffer/string fields */ 108 109 Pointer = ObjDesc->Buffer.Pointer; 110 Count = ObjDesc->Buffer.Length; 111 break; 112 113 default: 114 115 return_ACPI_STATUS (AE_TYPE); 116 } 117 118 /* 119 * Convert the buffer/string to an integer. Note that both buffers and 120 * strings are treated as raw data - we don't convert ascii to hex for 121 * strings. 122 * 123 * There are two terminating conditions for the loop: 124 * 1) The size of an integer has been reached, or 125 * 2) The end of the buffer or string has been reached 126 */ 127 Result = 0; 128 129 /* String conversion is different than Buffer conversion */ 130 131 switch (ObjDesc->Common.Type) 132 { 133 case ACPI_TYPE_STRING: 134 /* 135 * Convert string to an integer - for most cases, the string must be 136 * hexadecimal as per the ACPI specification. The only exception (as 137 * of ACPI 3.0) is that the ToInteger() operator allows both decimal 138 * and hexadecimal strings (hex prefixed with "0x"). 139 */ 140 Status = AcpiUtStrtoul64 ((char *) Pointer, Flags, &Result); 141 if (ACPI_FAILURE (Status)) 142 { 143 return_ACPI_STATUS (Status); 144 } 145 break; 146 147 case ACPI_TYPE_BUFFER: 148 149 /* Check for zero-length buffer */ 150 151 if (!Count) 152 { 153 return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); 154 } 155 156 /* Transfer no more than an integer's worth of data */ 157 158 if (Count > AcpiGbl_IntegerByteWidth) 159 { 160 Count = AcpiGbl_IntegerByteWidth; 161 } 162 163 /* 164 * Convert buffer to an integer - we simply grab enough raw data 165 * from the buffer to fill an integer 166 */ 167 for (i = 0; i < Count; i++) 168 { 169 /* 170 * Get next byte and shift it into the Result. 171 * Little endian is used, meaning that the first byte of the buffer 172 * is the LSB of the integer 173 */ 174 Result |= (((UINT64) Pointer[i]) << (i * 8)); 175 } 176 break; 177 178 default: 179 180 /* No other types can get here */ 181 182 break; 183 } 184 185 /* Create a new integer */ 186 187 ReturnDesc = AcpiUtCreateIntegerObject (Result); 188 if (!ReturnDesc) 189 { 190 return_ACPI_STATUS (AE_NO_MEMORY); 191 } 192 193 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", 194 ACPI_FORMAT_UINT64 (Result))); 195 196 /* Save the Result */ 197 198 (void) AcpiExTruncateFor32bitTable (ReturnDesc); 199 *ResultDesc = ReturnDesc; 200 return_ACPI_STATUS (AE_OK); 201 } 202 203 204 /******************************************************************************* 205 * 206 * FUNCTION: AcpiExConvertToBuffer 207 * 208 * PARAMETERS: ObjDesc - Object to be converted. Must be an 209 * Integer, Buffer, or String 210 * ResultDesc - Where the new buffer object is returned 211 * 212 * RETURN: Status 213 * 214 * DESCRIPTION: Convert an ACPI Object to a Buffer 215 * 216 ******************************************************************************/ 217 218 ACPI_STATUS 219 AcpiExConvertToBuffer ( 220 ACPI_OPERAND_OBJECT *ObjDesc, 221 ACPI_OPERAND_OBJECT **ResultDesc) 222 { 223 ACPI_OPERAND_OBJECT *ReturnDesc; 224 UINT8 *NewBuf; 225 226 227 ACPI_FUNCTION_TRACE_PTR (ExConvertToBuffer, ObjDesc); 228 229 230 switch (ObjDesc->Common.Type) 231 { 232 case ACPI_TYPE_BUFFER: 233 234 /* No conversion necessary */ 235 236 *ResultDesc = ObjDesc; 237 return_ACPI_STATUS (AE_OK); 238 239 240 case ACPI_TYPE_INTEGER: 241 /* 242 * Create a new Buffer object. 243 * Need enough space for one integer 244 */ 245 ReturnDesc = AcpiUtCreateBufferObject (AcpiGbl_IntegerByteWidth); 246 if (!ReturnDesc) 247 { 248 return_ACPI_STATUS (AE_NO_MEMORY); 249 } 250 251 /* Copy the integer to the buffer, LSB first */ 252 253 NewBuf = ReturnDesc->Buffer.Pointer; 254 memcpy (NewBuf, &ObjDesc->Integer.Value, AcpiGbl_IntegerByteWidth); 255 break; 256 257 case ACPI_TYPE_STRING: 258 /* 259 * Create a new Buffer object 260 * Size will be the string length 261 * 262 * NOTE: Add one to the string length to include the null terminator. 263 * The ACPI spec is unclear on this subject, but there is existing 264 * ASL/AML code that depends on the null being transferred to the new 265 * buffer. 266 */ 267 ReturnDesc = AcpiUtCreateBufferObject ((ACPI_SIZE) 268 ObjDesc->String.Length + 1); 269 if (!ReturnDesc) 270 { 271 return_ACPI_STATUS (AE_NO_MEMORY); 272 } 273 274 /* Copy the string to the buffer */ 275 276 NewBuf = ReturnDesc->Buffer.Pointer; 277 strncpy ((char *) NewBuf, (char *) ObjDesc->String.Pointer, 278 ObjDesc->String.Length); 279 break; 280 281 default: 282 283 return_ACPI_STATUS (AE_TYPE); 284 } 285 286 /* Mark buffer initialized */ 287 288 ReturnDesc->Common.Flags |= AOPOBJ_DATA_VALID; 289 *ResultDesc = ReturnDesc; 290 return_ACPI_STATUS (AE_OK); 291 } 292 293 294 /******************************************************************************* 295 * 296 * FUNCTION: AcpiExConvertToAscii 297 * 298 * PARAMETERS: Integer - Value to be converted 299 * Base - ACPI_STRING_DECIMAL or ACPI_STRING_HEX 300 * String - Where the string is returned 301 * DataWidth - Size of data item to be converted, in bytes 302 * 303 * RETURN: Actual string length 304 * 305 * DESCRIPTION: Convert an ACPI Integer to a hex or decimal string 306 * 307 ******************************************************************************/ 308 309 static UINT32 310 AcpiExConvertToAscii ( 311 UINT64 Integer, 312 UINT16 Base, 313 UINT8 *String, 314 UINT8 DataWidth) 315 { 316 UINT64 Digit; 317 UINT32 i; 318 UINT32 j; 319 UINT32 k = 0; 320 UINT32 HexLength; 321 UINT32 DecimalLength; 322 UINT32 Remainder; 323 BOOLEAN SupressZeros; 324 325 326 ACPI_FUNCTION_ENTRY (); 327 328 329 switch (Base) 330 { 331 case 10: 332 333 /* Setup max length for the decimal number */ 334 335 switch (DataWidth) 336 { 337 case 1: 338 339 DecimalLength = ACPI_MAX8_DECIMAL_DIGITS; 340 break; 341 342 case 4: 343 344 DecimalLength = ACPI_MAX32_DECIMAL_DIGITS; 345 break; 346 347 case 8: 348 default: 349 350 DecimalLength = ACPI_MAX64_DECIMAL_DIGITS; 351 break; 352 } 353 354 SupressZeros = TRUE; /* No leading zeros */ 355 Remainder = 0; 356 357 for (i = DecimalLength; i > 0; i--) 358 { 359 /* Divide by nth factor of 10 */ 360 361 Digit = Integer; 362 for (j = 0; j < i; j++) 363 { 364 (void) AcpiUtShortDivide (Digit, 10, &Digit, &Remainder); 365 } 366 367 /* Handle leading zeros */ 368 369 if (Remainder != 0) 370 { 371 SupressZeros = FALSE; 372 } 373 374 if (!SupressZeros) 375 { 376 String[k] = (UINT8) (ACPI_ASCII_ZERO + Remainder); 377 k++; 378 } 379 } 380 break; 381 382 case 16: 383 384 /* HexLength: 2 ascii hex chars per data byte */ 385 386 HexLength = ACPI_MUL_2 (DataWidth); 387 for (i = 0, j = (HexLength-1); i < HexLength; i++, j--) 388 { 389 /* Get one hex digit, most significant digits first */ 390 391 String[k] = (UINT8) 392 AcpiUtHexToAsciiChar (Integer, ACPI_MUL_4 (j)); 393 k++; 394 } 395 break; 396 397 default: 398 return (0); 399 } 400 401 /* 402 * Since leading zeros are suppressed, we must check for the case where 403 * the integer equals 0 404 * 405 * Finally, null terminate the string and return the length 406 */ 407 if (!k) 408 { 409 String [0] = ACPI_ASCII_ZERO; 410 k = 1; 411 } 412 413 String [k] = 0; 414 return ((UINT32) k); 415 } 416 417 418 /******************************************************************************* 419 * 420 * FUNCTION: AcpiExConvertToString 421 * 422 * PARAMETERS: ObjDesc - Object to be converted. Must be an 423 * Integer, Buffer, or String 424 * ResultDesc - Where the string object is returned 425 * Type - String flags (base and conversion type) 426 * 427 * RETURN: Status 428 * 429 * DESCRIPTION: Convert an ACPI Object to a string 430 * 431 ******************************************************************************/ 432 433 ACPI_STATUS 434 AcpiExConvertToString ( 435 ACPI_OPERAND_OBJECT *ObjDesc, 436 ACPI_OPERAND_OBJECT **ResultDesc, 437 UINT32 Type) 438 { 439 ACPI_OPERAND_OBJECT *ReturnDesc; 440 UINT8 *NewBuf; 441 UINT32 i; 442 UINT32 StringLength = 0; 443 UINT16 Base = 16; 444 UINT8 Separator = ','; 445 446 447 ACPI_FUNCTION_TRACE_PTR (ExConvertToString, ObjDesc); 448 449 450 switch (ObjDesc->Common.Type) 451 { 452 case ACPI_TYPE_STRING: 453 454 /* No conversion necessary */ 455 456 *ResultDesc = ObjDesc; 457 return_ACPI_STATUS (AE_OK); 458 459 case ACPI_TYPE_INTEGER: 460 461 switch (Type) 462 { 463 case ACPI_EXPLICIT_CONVERT_DECIMAL: 464 465 /* Make room for maximum decimal number */ 466 467 StringLength = ACPI_MAX_DECIMAL_DIGITS; 468 Base = 10; 469 break; 470 471 default: 472 473 /* Two hex string characters for each integer byte */ 474 475 StringLength = ACPI_MUL_2 (AcpiGbl_IntegerByteWidth); 476 break; 477 } 478 479 /* 480 * Create a new String 481 * Need enough space for one ASCII integer (plus null terminator) 482 */ 483 ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) StringLength); 484 if (!ReturnDesc) 485 { 486 return_ACPI_STATUS (AE_NO_MEMORY); 487 } 488 489 NewBuf = ReturnDesc->Buffer.Pointer; 490 491 /* Convert integer to string */ 492 493 StringLength = AcpiExConvertToAscii ( 494 ObjDesc->Integer.Value, Base, NewBuf, AcpiGbl_IntegerByteWidth); 495 496 /* Null terminate at the correct place */ 497 498 ReturnDesc->String.Length = StringLength; 499 NewBuf [StringLength] = 0; 500 break; 501 502 case ACPI_TYPE_BUFFER: 503 504 /* Setup string length, base, and separator */ 505 506 switch (Type) 507 { 508 case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by ToDecimalString */ 509 /* 510 * From ACPI: "If Data is a buffer, it is converted to a string of 511 * decimal values separated by commas." 512 */ 513 Base = 10; 514 515 /* 516 * Calculate the final string length. Individual string values 517 * are variable length (include separator for each) 518 */ 519 for (i = 0; i < ObjDesc->Buffer.Length; i++) 520 { 521 if (ObjDesc->Buffer.Pointer[i] >= 100) 522 { 523 StringLength += 4; 524 } 525 else if (ObjDesc->Buffer.Pointer[i] >= 10) 526 { 527 StringLength += 3; 528 } 529 else 530 { 531 StringLength += 2; 532 } 533 } 534 break; 535 536 case ACPI_IMPLICIT_CONVERT_HEX: 537 /* 538 * From the ACPI spec: 539 *"The entire contents of the buffer are converted to a string of 540 * two-character hexadecimal numbers, each separated by a space." 541 */ 542 Separator = ' '; 543 StringLength = (ObjDesc->Buffer.Length * 3); 544 break; 545 546 case ACPI_EXPLICIT_CONVERT_HEX: /* Used by ToHexString */ 547 /* 548 * From ACPI: "If Data is a buffer, it is converted to a string of 549 * hexadecimal values separated by commas." 550 */ 551 StringLength = (ObjDesc->Buffer.Length * 3); 552 break; 553 554 default: 555 return_ACPI_STATUS (AE_BAD_PARAMETER); 556 } 557 558 /* 559 * Create a new string object and string buffer 560 * (-1 because of extra separator included in StringLength from above) 561 * Allow creation of zero-length strings from zero-length buffers. 562 */ 563 if (StringLength) 564 { 565 StringLength--; 566 } 567 568 ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) StringLength); 569 if (!ReturnDesc) 570 { 571 return_ACPI_STATUS (AE_NO_MEMORY); 572 } 573 574 NewBuf = ReturnDesc->Buffer.Pointer; 575 576 /* 577 * Convert buffer bytes to hex or decimal values 578 * (separated by commas or spaces) 579 */ 580 for (i = 0; i < ObjDesc->Buffer.Length; i++) 581 { 582 NewBuf += AcpiExConvertToAscii ( 583 (UINT64) ObjDesc->Buffer.Pointer[i], Base, NewBuf, 1); 584 *NewBuf++ = Separator; /* each separated by a comma or space */ 585 } 586 587 /* 588 * Null terminate the string 589 * (overwrites final comma/space from above) 590 */ 591 if (ObjDesc->Buffer.Length) 592 { 593 NewBuf--; 594 } 595 *NewBuf = 0; 596 break; 597 598 default: 599 600 return_ACPI_STATUS (AE_TYPE); 601 } 602 603 *ResultDesc = ReturnDesc; 604 return_ACPI_STATUS (AE_OK); 605 } 606 607 608 /******************************************************************************* 609 * 610 * FUNCTION: AcpiExConvertToTargetType 611 * 612 * PARAMETERS: DestinationType - Current type of the destination 613 * SourceDesc - Source object to be converted. 614 * ResultDesc - Where the converted object is returned 615 * WalkState - Current method state 616 * 617 * RETURN: Status 618 * 619 * DESCRIPTION: Implements "implicit conversion" rules for storing an object. 620 * 621 ******************************************************************************/ 622 623 ACPI_STATUS 624 AcpiExConvertToTargetType ( 625 ACPI_OBJECT_TYPE DestinationType, 626 ACPI_OPERAND_OBJECT *SourceDesc, 627 ACPI_OPERAND_OBJECT **ResultDesc, 628 ACPI_WALK_STATE *WalkState) 629 { 630 ACPI_STATUS Status = AE_OK; 631 632 633 ACPI_FUNCTION_TRACE (ExConvertToTargetType); 634 635 636 /* Default behavior */ 637 638 *ResultDesc = SourceDesc; 639 640 /* 641 * If required by the target, 642 * perform implicit conversion on the source before we store it. 643 */ 644 switch (GET_CURRENT_ARG_TYPE (WalkState->OpInfo->RuntimeArgs)) 645 { 646 case ARGI_SIMPLE_TARGET: 647 case ARGI_FIXED_TARGET: 648 case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */ 649 650 switch (DestinationType) 651 { 652 case ACPI_TYPE_LOCAL_REGION_FIELD: 653 /* 654 * Named field can always handle conversions 655 */ 656 break; 657 658 default: 659 660 /* No conversion allowed for these types */ 661 662 if (DestinationType != SourceDesc->Common.Type) 663 { 664 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 665 "Explicit operator, will store (%s) over existing type (%s)\n", 666 AcpiUtGetObjectTypeName (SourceDesc), 667 AcpiUtGetTypeName (DestinationType))); 668 Status = AE_TYPE; 669 } 670 } 671 break; 672 673 case ARGI_TARGETREF: 674 case ARGI_STORE_TARGET: 675 676 switch (DestinationType) 677 { 678 case ACPI_TYPE_INTEGER: 679 case ACPI_TYPE_BUFFER_FIELD: 680 case ACPI_TYPE_LOCAL_BANK_FIELD: 681 case ACPI_TYPE_LOCAL_INDEX_FIELD: 682 /* 683 * These types require an Integer operand. We can convert 684 * a Buffer or a String to an Integer if necessary. 685 */ 686 Status = AcpiExConvertToInteger (SourceDesc, ResultDesc, 16); 687 break; 688 689 case ACPI_TYPE_STRING: 690 /* 691 * The operand must be a String. We can convert an 692 * Integer or Buffer if necessary 693 */ 694 Status = AcpiExConvertToString (SourceDesc, ResultDesc, 695 ACPI_IMPLICIT_CONVERT_HEX); 696 break; 697 698 case ACPI_TYPE_BUFFER: 699 /* 700 * The operand must be a Buffer. We can convert an 701 * Integer or String if necessary 702 */ 703 Status = AcpiExConvertToBuffer (SourceDesc, ResultDesc); 704 break; 705 706 default: 707 708 ACPI_ERROR ((AE_INFO, 709 "Bad destination type during conversion: 0x%X", 710 DestinationType)); 711 Status = AE_AML_INTERNAL; 712 break; 713 } 714 break; 715 716 case ARGI_REFERENCE: 717 /* 718 * CreateXxxxField cases - we are storing the field object into the name 719 */ 720 break; 721 722 default: 723 724 ACPI_ERROR ((AE_INFO, 725 "Unknown Target type ID 0x%X AmlOpcode 0x%X DestType %s", 726 GET_CURRENT_ARG_TYPE (WalkState->OpInfo->RuntimeArgs), 727 WalkState->Opcode, AcpiUtGetTypeName (DestinationType))); 728 Status = AE_AML_INTERNAL; 729 } 730 731 /* 732 * Source-to-Target conversion semantics: 733 * 734 * If conversion to the target type cannot be performed, then simply 735 * overwrite the target with the new object and type. 736 */ 737 if (Status == AE_TYPE) 738 { 739 Status = AE_OK; 740 } 741 742 return_ACPI_STATUS (Status); 743 } 744