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
63int
64AxExtractTables (
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
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_NAMESEG_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_COPY_NAMESEG (ThisSignature, Gbl_LineBuffer);
158            if (Signature)
159            {
160                /* Ignore signatures that don't match */
161
162                if (!ACPI_COMPARE_NAMESEG (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            switch (BytesConverted)
220            {
221            case 0:
222
223                State = AX_STATE_FIND_HEADER; /* No more data block lines */
224                continue;
225
226            case -1:
227
228                Status = -1;
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
250CleanupAndExit:
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
285int
286AxExtractToMultiAmlFile (
287    char                    *InputPathname)
288{
289    FILE                    *InputFile;
290    FILE                    *OutputFile;
291    int                     Status = 0;
292    int                     TotalBytesWritten = 0;
293    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_COPY_NAMESEG (ThisSignature, Gbl_LineBuffer);
362
363            /* Only want DSDT and SSDTs */
364
365            if (!ACPI_COMPARE_NAMESEG (ThisSignature, ACPI_SIG_DSDT) &&
366                !ACPI_COMPARE_NAMESEG (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 (OutputFile, ThisSignature);
390            switch (BytesConverted)
391            {
392            case 0:
393
394                State = AX_STATE_FIND_HEADER; /* No more data block lines */
395                continue;
396
397            case -1:
398
399                Status = -1;
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
417CleanupAndExit:
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
449int
450AxListAllTables (
451    char                    *InputPathname)
452{
453    FILE                    *InputFile;
454    unsigned char           Header[48];
455    UINT32                  ByteCount = 0;
456    INT32                   ThisLineByteCount;
457    unsigned int            State = AX_STATE_FIND_HEADER;
458
459
460    /* Open input in text mode, output is in binary mode */
461
462    InputFile = fopen (InputPathname, "r");
463    if (!InputFile)
464    {
465        printf ("Could not open input file %s\n", InputPathname);
466        return (-1);
467    }
468
469    if (!AxIsFileAscii (InputFile))
470    {
471        fclose (InputFile);
472        return (-1);
473    }
474
475    /* Info header */
476
477    printf ("\n Signature  Length    Version Oem       Oem         "
478        "Oem         Compiler Compiler\n");
479    printf (  "                              Id        TableId     "
480        "RevisionId  Name     Revision\n");
481    printf (  " _________  __________  ____  ________  __________  "
482        "__________  _______  __________\n\n");
483
484    /* Dump the headers for all tables found in the input file */
485
486    while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile))
487    {
488        /* Ignore empty lines */
489
490        if (AxIsEmptyLine (Gbl_LineBuffer))
491        {
492            continue;
493        }
494
495        /*
496         * Check up front if we have a header line of the form:
497         * DSDT @ 0xdfffd0c0 (10999 bytes)
498         */
499        if (AX_IS_TABLE_BLOCK_HEADER &&
500            (State == AX_STATE_EXTRACT_DATA))
501        {
502            State = AX_STATE_FIND_HEADER;
503        }
504
505        switch (State)
506        {
507        case AX_STATE_FIND_HEADER:
508
509            ByteCount = 0;
510            if (!AxIsDataBlockHeader ())
511            {
512                continue;
513            }
514
515            State = AX_STATE_EXTRACT_DATA;
516            continue;
517
518        case AX_STATE_EXTRACT_DATA:
519
520            /* Ignore any lines that don't look like a data line */
521
522            if (!AxIsHexDataLine ())
523            {
524                continue;   /* Toss any lines that are not raw hex data */
525            }
526
527            /* Convert header to hex and display it */
528
529            ThisLineByteCount = AxConvertToBinary (Gbl_LineBuffer,
530                &Header[ByteCount]);
531            if (ThisLineByteCount == EOF)
532            {
533                fclose (InputFile);
534                return (-1);
535            }
536
537            ByteCount += ThisLineByteCount;
538            if (ByteCount >= sizeof (ACPI_TABLE_HEADER))
539            {
540                AxDumpTableHeader (Header);
541                State = AX_STATE_FIND_HEADER;
542            }
543            continue;
544
545        default:
546            break;
547        }
548    }
549
550    printf ("\nFound %u ACPI tables in %s\n", Gbl_TableCount, InputPathname);
551    fclose (InputFile);
552    return (0);
553}
554