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