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