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