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