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