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