1 2 /****************************************************************************** 3 * 4 * Module Name: aslutils -- compiler utilities 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2011, Intel Corp. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45 46 #include <contrib/dev/acpica/compiler/aslcompiler.h> 47 #include "aslcompiler.y.h" 48 #include <contrib/dev/acpica/include/acdisasm.h> 49 #include <contrib/dev/acpica/include/acnamesp.h> 50 #include <contrib/dev/acpica/include/amlcode.h> 51 #include <contrib/dev/acpica/include/acapps.h> 52 53 #define _COMPONENT ACPI_COMPILER 54 ACPI_MODULE_NAME ("aslutils") 55 56 char AslHexLookup[] = 57 { 58 '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' 59 }; 60 61 62 /* Local prototypes */ 63 64 static void 65 UtPadNameWithUnderscores ( 66 char *NameSeg, 67 char *PaddedNameSeg); 68 69 static void 70 UtAttachNameseg ( 71 ACPI_PARSE_OBJECT *Op, 72 char *Name); 73 74 75 /******************************************************************************* 76 * 77 * FUNCTION: UtDisplaySupportedTables 78 * 79 * PARAMETERS: None 80 * 81 * RETURN: None 82 * 83 * DESCRIPTION: Print all supported ACPI table names. 84 * 85 ******************************************************************************/ 86 87 void 88 UtDisplaySupportedTables ( 89 void) 90 { 91 ACPI_DMTABLE_DATA *TableData; 92 UINT32 i = 6; 93 94 95 printf ("\nACPI tables supported by iASL subsystems in " 96 "version %8.8X:\n" 97 " ASL and Data Table compilers\n" 98 " AML and Data Table disassemblers\n" 99 " ACPI table template generator\n\n", ACPI_CA_VERSION); 100 101 /* Special tables */ 102 103 printf ("%8u) %s %s\n", 1, ACPI_SIG_DSDT, "Differentiated System Description Table"); 104 printf ("%8u) %s %s\n", 2, ACPI_SIG_SSDT, "Secondary System Description Table"); 105 printf ("%8u) %s %s\n", 3, ACPI_SIG_FADT, "Fixed ACPI Description Table (FADT)"); 106 printf ("%8u) %s %s\n", 4, ACPI_SIG_FACS, "Firmware ACPI Control Structure"); 107 printf ("%8u) %s %s\n", 5, ACPI_RSDP_NAME, "Root System Description Pointer"); 108 109 /* All data tables with common table header */ 110 111 for (TableData = AcpiDmTableData; TableData->Signature; TableData++) 112 { 113 printf ("%8u) %s %s\n", i, TableData->Signature, TableData->Name); 114 i++; 115 } 116 } 117 118 119 /******************************************************************************* 120 * 121 * FUNCTION: AcpiPsDisplayConstantOpcodes 122 * 123 * PARAMETERS: None 124 * 125 * RETURN: None 126 * 127 * DESCRIPTION: Print AML opcodes that can be used in constant expressions. 128 * 129 ******************************************************************************/ 130 131 void 132 UtDisplayConstantOpcodes ( 133 void) 134 { 135 UINT32 i; 136 137 138 printf ("Constant expression opcode information\n\n"); 139 140 for (i = 0; i < sizeof (AcpiGbl_AmlOpInfo) / sizeof (ACPI_OPCODE_INFO); i++) 141 { 142 if (AcpiGbl_AmlOpInfo[i].Flags & AML_CONSTANT) 143 { 144 printf ("%s\n", AcpiGbl_AmlOpInfo[i].Name); 145 } 146 } 147 } 148 149 150 /******************************************************************************* 151 * 152 * FUNCTION: UtLocalCalloc 153 * 154 * PARAMETERS: Size - Bytes to be allocated 155 * 156 * RETURN: Pointer to the allocated memory. Guaranteed to be valid. 157 * 158 * DESCRIPTION: Allocate zero-initialized memory. Aborts the compile on an 159 * allocation failure, on the assumption that nothing more can be 160 * accomplished. 161 * 162 ******************************************************************************/ 163 164 void * 165 UtLocalCalloc ( 166 UINT32 Size) 167 { 168 void *Allocated; 169 170 171 Allocated = ACPI_ALLOCATE_ZEROED (Size); 172 if (!Allocated) 173 { 174 AslCommonError (ASL_ERROR, ASL_MSG_MEMORY_ALLOCATION, 175 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, 176 Gbl_InputByteCount, Gbl_CurrentColumn, 177 Gbl_Files[ASL_FILE_INPUT].Filename, NULL); 178 179 CmCleanupAndExit (); 180 exit (1); 181 } 182 183 TotalAllocations++; 184 TotalAllocated += Size; 185 return (Allocated); 186 } 187 188 189 /******************************************************************************* 190 * 191 * FUNCTION: UtBeginEvent 192 * 193 * PARAMETERS: Name - Ascii name of this event 194 * 195 * RETURN: Event - Event number (integer index) 196 * 197 * DESCRIPTION: Saves the current time with this event 198 * 199 ******************************************************************************/ 200 201 UINT8 202 UtBeginEvent ( 203 char *Name) 204 { 205 206 if (AslGbl_NextEvent >= ASL_NUM_EVENTS) 207 { 208 AcpiOsPrintf ("Ran out of compiler event structs!\n"); 209 return (AslGbl_NextEvent); 210 } 211 212 /* Init event with current (start) time */ 213 214 AslGbl_Events[AslGbl_NextEvent].StartTime = AcpiOsGetTimer (); 215 AslGbl_Events[AslGbl_NextEvent].EventName = Name; 216 AslGbl_Events[AslGbl_NextEvent].Valid = TRUE; 217 218 return (AslGbl_NextEvent++); 219 } 220 221 222 /******************************************************************************* 223 * 224 * FUNCTION: UtEndEvent 225 * 226 * PARAMETERS: Event - Event number (integer index) 227 * 228 * RETURN: None 229 * 230 * DESCRIPTION: Saves the current time (end time) with this event 231 * 232 ******************************************************************************/ 233 234 void 235 UtEndEvent ( 236 UINT8 Event) 237 { 238 239 if (Event >= ASL_NUM_EVENTS) 240 { 241 return; 242 } 243 244 /* Insert end time for event */ 245 246 AslGbl_Events[Event].EndTime = AcpiOsGetTimer (); 247 } 248 249 250 /******************************************************************************* 251 * 252 * FUNCTION: UtHexCharToValue 253 * 254 * PARAMETERS: HexChar - Hex character in Ascii 255 * 256 * RETURN: The binary value of the hex character 257 * 258 * DESCRIPTION: Perform ascii-to-hex translation 259 * 260 ******************************************************************************/ 261 262 UINT8 263 UtHexCharToValue ( 264 int HexChar) 265 { 266 267 if (HexChar <= 0x39) 268 { 269 return ((UINT8) (HexChar - 0x30)); 270 } 271 272 if (HexChar <= 0x46) 273 { 274 return ((UINT8) (HexChar - 0x37)); 275 } 276 277 return ((UINT8) (HexChar - 0x57)); 278 } 279 280 281 /******************************************************************************* 282 * 283 * FUNCTION: UtConvertByteToHex 284 * 285 * PARAMETERS: RawByte - Binary data 286 * Buffer - Pointer to where the hex bytes will be stored 287 * 288 * RETURN: Ascii hex byte is stored in Buffer. 289 * 290 * DESCRIPTION: Perform hex-to-ascii translation. The return data is prefixed 291 * with "0x" 292 * 293 ******************************************************************************/ 294 295 void 296 UtConvertByteToHex ( 297 UINT8 RawByte, 298 UINT8 *Buffer) 299 { 300 301 Buffer[0] = '0'; 302 Buffer[1] = 'x'; 303 304 Buffer[2] = (UINT8) AslHexLookup[(RawByte >> 4) & 0xF]; 305 Buffer[3] = (UINT8) AslHexLookup[RawByte & 0xF]; 306 } 307 308 309 /******************************************************************************* 310 * 311 * FUNCTION: UtConvertByteToAsmHex 312 * 313 * PARAMETERS: RawByte - Binary data 314 * Buffer - Pointer to where the hex bytes will be stored 315 * 316 * RETURN: Ascii hex byte is stored in Buffer. 317 * 318 * DESCRIPTION: Perform hex-to-ascii translation. The return data is prefixed 319 * with "0x" 320 * 321 ******************************************************************************/ 322 323 void 324 UtConvertByteToAsmHex ( 325 UINT8 RawByte, 326 UINT8 *Buffer) 327 { 328 329 Buffer[0] = '0'; 330 Buffer[1] = (UINT8) AslHexLookup[(RawByte >> 4) & 0xF]; 331 Buffer[2] = (UINT8) AslHexLookup[RawByte & 0xF]; 332 Buffer[3] = 'h'; 333 } 334 335 336 /******************************************************************************* 337 * 338 * FUNCTION: DbgPrint 339 * 340 * PARAMETERS: Type - Type of output 341 * Fmt - Printf format string 342 * ... - variable printf list 343 * 344 * RETURN: None 345 * 346 * DESCRIPTION: Conditional print statement. Prints to stderr only if the 347 * debug flag is set. 348 * 349 ******************************************************************************/ 350 351 void 352 DbgPrint ( 353 UINT32 Type, 354 char *Fmt, 355 ...) 356 { 357 va_list Args; 358 359 360 va_start (Args, Fmt); 361 362 if (!Gbl_DebugFlag) 363 { 364 return; 365 } 366 367 if ((Type == ASL_PARSE_OUTPUT) && 368 (!(AslCompilerdebug))) 369 { 370 return; 371 } 372 373 (void) vfprintf (stderr, Fmt, Args); 374 va_end (Args); 375 return; 376 } 377 378 379 /******************************************************************************* 380 * 381 * FUNCTION: UtPrintFormattedName 382 * 383 * PARAMETERS: ParseOpcode - Parser keyword ID 384 * Level - Indentation level 385 * 386 * RETURN: None 387 * 388 * DESCRIPTION: Print the ascii name of the parse opcode. 389 * 390 ******************************************************************************/ 391 392 #define TEXT_OFFSET 10 393 394 void 395 UtPrintFormattedName ( 396 UINT16 ParseOpcode, 397 UINT32 Level) 398 { 399 400 if (Level) 401 { 402 DbgPrint (ASL_TREE_OUTPUT, 403 "%*s", (3 * Level), " "); 404 } 405 DbgPrint (ASL_TREE_OUTPUT, 406 " %-20.20s", UtGetOpName (ParseOpcode)); 407 408 if (Level < TEXT_OFFSET) 409 { 410 DbgPrint (ASL_TREE_OUTPUT, 411 "%*s", (TEXT_OFFSET - Level) * 3, " "); 412 } 413 } 414 415 416 /******************************************************************************* 417 * 418 * FUNCTION: UtSetParseOpName 419 * 420 * PARAMETERS: Op 421 * 422 * RETURN: None 423 * 424 * DESCRIPTION: Insert the ascii name of the parse opcode 425 * 426 ******************************************************************************/ 427 428 void 429 UtSetParseOpName ( 430 ACPI_PARSE_OBJECT *Op) 431 { 432 433 strncpy (Op->Asl.ParseOpName, UtGetOpName (Op->Asl.ParseOpcode), 434 ACPI_MAX_PARSEOP_NAME); 435 } 436 437 438 /******************************************************************************* 439 * 440 * FUNCTION: UtDisplaySummary 441 * 442 * PARAMETERS: FileID - ID of outpout file 443 * 444 * RETURN: None 445 * 446 * DESCRIPTION: Display compilation statistics 447 * 448 ******************************************************************************/ 449 450 void 451 UtDisplaySummary ( 452 UINT32 FileId) 453 { 454 455 if (FileId != ASL_FILE_STDOUT) 456 { 457 /* Compiler name and version number */ 458 459 FlPrintFile (FileId, "%s version %X%s\n", 460 ASL_COMPILER_NAME, (UINT32) ACPI_CA_VERSION, ACPI_WIDTH); 461 } 462 463 if (Gbl_FileType == ASL_INPUT_TYPE_ASCII_DATA) 464 { 465 FlPrintFile (FileId, 466 "Table Input: %s - %u lines, %u bytes, %u fields\n", 467 Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_CurrentLineNumber, 468 Gbl_InputByteCount, Gbl_InputFieldCount); 469 470 if ((Gbl_ExceptionCount[ASL_ERROR] == 0) || (Gbl_IgnoreErrors)) 471 { 472 FlPrintFile (FileId, 473 "Binary Output: %s - %u bytes\n\n", 474 Gbl_Files[ASL_FILE_AML_OUTPUT].Filename, Gbl_TableLength); 475 } 476 } 477 else 478 { 479 /* Input/Output summary */ 480 481 FlPrintFile (FileId, 482 "ASL Input: %s - %u lines, %u bytes, %u keywords\n", 483 Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_CurrentLineNumber, 484 Gbl_InputByteCount, TotalKeywords); 485 486 /* AML summary */ 487 488 if ((Gbl_ExceptionCount[ASL_ERROR] == 0) || (Gbl_IgnoreErrors)) 489 { 490 FlPrintFile (FileId, 491 "AML Output: %s - %u bytes, %u named objects, %u executable opcodes\n\n", 492 Gbl_Files[ASL_FILE_AML_OUTPUT].Filename, Gbl_TableLength, 493 TotalNamedObjects, TotalExecutableOpcodes); 494 } 495 } 496 497 /* Error summary */ 498 499 FlPrintFile (FileId, 500 "Compilation complete. %u Errors, %u Warnings, %u Remarks", 501 Gbl_ExceptionCount[ASL_ERROR], 502 Gbl_ExceptionCount[ASL_WARNING] + 503 Gbl_ExceptionCount[ASL_WARNING2] + 504 Gbl_ExceptionCount[ASL_WARNING3], 505 Gbl_ExceptionCount[ASL_REMARK]); 506 507 if (Gbl_FileType != ASL_INPUT_TYPE_ASCII_DATA) 508 { 509 FlPrintFile (FileId, 510 ", %u Optimizations", Gbl_ExceptionCount[ASL_OPTIMIZATION]); 511 } 512 513 FlPrintFile (FileId, "\n"); 514 } 515 516 517 /******************************************************************************* 518 * 519 * FUNCTION: UtDisplaySummary 520 * 521 * PARAMETERS: Op - Integer parse node 522 * LowValue - Smallest allowed value 523 * HighValue - Largest allowed value 524 * 525 * RETURN: Op if OK, otherwise NULL 526 * 527 * DESCRIPTION: Check integer for an allowable range 528 * 529 ******************************************************************************/ 530 531 ACPI_PARSE_OBJECT * 532 UtCheckIntegerRange ( 533 ACPI_PARSE_OBJECT *Op, 534 UINT32 LowValue, 535 UINT32 HighValue) 536 { 537 char *ParseError = NULL; 538 char Buffer[64]; 539 540 541 if (!Op) 542 { 543 return NULL; 544 } 545 546 if (Op->Asl.Value.Integer < LowValue) 547 { 548 ParseError = "Value below valid range"; 549 Op->Asl.Value.Integer = LowValue; 550 } 551 552 if (Op->Asl.Value.Integer > HighValue) 553 { 554 ParseError = "Value above valid range"; 555 Op->Asl.Value.Integer = HighValue; 556 } 557 558 if (ParseError) 559 { 560 sprintf (Buffer, "%s 0x%X-0x%X", ParseError, LowValue, HighValue); 561 AslCompilererror (Buffer); 562 563 return NULL; 564 } 565 566 return Op; 567 } 568 569 570 /******************************************************************************* 571 * 572 * FUNCTION: UtGetStringBuffer 573 * 574 * PARAMETERS: Length - Size of buffer requested 575 * 576 * RETURN: Pointer to the buffer. Aborts on allocation failure 577 * 578 * DESCRIPTION: Allocate a string buffer. Bypass the local 579 * dynamic memory manager for performance reasons (This has a 580 * major impact on the speed of the compiler.) 581 * 582 ******************************************************************************/ 583 584 char * 585 UtGetStringBuffer ( 586 UINT32 Length) 587 { 588 char *Buffer; 589 590 591 if ((Gbl_StringCacheNext + Length) >= Gbl_StringCacheLast) 592 { 593 Gbl_StringCacheNext = UtLocalCalloc (ASL_STRING_CACHE_SIZE + Length); 594 Gbl_StringCacheLast = Gbl_StringCacheNext + ASL_STRING_CACHE_SIZE + 595 Length; 596 } 597 598 Buffer = Gbl_StringCacheNext; 599 Gbl_StringCacheNext += Length; 600 601 return (Buffer); 602 } 603 604 605 /******************************************************************************* 606 * 607 * FUNCTION: UtInternalizeName 608 * 609 * PARAMETERS: ExternalName - Name to convert 610 * ConvertedName - Where the converted name is returned 611 * 612 * RETURN: Status 613 * 614 * DESCRIPTION: Convert an external (ASL) name to an internal (AML) name 615 * 616 ******************************************************************************/ 617 618 ACPI_STATUS 619 UtInternalizeName ( 620 char *ExternalName, 621 char **ConvertedName) 622 { 623 ACPI_NAMESTRING_INFO Info; 624 ACPI_STATUS Status; 625 626 627 if (!ExternalName) 628 { 629 return (AE_OK); 630 } 631 632 /* Get the length of the new internal name */ 633 634 Info.ExternalName = ExternalName; 635 AcpiNsGetInternalNameLength (&Info); 636 637 /* We need a segment to store the internal name */ 638 639 Info.InternalName = UtGetStringBuffer (Info.Length); 640 if (!Info.InternalName) 641 { 642 return (AE_NO_MEMORY); 643 } 644 645 /* Build the name */ 646 647 Status = AcpiNsBuildInternalName (&Info); 648 if (ACPI_FAILURE (Status)) 649 { 650 return (Status); 651 } 652 653 *ConvertedName = Info.InternalName; 654 return (AE_OK); 655 } 656 657 658 /******************************************************************************* 659 * 660 * FUNCTION: UtPadNameWithUnderscores 661 * 662 * PARAMETERS: NameSeg - Input nameseg 663 * PaddedNameSeg - Output padded nameseg 664 * 665 * RETURN: Padded nameseg. 666 * 667 * DESCRIPTION: Pads a NameSeg with underscores if necessary to form a full 668 * ACPI_NAME. 669 * 670 ******************************************************************************/ 671 672 static void 673 UtPadNameWithUnderscores ( 674 char *NameSeg, 675 char *PaddedNameSeg) 676 { 677 UINT32 i; 678 679 680 for (i = 0; (i < ACPI_NAME_SIZE); i++) 681 { 682 if (*NameSeg) 683 { 684 *PaddedNameSeg = *NameSeg; 685 NameSeg++; 686 } 687 else 688 { 689 *PaddedNameSeg = '_'; 690 } 691 PaddedNameSeg++; 692 } 693 } 694 695 696 /******************************************************************************* 697 * 698 * FUNCTION: UtAttachNameseg 699 * 700 * PARAMETERS: Op - Parent parse node 701 * Name - Full ExternalName 702 * 703 * RETURN: None; Sets the NameSeg field in parent node 704 * 705 * DESCRIPTION: Extract the last nameseg of the ExternalName and store it 706 * in the NameSeg field of the Op. 707 * 708 ******************************************************************************/ 709 710 static void 711 UtAttachNameseg ( 712 ACPI_PARSE_OBJECT *Op, 713 char *Name) 714 { 715 char *NameSeg; 716 char PaddedNameSeg[4]; 717 718 719 if (!Name) 720 { 721 return; 722 } 723 724 /* Look for the last dot in the namepath */ 725 726 NameSeg = strrchr (Name, '.'); 727 if (NameSeg) 728 { 729 /* Found last dot, we have also found the final nameseg */ 730 731 NameSeg++; 732 UtPadNameWithUnderscores (NameSeg, PaddedNameSeg); 733 } 734 else 735 { 736 /* No dots in the namepath, there is only a single nameseg. */ 737 /* Handle prefixes */ 738 739 while ((*Name == '\\') || (*Name == '^')) 740 { 741 Name++; 742 } 743 744 /* Remaing string should be one single nameseg */ 745 746 UtPadNameWithUnderscores (Name, PaddedNameSeg); 747 } 748 749 strncpy (Op->Asl.NameSeg, PaddedNameSeg, 4); 750 } 751 752 753 /******************************************************************************* 754 * 755 * FUNCTION: UtAttachNamepathToOwner 756 * 757 * PARAMETERS: Op - Parent parse node 758 * NameOp - Node that contains the name 759 * 760 * RETURN: Sets the ExternalName and Namepath in the parent node 761 * 762 * DESCRIPTION: Store the name in two forms in the parent node: The original 763 * (external) name, and the internalized name that is used within 764 * the ACPI namespace manager. 765 * 766 ******************************************************************************/ 767 768 void 769 UtAttachNamepathToOwner ( 770 ACPI_PARSE_OBJECT *Op, 771 ACPI_PARSE_OBJECT *NameOp) 772 { 773 ACPI_STATUS Status; 774 775 776 /* Full external path */ 777 778 Op->Asl.ExternalName = NameOp->Asl.Value.String; 779 780 /* Save the NameOp for possible error reporting later */ 781 782 Op->Asl.ParentMethod = (void *) NameOp; 783 784 /* Last nameseg of the path */ 785 786 UtAttachNameseg (Op, Op->Asl.ExternalName); 787 788 /* Create internalized path */ 789 790 Status = UtInternalizeName (NameOp->Asl.Value.String, &Op->Asl.Namepath); 791 if (ACPI_FAILURE (Status)) 792 { 793 /* TBD: abort on no memory */ 794 } 795 } 796 797 798 /******************************************************************************* 799 * 800 * FUNCTION: UtDoConstant 801 * 802 * PARAMETERS: String - Hex, Octal, or Decimal string 803 * 804 * RETURN: Converted Integer 805 * 806 * DESCRIPTION: Convert a string to an integer. With error checking. 807 * 808 ******************************************************************************/ 809 810 UINT64 811 UtDoConstant ( 812 char *String) 813 { 814 ACPI_STATUS Status; 815 UINT64 Converted; 816 char ErrBuf[64]; 817 818 819 Status = UtStrtoul64 (String, 0, &Converted); 820 if (ACPI_FAILURE (Status)) 821 { 822 sprintf (ErrBuf, "%s %s\n", "Conversion error:", 823 AcpiFormatException (Status)); 824 AslCompilererror (ErrBuf); 825 } 826 827 return (Converted); 828 } 829 830 831 /* TBD: use version in ACPI CA main code base? */ 832 833 /******************************************************************************* 834 * 835 * FUNCTION: UtStrtoul64 836 * 837 * PARAMETERS: String - Null terminated string 838 * Terminater - Where a pointer to the terminating byte is 839 * returned 840 * Base - Radix of the string 841 * 842 * RETURN: Converted value 843 * 844 * DESCRIPTION: Convert a string into an unsigned value. 845 * 846 ******************************************************************************/ 847 848 ACPI_STATUS 849 UtStrtoul64 ( 850 char *String, 851 UINT32 Base, 852 UINT64 *RetInteger) 853 { 854 UINT32 Index; 855 UINT32 Sign; 856 UINT64 ReturnValue = 0; 857 ACPI_STATUS Status = AE_OK; 858 859 860 *RetInteger = 0; 861 862 switch (Base) 863 { 864 case 0: 865 case 8: 866 case 10: 867 case 16: 868 break; 869 870 default: 871 /* 872 * The specified Base parameter is not in the domain of 873 * this function: 874 */ 875 return (AE_BAD_PARAMETER); 876 } 877 878 /* Skip over any white space in the buffer: */ 879 880 while (isspace ((int) *String) || *String == '\t') 881 { 882 ++String; 883 } 884 885 /* 886 * The buffer may contain an optional plus or minus sign. 887 * If it does, then skip over it but remember what is was: 888 */ 889 if (*String == '-') 890 { 891 Sign = NEGATIVE; 892 ++String; 893 } 894 else if (*String == '+') 895 { 896 ++String; 897 Sign = POSITIVE; 898 } 899 else 900 { 901 Sign = POSITIVE; 902 } 903 904 /* 905 * If the input parameter Base is zero, then we need to 906 * determine if it is octal, decimal, or hexadecimal: 907 */ 908 if (Base == 0) 909 { 910 if (*String == '0') 911 { 912 if (tolower ((int) *(++String)) == 'x') 913 { 914 Base = 16; 915 ++String; 916 } 917 else 918 { 919 Base = 8; 920 } 921 } 922 else 923 { 924 Base = 10; 925 } 926 } 927 928 /* 929 * For octal and hexadecimal bases, skip over the leading 930 * 0 or 0x, if they are present. 931 */ 932 if (Base == 8 && *String == '0') 933 { 934 String++; 935 } 936 937 if (Base == 16 && 938 *String == '0' && 939 tolower ((int) *(++String)) == 'x') 940 { 941 String++; 942 } 943 944 /* Main loop: convert the string to an unsigned long */ 945 946 while (*String) 947 { 948 if (isdigit ((int) *String)) 949 { 950 Index = ((UINT8) *String) - '0'; 951 } 952 else 953 { 954 Index = (UINT8) toupper ((int) *String); 955 if (isupper ((int) Index)) 956 { 957 Index = Index - 'A' + 10; 958 } 959 else 960 { 961 goto ErrorExit; 962 } 963 } 964 965 if (Index >= Base) 966 { 967 goto ErrorExit; 968 } 969 970 /* Check to see if value is out of range: */ 971 972 if (ReturnValue > ((ACPI_UINT64_MAX - (UINT64) Index) / 973 (UINT64) Base)) 974 { 975 goto ErrorExit; 976 } 977 else 978 { 979 ReturnValue *= Base; 980 ReturnValue += Index; 981 } 982 983 ++String; 984 } 985 986 987 /* If a minus sign was present, then "the conversion is negated": */ 988 989 if (Sign == NEGATIVE) 990 { 991 ReturnValue = (ACPI_UINT32_MAX - ReturnValue) + 1; 992 } 993 994 *RetInteger = ReturnValue; 995 return (Status); 996 997 998 ErrorExit: 999 switch (Base) 1000 { 1001 case 8: 1002 Status = AE_BAD_OCTAL_CONSTANT; 1003 break; 1004 1005 case 10: 1006 Status = AE_BAD_DECIMAL_CONSTANT; 1007 break; 1008 1009 case 16: 1010 Status = AE_BAD_HEX_CONSTANT; 1011 break; 1012 1013 default: 1014 /* Base validated above */ 1015 break; 1016 } 1017 1018 return (Status); 1019 } 1020 1021 1022