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