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