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