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