]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/acpixtract/acpixtract.c
Import ACPICA 20110316.
[FreeBSD/FreeBSD.git] / tools / acpixtract / acpixtract.c
1
2 /******************************************************************************
3  *
4  * Module Name: acpixtract - convert ascii ACPI tables to binary
5  *
6  *****************************************************************************/
7
8 /*
9  * Copyright (C) 2000 - 2011, Intel Corp.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <ctype.h>
49
50
51 /* Note: This is a 32-bit program only */
52
53 #define VERSION             0x20110225
54 #define FIND_HEADER         0
55 #define EXTRACT_DATA        1
56 #define BUFFER_SIZE         256
57 #define HEADER_LINE_LENGTH  17  /* strlen ("FACP @ 0x737e1000") */
58
59 /* Local prototypes */
60
61 static void
62 CheckAscii (
63     char                    *Name,
64     int                     Count);
65
66 static void
67 NormalizeSignature (
68     char                    *Signature);
69
70 static unsigned int
71 GetNextInstance (
72     char                    *InputPathname,
73     char                    *Signature);
74
75 static int
76 ExtractTables (
77     char                    *InputPathname,
78     char                    *Signature,
79     unsigned int            MinimumInstances);
80
81 static size_t
82 GetTableHeader (
83     FILE                    *InputFile,
84     unsigned char           *OutputData);
85
86 static unsigned int
87 CountTableInstances (
88     char                    *InputPathname,
89     char                    *Signature);
90
91 static int
92 ListTables (
93     char                    *InputPathname);
94
95 static size_t
96 ConvertLine (
97     char                    *InputLine,
98     unsigned char           *OutputData);
99
100 static void
101 DisplayUsage (
102     void);
103
104
105 typedef struct acpi_table_header
106 {
107     char                    Signature[4];
108     int                     Length;
109     unsigned char           Revision;
110     unsigned char           Checksum;
111     char                    OemId[6];
112     char                    OemTableId[8];
113     int                     OemRevision;
114     char                    AslCompilerId[4];
115     int                     AslCompilerRevision;
116
117 } ACPI_TABLE_HEADER;
118
119 struct TableInfo
120 {
121     unsigned int            Signature;
122     unsigned int            Instances;
123     unsigned int            NextInstance;
124     struct TableInfo        *Next;
125 };
126
127 static struct TableInfo     *ListHead = NULL;
128 static char                 Filename[16];
129 static unsigned char        Data[16];
130
131
132 /******************************************************************************
133  *
134  * FUNCTION:    DisplayUsage
135  *
136  * DESCRIPTION: Usage message
137  *
138  ******************************************************************************/
139
140 static void
141 DisplayUsage (
142     void)
143 {
144
145     printf ("Usage: acpixtract [option] <InputFile>\n");
146     printf ("\nExtract binary ACPI tables from text acpidump output\n");
147     printf ("Default invocation extracts all DSDTs and SSDTs\n");
148     printf ("Version %8.8X\n\n", VERSION);
149     printf ("Options:\n");
150     printf (" -a                    Extract all tables, not just DSDT/SSDT\n");
151     printf (" -l                    List table summaries, do not extract\n");
152     printf (" -s<Signature>         Extract all tables named <Signature>\n");
153     printf ("\n");
154 }
155
156
157 /*******************************************************************************
158  *
159  * FUNCTION:    CheckAscii
160  *
161  * PARAMETERS:  Name                - Ascii string, at least as long as Count
162  *              Count               - Number of characters to check
163  *
164  * RETURN:      None
165  *
166  * DESCRIPTION: Ensure that the requested number of characters are printable
167  *              Ascii characters. Sets non-printable and null chars to <space>.
168  *
169  ******************************************************************************/
170
171 static void
172 CheckAscii (
173     char                    *Name,
174     int                     Count)
175 {
176     int                     i;
177
178
179     for (i = 0; i < Count; i++)
180     {
181         if (!Name[i] || !isprint ((int) Name[i]))
182         {
183             Name[i] = ' ';
184         }
185     }
186 }
187
188
189 /*******************************************************************************
190  *
191  * FUNCTION:    NormalizeSignature
192  *
193  * PARAMETERS:  Name                - Ascii string containing an ACPI signature
194  *
195  * RETURN:      None
196  *
197  * DESCRIPTION: Change "RSD PTR" to "RSDP"
198  *
199  ******************************************************************************/
200
201 static void
202 NormalizeSignature (
203     char                    *Signature)
204 {
205
206     if (!strncmp (Signature, "RSD ", 4))
207     {
208         Signature[3] = 'P';
209     }
210 }
211
212
213 /******************************************************************************
214  *
215  * FUNCTION:    ConvertLine
216  *
217  * PARAMETERS:  InputLine           - One line from the input acpidump file
218  *              OutputData          - Where the converted data is returned
219  *
220  * RETURN:      The number of bytes actually converted
221  *
222  * DESCRIPTION: Convert one line of ascii text binary (up to 16 bytes)
223  *
224  ******************************************************************************/
225
226 static size_t
227 ConvertLine (
228     char                    *InputLine,
229     unsigned char           *OutputData)
230 {
231     char                    *End;
232     int                     BytesConverted;
233     int                     Converted[16];
234     int                     i;
235
236
237     /* Terminate the input line at the end of the actual data (for sscanf) */
238
239     End = strstr (InputLine + 2, "  ");
240     if (!End)
241     {
242         return (0); /* Don't understand the format */
243     }
244     *End = 0;
245
246     /*
247      * Convert one line of table data, of the form:
248      * <offset>: <up to 16 bytes of hex data> <ASCII representation> <newline>
249      *
250      * Example:
251      * 02C0: 5F 53 42 5F 4C 4E 4B 44 00 12 13 04 0C FF FF 08  _SB_LNKD........
252      */
253     BytesConverted = sscanf (InputLine,
254         "%*s %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
255         &Converted[0],  &Converted[1],  &Converted[2],  &Converted[3],
256         &Converted[4],  &Converted[5],  &Converted[6],  &Converted[7],
257         &Converted[8],  &Converted[9],  &Converted[10], &Converted[11],
258         &Converted[12], &Converted[13], &Converted[14], &Converted[15]);
259
260     /* Pack converted data into a byte array */
261
262     for (i = 0; i < BytesConverted; i++)
263     {
264         OutputData[i] = (unsigned char) Converted[i];
265     }
266
267     return ((size_t) BytesConverted);
268 }
269
270
271 /******************************************************************************
272  *
273  * FUNCTION:    GetTableHeader
274  *
275  * PARAMETERS:  InputFile           - Handle for the input acpidump file
276  *              OutputData          - Where the table header is returned
277  *
278  * RETURN:      The actual number of bytes converted
279  *
280  * DESCRIPTION: Extract and convert an ACPI table header
281  *
282  ******************************************************************************/
283
284 static size_t
285 GetTableHeader (
286     FILE                    *InputFile,
287     unsigned char           *OutputData)
288 {
289     size_t                  BytesConverted;
290     size_t                  TotalConverted = 0;
291     char                    Buffer[BUFFER_SIZE];
292     int                     i;
293
294
295     /* Get the full 36 byte header, requires 3 lines */
296
297     for (i = 0; i < 3; i++)
298     {
299         if (!fgets (Buffer, BUFFER_SIZE, InputFile))
300         {
301             return (TotalConverted);
302         }
303
304         BytesConverted = ConvertLine (Buffer, OutputData);
305         TotalConverted += BytesConverted;
306         OutputData += 16;
307
308         if (BytesConverted != 16)
309         {
310             return (TotalConverted);
311         }
312     }
313
314     return (TotalConverted);
315 }
316
317
318 /******************************************************************************
319  *
320  * FUNCTION:    CountTableInstances
321  *
322  * PARAMETERS:  InputPathname       - Filename for acpidump file
323  *              Signature           - Requested signature to count
324  *
325  * RETURN:      The number of instances of the signature
326  *
327  * DESCRIPTION: Count the instances of tables with the given signature within
328  *              the input acpidump file.
329  *
330  ******************************************************************************/
331
332 static unsigned int
333 CountTableInstances (
334     char                    *InputPathname,
335     char                    *Signature)
336 {
337     char                    Buffer[BUFFER_SIZE];
338     FILE                    *InputFile;
339     unsigned int            Instances = 0;
340
341
342     InputFile = fopen (InputPathname, "rt");
343     if (!InputFile)
344     {
345         printf ("Could not open %s\n", InputPathname);
346         return (0);
347     }
348
349     /* Count the number of instances of this signature */
350
351     while (fgets (Buffer, BUFFER_SIZE, InputFile))
352     {
353         /* Ignore empty lines and lines that start with a space */
354
355         if ((Buffer[0] == ' ') ||
356             (Buffer[0] == '\n'))
357         {
358             continue;
359         }
360
361         NormalizeSignature (Buffer);
362         if (!strncmp (Buffer, Signature, 4))
363         {
364             Instances++;
365         }
366     }
367
368     fclose (InputFile);
369     return (Instances);
370 }
371
372
373 /******************************************************************************
374  *
375  * FUNCTION:    GetNextInstance
376  *
377  * PARAMETERS:  InputPathname       - Filename for acpidump file
378  *              Signature           - Requested ACPI signature
379  *
380  * RETURN:      The next instance number for this signature. Zero if this
381  *              is the first instance of this signature.
382  *
383  * DESCRIPTION: Get the next instance number of the specified table. If this
384  *              is the first instance of the table, create a new instance
385  *              block. Note: only SSDT and PSDT tables can have multiple
386  *              instances.
387  *
388  ******************************************************************************/
389
390 static unsigned int
391 GetNextInstance (
392     char                    *InputPathname,
393     char                    *Signature)
394 {
395     struct TableInfo        *Info;
396
397
398     Info = ListHead;
399     while (Info)
400     {
401         if (*(unsigned int *) Signature == Info->Signature)
402         {
403             break;
404         }
405
406         Info = Info->Next;
407     }
408
409     if (!Info)
410     {
411         /* Signature not found, create new table info block */
412
413         Info = malloc (sizeof (struct TableInfo));
414         if (!Info)
415         {
416             printf ("Could not allocate memory\n");
417             exit (0);
418         }
419
420         Info->Signature = *(unsigned int *) Signature;
421         Info->Instances = CountTableInstances (InputPathname, Signature);
422         Info->NextInstance = 1;
423         Info->Next = ListHead;
424         ListHead = Info;
425     }
426
427     if (Info->Instances > 1)
428     {
429         return (Info->NextInstance++);
430     }
431
432     return (0);
433 }
434
435
436 /******************************************************************************
437  *
438  * FUNCTION:    ExtractTables
439  *
440  * PARAMETERS:  InputPathname       - Filename for acpidump file
441  *              Signature           - Requested ACPI signature to extract.
442  *                                    NULL means extract ALL tables.
443  *              MinimumInstances    - Min instances that are acceptable
444  *
445  * RETURN:      Status
446  *
447  * DESCRIPTION: Convert text ACPI tables to binary
448  *
449  ******************************************************************************/
450
451 static int
452 ExtractTables (
453     char                    *InputPathname,
454     char                    *Signature,
455     unsigned int            MinimumInstances)
456 {
457     char                    Buffer[BUFFER_SIZE];
458     FILE                    *InputFile;
459     FILE                    *OutputFile = NULL;
460     size_t                  BytesWritten;
461     size_t                  TotalBytesWritten = 0;
462     size_t                  BytesConverted;
463     unsigned int            State = FIND_HEADER;
464     unsigned int            FoundTable = 0;
465     unsigned int            Instances = 0;
466     unsigned int            ThisInstance;
467     char                    ThisSignature[4];
468     int                     Status = 0;
469
470
471     /* Open input in text mode, output is in binary mode */
472
473     InputFile = fopen (InputPathname, "rt");
474     if (!InputFile)
475     {
476         printf ("Could not open %s\n", InputPathname);
477         return (-1);
478     }
479
480     if (Signature)
481     {
482         /* Are there enough instances of the table to continue? */
483
484         NormalizeSignature (Signature);
485
486         Instances = CountTableInstances (InputPathname, Signature);
487         if (Instances < MinimumInstances)
488         {
489             printf ("Table %s was not found in %s\n", Signature, InputPathname);
490             Status = -1;
491             goto CleanupAndExit;
492         }
493
494         if (Instances == 0)
495         {
496             goto CleanupAndExit;
497         }
498     }
499
500     /* Convert all instances of the table to binary */
501
502     while (fgets (Buffer, BUFFER_SIZE, InputFile))
503     {
504         switch (State)
505         {
506         case FIND_HEADER:
507
508             /* Ignore lines that are too short to be header lines */
509
510             if (strlen (Buffer) < HEADER_LINE_LENGTH)
511             {
512                 continue;
513             }
514
515             /* Ignore empty lines and lines that start with a space */
516
517             if ((Buffer[0] == ' ') ||
518                 (Buffer[0] == '\n'))
519             {
520                 continue;
521             }
522
523             /* Ignore lines that are not of the form "ABCD @ " */
524
525             if ((Buffer[4] != ' ') ||
526                 (Buffer[5] != '@') ||
527                 (Buffer[6] != ' '))
528             {
529                 continue;
530             }
531
532             NormalizeSignature (Buffer);
533             strncpy (ThisSignature, Buffer, 4);
534
535             if (Signature)
536             {
537                 /* Ignore signatures that don't match */
538
539                 if (strncmp (ThisSignature, Signature, 4))
540                 {
541                     continue;
542                 }
543             }
544
545             /*
546              * Get the instance number for this signature. Only the
547              * SSDT and PSDT tables can have multiple instances.
548              */
549             ThisInstance = GetNextInstance (InputPathname, ThisSignature);
550
551             /* Build an output filename and create/open the output file */
552
553             if (ThisInstance > 0)
554             {
555                 sprintf (Filename, "%4.4s%u.dat", ThisSignature, ThisInstance);
556             }
557             else
558             {
559                 sprintf (Filename, "%4.4s.dat", ThisSignature);
560             }
561
562             OutputFile = fopen (Filename, "w+b");
563             if (!OutputFile)
564             {
565                 printf ("Could not open %s\n", Filename);
566                 Status = -1;
567                 goto CleanupAndExit;
568             }
569
570             State = EXTRACT_DATA;
571             TotalBytesWritten = 0;
572             FoundTable = 1;
573             continue;
574
575         case EXTRACT_DATA:
576
577             /* Empty line or non-data line terminates the data */
578
579             if ((Buffer[0] == '\n') ||
580                 (Buffer[0] != ' '))
581             {
582                 fclose (OutputFile);
583                 OutputFile = NULL;
584                 State = FIND_HEADER;
585
586                 printf ("Acpi table [%4.4s] - %u bytes written to %s\n",
587                     ThisSignature, (unsigned int) TotalBytesWritten, Filename);
588                 continue;
589             }
590
591             /* Convert the ascii data (one line of text) to binary */
592
593             BytesConverted = ConvertLine (Buffer, Data);
594
595             /* Write the binary data */
596
597             BytesWritten = fwrite (Data, 1, BytesConverted, OutputFile);
598             if (BytesWritten != BytesConverted)
599             {
600                 printf ("Write error on %s\n", Filename);
601                 fclose (OutputFile);
602                 OutputFile = NULL;
603                 Status = -1;
604                 goto CleanupAndExit;
605             }
606
607             TotalBytesWritten += BytesConverted;
608             continue;
609
610         default:
611             Status = -1;
612             goto CleanupAndExit;
613         }
614     }
615
616     if (!FoundTable)
617     {
618         printf ("Table %s was not found in %s\n", Signature, InputPathname);
619     }
620
621
622 CleanupAndExit:
623
624     if (OutputFile)
625     {
626         fclose (OutputFile);
627         if (State == EXTRACT_DATA)
628         {
629             /* Received an EOF while extracting data */
630
631             printf ("Acpi table [%4.4s] - %u bytes written to %s\n",
632                 ThisSignature, (unsigned int) TotalBytesWritten, Filename);
633         }
634     }
635
636     fclose (InputFile);
637     return (Status);
638 }
639
640
641 /******************************************************************************
642  *
643  * FUNCTION:    ListTables
644  *
645  * PARAMETERS:  InputPathname       - Filename for acpidump file
646  *
647  * RETURN:      Status
648  *
649  * DESCRIPTION: Display info for all ACPI tables found in input. Does not
650  *              perform an actual extraction of the tables.
651  *
652  ******************************************************************************/
653
654 static int
655 ListTables (
656     char                    *InputPathname)
657 {
658     FILE                    *InputFile;
659     char                    Buffer[BUFFER_SIZE];
660     size_t                  HeaderSize;
661     unsigned char           Header[48];
662     int                     TableCount = 0;
663     ACPI_TABLE_HEADER       *TableHeader = (ACPI_TABLE_HEADER *) (void *) Header;
664
665
666     /* Open input in text mode, output is in binary mode */
667
668     InputFile = fopen (InputPathname, "rt");
669     if (!InputFile)
670     {
671         printf ("Could not open %s\n", InputPathname);
672         return (-1);
673     }
674
675     /* Dump the headers for all tables found in the input file */
676
677     printf ("\nSignature Length Revision  OemId     OemTableId"
678             "   OemRevision CompilerId CompilerRevision\n\n");
679
680     while (fgets (Buffer, BUFFER_SIZE, InputFile))
681     {
682         /* Ignore empty lines and lines that start with a space */
683
684         if ((Buffer[0] == ' ') ||
685             (Buffer[0] == '\n'))
686         {
687             continue;
688         }
689
690         /* Get the 36 byte header and display the fields */
691
692         HeaderSize = GetTableHeader (InputFile, Header);
693         if (HeaderSize < 16)
694         {
695             continue;
696         }
697
698         /* RSDP has an oddball signature and header */
699
700         if (!strncmp (TableHeader->Signature, "RSD PTR ", 8))
701         {
702             CheckAscii ((char *) &Header[9], 6);
703             printf ("%8.4s                   \"%6.6s\"\n", "RSDP", &Header[9]);
704             TableCount++;
705             continue;
706         }
707
708         /* Minimum size for table with standard header */
709
710         if (HeaderSize < 36)
711         {
712             continue;
713         }
714
715         /* Signature and Table length */
716
717         TableCount++;
718         printf ("%8.4s % 7d", TableHeader->Signature, TableHeader->Length);
719
720         /* FACS has only signature and length */
721
722         if (!strncmp (TableHeader->Signature, "FACS", 4))
723         {
724             printf ("\n");
725             continue;
726         }
727
728         /* OEM IDs and Compiler IDs */
729
730         CheckAscii (TableHeader->OemId, 6);
731         CheckAscii (TableHeader->OemTableId, 8);
732         CheckAscii (TableHeader->AslCompilerId, 4);
733
734         printf ("     %2.2X    \"%6.6s\"  \"%8.8s\"    %8.8X    \"%4.4s\"     %8.8X\n",
735             TableHeader->Revision, TableHeader->OemId,
736             TableHeader->OemTableId, TableHeader->OemRevision,
737             TableHeader->AslCompilerId, TableHeader->AslCompilerRevision);
738     }
739
740     printf ("\nFound %u ACPI tables [%8.8X]\n", TableCount, VERSION);
741     fclose (InputFile);
742     return (0);
743 }
744
745
746 /******************************************************************************
747  *
748  * FUNCTION:    main
749  *
750  * DESCRIPTION: C main function
751  *
752  ******************************************************************************/
753
754 int
755 main (
756     int                     argc,
757     char                    *argv[])
758 {
759     int                     Status;
760
761
762     if (argc < 2)
763     {
764         DisplayUsage ();
765         return (0);
766     }
767
768     if (argv[1][0] == '-')
769     {
770         if (argc < 3)
771         {
772             DisplayUsage ();
773             return (0);
774         }
775
776         switch (argv[1][1])
777         {
778         case 'a':
779
780             /* Extract all tables found */
781
782             return (ExtractTables (argv[2], NULL, 0));
783
784         case 'l':
785
786             /* List tables only, do not extract */
787
788             return (ListTables (argv[2]));
789
790         case 's':
791
792             /* Extract only tables with this signature */
793
794             return (ExtractTables (argv[2], &argv[1][2], 1));
795
796         default:
797             DisplayUsage ();
798             return (0);
799         }
800     }
801
802     /*
803      * Default output is the DSDT and all SSDTs. One DSDT is required,
804      * any SSDTs are optional.
805      */
806     Status = ExtractTables (argv[1], "DSDT", 1);
807     if (Status)
808     {
809         return (Status);
810     }
811
812     Status = ExtractTables (argv[1], "SSDT", 0);
813     return (Status);
814 }
815
816