xref: /netbsd-src/sys/external/bsd/acpica/dist/tools/acpixtract/acpixtract.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /******************************************************************************
2  *
3  * Module Name: acpixtract - Top level functions to convert ascii/hex
4  *                           ACPI tables to the original binary tables
5  *
6  *****************************************************************************/
7 
8 /*
9  * Copyright (C) 2000 - 2018, 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 "acpixtract.h"
46 
47 
48 /******************************************************************************
49  *
50  * FUNCTION:    AxExtractTables
51  *
52  * PARAMETERS:  InputPathname       - Filename for input acpidump file
53  *              Signature           - Requested ACPI signature to extract.
54  *                                    NULL means extract ALL tables.
55  *              MinimumInstances    - Min instances that are acceptable
56  *
57  * RETURN:      Status
58  *
59  * DESCRIPTION: Convert text ACPI tables to binary
60  *
61  ******************************************************************************/
62 
63 int
64 AxExtractTables (
65     char                    *InputPathname,
66     char                    *Signature,
67     unsigned int            MinimumInstances)
68 {
69     FILE                    *InputFile;
70     FILE                    *OutputFile = NULL;
71     unsigned int            BytesConverted;
72     unsigned int            ThisTableBytesWritten = 0;
73     unsigned int            FoundTable = 0;
74     unsigned int            Instances = 0;
75     unsigned int            ThisInstance;
76     char                    ThisSignature[5];
77     char                    UpperSignature[5];
78     int                     Status = 0;
79     unsigned int            State = AX_STATE_FIND_HEADER;
80 
81 
82     /* Open input in text mode, output is in binary mode */
83 
84     InputFile = fopen (InputPathname, "r");
85     if (!InputFile)
86     {
87         printf ("Could not open input file %s\n", InputPathname);
88         return (-1);
89     }
90 
91     if (!AxIsFileAscii (InputFile))
92     {
93         fclose (InputFile);
94         return (-1);
95     }
96 
97     if (Signature)
98     {
99         strncpy (UpperSignature, Signature, ACPI_NAME_SIZE);
100         AcpiUtStrupr (UpperSignature);
101 
102         /* Are there enough instances of the table to continue? */
103 
104         AxNormalizeSignature (UpperSignature);
105         Instances = AxCountTableInstances (InputPathname, UpperSignature);
106 
107         if (Instances < MinimumInstances)
108         {
109             printf ("Table [%s] was not found in %s\n",
110                 UpperSignature, InputPathname);
111             fclose (InputFile);
112             return (0);             /* Don't abort */
113         }
114 
115         if (Instances == 0)
116         {
117             fclose (InputFile);
118             return (-1);
119         }
120     }
121 
122     /* Convert all instances of the table to binary */
123 
124     while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
125     {
126         /*
127          * Check up front if we have a header line of the form:
128          * DSDT @ 0xdfffd0c0 (10999 bytes)
129          */
130         if (AX_IS_TABLE_BLOCK_HEADER &&
131             (State == AX_STATE_EXTRACT_DATA))
132         {
133             /* End of previous table, start of new table */
134 
135             if (ThisTableBytesWritten)
136             {
137                 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
138                     ThisTableBytesWritten, Gbl_OutputFilename);
139             }
140             else
141             {
142                 Gbl_TableCount--;
143             }
144 
145             State = AX_STATE_FIND_HEADER;
146         }
147 
148         switch (State)
149         {
150         case AX_STATE_FIND_HEADER:
151 
152             if (!AxIsDataBlockHeader ())
153             {
154                 continue;
155             }
156 
157             ACPI_MOVE_NAME (ThisSignature, Gbl_LineBuffer);
158             if (Signature)
159             {
160                 /* Ignore signatures that don't match */
161 
162                 if (!ACPI_COMPARE_NAME (ThisSignature, UpperSignature))
163                 {
164                     continue;
165                 }
166             }
167 
168             /*
169              * Get the instance number for this signature. Only the
170              * SSDT and PSDT tables can have multiple instances.
171              */
172             ThisInstance = AxGetNextInstance (InputPathname, ThisSignature);
173 
174             /* Build an output filename and create/open the output file */
175 
176             if (ThisInstance > 0)
177             {
178                 /* Add instance number to the output filename */
179 
180                 sprintf (Gbl_OutputFilename, "%4.4s%u.dat",
181                     ThisSignature, ThisInstance);
182             }
183             else
184             {
185                 sprintf (Gbl_OutputFilename, "%4.4s.dat",
186                     ThisSignature);
187             }
188 
189             AcpiUtStrlwr (Gbl_OutputFilename);
190             OutputFile = fopen (Gbl_OutputFilename, "w+b");
191             if (!OutputFile)
192             {
193                 printf ("Could not open output file %s\n",
194                     Gbl_OutputFilename);
195                 fclose (InputFile);
196                 return (-1);
197             }
198 
199             /*
200              * Toss this block header of the form "<sig> @ <addr>" line
201              * and move on to the actual data block
202              */
203             Gbl_TableCount++;
204             FoundTable = 1;
205             ThisTableBytesWritten = 0;
206             State = AX_STATE_EXTRACT_DATA;
207             continue;
208 
209         case AX_STATE_EXTRACT_DATA:
210 
211             if (!AxIsHexDataLine ())
212             {
213                 continue;   /* Toss any lines that are not raw hex data */
214             }
215 
216             /* Empty line or non-data line terminates the data block */
217 
218             BytesConverted = AxConvertAndWrite (OutputFile, ThisSignature,
219                 ThisTableBytesWritten);
220             switch (BytesConverted)
221             {
222             case 0:
223 
224                 State = AX_STATE_FIND_HEADER; /* No more data block lines */
225                 continue;
226 
227             case -1:
228 
229                 goto CleanupAndExit; /* There was a write error */
230 
231             default: /* Normal case, get next line */
232 
233                 ThisTableBytesWritten += BytesConverted;
234                 continue;
235             }
236 
237         default:
238 
239             Status = -1;
240             goto CleanupAndExit;
241         }
242     }
243 
244     if (!FoundTable)
245     {
246         printf ("No ACPI tables were found in %s\n", InputPathname);
247     }
248 
249 
250 CleanupAndExit:
251 
252     if (State == AX_STATE_EXTRACT_DATA)
253     {
254         /* Received an input file EOF while extracting data */
255 
256         printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
257             ThisTableBytesWritten, Gbl_OutputFilename);
258     }
259 
260     if (OutputFile)
261     {
262         fclose (OutputFile);
263     }
264 
265     fclose (InputFile);
266     return (Status);
267 }
268 
269 
270 /******************************************************************************
271  *
272  * FUNCTION:    AxExtractToMultiAmlFile
273  *
274  * PARAMETERS:  InputPathname       - Filename for input acpidump file
275  *
276  * RETURN:      Status
277  *
278  * DESCRIPTION: Convert all DSDT/SSDT tables to binary and append them all
279  *              into a single output file. Used to simplify the loading of
280  *              multiple/many SSDTs into a utility like acpiexec -- instead
281  *              of creating many separate output files.
282  *
283  ******************************************************************************/
284 
285 int
286 AxExtractToMultiAmlFile (
287     char                    *InputPathname)
288 {
289     FILE                    *InputFile;
290     FILE                    *OutputFile;
291     int                     Status = 0;
292     unsigned int            TotalBytesWritten = 0;
293     unsigned int            ThisTableBytesWritten = 0;
294     unsigned int            BytesConverted;
295     char                    ThisSignature[4];
296     unsigned int            State = AX_STATE_FIND_HEADER;
297 
298 
299     strcpy (Gbl_OutputFilename, AX_MULTI_TABLE_FILENAME);
300 
301     /* Open the input file in text mode */
302 
303     InputFile = fopen (InputPathname, "r");
304     if (!InputFile)
305     {
306         printf ("Could not open input file %s\n", InputPathname);
307         return (-1);
308     }
309 
310     if (!AxIsFileAscii (InputFile))
311     {
312         fclose (InputFile);
313         return (-1);
314     }
315 
316     /* Open the output file in binary mode */
317 
318     OutputFile = fopen (Gbl_OutputFilename, "w+b");
319     if (!OutputFile)
320     {
321         printf ("Could not open output file %s\n", Gbl_OutputFilename);
322         fclose (InputFile);
323         return (-1);
324     }
325 
326     /* Convert the DSDT and all SSDTs to binary */
327 
328     while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
329     {
330         /*
331          * Check up front if we have a header line of the form:
332          * DSDT @ 0xdfffd0c0 (10999 bytes)
333          */
334         if (AX_IS_TABLE_BLOCK_HEADER &&
335             (State == AX_STATE_EXTRACT_DATA))
336         {
337             /* End of previous table, start of new table */
338 
339             if (ThisTableBytesWritten)
340             {
341                 printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
342                     ThisTableBytesWritten, Gbl_OutputFilename);
343             }
344             else
345             {
346                 Gbl_TableCount--;
347             }
348 
349             State = AX_STATE_FIND_HEADER;
350         }
351 
352         switch (State)
353         {
354         case AX_STATE_FIND_HEADER:
355 
356             if (!AxIsDataBlockHeader ())
357             {
358                 continue;
359             }
360 
361             ACPI_MOVE_NAME (ThisSignature, Gbl_LineBuffer);
362 
363             /* Only want DSDT and SSDTs */
364 
365             if (!ACPI_COMPARE_NAME (ThisSignature, ACPI_SIG_DSDT) &&
366                 !ACPI_COMPARE_NAME (ThisSignature, ACPI_SIG_SSDT))
367             {
368                 continue;
369             }
370 
371             /*
372              * Toss this block header of the form "<sig> @ <addr>" line
373              * and move on to the actual data block
374              */
375             Gbl_TableCount++;
376             ThisTableBytesWritten = 0;
377             State = AX_STATE_EXTRACT_DATA;
378             continue;
379 
380         case AX_STATE_EXTRACT_DATA:
381 
382             if (!AxIsHexDataLine ())
383             {
384                 continue;   /* Toss any lines that are not raw hex data */
385             }
386 
387             /* Empty line or non-data line terminates the data block */
388 
389             BytesConverted = AxConvertAndWrite (
390                 OutputFile, ThisSignature, ThisTableBytesWritten);
391             switch (BytesConverted)
392             {
393             case 0:
394 
395                 State = AX_STATE_FIND_HEADER; /* No more data block lines */
396                 continue;
397 
398             case -1:
399 
400                 goto CleanupAndExit; /* There was a write error */
401 
402             default: /* Normal case, get next line */
403 
404                 ThisTableBytesWritten += BytesConverted;
405                 TotalBytesWritten += BytesConverted;
406                 continue;
407             }
408 
409         default:
410 
411             Status = -1;
412             goto CleanupAndExit;
413         }
414     }
415 
416 
417 CleanupAndExit:
418 
419     if (State == AX_STATE_EXTRACT_DATA)
420     {
421         /* Received an input file EOF or error while writing data */
422 
423         printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten,
424             ThisTableBytesWritten, Gbl_OutputFilename);
425     }
426 
427     printf ("\n%u binary ACPI tables extracted and written to %s (%u bytes)\n",
428         Gbl_TableCount, Gbl_OutputFilename, TotalBytesWritten);
429 
430     fclose (InputFile);
431     fclose (OutputFile);
432     return (Status);
433 }
434 
435 
436 /******************************************************************************
437  *
438  * FUNCTION:    AxListAllTables
439  *
440  * PARAMETERS:  InputPathname       - Filename for acpidump file
441  *
442  * RETURN:      Status
443  *
444  * DESCRIPTION: Display info for all ACPI tables found in input. Does not
445  *              perform an actual extraction of the tables.
446  *
447  ******************************************************************************/
448 
449 int
450 AxListAllTables (
451     char                    *InputPathname)
452 {
453     FILE                    *InputFile;
454     unsigned char           Header[48];
455     UINT32                  ByteCount = 0;
456     unsigned int            State = AX_STATE_FIND_HEADER;
457 
458 
459     /* Open input in text mode, output is in binary mode */
460 
461     InputFile = fopen (InputPathname, "r");
462     if (!InputFile)
463     {
464         printf ("Could not open input file %s\n", InputPathname);
465         return (-1);
466     }
467 
468     if (!AxIsFileAscii (InputFile))
469     {
470         fclose (InputFile);
471         return (-1);
472     }
473 
474     /* Info header */
475 
476     printf ("\n Signature  Length    Version Oem       Oem         "
477         "Oem         Compiler Compiler\n");
478     printf (  "                              Id        TableId     "
479         "RevisionId  Name     Revision\n");
480     printf (  " _________  __________  ____  ________  __________  "
481         "__________  _______  __________\n\n");
482 
483     /* Dump the headers for all tables found in the input file */
484 
485     while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
486     {
487         /* Ignore empty lines */
488 
489         if (AxIsEmptyLine (Gbl_LineBuffer))
490         {
491             continue;
492         }
493 
494         /*
495          * Check up front if we have a header line of the form:
496          * DSDT @ 0xdfffd0c0 (10999 bytes)
497          */
498         if (AX_IS_TABLE_BLOCK_HEADER &&
499             (State == AX_STATE_EXTRACT_DATA))
500         {
501             State = AX_STATE_FIND_HEADER;
502         }
503 
504         switch (State)
505         {
506         case AX_STATE_FIND_HEADER:
507 
508             ByteCount = 0;
509             if (!AxIsDataBlockHeader ())
510             {
511                 continue;
512             }
513 
514             State = AX_STATE_EXTRACT_DATA;
515             continue;
516 
517         case AX_STATE_EXTRACT_DATA:
518 
519             /* Ignore any lines that don't look like a data line */
520 
521             if (!AxIsHexDataLine ())
522             {
523                 continue;   /* Toss any lines that are not raw hex data */
524             }
525 
526             /* Convert header to hex and display it */
527 
528             ByteCount += AxConvertToBinary (Gbl_LineBuffer, &Header[ByteCount]);
529             if (ByteCount >= sizeof (ACPI_TABLE_HEADER))
530             {
531                 AxDumpTableHeader (Header);
532                 State = AX_STATE_FIND_HEADER;
533             }
534             continue;
535 
536         default:
537             break;
538         }
539     }
540 
541     printf ("\nFound %u ACPI tables in %s\n", Gbl_TableCount, InputPathname);
542     fclose (InputFile);
543     return (0);
544 }
545