xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/dtio.c (revision 046a29855e04359424fd074e8313af6b6be8cfb6)
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 
53 static char *
54 DtTrim (
55     char                    *String);
56 
57 static ACPI_STATUS
58 DtParseLine (
59     char                    *LineBuffer,
60     UINT32                  Line,
61     UINT32                  Offset);
62 
63 static void
64 DtWriteBinary (
65     DT_SUBTABLE             *Subtable,
66     void                    *Context,
67     void                    *ReturnValue);
68 
69 static void
70 DtDumpBuffer (
71     UINT32                  FileId,
72     UINT8                   *Buffer,
73     UINT32                  Offset,
74     UINT32                  Length);
75 
76 static void
77 DtDumpSubtableInfo (
78     DT_SUBTABLE             *Subtable,
79     void                    *Context,
80     void                    *ReturnValue);
81 
82 static void
83 DtDumpSubtableTree (
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 
100 static 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 
115 static char *
DtTrim(char * String)116 DtTrim (
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 
202 static ACPI_STATUS
DtParseLine(char * LineBuffer,UINT32 Line,UINT32 Offset)203 DtParseLine (
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 
364 UINT32
DtGetNextLine(FILE * Handle,UINT32 Flags)365 DtGetNextLine (
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 
708 DT_FIELD *
DtScanFile(FILE * Handle)709 DtScanFile (
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 
769 static void
DtWriteBinary(DT_SUBTABLE * Subtable,void * Context,void * ReturnValue)770 DtWriteBinary (
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 
792 void
DtOutputBinary(DT_SUBTABLE * RootTable)793 DtOutputBinary (
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 
835 static void
DtDumpBuffer(UINT32 FileId,UINT8 * Buffer,UINT32 Offset,UINT32 Length)836 DtDumpBuffer (
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 
917 void
DtDumpFieldList(DT_FIELD * Field)918 DtDumpFieldList (
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 
959 static void
DtDumpSubtableInfo(DT_SUBTABLE * Subtable,void * Context,void * ReturnValue)960 DtDumpSubtableInfo (
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 
973 static void
DtDumpSubtableTree(DT_SUBTABLE * Subtable,void * Context,void * ReturnValue)974 DtDumpSubtableTree (
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 
1001 void
DtDumpSubtableList(void)1002 DtDumpSubtableList (
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 
1039 void
DtWriteFieldToListing(UINT8 * Buffer,DT_FIELD * Field,UINT32 Length)1040 DtWriteFieldToListing (
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 
1099 void
DtWriteTableToListing(void)1100 DtWriteTableToListing (
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