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 }