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