| /****************************************************************************** |
| * |
| * Module Name: acpixtract - Top level functions to convert ascii/hex |
| * ACPI tables to the original binary tables |
| * |
| *****************************************************************************/ |
| |
| /* |
| * Copyright (C) 2000 - 2022, Intel Corp. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions, and the following disclaimer, |
| * without modification. |
| * 2. Redistributions in binary form must reproduce at minimum a disclaimer |
| * substantially similar to the "NO WARRANTY" disclaimer below |
| * ("Disclaimer") and any redistribution must be conditioned upon |
| * including a substantially similar Disclaimer requirement for further |
| * binary redistribution. |
| * 3. Neither the names of the above-listed copyright holders nor the names |
| * of any contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * Alternatively, this software may be distributed under the terms of the |
| * GNU General Public License ("GPL") version 2 as published by the Free |
| * Software Foundation. |
| * |
| * NO WARRANTY |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
| * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGES. |
| */ |
| |
| #include "acpixtract.h" |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: AxExtractTables |
| * |
| * PARAMETERS: InputPathname - Filename for input acpidump file |
| * Signature - Requested ACPI signature to extract. |
| * NULL means extract ALL tables. |
| * MinimumInstances - Min instances that are acceptable |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Convert text ACPI tables to binary |
| * |
| ******************************************************************************/ |
| |
| int |
| AxExtractTables ( |
| char *InputPathname, |
| char *Signature, |
| unsigned int MinimumInstances) |
| { |
| FILE *InputFile; |
| FILE *OutputFile = NULL; |
| int BytesConverted; |
| int ThisTableBytesWritten = 0; |
| unsigned int FoundTable = 0; |
| unsigned int Instances = 0; |
| unsigned int ThisInstance; |
| char ThisSignature[5]; |
| char UpperSignature[5]; |
| int Status = 0; |
| unsigned int State = AX_STATE_FIND_HEADER; |
| |
| |
| /* Open input in text mode, output is in binary mode */ |
| |
| InputFile = fopen (InputPathname, "r"); |
| if (!InputFile) |
| { |
| printf ("Could not open input file %s\n", InputPathname); |
| return (-1); |
| } |
| |
| if (!AxIsFileAscii (InputFile)) |
| { |
| fclose (InputFile); |
| return (-1); |
| } |
| |
| if (Signature) |
| { |
| strncpy (UpperSignature, Signature, ACPI_NAMESEG_SIZE); |
| AcpiUtStrupr (UpperSignature); |
| |
| /* Are there enough instances of the table to continue? */ |
| |
| AxNormalizeSignature (UpperSignature); |
| Instances = AxCountTableInstances (InputPathname, UpperSignature); |
| |
| if (Instances < MinimumInstances) |
| { |
| printf ("Table [%s] was not found in %s\n", |
| UpperSignature, InputPathname); |
| fclose (InputFile); |
| return (0); /* Don't abort */ |
| } |
| |
| if (Instances == 0) |
| { |
| fclose (InputFile); |
| return (-1); |
| } |
| } |
| |
| /* Convert all instances of the table to binary */ |
| |
| while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile)) |
| { |
| /* |
| * Check up front if we have a header line of the form: |
| * DSDT @ 0xdfffd0c0 (10999 bytes) |
| */ |
| if (AX_IS_TABLE_BLOCK_HEADER && |
| (State == AX_STATE_EXTRACT_DATA)) |
| { |
| /* End of previous table, start of new table */ |
| |
| if (ThisTableBytesWritten) |
| { |
| printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten, |
| ThisTableBytesWritten, Gbl_OutputFilename); |
| } |
| else |
| { |
| Gbl_TableCount--; |
| } |
| |
| State = AX_STATE_FIND_HEADER; |
| } |
| |
| switch (State) |
| { |
| case AX_STATE_FIND_HEADER: |
| |
| if (!AxIsDataBlockHeader ()) |
| { |
| continue; |
| } |
| |
| ACPI_COPY_NAMESEG (ThisSignature, Gbl_LineBuffer); |
| if (Signature) |
| { |
| /* Ignore signatures that don't match */ |
| |
| if (!ACPI_COMPARE_NAMESEG (ThisSignature, UpperSignature)) |
| { |
| continue; |
| } |
| } |
| |
| /* |
| * Get the instance number for this signature. Only the |
| * SSDT and PSDT tables can have multiple instances. |
| */ |
| ThisInstance = AxGetNextInstance (InputPathname, ThisSignature); |
| |
| /* Build an output filename and create/open the output file */ |
| |
| if (ThisInstance > 0) |
| { |
| /* Add instance number to the output filename */ |
| |
| sprintf (Gbl_OutputFilename, "%4.4s%u.dat", |
| ThisSignature, ThisInstance); |
| } |
| else |
| { |
| sprintf (Gbl_OutputFilename, "%4.4s.dat", |
| ThisSignature); |
| } |
| |
| AcpiUtStrlwr (Gbl_OutputFilename); |
| OutputFile = fopen (Gbl_OutputFilename, "w+b"); |
| if (!OutputFile) |
| { |
| printf ("Could not open output file %s\n", |
| Gbl_OutputFilename); |
| fclose (InputFile); |
| return (-1); |
| } |
| |
| /* |
| * Toss this block header of the form "<sig> @ <addr>" line |
| * and move on to the actual data block |
| */ |
| Gbl_TableCount++; |
| FoundTable = 1; |
| ThisTableBytesWritten = 0; |
| State = AX_STATE_EXTRACT_DATA; |
| continue; |
| |
| case AX_STATE_EXTRACT_DATA: |
| |
| if (!AxIsHexDataLine ()) |
| { |
| continue; /* Toss any lines that are not raw hex data */ |
| } |
| |
| /* Empty line or non-data line terminates the data block */ |
| |
| BytesConverted = AxConvertAndWrite (OutputFile, ThisSignature); |
| switch (BytesConverted) |
| { |
| case 0: |
| |
| State = AX_STATE_FIND_HEADER; /* No more data block lines */ |
| continue; |
| |
| case -1: |
| |
| Status = -1; |
| goto CleanupAndExit; /* There was a write error */ |
| |
| default: /* Normal case, get next line */ |
| |
| ThisTableBytesWritten += BytesConverted; |
| continue; |
| } |
| |
| default: |
| |
| Status = -1; |
| goto CleanupAndExit; |
| } |
| } |
| |
| if (!FoundTable) |
| { |
| printf ("No ACPI tables were found in %s\n", InputPathname); |
| } |
| |
| |
| CleanupAndExit: |
| |
| if (State == AX_STATE_EXTRACT_DATA) |
| { |
| /* Received an input file EOF while extracting data */ |
| |
| printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten, |
| ThisTableBytesWritten, Gbl_OutputFilename); |
| } |
| |
| if (OutputFile) |
| { |
| fclose (OutputFile); |
| } |
| |
| fclose (InputFile); |
| return (Status); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: AxExtractToMultiAmlFile |
| * |
| * PARAMETERS: InputPathname - Filename for input acpidump file |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Convert all DSDT/SSDT tables to binary and append them all |
| * into a single output file. Used to simplify the loading of |
| * multiple/many SSDTs into a utility like acpiexec -- instead |
| * of creating many separate output files. |
| * |
| ******************************************************************************/ |
| |
| int |
| AxExtractToMultiAmlFile ( |
| char *InputPathname) |
| { |
| FILE *InputFile; |
| FILE *OutputFile; |
| int Status = 0; |
| int TotalBytesWritten = 0; |
| int ThisTableBytesWritten = 0; |
| unsigned int BytesConverted; |
| char ThisSignature[4]; |
| unsigned int State = AX_STATE_FIND_HEADER; |
| |
| |
| strcpy (Gbl_OutputFilename, AX_MULTI_TABLE_FILENAME); |
| |
| /* Open the input file in text mode */ |
| |
| InputFile = fopen (InputPathname, "r"); |
| if (!InputFile) |
| { |
| printf ("Could not open input file %s\n", InputPathname); |
| return (-1); |
| } |
| |
| if (!AxIsFileAscii (InputFile)) |
| { |
| fclose (InputFile); |
| return (-1); |
| } |
| |
| /* Open the output file in binary mode */ |
| |
| OutputFile = fopen (Gbl_OutputFilename, "w+b"); |
| if (!OutputFile) |
| { |
| printf ("Could not open output file %s\n", Gbl_OutputFilename); |
| fclose (InputFile); |
| return (-1); |
| } |
| |
| /* Convert the DSDT and all SSDTs to binary */ |
| |
| while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile)) |
| { |
| /* |
| * Check up front if we have a header line of the form: |
| * DSDT @ 0xdfffd0c0 (10999 bytes) |
| */ |
| if (AX_IS_TABLE_BLOCK_HEADER && |
| (State == AX_STATE_EXTRACT_DATA)) |
| { |
| /* End of previous table, start of new table */ |
| |
| if (ThisTableBytesWritten) |
| { |
| printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten, |
| ThisTableBytesWritten, Gbl_OutputFilename); |
| } |
| else |
| { |
| Gbl_TableCount--; |
| } |
| |
| State = AX_STATE_FIND_HEADER; |
| } |
| |
| switch (State) |
| { |
| case AX_STATE_FIND_HEADER: |
| |
| if (!AxIsDataBlockHeader ()) |
| { |
| continue; |
| } |
| |
| ACPI_COPY_NAMESEG (ThisSignature, Gbl_LineBuffer); |
| |
| /* Only want DSDT and SSDTs */ |
| |
| if (!ACPI_COMPARE_NAMESEG (ThisSignature, ACPI_SIG_DSDT) && |
| !ACPI_COMPARE_NAMESEG (ThisSignature, ACPI_SIG_SSDT)) |
| { |
| continue; |
| } |
| |
| /* |
| * Toss this block header of the form "<sig> @ <addr>" line |
| * and move on to the actual data block |
| */ |
| Gbl_TableCount++; |
| ThisTableBytesWritten = 0; |
| State = AX_STATE_EXTRACT_DATA; |
| continue; |
| |
| case AX_STATE_EXTRACT_DATA: |
| |
| if (!AxIsHexDataLine ()) |
| { |
| continue; /* Toss any lines that are not raw hex data */ |
| } |
| |
| /* Empty line or non-data line terminates the data block */ |
| |
| BytesConverted = AxConvertAndWrite (OutputFile, ThisSignature); |
| switch (BytesConverted) |
| { |
| case 0: |
| |
| State = AX_STATE_FIND_HEADER; /* No more data block lines */ |
| continue; |
| |
| case -1: |
| |
| Status = -1; |
| goto CleanupAndExit; /* There was a write error */ |
| |
| default: /* Normal case, get next line */ |
| |
| ThisTableBytesWritten += BytesConverted; |
| TotalBytesWritten += BytesConverted; |
| continue; |
| } |
| |
| default: |
| |
| Status = -1; |
| goto CleanupAndExit; |
| } |
| } |
| |
| |
| CleanupAndExit: |
| |
| if (State == AX_STATE_EXTRACT_DATA) |
| { |
| /* Received an input file EOF or error while writing data */ |
| |
| printf (AX_TABLE_INFO_FORMAT, ThisSignature, ThisTableBytesWritten, |
| ThisTableBytesWritten, Gbl_OutputFilename); |
| } |
| |
| printf ("\n%u binary ACPI tables extracted and written to %s (%u bytes)\n", |
| Gbl_TableCount, Gbl_OutputFilename, TotalBytesWritten); |
| |
| fclose (InputFile); |
| fclose (OutputFile); |
| return (Status); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: AxListAllTables |
| * |
| * PARAMETERS: InputPathname - Filename for acpidump file |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Display info for all ACPI tables found in input. Does not |
| * perform an actual extraction of the tables. |
| * |
| ******************************************************************************/ |
| |
| int |
| AxListAllTables ( |
| char *InputPathname) |
| { |
| FILE *InputFile; |
| unsigned char Header[48]; |
| UINT32 ByteCount = 0; |
| INT32 ThisLineByteCount; |
| unsigned int State = AX_STATE_FIND_HEADER; |
| |
| |
| /* Open input in text mode, output is in binary mode */ |
| |
| InputFile = fopen (InputPathname, "r"); |
| if (!InputFile) |
| { |
| printf ("Could not open input file %s\n", InputPathname); |
| return (-1); |
| } |
| |
| if (!AxIsFileAscii (InputFile)) |
| { |
| fclose (InputFile); |
| return (-1); |
| } |
| |
| /* Info header */ |
| |
| printf ("\n Signature Length Version Oem Oem " |
| "Oem Compiler Compiler\n"); |
| printf ( " Id TableId " |
| "RevisionId Name Revision\n"); |
| printf ( " _________ __________ ____ ________ __________ " |
| "__________ _______ __________\n\n"); |
| |
| /* Dump the headers for all tables found in the input file */ |
| |
| while (fgets (Gbl_LineBuffer, AX_LINE_BUFFER_SIZE, InputFile)) |
| { |
| /* Ignore empty lines */ |
| |
| if (AxIsEmptyLine (Gbl_LineBuffer)) |
| { |
| continue; |
| } |
| |
| /* |
| * Check up front if we have a header line of the form: |
| * DSDT @ 0xdfffd0c0 (10999 bytes) |
| */ |
| if (AX_IS_TABLE_BLOCK_HEADER && |
| (State == AX_STATE_EXTRACT_DATA)) |
| { |
| State = AX_STATE_FIND_HEADER; |
| } |
| |
| switch (State) |
| { |
| case AX_STATE_FIND_HEADER: |
| |
| ByteCount = 0; |
| if (!AxIsDataBlockHeader ()) |
| { |
| continue; |
| } |
| |
| State = AX_STATE_EXTRACT_DATA; |
| continue; |
| |
| case AX_STATE_EXTRACT_DATA: |
| |
| /* Ignore any lines that don't look like a data line */ |
| |
| if (!AxIsHexDataLine ()) |
| { |
| continue; /* Toss any lines that are not raw hex data */ |
| } |
| |
| /* Convert header to hex and display it */ |
| |
| ThisLineByteCount = AxConvertToBinary (Gbl_LineBuffer, |
| &Header[ByteCount]); |
| if (ThisLineByteCount == EOF) |
| { |
| fclose (InputFile); |
| return (-1); |
| } |
| |
| ByteCount += ThisLineByteCount; |
| if (ByteCount >= sizeof (ACPI_TABLE_HEADER)) |
| { |
| AxDumpTableHeader (Header); |
| State = AX_STATE_FIND_HEADER; |
| } |
| continue; |
| |
| default: |
| break; |
| } |
| } |
| |
| printf ("\nFound %u ACPI tables in %s\n", Gbl_TableCount, InputPathname); |
| fclose (InputFile); |
| return (0); |
| } |