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