1 /******************************************************************************
2  *
3  * Module Name: acpixtract - convert ascii ACPI tables to binary
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, 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 "acpixtract.h"
45 
46 
47 /******************************************************************************
48  *
49  * FUNCTION:    AxExtractTables
50  *
51  * PARAMETERS:  InputPathname       - Filename for input acpidump file
52  *              Signature           - Requested ACPI signature to extract.
53  *                                    NULL means extract ALL tables.
54  *              MinimumInstances    - Min instances that are acceptable
55  *
56  * RETURN:      Status
57  *
58  * DESCRIPTION: Convert text ACPI tables to binary
59  *
60  ******************************************************************************/
61 
62 int
63 AxExtractTables (
64     char                    *InputPathname,
65     char                    *Signature,
66     unsigned int            MinimumInstances)
67 {
68     FILE                    *InputFile;
69     FILE                    *OutputFile = NULL;
70     unsigned int            BytesConverted;
71     unsigned int            ThisTableBytesWritten = 0;
72     unsigned int            FoundTable = 0;
73     unsigned int            Instances = 0;
74     unsigned int            ThisInstance;
75     char                    ThisSignature[4];
76     int                     Status = 0;
77     unsigned int            State = AX_STATE_FIND_HEADER;
78 
79 
80     /* Open input in text mode, output is in binary mode */
81 
82     InputFile = fopen (InputPathname, "rt");
83     if (!InputFile)
84     {
85         printf ("Could not open input file %s\n", InputPathname);
86         return (-1);
87     }
88 
89     if (Signature)
90     {
91         /* Are there enough instances of the table to continue? */
92 
93         AxNormalizeSignature (Signature);
94 
95         Instances = AxCountTableInstances (InputPathname, Signature);
96         if (Instances < MinimumInstances)
97         {
98             printf ("Table [%s] was not found in %s\n",
99                 Signature, InputPathname);
100             fclose (InputFile);
101             return (-1);
102         }
103 
104         if (Instances == 0)
105         {
106             fclose (InputFile);
107             return (-1);
108         }
109     }
110 
111     /* Convert all instances of the table to binary */
112 
113     while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
114     {
115         switch (State)
116         {
117         case AX_STATE_FIND_HEADER:
118 
119             if (!AxIsDataBlockHeader ())
120             {
121                 continue;
122             }
123 
124             ACPI_MOVE_NAME (ThisSignature, Gbl_LineBuffer);
125             if (Signature)
126             {
127                 /* Ignore signatures that don't match */
128 
129                 if (!ACPI_COMPARE_NAME (ThisSignature, Signature))
130                 {
131                     continue;
132                 }
133             }
134 
135             /*
136              * Get the instance number for this signature. Only the
137              * SSDT and PSDT tables can have multiple instances.
138              */
139             ThisInstance = AxGetNextInstance (InputPathname, ThisSignature);
140 
141             /* Build an output filename and create/open the output file */
142 
143             if (ThisInstance > 0)
144             {
145                 /* Add instance number to the output filename */
146 
147                 sprintf (Gbl_OutputFilename, "%4.4s%u.dat",
148                     ThisSignature, ThisInstance);
149             }
150             else
151             {
152                 sprintf (Gbl_OutputFilename, "%4.4s.dat",
153                     ThisSignature);
154             }
155 
156             AcpiUtStrlwr (Gbl_OutputFilename);
157             OutputFile = fopen (Gbl_OutputFilename, "w+b");
158             if (!OutputFile)
159             {
160                 printf ("Could not open output file %s\n",
161                     Gbl_OutputFilename);
162                 fclose (InputFile);
163                 return (-1);
164             }
165 
166             /*
167              * Toss this block header of the form "<sig> @ <addr>" line
168              * and move on to the actual data block
169              */
170             Gbl_TableCount++;
171             FoundTable = 1;
172             ThisTableBytesWritten = 0;
173             State = AX_STATE_EXTRACT_DATA;
174             continue;
175 
176         case AX_STATE_EXTRACT_DATA:
177 
178             /* Empty line or non-data line terminates the data block */
179 
180             BytesConverted = AxProcessOneTextLine (
181                 OutputFile, ThisSignature, ThisTableBytesWritten);
182             switch (BytesConverted)
183             {
184             case 0:
185 
186                 State = AX_STATE_FIND_HEADER; /* No more data block lines */
187                 continue;
188 
189             case -1:
190 
191                 goto CleanupAndExit; /* There was a write error */
192 
193             default: /* Normal case, get next line */
194 
195                 ThisTableBytesWritten += BytesConverted;
196                 continue;
197             }
198 
199         default:
200 
201             Status = -1;
202             goto CleanupAndExit;
203         }
204     }
205 
206     if (!FoundTable)
207     {
208         printf ("Table [%s] was not found in %s\n",
209             Signature, InputPathname);
210     }
211 
212 
213 CleanupAndExit:
214 
215     if (State == AX_STATE_EXTRACT_DATA)
216     {
217         /* Received an input file EOF while extracting data */
218 
219         printf (AX_TABLE_INFO_FORMAT,
220             ThisSignature, ThisTableBytesWritten, Gbl_OutputFilename);
221     }
222 
223     if (Gbl_TableCount > 1)
224     {
225         printf ("\n%d binary ACPI tables extracted\n",
226             Gbl_TableCount);
227     }
228 
229     if (OutputFile)
230     {
231         fclose (OutputFile);
232     }
233 
234     fclose (InputFile);
235     return (Status);
236 }
237 
238 
239 /******************************************************************************
240  *
241  * FUNCTION:    AxExtractToMultiAmlFile
242  *
243  * PARAMETERS:  InputPathname       - Filename for input acpidump file
244  *
245  * RETURN:      Status
246  *
247  * DESCRIPTION: Convert all DSDT/SSDT tables to binary and append them all
248  *              into a single output file. Used to simplify the loading of
249  *              multiple/many SSDTs into a utility like acpiexec -- instead
250  *              of creating many separate output files.
251  *
252  ******************************************************************************/
253 
254 int
255 AxExtractToMultiAmlFile (
256     char                    *InputPathname)
257 {
258     FILE                    *InputFile;
259     FILE                    *OutputFile;
260     int                     Status = 0;
261     unsigned int            TotalBytesWritten = 0;
262     unsigned int            ThisTableBytesWritten = 0;
263     unsigned int             BytesConverted;
264     char                    ThisSignature[4];
265     unsigned int            State = AX_STATE_FIND_HEADER;
266 
267 
268     strcpy (Gbl_OutputFilename, AX_MULTI_TABLE_FILENAME);
269 
270     /* Open the input file in text mode */
271 
272     InputFile = fopen (InputPathname, "rt");
273     if (!InputFile)
274     {
275         printf ("Could not open input file %s\n", InputPathname);
276         return (-1);
277     }
278 
279     /* Open the output file in binary mode */
280 
281     OutputFile = fopen (Gbl_OutputFilename, "w+b");
282     if (!OutputFile)
283     {
284         printf ("Could not open output file %s\n", Gbl_OutputFilename);
285         fclose (InputFile);
286         return (-1);
287     }
288 
289     /* Convert the DSDT and all SSDTs to binary */
290 
291     while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
292     {
293         switch (State)
294         {
295         case AX_STATE_FIND_HEADER:
296 
297             if (!AxIsDataBlockHeader ())
298             {
299                 continue;
300             }
301 
302             ACPI_MOVE_NAME (ThisSignature, Gbl_LineBuffer);
303 
304             /* Only want DSDT and SSDTs */
305 
306             if (!ACPI_COMPARE_NAME (ThisSignature, ACPI_SIG_DSDT) &&
307                 !ACPI_COMPARE_NAME (ThisSignature, ACPI_SIG_SSDT))
308             {
309                 continue;
310             }
311 
312             /*
313              * Toss this block header of the form "<sig> @ <addr>" line
314              * and move on to the actual data block
315              */
316             Gbl_TableCount++;
317             ThisTableBytesWritten = 0;
318             State = AX_STATE_EXTRACT_DATA;
319             continue;
320 
321         case AX_STATE_EXTRACT_DATA:
322 
323             /* Empty line or non-data line terminates the data block */
324 
325             BytesConverted = AxProcessOneTextLine (
326                 OutputFile, ThisSignature, ThisTableBytesWritten);
327             switch (BytesConverted)
328             {
329             case 0:
330 
331                 State = AX_STATE_FIND_HEADER; /* No more data block lines */
332                 continue;
333 
334             case -1:
335 
336                 goto CleanupAndExit; /* There was a write error */
337 
338             default: /* Normal case, get next line */
339 
340                 ThisTableBytesWritten += BytesConverted;
341                 TotalBytesWritten += BytesConverted;
342                 continue;
343             }
344 
345         default:
346 
347             Status = -1;
348             goto CleanupAndExit;
349         }
350     }
351 
352 
353 CleanupAndExit:
354 
355     if (State == AX_STATE_EXTRACT_DATA)
356     {
357         /* Received an input file EOF or error while writing data */
358 
359         printf (AX_TABLE_INFO_FORMAT,
360             ThisSignature, ThisTableBytesWritten, Gbl_OutputFilename);
361     }
362 
363     printf ("\n%d binary ACPI tables extracted and written to %s (%u bytes)\n",
364         Gbl_TableCount, Gbl_OutputFilename, TotalBytesWritten);
365 
366     fclose (InputFile);
367     fclose (OutputFile);
368     return (Status);
369 }
370 
371 
372 /******************************************************************************
373  *
374  * FUNCTION:    AxListTables
375  *
376  * PARAMETERS:  InputPathname       - Filename for acpidump file
377  *
378  * RETURN:      Status
379  *
380  * DESCRIPTION: Display info for all ACPI tables found in input. Does not
381  *              perform an actual extraction of the tables.
382  *
383  ******************************************************************************/
384 
385 int
386 AxListTables (
387     char                    *InputPathname)
388 {
389     FILE                    *InputFile;
390     size_t                  HeaderSize;
391     unsigned char           Header[48];
392     ACPI_TABLE_HEADER       *TableHeader = (ACPI_TABLE_HEADER *) (void *) Header;
393 
394 
395     /* Open input in text mode, output is in binary mode */
396 
397     InputFile = fopen (InputPathname, "rt");
398     if (!InputFile)
399     {
400         printf ("Could not open input file %s\n", InputPathname);
401         return (-1);
402     }
403 
404     /* Dump the headers for all tables found in the input file */
405 
406     printf ("\nSignature  Length      Revision   OemId    OemTableId"
407         "   OemRevision CompilerId CompilerRevision\n\n");
408 
409     while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
410     {
411         /* Ignore empty lines and lines that start with a space */
412 
413         if (AxIsEmptyLine (Gbl_LineBuffer) ||
414             (Gbl_LineBuffer[0] == ' '))
415         {
416             continue;
417         }
418 
419         /* Get the 36 byte header and display the fields */
420 
421         HeaderSize = AxGetTableHeader (InputFile, Header);
422         if (HeaderSize < 16)
423         {
424             continue;
425         }
426 
427         /* RSDP has an oddball signature and header */
428 
429         if (!strncmp (TableHeader->Signature, "RSD PTR ", 8))
430         {
431             AxCheckAscii ((char *) &Header[9], 6);
432             printf ("%7.4s                          \"%6.6s\"\n", "RSDP",
433                 &Header[9]);
434             Gbl_TableCount++;
435             continue;
436         }
437 
438         /* Minimum size for table with standard header */
439 
440         if (HeaderSize < sizeof (ACPI_TABLE_HEADER))
441         {
442             continue;
443         }
444 
445         /* Signature and Table length */
446 
447         Gbl_TableCount++;
448         printf ("%7.4s   0x%8.8X", TableHeader->Signature,
449             TableHeader->Length);
450 
451         /* FACS has only signature and length */
452 
453         if (ACPI_COMPARE_NAME (TableHeader->Signature, "FACS"))
454         {
455             printf ("\n");
456             continue;
457         }
458 
459         /* OEM IDs and Compiler IDs */
460 
461         AxCheckAscii (TableHeader->OemId, 6);
462         AxCheckAscii (TableHeader->OemTableId, 8);
463         AxCheckAscii (TableHeader->AslCompilerId, 4);
464 
465         printf (
466             "     0x%2.2X    \"%6.6s\"  \"%8.8s\"   0x%8.8X"
467             "    \"%4.4s\"     0x%8.8X\n",
468             TableHeader->Revision, TableHeader->OemId,
469             TableHeader->OemTableId, TableHeader->OemRevision,
470             TableHeader->AslCompilerId, TableHeader->AslCompilerRevision);
471     }
472 
473     printf ("\nFound %u ACPI tables\n", Gbl_TableCount);
474     fclose (InputFile);
475     return (0);
476 }
477