]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/acpixtract/acpixtract.c
Import ACPICA 20120111.
[FreeBSD/FreeBSD.git] / tools / acpixtract / acpixtract.c
1 /******************************************************************************
2  *
3  * Module Name: acpixtract - convert ascii ACPI tables to binary
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2012, 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 "acpi.h"
45 #include "accommon.h"
46 #include "acapps.h"
47
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <ctype.h>
52
53 /* Local prototypes */
54
55 static void
56 AxStrlwr (
57     char                    *String);
58
59 static void
60 AxCheckAscii (
61     char                    *Name,
62     int                     Count);
63
64 static void
65 AxNormalizeSignature (
66     char                    *Signature);
67
68 static unsigned int
69 AxGetNextInstance (
70     char                    *InputPathname,
71     char                    *Signature);
72
73 static size_t
74 AxGetTableHeader (
75     FILE                    *InputFile,
76     unsigned char           *OutputData);
77
78 static unsigned int
79 AxCountTableInstances (
80     char                    *InputPathname,
81     char                    *Signature);
82
83 int
84 AxExtractTables (
85     char                    *InputPathname,
86     char                    *Signature,
87     unsigned int            MinimumInstances);
88
89 int
90 AxListTables (
91     char                    *InputPathname);
92
93 static size_t
94 AxConvertLine (
95     char                    *InputLine,
96     unsigned char           *OutputData);
97
98
99 typedef struct AxTableInfo
100 {
101     UINT32                  Signature;
102     unsigned int            Instances;
103     unsigned int            NextInstance;
104     struct AxTableInfo      *Next;
105
106 } AX_TABLE_INFO;
107
108 /* Extraction states */
109
110 #define AX_STATE_FIND_HEADER        0
111 #define AX_STATE_EXTRACT_DATA       1
112
113 /* Miscellaneous constants */
114
115 #define AX_LINE_BUFFER_SIZE         256
116 #define AX_MIN_TABLE_NAME_LENGTH    6   /* strlen ("DSDT @") */
117
118
119 static AX_TABLE_INFO        *AxTableListHead = NULL;
120 static char                 Filename[16];
121 static unsigned char        Data[16];
122 static char                 LineBuffer[AX_LINE_BUFFER_SIZE];
123 static char                 HeaderBuffer[AX_LINE_BUFFER_SIZE];
124 static char                 InstanceBuffer[AX_LINE_BUFFER_SIZE];
125
126
127 /*******************************************************************************
128  *
129  * FUNCTION:    AxStrlwr
130  *
131  * PARAMETERS:  String              - Ascii string
132  *
133  * RETURN:      None
134  *
135  * DESCRIPTION: String lowercase function.
136  *
137  ******************************************************************************/
138
139 static void
140 AxStrlwr (
141     char                    *String)
142 {
143
144     while (*String)
145     {
146         *String = (char) tolower ((int) *String);
147         String++;
148     }
149 }
150
151
152 /*******************************************************************************
153  *
154  * FUNCTION:    AxCheckAscii
155  *
156  * PARAMETERS:  Name                - Ascii string, at least as long as Count
157  *              Count               - Number of characters to check
158  *
159  * RETURN:      None
160  *
161  * DESCRIPTION: Ensure that the requested number of characters are printable
162  *              Ascii characters. Sets non-printable and null chars to <space>.
163  *
164  ******************************************************************************/
165
166 static void
167 AxCheckAscii (
168     char                    *Name,
169     int                     Count)
170 {
171     int                     i;
172
173
174     for (i = 0; i < Count; i++)
175     {
176         if (!Name[i] || !isprint ((int) Name[i]))
177         {
178             Name[i] = ' ';
179         }
180     }
181 }
182
183
184 /*******************************************************************************
185  *
186  * FUNCTION:    AxNormalizeSignature
187  *
188  * PARAMETERS:  Name                - Ascii string containing an ACPI signature
189  *
190  * RETURN:      None
191  *
192  * DESCRIPTION: Change "RSD PTR" to "RSDP"
193  *
194  ******************************************************************************/
195
196 static void
197 AxNormalizeSignature (
198     char                    *Signature)
199 {
200
201     if (!strncmp (Signature, "RSD ", 4))
202     {
203         Signature[3] = 'P';
204     }
205 }
206
207
208 /******************************************************************************
209  *
210  * FUNCTION:    AxConvertLine
211  *
212  * PARAMETERS:  InputLine           - One line from the input acpidump file
213  *              OutputData          - Where the converted data is returned
214  *
215  * RETURN:      The number of bytes actually converted
216  *
217  * DESCRIPTION: Convert one line of ascii text binary (up to 16 bytes)
218  *
219  ******************************************************************************/
220
221 static size_t
222 AxConvertLine (
223     char                    *InputLine,
224     unsigned char           *OutputData)
225 {
226     char                    *End;
227     int                     BytesConverted;
228     int                     Converted[16];
229     int                     i;
230
231
232     /* Terminate the input line at the end of the actual data (for sscanf) */
233
234     End = strstr (InputLine + 2, "  ");
235     if (!End)
236     {
237         return (0); /* Don't understand the format */
238     }
239     *End = 0;
240
241     /*
242      * Convert one line of table data, of the form:
243      * <offset>: <up to 16 bytes of hex data> <ASCII representation> <newline>
244      *
245      * Example:
246      * 02C0: 5F 53 42 5F 4C 4E 4B 44 00 12 13 04 0C FF FF 08  _SB_LNKD........
247      */
248     BytesConverted = sscanf (InputLine,
249         "%*s %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
250         &Converted[0],  &Converted[1],  &Converted[2],  &Converted[3],
251         &Converted[4],  &Converted[5],  &Converted[6],  &Converted[7],
252         &Converted[8],  &Converted[9],  &Converted[10], &Converted[11],
253         &Converted[12], &Converted[13], &Converted[14], &Converted[15]);
254
255     /* Pack converted data into a byte array */
256
257     for (i = 0; i < BytesConverted; i++)
258     {
259         OutputData[i] = (unsigned char) Converted[i];
260     }
261
262     return ((size_t) BytesConverted);
263 }
264
265
266 /******************************************************************************
267  *
268  * FUNCTION:    AxGetTableHeader
269  *
270  * PARAMETERS:  InputFile           - Handle for the input acpidump file
271  *              OutputData          - Where the table header is returned
272  *
273  * RETURN:      The actual number of bytes converted
274  *
275  * DESCRIPTION: Extract and convert an ACPI table header
276  *
277  ******************************************************************************/
278
279 static size_t
280 AxGetTableHeader (
281     FILE                    *InputFile,
282     unsigned char           *OutputData)
283 {
284     size_t                  BytesConverted;
285     size_t                  TotalConverted = 0;
286     int                     i;
287
288
289     /* Get the full 36 byte ACPI table header, requires 3 input text lines */
290
291     for (i = 0; i < 3; i++)
292     {
293         if (!fgets (HeaderBuffer, AX_LINE_BUFFER_SIZE, InputFile))
294         {
295             return (TotalConverted);
296         }
297
298         BytesConverted = AxConvertLine (HeaderBuffer, OutputData);
299         TotalConverted += BytesConverted;
300         OutputData += 16;
301
302         if (BytesConverted != 16)
303         {
304             return (TotalConverted);
305         }
306     }
307
308     return (TotalConverted);
309 }
310
311
312 /******************************************************************************
313  *
314  * FUNCTION:    AxCountTableInstances
315  *
316  * PARAMETERS:  InputPathname       - Filename for acpidump file
317  *              Signature           - Requested signature to count
318  *
319  * RETURN:      The number of instances of the signature
320  *
321  * DESCRIPTION: Count the instances of tables with the given signature within
322  *              the input acpidump file.
323  *
324  ******************************************************************************/
325
326 static unsigned int
327 AxCountTableInstances (
328     char                    *InputPathname,
329     char                    *Signature)
330 {
331     FILE                    *InputFile;
332     unsigned int            Instances = 0;
333
334
335     InputFile = fopen (InputPathname, "rt");
336     if (!InputFile)
337     {
338         printf ("Could not open %s\n", InputPathname);
339         return (0);
340     }
341
342     /* Count the number of instances of this signature */
343
344     while (fgets (InstanceBuffer, AX_LINE_BUFFER_SIZE, InputFile))
345     {
346         /* Ignore empty lines and lines that start with a space */
347
348         if ((InstanceBuffer[0] == ' ') ||
349             (InstanceBuffer[0] == '\n'))
350         {
351             continue;
352         }
353
354         AxNormalizeSignature (InstanceBuffer);
355         if (!strncmp (InstanceBuffer, Signature, 4))
356         {
357             Instances++;
358         }
359     }
360
361     fclose (InputFile);
362     return (Instances);
363 }
364
365
366 /******************************************************************************
367  *
368  * FUNCTION:    AxGetNextInstance
369  *
370  * PARAMETERS:  InputPathname       - Filename for acpidump file
371  *              Signature           - Requested ACPI signature
372  *
373  * RETURN:      The next instance number for this signature. Zero if this
374  *              is the first instance of this signature.
375  *
376  * DESCRIPTION: Get the next instance number of the specified table. If this
377  *              is the first instance of the table, create a new instance
378  *              block. Note: only SSDT and PSDT tables can have multiple
379  *              instances.
380  *
381  ******************************************************************************/
382
383 static unsigned int
384 AxGetNextInstance (
385     char                    *InputPathname,
386     char                    *Signature)
387 {
388     AX_TABLE_INFO           *Info;
389
390
391     Info = AxTableListHead;
392     while (Info)
393     {
394         if (*(UINT32 *) Signature == Info->Signature)
395         {
396             break;
397         }
398
399         Info = Info->Next;
400     }
401
402     if (!Info)
403     {
404         /* Signature not found, create new table info block */
405
406         Info = malloc (sizeof (AX_TABLE_INFO));
407         if (!Info)
408         {
409             printf ("Could not allocate memory\n");
410             exit (0);
411         }
412
413         Info->Signature = *(UINT32 *) Signature;
414         Info->Instances = AxCountTableInstances (InputPathname, Signature);
415         Info->NextInstance = 1;
416         Info->Next = AxTableListHead;
417         AxTableListHead = Info;
418     }
419
420     if (Info->Instances > 1)
421     {
422         return (Info->NextInstance++);
423     }
424
425     return (0);
426 }
427
428
429 /******************************************************************************
430  *
431  * FUNCTION:    AxExtractTables
432  *
433  * PARAMETERS:  InputPathname       - Filename for acpidump file
434  *              Signature           - Requested ACPI signature to extract.
435  *                                    NULL means extract ALL tables.
436  *              MinimumInstances    - Min instances that are acceptable
437  *
438  * RETURN:      Status
439  *
440  * DESCRIPTION: Convert text ACPI tables to binary
441  *
442  ******************************************************************************/
443
444 int
445 AxExtractTables (
446     char                    *InputPathname,
447     char                    *Signature,
448     unsigned int            MinimumInstances)
449 {
450     FILE                    *InputFile;
451     FILE                    *OutputFile = NULL;
452     size_t                  BytesWritten;
453     size_t                  TotalBytesWritten = 0;
454     size_t                  BytesConverted;
455     unsigned int            State = AX_STATE_FIND_HEADER;
456     unsigned int            FoundTable = 0;
457     unsigned int            Instances = 0;
458     unsigned int            ThisInstance;
459     char                    ThisSignature[4];
460     int                     Status = 0;
461
462
463     /* Open input in text mode, output is in binary mode */
464
465     InputFile = fopen (InputPathname, "rt");
466     if (!InputFile)
467     {
468         printf ("Could not open %s\n", InputPathname);
469         return (-1);
470     }
471
472     if (Signature)
473     {
474         /* Are there enough instances of the table to continue? */
475
476         AxNormalizeSignature (Signature);
477
478         Instances = AxCountTableInstances (InputPathname, Signature);
479         if (Instances < MinimumInstances)
480         {
481             printf ("Table %s was not found in %s\n", Signature, InputPathname);
482             Status = -1;
483             goto CleanupAndExit;
484         }
485
486         if (Instances == 0)
487         {
488             goto CleanupAndExit;
489         }
490     }
491
492     /* Convert all instances of the table to binary */
493
494     while (fgets (LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
495     {
496         switch (State)
497         {
498         case AX_STATE_FIND_HEADER:
499
500             /* Ignore lines that are too short to be header lines */
501
502             if (strlen (LineBuffer) < AX_MIN_TABLE_NAME_LENGTH)
503             {
504                 continue;
505             }
506
507             /* Ignore empty lines and lines that start with a space */
508
509             if ((LineBuffer[0] == ' ') ||
510                 (LineBuffer[0] == '\n'))
511             {
512                 continue;
513             }
514
515             /*
516              * Ignore lines that are not of the form <sig> @ <addr>.
517              * Examples of lines that must be supported:
518              *
519              * DSDT @ 0x737e4000
520              * XSDT @ 0x737f2fff
521              * RSD PTR @ 0xf6cd0
522              * SSDT @ (nil)
523              */
524             if (!strstr (LineBuffer, " @ "))
525             {
526                 continue;
527             }
528
529             AxNormalizeSignature (LineBuffer);
530             strncpy (ThisSignature, LineBuffer, 4);
531
532             if (Signature)
533             {
534                 /* Ignore signatures that don't match */
535
536                 if (strncmp (ThisSignature, Signature, 4))
537                 {
538                     continue;
539                 }
540             }
541
542             /*
543              * Get the instance number for this signature. Only the
544              * SSDT and PSDT tables can have multiple instances.
545              */
546             ThisInstance = AxGetNextInstance (InputPathname, ThisSignature);
547
548             /* Build an output filename and create/open the output file */
549
550             if (ThisInstance > 0)
551             {
552                 sprintf (Filename, "%4.4s%u.dat", ThisSignature, ThisInstance);
553             }
554             else
555             {
556                 sprintf (Filename, "%4.4s.dat", ThisSignature);
557             }
558
559             AxStrlwr (Filename);
560             OutputFile = fopen (Filename, "w+b");
561             if (!OutputFile)
562             {
563                 printf ("Could not open %s\n", Filename);
564                 Status = -1;
565                 goto CleanupAndExit;
566             }
567
568             State = AX_STATE_EXTRACT_DATA;
569             TotalBytesWritten = 0;
570             FoundTable = 1;
571             continue;
572
573         case AX_STATE_EXTRACT_DATA:
574
575             /* Empty line or non-data line terminates the data */
576
577             if ((LineBuffer[0] == '\n') ||
578                 (LineBuffer[0] != ' '))
579             {
580                 fclose (OutputFile);
581                 OutputFile = NULL;
582                 State = AX_STATE_FIND_HEADER;
583
584                 printf ("Acpi table [%4.4s] - %u bytes written to %s\n",
585                     ThisSignature, (unsigned int) TotalBytesWritten, Filename);
586                 continue;
587             }
588
589             /* Convert the ascii data (one line of text) to binary */
590
591             BytesConverted = AxConvertLine (LineBuffer, Data);
592
593             /* Write the binary data */
594
595             BytesWritten = fwrite (Data, 1, BytesConverted, OutputFile);
596             if (BytesWritten != BytesConverted)
597             {
598                 printf ("Write error on %s\n", Filename);
599                 fclose (OutputFile);
600                 OutputFile = NULL;
601                 Status = -1;
602                 goto CleanupAndExit;
603             }
604
605             TotalBytesWritten += BytesConverted;
606             continue;
607
608         default:
609             Status = -1;
610             goto CleanupAndExit;
611         }
612     }
613
614     if (!FoundTable)
615     {
616         printf ("Table %s was not found in %s\n", Signature, InputPathname);
617     }
618
619
620 CleanupAndExit:
621
622     if (OutputFile)
623     {
624         fclose (OutputFile);
625         if (State == AX_STATE_EXTRACT_DATA)
626         {
627             /* Received an EOF while extracting data */
628
629             printf ("Acpi table [%4.4s] - %u bytes written to %s\n",
630                 ThisSignature, (unsigned int) TotalBytesWritten, Filename);
631         }
632     }
633
634     fclose (InputFile);
635     return (Status);
636 }
637
638
639 /******************************************************************************
640  *
641  * FUNCTION:    AxListTables
642  *
643  * PARAMETERS:  InputPathname       - Filename for acpidump file
644  *
645  * RETURN:      Status
646  *
647  * DESCRIPTION: Display info for all ACPI tables found in input. Does not
648  *              perform an actual extraction of the tables.
649  *
650  ******************************************************************************/
651
652 int
653 AxListTables (
654     char                    *InputPathname)
655 {
656     FILE                    *InputFile;
657     size_t                  HeaderSize;
658     unsigned char           Header[48];
659     int                     TableCount = 0;
660     ACPI_TABLE_HEADER       *TableHeader = (ACPI_TABLE_HEADER *) (void *) Header;
661
662
663     /* Open input in text mode, output is in binary mode */
664
665     InputFile = fopen (InputPathname, "rt");
666     if (!InputFile)
667     {
668         printf ("Could not open %s\n", InputPathname);
669         return (-1);
670     }
671
672     /* Dump the headers for all tables found in the input file */
673
674     printf ("\nSignature Length Revision  OemId     OemTableId"
675             "   OemRevision CompilerId CompilerRevision\n\n");
676
677     while (fgets (LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
678     {
679         /* Ignore empty lines and lines that start with a space */
680
681         if ((LineBuffer[0] == ' ') ||
682             (LineBuffer[0] == '\n'))
683         {
684             continue;
685         }
686
687         /* Get the 36 byte header and display the fields */
688
689         HeaderSize = AxGetTableHeader (InputFile, Header);
690         if (HeaderSize < 16)
691         {
692             continue;
693         }
694
695         /* RSDP has an oddball signature and header */
696
697         if (!strncmp (TableHeader->Signature, "RSD PTR ", 8))
698         {
699             AxCheckAscii ((char *) &Header[9], 6);
700             printf ("%8.4s                   \"%6.6s\"\n", "RSDP", &Header[9]);
701             TableCount++;
702             continue;
703         }
704
705         /* Minimum size for table with standard header */
706
707         if (HeaderSize < sizeof (ACPI_TABLE_HEADER))
708         {
709             continue;
710         }
711
712         /* Signature and Table length */
713
714         TableCount++;
715         printf ("%8.4s % 7d", TableHeader->Signature, TableHeader->Length);
716
717         /* FACS has only signature and length */
718
719         if (!strncmp (TableHeader->Signature, "FACS", 4))
720         {
721             printf ("\n");
722             continue;
723         }
724
725         /* OEM IDs and Compiler IDs */
726
727         AxCheckAscii (TableHeader->OemId, 6);
728         AxCheckAscii (TableHeader->OemTableId, 8);
729         AxCheckAscii (TableHeader->AslCompilerId, 4);
730
731         printf ("     %2.2X    \"%6.6s\"  \"%8.8s\"    %8.8X    \"%4.4s\"     %8.8X\n",
732             TableHeader->Revision, TableHeader->OemId,
733             TableHeader->OemTableId, TableHeader->OemRevision,
734             TableHeader->AslCompilerId, TableHeader->AslCompilerRevision);
735     }
736
737     printf ("\nFound %u ACPI tables\n", TableCount);
738     fclose (InputFile);
739     return (0);
740 }