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