1 /****************************************************************************** 2 * 3 * Module Name: asllisting - Listing file generation 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2021, 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 MERCHANTABILITY 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 "amlcode.h" 47 #include "acparser.h" 48 #include "acnamesp.h" 49 50 51 #define _COMPONENT ACPI_COMPILER 52 ACPI_MODULE_NAME ("asllisting") 53 54 55 /* Local prototypes */ 56 57 static void 58 LsGenerateListing ( 59 UINT32 FileId); 60 61 static ACPI_STATUS 62 LsAmlListingWalk ( 63 ACPI_PARSE_OBJECT *Op, 64 UINT32 Level, 65 void *Context); 66 67 static ACPI_STATUS 68 LsTreeWriteWalk ( 69 ACPI_PARSE_OBJECT *Op, 70 UINT32 Level, 71 void *Context); 72 73 static void 74 LsWriteNodeToListing ( 75 ACPI_PARSE_OBJECT *Op, 76 UINT32 FileId); 77 78 static void 79 LsFinishSourceListing ( 80 UINT32 FileId); 81 82 83 /******************************************************************************* 84 * 85 * FUNCTION: LsDoListings 86 * 87 * PARAMETERS: None. Examines the various output file global flags. 88 * 89 * RETURN: None 90 * 91 * DESCRIPTION: Generate all requested listing files. 92 * 93 ******************************************************************************/ 94 95 void 96 LsDoListings ( 97 void) 98 { 99 100 if (AslGbl_C_OutputFlag) 101 { 102 LsGenerateListing (ASL_FILE_C_SOURCE_OUTPUT); 103 } 104 105 if (AslGbl_ListingFlag) 106 { 107 LsGenerateListing (ASL_FILE_LISTING_OUTPUT); 108 } 109 110 if (AslGbl_AsmOutputFlag) 111 { 112 LsGenerateListing (ASL_FILE_ASM_SOURCE_OUTPUT); 113 } 114 115 if (AslGbl_C_IncludeOutputFlag) 116 { 117 LsGenerateListing (ASL_FILE_C_INCLUDE_OUTPUT); 118 } 119 120 if (AslGbl_AsmIncludeOutputFlag) 121 { 122 LsGenerateListing (ASL_FILE_ASM_INCLUDE_OUTPUT); 123 } 124 125 if (AslGbl_C_OffsetTableFlag) 126 { 127 LsGenerateListing (ASL_FILE_C_OFFSET_OUTPUT); 128 } 129 } 130 131 132 /******************************************************************************* 133 * 134 * FUNCTION: LsGenerateListing 135 * 136 * PARAMETERS: FileId - ID of listing file 137 * 138 * RETURN: None 139 * 140 * DESCRIPTION: Generate a listing file. This can be one of the several types 141 * of "listings" supported. 142 * 143 ******************************************************************************/ 144 145 static void 146 LsGenerateListing ( 147 UINT32 FileId) 148 { 149 UINT32 WalkMode = ASL_WALK_VISIT_DOWNWARD | ASL_WALK_VISIT_DB_SEPARATELY; 150 151 /* Start at the beginning of both the source and AML files */ 152 153 FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0); 154 FlSeekFile (ASL_FILE_AML_OUTPUT, 0); 155 AslGbl_SourceLine = 0; 156 AslGbl_CurrentHexColumn = 0; 157 LsPushNode (AslGbl_Files[ASL_FILE_INPUT].Filename); 158 159 if (FileId == ASL_FILE_C_OFFSET_OUTPUT) 160 { 161 AslGbl_CurrentAmlOffset = 0; 162 163 /* Offset table file has a special header and footer */ 164 165 LsDoOffsetTableHeader (FileId); 166 167 TrWalkParseTree (AslGbl_CurrentDB, WalkMode, 168 LsAmlOffsetWalk, NULL, (void *) ACPI_TO_POINTER (FileId)); 169 LsDoOffsetTableFooter (FileId); 170 return; 171 } 172 173 /* Process all parse nodes */ 174 175 TrWalkParseTree (AslGbl_CurrentDB, WalkMode, 176 LsAmlListingWalk, NULL, (void *) ACPI_TO_POINTER (FileId)); 177 178 /* Final processing */ 179 180 LsFinishSourceListing (FileId); 181 } 182 183 184 /******************************************************************************* 185 * 186 * FUNCTION: LsAmlListingWalk 187 * 188 * PARAMETERS: ASL_WALK_CALLBACK 189 * 190 * RETURN: Status 191 * 192 * DESCRIPTION: Process one node during a listing file generation. 193 * 194 ******************************************************************************/ 195 196 static ACPI_STATUS 197 LsAmlListingWalk ( 198 ACPI_PARSE_OBJECT *Op, 199 UINT32 Level, 200 void *Context) 201 { 202 UINT8 FileByte; 203 UINT32 i; 204 UINT32 FileId = (UINT32) ACPI_TO_INTEGER (Context); 205 206 207 LsWriteNodeToListing (Op, FileId); 208 209 if (Op->Asl.CompileFlags & OP_IS_RESOURCE_DATA) 210 { 211 /* Buffer is a resource template, don't dump the data all at once */ 212 213 return (AE_OK); 214 } 215 216 if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) || 217 (FileId == ASL_FILE_C_INCLUDE_OUTPUT)) 218 { 219 return (AE_OK); 220 } 221 222 /* Write the hex bytes to the listing file(s) (if requested) */ 223 224 for (i = 0; i < Op->Asl.FinalAmlLength; i++) 225 { 226 if (ACPI_FAILURE (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1))) 227 { 228 FlFileError (ASL_FILE_AML_OUTPUT, ASL_MSG_READ); 229 AslAbort (); 230 } 231 232 LsWriteListingHexBytes (&FileByte, 1, FileId); 233 } 234 235 return (AE_OK); 236 } 237 238 239 /******************************************************************************* 240 * 241 * FUNCTION: LsDumpParseTree, LsTreeWriteWalk 242 * 243 * PARAMETERS: None 244 * 245 * RETURN: None 246 * 247 * DESCRIPTION: Dump entire parse tree, for compiler debug only 248 * 249 ******************************************************************************/ 250 251 void 252 LsDumpParseTree ( 253 void) 254 { 255 256 if (!AslGbl_DebugFlag) 257 { 258 return; 259 } 260 261 DbgPrint (ASL_TREE_OUTPUT, "\nOriginal parse tree from parser:\n\n"); 262 DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_HEADER1); 263 264 TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD, 265 LsTreeWriteWalk, NULL, NULL); 266 267 DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_HEADER1); 268 } 269 270 271 static ACPI_STATUS 272 LsTreeWriteWalk ( 273 ACPI_PARSE_OBJECT *Op, 274 UINT32 Level, 275 void *Context) 276 { 277 278 /* Dump ParseOp name and possible value */ 279 280 switch (Op->Asl.ParseOpcode) 281 { 282 case PARSEOP_NAMESEG: 283 case PARSEOP_NAMESTRING: 284 case PARSEOP_METHODCALL: 285 case PARSEOP_STRING_LITERAL: 286 287 UtDumpStringOp (Op, Level); 288 break; 289 290 case PARSEOP_BYTECONST: 291 292 UtDumpIntegerOp (Op, Level, 2); 293 break; 294 295 case PARSEOP_WORDCONST: 296 case PARSEOP_PACKAGE_LENGTH: 297 298 UtDumpIntegerOp (Op, Level, 4); 299 break; 300 301 case PARSEOP_DWORDCONST: 302 case PARSEOP_EISAID: 303 304 UtDumpIntegerOp (Op, Level, 8); 305 break; 306 307 case PARSEOP_QWORDCONST: 308 case PARSEOP_INTEGER: 309 case PARSEOP_ONE: 310 case PARSEOP_ZERO: 311 case PARSEOP_ONES: 312 313 UtDumpIntegerOp (Op, Level, 16); 314 break; 315 316 case PARSEOP_INCLUDE: 317 318 DbgPrint (ASL_TREE_OUTPUT, 319 "Open: %s\n", Op->Asl.Value.String); 320 return (AE_OK); 321 322 case PARSEOP_INCLUDE_END: 323 324 DbgPrint (ASL_TREE_OUTPUT, 325 "Close: %s\n", Op->Asl.Filename); 326 return (AE_OK); 327 328 default: 329 330 UtDumpBasicOp (Op, Level); 331 break; 332 } 333 334 /* Dump the remaining data */ 335 336 DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_DEBUG1, 337 Op->Asl.ParseOpcode, Op->Asl.CompileFlags, 338 Op->Asl.LineNumber, Op->Asl.EndLine, 339 Op->Asl.LogicalLineNumber, Op->Asl.EndLogicalLine); 340 341 TrPrintOpFlags (Op->Asl.CompileFlags, ASL_TREE_OUTPUT); 342 DbgPrint (ASL_TREE_OUTPUT, "\n"); 343 return (AE_OK); 344 } 345 346 347 /******************************************************************************* 348 * 349 * FUNCTION: LsWriteNodeToListing 350 * 351 * PARAMETERS: Op - Parse node to write to the listing file. 352 * FileId - ID of current listing file 353 * 354 * RETURN: None. 355 * 356 * DESCRIPTION: Write "a node" to the listing file. This means to 357 * 1) Write out all of the source text associated with the node 358 * 2) Write out all of the AML bytes associated with the node 359 * 3) Write any compiler exceptions associated with the node 360 * 361 ******************************************************************************/ 362 363 static void 364 LsWriteNodeToListing ( 365 ACPI_PARSE_OBJECT *Op, 366 UINT32 FileId) 367 { 368 const ACPI_OPCODE_INFO *OpInfo; 369 UINT32 OpClass; 370 char *Pathname; 371 UINT32 Length; 372 UINT32 i; 373 374 375 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 376 OpClass = OpInfo->Class; 377 378 /* TBD: clean this up with a single flag that says: 379 * I start a named output block 380 */ 381 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 382 { 383 switch (Op->Asl.ParseOpcode) 384 { 385 case PARSEOP_DEFINITION_BLOCK: 386 case PARSEOP_METHODCALL: 387 case PARSEOP_INCLUDE: 388 case PARSEOP_INCLUDE_END: 389 case PARSEOP_DEFAULT_ARG: 390 391 break; 392 393 default: 394 395 switch (OpClass) 396 { 397 case AML_CLASS_NAMED_OBJECT: 398 399 switch (Op->Asl.AmlOpcode) 400 { 401 case AML_SCOPE_OP: 402 case AML_ALIAS_OP: 403 404 break; 405 406 default: 407 408 if (Op->Asl.ExternalName) 409 { 410 LsFlushListingBuffer (FileId); 411 FlPrintFile (FileId, " };\n"); 412 } 413 break; 414 } 415 break; 416 417 default: 418 419 /* Don't care about other objects */ 420 421 break; 422 } 423 break; 424 } 425 } 426 427 /* These cases do not have a corresponding AML opcode */ 428 429 switch (Op->Asl.ParseOpcode) 430 { 431 case PARSEOP_DEFINITION_BLOCK: 432 433 /* Always start a definition block at AML offset zero */ 434 435 AslGbl_CurrentAmlOffset = 0; 436 LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, FileId); 437 438 /* Use the table Signature and TableId to build a unique name */ 439 440 switch (FileId) 441 { 442 case ASL_FILE_ASM_SOURCE_OUTPUT: 443 444 FlPrintFile (FileId, 445 "%s_%s_Header \\\n", 446 AslGbl_TableSignature, AslGbl_TableId); 447 break; 448 449 case ASL_FILE_C_SOURCE_OUTPUT: 450 451 FlPrintFile (FileId, 452 " unsigned char %s_%s_Header [] =\n {\n", 453 AslGbl_TableSignature, AslGbl_TableId); 454 break; 455 456 case ASL_FILE_ASM_INCLUDE_OUTPUT: 457 458 FlPrintFile (FileId, 459 "extrn %s_%s_Header : byte\n", 460 AslGbl_TableSignature, AslGbl_TableId); 461 break; 462 463 case ASL_FILE_C_INCLUDE_OUTPUT: 464 465 FlPrintFile (FileId, 466 "extern unsigned char %s_%s_Header [];\n", 467 AslGbl_TableSignature, AslGbl_TableId); 468 break; 469 470 default: 471 break; 472 } 473 474 return; 475 476 477 case PARSEOP_METHODCALL: 478 479 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 480 FileId); 481 return; 482 483 484 case PARSEOP_INCLUDE: 485 486 /* Flush everything up to and including the include source line */ 487 488 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 489 FileId); 490 491 /* Create a new listing node and push it */ 492 493 LsPushNode (Op->Asl.Value.String); 494 return; 495 496 497 case PARSEOP_INCLUDE_END: 498 499 /* Flush out the rest of the include file */ 500 501 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 502 FileId); 503 504 /* Pop off this listing node and go back to the parent file */ 505 506 (void) LsPopNode (); 507 return; 508 509 510 case PARSEOP_DEFAULT_ARG: 511 512 if (Op->Asl.CompileFlags & OP_IS_RESOURCE_DESC) 513 { 514 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.EndLogicalLine, 515 FileId); 516 } 517 return; 518 519 520 default: 521 522 /* All other opcodes have an AML opcode */ 523 524 break; 525 } 526 527 /* 528 * Otherwise, we look at the AML opcode because we can 529 * switch on the opcode type, getting an entire class 530 * at once 531 */ 532 switch (OpClass) 533 { 534 case AML_CLASS_ARGUMENT: /* argument type only */ 535 case AML_CLASS_INTERNAL: 536 537 break; 538 539 case AML_CLASS_NAMED_OBJECT: 540 541 switch (Op->Asl.AmlOpcode) 542 { 543 case AML_FIELD_OP: 544 case AML_INDEX_FIELD_OP: 545 case AML_BANK_FIELD_OP: 546 /* 547 * For fields, we want to dump all the AML after the 548 * entire definition 549 */ 550 LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, 551 FileId); 552 break; 553 554 case AML_NAME_OP: 555 556 if (Op->Asl.CompileFlags & OP_IS_RESOURCE_DESC) 557 { 558 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 559 FileId); 560 } 561 else 562 { 563 /* 564 * For fields, we want to dump all the AML after the 565 * entire definition 566 */ 567 LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, 568 FileId); 569 } 570 break; 571 572 default: 573 574 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 575 FileId); 576 break; 577 } 578 579 switch (Op->Asl.AmlOpcode) 580 { 581 case AML_SCOPE_OP: 582 case AML_ALIAS_OP: 583 584 /* These opcodes do not declare a new object, ignore them */ 585 586 break; 587 588 default: 589 590 /* All other named object opcodes come here */ 591 592 switch (FileId) 593 { 594 case ASL_FILE_ASM_SOURCE_OUTPUT: 595 case ASL_FILE_C_SOURCE_OUTPUT: 596 case ASL_FILE_ASM_INCLUDE_OUTPUT: 597 case ASL_FILE_C_INCLUDE_OUTPUT: 598 /* 599 * For named objects, we will create a valid symbol so that the 600 * AML code can be referenced from C or ASM 601 */ 602 if (Op->Asl.ExternalName) 603 { 604 /* Get the full pathname associated with this node */ 605 606 Pathname = AcpiNsGetExternalPathname (Op->Asl.Node); 607 Length = strlen (Pathname); 608 if (Length >= 4) 609 { 610 /* Convert all dots in the path to underscores */ 611 612 for (i = 0; i < Length; i++) 613 { 614 if (Pathname[i] == '.') 615 { 616 Pathname[i] = '_'; 617 } 618 } 619 620 /* Create the appropriate symbol in the output file */ 621 622 switch (FileId) 623 { 624 case ASL_FILE_ASM_SOURCE_OUTPUT: 625 626 FlPrintFile (FileId, 627 "%s_%s_%s \\\n", 628 AslGbl_TableSignature, AslGbl_TableId, &Pathname[1]); 629 break; 630 631 case ASL_FILE_C_SOURCE_OUTPUT: 632 633 FlPrintFile (FileId, 634 " unsigned char %s_%s_%s [] =\n {\n", 635 AslGbl_TableSignature, AslGbl_TableId, &Pathname[1]); 636 break; 637 638 case ASL_FILE_ASM_INCLUDE_OUTPUT: 639 640 FlPrintFile (FileId, 641 "extrn %s_%s_%s : byte\n", 642 AslGbl_TableSignature, AslGbl_TableId, &Pathname[1]); 643 break; 644 645 case ASL_FILE_C_INCLUDE_OUTPUT: 646 647 FlPrintFile (FileId, 648 "extern unsigned char %s_%s_%s [];\n", 649 AslGbl_TableSignature, AslGbl_TableId, &Pathname[1]); 650 break; 651 652 default: 653 break; 654 } 655 } 656 657 ACPI_FREE (Pathname); 658 } 659 break; 660 661 default: 662 663 /* Nothing to do for listing file */ 664 665 break; 666 } 667 } 668 break; 669 670 case AML_CLASS_EXECUTE: 671 case AML_CLASS_CREATE: 672 default: 673 674 if ((Op->Asl.ParseOpcode == PARSEOP_BUFFER) && 675 (Op->Asl.CompileFlags & OP_IS_RESOURCE_DESC)) 676 { 677 return; 678 } 679 680 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 681 FileId); 682 break; 683 684 case AML_CLASS_UNKNOWN: 685 686 break; 687 } 688 } 689 690 691 /******************************************************************************* 692 * 693 * FUNCTION: LsFinishSourceListing 694 * 695 * PARAMETERS: FileId - ID of current listing file. 696 * 697 * RETURN: None 698 * 699 * DESCRIPTION: Cleanup routine for the listing file. Flush the hex AML 700 * listing buffer, and flush out any remaining lines in the 701 * source input file. 702 * 703 ******************************************************************************/ 704 705 static void 706 LsFinishSourceListing ( 707 UINT32 FileId) 708 { 709 710 if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) || 711 (FileId == ASL_FILE_C_INCLUDE_OUTPUT)) 712 { 713 return; 714 } 715 716 LsFlushListingBuffer (FileId); 717 AslGbl_CurrentAmlOffset = 0; 718 719 /* Flush any remaining text in the source file */ 720 721 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 722 { 723 FlPrintFile (FileId, " /*\n"); 724 } 725 726 while (LsWriteOneSourceLine (FileId)) 727 { ; } 728 729 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 730 { 731 FlPrintFile (FileId, "\n */\n };\n"); 732 } 733 734 FlPrintFile (FileId, "\n"); 735 736 if (FileId == ASL_FILE_LISTING_OUTPUT) 737 { 738 /* Print a summary of the compile exceptions */ 739 740 FlPrintFile (FileId, "\n\nSummary of errors and warnings\n\n"); 741 AePrintErrorLog (FileId); 742 FlPrintFile (FileId, "\n"); 743 UtDisplayOneSummary (FileId, TRUE); 744 FlPrintFile (FileId, "\n"); 745 } 746 } 747