1 /****************************************************************************** 2 * 3 * Module Name: asllisting - Listing file generation 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 "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 (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 (RootNode, ASL_WALK_VISIT_DOWNWARD, LsAmlOffsetWalk, 167 NULL, (void *) ACPI_TO_POINTER (FileId)); 168 LsDoOffsetTableFooter (FileId); 169 return; 170 } 171 172 /* Process all parse nodes */ 173 174 TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, LsAmlListingWalk, 175 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 TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, 262 LsTreeWriteWalk, NULL, NULL); 263 } 264 265 266 static ACPI_STATUS 267 LsTreeWriteWalk ( 268 ACPI_PARSE_OBJECT *Op, 269 UINT32 Level, 270 void *Context) 271 { 272 273 /* Debug output */ 274 275 DbgPrint (ASL_TREE_OUTPUT, 276 "%5.5d [%2d]", Op->Asl.LogicalLineNumber, Level); 277 278 UtPrintFormattedName (Op->Asl.ParseOpcode, Level); 279 280 if (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) 281 { 282 DbgPrint (ASL_TREE_OUTPUT, 283 "%10.4s ", Op->Asl.Value.Name); 284 } 285 else if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || 286 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 287 { 288 DbgPrint (ASL_TREE_OUTPUT, 289 "%10.32s ", Op->Asl.Value.String); 290 } 291 else if (Op->Asl.ParseOpcode == PARSEOP_INCLUDE) 292 { 293 DbgPrint (ASL_TREE_OUTPUT, 294 "Open: %s\n", Op->Asl.Value.String); 295 return (AE_OK); 296 } 297 else if (Op->Asl.ParseOpcode == PARSEOP_INCLUDE_END) 298 { 299 DbgPrint (ASL_TREE_OUTPUT, 300 "Close: %s\n", Op->Asl.Filename); 301 return (AE_OK); 302 } 303 else 304 { 305 DbgPrint (ASL_TREE_OUTPUT, " "); 306 } 307 308 DbgPrint (ASL_TREE_OUTPUT, " (%.4X) Flags %8.8X", 309 Op->Asl.ParseOpcode, Op->Asl.CompileFlags); 310 TrPrintNodeCompileFlags (Op->Asl.CompileFlags); 311 DbgPrint (ASL_TREE_OUTPUT, "\n"); 312 return (AE_OK); 313 } 314 315 316 /******************************************************************************* 317 * 318 * FUNCTION: LsWriteNodeToListing 319 * 320 * PARAMETERS: Op - Parse node to write to the listing file. 321 * FileId - ID of current listing file 322 * 323 * RETURN: None. 324 * 325 * DESCRIPTION: Write "a node" to the listing file. This means to 326 * 1) Write out all of the source text associated with the node 327 * 2) Write out all of the AML bytes associated with the node 328 * 3) Write any compiler exceptions associated with the node 329 * 330 ******************************************************************************/ 331 332 static void 333 LsWriteNodeToListing ( 334 ACPI_PARSE_OBJECT *Op, 335 UINT32 FileId) 336 { 337 const ACPI_OPCODE_INFO *OpInfo; 338 UINT32 OpClass; 339 char *Pathname; 340 UINT32 Length; 341 UINT32 i; 342 343 344 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 345 OpClass = OpInfo->Class; 346 347 /* TBD: clean this up with a single flag that says: 348 * I start a named output block 349 */ 350 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 351 { 352 switch (Op->Asl.ParseOpcode) 353 { 354 case PARSEOP_DEFINITION_BLOCK: 355 case PARSEOP_METHODCALL: 356 case PARSEOP_INCLUDE: 357 case PARSEOP_INCLUDE_END: 358 case PARSEOP_DEFAULT_ARG: 359 360 break; 361 362 default: 363 364 switch (OpClass) 365 { 366 case AML_CLASS_NAMED_OBJECT: 367 368 switch (Op->Asl.AmlOpcode) 369 { 370 case AML_SCOPE_OP: 371 case AML_ALIAS_OP: 372 373 break; 374 375 default: 376 377 if (Op->Asl.ExternalName) 378 { 379 LsFlushListingBuffer (FileId); 380 FlPrintFile (FileId, " };\n"); 381 } 382 break; 383 } 384 break; 385 386 default: 387 388 /* Don't care about other objects */ 389 390 break; 391 } 392 break; 393 } 394 } 395 396 /* These cases do not have a corresponding AML opcode */ 397 398 switch (Op->Asl.ParseOpcode) 399 { 400 case PARSEOP_DEFINITION_BLOCK: 401 402 LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, FileId); 403 404 /* Use the table Signature and TableId to build a unique name */ 405 406 switch (FileId) 407 { 408 case ASL_FILE_ASM_SOURCE_OUTPUT: 409 410 FlPrintFile (FileId, 411 "%s_%s_Header \\\n", 412 Gbl_TableSignature, Gbl_TableId); 413 break; 414 415 case ASL_FILE_C_SOURCE_OUTPUT: 416 417 FlPrintFile (FileId, 418 " unsigned char %s_%s_Header [] =\n {\n", 419 Gbl_TableSignature, Gbl_TableId); 420 break; 421 422 case ASL_FILE_ASM_INCLUDE_OUTPUT: 423 424 FlPrintFile (FileId, 425 "extrn %s_%s_Header : byte\n", 426 Gbl_TableSignature, Gbl_TableId); 427 break; 428 429 case ASL_FILE_C_INCLUDE_OUTPUT: 430 431 FlPrintFile (FileId, 432 "extern unsigned char %s_%s_Header [];\n", 433 Gbl_TableSignature, Gbl_TableId); 434 break; 435 436 default: 437 break; 438 } 439 440 return; 441 442 443 case PARSEOP_METHODCALL: 444 445 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 446 FileId); 447 return; 448 449 450 case PARSEOP_INCLUDE: 451 452 /* Flush everything up to and including the include source line */ 453 454 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 455 FileId); 456 457 /* Create a new listing node and push it */ 458 459 LsPushNode (Op->Asl.Value.String); 460 return; 461 462 463 case PARSEOP_INCLUDE_END: 464 465 /* Flush out the rest of the include file */ 466 467 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 468 FileId); 469 470 /* Pop off this listing node and go back to the parent file */ 471 472 (void) LsPopNode (); 473 return; 474 475 476 case PARSEOP_DEFAULT_ARG: 477 478 if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC) 479 { 480 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.EndLogicalLine, 481 FileId); 482 } 483 return; 484 485 486 default: 487 488 /* All other opcodes have an AML opcode */ 489 490 break; 491 } 492 493 /* 494 * Otherwise, we look at the AML opcode because we can 495 * switch on the opcode type, getting an entire class 496 * at once 497 */ 498 switch (OpClass) 499 { 500 case AML_CLASS_ARGUMENT: /* argument type only */ 501 case AML_CLASS_INTERNAL: 502 503 break; 504 505 case AML_CLASS_NAMED_OBJECT: 506 507 switch (Op->Asl.AmlOpcode) 508 { 509 case AML_FIELD_OP: 510 case AML_INDEX_FIELD_OP: 511 case AML_BANK_FIELD_OP: 512 /* 513 * For fields, we want to dump all the AML after the 514 * entire definition 515 */ 516 LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, 517 FileId); 518 break; 519 520 case AML_NAME_OP: 521 522 if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC) 523 { 524 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 525 FileId); 526 } 527 else 528 { 529 /* 530 * For fields, we want to dump all the AML after the 531 * entire definition 532 */ 533 LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, 534 FileId); 535 } 536 break; 537 538 default: 539 540 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 541 FileId); 542 break; 543 } 544 545 switch (Op->Asl.AmlOpcode) 546 { 547 case AML_SCOPE_OP: 548 case AML_ALIAS_OP: 549 550 /* These opcodes do not declare a new object, ignore them */ 551 552 break; 553 554 default: 555 556 /* All other named object opcodes come here */ 557 558 switch (FileId) 559 { 560 case ASL_FILE_ASM_SOURCE_OUTPUT: 561 case ASL_FILE_C_SOURCE_OUTPUT: 562 case ASL_FILE_ASM_INCLUDE_OUTPUT: 563 case ASL_FILE_C_INCLUDE_OUTPUT: 564 /* 565 * For named objects, we will create a valid symbol so that the 566 * AML code can be referenced from C or ASM 567 */ 568 if (Op->Asl.ExternalName) 569 { 570 /* Get the full pathname associated with this node */ 571 572 Pathname = AcpiNsGetExternalPathname (Op->Asl.Node); 573 Length = strlen (Pathname); 574 if (Length >= 4) 575 { 576 /* Convert all dots in the path to underscores */ 577 578 for (i = 0; i < Length; i++) 579 { 580 if (Pathname[i] == '.') 581 { 582 Pathname[i] = '_'; 583 } 584 } 585 586 /* Create the appropriate symbol in the output file */ 587 588 switch (FileId) 589 { 590 case ASL_FILE_ASM_SOURCE_OUTPUT: 591 592 FlPrintFile (FileId, 593 "%s_%s_%s \\\n", 594 Gbl_TableSignature, Gbl_TableId, &Pathname[1]); 595 break; 596 597 case ASL_FILE_C_SOURCE_OUTPUT: 598 599 FlPrintFile (FileId, 600 " unsigned char %s_%s_%s [] =\n {\n", 601 Gbl_TableSignature, Gbl_TableId, &Pathname[1]); 602 break; 603 604 case ASL_FILE_ASM_INCLUDE_OUTPUT: 605 606 FlPrintFile (FileId, 607 "extrn %s_%s_%s : byte\n", 608 Gbl_TableSignature, Gbl_TableId, &Pathname[1]); 609 break; 610 611 case ASL_FILE_C_INCLUDE_OUTPUT: 612 613 FlPrintFile (FileId, 614 "extern unsigned char %s_%s_%s [];\n", 615 Gbl_TableSignature, Gbl_TableId, &Pathname[1]); 616 break; 617 618 default: 619 break; 620 } 621 } 622 623 ACPI_FREE (Pathname); 624 } 625 break; 626 627 default: 628 629 /* Nothing to do for listing file */ 630 631 break; 632 } 633 } 634 break; 635 636 case AML_CLASS_EXECUTE: 637 case AML_CLASS_CREATE: 638 default: 639 640 if ((Op->Asl.ParseOpcode == PARSEOP_BUFFER) && 641 (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)) 642 { 643 return; 644 } 645 646 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 647 FileId); 648 break; 649 650 case AML_CLASS_UNKNOWN: 651 652 break; 653 } 654 } 655 656 657 /******************************************************************************* 658 * 659 * FUNCTION: LsFinishSourceListing 660 * 661 * PARAMETERS: FileId - ID of current listing file. 662 * 663 * RETURN: None 664 * 665 * DESCRIPTION: Cleanup routine for the listing file. Flush the hex AML 666 * listing buffer, and flush out any remaining lines in the 667 * source input file. 668 * 669 ******************************************************************************/ 670 671 static void 672 LsFinishSourceListing ( 673 UINT32 FileId) 674 { 675 676 if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) || 677 (FileId == ASL_FILE_C_INCLUDE_OUTPUT)) 678 { 679 return; 680 } 681 682 LsFlushListingBuffer (FileId); 683 Gbl_CurrentAmlOffset = 0; 684 685 /* Flush any remaining text in the source file */ 686 687 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 688 { 689 FlPrintFile (FileId, " /*\n"); 690 } 691 692 while (LsWriteOneSourceLine (FileId)) 693 { ; } 694 695 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 696 { 697 FlPrintFile (FileId, "\n */\n };\n"); 698 } 699 700 FlPrintFile (FileId, "\n"); 701 702 if (FileId == ASL_FILE_LISTING_OUTPUT) 703 { 704 /* Print a summary of the compile exceptions */ 705 706 FlPrintFile (FileId, "\n\nSummary of errors and warnings\n\n"); 707 AePrintErrorLog (FileId); 708 FlPrintFile (FileId, "\n"); 709 UtDisplaySummary (FileId); 710 FlPrintFile (FileId, "\n"); 711 } 712 } 713