Path: blob/main/sys/contrib/dev/acpica/common/acfileio.c
48375 views
/******************************************************************************1*2* Module Name: acfileio - Get ACPI tables from file3*4*****************************************************************************/56/******************************************************************************7*8* 1. Copyright Notice9*10* Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.11* All rights reserved.12*13* 2. License14*15* 2.1. This is your license from Intel Corp. under its intellectual property16* rights. You may have additional license terms from the party that provided17* you this software, covering your right to use that party's intellectual18* property rights.19*20* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a21* copy of the source code appearing in this file ("Covered Code") an22* irrevocable, perpetual, worldwide license under Intel's copyrights in the23* base code distributed originally by Intel ("Original Intel Code") to copy,24* make derivatives, distribute, use and display any portion of the Covered25* Code in any form, with the right to sublicense such rights; and26*27* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent28* license (with the right to sublicense), under only those claims of Intel29* patents that are infringed by the Original Intel Code, to make, use, sell,30* offer to sell, and import the Covered Code and derivative works thereof31* solely to the minimum extent necessary to exercise the above copyright32* license, and in no event shall the patent license extend to any additions33* to or modifications of the Original Intel Code. No other license or right34* is granted directly or by implication, estoppel or otherwise;35*36* The above copyright and patent license is granted only if the following37* conditions are met:38*39* 3. Conditions40*41* 3.1. Redistribution of Source with Rights to Further Distribute Source.42* Redistribution of source code of any substantial portion of the Covered43* Code or modification with rights to further distribute source must include44* the above Copyright Notice, the above License, this list of Conditions,45* and the following Disclaimer and Export Compliance provision. In addition,46* Licensee must cause all Covered Code to which Licensee contributes to47* contain a file documenting the changes Licensee made to create that Covered48* Code and the date of any change. Licensee must include in that file the49* documentation of any changes made by any predecessor Licensee. Licensee50* must include a prominent statement that the modification is derived,51* directly or indirectly, from Original Intel Code.52*53* 3.2. Redistribution of Source with no Rights to Further Distribute Source.54* Redistribution of source code of any substantial portion of the Covered55* Code or modification without rights to further distribute source must56* include the following Disclaimer and Export Compliance provision in the57* documentation and/or other materials provided with distribution. In58* addition, Licensee may not authorize further sublicense of source of any59* portion of the Covered Code, and must include terms to the effect that the60* license from Licensee to its licensee is limited to the intellectual61* property embodied in the software Licensee provides to its licensee, and62* not to intellectual property embodied in modifications its licensee may63* make.64*65* 3.3. Redistribution of Executable. Redistribution in executable form of any66* substantial portion of the Covered Code or modification must reproduce the67* above Copyright Notice, and the following Disclaimer and Export Compliance68* provision in the documentation and/or other materials provided with the69* distribution.70*71* 3.4. Intel retains all right, title, and interest in and to the Original72* Intel Code.73*74* 3.5. Neither the name Intel nor any other trademark owned or controlled by75* Intel shall be used in advertising or otherwise to promote the sale, use or76* other dealings in products derived from or relating to the Covered Code77* without prior written authorization from Intel.78*79* 4. Disclaimer and Export Compliance80*81* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED82* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE83* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,84* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY85* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY86* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A87* PARTICULAR PURPOSE.88*89* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES90* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR91* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,92* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY93* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL94* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS95* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY96* LIMITED REMEDY.97*98* 4.3. Licensee shall not export, either directly or indirectly, any of this99* software or system incorporating such software without first obtaining any100* required license or other approval from the U. S. Department of Commerce or101* any other agency or department of the United States Government. In the102* event Licensee exports any such software from the United States or103* re-exports any such software from a foreign destination, Licensee shall104* ensure that the distribution and export/re-export of the software is in105* compliance with all laws, regulations, orders, or other restrictions of the106* U.S. Export Administration Regulations. Licensee agrees that neither it nor107* any of its subsidiaries will export/re-export any technical data, process,108* software, or service, directly or indirectly, to any country for which the109* United States government or any agency thereof requires an export license,110* other governmental approval, or letter of assurance, without first obtaining111* such license, approval or letter.112*113*****************************************************************************114*115* Alternatively, you may choose to be licensed under the terms of the116* following license:117*118* Redistribution and use in source and binary forms, with or without119* modification, are permitted provided that the following conditions120* are met:121* 1. Redistributions of source code must retain the above copyright122* notice, this list of conditions, and the following disclaimer,123* without modification.124* 2. Redistributions in binary form must reproduce at minimum a disclaimer125* substantially similar to the "NO WARRANTY" disclaimer below126* ("Disclaimer") and any redistribution must be conditioned upon127* including a substantially similar Disclaimer requirement for further128* binary redistribution.129* 3. Neither the names of the above-listed copyright holders nor the names130* of any contributors may be used to endorse or promote products derived131* from this software without specific prior written permission.132*133* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS134* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT135* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR136* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT137* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,138* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT139* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,140* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY141* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT142* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE143* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.144*145* Alternatively, you may choose to be licensed under the terms of the146* GNU General Public License ("GPL") version 2 as published by the Free147* Software Foundation.148*149*****************************************************************************/150151#include <contrib/dev/acpica/include/acpi.h>152#include <contrib/dev/acpica/include/accommon.h>153#include <contrib/dev/acpica/include/actables.h>154#include <contrib/dev/acpica/include/acutils.h>155#include <contrib/dev/acpica/include/acapps.h>156157#define _COMPONENT ACPI_UTILITIES158ACPI_MODULE_NAME ("acfileio")159160161/* Local prototypes */162163static ACPI_STATUS164AcGetOneTableFromFile (165char *Filename,166FILE *File,167UINT8 GetOnlyAmlTables,168ACPI_TABLE_HEADER **Table);169170static ACPI_STATUS171AcCheckTextModeCorruption (172ACPI_TABLE_HEADER *Table);173174175/*******************************************************************************176*177* FUNCTION: AcDeleteTableList178*179* PARAMETERS: ListHead - List to delete180*181* RETURN: Status182*183* DESCRIPTION: Delete a list of tables. This is useful for removing memory184* allocated by AcGetAllTablesFromFile185*186******************************************************************************/187188void189AcDeleteTableList (190ACPI_NEW_TABLE_DESC *ListHead)191{192ACPI_NEW_TABLE_DESC *Current = ListHead;193ACPI_NEW_TABLE_DESC *Previous = Current;194195196while (Current)197{198Current = Current->Next;199AcpiOsFree (Previous);200Previous = Current;201}202}203204205/*******************************************************************************206*207* FUNCTION: AcGetAllTablesFromFile208*209* PARAMETERS: Filename - Table filename210* GetOnlyAmlTables - TRUE if the tables must be AML tables211* ReturnListHead - Where table list is returned212*213* RETURN: Status214*215* DESCRIPTION: Get all ACPI tables from within a single file.216*217******************************************************************************/218219ACPI_STATUS220AcGetAllTablesFromFile (221char *Filename,222UINT8 GetOnlyAmlTables,223ACPI_NEW_TABLE_DESC **ReturnListHead)224{225ACPI_NEW_TABLE_DESC *ListHead = NULL;226ACPI_NEW_TABLE_DESC *ListTail = NULL;227ACPI_NEW_TABLE_DESC *TableDesc;228FILE *File;229ACPI_TABLE_HEADER *Table = NULL;230UINT32 FileSize;231ACPI_STATUS Status = AE_OK;232233234File = fopen (Filename, "rb");235if (!File)236{237fprintf (stderr, "Could not open input file: %s\n", Filename);238if (errno == ENOENT)239{240return (AE_NOT_EXIST);241}242243return (AE_ERROR);244}245246/* Get the file size */247248FileSize = CmGetFileSize (File);249if (FileSize == ACPI_UINT32_MAX)250{251Status = AE_ERROR;252goto Exit;253}254255fprintf (stderr,256"Input file %s, Length 0x%X (%u) bytes\n",257Filename, FileSize, FileSize);258259/* We must have at least one ACPI table header */260261if (FileSize < sizeof (ACPI_TABLE_HEADER))262{263Status = AE_BAD_HEADER;264goto Exit;265}266267/* Check for an non-binary file */268269if (!AcIsFileBinary (File))270{271fprintf (stderr,272" %s: File does not appear to contain a valid AML table\n",273Filename);274Status = AE_TYPE;275goto Exit;276}277278/* Read all tables within the file */279280while (ACPI_SUCCESS (Status))281{282/* Get one entire ACPI table */283284Status = AcGetOneTableFromFile (285Filename, File, GetOnlyAmlTables, &Table);286287if (Status == AE_CTRL_TERMINATE)288{289Status = AE_OK;290break;291}292else if (Status == AE_TYPE)293{294Status = AE_OK;295goto Exit;296}297else if (ACPI_FAILURE (Status))298{299goto Exit;300}301302/* Print table header for iASL/disassembler only */303304#ifdef ACPI_ASL_COMPILER305306AcpiTbPrintTableHeader (0, Table);307#endif308309/* Allocate and link a table descriptor */310311TableDesc = AcpiOsAllocate (sizeof (ACPI_NEW_TABLE_DESC));312if (!TableDesc)313{314AcpiOsFree (Table);315Status = AE_NO_MEMORY;316goto Exit;317}318319TableDesc->Table = Table;320TableDesc->Next = NULL;321322/* Link at the end of the local table list */323324if (!ListHead)325{326ListHead = TableDesc;327ListTail = TableDesc;328}329else330{331ListTail->Next = TableDesc;332ListTail = TableDesc;333}334}335336/* Add the local table list to the end of the global list */337338if (*ReturnListHead)339{340ListTail = *ReturnListHead;341while (ListTail->Next)342{343ListTail = ListTail->Next;344}345346ListTail->Next = ListHead;347}348else349{350*ReturnListHead = ListHead;351}352353Exit:354fclose(File);355return (Status);356}357358359/*******************************************************************************360*361* FUNCTION: AcGetOneTableFromFile362*363* PARAMETERS: Filename - File where table is located364* File - Open FILE pointer to Filename365* GetOnlyAmlTables - TRUE if the tables must be AML tables.366* ReturnTable - Where a pointer to the table is returned367*368* RETURN: Status369*370* DESCRIPTION: Read the next ACPI table from a file. Implements support371* for multiple tables within a single file. File must already372* be open.373*374* Note: Loading an RSDP is not supported.375*376******************************************************************************/377378static ACPI_STATUS379AcGetOneTableFromFile (380char *Filename,381FILE *File,382UINT8 GetOnlyAmlTables,383ACPI_TABLE_HEADER **ReturnTable)384{385ACPI_STATUS Status = AE_OK;386ACPI_TABLE_HEADER TableHeader;387ACPI_TABLE_HEADER *Table;388INT32 Count;389UINT32 TableLength;390UINT32 HeaderLength;391long TableOffset = 0;392393*ReturnTable = NULL;394395/* Get the table header to examine signature and length */396/*397* Special handling for the CDAT table (both the Length field398* and the Checksum field are not in the standard positions).399* (The table header is non-standard).400*/401if (AcpiGbl_CDAT)402{403HeaderLength = sizeof (ACPI_TABLE_CDAT);404}405else406{407HeaderLength = sizeof (ACPI_TABLE_HEADER);408}409410Status = AcValidateTableHeader (File, TableOffset);411if (ACPI_FAILURE (Status))412{413return (Status);414}415416TableOffset = ftell (File);417Count = fread (&TableHeader, 1, HeaderLength, File);418if (Count != (INT32) HeaderLength)419{420return (AE_CTRL_TERMINATE);421}422423if (GetOnlyAmlTables)424{425/* Validate the table signature/header (limited ASCII chars) */426427/*428* Table must be an AML table (DSDT/SSDT).429* Used for iASL -e option only.430*/431if (!AcpiUtIsAmlTable (&TableHeader))432{433fprintf (stderr,434" %s: Table [%4.4s] is not an AML table - ignoring\n",435Filename, TableHeader.Signature);436437return (AE_TYPE);438}439}440441/*442* Special handling for the CDAT table (both the Length field443* and the Checksum field are not in the standard positions).444*/445if (AcpiGbl_CDAT)446{447TableLength = ACPI_CAST_PTR (ACPI_TABLE_CDAT, &TableHeader)->Length;448}449else450{451TableLength = TableHeader.Length;452}453454/* Allocate a buffer for the entire table */455456Table = AcpiOsAllocate ((ACPI_SIZE) TableLength);457if (!Table)458{459return (AE_NO_MEMORY);460}461462/* Read the entire ACPI table, including header */463464fseek (File, TableOffset, SEEK_SET);465Count = fread (Table, 1, TableLength, File);466467/*468* Checks for data table headers happen later in the execution. Only verify469* for Aml tables at this point in the code.470*/471if (GetOnlyAmlTables && Count != (INT32) TableLength)472{473Status = AE_ERROR;474goto ErrorExit;475}476477/*478* Validate the checksum (just issue a warning if incorrect).479* Note: CDAT is special cased here because the table does480* not have the checksum field in the standard position.481*/482if (AcpiGbl_CDAT)483{484Status = AcpiUtVerifyCdatChecksum ((ACPI_TABLE_CDAT *) Table, TableLength);485} else486{487Status = AcpiUtVerifyChecksum (Table, TableLength);488}489490if (ACPI_FAILURE (Status))491{492Status = AcCheckTextModeCorruption (Table);493if (ACPI_FAILURE (Status))494{495goto ErrorExit;496}497}498499*ReturnTable = Table;500return (AE_OK);501502503ErrorExit:504AcpiOsFree (Table);505return (Status);506}507508509/*******************************************************************************510*511* FUNCTION: AcIsFileBinary512*513* PARAMETERS: File - Open input file514*515* RETURN: TRUE if file appears to be binary516*517* DESCRIPTION: Scan a file for any non-ASCII bytes.518*519* Note: Maintains current file position.520*521******************************************************************************/522523BOOLEAN524AcIsFileBinary (525FILE *File)526{527UINT8 Byte;528BOOLEAN IsBinary = FALSE;529long FileOffset;530531532/* Scan entire file for any non-ASCII bytes */533534FileOffset = ftell (File);535while (fread (&Byte, 1, 1, File) == 1)536{537if (!isprint (Byte) && !isspace (Byte))538{539IsBinary = TRUE;540goto Exit;541}542}543544Exit:545fseek (File, FileOffset, SEEK_SET);546return (IsBinary);547}548549550/*******************************************************************************551*552* FUNCTION: AcValidateTableHeader553*554* PARAMETERS: File - Open input file555*556* RETURN: Status557*558* DESCRIPTION: Determine if a file seems to contain one or more binary ACPI559* tables, via the560* following checks on what would be the table header:561* 1) File must be at least as long as an ACPI_TABLE_HEADER562* 2) There must be enough room in the file to hold entire table563* 3) Signature, OemId, OemTableId, AslCompilerId must be ASCII564*565* Note: There can be multiple definition blocks per file, so we cannot566* expect/compare the file size to be equal to the table length. 12/2015.567*568* Note: Maintains current file position.569*570******************************************************************************/571572ACPI_STATUS573AcValidateTableHeader (574FILE *File,575long TableOffset)576{577ACPI_TABLE_HEADER TableHeader;578ACPI_TABLE_CDAT *CdatTableHeader = ACPI_CAST_PTR (ACPI_TABLE_CDAT, &TableHeader);579UINT32 HeaderLength;580ACPI_SIZE Actual;581long OriginalOffset;582UINT32 FileSize;583UINT32 i;584585586ACPI_FUNCTION_TRACE (AcValidateTableHeader);587588/* Determine the type of table header */589590if (AcpiGbl_CDAT)591{592HeaderLength = sizeof (ACPI_TABLE_CDAT);593}594else595{596HeaderLength = sizeof (ACPI_TABLE_HEADER);597}598599/* Read a potential table header */600601OriginalOffset = ftell (File);602if (fseek (File, TableOffset, SEEK_SET))603{604fprintf (stderr, "SEEK error\n");605}606Actual = fread (&TableHeader, 1, HeaderLength, File);607if (fseek (File, OriginalOffset, SEEK_SET))608{609fprintf (stderr, "SEEK error\n");610}611612if (Actual < HeaderLength)613{614fprintf (stderr,615"Could not read entire table header: Actual %u, Requested %u\n",616(UINT32) Actual, HeaderLength);617return (AE_ERROR);618}619620/* Validate the signature (limited ASCII chars) */621622if (!AcpiGbl_CDAT && !AcpiUtValidNameseg (TableHeader.Signature))623{624/*625* The "-ds cdat" option was not used, and the signature is not valid.626*627* For CDAT we are assuming that there should be at least one non-ASCII628* byte in the (normally) 4-character Signature field (at least the629* high-order byte should be zero). Otherwise, this is OK.630*/631fprintf (stderr,632"\nTable appears to be a CDAT table, which has no signature.\n"633"If this is in fact a CDAT table, use the -ds option on the\n"634"command line to specify the table type (signature):\n"635"\"iasl -d -ds CDAT <file>\" or \"iasl -ds CDAT -T CDAT\"\n\n");636637return (AE_BAD_SIGNATURE);638}639640/* Validate table length against bytes remaining in the file */641642FileSize = CmGetFileSize (File);643if (!AcpiGbl_CDAT)644{645/* Standard ACPI table header */646647if (TableHeader.Length > (UINT32) (FileSize - TableOffset))648{649fprintf (stderr, "Table [%4.4s] is too long for file - "650"needs: 0x%.2X, remaining in file: 0x%.2X\n",651TableHeader.Signature, TableHeader.Length,652(UINT32) (FileSize - TableOffset));653return (AE_BAD_HEADER);654}655}656else if (CdatTableHeader->Length > (UINT32) (FileSize - TableOffset))657{658/* Special header for CDAT table */659660fprintf (stderr, "Table [CDAT] is too long for file - "661"needs: 0x%.2X, remaining in file: 0x%.2X\n",662CdatTableHeader->Length,663(UINT32) (FileSize - TableOffset));664return (AE_BAD_HEADER);665}666667/* For CDAT table, there are no ASCII fields in the header, we are done */668669if (AcpiGbl_CDAT)670{671return (AE_OK);672}673674/*675* These standard fields must be ASCII: OemId, OemTableId, AslCompilerId.676* We allow a NULL terminator in OemId and OemTableId.677*/678for (i = 0; i < ACPI_NAMESEG_SIZE; i++)679{680if (!ACPI_IS_ASCII ((UINT8) TableHeader.AslCompilerId[i]))681{682goto BadCharacters;683}684}685686for (i = 0; (i < ACPI_OEM_ID_SIZE) && (TableHeader.OemId[i]); i++)687{688if (!ACPI_IS_ASCII ((UINT8) TableHeader.OemId[i]))689{690goto BadCharacters;691}692}693694for (i = 0; (i < ACPI_OEM_TABLE_ID_SIZE) && (TableHeader.OemTableId[i]); i++)695{696if (!ACPI_IS_ASCII ((UINT8) TableHeader.OemTableId[i]))697{698goto BadCharacters;699}700}701702return (AE_OK);703704705BadCharacters:706707ACPI_WARNING ((AE_INFO,708"Table header for [%4.4s] has invalid ASCII character(s)",709TableHeader.Signature));710return (AE_OK);711}712713714/*******************************************************************************715*716* FUNCTION: AcCheckTextModeCorruption717*718* PARAMETERS: Table - Table buffer starting with table header719*720* RETURN: Status721*722* DESCRIPTION: Check table for text mode file corruption where all linefeed723* characters (LF) have been replaced by carriage return linefeed724* pairs (CR/LF).725*726******************************************************************************/727728static ACPI_STATUS729AcCheckTextModeCorruption (730ACPI_TABLE_HEADER *Table)731{732UINT32 i;733UINT32 Pairs = 0;734UINT8 *Buffer = ACPI_CAST_PTR (UINT8, Table);735736737/* Scan entire table to determine if each LF has been prefixed with a CR */738739for (i = 1; i < Table->Length; i++)740{741if (Buffer[i] == 0x0A)742{743if (Buffer[i - 1] != 0x0D)744{745/* The LF does not have a preceding CR, table not corrupted */746747return (AE_OK);748}749else750{751/* Found a CR/LF pair */752753Pairs++;754}755756i++;757}758}759760if (!Pairs)761{762return (AE_OK);763}764765/*766* Entire table scanned, each CR is part of a CR/LF pair --767* meaning that the table was treated as a text file somewhere.768*769* NOTE: We can't "fix" the table, because any existing CR/LF pairs in the770* original table are left untouched by the text conversion process --771* meaning that we cannot simply replace CR/LF pairs with LFs.772*/773AcpiOsPrintf ("Table has been corrupted by text mode conversion\n");774AcpiOsPrintf ("All LFs (%u) were changed to CR/LF pairs\n", Pairs);775AcpiOsPrintf ("Table cannot be repaired!\n");776777return (AE_BAD_VALUE);778}779780781