Home | History | Annotate | Line # | Download | only in compiler
      1 /******************************************************************************
      2  *
      3  * Module Name: dtio.c - File I/O support for data table compiler
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2026, 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 
     53 static char *
     54 DtTrim (
     55     char                    *String);
     56 
     57 static ACPI_STATUS
     58 DtParseLine (
     59     char                    *LineBuffer,
     60     UINT32                  Line,
     61     UINT32                  Offset);
     62 
     63 static void
     64 DtWriteBinary (
     65     DT_SUBTABLE             *Subtable,
     66     void                    *Context,
     67     void                    *ReturnValue);
     68 
     69 static void
     70 DtDumpBuffer (
     71     UINT32                  FileId,
     72     UINT8                   *Buffer,
     73     UINT32                  Offset,
     74     UINT32                  Length);
     75 
     76 static void
     77 DtDumpSubtableInfo (
     78     DT_SUBTABLE             *Subtable,
     79     void                    *Context,
     80     void                    *ReturnValue);
     81 
     82 static void
     83 DtDumpSubtableTree (
     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 
    100 static 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 
    115 static char *
    116 DtTrim (
    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         memcpy (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 
    202 static ACPI_STATUS
    203 DtParseLine (
    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     memcpy (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     /* No value characters present */
    318     if (End <= Start)
    319     {
    320         return (AE_OK);
    321     }
    322 
    323     Length = ACPI_PTR_DIFF (End, Start);
    324     TmpValue = UtLocalCalloc (Length + 1);
    325 
    326     memcpy (TmpValue, Start, Length);
    327     Value = DtTrim (TmpValue);
    328     ACPI_FREE (TmpValue);
    329 
    330     /* Create a new field object only if we have a valid value field */
    331 
    332     if ((Value && *Value) || IsNullString)
    333     {
    334         Field = UtFieldCacheCalloc ();
    335         Field->Name = Name;
    336         Field->Value = Value;
    337         Field->Line = Line;
    338         Field->ByteOffset = Offset;
    339         Field->NameColumn = NameColumn;
    340         Field->Column = Column;
    341         Field->StringLength = Length;
    342 
    343         DtLinkField (Field);
    344     }
    345     /* Else -- Ignore this field, it has no valid data */
    346 
    347     return (AE_OK);
    348 }
    349 
    350 
    351 /******************************************************************************
    352  *
    353  * FUNCTION:    DtGetNextLine
    354  *
    355  * PARAMETERS:  Handle              - Open file handle for the source file
    356  *
    357  * RETURN:      Filled line buffer and offset of start-of-line (ASL_EOF on EOF)
    358  *
    359  * DESCRIPTION: Get the next valid source line. Removes all comments.
    360  *              Ignores empty lines.
    361  *
    362  * Handles both slash-asterisk and slash-slash comments.
    363  * Also, quoted strings, but no escapes within.
    364  *
    365  * Line is returned in AslGbl_CurrentLineBuffer.
    366  * Line number in original file is returned in AslGbl_CurrentLineNumber.
    367  *
    368  *****************************************************************************/
    369 
    370 UINT32
    371 DtGetNextLine (
    372     FILE                    *Handle,
    373     UINT32                  Flags)
    374 {
    375     BOOLEAN                 LineNotAllBlanks = FALSE;
    376     UINT32                  State = DT_NORMAL_TEXT;
    377     UINT32                  CurrentLineOffset;
    378     UINT32                  i;
    379     int                     c;
    380     int                     c1;
    381 
    382 
    383     memset (AslGbl_CurrentLineBuffer, 0, AslGbl_LineBufferSize);
    384     for (i = 0; ;)
    385     {
    386         /*
    387          * If line is too long, expand the line buffers. Also increases
    388          * AslGbl_LineBufferSize.
    389          */
    390         if (i >= AslGbl_LineBufferSize)
    391         {
    392             UtExpandLineBuffers ();
    393         }
    394 
    395         c = getc (Handle);
    396         if (c == EOF)
    397         {
    398             switch (State)
    399             {
    400             case DT_START_QUOTED_STRING:
    401             case DT_SLASH_ASTERISK_COMMENT:
    402 
    403                 AcpiOsPrintf ("**** EOF within comment/string %u\n", State);
    404                 break;
    405 
    406             default:
    407 
    408                 break;
    409             }
    410 
    411             /* Standalone EOF is OK */
    412 
    413             if (i == 0)
    414             {
    415                 return (ASL_EOF);
    416             }
    417 
    418             /*
    419              * Received an EOF in the middle of a line. Terminate the
    420              * line with a newline. The next call to this function will
    421              * return a standalone EOF. Thus, the upper parsing software
    422              * never has to deal with an EOF within a valid line (or
    423              * the last line does not get tossed on the floor.)
    424              */
    425             c = '\n';
    426             State = DT_NORMAL_TEXT;
    427         }
    428         else if (c == '\r')
    429         {
    430             c1 = getc (Handle);
    431             if (c1 == '\n')
    432             {
    433                 /*
    434                  * Skip the carriage return as if it didn't exist. This is
    435                  * onlt meant for input files in DOS format in unix. fopen in
    436                  * unix may not support "text mode" and leaves CRLF intact.
    437                  */
    438                 c = '\n';
    439             }
    440             else
    441             {
    442                 /* This was not a CRLF. Only a CR */
    443 
    444                 ungetc(c1, Handle);
    445 
    446                 DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL,
    447                     "Carriage return without linefeed detected");
    448                 return (ASL_EOF);
    449             }
    450         }
    451 
    452         switch (State)
    453         {
    454         case DT_NORMAL_TEXT:
    455 
    456             /* Normal text, insert char into line buffer */
    457 
    458             AslGbl_CurrentLineBuffer[i] = (char) c;
    459             switch (c)
    460             {
    461             case '/':
    462 
    463                 State = DT_START_COMMENT;
    464                 break;
    465 
    466             case '"':
    467 
    468                 State = DT_START_QUOTED_STRING;
    469                 LineNotAllBlanks = TRUE;
    470                 i++;
    471                 break;
    472 
    473             case '\\':
    474                 /*
    475                  * The continuation char MUST be last char on this line.
    476                  * Otherwise, it will be assumed to be a valid ASL char.
    477                  */
    478                 State = DT_MERGE_LINES;
    479                 break;
    480 
    481             case '\n':
    482 
    483                 CurrentLineOffset = AslGbl_NextLineOffset;
    484                 AslGbl_NextLineOffset = (UINT32) ftell (Handle);
    485                 AslGbl_CurrentLineNumber++;
    486 
    487                 /*
    488                  * Exit if line is complete. Ignore empty lines (only \n)
    489                  * or lines that contain nothing but blanks.
    490                  */
    491                 if ((i != 0) && LineNotAllBlanks)
    492                 {
    493                     if ((i + 1) >= AslGbl_LineBufferSize)
    494                     {
    495                         UtExpandLineBuffers ();
    496                     }
    497 
    498                     AslGbl_CurrentLineBuffer[i+1] = 0; /* Terminate string */
    499                     return (CurrentLineOffset);
    500                 }
    501 
    502                 /* Toss this line and start a new one */
    503 
    504                 i = 0;
    505                 LineNotAllBlanks = FALSE;
    506                 break;
    507 
    508             default:
    509 
    510                 if (c != ' ')
    511                 {
    512                     LineNotAllBlanks = TRUE;
    513                 }
    514 
    515                 i++;
    516                 break;
    517             }
    518             break;
    519 
    520         case DT_START_QUOTED_STRING:
    521 
    522             /* Insert raw chars until end of quoted string */
    523 
    524             AslGbl_CurrentLineBuffer[i] = (char) c;
    525             i++;
    526 
    527             switch (c)
    528             {
    529             case '"':
    530 
    531                 State = DT_NORMAL_TEXT;
    532                 break;
    533 
    534             case '\\':
    535 
    536                 State = DT_ESCAPE_SEQUENCE;
    537                 break;
    538 
    539             case '\n':
    540 
    541                 if (!(Flags & DT_ALLOW_MULTILINE_QUOTES))
    542                 {
    543                     AcpiOsPrintf (
    544                         "ERROR at line %u: Unterminated quoted string\n",
    545                         AslGbl_CurrentLineNumber++);
    546                     State = DT_NORMAL_TEXT;
    547                 }
    548                 break;
    549 
    550             default:    /* Get next character */
    551 
    552                 break;
    553             }
    554             break;
    555 
    556         case DT_ESCAPE_SEQUENCE:
    557 
    558             /* Just copy the escaped character. TBD: sufficient for table compiler? */
    559 
    560             AslGbl_CurrentLineBuffer[i] = (char) c;
    561             i++;
    562             State = DT_START_QUOTED_STRING;
    563             break;
    564 
    565         case DT_START_COMMENT:
    566 
    567             /* Open comment if this character is an asterisk or slash */
    568 
    569             switch (c)
    570             {
    571             case '*':
    572 
    573                 State = DT_SLASH_ASTERISK_COMMENT;
    574                 break;
    575 
    576             case '/':
    577 
    578                 State = DT_SLASH_SLASH_COMMENT;
    579                 break;
    580 
    581             default:    /* Not a comment */
    582 
    583                 i++;    /* Save the preceding slash */
    584                 if (i >= AslGbl_LineBufferSize)
    585                 {
    586                     UtExpandLineBuffers ();
    587                 }
    588 
    589                 AslGbl_CurrentLineBuffer[i] = (char) c;
    590                 i++;
    591                 State = DT_NORMAL_TEXT;
    592                 break;
    593             }
    594             break;
    595 
    596         case DT_SLASH_ASTERISK_COMMENT:
    597 
    598             /* Ignore chars until an asterisk-slash is found */
    599 
    600             switch (c)
    601             {
    602             case '\n':
    603 
    604                 AslGbl_NextLineOffset = (UINT32) ftell (Handle);
    605                 AslGbl_CurrentLineNumber++;
    606                 break;
    607 
    608             case '*':
    609 
    610                 State = DT_END_COMMENT;
    611                 break;
    612 
    613             default:
    614 
    615                 break;
    616             }
    617             break;
    618 
    619         case DT_SLASH_SLASH_COMMENT:
    620 
    621             /* Ignore chars until end-of-line */
    622 
    623             if (c == '\n')
    624             {
    625                 /* We will exit via the NORMAL_TEXT path */
    626 
    627                 ungetc (c, Handle);
    628                 State = DT_NORMAL_TEXT;
    629             }
    630             break;
    631 
    632         case DT_END_COMMENT:
    633 
    634             /* End comment if this char is a slash */
    635 
    636             switch (c)
    637             {
    638             case '/':
    639 
    640                 State = DT_NORMAL_TEXT;
    641                 break;
    642 
    643             case '\n':
    644 
    645                 AslGbl_NextLineOffset = (UINT32) ftell (Handle);
    646                 AslGbl_CurrentLineNumber++;
    647                 break;
    648 
    649             case '*':
    650 
    651                 /* Consume all adjacent asterisks */
    652                 break;
    653 
    654             default:
    655 
    656                 State = DT_SLASH_ASTERISK_COMMENT;
    657                 break;
    658             }
    659             break;
    660 
    661         case DT_MERGE_LINES:
    662 
    663             if (c != '\n')
    664             {
    665                 /*
    666                  * This is not a continuation backslash, it is a normal
    667                  * normal ASL backslash - for example: Scope(\_SB_)
    668                  */
    669                 i++; /* Keep the backslash that is already in the buffer */
    670 
    671                 ungetc (c, Handle);
    672                 State = DT_NORMAL_TEXT;
    673             }
    674             else
    675             {
    676                 /*
    677                  * This is a continuation line -- a backlash followed
    678                  * immediately by a newline. Insert a space between the
    679                  * lines (overwrite the backslash)
    680                  */
    681                 AslGbl_CurrentLineBuffer[i] = ' ';
    682                 i++;
    683 
    684                 /* Ignore newline, this will merge the lines */
    685 
    686                 AslGbl_NextLineOffset = (UINT32) ftell (Handle);
    687                 AslGbl_CurrentLineNumber++;
    688                 State = DT_NORMAL_TEXT;
    689             }
    690             break;
    691 
    692         default:
    693 
    694             DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, "Unknown input state");
    695             return (ASL_EOF);
    696         }
    697     }
    698 }
    699 
    700 
    701 /******************************************************************************
    702  *
    703  * FUNCTION:    DtScanFile
    704  *
    705  * PARAMETERS:  Handle              - Open file handle for the source file
    706  *
    707  * RETURN:      Pointer to start of the constructed parse tree.
    708  *
    709  * DESCRIPTION: Scan source file, link all field names and values
    710  *              to the global parse tree: AslGbl_FieldList
    711  *
    712  *****************************************************************************/
    713 
    714 DT_FIELD *
    715 DtScanFile (
    716     FILE                    *Handle)
    717 {
    718     ACPI_STATUS             Status;
    719     UINT32                  Offset;
    720 
    721 
    722     ACPI_FUNCTION_NAME (DtScanFile);
    723 
    724 
    725     /* Get the file size */
    726 
    727     AslGbl_InputByteCount = CmGetFileSize (Handle);
    728     if (AslGbl_InputByteCount == ACPI_UINT32_MAX)
    729     {
    730         AslAbort ();
    731     }
    732 
    733     AslGbl_CurrentLineNumber = 0;
    734     AslGbl_CurrentLineOffset = 0;
    735     AslGbl_NextLineOffset = 0;
    736 
    737     /* Scan line-by-line */
    738 
    739     while ((Offset = DtGetNextLine (Handle, 0)) != ASL_EOF)
    740     {
    741         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Line %2.2u/%4.4X - %s",
    742             AslGbl_CurrentLineNumber, Offset, AslGbl_CurrentLineBuffer));
    743 
    744         Status = DtParseLine (AslGbl_CurrentLineBuffer,
    745             AslGbl_CurrentLineNumber, Offset);
    746         if (Status == AE_NOT_FOUND)
    747         {
    748             break;
    749         }
    750     }
    751 
    752     /* Dump the parse tree if debug enabled */
    753 
    754     DtDumpFieldList (AslGbl_FieldList);
    755     return (AslGbl_FieldList);
    756 }
    757 
    758 
    759 /*
    760  * Output functions
    761  */
    762 
    763 /******************************************************************************
    764  *
    765  * FUNCTION:    DtWriteBinary
    766  *
    767  * PARAMETERS:  DT_WALK_CALLBACK
    768  *
    769  * RETURN:      Status
    770  *
    771  * DESCRIPTION: Write one subtable of a binary ACPI table
    772  *
    773  *****************************************************************************/
    774 
    775 static void
    776 DtWriteBinary (
    777     DT_SUBTABLE             *Subtable,
    778     void                    *Context,
    779     void                    *ReturnValue)
    780 {
    781 
    782     FlWriteFile (ASL_FILE_AML_OUTPUT, Subtable->Buffer, Subtable->Length);
    783 }
    784 
    785 
    786 /******************************************************************************
    787  *
    788  * FUNCTION:    DtOutputBinary
    789  *
    790  * PARAMETERS:
    791  *
    792  * RETURN:      Status
    793  *
    794  * DESCRIPTION: Write entire binary ACPI table (result of compilation)
    795  *
    796  *****************************************************************************/
    797 
    798 void
    799 DtOutputBinary (
    800     DT_SUBTABLE             *RootTable)
    801 {
    802 
    803     if (!RootTable)
    804     {
    805         return;
    806     }
    807 
    808     /* Walk the entire parse tree, emitting the binary data */
    809 
    810     DtWalkTableTree (RootTable, DtWriteBinary, NULL, NULL);
    811 
    812     AslGbl_TableLength = CmGetFileSize (AslGbl_Files[ASL_FILE_AML_OUTPUT].Handle);
    813     if (AslGbl_TableLength == ACPI_UINT32_MAX)
    814     {
    815         AslAbort ();
    816     }
    817 }
    818 
    819 
    820 /*
    821  * Listing support
    822  */
    823 
    824 /******************************************************************************
    825  *
    826  * FUNCTION:    DtDumpBuffer
    827  *
    828  * PARAMETERS:  FileID              - Where to write buffer data
    829  *              Buffer              - Buffer to dump
    830  *              Offset              - Offset in current table
    831  *              Length              - Buffer Length
    832  *
    833  * RETURN:      None
    834  *
    835  * DESCRIPTION: Another copy of DumpBuffer routine (unfortunately).
    836  *
    837  * TBD: merge dump buffer routines
    838  *
    839  *****************************************************************************/
    840 
    841 static void
    842 DtDumpBuffer (
    843     UINT32                  FileId,
    844     UINT8                   *Buffer,
    845     UINT32                  Offset,
    846     UINT32                  Length)
    847 {
    848     UINT32                  i;
    849     UINT32                  j;
    850     UINT8                   BufChar;
    851 
    852 
    853     FlPrintFile (FileId, "Output: [%3.3Xh %4.4d %3.3Xh] ",
    854         Offset, Offset, Length);
    855 
    856     i = 0;
    857     while (i < Length)
    858     {
    859         if (i >= 16)
    860         {
    861             FlPrintFile (FileId, "%24s", "");
    862         }
    863 
    864         /* Print 16 hex chars */
    865 
    866         for (j = 0; j < 16;)
    867         {
    868             if (i + j >= Length)
    869             {
    870                 /* Dump fill spaces */
    871 
    872                 FlPrintFile (FileId, "   ");
    873                 j++;
    874                 continue;
    875             }
    876 
    877             FlPrintFile (FileId, "%02X ", Buffer[i+j]);
    878             j++;
    879         }
    880 
    881         FlPrintFile (FileId, " ");
    882         for (j = 0; j < 16; j++)
    883         {
    884             if (i + j >= Length)
    885             {
    886                 FlPrintFile (FileId, "\n\n");
    887                 return;
    888             }
    889 
    890             BufChar = Buffer[(ACPI_SIZE) i + j];
    891             if (isprint (BufChar))
    892             {
    893                 FlPrintFile (FileId, "%c", BufChar);
    894             }
    895             else
    896             {
    897                 FlPrintFile (FileId, ".");
    898             }
    899         }
    900 
    901         /* Done with that line. */
    902 
    903         FlPrintFile (FileId, "\n");
    904         i += 16;
    905     }
    906 
    907     FlPrintFile (FileId, "\n\n");
    908 }
    909 
    910 
    911 /******************************************************************************
    912  *
    913  * FUNCTION:    DtDumpFieldList
    914  *
    915  * PARAMETERS:  Field               - Root field
    916  *
    917  * RETURN:      None
    918  *
    919  * DESCRIPTION: Dump the entire field list
    920  *
    921  *****************************************************************************/
    922 
    923 void
    924 DtDumpFieldList (
    925     DT_FIELD                *Field)
    926 {
    927 
    928     if (!AslGbl_DebugFlag || !Field)
    929     {
    930         return;
    931     }
    932 
    933     DbgPrint (ASL_DEBUG_OUTPUT,  "\nField List:\n"
    934         "LineNo   ByteOff  NameCol  Column   TableOff "
    935         "Flags %32s : %s\n\n", "Name", "Value");
    936 
    937     while (Field)
    938     {
    939         DbgPrint (ASL_DEBUG_OUTPUT,
    940             "%.08X %.08X %.08X %.08X %.08X %2.2X    %32s : %s\n",
    941             Field->Line, Field->ByteOffset, Field->NameColumn,
    942             Field->Column, Field->TableOffset, Field->Flags,
    943             Field->Name, Field->Value);
    944 
    945         Field = Field->Next;
    946     }
    947 
    948     DbgPrint (ASL_DEBUG_OUTPUT,  "\n\n");
    949 }
    950 
    951 
    952 /******************************************************************************
    953  *
    954  * FUNCTION:    DtDumpSubtableInfo, DtDumpSubtableTree
    955  *
    956  * PARAMETERS:  DT_WALK_CALLBACK
    957  *
    958  * RETURN:      None
    959  *
    960  * DESCRIPTION: Info - dump a subtable tree entry with extra information.
    961  *              Tree - dump a subtable tree formatted by depth indentation.
    962  *
    963  *****************************************************************************/
    964 
    965 static void
    966 DtDumpSubtableInfo (
    967     DT_SUBTABLE             *Subtable,
    968     void                    *Context,
    969     void                    *ReturnValue)
    970 {
    971 
    972     DbgPrint (ASL_DEBUG_OUTPUT,
    973         "[%.04X] %24s %.08X %.08X %.08X %.08X %p %p %p %p\n",
    974         Subtable->Depth, Subtable->Name, Subtable->Length, Subtable->TotalLength,
    975         Subtable->SizeOfLengthField, Subtable->Flags, Subtable,
    976         Subtable->Parent, Subtable->Child, Subtable->Peer);
    977 }
    978 
    979 static void
    980 DtDumpSubtableTree (
    981     DT_SUBTABLE             *Subtable,
    982     void                    *Context,
    983     void                    *ReturnValue)
    984 {
    985 
    986     DbgPrint (ASL_DEBUG_OUTPUT,
    987         "[%.04X] %24s %*s%p (%.02X) - (%.02X)        %.02X\n",
    988         Subtable->Depth, Subtable->Name, (4 * Subtable->Depth), " ",
    989         Subtable, Subtable->Length, Subtable->TotalLength, *Subtable->Buffer);
    990 }
    991 
    992 
    993 /******************************************************************************
    994  *
    995  * FUNCTION:    DtDumpSubtableList
    996  *
    997  * PARAMETERS:  None
    998  *
    999  * RETURN:      None
   1000  *
   1001  * DESCRIPTION: Dump the raw list of subtables with information, and also
   1002  *              dump the subtable list in formatted tree format. Assists with
   1003  *              the development of new table code.
   1004  *
   1005  *****************************************************************************/
   1006 
   1007 void
   1008 DtDumpSubtableList (
   1009     void)
   1010 {
   1011 
   1012     if (!AslGbl_DebugFlag || !AslGbl_RootTable)
   1013     {
   1014         return;
   1015     }
   1016 
   1017     DbgPrint (ASL_DEBUG_OUTPUT,
   1018         "Subtable Info:\n"
   1019         "Depth                      Name Length   TotalLen LenSize  Flags    "
   1020         "This     Parent   Child    Peer\n\n");
   1021     DtWalkTableTree (AslGbl_RootTable, DtDumpSubtableInfo, NULL, NULL);
   1022 
   1023     DbgPrint (ASL_DEBUG_OUTPUT,
   1024         "\nSubtable Tree: (Depth, Name, Subtable, Length, TotalLength, Integer Value)\n\n");
   1025     DtWalkTableTree (AslGbl_RootTable, DtDumpSubtableTree, NULL, NULL);
   1026 
   1027     DbgPrint (ASL_DEBUG_OUTPUT, "\n");
   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 (!AslGbl_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             (UINT32) strlen (Field->Value));
   1082     }
   1083 
   1084     FlPrintFile (ASL_FILE_LISTING_OUTPUT, "\n");
   1085 
   1086     /* Dump the hex data that will be output for this field */
   1087 
   1088     DtDumpBuffer (ASL_FILE_LISTING_OUTPUT, Buffer, Field->TableOffset, Length);
   1089 }
   1090 
   1091 
   1092 /******************************************************************************
   1093  *
   1094  * FUNCTION:    DtWriteTableToListing
   1095  *
   1096  * PARAMETERS:  None
   1097  *
   1098  * RETURN:      None
   1099  *
   1100  * DESCRIPTION: Write the entire compiled table to the listing file
   1101  *              in hex format
   1102  *
   1103  *****************************************************************************/
   1104 
   1105 void
   1106 DtWriteTableToListing (
   1107     void)
   1108 {
   1109     UINT8                   *Buffer;
   1110 
   1111 
   1112     if (!AslGbl_ListingFlag)
   1113     {
   1114         return;
   1115     }
   1116 
   1117     /* Read the entire table from the output file */
   1118 
   1119     Buffer = UtLocalCalloc (AslGbl_TableLength);
   1120     FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
   1121     FlReadFile (ASL_FILE_AML_OUTPUT, Buffer, AslGbl_TableLength);
   1122 
   1123     /* Dump the raw table data */
   1124 
   1125     AcpiOsRedirectOutput (AslGbl_Files[ASL_FILE_LISTING_OUTPUT].Handle);
   1126 
   1127     AcpiOsPrintf ("\n%s: Length %d (0x%X)\n\n",
   1128         ACPI_RAW_TABLE_DATA_HEADER, AslGbl_TableLength, AslGbl_TableLength);
   1129     AcpiUtDumpBuffer (Buffer, AslGbl_TableLength, DB_BYTE_DISPLAY, 0);
   1130 
   1131     AcpiOsRedirectOutput (stdout);
   1132     ACPI_FREE (Buffer);
   1133 }
   1134