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