xref: /freebsd/sys/contrib/dev/acpica/compiler/dtio.c (revision aa0a1e58)
1 /******************************************************************************
2  *
3  * Module Name: dtio.c - File I/O support for data table compiler
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2011, 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 #define __DTIO_C__
45 
46 #include <contrib/dev/acpica/compiler/aslcompiler.h>
47 #include <contrib/dev/acpica/compiler/dtcompiler.h>
48 
49 #define _COMPONENT          DT_COMPILER
50         ACPI_MODULE_NAME    ("dtio")
51 
52 
53 /* Local prototypes */
54 
55 static char *
56 DtTrim (
57     char                    *String);
58 
59 static void
60 DtLinkField (
61     DT_FIELD                *Field);
62 
63 static void
64 DtMergeField (
65     char                    *Value);
66 
67 static ACPI_STATUS
68 DtParseLine (
69     char                    *LineBuffer,
70     UINT32                  Line,
71     UINT32                  Offset);
72 
73 UINT32
74 DtGetNextLine (
75     FILE                    *Handle);
76 
77 static void
78 DtWriteBinary (
79     DT_SUBTABLE             *Subtable,
80     void                    *Context,
81     void                    *ReturnValue);
82 
83 static void
84 DtDumpBuffer (
85     UINT32                  FileId,
86     UINT8                   *Buffer,
87     UINT32                  Offset,
88     UINT32                  Length);
89 
90 
91 /* States for DtGetNextLine */
92 
93 #define DT_NORMAL_TEXT              0
94 #define DT_START_QUOTED_STRING      1
95 #define DT_START_COMMENT            2
96 #define DT_SLASH_ASTERISK_COMMENT   3
97 #define DT_SLASH_SLASH_COMMENT      4
98 #define DT_END_COMMENT              5
99 
100 static UINT32  Gbl_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 *
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 (!ACPI_STRCMP (String, " "))
128     {
129         ReturnString = UtLocalCalloc (1);
130         return (ReturnString);
131     }
132 
133     /* Setup pointers to start and end of input string */
134 
135     Start = String;
136     End = String + ACPI_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 == '\r' || *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 = UtLocalCalloc (Length + 1);
178     if (ACPI_STRLEN (Start))
179     {
180         ACPI_STRNCPY (ReturnString, Start, Length);
181     }
182 
183     ReturnString[Length] = 0;
184     return (ReturnString);
185 }
186 
187 
188 /******************************************************************************
189  *
190  * FUNCTION:    DtLinkField
191  *
192  * PARAMETERS:  Field               - New field object to link
193  *
194  * RETURN:      None
195  *
196  * DESCRIPTION: Link one field name and value to the list
197  *
198  *****************************************************************************/
199 
200 static void
201 DtLinkField (
202     DT_FIELD                *Field)
203 {
204     DT_FIELD                *Prev;
205     DT_FIELD                *Next;
206 
207 
208     Prev = Next = Gbl_FieldList;
209 
210     while (Next)
211     {
212         Prev = Next;
213         Next = Next->Next;
214     }
215 
216     if (Prev)
217     {
218         Prev->Next = Field;
219     }
220     else
221     {
222         Gbl_FieldList = Field;
223     }
224 }
225 
226 
227 /******************************************************************************
228  *
229  * FUNCTION:    DtMergeField
230  *
231  * PARAMETERS:  Value               - Merge this line into previous one
232  *
233  * RETURN:      None
234  *
235  * DESCRIPTION: Merge a field value to the previous one,
236  *              probably for a multi-line buffer definition.
237  *
238  *****************************************************************************/
239 
240 static void
241 DtMergeField (
242     char                    *Value)
243 {
244     DT_FIELD                *Prev;
245     DT_FIELD                *Next;
246     char                    *NewValue;
247     UINT32                  PrevLength;
248     UINT32                  ThisLength;
249 
250 
251     Prev = Next = Gbl_FieldList;
252 
253     while (Next)
254     {
255         Prev = Next;
256         Next = Next->Next;
257     }
258 
259     if (Prev)
260     {
261         PrevLength = ACPI_STRLEN (Prev->Value);
262         ThisLength = ACPI_STRLEN (Value);
263 
264         /* Add two for: separator + NULL terminator */
265 
266         NewValue = UtLocalCalloc (PrevLength + ThisLength + 2);
267         ACPI_STRNCPY (NewValue, Prev->Value, PrevLength);
268         NewValue[PrevLength] = ' ';
269 
270         ACPI_STRNCPY ((NewValue + PrevLength + 1), Value, ThisLength);
271         ACPI_FREE (Prev->Value);
272         Prev->Value = NewValue;
273     }
274 }
275 
276 
277 /******************************************************************************
278  *
279  * FUNCTION:    DtParseLine
280  *
281  * PARAMETERS:  LineBuffer          - Current source code line
282  *              Line                - Current line number in the source
283  *              Offset              - Current byte offset of the line
284  *
285  * RETURN:      Status
286  *
287  * DESCRIPTION: Parse one source line
288  *
289  *****************************************************************************/
290 
291 static ACPI_STATUS
292 DtParseLine (
293     char                    *LineBuffer,
294     UINT32                  Line,
295     UINT32                  Offset)
296 {
297     char                    *Start;
298     char                    *End;
299     char                    *TmpName;
300     char                    *TmpValue;
301     char                    *Name;
302     char                    *Value;
303     char                    *Colon;
304     UINT32                  Length;
305     DT_FIELD                *Field;
306     UINT32                  Column;
307     UINT32                  NameColumn;
308 
309 
310     if (!LineBuffer)
311     {
312         return (AE_OK);
313     }
314 
315     /* All lines after "Raw Table Data" are ingored */
316 
317     if (strstr (LineBuffer, ACPI_RAW_TABLE_DATA_HEADER))
318     {
319         return (AE_NOT_FOUND);
320     }
321 
322     Colon = strchr (LineBuffer, ':');
323     if (!Colon)
324     {
325         return (AE_OK);
326     }
327 
328     Start = LineBuffer;
329     End = Colon;
330 
331     while (Start < Colon)
332     {
333         if (*Start == ' ')
334         {
335             Start++;
336             continue;
337         }
338 
339         /* Found left bracket, go to the right bracket */
340 
341         if (*Start == '[')
342         {
343             while (Start < Colon && *Start != ']')
344             {
345                 Start++;
346             }
347 
348             if (Start == Colon)
349             {
350                 break;
351             }
352 
353             Start++;
354             continue;
355         }
356 
357         break;
358     }
359 
360     /*
361      * There are two column values. One for the field name,
362      * and one for the field value.
363      */
364     Column = ACPI_PTR_DIFF (Colon, LineBuffer) + 3;
365     NameColumn = ACPI_PTR_DIFF (Start, LineBuffer) + 1;
366 
367     Length = ACPI_PTR_DIFF (End, Start);
368 
369     TmpName = UtLocalCalloc (Length + 1);
370     ACPI_STRNCPY (TmpName, Start, Length);
371     Name = DtTrim (TmpName);
372     ACPI_FREE (TmpName);
373 
374     Start = End = (Colon + 1);
375 
376     while (*End)
377     {
378         /* Found left quotation, go to the right quotation and break */
379 
380         if (*End == '"')
381         {
382             End++;
383             while (*End && (*End != '"'))
384             {
385                 End++;
386             }
387 
388             End++;
389             break;
390         }
391 
392         /*
393          * Special "comment" fields at line end, ignore them.
394          * Note: normal slash-slash and slash-asterisk comments are
395          * stripped already by the DtGetNextLine parser.
396          *
397          * TBD: Perhaps DtGetNextLine should parse the following type
398          * of comments also.
399          */
400         if (*End == '(' ||
401             *End == '<')
402         {
403             break;
404         }
405 
406         End++;
407     }
408 
409     Length = ACPI_PTR_DIFF (End, Start);
410     TmpValue = UtLocalCalloc (Length + 1);
411 
412     ACPI_STRNCPY (TmpValue, Start, Length);
413     Value = DtTrim (TmpValue);
414     ACPI_FREE (TmpValue);
415 
416     if (ACPI_STRLEN (Name) && Value)
417     {
418         Field = UtLocalCalloc (sizeof (DT_FIELD));
419         Field->Name = Name;
420         Field->Value = Value;
421         Field->Line = Line;
422         Field->ByteOffset = Offset;
423         Field->NameColumn = NameColumn;
424         Field->Column = Column;
425 
426         DtLinkField (Field);
427     }
428     else if (!ACPI_STRLEN (Name))
429     {
430         /* Handle multi-line buffers (length > 16) */
431 
432         DtMergeField (Value);
433     }
434     else
435     {
436         ACPI_FREE (Name);
437         ACPI_FREE (Value);
438     }
439 
440     return (AE_OK);
441 }
442 
443 
444 /******************************************************************************
445  *
446  * FUNCTION:    DtGetNextLine
447  *
448  * PARAMETERS:  Handle              - Open file handle for the source file
449  *
450  * RETURN:      Filled line buffer and offset of start-of-line (zero on EOF)
451  *
452  * DESCRIPTION: Get the next valid source line. Removes all comments.
453  *              Ignores empty lines.
454  *
455  * Handles both slash-asterisk and slash-slash comments.
456  * Also, quoted strings, but no escapes within.
457  *
458  * Line is returned in Gbl_CurrentLineBuffer.
459  * Line number in original file is returned in Gbl_CurrentLineNumber.
460  *
461  *****************************************************************************/
462 
463 UINT32
464 DtGetNextLine (
465     FILE                    *Handle)
466 {
467     UINT32                  State = DT_NORMAL_TEXT;
468     UINT32                  CurrentLineOffset;
469     UINT32                  i;
470     char                    c;
471 
472 
473     for (i = 0; i < ASL_LINE_BUFFER_SIZE;)
474     {
475         c = (char) getc (Handle);
476         if (c == EOF)
477         {
478             switch (State)
479             {
480             case DT_START_QUOTED_STRING:
481             case DT_SLASH_ASTERISK_COMMENT:
482             case DT_SLASH_SLASH_COMMENT:
483 
484                 AcpiOsPrintf ("**** EOF within comment/string %u\n", State);
485                 break;
486 
487             default:
488                 break;
489             }
490 
491             return (0);
492         }
493 
494         switch (State)
495         {
496         case DT_NORMAL_TEXT:
497 
498             /* Normal text, insert char into line buffer */
499 
500             Gbl_CurrentLineBuffer[i] = c;
501             switch (c)
502             {
503             case '/':
504                 State = DT_START_COMMENT;
505                 break;
506 
507             case '"':
508                 State = DT_START_QUOTED_STRING;
509                 i++;
510                 break;
511 
512             case '\n':
513                 CurrentLineOffset = Gbl_NextLineOffset;
514                 Gbl_NextLineOffset = (UINT32) ftell (Handle);
515                 Gbl_CurrentLineNumber++;
516 
517                 /* Exit if line is complete. Ignore blank lines */
518 
519                 if (i != 0)
520                 {
521                     Gbl_CurrentLineBuffer[i+1] = 0; /* Terminate line */
522                     return (CurrentLineOffset);
523                 }
524                 break;
525 
526             default:
527                 i++;
528                 break;
529             }
530             break;
531 
532         case DT_START_QUOTED_STRING:
533 
534             /* Insert raw chars until end of quoted string */
535 
536             Gbl_CurrentLineBuffer[i] = c;
537             i++;
538 
539             if (c == '"')
540             {
541                 State = DT_NORMAL_TEXT;
542             }
543             break;
544 
545         case DT_START_COMMENT:
546 
547             /* Open comment if this character is an asterisk or slash */
548 
549             switch (c)
550             {
551             case '*':
552                 State = DT_SLASH_ASTERISK_COMMENT;
553                 break;
554 
555             case '/':
556                 State = DT_SLASH_SLASH_COMMENT;
557                 break;
558 
559             default:    /* Not a comment */
560                 i++;    /* Save the preceeding slash */
561                 Gbl_CurrentLineBuffer[i] = c;
562                 i++;
563                 State = DT_NORMAL_TEXT;
564                 break;
565             }
566             break;
567 
568         case DT_SLASH_ASTERISK_COMMENT:
569 
570             /* Ignore chars until an asterisk-slash is found */
571 
572             switch (c)
573             {
574             case '\n':
575                 Gbl_NextLineOffset = (UINT32) ftell (Handle);
576                 Gbl_CurrentLineNumber++;
577                 break;
578 
579             case '*':
580                 State = DT_END_COMMENT;
581                 break;
582 
583             default:
584                 break;
585             }
586             break;
587 
588         case DT_SLASH_SLASH_COMMENT:
589 
590             /* Ignore chars until end-of-line */
591 
592             if (c == '\n')
593             {
594                 /* We will exit via the NORMAL_TEXT path */
595 
596                 ungetc (c, Handle);
597                 State = DT_NORMAL_TEXT;
598             }
599             break;
600 
601         case DT_END_COMMENT:
602 
603             /* End comment if this char is a slash */
604 
605             switch (c)
606             {
607             case '/':
608                 State = DT_NORMAL_TEXT;
609                 break;
610 
611             case '\n':
612                 CurrentLineOffset = Gbl_NextLineOffset;
613                 Gbl_NextLineOffset = (UINT32) ftell (Handle);
614                 Gbl_CurrentLineNumber++;
615                 break;
616 
617             case '*':
618                 /* Consume all adjacent asterisks */
619                 break;
620 
621             default:
622                 State = DT_SLASH_ASTERISK_COMMENT;
623                 break;
624             }
625             break;
626 
627         default:
628             DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, "Unknown input state");
629             return (0);
630         }
631     }
632 
633     printf ("ERROR - Input line is too long (max %u)\n", ASL_LINE_BUFFER_SIZE);
634     return (0);
635 }
636 
637 
638 /******************************************************************************
639  *
640  * FUNCTION:    DtScanFile
641  *
642  * PARAMETERS:  Handle              - Open file handle for the source file
643  *
644  * RETURN:      Pointer to start of the constructed parse tree.
645  *
646  * DESCRIPTION: Scan source file, link all field names and values
647  *              to the global parse tree: Gbl_FieldList
648  *
649  *****************************************************************************/
650 
651 DT_FIELD *
652 DtScanFile (
653     FILE                    *Handle)
654 {
655     ACPI_STATUS             Status;
656     UINT32                  Offset;
657 
658 
659     ACPI_FUNCTION_NAME (DtScanFile);
660 
661 
662     /* Get the file size */
663 
664     Gbl_InputByteCount = DtGetFileSize (Handle);
665 
666     Gbl_CurrentLineNumber = 0;
667     Gbl_CurrentLineOffset = 0;
668     Gbl_NextLineOffset = 0;
669 
670     /* Scan line-by-line */
671 
672     while ((Offset = DtGetNextLine (Handle)))
673     {
674         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Line %2.2u/%4.4X - %s",
675             Gbl_CurrentLineNumber, Offset, Gbl_CurrentLineBuffer));
676 
677         Status = DtParseLine (Gbl_CurrentLineBuffer, Gbl_CurrentLineNumber, Offset);
678         if (Status == AE_NOT_FOUND)
679         {
680             break;
681         }
682     }
683 
684     return (Gbl_FieldList);
685 }
686 
687 
688 /*
689  * Output functions
690  */
691 
692 /******************************************************************************
693  *
694  * FUNCTION:    DtWriteBinary
695  *
696  * PARAMETERS:  DT_WALK_CALLBACK
697  *
698  * RETURN:      Status
699  *
700  * DESCRIPTION: Write one subtable of a binary ACPI table
701  *
702  *****************************************************************************/
703 
704 static void
705 DtWriteBinary (
706     DT_SUBTABLE             *Subtable,
707     void                    *Context,
708     void                    *ReturnValue)
709 {
710 
711     FlWriteFile (ASL_FILE_AML_OUTPUT, Subtable->Buffer, Subtable->Length);
712 }
713 
714 
715 /******************************************************************************
716  *
717  * FUNCTION:    DtOutputBinary
718  *
719  * PARAMETERS:
720  *
721  * RETURN:      Status
722  *
723  * DESCRIPTION: Write entire binary ACPI table (result of compilation)
724  *
725  *****************************************************************************/
726 
727 void
728 DtOutputBinary (
729     DT_SUBTABLE             *RootTable)
730 {
731 
732     if (!RootTable)
733     {
734         return;
735     }
736 
737     /* Walk the entire parse tree, emitting the binary data */
738 
739     DtWalkTableTree (RootTable, DtWriteBinary, NULL, NULL);
740     Gbl_TableLength = DtGetFileSize (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle);
741 }
742 
743 
744 /*
745  * Listing support
746  */
747 
748 /******************************************************************************
749  *
750  * FUNCTION:    DtDumpBuffer
751  *
752  * PARAMETERS:  FileID              - Where to write buffer data
753  *              Buffer              - Buffer to dump
754  *              Offset              - Offset in current table
755  *              Length              - Buffer Length
756  *
757  * RETURN:      None
758  *
759  * DESCRIPTION: Another copy of DumpBuffer routine (unfortunately).
760  *
761  * TBD: merge dump buffer routines
762  *
763  *****************************************************************************/
764 
765 static void
766 DtDumpBuffer (
767     UINT32                  FileId,
768     UINT8                   *Buffer,
769     UINT32                  Offset,
770     UINT32                  Length)
771 {
772     UINT32                  i;
773     UINT32                  j;
774     UINT8                   BufChar;
775 
776 
777     FlPrintFile (FileId, "Output: [%3.3Xh %4.4d% 3d] ",
778         Offset, Offset, Length);
779 
780     i = 0;
781     while (i < Length)
782     {
783         if (i >= 16)
784         {
785             FlPrintFile (FileId, "%23s", "");
786         }
787 
788         /* Print 16 hex chars */
789 
790         for (j = 0; j < 16;)
791         {
792             if (i + j >= Length)
793             {
794                 /* Dump fill spaces */
795 
796                 FlPrintFile (FileId, "   ");
797                 j++;
798                 continue;
799             }
800 
801             FlPrintFile (FileId, "%02X ", Buffer[i+j]);
802             j++;
803         }
804 
805         FlPrintFile (FileId, " ");
806         for (j = 0; j < 16; j++)
807         {
808             if (i + j >= Length)
809             {
810                 FlPrintFile (FileId, "\n\n");
811                 return;
812             }
813 
814             BufChar = Buffer[(ACPI_SIZE) i + j];
815             if (ACPI_IS_PRINT (BufChar))
816             {
817                 FlPrintFile (FileId, "%c", BufChar);
818             }
819             else
820             {
821                 FlPrintFile (FileId, ".");
822             }
823         }
824 
825         /* Done with that line. */
826 
827         FlPrintFile (FileId, "\n");
828         i += 16;
829     }
830 
831     FlPrintFile (FileId, "\n\n");
832 }
833 
834 
835 /******************************************************************************
836  *
837  * FUNCTION:    DtWriteFieldToListing
838  *
839  * PARAMETERS:  Buffer              - Contains the compiled data
840  *              Field               - Field node for the input line
841  *              Length              - Length of the output data
842  *
843  * RETURN:      None
844  *
845  * DESCRIPTION: Write one field to the listing file (if listing is enabled).
846  *
847  *****************************************************************************/
848 
849 void
850 DtWriteFieldToListing (
851     UINT8                   *Buffer,
852     DT_FIELD                *Field,
853     UINT32                  Length)
854 {
855     UINT8                   FileByte;
856 
857 
858     if (!Gbl_ListingFlag || !Field)
859     {
860         return;
861     }
862 
863     /* Dump the original source line */
864 
865     FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Input:  ");
866     FlSeekFile (ASL_FILE_INPUT, Field->ByteOffset);
867 
868     while (FlReadFile (ASL_FILE_INPUT, &FileByte, 1) == AE_OK)
869     {
870         FlWriteFile (ASL_FILE_LISTING_OUTPUT, &FileByte, 1);
871         if (FileByte == '\n')
872         {
873             break;
874         }
875     }
876 
877     /* Dump the line as parsed and represented internally */
878 
879     FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Parsed: %*s : %s\n",
880         Field->Column-4, Field->Name, Field->Value);
881 
882     /* Dump the hex data that will be output for this field */
883 
884     DtDumpBuffer (ASL_FILE_LISTING_OUTPUT, Buffer, Field->TableOffset, Length);
885 }
886 
887 
888 /******************************************************************************
889  *
890  * FUNCTION:    DtWriteTableToListing
891  *
892  * PARAMETERS:  None
893  *
894  * RETURN:      None
895  *
896  * DESCRIPTION: Write the entire compiled table to the listing file
897  *              in hex format
898  *
899  *****************************************************************************/
900 
901 void
902 DtWriteTableToListing (
903     void)
904 {
905     UINT8                   *Buffer;
906 
907 
908     if (!Gbl_ListingFlag)
909     {
910         return;
911     }
912 
913     /* Read the entire table from the output file */
914 
915     Buffer = UtLocalCalloc (Gbl_TableLength);
916     FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
917     FlReadFile (ASL_FILE_AML_OUTPUT, Buffer, Gbl_TableLength);
918 
919     /* Dump the raw table data */
920 
921     AcpiOsRedirectOutput (Gbl_Files[ASL_FILE_LISTING_OUTPUT].Handle);
922 
923     AcpiOsPrintf ("\n%s: Length %d (0x%X)\n\n",
924         ACPI_RAW_TABLE_DATA_HEADER, Gbl_TableLength, Gbl_TableLength);
925     AcpiUtDumpBuffer2 (Buffer, Gbl_TableLength, DB_BYTE_DISPLAY);
926 
927     AcpiOsRedirectOutput (stdout);
928 }
929