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