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