1 /****************************************************************************** 2 * 3 * Module Name: acfileio - Get ACPI tables from file 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include "acpi.h" 45 #include "accommon.h" 46 #include "acapps.h" 47 #include "actables.h" 48 #include "acutils.h" 49 #include <errno.h> 50 51 #define _COMPONENT ACPI_UTILITIES 52 ACPI_MODULE_NAME ("acfileio") 53 54 55 /* Local prototypes */ 56 57 static ACPI_STATUS 58 AcpiAcGetOneTableFromFile ( 59 char *Filename, 60 FILE *File, 61 UINT8 GetOnlyAmlTables, 62 ACPI_TABLE_HEADER **Table); 63 64 static ACPI_STATUS 65 AcpiAcCheckTextModeCorruption ( 66 ACPI_TABLE_HEADER *Table); 67 68 69 /******************************************************************************* 70 * 71 * FUNCTION: AcpiAcGetAllTablesFromFile 72 * 73 * PARAMETERS: Filename - Table filename 74 * GetOnlyAmlTables - TRUE if the tables must be AML tables 75 * ReturnListHead - Where table list is returned 76 * 77 * RETURN: Status 78 * 79 * DESCRIPTION: Get all ACPI tables from within a single file. 80 * 81 ******************************************************************************/ 82 83 ACPI_STATUS 84 AcpiAcGetAllTablesFromFile ( 85 char *Filename, 86 UINT8 GetOnlyAmlTables, 87 ACPI_NEW_TABLE_DESC **ReturnListHead) 88 { 89 ACPI_NEW_TABLE_DESC *ListHead = NULL; 90 ACPI_NEW_TABLE_DESC *ListTail = NULL; 91 ACPI_NEW_TABLE_DESC *TableDesc; 92 FILE *File; 93 ACPI_TABLE_HEADER *Table = NULL; 94 UINT32 FileSize; 95 ACPI_STATUS Status = AE_OK; 96 97 98 File = fopen (Filename, "rb"); 99 if (!File) 100 { 101 perror ("Could not open input file"); 102 if (errno == ENOENT) 103 { 104 return (AE_NOT_EXIST); 105 } 106 107 return (AE_ERROR); 108 } 109 110 /* Get the file size */ 111 112 FileSize = CmGetFileSize (File); 113 if (FileSize == ACPI_UINT32_MAX) 114 { 115 return (AE_ERROR); 116 } 117 118 if (FileSize < 4) 119 { 120 return (AE_BAD_HEADER); 121 } 122 123 /* Read all tables within the file */ 124 125 while (ACPI_SUCCESS (Status)) 126 { 127 /* Get one entire ACPI table */ 128 129 Status = AcpiAcGetOneTableFromFile ( 130 Filename, File, GetOnlyAmlTables, &Table); 131 if (Status == AE_CTRL_TERMINATE) 132 { 133 Status = AE_OK; 134 break; 135 } 136 else if (Status == AE_TYPE) 137 { 138 continue; 139 } 140 else if (ACPI_FAILURE (Status)) 141 { 142 return (Status); 143 } 144 145 /* Allocate and link a table descriptor */ 146 147 TableDesc = AcpiOsAllocate (sizeof (ACPI_NEW_TABLE_DESC)); 148 TableDesc->Table = Table; 149 TableDesc->Next = NULL; 150 151 /* Link at the end of the local table list */ 152 153 if (!ListHead) 154 { 155 ListHead = TableDesc; 156 ListTail = TableDesc; 157 } 158 else 159 { 160 ListTail->Next = TableDesc; 161 ListTail = TableDesc; 162 } 163 } 164 165 /* Add the local table list to the end of the global list */ 166 167 if (*ReturnListHead) 168 { 169 ListTail = *ReturnListHead; 170 while (ListTail->Next) 171 { 172 ListTail = ListTail->Next; 173 } 174 175 ListTail->Next = ListHead; 176 } 177 else 178 { 179 *ReturnListHead = ListHead; 180 } 181 182 fclose(File); 183 return (Status); 184 } 185 186 187 /******************************************************************************* 188 * 189 * FUNCTION: AcpiAcGetOneTableFromFile 190 * 191 * PARAMETERS: Filename - File where table is located 192 * File - Open FILE pointer to Filename 193 * GetOnlyAmlTables - TRUE if the tables must be AML tables. 194 * ReturnTable - Where a pointer to the table is returned 195 * 196 * RETURN: Status 197 * 198 * DESCRIPTION: Read the next ACPI table from a file. Implements support 199 * for multiple tables within a single file. File must already 200 * be open. 201 * 202 * Note: Loading an RSDP is not supported. 203 * 204 ******************************************************************************/ 205 206 static ACPI_STATUS 207 AcpiAcGetOneTableFromFile ( 208 char *Filename, 209 FILE *File, 210 UINT8 GetOnlyAmlTables, 211 ACPI_TABLE_HEADER **ReturnTable) 212 { 213 ACPI_STATUS Status = AE_OK; 214 ACPI_TABLE_HEADER TableHeader; 215 ACPI_TABLE_HEADER *Table; 216 INT32 Count; 217 long Position; 218 219 220 *ReturnTable = NULL; 221 222 223 /* Get just the table header to get signature and length */ 224 225 Position = ftell (File); 226 Count = fread (&TableHeader, 1, sizeof (ACPI_TABLE_HEADER), File); 227 if (Count != sizeof (ACPI_TABLE_HEADER)) 228 { 229 return (AE_CTRL_TERMINATE); 230 } 231 232 if (GetOnlyAmlTables) 233 { 234 /* Table must be an AML table (DSDT/SSDT) or FADT */ 235 236 if (!ACPI_COMPARE_NAME (TableHeader.Signature, ACPI_SIG_FADT) && 237 !AcpiUtIsAmlTable (&TableHeader)) 238 { 239 fprintf (stderr, 240 " %s: [%4.4s] is not an AML table - ignoring\n", 241 Filename, TableHeader.Signature); 242 243 return (AE_TYPE); 244 } 245 } 246 247 /* Allocate a buffer for the entire table */ 248 249 Table = AcpiOsAllocate ((size_t) TableHeader.Length); 250 if (!Table) 251 { 252 return (AE_NO_MEMORY); 253 } 254 255 /* Now read the entire table */ 256 257 fseek (File, Position, SEEK_SET); 258 259 Count = fread (Table, 1, TableHeader.Length, File); 260 if (Count != (INT32) TableHeader.Length) 261 { 262 Status = AE_ERROR; 263 goto ErrorExit; 264 } 265 266 /* Validate the checksum (just issue a warning) */ 267 268 Status = AcpiTbVerifyChecksum (Table, TableHeader.Length); 269 if (ACPI_FAILURE (Status)) 270 { 271 Status = AcpiAcCheckTextModeCorruption (Table); 272 if (ACPI_FAILURE (Status)) 273 { 274 goto ErrorExit; 275 } 276 } 277 278 fprintf (stderr, 279 "Loading ACPI table [%4.4s] from file %12s - Length 0x%06X (%u)\n", 280 TableHeader.Signature, Filename, 281 TableHeader.Length, TableHeader.Length); 282 283 *ReturnTable = Table; 284 return (AE_OK); 285 286 287 ErrorExit: 288 AcpiOsFree (Table); 289 return (Status); 290 } 291 292 293 /******************************************************************************* 294 * 295 * FUNCTION: AcpiAcCheckTextModeCorruption 296 * 297 * PARAMETERS: Table - Table buffer starting with table header 298 * 299 * RETURN: Status 300 * 301 * DESCRIPTION: Check table for text mode file corruption where all linefeed 302 * characters (LF) have been replaced by carriage return linefeed 303 * pairs (CR/LF). 304 * 305 ******************************************************************************/ 306 307 static ACPI_STATUS 308 AcpiAcCheckTextModeCorruption ( 309 ACPI_TABLE_HEADER *Table) 310 { 311 UINT32 i; 312 UINT32 Pairs = 0; 313 UINT8 *Buffer = ACPI_CAST_PTR (UINT8, Table); 314 315 316 /* Scan entire table to determine if each LF has been prefixed with a CR */ 317 318 for (i = 1; i < Table->Length; i++) 319 { 320 if (Buffer[i] == 0x0A) 321 { 322 if (Buffer[i - 1] != 0x0D) 323 { 324 /* The LF does not have a preceding CR, table not corrupted */ 325 326 return (AE_OK); 327 } 328 else 329 { 330 /* Found a CR/LF pair */ 331 332 Pairs++; 333 } 334 335 i++; 336 } 337 } 338 339 if (!Pairs) 340 { 341 return (AE_OK); 342 } 343 344 /* 345 * Entire table scanned, each CR is part of a CR/LF pair -- 346 * meaning that the table was treated as a text file somewhere. 347 * 348 * NOTE: We can't "fix" the table, because any existing CR/LF pairs in the 349 * original table are left untouched by the text conversion process -- 350 * meaning that we cannot simply replace CR/LF pairs with LFs. 351 */ 352 AcpiOsPrintf ("Table has been corrupted by text mode conversion\n"); 353 AcpiOsPrintf ("All LFs (%u) were changed to CR/LF pairs\n", Pairs); 354 AcpiOsPrintf ("Table cannot be repaired!\n"); 355 356 return (AE_BAD_VALUE); 357 } 358