1 /****************************************************************************** 2 * 3 * Module Name: exconvrt - Object conversion routines 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, 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 <contrib/dev/acpica/include/acpi.h> 45 #include <contrib/dev/acpica/include/accommon.h> 46 #include <contrib/dev/acpica/include/acinterp.h> 47 #include <contrib/dev/acpica/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, 255 &ObjDesc->Integer.Value, 256 AcpiGbl_IntegerByteWidth); 257 break; 258 259 case ACPI_TYPE_STRING: 260 /* 261 * Create a new Buffer object 262 * Size will be the string length 263 * 264 * NOTE: Add one to the string length to include the null terminator. 265 * The ACPI spec is unclear on this subject, but there is existing 266 * ASL/AML code that depends on the null being transferred to the new 267 * buffer. 268 */ 269 ReturnDesc = AcpiUtCreateBufferObject ( 270 (ACPI_SIZE) ObjDesc->String.Length + 1); 271 if (!ReturnDesc) 272 { 273 return_ACPI_STATUS (AE_NO_MEMORY); 274 } 275 276 /* Copy the string to the buffer */ 277 278 NewBuf = ReturnDesc->Buffer.Pointer; 279 strncpy ((char *) NewBuf, (char *) ObjDesc->String.Pointer, 280 ObjDesc->String.Length); 281 break; 282 283 default: 284 285 return_ACPI_STATUS (AE_TYPE); 286 } 287 288 /* Mark buffer initialized */ 289 290 ReturnDesc->Common.Flags |= AOPOBJ_DATA_VALID; 291 *ResultDesc = ReturnDesc; 292 return_ACPI_STATUS (AE_OK); 293 } 294 295 296 /******************************************************************************* 297 * 298 * FUNCTION: AcpiExConvertToAscii 299 * 300 * PARAMETERS: Integer - Value to be converted 301 * Base - ACPI_STRING_DECIMAL or ACPI_STRING_HEX 302 * String - Where the string is returned 303 * DataWidth - Size of data item to be converted, in bytes 304 * 305 * RETURN: Actual string length 306 * 307 * DESCRIPTION: Convert an ACPI Integer to a hex or decimal string 308 * 309 ******************************************************************************/ 310 311 static UINT32 312 AcpiExConvertToAscii ( 313 UINT64 Integer, 314 UINT16 Base, 315 UINT8 *String, 316 UINT8 DataWidth) 317 { 318 UINT64 Digit; 319 UINT32 i; 320 UINT32 j; 321 UINT32 k = 0; 322 UINT32 HexLength; 323 UINT32 DecimalLength; 324 UINT32 Remainder; 325 BOOLEAN SupressZeros; 326 327 328 ACPI_FUNCTION_ENTRY (); 329 330 331 switch (Base) 332 { 333 case 10: 334 335 /* Setup max length for the decimal number */ 336 337 switch (DataWidth) 338 { 339 case 1: 340 341 DecimalLength = ACPI_MAX8_DECIMAL_DIGITS; 342 break; 343 344 case 4: 345 346 DecimalLength = ACPI_MAX32_DECIMAL_DIGITS; 347 break; 348 349 case 8: 350 default: 351 352 DecimalLength = ACPI_MAX64_DECIMAL_DIGITS; 353 break; 354 } 355 356 SupressZeros = TRUE; /* No leading zeros */ 357 Remainder = 0; 358 359 for (i = DecimalLength; i > 0; i--) 360 { 361 /* Divide by nth factor of 10 */ 362 363 Digit = Integer; 364 for (j = 0; j < i; j++) 365 { 366 (void) AcpiUtShortDivide (Digit, 10, &Digit, &Remainder); 367 } 368 369 /* Handle leading zeros */ 370 371 if (Remainder != 0) 372 { 373 SupressZeros = FALSE; 374 } 375 376 if (!SupressZeros) 377 { 378 String[k] = (UINT8) (ACPI_ASCII_ZERO + Remainder); 379 k++; 380 } 381 } 382 break; 383 384 case 16: 385 386 /* HexLength: 2 ascii hex chars per data byte */ 387 388 HexLength = ACPI_MUL_2 (DataWidth); 389 for (i = 0, j = (HexLength-1); i < HexLength; i++, j--) 390 { 391 /* Get one hex digit, most significant digits first */ 392 393 String[k] = (UINT8) AcpiUtHexToAsciiChar (Integer, ACPI_MUL_4 (j)); 394 k++; 395 } 396 break; 397 398 default: 399 return (0); 400 } 401 402 /* 403 * Since leading zeros are suppressed, we must check for the case where 404 * the integer equals 0 405 * 406 * Finally, null terminate the string and return the length 407 */ 408 if (!k) 409 { 410 String [0] = ACPI_ASCII_ZERO; 411 k = 1; 412 } 413 414 String [k] = 0; 415 return ((UINT32) k); 416 } 417 418 419 /******************************************************************************* 420 * 421 * FUNCTION: AcpiExConvertToString 422 * 423 * PARAMETERS: ObjDesc - Object to be converted. Must be an 424 * Integer, Buffer, or String 425 * ResultDesc - Where the string object is returned 426 * Type - String flags (base and conversion type) 427 * 428 * RETURN: Status 429 * 430 * DESCRIPTION: Convert an ACPI Object to a string 431 * 432 ******************************************************************************/ 433 434 ACPI_STATUS 435 AcpiExConvertToString ( 436 ACPI_OPERAND_OBJECT *ObjDesc, 437 ACPI_OPERAND_OBJECT **ResultDesc, 438 UINT32 Type) 439 { 440 ACPI_OPERAND_OBJECT *ReturnDesc; 441 UINT8 *NewBuf; 442 UINT32 i; 443 UINT32 StringLength = 0; 444 UINT16 Base = 16; 445 UINT8 Separator = ','; 446 447 448 ACPI_FUNCTION_TRACE_PTR (ExConvertToString, ObjDesc); 449 450 451 switch (ObjDesc->Common.Type) 452 { 453 case ACPI_TYPE_STRING: 454 455 /* No conversion necessary */ 456 457 *ResultDesc = ObjDesc; 458 return_ACPI_STATUS (AE_OK); 459 460 case ACPI_TYPE_INTEGER: 461 462 switch (Type) 463 { 464 case ACPI_EXPLICIT_CONVERT_DECIMAL: 465 466 /* Make room for maximum decimal number */ 467 468 StringLength = ACPI_MAX_DECIMAL_DIGITS; 469 Base = 10; 470 break; 471 472 default: 473 474 /* Two hex string characters for each integer byte */ 475 476 StringLength = ACPI_MUL_2 (AcpiGbl_IntegerByteWidth); 477 break; 478 } 479 480 /* 481 * Create a new String 482 * Need enough space for one ASCII integer (plus null terminator) 483 */ 484 ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) StringLength); 485 if (!ReturnDesc) 486 { 487 return_ACPI_STATUS (AE_NO_MEMORY); 488 } 489 490 NewBuf = ReturnDesc->Buffer.Pointer; 491 492 /* Convert integer to string */ 493 494 StringLength = AcpiExConvertToAscii (ObjDesc->Integer.Value, Base, 495 NewBuf, AcpiGbl_IntegerByteWidth); 496 497 /* Null terminate at the correct place */ 498 499 ReturnDesc->String.Length = StringLength; 500 NewBuf [StringLength] = 0; 501 break; 502 503 case ACPI_TYPE_BUFFER: 504 505 /* Setup string length, base, and separator */ 506 507 switch (Type) 508 { 509 case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by ToDecimalString */ 510 /* 511 * From ACPI: "If Data is a buffer, it is converted to a string of 512 * decimal values separated by commas." 513 */ 514 Base = 10; 515 516 /* 517 * Calculate the final string length. Individual string values 518 * are variable length (include separator for each) 519 */ 520 for (i = 0; i < ObjDesc->Buffer.Length; i++) 521 { 522 if (ObjDesc->Buffer.Pointer[i] >= 100) 523 { 524 StringLength += 4; 525 } 526 else if (ObjDesc->Buffer.Pointer[i] >= 10) 527 { 528 StringLength += 3; 529 } 530 else 531 { 532 StringLength += 2; 533 } 534 } 535 break; 536 537 case ACPI_IMPLICIT_CONVERT_HEX: 538 /* 539 * From the ACPI spec: 540 *"The entire contents of the buffer are converted to a string of 541 * two-character hexadecimal numbers, each separated by a space." 542 */ 543 Separator = ' '; 544 StringLength = (ObjDesc->Buffer.Length * 3); 545 break; 546 547 case ACPI_EXPLICIT_CONVERT_HEX: /* Used by ToHexString */ 548 /* 549 * From ACPI: "If Data is a buffer, it is converted to a string of 550 * hexadecimal values separated by commas." 551 */ 552 StringLength = (ObjDesc->Buffer.Length * 3); 553 break; 554 555 default: 556 return_ACPI_STATUS (AE_BAD_PARAMETER); 557 } 558 559 /* 560 * Create a new string object and string buffer 561 * (-1 because of extra separator included in StringLength from above) 562 * Allow creation of zero-length strings from zero-length buffers. 563 */ 564 if (StringLength) 565 { 566 StringLength--; 567 } 568 569 ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) StringLength); 570 if (!ReturnDesc) 571 { 572 return_ACPI_STATUS (AE_NO_MEMORY); 573 } 574 575 NewBuf = ReturnDesc->Buffer.Pointer; 576 577 /* 578 * Convert buffer bytes to hex or decimal values 579 * (separated by commas or spaces) 580 */ 581 for (i = 0; i < ObjDesc->Buffer.Length; i++) 582 { 583 NewBuf += AcpiExConvertToAscii ( 584 (UINT64) ObjDesc->Buffer.Pointer[i], Base, 585 NewBuf, 1); 586 *NewBuf++ = Separator; /* each separated by a comma or space */ 587 } 588 589 /* 590 * Null terminate the string 591 * (overwrites final comma/space from above) 592 */ 593 if (ObjDesc->Buffer.Length) 594 { 595 NewBuf--; 596 } 597 *NewBuf = 0; 598 break; 599 600 default: 601 602 return_ACPI_STATUS (AE_TYPE); 603 } 604 605 *ResultDesc = ReturnDesc; 606 return_ACPI_STATUS (AE_OK); 607 } 608 609 610 /******************************************************************************* 611 * 612 * FUNCTION: AcpiExConvertToTargetType 613 * 614 * PARAMETERS: DestinationType - Current type of the destination 615 * SourceDesc - Source object to be converted. 616 * ResultDesc - Where the converted object is returned 617 * WalkState - Current method state 618 * 619 * RETURN: Status 620 * 621 * DESCRIPTION: Implements "implicit conversion" rules for storing an object. 622 * 623 ******************************************************************************/ 624 625 ACPI_STATUS 626 AcpiExConvertToTargetType ( 627 ACPI_OBJECT_TYPE DestinationType, 628 ACPI_OPERAND_OBJECT *SourceDesc, 629 ACPI_OPERAND_OBJECT **ResultDesc, 630 ACPI_WALK_STATE *WalkState) 631 { 632 ACPI_STATUS Status = AE_OK; 633 634 635 ACPI_FUNCTION_TRACE (ExConvertToTargetType); 636 637 638 /* Default behavior */ 639 640 *ResultDesc = SourceDesc; 641 642 /* 643 * If required by the target, 644 * perform implicit conversion on the source before we store it. 645 */ 646 switch (GET_CURRENT_ARG_TYPE (WalkState->OpInfo->RuntimeArgs)) 647 { 648 case ARGI_SIMPLE_TARGET: 649 case ARGI_FIXED_TARGET: 650 case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */ 651 652 switch (DestinationType) 653 { 654 case ACPI_TYPE_LOCAL_REGION_FIELD: 655 /* 656 * Named field can always handle conversions 657 */ 658 break; 659 660 default: 661 662 /* No conversion allowed for these types */ 663 664 if (DestinationType != SourceDesc->Common.Type) 665 { 666 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 667 "Explicit operator, will store (%s) over existing type (%s)\n", 668 AcpiUtGetObjectTypeName (SourceDesc), 669 AcpiUtGetTypeName (DestinationType))); 670 Status = AE_TYPE; 671 } 672 } 673 break; 674 675 case ARGI_TARGETREF: 676 677 switch (DestinationType) 678 { 679 case ACPI_TYPE_INTEGER: 680 case ACPI_TYPE_BUFFER_FIELD: 681 case ACPI_TYPE_LOCAL_BANK_FIELD: 682 case ACPI_TYPE_LOCAL_INDEX_FIELD: 683 /* 684 * These types require an Integer operand. We can convert 685 * a Buffer or a String to an Integer if necessary. 686 */ 687 Status = AcpiExConvertToInteger (SourceDesc, ResultDesc, 688 16); 689 break; 690 691 case ACPI_TYPE_STRING: 692 /* 693 * The operand must be a String. We can convert an 694 * Integer or Buffer if necessary 695 */ 696 Status = AcpiExConvertToString (SourceDesc, ResultDesc, 697 ACPI_IMPLICIT_CONVERT_HEX); 698 break; 699 700 case ACPI_TYPE_BUFFER: 701 /* 702 * The operand must be a Buffer. We can convert an 703 * Integer or String if necessary 704 */ 705 Status = AcpiExConvertToBuffer (SourceDesc, ResultDesc); 706 break; 707 708 default: 709 710 ACPI_ERROR ((AE_INFO, "Bad destination type during conversion: 0x%X", 711 DestinationType)); 712 Status = AE_AML_INTERNAL; 713 break; 714 } 715 break; 716 717 case ARGI_REFERENCE: 718 /* 719 * CreateXxxxField cases - we are storing the field object into the name 720 */ 721 break; 722 723 default: 724 725 ACPI_ERROR ((AE_INFO, 726 "Unknown Target type ID 0x%X AmlOpcode 0x%X DestType %s", 727 GET_CURRENT_ARG_TYPE (WalkState->OpInfo->RuntimeArgs), 728 WalkState->Opcode, AcpiUtGetTypeName (DestinationType))); 729 Status = AE_AML_INTERNAL; 730 } 731 732 /* 733 * Source-to-Target conversion semantics: 734 * 735 * If conversion to the target type cannot be performed, then simply 736 * overwrite the target with the new object and type. 737 */ 738 if (Status == AE_TYPE) 739 { 740 Status = AE_OK; 741 } 742 743 return_ACPI_STATUS (Status); 744 } 745