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