1 2 /****************************************************************************** 3 * 4 * Module Name: asllisting - Listing file generation 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2011, Intel Corp. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45 46 #include <contrib/dev/acpica/compiler/aslcompiler.h> 47 #include "aslcompiler.y.h" 48 #include <contrib/dev/acpica/include/amlcode.h> 49 #include <contrib/dev/acpica/include/acparser.h> 50 #include <contrib/dev/acpica/include/acnamesp.h> 51 52 #define _COMPONENT ACPI_COMPILER 53 ACPI_MODULE_NAME ("aslisting") 54 55 /* Local prototypes */ 56 57 static void 58 LsDumpAscii ( 59 UINT32 FileId, 60 UINT32 Count, 61 UINT8 *Buffer); 62 63 static void 64 LsDumpAsciiInComment ( 65 UINT32 FileId, 66 UINT32 Count, 67 UINT8 *Buffer); 68 69 static ACPI_STATUS 70 LsAmlListingWalk ( 71 ACPI_PARSE_OBJECT *Op, 72 UINT32 Level, 73 void *Context); 74 75 static void 76 LsGenerateListing ( 77 UINT32 FileId); 78 79 static void 80 LsPushNode ( 81 char *Filename); 82 83 static ASL_LISTING_NODE * 84 LsPopNode ( 85 void); 86 87 static void 88 LsCheckException ( 89 UINT32 LineNumber, 90 UINT32 FileId); 91 92 static void 93 LsFlushListingBuffer ( 94 UINT32 FileId); 95 96 static void 97 LsWriteListingHexBytes ( 98 UINT8 *Buffer, 99 UINT32 Length, 100 UINT32 FileId); 101 102 static UINT32 103 LsWriteOneSourceLine ( 104 UINT32 FileId); 105 106 static void 107 LsFinishSourceListing ( 108 UINT32 FileId); 109 110 static void 111 LsWriteSourceLines ( 112 UINT32 ToLineNumber, 113 UINT32 ToLogicalLineNumber, 114 UINT32 FileId); 115 116 static void 117 LsWriteNodeToListing ( 118 ACPI_PARSE_OBJECT *Op, 119 UINT32 FileId); 120 121 static void 122 LsDoHexOutputC ( 123 void); 124 125 static void 126 LsDoHexOutputAsm ( 127 void); 128 129 static void 130 LsDoHexOutputAsl ( 131 void); 132 133 static ACPI_STATUS 134 LsTreeWriteWalk ( 135 ACPI_PARSE_OBJECT *Op, 136 UINT32 Level, 137 void *Context); 138 139 140 /******************************************************************************* 141 * 142 * FUNCTION: LsTreeWriteWalk 143 * 144 * PARAMETERS: ASL_WALK_CALLBACK 145 * 146 * 147 * RETURN: None. 148 * 149 * DESCRIPTION: Dump entire parse tree, for compiler debug only 150 * 151 ******************************************************************************/ 152 153 static ACPI_STATUS 154 LsTreeWriteWalk ( 155 ACPI_PARSE_OBJECT *Op, 156 UINT32 Level, 157 void *Context) 158 { 159 160 /* Debug output */ 161 162 DbgPrint (ASL_TREE_OUTPUT, 163 "%5.5d [%2d]", Op->Asl.LogicalLineNumber, Level); 164 UtPrintFormattedName (Op->Asl.ParseOpcode, Level); 165 166 167 DbgPrint (ASL_TREE_OUTPUT, "\n"); 168 return (AE_OK); 169 } 170 171 172 void 173 LsDumpParseTree ( 174 void) 175 { 176 177 if (!Gbl_DebugFlag) 178 { 179 return; 180 } 181 182 DbgPrint (ASL_TREE_OUTPUT, "\nOriginal parse tree from parser:\n\n"); 183 TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, 184 LsTreeWriteWalk, NULL, NULL); 185 } 186 187 188 /******************************************************************************* 189 * 190 * FUNCTION: LsDumpAscii 191 * 192 * PARAMETERS: FileId - ID of current listing file 193 * Count - Number of bytes to convert 194 * Buffer - Buffer of bytes to convert 195 * 196 * RETURN: None. 197 * 198 * DESCRIPTION: Convert hex bytes to ascii 199 * 200 ******************************************************************************/ 201 202 static void 203 LsDumpAscii ( 204 UINT32 FileId, 205 UINT32 Count, 206 UINT8 *Buffer) 207 { 208 UINT8 BufChar; 209 UINT32 i; 210 211 212 FlPrintFile (FileId, " \""); 213 for (i = 0; i < Count; i++) 214 { 215 BufChar = Buffer[i]; 216 if (isprint (BufChar)) 217 { 218 FlPrintFile (FileId, "%c", BufChar); 219 } 220 else 221 { 222 /* Not a printable character, just put out a dot */ 223 224 FlPrintFile (FileId, "."); 225 } 226 } 227 FlPrintFile (FileId, "\""); 228 } 229 230 231 /******************************************************************************* 232 * 233 * FUNCTION: LsDumpAsciiInComment 234 * 235 * PARAMETERS: FileId - ID of current listing file 236 * Count - Number of bytes to convert 237 * Buffer - Buffer of bytes to convert 238 * 239 * RETURN: None. 240 * 241 * DESCRIPTION: Convert hex bytes to ascii 242 * 243 ******************************************************************************/ 244 245 static void 246 LsDumpAsciiInComment ( 247 UINT32 FileId, 248 UINT32 Count, 249 UINT8 *Buffer) 250 { 251 UINT8 BufChar = 0; 252 UINT8 LastChar; 253 UINT32 i; 254 255 256 FlPrintFile (FileId, " \""); 257 for (i = 0; i < Count; i++) 258 { 259 LastChar = BufChar; 260 BufChar = Buffer[i]; 261 262 if (isprint (BufChar)) 263 { 264 /* Handle embedded C comment sequences */ 265 266 if (((LastChar == '*') && (BufChar == '/')) || 267 ((LastChar == '/') && (BufChar == '*'))) 268 { 269 /* Insert a space to break the sequence */ 270 271 FlPrintFile (FileId, ".", BufChar); 272 } 273 274 FlPrintFile (FileId, "%c", BufChar); 275 } 276 else 277 { 278 /* Not a printable character, just put out a dot */ 279 280 FlPrintFile (FileId, "."); 281 } 282 } 283 FlPrintFile (FileId, "\""); 284 } 285 286 287 /******************************************************************************* 288 * 289 * FUNCTION: LsAmlListingWalk 290 * 291 * PARAMETERS: ASL_WALK_CALLBACK 292 * 293 * RETURN: Status 294 * 295 * DESCRIPTION: Process one node during a listing file generation. 296 * 297 ******************************************************************************/ 298 299 static ACPI_STATUS 300 LsAmlListingWalk ( 301 ACPI_PARSE_OBJECT *Op, 302 UINT32 Level, 303 void *Context) 304 { 305 UINT8 FileByte; 306 UINT32 i; 307 UINT32 FileId = (UINT32) ACPI_TO_INTEGER (Context); 308 309 310 LsWriteNodeToListing (Op, FileId); 311 312 if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DATA) 313 { 314 /* Buffer is a resource template, don't dump the data all at once */ 315 316 return (AE_OK); 317 } 318 319 /* Write the hex bytes to the listing file(s) (if requested) */ 320 321 for (i = 0; i < Op->Asl.FinalAmlLength; i++) 322 { 323 if (ACPI_FAILURE (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1))) 324 { 325 FlFileError (ASL_FILE_AML_OUTPUT, ASL_MSG_READ); 326 AslAbort (); 327 } 328 LsWriteListingHexBytes (&FileByte, 1, FileId); 329 } 330 331 return (AE_OK); 332 } 333 334 335 /******************************************************************************* 336 * 337 * FUNCTION: LsGenerateListing 338 * 339 * PARAMETERS: FileId - ID of listing file 340 * 341 * RETURN: None 342 * 343 * DESCRIPTION: Generate a listing file. This can be one of the several types 344 * of "listings" supported. 345 * 346 ******************************************************************************/ 347 348 static void 349 LsGenerateListing ( 350 UINT32 FileId) 351 { 352 353 /* Start at the beginning of both the source and AML files */ 354 355 FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0); 356 FlSeekFile (ASL_FILE_AML_OUTPUT, 0); 357 Gbl_SourceLine = 0; 358 Gbl_CurrentHexColumn = 0; 359 LsPushNode (Gbl_Files[ASL_FILE_INPUT].Filename); 360 361 /* Process all parse nodes */ 362 363 TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, LsAmlListingWalk, 364 NULL, (void *) ACPI_TO_POINTER (FileId)); 365 366 /* Final processing */ 367 368 LsFinishSourceListing (FileId); 369 } 370 371 372 /******************************************************************************* 373 * 374 * FUNCTION: LsDoListings 375 * 376 * PARAMETERS: None. 377 * 378 * RETURN: None 379 * 380 * DESCRIPTION: Generate all requested listing files. 381 * 382 ******************************************************************************/ 383 384 void 385 LsDoListings ( 386 void) 387 { 388 389 if (Gbl_C_OutputFlag) 390 { 391 LsGenerateListing (ASL_FILE_C_SOURCE_OUTPUT); 392 } 393 394 if (Gbl_ListingFlag) 395 { 396 LsGenerateListing (ASL_FILE_LISTING_OUTPUT); 397 } 398 399 if (Gbl_AsmOutputFlag) 400 { 401 LsGenerateListing (ASL_FILE_ASM_SOURCE_OUTPUT); 402 } 403 404 if (Gbl_C_IncludeOutputFlag) 405 { 406 LsGenerateListing (ASL_FILE_C_INCLUDE_OUTPUT); 407 } 408 409 if (Gbl_AsmIncludeOutputFlag) 410 { 411 LsGenerateListing (ASL_FILE_ASM_INCLUDE_OUTPUT); 412 } 413 } 414 415 416 /******************************************************************************* 417 * 418 * FUNCTION: LsPushNode 419 * 420 * PARAMETERS: Filename - Pointer to the include filename 421 * 422 * RETURN: None 423 * 424 * DESCRIPTION: Push a listing node on the listing/include file stack. This 425 * stack enables tracking of include files (infinitely nested) 426 * and resumption of the listing of the parent file when the 427 * include file is finished. 428 * 429 ******************************************************************************/ 430 431 static void 432 LsPushNode ( 433 char *Filename) 434 { 435 ASL_LISTING_NODE *Lnode; 436 437 438 /* Create a new node */ 439 440 Lnode = UtLocalCalloc (sizeof (ASL_LISTING_NODE)); 441 442 /* Initialize */ 443 444 Lnode->Filename = Filename; 445 Lnode->LineNumber = 0; 446 447 /* Link (push) */ 448 449 Lnode->Next = Gbl_ListingNode; 450 Gbl_ListingNode = Lnode; 451 } 452 453 454 /******************************************************************************* 455 * 456 * FUNCTION: LsPopNode 457 * 458 * PARAMETERS: None 459 * 460 * RETURN: List head after current head is popped off 461 * 462 * DESCRIPTION: Pop the current head of the list, free it, and return the 463 * next node on the stack (the new current node). 464 * 465 ******************************************************************************/ 466 467 static ASL_LISTING_NODE * 468 LsPopNode ( 469 void) 470 { 471 ASL_LISTING_NODE *Lnode; 472 473 474 /* Just grab the node at the head of the list */ 475 476 Lnode = Gbl_ListingNode; 477 if ((!Lnode) || 478 (!Lnode->Next)) 479 { 480 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL, 481 "Could not pop empty listing stack"); 482 return Gbl_ListingNode; 483 } 484 485 Gbl_ListingNode = Lnode->Next; 486 ACPI_FREE (Lnode); 487 488 /* New "Current" node is the new head */ 489 490 return (Gbl_ListingNode); 491 } 492 493 494 /******************************************************************************* 495 * 496 * FUNCTION: LsCheckException 497 * 498 * PARAMETERS: LineNumber - Current logical (cumulative) line # 499 * FileId - ID of output listing file 500 * 501 * RETURN: None 502 * 503 * DESCRIPTION: Check if there is an exception for this line, and if there is, 504 * put it in the listing immediately. Handles multiple errors 505 * per line. Gbl_NextError points to the next error in the 506 * sorted (by line #) list of compile errors/warnings. 507 * 508 ******************************************************************************/ 509 510 static void 511 LsCheckException ( 512 UINT32 LineNumber, 513 UINT32 FileId) 514 { 515 516 if ((!Gbl_NextError) || 517 (LineNumber < Gbl_NextError->LogicalLineNumber )) 518 { 519 return; 520 } 521 522 /* Handle multiple errors per line */ 523 524 if (FileId == ASL_FILE_LISTING_OUTPUT) 525 { 526 while (Gbl_NextError && 527 (LineNumber >= Gbl_NextError->LogicalLineNumber)) 528 { 529 AePrintException (FileId, Gbl_NextError, "\n[****iasl****]\n"); 530 531 Gbl_NextError = Gbl_NextError->Next; 532 } 533 534 FlPrintFile (FileId, "\n"); 535 } 536 } 537 538 539 /******************************************************************************* 540 * 541 * FUNCTION: LsFlushListingBuffer 542 * 543 * PARAMETERS: FileId - ID of the listing file 544 * 545 * RETURN: None 546 * 547 * DESCRIPTION: Flush out the current contents of the 16-byte hex AML code 548 * buffer. Usually called at the termination of a single line 549 * of source code or when the buffer is full. 550 * 551 ******************************************************************************/ 552 553 static void 554 LsFlushListingBuffer ( 555 UINT32 FileId) 556 { 557 UINT32 i; 558 559 560 if (Gbl_CurrentHexColumn == 0) 561 { 562 return; 563 } 564 565 /* Write the hex bytes */ 566 567 switch (FileId) 568 { 569 case ASL_FILE_LISTING_OUTPUT: 570 571 for (i = 0; i < Gbl_CurrentHexColumn; i++) 572 { 573 FlPrintFile (FileId, "%2.2X ", Gbl_AmlBuffer[i]); 574 } 575 576 for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 3); i++) 577 { 578 FlWriteFile (FileId, ".", 1); 579 } 580 581 /* Write the ASCII character associated with each of the bytes */ 582 583 LsDumpAscii (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer); 584 break; 585 586 587 case ASL_FILE_ASM_SOURCE_OUTPUT: 588 589 for (i = 0; i < Gbl_CurrentHexColumn; i++) 590 { 591 if (i > 0) 592 { 593 FlPrintFile (FileId, ","); 594 } 595 FlPrintFile (FileId, "0%2.2Xh", Gbl_AmlBuffer[i]); 596 } 597 598 for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++) 599 { 600 FlWriteFile (FileId, " ", 1); 601 } 602 603 FlPrintFile (FileId, " ;%8.8X", 604 Gbl_CurrentAmlOffset - HEX_LISTING_LINE_SIZE); 605 606 /* Write the ASCII character associated with each of the bytes */ 607 608 LsDumpAscii (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer); 609 break; 610 611 612 case ASL_FILE_C_SOURCE_OUTPUT: 613 614 for (i = 0; i < Gbl_CurrentHexColumn; i++) 615 { 616 FlPrintFile (FileId, "0x%2.2X,", Gbl_AmlBuffer[i]); 617 } 618 619 for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++) 620 { 621 FlWriteFile (FileId, " ", 1); 622 } 623 624 FlPrintFile (FileId, " /* %8.8X", 625 Gbl_CurrentAmlOffset - HEX_LISTING_LINE_SIZE); 626 627 /* Write the ASCII character associated with each of the bytes */ 628 629 LsDumpAsciiInComment (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer); 630 FlPrintFile (FileId, " */"); 631 break; 632 633 default: 634 /* No other types supported */ 635 return; 636 } 637 638 FlPrintFile (FileId, "\n"); 639 640 Gbl_CurrentHexColumn = 0; 641 Gbl_HexBytesWereWritten = TRUE; 642 } 643 644 645 /******************************************************************************* 646 * 647 * FUNCTION: LsWriteListingHexBytes 648 * 649 * PARAMETERS: Buffer - AML code buffer 650 * Length - Number of AML bytes to write 651 * FileId - ID of current listing file. 652 * 653 * RETURN: None 654 * 655 * DESCRIPTION: Write the contents of the AML buffer to the listing file via 656 * the listing buffer. The listing buffer is flushed every 16 657 * AML bytes. 658 * 659 ******************************************************************************/ 660 661 static void 662 LsWriteListingHexBytes ( 663 UINT8 *Buffer, 664 UINT32 Length, 665 UINT32 FileId) 666 { 667 UINT32 i; 668 669 670 /* Transfer all requested bytes */ 671 672 for (i = 0; i < Length; i++) 673 { 674 /* Print line header when buffer is empty */ 675 676 if (Gbl_CurrentHexColumn == 0) 677 { 678 if (Gbl_HasIncludeFiles) 679 { 680 FlPrintFile (FileId, "%*s", 10, " "); 681 } 682 683 switch (FileId) 684 { 685 case ASL_FILE_LISTING_OUTPUT: 686 687 FlPrintFile (FileId, "%8.8X....", Gbl_CurrentAmlOffset); 688 break; 689 690 case ASL_FILE_ASM_SOURCE_OUTPUT: 691 692 FlPrintFile (FileId, " db "); 693 break; 694 695 case ASL_FILE_C_SOURCE_OUTPUT: 696 697 FlPrintFile (FileId, " "); 698 break; 699 700 default: 701 /* No other types supported */ 702 return; 703 } 704 } 705 706 /* Transfer AML byte and update counts */ 707 708 Gbl_AmlBuffer[Gbl_CurrentHexColumn] = Buffer[i]; 709 710 Gbl_CurrentHexColumn++; 711 Gbl_CurrentAmlOffset++; 712 713 /* Flush buffer when it is full */ 714 715 if (Gbl_CurrentHexColumn >= HEX_LISTING_LINE_SIZE) 716 { 717 LsFlushListingBuffer (FileId); 718 } 719 } 720 } 721 722 723 /******************************************************************************* 724 * 725 * FUNCTION: LsWriteOneSourceLine 726 * 727 * PARAMETERS: FileID - ID of current listing file 728 * 729 * RETURN: FALSE on EOF (input source file), TRUE otherwise 730 * 731 * DESCRIPTION: Read one line from the input source file and echo it to the 732 * listing file, prefixed with the line number, and if the source 733 * file contains include files, prefixed with the current filename 734 * 735 ******************************************************************************/ 736 737 static UINT32 738 LsWriteOneSourceLine ( 739 UINT32 FileId) 740 { 741 UINT8 FileByte; 742 743 744 Gbl_SourceLine++; 745 Gbl_ListingNode->LineNumber++; 746 747 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 748 { 749 FlPrintFile (FileId, " *"); 750 } 751 if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT) 752 { 753 FlPrintFile (FileId, "; "); 754 } 755 756 if (Gbl_HasIncludeFiles) 757 { 758 /* 759 * This file contains "include" statements, print the current 760 * filename and line number within the current file 761 */ 762 FlPrintFile (FileId, "%12s %5d....", 763 Gbl_ListingNode->Filename, Gbl_ListingNode->LineNumber); 764 } 765 else 766 { 767 /* No include files, just print the line number */ 768 769 FlPrintFile (FileId, "%8d....", Gbl_SourceLine); 770 } 771 772 /* Read one line (up to a newline or EOF) */ 773 774 while (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) == AE_OK) 775 { 776 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 777 { 778 if (FileByte == '/') 779 { 780 FileByte = '*'; 781 } 782 } 783 784 FlWriteFile (FileId, &FileByte, 1); 785 if (FileByte == '\n') 786 { 787 /* 788 * Check if an error occurred on this source line during the compile. 789 * If so, we print the error message after the source line. 790 */ 791 LsCheckException (Gbl_SourceLine, FileId); 792 return (1); 793 } 794 } 795 796 /* EOF on the input file was reached */ 797 798 return (0); 799 } 800 801 802 /******************************************************************************* 803 * 804 * FUNCTION: LsFinishSourceListing 805 * 806 * PARAMETERS: FileId - ID of current listing file. 807 * 808 * RETURN: None 809 * 810 * DESCRIPTION: Cleanup routine for the listing file. Flush the hex AML 811 * listing buffer, and flush out any remaining lines in the 812 * source input file. 813 * 814 ******************************************************************************/ 815 816 static void 817 LsFinishSourceListing ( 818 UINT32 FileId) 819 { 820 821 if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) || 822 (FileId == ASL_FILE_C_INCLUDE_OUTPUT)) 823 { 824 return; 825 } 826 827 LsFlushListingBuffer (FileId); 828 Gbl_CurrentAmlOffset = 0; 829 830 /* Flush any remaining text in the source file */ 831 832 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 833 { 834 FlPrintFile (FileId, " /*\n"); 835 } 836 837 while (LsWriteOneSourceLine (FileId)) 838 { ; } 839 840 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 841 { 842 FlPrintFile (FileId, "\n */\n };\n"); 843 } 844 845 FlPrintFile (FileId, "\n"); 846 847 if (FileId == ASL_FILE_LISTING_OUTPUT) 848 { 849 /* Print a summary of the compile exceptions */ 850 851 FlPrintFile (FileId, "\n\nSummary of errors and warnings\n\n"); 852 AePrintErrorLog (FileId); 853 FlPrintFile (FileId, "\n\n"); 854 UtDisplaySummary (FileId); 855 FlPrintFile (FileId, "\n\n"); 856 } 857 } 858 859 860 /******************************************************************************* 861 * 862 * FUNCTION: LsWriteSourceLines 863 * 864 * PARAMETERS: ToLineNumber - 865 * ToLogicalLineNumber - Write up to this source line number 866 * FileId - ID of current listing file 867 * 868 * RETURN: None 869 * 870 * DESCRIPTION: Read then write source lines to the listing file until we have 871 * reached the specified logical (cumulative) line number. This 872 * automatically echos out comment blocks and other non-AML 873 * generating text until we get to the actual AML-generating line 874 * of ASL code specified by the logical line number. 875 * 876 ******************************************************************************/ 877 878 static void 879 LsWriteSourceLines ( 880 UINT32 ToLineNumber, 881 UINT32 ToLogicalLineNumber, 882 UINT32 FileId) 883 { 884 885 if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) || 886 (FileId == ASL_FILE_C_INCLUDE_OUTPUT)) 887 { 888 return; 889 } 890 891 Gbl_CurrentLine = ToLogicalLineNumber; 892 893 /* Flush any hex bytes remaining from the last opcode */ 894 895 LsFlushListingBuffer (FileId); 896 897 /* Read lines and write them as long as we are not caught up */ 898 899 if (Gbl_SourceLine < Gbl_CurrentLine) 900 { 901 /* 902 * If we just completed writing some AML hex bytes, output a linefeed 903 * to add some whitespace for readability. 904 */ 905 if (Gbl_HexBytesWereWritten) 906 { 907 FlPrintFile (FileId, "\n"); 908 Gbl_HexBytesWereWritten = FALSE; 909 } 910 911 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 912 { 913 FlPrintFile (FileId, " /*\n"); 914 } 915 916 /* Write one line at a time until we have reached the target line # */ 917 918 while ((Gbl_SourceLine < Gbl_CurrentLine) && 919 LsWriteOneSourceLine (FileId)) 920 { ; } 921 922 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 923 { 924 FlPrintFile (FileId, " */"); 925 } 926 FlPrintFile (FileId, "\n"); 927 } 928 } 929 930 931 /******************************************************************************* 932 * 933 * FUNCTION: LsWriteNodeToListing 934 * 935 * PARAMETERS: Op - Parse node to write to the listing file. 936 * FileId - ID of current listing file 937 * 938 * RETURN: None. 939 * 940 * DESCRIPTION: Write "a node" to the listing file. This means to 941 * 1) Write out all of the source text associated with the node 942 * 2) Write out all of the AML bytes associated with the node 943 * 3) Write any compiler exceptions associated with the node 944 * 945 ******************************************************************************/ 946 947 static void 948 LsWriteNodeToListing ( 949 ACPI_PARSE_OBJECT *Op, 950 UINT32 FileId) 951 { 952 const ACPI_OPCODE_INFO *OpInfo; 953 UINT32 OpClass; 954 char *Pathname; 955 UINT32 Length; 956 UINT32 i; 957 958 959 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 960 OpClass = OpInfo->Class; 961 962 /* TBD: clean this up with a single flag that says: 963 * I start a named output block 964 */ 965 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 966 { 967 switch (Op->Asl.ParseOpcode) 968 { 969 case PARSEOP_DEFINITIONBLOCK: 970 case PARSEOP_METHODCALL: 971 case PARSEOP_INCLUDE: 972 case PARSEOP_INCLUDE_END: 973 case PARSEOP_DEFAULT_ARG: 974 975 break; 976 977 default: 978 switch (OpClass) 979 { 980 case AML_CLASS_NAMED_OBJECT: 981 switch (Op->Asl.AmlOpcode) 982 { 983 case AML_SCOPE_OP: 984 case AML_ALIAS_OP: 985 break; 986 987 default: 988 if (Op->Asl.ExternalName) 989 { 990 LsFlushListingBuffer (FileId); 991 FlPrintFile (FileId, " };\n"); 992 } 993 break; 994 } 995 break; 996 997 default: 998 /* Don't care about other objects */ 999 break; 1000 } 1001 break; 1002 } 1003 } 1004 1005 /* These cases do not have a corresponding AML opcode */ 1006 1007 switch (Op->Asl.ParseOpcode) 1008 { 1009 case PARSEOP_DEFINITIONBLOCK: 1010 1011 LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, FileId); 1012 1013 /* Use the table Signature and TableId to build a unique name */ 1014 1015 if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT) 1016 { 1017 FlPrintFile (FileId, 1018 "%s_%s_Header \\\n", 1019 Gbl_TableSignature, Gbl_TableId); 1020 } 1021 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 1022 { 1023 FlPrintFile (FileId, 1024 " unsigned char %s_%s_Header [] =\n {\n", 1025 Gbl_TableSignature, Gbl_TableId); 1026 } 1027 if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) 1028 { 1029 FlPrintFile (FileId, 1030 "extrn %s_%s_Header : byte\n", 1031 Gbl_TableSignature, Gbl_TableId); 1032 } 1033 if (FileId == ASL_FILE_C_INCLUDE_OUTPUT) 1034 { 1035 FlPrintFile (FileId, 1036 "extern unsigned char %s_%s_Header [];\n", 1037 Gbl_TableSignature, Gbl_TableId); 1038 } 1039 return; 1040 1041 1042 case PARSEOP_METHODCALL: 1043 1044 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 1045 FileId); 1046 return; 1047 1048 1049 case PARSEOP_INCLUDE: 1050 1051 /* Flush everything up to and including the include source line */ 1052 1053 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 1054 FileId); 1055 1056 /* Create a new listing node and push it */ 1057 1058 LsPushNode (Op->Asl.Child->Asl.Value.String); 1059 return; 1060 1061 1062 case PARSEOP_INCLUDE_END: 1063 1064 /* Flush out the rest of the include file */ 1065 1066 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 1067 FileId); 1068 1069 /* Pop off this listing node and go back to the parent file */ 1070 1071 (void) LsPopNode (); 1072 return; 1073 1074 1075 case PARSEOP_DEFAULT_ARG: 1076 1077 if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC) 1078 { 1079 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.EndLogicalLine, 1080 FileId); 1081 } 1082 return; 1083 1084 1085 default: 1086 /* All other opcodes have an AML opcode */ 1087 break; 1088 } 1089 1090 /* 1091 * Otherwise, we look at the AML opcode because we can 1092 * switch on the opcode type, getting an entire class 1093 * at once 1094 */ 1095 switch (OpClass) 1096 { 1097 case AML_CLASS_ARGUMENT: /* argument type only */ 1098 case AML_CLASS_INTERNAL: 1099 1100 break; 1101 1102 1103 case AML_CLASS_NAMED_OBJECT: 1104 1105 switch (Op->Asl.AmlOpcode) 1106 { 1107 case AML_FIELD_OP: 1108 case AML_INDEX_FIELD_OP: 1109 case AML_BANK_FIELD_OP: 1110 1111 /* 1112 * For fields, we want to dump all the AML after the 1113 * entire definition 1114 */ 1115 LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, 1116 FileId); 1117 break; 1118 1119 case AML_NAME_OP: 1120 1121 if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC) 1122 { 1123 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 1124 FileId); 1125 } 1126 else 1127 { 1128 /* 1129 * For fields, we want to dump all the AML after the 1130 * entire definition 1131 */ 1132 LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, 1133 FileId); 1134 } 1135 break; 1136 1137 default: 1138 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 1139 FileId); 1140 break; 1141 } 1142 1143 switch (Op->Asl.AmlOpcode) 1144 { 1145 case AML_SCOPE_OP: 1146 case AML_ALIAS_OP: 1147 1148 /* These opcodes do not declare a new object, ignore them */ 1149 1150 break; 1151 1152 default: 1153 1154 /* All other named object opcodes come here */ 1155 1156 switch (FileId) 1157 { 1158 case ASL_FILE_ASM_SOURCE_OUTPUT: 1159 case ASL_FILE_C_SOURCE_OUTPUT: 1160 case ASL_FILE_ASM_INCLUDE_OUTPUT: 1161 case ASL_FILE_C_INCLUDE_OUTPUT: 1162 1163 /* 1164 * For named objects, we will create a valid symbol so that the 1165 * AML code can be referenced from C or ASM 1166 */ 1167 if (Op->Asl.ExternalName) 1168 { 1169 /* Get the full pathname associated with this node */ 1170 1171 Pathname = AcpiNsGetExternalPathname (Op->Asl.Node); 1172 Length = strlen (Pathname); 1173 if (Length >= 4) 1174 { 1175 /* Convert all dots in the path to underscores */ 1176 1177 for (i = 0; i < Length; i++) 1178 { 1179 if (Pathname[i] == '.') 1180 { 1181 Pathname[i] = '_'; 1182 } 1183 } 1184 1185 /* Create the appropriate symbol in the output file */ 1186 1187 if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT) 1188 { 1189 FlPrintFile (FileId, 1190 "%s_%s_%s \\\n", 1191 Gbl_TableSignature, Gbl_TableId, &Pathname[1]); 1192 } 1193 if (FileId == ASL_FILE_C_SOURCE_OUTPUT) 1194 { 1195 FlPrintFile (FileId, 1196 " unsigned char %s_%s_%s [] =\n {\n", 1197 Gbl_TableSignature, Gbl_TableId, &Pathname[1]); 1198 } 1199 if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) 1200 { 1201 FlPrintFile (FileId, 1202 "extrn %s_%s_%s : byte\n", 1203 Gbl_TableSignature, Gbl_TableId, &Pathname[1]); 1204 } 1205 if (FileId == ASL_FILE_C_INCLUDE_OUTPUT) 1206 { 1207 FlPrintFile (FileId, 1208 "extern unsigned char %s_%s_%s [];\n", 1209 Gbl_TableSignature, Gbl_TableId, &Pathname[1]); 1210 } 1211 } 1212 ACPI_FREE (Pathname); 1213 } 1214 break; 1215 1216 default: 1217 /* Nothing to do for listing file */ 1218 break; 1219 } 1220 } 1221 break; 1222 1223 case AML_CLASS_EXECUTE: 1224 case AML_CLASS_CREATE: 1225 default: 1226 1227 if ((Op->Asl.ParseOpcode == PARSEOP_BUFFER) && 1228 (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)) 1229 { 1230 return; 1231 } 1232 1233 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber, 1234 FileId); 1235 break; 1236 1237 case AML_CLASS_UNKNOWN: 1238 break; 1239 } 1240 } 1241 1242 1243 /******************************************************************************* 1244 * 1245 * FUNCTION: LsDoHexOutput 1246 * 1247 * PARAMETERS: None 1248 * 1249 * RETURN: None. 1250 * 1251 * DESCRIPTION: Create the hex output file. 1252 * 1253 ******************************************************************************/ 1254 1255 void 1256 LsDoHexOutput ( 1257 void) 1258 { 1259 1260 switch (Gbl_HexOutputFlag) 1261 { 1262 case HEX_OUTPUT_C: 1263 1264 LsDoHexOutputC (); 1265 break; 1266 1267 case HEX_OUTPUT_ASM: 1268 1269 LsDoHexOutputAsm (); 1270 break; 1271 1272 case HEX_OUTPUT_ASL: 1273 1274 LsDoHexOutputAsl (); 1275 break; 1276 1277 default: 1278 /* No other output types supported */ 1279 break; 1280 } 1281 } 1282 1283 1284 /******************************************************************************* 1285 * 1286 * FUNCTION: LsDoHexOutputC 1287 * 1288 * PARAMETERS: None 1289 * 1290 * RETURN: None. 1291 * 1292 * DESCRIPTION: Create the hex output file. This is the same data as the AML 1293 * output file, but formatted into hex/ascii bytes suitable for 1294 * inclusion into a C source file. 1295 * 1296 ******************************************************************************/ 1297 1298 static void 1299 LsDoHexOutputC ( 1300 void) 1301 { 1302 UINT8 FileData[HEX_TABLE_LINE_SIZE]; 1303 UINT32 LineLength; 1304 UINT32 Offset = 0; 1305 UINT32 AmlFileSize; 1306 UINT32 i; 1307 1308 1309 /* Get AML size, seek back to start */ 1310 1311 AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT); 1312 1313 FlPrintFile (ASL_FILE_HEX_OUTPUT, " * C source code output\n"); 1314 FlPrintFile (ASL_FILE_HEX_OUTPUT, " * AML code block contains 0x%X bytes\n *\n */\n", 1315 AmlFileSize); 1316 FlPrintFile (ASL_FILE_HEX_OUTPUT, "unsigned char AmlCode[] =\n{\n"); 1317 1318 while (Offset < AmlFileSize) 1319 { 1320 /* Read enough bytes needed for one output line */ 1321 1322 LineLength = fread (FileData, 1, HEX_TABLE_LINE_SIZE, 1323 Gbl_Files[ASL_FILE_AML_OUTPUT].Handle); 1324 if (!LineLength) 1325 { 1326 break; 1327 } 1328 1329 FlPrintFile (ASL_FILE_HEX_OUTPUT, " "); 1330 1331 for (i = 0; i < LineLength; i++) 1332 { 1333 /* 1334 * Print each hex byte. 1335 * Add a comma until the very last byte of the AML file 1336 * (Some C compilers complain about a trailing comma) 1337 */ 1338 FlPrintFile (ASL_FILE_HEX_OUTPUT, "0x%2.2X", FileData[i]); 1339 if ((Offset + i + 1) < AmlFileSize) 1340 { 1341 FlPrintFile (ASL_FILE_HEX_OUTPUT, ","); 1342 } 1343 else 1344 { 1345 FlPrintFile (ASL_FILE_HEX_OUTPUT, " "); 1346 } 1347 } 1348 1349 /* Add fill spaces if needed for last line */ 1350 1351 if (LineLength < HEX_TABLE_LINE_SIZE) 1352 { 1353 FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s", 1354 5 * (HEX_TABLE_LINE_SIZE - LineLength), " "); 1355 } 1356 1357 /* Emit the offset and ascii dump for the entire line */ 1358 1359 FlPrintFile (ASL_FILE_HEX_OUTPUT, " /* %8.8X", Offset); 1360 LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData); 1361 FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s*/\n", 1362 HEX_TABLE_LINE_SIZE - LineLength + 1, " "); 1363 1364 Offset += LineLength; 1365 } 1366 1367 FlPrintFile (ASL_FILE_HEX_OUTPUT, "};\n"); 1368 FlCloseFile (ASL_FILE_HEX_OUTPUT); 1369 } 1370 1371 1372 /******************************************************************************* 1373 * 1374 * FUNCTION: LsDoHexOutputAsl 1375 * 1376 * PARAMETERS: None 1377 * 1378 * RETURN: None. 1379 * 1380 * DESCRIPTION: Create the hex output file. This is the same data as the AML 1381 * output file, but formatted into hex/ascii bytes suitable for 1382 * inclusion into a C source file. 1383 * 1384 ******************************************************************************/ 1385 1386 static void 1387 LsDoHexOutputAsl ( 1388 void) 1389 { 1390 UINT8 FileData[HEX_TABLE_LINE_SIZE]; 1391 UINT32 LineLength; 1392 UINT32 Offset = 0; 1393 UINT32 AmlFileSize; 1394 UINT32 i; 1395 1396 1397 /* Get AML size, seek back to start */ 1398 1399 AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT); 1400 1401 FlPrintFile (ASL_FILE_HEX_OUTPUT, " * ASL source code output\n"); 1402 FlPrintFile (ASL_FILE_HEX_OUTPUT, " * AML code block contains 0x%X bytes\n *\n */\n", 1403 AmlFileSize); 1404 FlPrintFile (ASL_FILE_HEX_OUTPUT, " Name (BUF1, Buffer()\n {\n"); 1405 1406 while (Offset < AmlFileSize) 1407 { 1408 /* Read enough bytes needed for one output line */ 1409 1410 LineLength = fread (FileData, 1, HEX_TABLE_LINE_SIZE, 1411 Gbl_Files[ASL_FILE_AML_OUTPUT].Handle); 1412 if (!LineLength) 1413 { 1414 break; 1415 } 1416 1417 FlPrintFile (ASL_FILE_HEX_OUTPUT, " "); 1418 1419 for (i = 0; i < LineLength; i++) 1420 { 1421 /* 1422 * Print each hex byte. 1423 * Add a comma until the very last byte of the AML file 1424 * (Some C compilers complain about a trailing comma) 1425 */ 1426 FlPrintFile (ASL_FILE_HEX_OUTPUT, "0x%2.2X", FileData[i]); 1427 if ((Offset + i + 1) < AmlFileSize) 1428 { 1429 FlPrintFile (ASL_FILE_HEX_OUTPUT, ","); 1430 } 1431 else 1432 { 1433 FlPrintFile (ASL_FILE_HEX_OUTPUT, " "); 1434 } 1435 } 1436 1437 /* Add fill spaces if needed for last line */ 1438 1439 if (LineLength < HEX_TABLE_LINE_SIZE) 1440 { 1441 FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s", 1442 5 * (HEX_TABLE_LINE_SIZE - LineLength), " "); 1443 } 1444 1445 /* Emit the offset and ascii dump for the entire line */ 1446 1447 FlPrintFile (ASL_FILE_HEX_OUTPUT, " /* %8.8X", Offset); 1448 LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData); 1449 FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s*/\n", 1450 HEX_TABLE_LINE_SIZE - LineLength + 1, " "); 1451 1452 Offset += LineLength; 1453 } 1454 1455 FlPrintFile (ASL_FILE_HEX_OUTPUT, " })\n"); 1456 FlCloseFile (ASL_FILE_HEX_OUTPUT); 1457 } 1458 1459 1460 /******************************************************************************* 1461 * 1462 * FUNCTION: LsDoHexOutputAsm 1463 * 1464 * PARAMETERS: None 1465 * 1466 * RETURN: None. 1467 * 1468 * DESCRIPTION: Create the hex output file. This is the same data as the AML 1469 * output file, but formatted into hex/ascii bytes suitable for 1470 * inclusion into a ASM source file. 1471 * 1472 ******************************************************************************/ 1473 1474 static void 1475 LsDoHexOutputAsm ( 1476 void) 1477 { 1478 UINT8 FileData[HEX_TABLE_LINE_SIZE]; 1479 UINT32 LineLength; 1480 UINT32 Offset = 0; 1481 UINT32 AmlFileSize; 1482 UINT32 i; 1483 1484 1485 /* Get AML size, seek back to start */ 1486 1487 AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT); 1488 1489 FlPrintFile (ASL_FILE_HEX_OUTPUT, "; Assembly code source output\n"); 1490 FlPrintFile (ASL_FILE_HEX_OUTPUT, "; AML code block contains 0x%X bytes\n;\n", 1491 AmlFileSize); 1492 1493 while (Offset < AmlFileSize) 1494 { 1495 /* Read enough bytes needed for one output line */ 1496 1497 LineLength = fread (FileData, 1, HEX_TABLE_LINE_SIZE, 1498 Gbl_Files[ASL_FILE_AML_OUTPUT].Handle); 1499 if (!LineLength) 1500 { 1501 break; 1502 } 1503 1504 FlPrintFile (ASL_FILE_HEX_OUTPUT, " db "); 1505 1506 for (i = 0; i < LineLength; i++) 1507 { 1508 /* 1509 * Print each hex byte. 1510 * Add a comma until the last byte of the line 1511 */ 1512 FlPrintFile (ASL_FILE_HEX_OUTPUT, "0%2.2Xh", FileData[i]); 1513 if ((i + 1) < LineLength) 1514 { 1515 FlPrintFile (ASL_FILE_HEX_OUTPUT, ","); 1516 } 1517 } 1518 1519 FlPrintFile (ASL_FILE_HEX_OUTPUT, " "); 1520 1521 /* Add fill spaces if needed for last line */ 1522 1523 if (LineLength < HEX_TABLE_LINE_SIZE) 1524 { 1525 FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s", 1526 5 * (HEX_TABLE_LINE_SIZE - LineLength), " "); 1527 } 1528 1529 /* Emit the offset and ascii dump for the entire line */ 1530 1531 FlPrintFile (ASL_FILE_HEX_OUTPUT, " ; %8.8X", Offset); 1532 LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData); 1533 FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n"); 1534 1535 Offset += LineLength; 1536 } 1537 1538 FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n"); 1539 FlCloseFile (ASL_FILE_HEX_OUTPUT); 1540 } 1541 1542 1543