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 }