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