1 /****************************************************************************** 2 * 3 * Module Name: dtio.c - File I/O support for data table compiler 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2014, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #define __DTIO_C__ 45 46 #include "aslcompiler.h" 47 #include "dtcompiler.h" 48 49 #define _COMPONENT DT_COMPILER 50 ACPI_MODULE_NAME ("dtio") 51 52 53 /* Local prototypes */ 54 55 static char * 56 DtTrim ( 57 char *String); 58 59 static void 60 DtLinkField ( 61 DT_FIELD *Field); 62 63 static ACPI_STATUS 64 DtParseLine ( 65 char *LineBuffer, 66 UINT32 Line, 67 UINT32 Offset); 68 69 static void 70 DtWriteBinary ( 71 DT_SUBTABLE *Subtable, 72 void *Context, 73 void *ReturnValue); 74 75 static void 76 DtDumpBuffer ( 77 UINT32 FileId, 78 UINT8 *Buffer, 79 UINT32 Offset, 80 UINT32 Length); 81 82 static void 83 DtDumpSubtableInfo ( 84 DT_SUBTABLE *Subtable, 85 void *Context, 86 void *ReturnValue); 87 88 static void 89 DtDumpSubtableTree ( 90 DT_SUBTABLE *Subtable, 91 void *Context, 92 void *ReturnValue); 93 94 95 /* States for DtGetNextLine */ 96 97 #define DT_NORMAL_TEXT 0 98 #define DT_START_QUOTED_STRING 1 99 #define DT_START_COMMENT 2 100 #define DT_SLASH_ASTERISK_COMMENT 3 101 #define DT_SLASH_SLASH_COMMENT 4 102 #define DT_END_COMMENT 5 103 #define DT_MERGE_LINES 6 104 #define DT_ESCAPE_SEQUENCE 7 105 106 static UINT32 Gbl_NextLineOffset; 107 108 109 /****************************************************************************** 110 * 111 * FUNCTION: DtTrim 112 * 113 * PARAMETERS: String - Current source code line to trim 114 * 115 * RETURN: Trimmed line. Must be freed by caller. 116 * 117 * DESCRIPTION: Trim left and right spaces 118 * 119 *****************************************************************************/ 120 121 static char * 122 DtTrim ( 123 char *String) 124 { 125 char *Start; 126 char *End; 127 char *ReturnString; 128 ACPI_SIZE Length; 129 130 131 /* Skip lines that start with a space */ 132 133 if (!ACPI_STRCMP (String, " ")) 134 { 135 ReturnString = UtLocalCalloc (1); 136 return (ReturnString); 137 } 138 139 /* Setup pointers to start and end of input string */ 140 141 Start = String; 142 End = String + ACPI_STRLEN (String) - 1; 143 144 /* Find first non-whitespace character */ 145 146 while ((Start <= End) && ((*Start == ' ') || (*Start == '\t'))) 147 { 148 Start++; 149 } 150 151 /* Find last non-space character */ 152 153 while (End >= Start) 154 { 155 if (*End == '\r' || *End == '\n') 156 { 157 End--; 158 continue; 159 } 160 161 if (*End != ' ') 162 { 163 break; 164 } 165 166 End--; 167 } 168 169 /* Remove any quotes around the string */ 170 171 if (*Start == '\"') 172 { 173 Start++; 174 } 175 if (*End == '\"') 176 { 177 End--; 178 } 179 180 /* Create the trimmed return string */ 181 182 Length = ACPI_PTR_DIFF (End, Start) + 1; 183 ReturnString = UtLocalCalloc (Length + 1); 184 if (ACPI_STRLEN (Start)) 185 { 186 ACPI_STRNCPY (ReturnString, Start, Length); 187 } 188 189 ReturnString[Length] = 0; 190 return (ReturnString); 191 } 192 193 194 /****************************************************************************** 195 * 196 * FUNCTION: DtLinkField 197 * 198 * PARAMETERS: Field - New field object to link 199 * 200 * RETURN: None 201 * 202 * DESCRIPTION: Link one field name and value to the list 203 * 204 *****************************************************************************/ 205 206 static void 207 DtLinkField ( 208 DT_FIELD *Field) 209 { 210 DT_FIELD *Prev; 211 DT_FIELD *Next; 212 213 214 Prev = Next = Gbl_FieldList; 215 216 while (Next) 217 { 218 Prev = Next; 219 Next = Next->Next; 220 } 221 222 if (Prev) 223 { 224 Prev->Next = Field; 225 } 226 else 227 { 228 Gbl_FieldList = Field; 229 } 230 } 231 232 233 /****************************************************************************** 234 * 235 * FUNCTION: DtParseLine 236 * 237 * PARAMETERS: LineBuffer - Current source code line 238 * Line - Current line number in the source 239 * Offset - Current byte offset of the line 240 * 241 * RETURN: Status 242 * 243 * DESCRIPTION: Parse one source line 244 * 245 *****************************************************************************/ 246 247 static ACPI_STATUS 248 DtParseLine ( 249 char *LineBuffer, 250 UINT32 Line, 251 UINT32 Offset) 252 { 253 char *Start; 254 char *End; 255 char *TmpName; 256 char *TmpValue; 257 char *Name; 258 char *Value; 259 char *Colon; 260 UINT32 Length; 261 DT_FIELD *Field; 262 UINT32 Column; 263 UINT32 NameColumn; 264 BOOLEAN IsNullString = FALSE; 265 266 267 if (!LineBuffer) 268 { 269 return (AE_OK); 270 } 271 272 /* All lines after "Raw Table Data" are ingored */ 273 274 if (strstr (LineBuffer, ACPI_RAW_TABLE_DATA_HEADER)) 275 { 276 return (AE_NOT_FOUND); 277 } 278 279 Colon = strchr (LineBuffer, ':'); 280 if (!Colon) 281 { 282 return (AE_OK); 283 } 284 285 Start = LineBuffer; 286 End = Colon; 287 288 while (Start < Colon) 289 { 290 if (*Start == '[') 291 { 292 /* Found left bracket, go to the right bracket */ 293 294 while (Start < Colon && *Start != ']') 295 { 296 Start++; 297 } 298 } 299 else if (*Start != ' ') 300 { 301 break; 302 } 303 304 Start++; 305 } 306 307 /* 308 * There are two column values. One for the field name, 309 * and one for the field value. 310 */ 311 Column = ACPI_PTR_DIFF (Colon, LineBuffer) + 3; 312 NameColumn = ACPI_PTR_DIFF (Start, LineBuffer) + 1; 313 314 Length = ACPI_PTR_DIFF (End, Start); 315 316 TmpName = UtLocalCalloc (Length + 1); 317 ACPI_STRNCPY (TmpName, Start, Length); 318 Name = DtTrim (TmpName); 319 ACPI_FREE (TmpName); 320 321 Start = End = (Colon + 1); 322 while (*End) 323 { 324 /* Found left quotation, go to the right quotation and break */ 325 326 if (*End == '"') 327 { 328 End++; 329 330 /* Check for an explicit null string */ 331 332 if (*End == '"') 333 { 334 IsNullString = TRUE; 335 } 336 while (*End && (*End != '"')) 337 { 338 End++; 339 } 340 341 End++; 342 break; 343 } 344 345 /* 346 * Special "comment" fields at line end, ignore them. 347 * Note: normal slash-slash and slash-asterisk comments are 348 * stripped already by the DtGetNextLine parser. 349 * 350 * TBD: Perhaps DtGetNextLine should parse the following type 351 * of comments also. 352 */ 353 if (*End == '[') 354 { 355 End--; 356 break; 357 } 358 End++; 359 } 360 361 Length = ACPI_PTR_DIFF (End, Start); 362 TmpValue = UtLocalCalloc (Length + 1); 363 364 ACPI_STRNCPY (TmpValue, Start, Length); 365 Value = DtTrim (TmpValue); 366 ACPI_FREE (TmpValue); 367 368 /* Create a new field object only if we have a valid value field */ 369 370 if ((Value && *Value) || IsNullString) 371 { 372 Field = UtLocalCalloc (sizeof (DT_FIELD)); 373 Field->Name = Name; 374 Field->Value = Value; 375 Field->Line = Line; 376 Field->ByteOffset = Offset; 377 Field->NameColumn = NameColumn; 378 Field->Column = Column; 379 380 DtLinkField (Field); 381 } 382 else /* Ignore this field, it has no valid data */ 383 { 384 ACPI_FREE (Name); 385 ACPI_FREE (Value); 386 } 387 388 return (AE_OK); 389 } 390 391 392 /****************************************************************************** 393 * 394 * FUNCTION: DtGetNextLine 395 * 396 * PARAMETERS: Handle - Open file handle for the source file 397 * 398 * RETURN: Filled line buffer and offset of start-of-line (ASL_EOF on EOF) 399 * 400 * DESCRIPTION: Get the next valid source line. Removes all comments. 401 * Ignores empty lines. 402 * 403 * Handles both slash-asterisk and slash-slash comments. 404 * Also, quoted strings, but no escapes within. 405 * 406 * Line is returned in Gbl_CurrentLineBuffer. 407 * Line number in original file is returned in Gbl_CurrentLineNumber. 408 * 409 *****************************************************************************/ 410 411 UINT32 412 DtGetNextLine ( 413 FILE *Handle) 414 { 415 BOOLEAN LineNotAllBlanks = FALSE; 416 UINT32 State = DT_NORMAL_TEXT; 417 UINT32 CurrentLineOffset; 418 UINT32 i; 419 int c; 420 421 422 for (i = 0; ;) 423 { 424 /* 425 * If line is too long, expand the line buffers. Also increases 426 * Gbl_LineBufferSize. 427 */ 428 if (i >= Gbl_LineBufferSize) 429 { 430 UtExpandLineBuffers (); 431 } 432 433 c = getc (Handle); 434 if (c == EOF) 435 { 436 switch (State) 437 { 438 case DT_START_QUOTED_STRING: 439 case DT_SLASH_ASTERISK_COMMENT: 440 441 AcpiOsPrintf ("**** EOF within comment/string %u\n", State); 442 break; 443 444 default: 445 446 break; 447 } 448 449 /* Standalone EOF is OK */ 450 451 if (i == 0) 452 { 453 return (ASL_EOF); 454 } 455 456 /* 457 * Received an EOF in the middle of a line. Terminate the 458 * line with a newline. The next call to this function will 459 * return a standalone EOF. Thus, the upper parsing software 460 * never has to deal with an EOF within a valid line (or 461 * the last line does not get tossed on the floor.) 462 */ 463 c = '\n'; 464 State = DT_NORMAL_TEXT; 465 } 466 467 switch (State) 468 { 469 case DT_NORMAL_TEXT: 470 471 /* Normal text, insert char into line buffer */ 472 473 Gbl_CurrentLineBuffer[i] = (char) c; 474 switch (c) 475 { 476 case '/': 477 478 State = DT_START_COMMENT; 479 break; 480 481 case '"': 482 483 State = DT_START_QUOTED_STRING; 484 LineNotAllBlanks = TRUE; 485 i++; 486 break; 487 488 case '\\': 489 /* 490 * The continuation char MUST be last char on this line. 491 * Otherwise, it will be assumed to be a valid ASL char. 492 */ 493 State = DT_MERGE_LINES; 494 break; 495 496 case '\n': 497 498 CurrentLineOffset = Gbl_NextLineOffset; 499 Gbl_NextLineOffset = (UINT32) ftell (Handle); 500 Gbl_CurrentLineNumber++; 501 502 /* 503 * Exit if line is complete. Ignore empty lines (only \n) 504 * or lines that contain nothing but blanks. 505 */ 506 if ((i != 0) && LineNotAllBlanks) 507 { 508 if ((i + 1) >= Gbl_LineBufferSize) 509 { 510 UtExpandLineBuffers (); 511 } 512 513 Gbl_CurrentLineBuffer[i+1] = 0; /* Terminate string */ 514 return (CurrentLineOffset); 515 } 516 517 /* Toss this line and start a new one */ 518 519 i = 0; 520 LineNotAllBlanks = FALSE; 521 break; 522 523 default: 524 525 if (c != ' ') 526 { 527 LineNotAllBlanks = TRUE; 528 } 529 530 i++; 531 break; 532 } 533 break; 534 535 case DT_START_QUOTED_STRING: 536 537 /* Insert raw chars until end of quoted string */ 538 539 Gbl_CurrentLineBuffer[i] = (char) c; 540 i++; 541 542 switch (c) 543 { 544 case '"': 545 546 State = DT_NORMAL_TEXT; 547 break; 548 549 case '\\': 550 551 State = DT_ESCAPE_SEQUENCE; 552 break; 553 554 case '\n': 555 556 AcpiOsPrintf ("ERROR at line %u: Unterminated quoted string\n", 557 Gbl_CurrentLineNumber++); 558 State = DT_NORMAL_TEXT; 559 break; 560 561 default: /* Get next character */ 562 563 break; 564 } 565 break; 566 567 case DT_ESCAPE_SEQUENCE: 568 569 /* Just copy the escaped character. TBD: sufficient for table compiler? */ 570 571 Gbl_CurrentLineBuffer[i] = (char) c; 572 i++; 573 State = DT_START_QUOTED_STRING; 574 break; 575 576 case DT_START_COMMENT: 577 578 /* Open comment if this character is an asterisk or slash */ 579 580 switch (c) 581 { 582 case '*': 583 584 State = DT_SLASH_ASTERISK_COMMENT; 585 break; 586 587 case '/': 588 589 State = DT_SLASH_SLASH_COMMENT; 590 break; 591 592 default: /* Not a comment */ 593 594 i++; /* Save the preceding slash */ 595 if (i >= Gbl_LineBufferSize) 596 { 597 UtExpandLineBuffers (); 598 } 599 600 Gbl_CurrentLineBuffer[i] = (char) c; 601 i++; 602 State = DT_NORMAL_TEXT; 603 break; 604 } 605 break; 606 607 case DT_SLASH_ASTERISK_COMMENT: 608 609 /* Ignore chars until an asterisk-slash is found */ 610 611 switch (c) 612 { 613 case '\n': 614 615 Gbl_NextLineOffset = (UINT32) ftell (Handle); 616 Gbl_CurrentLineNumber++; 617 break; 618 619 case '*': 620 621 State = DT_END_COMMENT; 622 break; 623 624 default: 625 626 break; 627 } 628 break; 629 630 case DT_SLASH_SLASH_COMMENT: 631 632 /* Ignore chars until end-of-line */ 633 634 if (c == '\n') 635 { 636 /* We will exit via the NORMAL_TEXT path */ 637 638 ungetc (c, Handle); 639 State = DT_NORMAL_TEXT; 640 } 641 break; 642 643 case DT_END_COMMENT: 644 645 /* End comment if this char is a slash */ 646 647 switch (c) 648 { 649 case '/': 650 651 State = DT_NORMAL_TEXT; 652 break; 653 654 case '\n': 655 656 CurrentLineOffset = Gbl_NextLineOffset; 657 Gbl_NextLineOffset = (UINT32) ftell (Handle); 658 Gbl_CurrentLineNumber++; 659 break; 660 661 case '*': 662 663 /* Consume all adjacent asterisks */ 664 break; 665 666 default: 667 668 State = DT_SLASH_ASTERISK_COMMENT; 669 break; 670 } 671 break; 672 673 case DT_MERGE_LINES: 674 675 if (c != '\n') 676 { 677 /* 678 * This is not a continuation backslash, it is a normal 679 * normal ASL backslash - for example: Scope(\_SB_) 680 */ 681 i++; /* Keep the backslash that is already in the buffer */ 682 683 ungetc (c, Handle); 684 State = DT_NORMAL_TEXT; 685 } 686 else 687 { 688 /* 689 * This is a continuation line -- a backlash followed 690 * immediately by a newline. Insert a space between the 691 * lines (overwrite the backslash) 692 */ 693 Gbl_CurrentLineBuffer[i] = ' '; 694 i++; 695 696 /* Ignore newline, this will merge the lines */ 697 698 CurrentLineOffset = Gbl_NextLineOffset; 699 Gbl_NextLineOffset = (UINT32) ftell (Handle); 700 Gbl_CurrentLineNumber++; 701 State = DT_NORMAL_TEXT; 702 } 703 break; 704 705 default: 706 707 DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, "Unknown input state"); 708 return (ASL_EOF); 709 } 710 } 711 } 712 713 714 /****************************************************************************** 715 * 716 * FUNCTION: DtScanFile 717 * 718 * PARAMETERS: Handle - Open file handle for the source file 719 * 720 * RETURN: Pointer to start of the constructed parse tree. 721 * 722 * DESCRIPTION: Scan source file, link all field names and values 723 * to the global parse tree: Gbl_FieldList 724 * 725 *****************************************************************************/ 726 727 DT_FIELD * 728 DtScanFile ( 729 FILE *Handle) 730 { 731 ACPI_STATUS Status; 732 UINT32 Offset; 733 734 735 ACPI_FUNCTION_NAME (DtScanFile); 736 737 738 /* Get the file size */ 739 740 Gbl_InputByteCount = DtGetFileSize (Handle); 741 742 Gbl_CurrentLineNumber = 0; 743 Gbl_CurrentLineOffset = 0; 744 Gbl_NextLineOffset = 0; 745 746 /* Scan line-by-line */ 747 748 while ((Offset = DtGetNextLine (Handle)) != ASL_EOF) 749 { 750 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Line %2.2u/%4.4X - %s", 751 Gbl_CurrentLineNumber, Offset, Gbl_CurrentLineBuffer)); 752 753 Status = DtParseLine (Gbl_CurrentLineBuffer, Gbl_CurrentLineNumber, Offset); 754 if (Status == AE_NOT_FOUND) 755 { 756 break; 757 } 758 } 759 760 /* Dump the parse tree if debug enabled */ 761 762 DtDumpFieldList (Gbl_FieldList); 763 return (Gbl_FieldList); 764 } 765 766 767 /* 768 * Output functions 769 */ 770 771 /****************************************************************************** 772 * 773 * FUNCTION: DtWriteBinary 774 * 775 * PARAMETERS: DT_WALK_CALLBACK 776 * 777 * RETURN: Status 778 * 779 * DESCRIPTION: Write one subtable of a binary ACPI table 780 * 781 *****************************************************************************/ 782 783 static void 784 DtWriteBinary ( 785 DT_SUBTABLE *Subtable, 786 void *Context, 787 void *ReturnValue) 788 { 789 790 FlWriteFile (ASL_FILE_AML_OUTPUT, Subtable->Buffer, Subtable->Length); 791 } 792 793 794 /****************************************************************************** 795 * 796 * FUNCTION: DtOutputBinary 797 * 798 * PARAMETERS: 799 * 800 * RETURN: Status 801 * 802 * DESCRIPTION: Write entire binary ACPI table (result of compilation) 803 * 804 *****************************************************************************/ 805 806 void 807 DtOutputBinary ( 808 DT_SUBTABLE *RootTable) 809 { 810 811 if (!RootTable) 812 { 813 return; 814 } 815 816 /* Walk the entire parse tree, emitting the binary data */ 817 818 DtWalkTableTree (RootTable, DtWriteBinary, NULL, NULL); 819 Gbl_TableLength = DtGetFileSize (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle); 820 } 821 822 823 /* 824 * Listing support 825 */ 826 827 /****************************************************************************** 828 * 829 * FUNCTION: DtDumpBuffer 830 * 831 * PARAMETERS: FileID - Where to write buffer data 832 * Buffer - Buffer to dump 833 * Offset - Offset in current table 834 * Length - Buffer Length 835 * 836 * RETURN: None 837 * 838 * DESCRIPTION: Another copy of DumpBuffer routine (unfortunately). 839 * 840 * TBD: merge dump buffer routines 841 * 842 *****************************************************************************/ 843 844 static void 845 DtDumpBuffer ( 846 UINT32 FileId, 847 UINT8 *Buffer, 848 UINT32 Offset, 849 UINT32 Length) 850 { 851 UINT32 i; 852 UINT32 j; 853 UINT8 BufChar; 854 855 856 FlPrintFile (FileId, "Output: [%3.3Xh %4.4d %3d] ", 857 Offset, Offset, Length); 858 859 i = 0; 860 while (i < Length) 861 { 862 if (i >= 16) 863 { 864 FlPrintFile (FileId, "%24s", ""); 865 } 866 867 /* Print 16 hex chars */ 868 869 for (j = 0; j < 16;) 870 { 871 if (i + j >= Length) 872 { 873 /* Dump fill spaces */ 874 875 FlPrintFile (FileId, " "); 876 j++; 877 continue; 878 } 879 880 FlPrintFile (FileId, "%02X ", Buffer[i+j]); 881 j++; 882 } 883 884 FlPrintFile (FileId, " "); 885 for (j = 0; j < 16; j++) 886 { 887 if (i + j >= Length) 888 { 889 FlPrintFile (FileId, "\n\n"); 890 return; 891 } 892 893 BufChar = Buffer[(ACPI_SIZE) i + j]; 894 if (ACPI_IS_PRINT (BufChar)) 895 { 896 FlPrintFile (FileId, "%c", BufChar); 897 } 898 else 899 { 900 FlPrintFile (FileId, "."); 901 } 902 } 903 904 /* Done with that line. */ 905 906 FlPrintFile (FileId, "\n"); 907 i += 16; 908 } 909 910 FlPrintFile (FileId, "\n\n"); 911 } 912 913 914 /****************************************************************************** 915 * 916 * FUNCTION: DtDumpFieldList 917 * 918 * PARAMETERS: Field - Root field 919 * 920 * RETURN: None 921 * 922 * DESCRIPTION: Dump the entire field list 923 * 924 *****************************************************************************/ 925 926 void 927 DtDumpFieldList ( 928 DT_FIELD *Field) 929 { 930 931 if (!Gbl_DebugFlag || !Field) 932 { 933 return; 934 } 935 936 DbgPrint (ASL_DEBUG_OUTPUT, "\nField List:\n" 937 "LineNo ByteOff NameCol Column TableOff " 938 "Flags %32s : %s\n\n", "Name", "Value"); 939 while (Field) 940 { 941 DbgPrint (ASL_DEBUG_OUTPUT, 942 "%.08X %.08X %.08X %.08X %.08X %.08X %32s : %s\n", 943 Field->Line, Field->ByteOffset, Field->NameColumn, 944 Field->Column, Field->TableOffset, Field->Flags, 945 Field->Name, Field->Value); 946 947 Field = Field->Next; 948 } 949 950 DbgPrint (ASL_DEBUG_OUTPUT, "\n\n"); 951 } 952 953 954 /****************************************************************************** 955 * 956 * FUNCTION: DtDumpSubtableInfo, DtDumpSubtableTree 957 * 958 * PARAMETERS: DT_WALK_CALLBACK 959 * 960 * RETURN: None 961 * 962 * DESCRIPTION: Info - dump a subtable tree entry with extra information. 963 * Tree - dump a subtable tree formatted by depth indentation. 964 * 965 *****************************************************************************/ 966 967 static void 968 DtDumpSubtableInfo ( 969 DT_SUBTABLE *Subtable, 970 void *Context, 971 void *ReturnValue) 972 { 973 974 DbgPrint (ASL_DEBUG_OUTPUT, 975 "[%.04X] %.08X %.08X %.08X %.08X %.08X %p %p %p\n", 976 Subtable->Depth, Subtable->Length, Subtable->TotalLength, 977 Subtable->SizeOfLengthField, Subtable->Flags, Subtable, 978 Subtable->Parent, Subtable->Child, Subtable->Peer); 979 } 980 981 static void 982 DtDumpSubtableTree ( 983 DT_SUBTABLE *Subtable, 984 void *Context, 985 void *ReturnValue) 986 { 987 988 DbgPrint (ASL_DEBUG_OUTPUT, 989 "[%.04X] %*s%08X (%.02X) - (%.02X)\n", 990 Subtable->Depth, (4 * Subtable->Depth), " ", 991 Subtable, Subtable->Length, Subtable->TotalLength); 992 } 993 994 995 /****************************************************************************** 996 * 997 * FUNCTION: DtDumpSubtableList 998 * 999 * PARAMETERS: None 1000 * 1001 * RETURN: None 1002 * 1003 * DESCRIPTION: Dump the raw list of subtables with information, and also 1004 * dump the subtable list in formatted tree format. Assists with 1005 * the development of new table code. 1006 * 1007 *****************************************************************************/ 1008 1009 void 1010 DtDumpSubtableList ( 1011 void) 1012 { 1013 1014 if (!Gbl_DebugFlag || !Gbl_RootTable) 1015 { 1016 return; 1017 } 1018 1019 DbgPrint (ASL_DEBUG_OUTPUT, 1020 "Subtable Info:\n" 1021 "Depth Length TotalLen LenSize Flags " 1022 "This Parent Child Peer\n\n"); 1023 DtWalkTableTree (Gbl_RootTable, DtDumpSubtableInfo, NULL, NULL); 1024 1025 DbgPrint (ASL_DEBUG_OUTPUT, 1026 "\nSubtable Tree: (Depth, Subtable, Length, TotalLength)\n\n"); 1027 DtWalkTableTree (Gbl_RootTable, DtDumpSubtableTree, NULL, NULL); 1028 } 1029 1030 1031 /****************************************************************************** 1032 * 1033 * FUNCTION: DtWriteFieldToListing 1034 * 1035 * PARAMETERS: Buffer - Contains the compiled data 1036 * Field - Field node for the input line 1037 * Length - Length of the output data 1038 * 1039 * RETURN: None 1040 * 1041 * DESCRIPTION: Write one field to the listing file (if listing is enabled). 1042 * 1043 *****************************************************************************/ 1044 1045 void 1046 DtWriteFieldToListing ( 1047 UINT8 *Buffer, 1048 DT_FIELD *Field, 1049 UINT32 Length) 1050 { 1051 UINT8 FileByte; 1052 1053 1054 if (!Gbl_ListingFlag || !Field) 1055 { 1056 return; 1057 } 1058 1059 /* Dump the original source line */ 1060 1061 FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Input: "); 1062 FlSeekFile (ASL_FILE_INPUT, Field->ByteOffset); 1063 1064 while (FlReadFile (ASL_FILE_INPUT, &FileByte, 1) == AE_OK) 1065 { 1066 FlWriteFile (ASL_FILE_LISTING_OUTPUT, &FileByte, 1); 1067 if (FileByte == '\n') 1068 { 1069 break; 1070 } 1071 } 1072 1073 /* Dump the line as parsed and represented internally */ 1074 1075 FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Parsed: %*s : %.64s", 1076 Field->Column-4, Field->Name, Field->Value); 1077 1078 if (strlen (Field->Value) > 64) 1079 { 1080 FlPrintFile (ASL_FILE_LISTING_OUTPUT, "...Additional data, length 0x%X\n", 1081 strlen (Field->Value)); 1082 } 1083 FlPrintFile (ASL_FILE_LISTING_OUTPUT, "\n"); 1084 1085 /* Dump the hex data that will be output for this field */ 1086 1087 DtDumpBuffer (ASL_FILE_LISTING_OUTPUT, Buffer, Field->TableOffset, Length); 1088 } 1089 1090 1091 /****************************************************************************** 1092 * 1093 * FUNCTION: DtWriteTableToListing 1094 * 1095 * PARAMETERS: None 1096 * 1097 * RETURN: None 1098 * 1099 * DESCRIPTION: Write the entire compiled table to the listing file 1100 * in hex format 1101 * 1102 *****************************************************************************/ 1103 1104 void 1105 DtWriteTableToListing ( 1106 void) 1107 { 1108 UINT8 *Buffer; 1109 1110 1111 if (!Gbl_ListingFlag) 1112 { 1113 return; 1114 } 1115 1116 /* Read the entire table from the output file */ 1117 1118 Buffer = UtLocalCalloc (Gbl_TableLength); 1119 FlSeekFile (ASL_FILE_AML_OUTPUT, 0); 1120 FlReadFile (ASL_FILE_AML_OUTPUT, Buffer, Gbl_TableLength); 1121 1122 /* Dump the raw table data */ 1123 1124 AcpiOsRedirectOutput (Gbl_Files[ASL_FILE_LISTING_OUTPUT].Handle); 1125 1126 AcpiOsPrintf ("\n%s: Length %d (0x%X)\n\n", 1127 ACPI_RAW_TABLE_DATA_HEADER, Gbl_TableLength, Gbl_TableLength); 1128 AcpiUtDumpBuffer (Buffer, Gbl_TableLength, DB_BYTE_DISPLAY, 0); 1129 1130 AcpiOsRedirectOutput (stdout); 1131 ACPI_FREE (Buffer); 1132 }