1*f8146b88SJung-uk Kim /****************************************************************************** 2*f8146b88SJung-uk Kim * 3*f8146b88SJung-uk Kim * Module Name: acfileio - Get ACPI tables from file 4*f8146b88SJung-uk Kim * 5*f8146b88SJung-uk Kim *****************************************************************************/ 6*f8146b88SJung-uk Kim 7*f8146b88SJung-uk Kim /* 8*f8146b88SJung-uk Kim * Copyright (C) 2000 - 2016, Intel Corp. 9*f8146b88SJung-uk Kim * All rights reserved. 10*f8146b88SJung-uk Kim * 11*f8146b88SJung-uk Kim * Redistribution and use in source and binary forms, with or without 12*f8146b88SJung-uk Kim * modification, are permitted provided that the following conditions 13*f8146b88SJung-uk Kim * are met: 14*f8146b88SJung-uk Kim * 1. Redistributions of source code must retain the above copyright 15*f8146b88SJung-uk Kim * notice, this list of conditions, and the following disclaimer, 16*f8146b88SJung-uk Kim * without modification. 17*f8146b88SJung-uk Kim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18*f8146b88SJung-uk Kim * substantially similar to the "NO WARRANTY" disclaimer below 19*f8146b88SJung-uk Kim * ("Disclaimer") and any redistribution must be conditioned upon 20*f8146b88SJung-uk Kim * including a substantially similar Disclaimer requirement for further 21*f8146b88SJung-uk Kim * binary redistribution. 22*f8146b88SJung-uk Kim * 3. Neither the names of the above-listed copyright holders nor the names 23*f8146b88SJung-uk Kim * of any contributors may be used to endorse or promote products derived 24*f8146b88SJung-uk Kim * from this software without specific prior written permission. 25*f8146b88SJung-uk Kim * 26*f8146b88SJung-uk Kim * Alternatively, this software may be distributed under the terms of the 27*f8146b88SJung-uk Kim * GNU General Public License ("GPL") version 2 as published by the Free 28*f8146b88SJung-uk Kim * Software Foundation. 29*f8146b88SJung-uk Kim * 30*f8146b88SJung-uk Kim * NO WARRANTY 31*f8146b88SJung-uk Kim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32*f8146b88SJung-uk Kim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33*f8146b88SJung-uk Kim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34*f8146b88SJung-uk Kim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35*f8146b88SJung-uk Kim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36*f8146b88SJung-uk Kim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37*f8146b88SJung-uk Kim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38*f8146b88SJung-uk Kim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39*f8146b88SJung-uk Kim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40*f8146b88SJung-uk Kim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41*f8146b88SJung-uk Kim * POSSIBILITY OF SUCH DAMAGES. 42*f8146b88SJung-uk Kim */ 43*f8146b88SJung-uk Kim 44*f8146b88SJung-uk Kim #include <contrib/dev/acpica/include/acpi.h> 45*f8146b88SJung-uk Kim #include <contrib/dev/acpica/include/accommon.h> 46*f8146b88SJung-uk Kim #include <contrib/dev/acpica/include/acapps.h> 47*f8146b88SJung-uk Kim #include <contrib/dev/acpica/include/actables.h> 48*f8146b88SJung-uk Kim #include <contrib/dev/acpica/include/acutils.h> 49*f8146b88SJung-uk Kim #include <errno.h> 50*f8146b88SJung-uk Kim 51*f8146b88SJung-uk Kim #define _COMPONENT ACPI_UTILITIES 52*f8146b88SJung-uk Kim ACPI_MODULE_NAME ("acfileio") 53*f8146b88SJung-uk Kim 54*f8146b88SJung-uk Kim 55*f8146b88SJung-uk Kim /* Local prototypes */ 56*f8146b88SJung-uk Kim 57*f8146b88SJung-uk Kim static ACPI_STATUS 58*f8146b88SJung-uk Kim AcGetOneTableFromFile ( 59*f8146b88SJung-uk Kim char *Filename, 60*f8146b88SJung-uk Kim FILE *File, 61*f8146b88SJung-uk Kim UINT8 GetOnlyAmlTables, 62*f8146b88SJung-uk Kim ACPI_TABLE_HEADER **Table); 63*f8146b88SJung-uk Kim 64*f8146b88SJung-uk Kim static ACPI_STATUS 65*f8146b88SJung-uk Kim AcCheckTextModeCorruption ( 66*f8146b88SJung-uk Kim ACPI_TABLE_HEADER *Table); 67*f8146b88SJung-uk Kim 68*f8146b88SJung-uk Kim 69*f8146b88SJung-uk Kim /******************************************************************************* 70*f8146b88SJung-uk Kim * 71*f8146b88SJung-uk Kim * FUNCTION: AcGetAllTablesFromFile 72*f8146b88SJung-uk Kim * 73*f8146b88SJung-uk Kim * PARAMETERS: Filename - Table filename 74*f8146b88SJung-uk Kim * GetOnlyAmlTables - TRUE if the tables must be AML tables 75*f8146b88SJung-uk Kim * ReturnListHead - Where table list is returned 76*f8146b88SJung-uk Kim * 77*f8146b88SJung-uk Kim * RETURN: Status 78*f8146b88SJung-uk Kim * 79*f8146b88SJung-uk Kim * DESCRIPTION: Get all ACPI tables from within a single file. 80*f8146b88SJung-uk Kim * 81*f8146b88SJung-uk Kim ******************************************************************************/ 82*f8146b88SJung-uk Kim 83*f8146b88SJung-uk Kim ACPI_STATUS 84*f8146b88SJung-uk Kim AcGetAllTablesFromFile ( 85*f8146b88SJung-uk Kim char *Filename, 86*f8146b88SJung-uk Kim UINT8 GetOnlyAmlTables, 87*f8146b88SJung-uk Kim ACPI_NEW_TABLE_DESC **ReturnListHead) 88*f8146b88SJung-uk Kim { 89*f8146b88SJung-uk Kim ACPI_NEW_TABLE_DESC *ListHead = NULL; 90*f8146b88SJung-uk Kim ACPI_NEW_TABLE_DESC *ListTail = NULL; 91*f8146b88SJung-uk Kim ACPI_NEW_TABLE_DESC *TableDesc; 92*f8146b88SJung-uk Kim FILE *File; 93*f8146b88SJung-uk Kim ACPI_TABLE_HEADER *Table = NULL; 94*f8146b88SJung-uk Kim UINT32 FileSize; 95*f8146b88SJung-uk Kim ACPI_STATUS Status = AE_OK; 96*f8146b88SJung-uk Kim 97*f8146b88SJung-uk Kim 98*f8146b88SJung-uk Kim File = fopen (Filename, "rb"); 99*f8146b88SJung-uk Kim if (!File) 100*f8146b88SJung-uk Kim { 101*f8146b88SJung-uk Kim perror ("Could not open input file"); 102*f8146b88SJung-uk Kim if (errno == ENOENT) 103*f8146b88SJung-uk Kim { 104*f8146b88SJung-uk Kim return (AE_NOT_EXIST); 105*f8146b88SJung-uk Kim } 106*f8146b88SJung-uk Kim 107*f8146b88SJung-uk Kim return (AE_ERROR); 108*f8146b88SJung-uk Kim } 109*f8146b88SJung-uk Kim 110*f8146b88SJung-uk Kim /* Get the file size */ 111*f8146b88SJung-uk Kim 112*f8146b88SJung-uk Kim FileSize = CmGetFileSize (File); 113*f8146b88SJung-uk Kim if (FileSize == ACPI_UINT32_MAX) 114*f8146b88SJung-uk Kim { 115*f8146b88SJung-uk Kim Status = AE_ERROR; 116*f8146b88SJung-uk Kim goto ErrorExit; 117*f8146b88SJung-uk Kim } 118*f8146b88SJung-uk Kim 119*f8146b88SJung-uk Kim fprintf (stderr, 120*f8146b88SJung-uk Kim "Input file %s, Length 0x%X (%u) bytes\n", 121*f8146b88SJung-uk Kim Filename, FileSize, FileSize); 122*f8146b88SJung-uk Kim 123*f8146b88SJung-uk Kim /* We must have at least one ACPI table header */ 124*f8146b88SJung-uk Kim 125*f8146b88SJung-uk Kim if (FileSize < sizeof (ACPI_TABLE_HEADER)) 126*f8146b88SJung-uk Kim { 127*f8146b88SJung-uk Kim Status = AE_BAD_HEADER; 128*f8146b88SJung-uk Kim goto ErrorExit; 129*f8146b88SJung-uk Kim } 130*f8146b88SJung-uk Kim 131*f8146b88SJung-uk Kim /* Check for an non-binary file */ 132*f8146b88SJung-uk Kim 133*f8146b88SJung-uk Kim if (!AcIsFileBinary (File)) 134*f8146b88SJung-uk Kim { 135*f8146b88SJung-uk Kim fprintf (stderr, 136*f8146b88SJung-uk Kim " %s: File does not appear to contain a valid AML table\n", 137*f8146b88SJung-uk Kim Filename); 138*f8146b88SJung-uk Kim return (AE_TYPE); 139*f8146b88SJung-uk Kim } 140*f8146b88SJung-uk Kim 141*f8146b88SJung-uk Kim /* Read all tables within the file */ 142*f8146b88SJung-uk Kim 143*f8146b88SJung-uk Kim while (ACPI_SUCCESS (Status)) 144*f8146b88SJung-uk Kim { 145*f8146b88SJung-uk Kim /* Get one entire ACPI table */ 146*f8146b88SJung-uk Kim 147*f8146b88SJung-uk Kim Status = AcGetOneTableFromFile ( 148*f8146b88SJung-uk Kim Filename, File, GetOnlyAmlTables, &Table); 149*f8146b88SJung-uk Kim 150*f8146b88SJung-uk Kim if (Status == AE_CTRL_TERMINATE) 151*f8146b88SJung-uk Kim { 152*f8146b88SJung-uk Kim Status = AE_OK; 153*f8146b88SJung-uk Kim break; 154*f8146b88SJung-uk Kim } 155*f8146b88SJung-uk Kim else if (Status == AE_TYPE) 156*f8146b88SJung-uk Kim { 157*f8146b88SJung-uk Kim return (AE_OK); 158*f8146b88SJung-uk Kim } 159*f8146b88SJung-uk Kim else if (ACPI_FAILURE (Status)) 160*f8146b88SJung-uk Kim { 161*f8146b88SJung-uk Kim goto ErrorExit; 162*f8146b88SJung-uk Kim } 163*f8146b88SJung-uk Kim 164*f8146b88SJung-uk Kim /* Print table header for iASL/disassembler only */ 165*f8146b88SJung-uk Kim 166*f8146b88SJung-uk Kim #ifdef ACPI_ASL_COMPILER 167*f8146b88SJung-uk Kim 168*f8146b88SJung-uk Kim AcpiTbPrintTableHeader (0, Table); 169*f8146b88SJung-uk Kim #endif 170*f8146b88SJung-uk Kim 171*f8146b88SJung-uk Kim /* Allocate and link a table descriptor */ 172*f8146b88SJung-uk Kim 173*f8146b88SJung-uk Kim TableDesc = AcpiOsAllocate (sizeof (ACPI_NEW_TABLE_DESC)); 174*f8146b88SJung-uk Kim TableDesc->Table = Table; 175*f8146b88SJung-uk Kim TableDesc->Next = NULL; 176*f8146b88SJung-uk Kim 177*f8146b88SJung-uk Kim /* Link at the end of the local table list */ 178*f8146b88SJung-uk Kim 179*f8146b88SJung-uk Kim if (!ListHead) 180*f8146b88SJung-uk Kim { 181*f8146b88SJung-uk Kim ListHead = TableDesc; 182*f8146b88SJung-uk Kim ListTail = TableDesc; 183*f8146b88SJung-uk Kim } 184*f8146b88SJung-uk Kim else 185*f8146b88SJung-uk Kim { 186*f8146b88SJung-uk Kim ListTail->Next = TableDesc; 187*f8146b88SJung-uk Kim ListTail = TableDesc; 188*f8146b88SJung-uk Kim } 189*f8146b88SJung-uk Kim } 190*f8146b88SJung-uk Kim 191*f8146b88SJung-uk Kim /* Add the local table list to the end of the global list */ 192*f8146b88SJung-uk Kim 193*f8146b88SJung-uk Kim if (*ReturnListHead) 194*f8146b88SJung-uk Kim { 195*f8146b88SJung-uk Kim ListTail = *ReturnListHead; 196*f8146b88SJung-uk Kim while (ListTail->Next) 197*f8146b88SJung-uk Kim { 198*f8146b88SJung-uk Kim ListTail = ListTail->Next; 199*f8146b88SJung-uk Kim } 200*f8146b88SJung-uk Kim 201*f8146b88SJung-uk Kim ListTail->Next = ListHead; 202*f8146b88SJung-uk Kim } 203*f8146b88SJung-uk Kim else 204*f8146b88SJung-uk Kim { 205*f8146b88SJung-uk Kim *ReturnListHead = ListHead; 206*f8146b88SJung-uk Kim } 207*f8146b88SJung-uk Kim 208*f8146b88SJung-uk Kim ErrorExit: 209*f8146b88SJung-uk Kim fclose(File); 210*f8146b88SJung-uk Kim return (Status); 211*f8146b88SJung-uk Kim } 212*f8146b88SJung-uk Kim 213*f8146b88SJung-uk Kim 214*f8146b88SJung-uk Kim /******************************************************************************* 215*f8146b88SJung-uk Kim * 216*f8146b88SJung-uk Kim * FUNCTION: AcGetOneTableFromFile 217*f8146b88SJung-uk Kim * 218*f8146b88SJung-uk Kim * PARAMETERS: Filename - File where table is located 219*f8146b88SJung-uk Kim * File - Open FILE pointer to Filename 220*f8146b88SJung-uk Kim * GetOnlyAmlTables - TRUE if the tables must be AML tables. 221*f8146b88SJung-uk Kim * ReturnTable - Where a pointer to the table is returned 222*f8146b88SJung-uk Kim * 223*f8146b88SJung-uk Kim * RETURN: Status 224*f8146b88SJung-uk Kim * 225*f8146b88SJung-uk Kim * DESCRIPTION: Read the next ACPI table from a file. Implements support 226*f8146b88SJung-uk Kim * for multiple tables within a single file. File must already 227*f8146b88SJung-uk Kim * be open. 228*f8146b88SJung-uk Kim * 229*f8146b88SJung-uk Kim * Note: Loading an RSDP is not supported. 230*f8146b88SJung-uk Kim * 231*f8146b88SJung-uk Kim ******************************************************************************/ 232*f8146b88SJung-uk Kim 233*f8146b88SJung-uk Kim static ACPI_STATUS 234*f8146b88SJung-uk Kim AcGetOneTableFromFile ( 235*f8146b88SJung-uk Kim char *Filename, 236*f8146b88SJung-uk Kim FILE *File, 237*f8146b88SJung-uk Kim UINT8 GetOnlyAmlTables, 238*f8146b88SJung-uk Kim ACPI_TABLE_HEADER **ReturnTable) 239*f8146b88SJung-uk Kim { 240*f8146b88SJung-uk Kim ACPI_STATUS Status = AE_OK; 241*f8146b88SJung-uk Kim ACPI_TABLE_HEADER TableHeader; 242*f8146b88SJung-uk Kim ACPI_TABLE_HEADER *Table; 243*f8146b88SJung-uk Kim INT32 Count; 244*f8146b88SJung-uk Kim long TableOffset; 245*f8146b88SJung-uk Kim 246*f8146b88SJung-uk Kim 247*f8146b88SJung-uk Kim *ReturnTable = NULL; 248*f8146b88SJung-uk Kim 249*f8146b88SJung-uk Kim /* Get the table header to examine signature and length */ 250*f8146b88SJung-uk Kim 251*f8146b88SJung-uk Kim TableOffset = ftell (File); 252*f8146b88SJung-uk Kim Count = fread (&TableHeader, 1, sizeof (ACPI_TABLE_HEADER), File); 253*f8146b88SJung-uk Kim if (Count != sizeof (ACPI_TABLE_HEADER)) 254*f8146b88SJung-uk Kim { 255*f8146b88SJung-uk Kim return (AE_CTRL_TERMINATE); 256*f8146b88SJung-uk Kim } 257*f8146b88SJung-uk Kim 258*f8146b88SJung-uk Kim /* Validate the table signature/header (limited ASCII chars) */ 259*f8146b88SJung-uk Kim 260*f8146b88SJung-uk Kim Status = AcValidateTableHeader (File, TableOffset); 261*f8146b88SJung-uk Kim if (ACPI_FAILURE (Status)) 262*f8146b88SJung-uk Kim { 263*f8146b88SJung-uk Kim return (Status); 264*f8146b88SJung-uk Kim } 265*f8146b88SJung-uk Kim 266*f8146b88SJung-uk Kim if (GetOnlyAmlTables) 267*f8146b88SJung-uk Kim { 268*f8146b88SJung-uk Kim /* Table must be an AML table (DSDT/SSDT) or FADT */ 269*f8146b88SJung-uk Kim 270*f8146b88SJung-uk Kim if (!ACPI_COMPARE_NAME (TableHeader.Signature, ACPI_SIG_FADT) && 271*f8146b88SJung-uk Kim !AcpiUtIsAmlTable (&TableHeader)) 272*f8146b88SJung-uk Kim { 273*f8146b88SJung-uk Kim fprintf (stderr, 274*f8146b88SJung-uk Kim " %s: Table [%4.4s] is not an AML table - ignoring\n", 275*f8146b88SJung-uk Kim Filename, TableHeader.Signature); 276*f8146b88SJung-uk Kim 277*f8146b88SJung-uk Kim return (AE_TYPE); 278*f8146b88SJung-uk Kim } 279*f8146b88SJung-uk Kim } 280*f8146b88SJung-uk Kim 281*f8146b88SJung-uk Kim /* Allocate a buffer for the entire table */ 282*f8146b88SJung-uk Kim 283*f8146b88SJung-uk Kim Table = AcpiOsAllocate ((size_t) TableHeader.Length); 284*f8146b88SJung-uk Kim if (!Table) 285*f8146b88SJung-uk Kim { 286*f8146b88SJung-uk Kim return (AE_NO_MEMORY); 287*f8146b88SJung-uk Kim } 288*f8146b88SJung-uk Kim 289*f8146b88SJung-uk Kim /* Read the entire ACPI table, including header */ 290*f8146b88SJung-uk Kim 291*f8146b88SJung-uk Kim fseek (File, TableOffset, SEEK_SET); 292*f8146b88SJung-uk Kim 293*f8146b88SJung-uk Kim Count = fread (Table, 1, TableHeader.Length, File); 294*f8146b88SJung-uk Kim if (Count != (INT32) TableHeader.Length) 295*f8146b88SJung-uk Kim { 296*f8146b88SJung-uk Kim Status = AE_ERROR; 297*f8146b88SJung-uk Kim goto ErrorExit; 298*f8146b88SJung-uk Kim } 299*f8146b88SJung-uk Kim 300*f8146b88SJung-uk Kim /* Validate the checksum (just issue a warning) */ 301*f8146b88SJung-uk Kim 302*f8146b88SJung-uk Kim Status = AcpiTbVerifyChecksum (Table, TableHeader.Length); 303*f8146b88SJung-uk Kim if (ACPI_FAILURE (Status)) 304*f8146b88SJung-uk Kim { 305*f8146b88SJung-uk Kim Status = AcCheckTextModeCorruption (Table); 306*f8146b88SJung-uk Kim if (ACPI_FAILURE (Status)) 307*f8146b88SJung-uk Kim { 308*f8146b88SJung-uk Kim goto ErrorExit; 309*f8146b88SJung-uk Kim } 310*f8146b88SJung-uk Kim } 311*f8146b88SJung-uk Kim 312*f8146b88SJung-uk Kim *ReturnTable = Table; 313*f8146b88SJung-uk Kim return (AE_OK); 314*f8146b88SJung-uk Kim 315*f8146b88SJung-uk Kim 316*f8146b88SJung-uk Kim ErrorExit: 317*f8146b88SJung-uk Kim AcpiOsFree (Table); 318*f8146b88SJung-uk Kim return (Status); 319*f8146b88SJung-uk Kim } 320*f8146b88SJung-uk Kim 321*f8146b88SJung-uk Kim 322*f8146b88SJung-uk Kim /******************************************************************************* 323*f8146b88SJung-uk Kim * 324*f8146b88SJung-uk Kim * FUNCTION: AcIsFileBinary 325*f8146b88SJung-uk Kim * 326*f8146b88SJung-uk Kim * PARAMETERS: File - Open input file 327*f8146b88SJung-uk Kim * 328*f8146b88SJung-uk Kim * RETURN: TRUE if file appears to be binary 329*f8146b88SJung-uk Kim * 330*f8146b88SJung-uk Kim * DESCRIPTION: Scan a file for any non-ASCII bytes. 331*f8146b88SJung-uk Kim * 332*f8146b88SJung-uk Kim * Note: Maintains current file position. 333*f8146b88SJung-uk Kim * 334*f8146b88SJung-uk Kim ******************************************************************************/ 335*f8146b88SJung-uk Kim 336*f8146b88SJung-uk Kim BOOLEAN 337*f8146b88SJung-uk Kim AcIsFileBinary ( 338*f8146b88SJung-uk Kim FILE *File) 339*f8146b88SJung-uk Kim { 340*f8146b88SJung-uk Kim UINT8 Byte; 341*f8146b88SJung-uk Kim BOOLEAN IsBinary = FALSE; 342*f8146b88SJung-uk Kim long FileOffset; 343*f8146b88SJung-uk Kim 344*f8146b88SJung-uk Kim 345*f8146b88SJung-uk Kim /* Scan entire file for any non-ASCII bytes */ 346*f8146b88SJung-uk Kim 347*f8146b88SJung-uk Kim FileOffset = ftell (File); 348*f8146b88SJung-uk Kim while (fread (&Byte, 1, 1, File) == 1) 349*f8146b88SJung-uk Kim { 350*f8146b88SJung-uk Kim if (!isprint (Byte) && !isspace (Byte)) 351*f8146b88SJung-uk Kim { 352*f8146b88SJung-uk Kim IsBinary = TRUE; 353*f8146b88SJung-uk Kim goto Exit; 354*f8146b88SJung-uk Kim } 355*f8146b88SJung-uk Kim } 356*f8146b88SJung-uk Kim 357*f8146b88SJung-uk Kim Exit: 358*f8146b88SJung-uk Kim fseek (File, FileOffset, SEEK_SET); 359*f8146b88SJung-uk Kim return (IsBinary); 360*f8146b88SJung-uk Kim } 361*f8146b88SJung-uk Kim 362*f8146b88SJung-uk Kim 363*f8146b88SJung-uk Kim /******************************************************************************* 364*f8146b88SJung-uk Kim * 365*f8146b88SJung-uk Kim * FUNCTION: AcValidateTableHeader 366*f8146b88SJung-uk Kim * 367*f8146b88SJung-uk Kim * PARAMETERS: File - Open input file 368*f8146b88SJung-uk Kim * 369*f8146b88SJung-uk Kim * RETURN: Status 370*f8146b88SJung-uk Kim * 371*f8146b88SJung-uk Kim * DESCRIPTION: Determine if a file seems to contain one or more binary ACPI 372*f8146b88SJung-uk Kim * tables, via the 373*f8146b88SJung-uk Kim * following checks on what would be the table header: 374*f8146b88SJung-uk Kim * 1) File must be at least as long as an ACPI_TABLE_HEADER 375*f8146b88SJung-uk Kim * 2) There must be enough room in the file to hold entire table 376*f8146b88SJung-uk Kim * 3) Signature, OemId, OemTableId, AslCompilerId must be ASCII 377*f8146b88SJung-uk Kim * 378*f8146b88SJung-uk Kim * Note: There can be multiple definition blocks per file, so we cannot 379*f8146b88SJung-uk Kim * expect/compare the file size to be equal to the table length. 12/2015. 380*f8146b88SJung-uk Kim * 381*f8146b88SJung-uk Kim * Note: Maintains current file position. 382*f8146b88SJung-uk Kim * 383*f8146b88SJung-uk Kim ******************************************************************************/ 384*f8146b88SJung-uk Kim 385*f8146b88SJung-uk Kim ACPI_STATUS 386*f8146b88SJung-uk Kim AcValidateTableHeader ( 387*f8146b88SJung-uk Kim FILE *File, 388*f8146b88SJung-uk Kim long TableOffset) 389*f8146b88SJung-uk Kim { 390*f8146b88SJung-uk Kim ACPI_TABLE_HEADER TableHeader; 391*f8146b88SJung-uk Kim size_t Actual; 392*f8146b88SJung-uk Kim long OriginalOffset; 393*f8146b88SJung-uk Kim UINT32 FileSize; 394*f8146b88SJung-uk Kim UINT32 i; 395*f8146b88SJung-uk Kim 396*f8146b88SJung-uk Kim 397*f8146b88SJung-uk Kim ACPI_FUNCTION_TRACE ("AcValidateTableHeader"); 398*f8146b88SJung-uk Kim 399*f8146b88SJung-uk Kim 400*f8146b88SJung-uk Kim /* Read a potential table header */ 401*f8146b88SJung-uk Kim 402*f8146b88SJung-uk Kim OriginalOffset = ftell (File); 403*f8146b88SJung-uk Kim fseek (File, TableOffset, SEEK_SET); 404*f8146b88SJung-uk Kim 405*f8146b88SJung-uk Kim Actual = fread (&TableHeader, 1, sizeof (ACPI_TABLE_HEADER), File); 406*f8146b88SJung-uk Kim fseek (File, OriginalOffset, SEEK_SET); 407*f8146b88SJung-uk Kim 408*f8146b88SJung-uk Kim if (Actual < sizeof (ACPI_TABLE_HEADER)) 409*f8146b88SJung-uk Kim { 410*f8146b88SJung-uk Kim return (AE_ERROR); 411*f8146b88SJung-uk Kim } 412*f8146b88SJung-uk Kim 413*f8146b88SJung-uk Kim /* Validate the signature (limited ASCII chars) */ 414*f8146b88SJung-uk Kim 415*f8146b88SJung-uk Kim if (!AcpiUtValidNameseg (TableHeader.Signature)) 416*f8146b88SJung-uk Kim { 417*f8146b88SJung-uk Kim fprintf (stderr, "Invalid table signature: 0x%8.8X\n", 418*f8146b88SJung-uk Kim *ACPI_CAST_PTR (UINT32, TableHeader.Signature)); 419*f8146b88SJung-uk Kim return (AE_BAD_SIGNATURE); 420*f8146b88SJung-uk Kim } 421*f8146b88SJung-uk Kim 422*f8146b88SJung-uk Kim /* Validate table length against bytes remaining in the file */ 423*f8146b88SJung-uk Kim 424*f8146b88SJung-uk Kim FileSize = CmGetFileSize (File); 425*f8146b88SJung-uk Kim if (TableHeader.Length > (UINT32) (FileSize - TableOffset)) 426*f8146b88SJung-uk Kim { 427*f8146b88SJung-uk Kim fprintf (stderr, "Table [%4.4s] is too long for file - " 428*f8146b88SJung-uk Kim "needs: 0x%.2X, remaining in file: 0x%.2X\n", 429*f8146b88SJung-uk Kim TableHeader.Signature, TableHeader.Length, 430*f8146b88SJung-uk Kim (UINT32) (FileSize - TableOffset)); 431*f8146b88SJung-uk Kim return (AE_BAD_HEADER); 432*f8146b88SJung-uk Kim } 433*f8146b88SJung-uk Kim 434*f8146b88SJung-uk Kim /* 435*f8146b88SJung-uk Kim * These fields must be ASCII: OemId, OemTableId, AslCompilerId. 436*f8146b88SJung-uk Kim * We allow a NULL terminator in OemId and OemTableId. 437*f8146b88SJung-uk Kim */ 438*f8146b88SJung-uk Kim for (i = 0; i < ACPI_NAME_SIZE; i++) 439*f8146b88SJung-uk Kim { 440*f8146b88SJung-uk Kim if (!ACPI_IS_ASCII ((UINT8) TableHeader.AslCompilerId[i])) 441*f8146b88SJung-uk Kim { 442*f8146b88SJung-uk Kim goto BadCharacters; 443*f8146b88SJung-uk Kim } 444*f8146b88SJung-uk Kim } 445*f8146b88SJung-uk Kim 446*f8146b88SJung-uk Kim for (i = 0; (i < ACPI_OEM_ID_SIZE) && (TableHeader.OemId[i]); i++) 447*f8146b88SJung-uk Kim { 448*f8146b88SJung-uk Kim if (!ACPI_IS_ASCII ((UINT8) TableHeader.OemId[i])) 449*f8146b88SJung-uk Kim { 450*f8146b88SJung-uk Kim goto BadCharacters; 451*f8146b88SJung-uk Kim } 452*f8146b88SJung-uk Kim } 453*f8146b88SJung-uk Kim 454*f8146b88SJung-uk Kim for (i = 0; (i < ACPI_OEM_TABLE_ID_SIZE) && (TableHeader.OemTableId[i]); i++) 455*f8146b88SJung-uk Kim { 456*f8146b88SJung-uk Kim if (!ACPI_IS_ASCII ((UINT8) TableHeader.OemTableId[i])) 457*f8146b88SJung-uk Kim { 458*f8146b88SJung-uk Kim goto BadCharacters; 459*f8146b88SJung-uk Kim } 460*f8146b88SJung-uk Kim } 461*f8146b88SJung-uk Kim 462*f8146b88SJung-uk Kim return (AE_OK); 463*f8146b88SJung-uk Kim 464*f8146b88SJung-uk Kim 465*f8146b88SJung-uk Kim BadCharacters: 466*f8146b88SJung-uk Kim 467*f8146b88SJung-uk Kim ACPI_WARNING ((AE_INFO, 468*f8146b88SJung-uk Kim "Table header for [%4.4s] has invalid ASCII character(s)", 469*f8146b88SJung-uk Kim TableHeader.Signature)); 470*f8146b88SJung-uk Kim return (AE_OK); 471*f8146b88SJung-uk Kim } 472*f8146b88SJung-uk Kim 473*f8146b88SJung-uk Kim 474*f8146b88SJung-uk Kim /******************************************************************************* 475*f8146b88SJung-uk Kim * 476*f8146b88SJung-uk Kim * FUNCTION: AcCheckTextModeCorruption 477*f8146b88SJung-uk Kim * 478*f8146b88SJung-uk Kim * PARAMETERS: Table - Table buffer starting with table header 479*f8146b88SJung-uk Kim * 480*f8146b88SJung-uk Kim * RETURN: Status 481*f8146b88SJung-uk Kim * 482*f8146b88SJung-uk Kim * DESCRIPTION: Check table for text mode file corruption where all linefeed 483*f8146b88SJung-uk Kim * characters (LF) have been replaced by carriage return linefeed 484*f8146b88SJung-uk Kim * pairs (CR/LF). 485*f8146b88SJung-uk Kim * 486*f8146b88SJung-uk Kim ******************************************************************************/ 487*f8146b88SJung-uk Kim 488*f8146b88SJung-uk Kim static ACPI_STATUS 489*f8146b88SJung-uk Kim AcCheckTextModeCorruption ( 490*f8146b88SJung-uk Kim ACPI_TABLE_HEADER *Table) 491*f8146b88SJung-uk Kim { 492*f8146b88SJung-uk Kim UINT32 i; 493*f8146b88SJung-uk Kim UINT32 Pairs = 0; 494*f8146b88SJung-uk Kim UINT8 *Buffer = ACPI_CAST_PTR (UINT8, Table); 495*f8146b88SJung-uk Kim 496*f8146b88SJung-uk Kim 497*f8146b88SJung-uk Kim /* Scan entire table to determine if each LF has been prefixed with a CR */ 498*f8146b88SJung-uk Kim 499*f8146b88SJung-uk Kim for (i = 1; i < Table->Length; i++) 500*f8146b88SJung-uk Kim { 501*f8146b88SJung-uk Kim if (Buffer[i] == 0x0A) 502*f8146b88SJung-uk Kim { 503*f8146b88SJung-uk Kim if (Buffer[i - 1] != 0x0D) 504*f8146b88SJung-uk Kim { 505*f8146b88SJung-uk Kim /* The LF does not have a preceding CR, table not corrupted */ 506*f8146b88SJung-uk Kim 507*f8146b88SJung-uk Kim return (AE_OK); 508*f8146b88SJung-uk Kim } 509*f8146b88SJung-uk Kim else 510*f8146b88SJung-uk Kim { 511*f8146b88SJung-uk Kim /* Found a CR/LF pair */ 512*f8146b88SJung-uk Kim 513*f8146b88SJung-uk Kim Pairs++; 514*f8146b88SJung-uk Kim } 515*f8146b88SJung-uk Kim 516*f8146b88SJung-uk Kim i++; 517*f8146b88SJung-uk Kim } 518*f8146b88SJung-uk Kim } 519*f8146b88SJung-uk Kim 520*f8146b88SJung-uk Kim if (!Pairs) 521*f8146b88SJung-uk Kim { 522*f8146b88SJung-uk Kim return (AE_OK); 523*f8146b88SJung-uk Kim } 524*f8146b88SJung-uk Kim 525*f8146b88SJung-uk Kim /* 526*f8146b88SJung-uk Kim * Entire table scanned, each CR is part of a CR/LF pair -- 527*f8146b88SJung-uk Kim * meaning that the table was treated as a text file somewhere. 528*f8146b88SJung-uk Kim * 529*f8146b88SJung-uk Kim * NOTE: We can't "fix" the table, because any existing CR/LF pairs in the 530*f8146b88SJung-uk Kim * original table are left untouched by the text conversion process -- 531*f8146b88SJung-uk Kim * meaning that we cannot simply replace CR/LF pairs with LFs. 532*f8146b88SJung-uk Kim */ 533*f8146b88SJung-uk Kim AcpiOsPrintf ("Table has been corrupted by text mode conversion\n"); 534*f8146b88SJung-uk Kim AcpiOsPrintf ("All LFs (%u) were changed to CR/LF pairs\n", Pairs); 535*f8146b88SJung-uk Kim AcpiOsPrintf ("Table cannot be repaired!\n"); 536*f8146b88SJung-uk Kim 537*f8146b88SJung-uk Kim return (AE_BAD_VALUE); 538*f8146b88SJung-uk Kim } 539