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