1 /****************************************************************************** 2 * 3 * Module Name: aslutils -- compiler utilities 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2017, 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 "aslcompiler.h" 45 #include "aslcompiler.y.h" 46 #include "acdisasm.h" 47 #include "acnamesp.h" 48 #include "amlcode.h" 49 #include "acapps.h" 50 #include <sys/stat.h> 51 52 53 #define _COMPONENT ACPI_COMPILER 54 ACPI_MODULE_NAME ("aslutils") 55 56 57 /* Local prototypes */ 58 59 static void 60 UtPadNameWithUnderscores ( 61 char *NameSeg, 62 char *PaddedNameSeg); 63 64 static void 65 UtAttachNameseg ( 66 ACPI_PARSE_OBJECT *Op, 67 char *Name); 68 69 70 /******************************************************************************* 71 * 72 * FUNCTION: UtIsBigEndianMachine 73 * 74 * PARAMETERS: None 75 * 76 * RETURN: TRUE if machine is big endian 77 * FALSE if machine is little endian 78 * 79 * DESCRIPTION: Detect whether machine is little endian or big endian. 80 * 81 ******************************************************************************/ 82 83 UINT8 84 UtIsBigEndianMachine ( 85 void) 86 { 87 union { 88 UINT32 Integer; 89 UINT8 Bytes[4]; 90 } Overlay = {0xFF000000}; 91 92 93 return (Overlay.Bytes[0]); /* Returns 0xFF (TRUE) for big endian */ 94 } 95 96 97 /****************************************************************************** 98 * 99 * FUNCTION: UtQueryForOverwrite 100 * 101 * PARAMETERS: Pathname - Output filename 102 * 103 * RETURN: TRUE if file does not exist or overwrite is authorized 104 * 105 * DESCRIPTION: Query for file overwrite if it already exists. 106 * 107 ******************************************************************************/ 108 109 BOOLEAN 110 UtQueryForOverwrite ( 111 char *Pathname) 112 { 113 struct stat StatInfo; 114 115 116 if (!stat (Pathname, &StatInfo)) 117 { 118 fprintf (stderr, "Target file \"%s\" already exists, overwrite? [y|n] ", 119 Pathname); 120 121 if (getchar () != 'y') 122 { 123 return (FALSE); 124 } 125 } 126 127 return (TRUE); 128 } 129 130 131 /******************************************************************************* 132 * 133 * FUNCTION: UtDisplaySupportedTables 134 * 135 * PARAMETERS: None 136 * 137 * RETURN: None 138 * 139 * DESCRIPTION: Print all supported ACPI table names. 140 * 141 ******************************************************************************/ 142 143 void 144 UtDisplaySupportedTables ( 145 void) 146 { 147 const AH_TABLE *TableData; 148 UINT32 i; 149 150 151 printf ("\nACPI tables supported by iASL version %8.8X:\n" 152 " (Compiler, Disassembler, Template Generator)\n\n", 153 ACPI_CA_VERSION); 154 155 /* All ACPI tables with the common table header */ 156 157 printf ("\n Supported ACPI tables:\n"); 158 for (TableData = Gbl_AcpiSupportedTables, i = 1; 159 TableData->Signature; TableData++, i++) 160 { 161 printf ("%8u) %s %s\n", i, 162 TableData->Signature, TableData->Description); 163 } 164 } 165 166 167 /******************************************************************************* 168 * 169 * FUNCTION: UtDisplayConstantOpcodes 170 * 171 * PARAMETERS: None 172 * 173 * RETURN: None 174 * 175 * DESCRIPTION: Print AML opcodes that can be used in constant expressions. 176 * 177 ******************************************************************************/ 178 179 void 180 UtDisplayConstantOpcodes ( 181 void) 182 { 183 UINT32 i; 184 185 186 printf ("Constant expression opcode information\n\n"); 187 188 for (i = 0; i < sizeof (AcpiGbl_AmlOpInfo) / sizeof (ACPI_OPCODE_INFO); i++) 189 { 190 if (AcpiGbl_AmlOpInfo[i].Flags & AML_CONSTANT) 191 { 192 printf ("%s\n", AcpiGbl_AmlOpInfo[i].Name); 193 } 194 } 195 } 196 197 198 /******************************************************************************* 199 * 200 * FUNCTION: UtBeginEvent 201 * 202 * PARAMETERS: Name - Ascii name of this event 203 * 204 * RETURN: Event number (integer index) 205 * 206 * DESCRIPTION: Saves the current time with this event 207 * 208 ******************************************************************************/ 209 210 UINT8 211 UtBeginEvent ( 212 char *Name) 213 { 214 215 if (AslGbl_NextEvent >= ASL_NUM_EVENTS) 216 { 217 AcpiOsPrintf ("Ran out of compiler event structs!\n"); 218 return (AslGbl_NextEvent); 219 } 220 221 /* Init event with current (start) time */ 222 223 AslGbl_Events[AslGbl_NextEvent].StartTime = AcpiOsGetTimer (); 224 AslGbl_Events[AslGbl_NextEvent].EventName = Name; 225 AslGbl_Events[AslGbl_NextEvent].Valid = TRUE; 226 return (AslGbl_NextEvent++); 227 } 228 229 230 /******************************************************************************* 231 * 232 * FUNCTION: UtEndEvent 233 * 234 * PARAMETERS: Event - Event number (integer index) 235 * 236 * RETURN: None 237 * 238 * DESCRIPTION: Saves the current time (end time) with this event 239 * 240 ******************************************************************************/ 241 242 void 243 UtEndEvent ( 244 UINT8 Event) 245 { 246 247 if (Event >= ASL_NUM_EVENTS) 248 { 249 return; 250 } 251 252 /* Insert end time for event */ 253 254 AslGbl_Events[Event].EndTime = AcpiOsGetTimer (); 255 } 256 257 258 /******************************************************************************* 259 * 260 * FUNCTION: DbgPrint 261 * 262 * PARAMETERS: Type - Type of output 263 * Fmt - Printf format string 264 * ... - variable printf list 265 * 266 * RETURN: None 267 * 268 * DESCRIPTION: Conditional print statement. Prints to stderr only if the 269 * debug flag is set. 270 * 271 ******************************************************************************/ 272 273 void 274 DbgPrint ( 275 UINT32 Type, 276 char *Fmt, 277 ...) 278 { 279 va_list Args; 280 281 282 if (!Gbl_DebugFlag) 283 { 284 return; 285 } 286 287 if ((Type == ASL_PARSE_OUTPUT) && 288 (!(AslCompilerdebug))) 289 { 290 return; 291 } 292 293 va_start (Args, Fmt); 294 (void) vfprintf (stderr, Fmt, Args); 295 va_end (Args); 296 return; 297 } 298 299 300 /******************************************************************************* 301 * 302 * FUNCTION: UtSetParseOpName 303 * 304 * PARAMETERS: Op - Parse op to be named. 305 * 306 * RETURN: None 307 * 308 * DESCRIPTION: Insert the ascii name of the parse opcode 309 * 310 ******************************************************************************/ 311 312 void 313 UtSetParseOpName ( 314 ACPI_PARSE_OBJECT *Op) 315 { 316 317 strncpy (Op->Asl.ParseOpName, UtGetOpName (Op->Asl.ParseOpcode), 318 ACPI_MAX_PARSEOP_NAME); 319 } 320 321 322 /******************************************************************************* 323 * 324 * FUNCTION: UtDisplaySummary 325 * 326 * PARAMETERS: FileID - ID of outpout file 327 * 328 * RETURN: None 329 * 330 * DESCRIPTION: Display compilation statistics 331 * 332 ******************************************************************************/ 333 334 void 335 UtDisplaySummary ( 336 UINT32 FileId) 337 { 338 UINT32 i; 339 340 341 if (FileId != ASL_FILE_STDOUT) 342 { 343 /* Compiler name and version number */ 344 345 FlPrintFile (FileId, "%s version %X [%s]\n\n", 346 ASL_COMPILER_NAME, (UINT32) ACPI_CA_VERSION, "2017-01-19"); 347 } 348 349 /* Summary of main input and output files */ 350 351 if (Gbl_FileType == ASL_INPUT_TYPE_ASCII_DATA) 352 { 353 FlPrintFile (FileId, 354 "%-14s %s - %u lines, %u bytes, %u fields\n", 355 "Table Input:", 356 Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_CurrentLineNumber, 357 Gbl_InputByteCount, Gbl_InputFieldCount); 358 359 if ((Gbl_ExceptionCount[ASL_ERROR] == 0) || (Gbl_IgnoreErrors)) 360 { 361 FlPrintFile (FileId, 362 "%-14s %s - %u bytes\n", 363 "Binary Output:", 364 Gbl_Files[ASL_FILE_AML_OUTPUT].Filename, Gbl_TableLength); 365 } 366 } 367 else 368 { 369 FlPrintFile (FileId, 370 "%-14s %s - %u lines, %u bytes, %u keywords\n", 371 "ASL Input:", 372 Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_CurrentLineNumber, 373 Gbl_OriginalInputFileSize, TotalKeywords); 374 375 /* AML summary */ 376 377 if ((Gbl_ExceptionCount[ASL_ERROR] == 0) || (Gbl_IgnoreErrors)) 378 { 379 if (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle) 380 { 381 FlPrintFile (FileId, 382 "%-14s %s - %u bytes, %u named objects, " 383 "%u executable opcodes\n", 384 "AML Output:", 385 Gbl_Files[ASL_FILE_AML_OUTPUT].Filename, 386 FlGetFileSize (ASL_FILE_AML_OUTPUT), 387 TotalNamedObjects, TotalExecutableOpcodes); 388 } 389 } 390 } 391 392 /* Display summary of any optional files */ 393 394 for (i = ASL_FILE_SOURCE_OUTPUT; i <= ASL_MAX_FILE_TYPE; i++) 395 { 396 if (!Gbl_Files[i].Filename || !Gbl_Files[i].Handle) 397 { 398 continue; 399 } 400 401 /* .SRC is a temp file unless specifically requested */ 402 403 if ((i == ASL_FILE_SOURCE_OUTPUT) && (!Gbl_SourceOutputFlag)) 404 { 405 continue; 406 } 407 408 /* .PRE is the preprocessor intermediate file */ 409 410 if ((i == ASL_FILE_PREPROCESSOR) && (!Gbl_KeepPreprocessorTempFile)) 411 { 412 continue; 413 } 414 415 FlPrintFile (FileId, "%14s %s - %u bytes\n", 416 Gbl_Files[i].ShortDescription, 417 Gbl_Files[i].Filename, FlGetFileSize (i)); 418 } 419 420 /* Error summary */ 421 422 FlPrintFile (FileId, 423 "\nCompilation complete. %u Errors, %u Warnings, %u Remarks", 424 Gbl_ExceptionCount[ASL_ERROR], 425 Gbl_ExceptionCount[ASL_WARNING] + 426 Gbl_ExceptionCount[ASL_WARNING2] + 427 Gbl_ExceptionCount[ASL_WARNING3], 428 Gbl_ExceptionCount[ASL_REMARK]); 429 430 if (Gbl_FileType != ASL_INPUT_TYPE_ASCII_DATA) 431 { 432 FlPrintFile (FileId, ", %u Optimizations", 433 Gbl_ExceptionCount[ASL_OPTIMIZATION]); 434 435 if (TotalFolds) 436 { 437 FlPrintFile (FileId, ", %u Constants Folded", TotalFolds); 438 } 439 } 440 441 FlPrintFile (FileId, "\n"); 442 } 443 444 445 /******************************************************************************* 446 * 447 * FUNCTION: UtCheckIntegerRange 448 * 449 * PARAMETERS: Op - Integer parse node 450 * LowValue - Smallest allowed value 451 * HighValue - Largest allowed value 452 * 453 * RETURN: Op if OK, otherwise NULL 454 * 455 * DESCRIPTION: Check integer for an allowable range 456 * 457 ******************************************************************************/ 458 459 ACPI_PARSE_OBJECT * 460 UtCheckIntegerRange ( 461 ACPI_PARSE_OBJECT *Op, 462 UINT32 LowValue, 463 UINT32 HighValue) 464 { 465 466 if (!Op) 467 { 468 return (NULL); 469 } 470 471 if ((Op->Asl.Value.Integer < LowValue) || 472 (Op->Asl.Value.Integer > HighValue)) 473 { 474 snprintf (MsgBuffer, sizeof(MsgBuffer), "0x%X, allowable: 0x%X-0x%X", 475 (UINT32) Op->Asl.Value.Integer, LowValue, HighValue); 476 477 AslError (ASL_ERROR, ASL_MSG_RANGE, Op, MsgBuffer); 478 return (NULL); 479 } 480 481 return (Op); 482 } 483 484 485 /******************************************************************************* 486 * 487 * FUNCTION: UtInternalizeName 488 * 489 * PARAMETERS: ExternalName - Name to convert 490 * ConvertedName - Where the converted name is returned 491 * 492 * RETURN: Status 493 * 494 * DESCRIPTION: Convert an external (ASL) name to an internal (AML) name 495 * 496 ******************************************************************************/ 497 498 ACPI_STATUS 499 UtInternalizeName ( 500 char *ExternalName, 501 char **ConvertedName) 502 { 503 ACPI_NAMESTRING_INFO Info; 504 ACPI_STATUS Status; 505 506 507 if (!ExternalName) 508 { 509 return (AE_OK); 510 } 511 512 /* Get the length of the new internal name */ 513 514 Info.ExternalName = ExternalName; 515 AcpiNsGetInternalNameLength (&Info); 516 517 /* We need a segment to store the internal name */ 518 519 Info.InternalName = UtLocalCacheCalloc (Info.Length); 520 521 /* Build the name */ 522 523 Status = AcpiNsBuildInternalName (&Info); 524 if (ACPI_FAILURE (Status)) 525 { 526 return (Status); 527 } 528 529 *ConvertedName = Info.InternalName; 530 return (AE_OK); 531 } 532 533 534 /******************************************************************************* 535 * 536 * FUNCTION: UtPadNameWithUnderscores 537 * 538 * PARAMETERS: NameSeg - Input nameseg 539 * PaddedNameSeg - Output padded nameseg 540 * 541 * RETURN: Padded nameseg. 542 * 543 * DESCRIPTION: Pads a NameSeg with underscores if necessary to form a full 544 * ACPI_NAME. 545 * 546 ******************************************************************************/ 547 548 static void 549 UtPadNameWithUnderscores ( 550 char *NameSeg, 551 char *PaddedNameSeg) 552 { 553 UINT32 i; 554 555 556 for (i = 0; (i < ACPI_NAME_SIZE); i++) 557 { 558 if (*NameSeg) 559 { 560 *PaddedNameSeg = *NameSeg; 561 NameSeg++; 562 } 563 else 564 { 565 *PaddedNameSeg = '_'; 566 } 567 568 PaddedNameSeg++; 569 } 570 } 571 572 573 /******************************************************************************* 574 * 575 * FUNCTION: UtAttachNameseg 576 * 577 * PARAMETERS: Op - Parent parse node 578 * Name - Full ExternalName 579 * 580 * RETURN: None; Sets the NameSeg field in parent node 581 * 582 * DESCRIPTION: Extract the last nameseg of the ExternalName and store it 583 * in the NameSeg field of the Op. 584 * 585 ******************************************************************************/ 586 587 static void 588 UtAttachNameseg ( 589 ACPI_PARSE_OBJECT *Op, 590 char *Name) 591 { 592 char *NameSeg; 593 char PaddedNameSeg[4]; 594 595 596 if (!Name) 597 { 598 return; 599 } 600 601 /* Look for the last dot in the namepath */ 602 603 NameSeg = strrchr (Name, '.'); 604 if (NameSeg) 605 { 606 /* Found last dot, we have also found the final nameseg */ 607 608 NameSeg++; 609 UtPadNameWithUnderscores (NameSeg, PaddedNameSeg); 610 } 611 else 612 { 613 /* No dots in the namepath, there is only a single nameseg. */ 614 /* Handle prefixes */ 615 616 while (ACPI_IS_ROOT_PREFIX (*Name) || 617 ACPI_IS_PARENT_PREFIX (*Name)) 618 { 619 Name++; 620 } 621 622 /* Remaining string should be one single nameseg */ 623 624 UtPadNameWithUnderscores (Name, PaddedNameSeg); 625 } 626 627 ACPI_MOVE_NAME (Op->Asl.NameSeg, PaddedNameSeg); 628 } 629 630 631 /******************************************************************************* 632 * 633 * FUNCTION: UtAttachNamepathToOwner 634 * 635 * PARAMETERS: Op - Parent parse node 636 * NameOp - Node that contains the name 637 * 638 * RETURN: Sets the ExternalName and Namepath in the parent node 639 * 640 * DESCRIPTION: Store the name in two forms in the parent node: The original 641 * (external) name, and the internalized name that is used within 642 * the ACPI namespace manager. 643 * 644 ******************************************************************************/ 645 646 void 647 UtAttachNamepathToOwner ( 648 ACPI_PARSE_OBJECT *Op, 649 ACPI_PARSE_OBJECT *NameOp) 650 { 651 ACPI_STATUS Status; 652 653 654 /* Full external path */ 655 656 Op->Asl.ExternalName = NameOp->Asl.Value.String; 657 658 /* Save the NameOp for possible error reporting later */ 659 660 Op->Asl.ParentMethod = (void *) NameOp; 661 662 /* Last nameseg of the path */ 663 664 UtAttachNameseg (Op, Op->Asl.ExternalName); 665 666 /* Create internalized path */ 667 668 Status = UtInternalizeName (NameOp->Asl.Value.String, &Op->Asl.Namepath); 669 if (ACPI_FAILURE (Status)) 670 { 671 /* TBD: abort on no memory */ 672 } 673 } 674 675 676 /******************************************************************************* 677 * 678 * FUNCTION: UtDoConstant 679 * 680 * PARAMETERS: String - Hex/Decimal/Octal 681 * 682 * RETURN: Converted Integer 683 * 684 * DESCRIPTION: Convert a string to an integer, with overflow/error checking. 685 * 686 ******************************************************************************/ 687 688 UINT64 689 UtDoConstant ( 690 char *String) 691 { 692 ACPI_STATUS Status; 693 UINT64 ConvertedInteger; 694 char ErrBuf[64]; 695 696 697 Status = AcpiUtStrtoul64 (String, &ConvertedInteger); 698 if (ACPI_FAILURE (Status)) 699 { 700 snprintf (ErrBuf, sizeof(ErrBuf), "While creating 64-bit constant: %s\n", 701 AcpiFormatException (Status)); 702 703 AslCommonError (ASL_ERROR, ASL_MSG_SYNTAX, Gbl_CurrentLineNumber, 704 Gbl_LogicalLineNumber, Gbl_CurrentLineOffset, 705 Gbl_CurrentColumn, Gbl_Files[ASL_FILE_INPUT].Filename, ErrBuf); 706 } 707 708 return (ConvertedInteger); 709 } 710