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