1/******************************************************************************* 2 * 3 * Module Name: utfileio - simple file I/O routines 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 <contrib/dev/acpica/include/acpi.h> 45#include <contrib/dev/acpica/include/accommon.h> 46#include <contrib/dev/acpica/include/actables.h> 47#include <contrib/dev/acpica/include/acapps.h> 48 49#ifdef ACPI_ASL_COMPILER 50#include <contrib/dev/acpica/compiler/aslcompiler.h> 51#endif 52 53 54#define _COMPONENT ACPI_CA_DEBUGGER 55 ACPI_MODULE_NAME ("utfileio") 56 57 58#ifdef ACPI_APPLICATION 59 60/* Local prototypes */ 61 62static ACPI_STATUS 63AcpiUtCheckTextModeCorruption ( 64 UINT8 *Table, 65 UINT32 TableLength, 66 UINT32 FileLength); 67 68static ACPI_STATUS 69AcpiUtReadTable ( 70 FILE *fp, 71 ACPI_TABLE_HEADER **Table, 72 UINT32 *TableLength); 73 74 75/******************************************************************************* 76 * 77 * FUNCTION: AcpiUtCheckTextModeCorruption 78 * 79 * PARAMETERS: Table - Table buffer 80 * TableLength - Length of table from the table header 81 * FileLength - Length of the file that contains the table 82 * 83 * RETURN: Status 84 * 85 * DESCRIPTION: Check table for text mode file corruption where all linefeed 86 * characters (LF) have been replaced by carriage return linefeed 87 * pairs (CR/LF). 88 * 89 ******************************************************************************/ 90 91static ACPI_STATUS 92AcpiUtCheckTextModeCorruption ( 93 UINT8 *Table, 94 UINT32 TableLength, 95 UINT32 FileLength) 96{ 97 UINT32 i; 98 UINT32 Pairs = 0; 99 100 101 if (TableLength != FileLength) 102 { 103 ACPI_WARNING ((AE_INFO, 104 "File length (0x%X) is not the same as the table length (0x%X)", 105 FileLength, TableLength)); 106 } 107 108 /* Scan entire table to determine if each LF has been prefixed with a CR */ 109 110 for (i = 1; i < FileLength; i++) 111 { 112 if (Table[i] == 0x0A) 113 { 114 if (Table[i - 1] != 0x0D) 115 { 116 /* The LF does not have a preceding CR, table not corrupted */ 117 118 return (AE_OK); 119 } 120 else 121 { 122 /* Found a CR/LF pair */ 123 124 Pairs++; 125 } 126 i++; 127 } 128 } 129 130 if (!Pairs) 131 { 132 return (AE_OK); 133 } 134 135 /* 136 * Entire table scanned, each CR is part of a CR/LF pair -- 137 * meaning that the table was treated as a text file somewhere. 138 * 139 * NOTE: We can't "fix" the table, because any existing CR/LF pairs in the 140 * original table are left untouched by the text conversion process -- 141 * meaning that we cannot simply replace CR/LF pairs with LFs. 142 */ 143 AcpiOsPrintf ("Table has been corrupted by text mode conversion\n"); 144 AcpiOsPrintf ("All LFs (%u) were changed to CR/LF pairs\n", Pairs); 145 AcpiOsPrintf ("Table cannot be repaired!\n"); 146 return (AE_BAD_VALUE); 147} 148 149 150/******************************************************************************* 151 * 152 * FUNCTION: AcpiUtReadTable 153 * 154 * PARAMETERS: fp - File that contains table 155 * Table - Return value, buffer with table 156 * TableLength - Return value, length of table 157 * 158 * RETURN: Status 159 * 160 * DESCRIPTION: Load the DSDT from the file pointer 161 * 162 ******************************************************************************/ 163 164static ACPI_STATUS 165AcpiUtReadTable ( 166 FILE *fp, 167 ACPI_TABLE_HEADER **Table, 168 UINT32 *TableLength) 169{ 170 ACPI_TABLE_HEADER TableHeader; 171 UINT32 Actual; 172 ACPI_STATUS Status; 173 UINT32 FileSize; 174 BOOLEAN StandardHeader = TRUE; 175 INT32 Count; 176 177 /* Get the file size */ 178 179 FileSize = CmGetFileSize (fp); 180 if (FileSize == ACPI_UINT32_MAX) 181 { 182 return (AE_ERROR); 183 } 184 185 if (FileSize < 4) 186 { 187 return (AE_BAD_HEADER); 188 } 189 190 /* Read the signature */ 191 192 fseek (fp, 0, SEEK_SET); 193 194 Count = fread (&TableHeader, 1, sizeof (ACPI_TABLE_HEADER), fp); 195 if (Count != sizeof (ACPI_TABLE_HEADER)) 196 { 197 AcpiOsPrintf ("Could not read the table header\n"); 198 return (AE_BAD_HEADER); 199 } 200 201 /* The RSDP table does not have standard ACPI header */ 202 203 if (ACPI_VALIDATE_RSDP_SIG (TableHeader.Signature)) 204 { 205 *TableLength = FileSize; 206 StandardHeader = FALSE; 207 } 208 else 209 { 210 211#if 0 212 /* Validate the table header/length */ 213 214 Status = AcpiTbValidateTableHeader (&TableHeader); 215 if (ACPI_FAILURE (Status)) 216 { 217 AcpiOsPrintf ("Table header is invalid!\n"); 218 return (Status); 219 } 220#endif 221 222 /* File size must be at least as long as the Header-specified length */ 223 224 if (TableHeader.Length > FileSize) 225 { 226 AcpiOsPrintf ( 227 "TableHeader length [0x%X] greater than the input file size [0x%X]\n", 228 TableHeader.Length, FileSize); 229 230#ifdef ACPI_ASL_COMPILER 231 AcpiOsPrintf ("File is corrupt or is ASCII text -- " 232 "it must be a binary file\n"); 233#endif 234 return (AE_BAD_HEADER); 235 } 236 237#ifdef ACPI_OBSOLETE_CODE 238 /* We only support a limited number of table types */ 239 240 if (!ACPI_COMPARE_NAME ((char *) TableHeader.Signature, ACPI_SIG_DSDT) && 241 !ACPI_COMPARE_NAME ((char *) TableHeader.Signature, ACPI_SIG_PSDT) && 242 !ACPI_COMPARE_NAME ((char *) TableHeader.Signature, ACPI_SIG_SSDT)) 243 { 244 AcpiOsPrintf ("Table signature [%4.4s] is invalid or not supported\n", 245 (char *) TableHeader.Signature); 246 ACPI_DUMP_BUFFER (&TableHeader, sizeof (ACPI_TABLE_HEADER)); 247 return (AE_ERROR); 248 } 249#endif 250 251 *TableLength = TableHeader.Length; 252 } 253 254 /* Allocate a buffer for the table */ 255 256 *Table = AcpiOsAllocate ((size_t) FileSize); 257 if (!*Table) 258 { 259 AcpiOsPrintf ( 260 "Could not allocate memory for ACPI table %4.4s (size=0x%X)\n", 261 TableHeader.Signature, *TableLength); 262 return (AE_NO_MEMORY); 263 } 264 265 /* Get the rest of the table */ 266 267 fseek (fp, 0, SEEK_SET); 268 Actual = fread (*Table, 1, (size_t) FileSize, fp); 269 if (Actual == FileSize) 270 { 271 if (StandardHeader) 272 { 273 /* Now validate the checksum */ 274 275 Status = AcpiTbVerifyChecksum ((void *) *Table, 276 ACPI_CAST_PTR (ACPI_TABLE_HEADER, *Table)->Length); 277 278 if (Status == AE_BAD_CHECKSUM) 279 { 280 Status = AcpiUtCheckTextModeCorruption ((UINT8 *) *Table, 281 FileSize, (*Table)->Length); 282 return (Status); 283 } 284 } 285 return (AE_OK); 286 } 287 288 if (Actual > 0) 289 { 290 AcpiOsPrintf ("Warning - reading table, asked for %X got %X\n", 291 FileSize, Actual); 292 return (AE_OK); 293 } 294 295 AcpiOsPrintf ("Error - could not read the table file\n"); 296 AcpiOsFree (*Table); 297 *Table = NULL; 298 *TableLength = 0; 299 return (AE_ERROR); 300} 301 302 303/******************************************************************************* 304 * 305 * FUNCTION: AcpiUtReadTableFromFile 306 * 307 * PARAMETERS: Filename - File where table is located 308 * Table - Where a pointer to the table is returned 309 * 310 * RETURN: Status 311 * 312 * DESCRIPTION: Get an ACPI table from a file 313 * 314 ******************************************************************************/ 315 316ACPI_STATUS 317AcpiUtReadTableFromFile ( 318 char *Filename, 319 ACPI_TABLE_HEADER **Table) 320{ 321 FILE *File; 322 UINT32 FileSize; 323 UINT32 TableLength; 324 ACPI_STATUS Status = AE_ERROR; 325 326 327 /* Open the file, get current size */ 328 329 File = fopen (Filename, "rb"); 330 if (!File) 331 { 332 perror ("Could not open input file"); 333 return (Status); 334 } 335 336 FileSize = CmGetFileSize (File); 337 if (FileSize == ACPI_UINT32_MAX) 338 { 339 goto Exit; 340 } 341 342 /* Get the entire file */ 343 344 fprintf (stderr, "Reading ACPI table from file %10s - Length %.8u (0x%06X)\n", 345 Filename, FileSize, FileSize); 346 347 Status = AcpiUtReadTable (File, Table, &TableLength); 348 if (ACPI_FAILURE (Status)) 349 { 350 AcpiOsPrintf ("Could not get table from the file\n"); 351 } 352 353Exit: 354 fclose(File); 355 return (Status); 356} 357 358#endif 359