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 <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, 141 AcpiGbl_IntegerByteWidth, &Result); 142 if (ACPI_FAILURE (Status)) 143 { 144 return_ACPI_STATUS (Status); 145 } 146 break; 147 148 case ACPI_TYPE_BUFFER: 149 150 /* Check for zero-length buffer */ 151 152 if (!Count) 153 { 154 return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); 155 } 156 157 /* Transfer no more than an integer's worth of data */ 158 159 if (Count > AcpiGbl_IntegerByteWidth) 160 { 161 Count = AcpiGbl_IntegerByteWidth; 162 } 163 164 /* 165 * Convert buffer to an integer - we simply grab enough raw data 166 * from the buffer to fill an integer 167 */ 168 for (i = 0; i < Count; i++) 169 { 170 /* 171 * Get next byte and shift it into the Result. 172 * Little endian is used, meaning that the first byte of the buffer 173 * is the LSB of the integer 174 */ 175 Result |= (((UINT64) Pointer[i]) << (i * 8)); 176 } 177 break; 178 179 default: 180 181 /* No other types can get here */ 182 183 break; 184 } 185 186 /* Create a new integer */ 187 188 ReturnDesc = AcpiUtCreateIntegerObject (Result); 189 if (!ReturnDesc) 190 { 191 return_ACPI_STATUS (AE_NO_MEMORY); 192 } 193 194 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", 195 ACPI_FORMAT_UINT64 (Result))); 196 197 /* Save the Result */ 198 199 (void) AcpiExTruncateFor32bitTable (ReturnDesc); 200 *ResultDesc = ReturnDesc; 201 return_ACPI_STATUS (AE_OK); 202 } 203 204 205 /******************************************************************************* 206 * 207 * FUNCTION: AcpiExConvertToBuffer 208 * 209 * PARAMETERS: ObjDesc - Object to be converted. Must be an 210 * Integer, Buffer, or String 211 * ResultDesc - Where the new buffer object is returned 212 * 213 * RETURN: Status 214 * 215 * DESCRIPTION: Convert an ACPI Object to a Buffer 216 * 217 ******************************************************************************/ 218 219 ACPI_STATUS 220 AcpiExConvertToBuffer ( 221 ACPI_OPERAND_OBJECT *ObjDesc, 222 ACPI_OPERAND_OBJECT **ResultDesc) 223 { 224 ACPI_OPERAND_OBJECT *ReturnDesc; 225 UINT8 *NewBuf; 226 227 228 ACPI_FUNCTION_TRACE_PTR (ExConvertToBuffer, ObjDesc); 229 230 231 switch (ObjDesc->Common.Type) 232 { 233 case ACPI_TYPE_BUFFER: 234 235 /* No conversion necessary */ 236 237 *ResultDesc = ObjDesc; 238 return_ACPI_STATUS (AE_OK); 239 240 241 case ACPI_TYPE_INTEGER: 242 /* 243 * Create a new Buffer object. 244 * Need enough space for one integer 245 */ 246 ReturnDesc = AcpiUtCreateBufferObject (AcpiGbl_IntegerByteWidth); 247 if (!ReturnDesc) 248 { 249 return_ACPI_STATUS (AE_NO_MEMORY); 250 } 251 252 /* Copy the integer to the buffer, LSB first */ 253 254 NewBuf = ReturnDesc->Buffer.Pointer; 255 memcpy (NewBuf, &ObjDesc->Integer.Value, AcpiGbl_IntegerByteWidth); 256 break; 257 258 case ACPI_TYPE_STRING: 259 /* 260 * Create a new Buffer object 261 * Size will be the string length 262 * 263 * NOTE: Add one to the string length to include the null terminator. 264 * The ACPI spec is unclear on this subject, but there is existing 265 * ASL/AML code that depends on the null being transferred to the new 266 * buffer. 267 */ 268 ReturnDesc = AcpiUtCreateBufferObject ((ACPI_SIZE) 269 ObjDesc->String.Length + 1); 270 if (!ReturnDesc) 271 { 272 return_ACPI_STATUS (AE_NO_MEMORY); 273 } 274 275 /* Copy the string to the buffer */ 276 277 NewBuf = ReturnDesc->Buffer.Pointer; 278 strncpy ((char *) NewBuf, (char *) ObjDesc->String.Pointer, 279 ObjDesc->String.Length); 280 break; 281 282 default: 283 284 return_ACPI_STATUS (AE_TYPE); 285 } 286 287 /* Mark buffer initialized */ 288 289 ReturnDesc->Common.Flags |= AOPOBJ_DATA_VALID; 290 *ResultDesc = ReturnDesc; 291 return_ACPI_STATUS (AE_OK); 292 } 293 294 295 /******************************************************************************* 296 * 297 * FUNCTION: AcpiExConvertToAscii 298 * 299 * PARAMETERS: Integer - Value to be converted 300 * Base - ACPI_STRING_DECIMAL or ACPI_STRING_HEX 301 * String - Where the string is returned 302 * DataWidth - Size of data item to be converted, in bytes 303 * 304 * RETURN: Actual string length 305 * 306 * DESCRIPTION: Convert an ACPI Integer to a hex or decimal string 307 * 308 ******************************************************************************/ 309 310 static UINT32 311 AcpiExConvertToAscii ( 312 UINT64 Integer, 313 UINT16 Base, 314 UINT8 *String, 315 UINT8 DataWidth) 316 { 317 UINT64 Digit; 318 UINT32 i; 319 UINT32 j; 320 UINT32 k = 0; 321 UINT32 HexLength; 322 UINT32 DecimalLength; 323 UINT32 Remainder; 324 BOOLEAN SupressZeros; 325 326 327 ACPI_FUNCTION_ENTRY (); 328 329 330 switch (Base) 331 { 332 case 10: 333 334 /* Setup max length for the decimal number */ 335 336 switch (DataWidth) 337 { 338 case 1: 339 340 DecimalLength = ACPI_MAX8_DECIMAL_DIGITS; 341 break; 342 343 case 4: 344 345 DecimalLength = ACPI_MAX32_DECIMAL_DIGITS; 346 break; 347 348 case 8: 349 default: 350 351 DecimalLength = ACPI_MAX64_DECIMAL_DIGITS; 352 break; 353 } 354 355 SupressZeros = TRUE; /* No leading zeros */ 356 Remainder = 0; 357 358 for (i = DecimalLength; i > 0; i--) 359 { 360 /* Divide by nth factor of 10 */ 361 362 Digit = Integer; 363 for (j = 0; j < i; j++) 364 { 365 (void) AcpiUtShortDivide (Digit, 10, &Digit, &Remainder); 366 } 367 368 /* Handle leading zeros */ 369 370 if (Remainder != 0) 371 { 372 SupressZeros = FALSE; 373 } 374 375 if (!SupressZeros) 376 { 377 String[k] = (UINT8) (ACPI_ASCII_ZERO + Remainder); 378 k++; 379 } 380 } 381 break; 382 383 case 16: 384 385 /* HexLength: 2 ascii hex chars per data byte */ 386 387 HexLength = ACPI_MUL_2 (DataWidth); 388 for (i = 0, j = (HexLength-1); i < HexLength; i++, j--) 389 { 390 /* Get one hex digit, most significant digits first */ 391 392 String[k] = (UINT8) 393 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 ( 495 ObjDesc->Integer.Value, Base, 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, NewBuf, 1); 585 *NewBuf++ = Separator; /* each separated by a comma or space */ 586 } 587 588 /* 589 * Null terminate the string 590 * (overwrites final comma/space from above) 591 */ 592 if (ObjDesc->Buffer.Length) 593 { 594 NewBuf--; 595 } 596 *NewBuf = 0; 597 break; 598 599 default: 600 601 return_ACPI_STATUS (AE_TYPE); 602 } 603 604 *ResultDesc = ReturnDesc; 605 return_ACPI_STATUS (AE_OK); 606 } 607 608 609 /******************************************************************************* 610 * 611 * FUNCTION: AcpiExConvertToTargetType 612 * 613 * PARAMETERS: DestinationType - Current type of the destination 614 * SourceDesc - Source object to be converted. 615 * ResultDesc - Where the converted object is returned 616 * WalkState - Current method state 617 * 618 * RETURN: Status 619 * 620 * DESCRIPTION: Implements "implicit conversion" rules for storing an object. 621 * 622 ******************************************************************************/ 623 624 ACPI_STATUS 625 AcpiExConvertToTargetType ( 626 ACPI_OBJECT_TYPE DestinationType, 627 ACPI_OPERAND_OBJECT *SourceDesc, 628 ACPI_OPERAND_OBJECT **ResultDesc, 629 ACPI_WALK_STATE *WalkState) 630 { 631 ACPI_STATUS Status = AE_OK; 632 633 634 ACPI_FUNCTION_TRACE (ExConvertToTargetType); 635 636 637 /* Default behavior */ 638 639 *ResultDesc = SourceDesc; 640 641 /* 642 * If required by the target, 643 * perform implicit conversion on the source before we store it. 644 */ 645 switch (GET_CURRENT_ARG_TYPE (WalkState->OpInfo->RuntimeArgs)) 646 { 647 case ARGI_SIMPLE_TARGET: 648 case ARGI_FIXED_TARGET: 649 case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */ 650 651 switch (DestinationType) 652 { 653 case ACPI_TYPE_LOCAL_REGION_FIELD: 654 /* 655 * Named field can always handle conversions 656 */ 657 break; 658 659 default: 660 661 /* No conversion allowed for these types */ 662 663 if (DestinationType != SourceDesc->Common.Type) 664 { 665 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 666 "Explicit operator, will store (%s) over existing type (%s)\n", 667 AcpiUtGetObjectTypeName (SourceDesc), 668 AcpiUtGetTypeName (DestinationType))); 669 Status = AE_TYPE; 670 } 671 } 672 break; 673 674 case ARGI_TARGETREF: 675 case ARGI_STORE_TARGET: 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, 16); 688 break; 689 690 case ACPI_TYPE_STRING: 691 /* 692 * The operand must be a String. We can convert an 693 * Integer or Buffer if necessary 694 */ 695 Status = AcpiExConvertToString (SourceDesc, ResultDesc, 696 ACPI_IMPLICIT_CONVERT_HEX); 697 break; 698 699 case ACPI_TYPE_BUFFER: 700 /* 701 * The operand must be a Buffer. We can convert an 702 * Integer or String if necessary 703 */ 704 Status = AcpiExConvertToBuffer (SourceDesc, ResultDesc); 705 break; 706 707 default: 708 709 ACPI_ERROR ((AE_INFO, 710 "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