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