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