| 1 | /****************************************************************************** | 
| 2 |  * | 
| 3 |  * Module Name: acfileio - Get ACPI tables from file | 
| 4 |  * | 
| 5 |  *****************************************************************************/ | 
| 6 |  | 
| 7 | /* | 
| 8 |  * Copyright (C) 2000 - 2019, 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 "actables.h" | 
| 47 | #include "acutils.h" | 
| 48 | #include "acapps.h" | 
| 49 |  | 
| 50 | #define _COMPONENT          ACPI_UTILITIES | 
| 51 |         ACPI_MODULE_NAME    ("acfileio" ) | 
| 52 |  | 
| 53 |  | 
| 54 | /* Local prototypes */ | 
| 55 |  | 
| 56 | static ACPI_STATUS | 
| 57 | AcGetOneTableFromFile ( | 
| 58 |     char                    *Filename, | 
| 59 |     FILE                    *File, | 
| 60 |     UINT8                   GetOnlyAmlTables, | 
| 61 |     ACPI_TABLE_HEADER       **Table); | 
| 62 |  | 
| 63 | static ACPI_STATUS | 
| 64 | AcCheckTextModeCorruption ( | 
| 65 |     ACPI_TABLE_HEADER       *Table); | 
| 66 |  | 
| 67 |  | 
| 68 | /******************************************************************************* | 
| 69 |  * | 
| 70 |  * FUNCTION:    AcDeleteTableList | 
| 71 |  * | 
| 72 |  * PARAMETERS:  ListHead            - List to delete | 
| 73 |  * | 
| 74 |  * RETURN:      Status | 
| 75 |  * | 
| 76 |  * DESCRIPTION: Delete a list of tables. This is useful for removing memory | 
| 77 |  *              allocated by AcGetAllTablesFromFile | 
| 78 |  * | 
| 79 |  ******************************************************************************/ | 
| 80 |  | 
| 81 | void | 
| 82 | AcDeleteTableList ( | 
| 83 |     ACPI_NEW_TABLE_DESC     *ListHead) | 
| 84 | { | 
| 85 |     ACPI_NEW_TABLE_DESC     *Current = ListHead; | 
| 86 |     ACPI_NEW_TABLE_DESC     *Previous = Current; | 
| 87 |  | 
| 88 |  | 
| 89 |     while (Current) | 
| 90 |     { | 
| 91 |         Current = Current->Next; | 
| 92 |         AcpiOsFree (Previous); | 
| 93 |         Previous = Current; | 
| 94 |     } | 
| 95 | } | 
| 96 |  | 
| 97 |  | 
| 98 | /******************************************************************************* | 
| 99 |  * | 
| 100 |  * FUNCTION:    AcGetAllTablesFromFile | 
| 101 |  * | 
| 102 |  * PARAMETERS:  Filename            - Table filename | 
| 103 |  *              GetOnlyAmlTables    - TRUE if the tables must be AML tables | 
| 104 |  *              ReturnListHead      - Where table list is returned | 
| 105 |  * | 
| 106 |  * RETURN:      Status | 
| 107 |  * | 
| 108 |  * DESCRIPTION: Get all ACPI tables from within a single file. | 
| 109 |  * | 
| 110 |  ******************************************************************************/ | 
| 111 |  | 
| 112 | ACPI_STATUS | 
| 113 | AcGetAllTablesFromFile ( | 
| 114 |     char                    *Filename, | 
| 115 |     UINT8                   GetOnlyAmlTables, | 
| 116 |     ACPI_NEW_TABLE_DESC     **ReturnListHead) | 
| 117 | { | 
| 118 |     ACPI_NEW_TABLE_DESC     *ListHead = NULL; | 
| 119 |     ACPI_NEW_TABLE_DESC     *ListTail = NULL; | 
| 120 |     ACPI_NEW_TABLE_DESC     *TableDesc; | 
| 121 |     FILE                    *File; | 
| 122 |     ACPI_TABLE_HEADER       *Table = NULL; | 
| 123 |     UINT32                  FileSize; | 
| 124 |     ACPI_STATUS             Status = AE_OK; | 
| 125 |  | 
| 126 |  | 
| 127 |     File = fopen (Filename, "rb" ); | 
| 128 |     if (!File) | 
| 129 |     { | 
| 130 |         fprintf (stderr, "Could not open input file: %s\n" , Filename); | 
| 131 |         if (errno == ENOENT) | 
| 132 |         { | 
| 133 |             return (AE_NOT_EXIST); | 
| 134 |         } | 
| 135 |  | 
| 136 |         return (AE_ERROR); | 
| 137 |     } | 
| 138 |  | 
| 139 |     /* Get the file size */ | 
| 140 |  | 
| 141 |     FileSize = CmGetFileSize (File); | 
| 142 |     if (FileSize == ACPI_UINT32_MAX) | 
| 143 |     { | 
| 144 |         Status = AE_ERROR; | 
| 145 |         goto Exit; | 
| 146 |     } | 
| 147 |  | 
| 148 |     fprintf (stderr, | 
| 149 |         "Input file %s, Length 0x%X (%u) bytes\n" , | 
| 150 |         Filename, FileSize, FileSize); | 
| 151 |  | 
| 152 |     /* We must have at least one ACPI table header */ | 
| 153 |  | 
| 154 |     if (FileSize < sizeof (ACPI_TABLE_HEADER)) | 
| 155 |     { | 
| 156 |         Status = AE_BAD_HEADER; | 
| 157 |         goto Exit; | 
| 158 |     } | 
| 159 |  | 
| 160 |     /* Check for an non-binary file */ | 
| 161 |  | 
| 162 |     if (!AcIsFileBinary (File)) | 
| 163 |     { | 
| 164 |         fprintf (stderr, | 
| 165 |             "    %s: File does not appear to contain a valid AML table\n" , | 
| 166 |             Filename); | 
| 167 |         Status = AE_TYPE; | 
| 168 |         goto Exit; | 
| 169 |     } | 
| 170 |  | 
| 171 |     /* Read all tables within the file */ | 
| 172 |  | 
| 173 |     while (ACPI_SUCCESS (Status)) | 
| 174 |     { | 
| 175 |         /* Get one entire ACPI table */ | 
| 176 |  | 
| 177 |         Status = AcGetOneTableFromFile ( | 
| 178 |             Filename, File, GetOnlyAmlTables, &Table); | 
| 179 |  | 
| 180 |         if (Status == AE_CTRL_TERMINATE) | 
| 181 |         { | 
| 182 |             Status = AE_OK; | 
| 183 |             break; | 
| 184 |         } | 
| 185 |         else if (Status == AE_TYPE) | 
| 186 |         { | 
| 187 |             Status = AE_OK; | 
| 188 |             goto Exit; | 
| 189 |         } | 
| 190 |         else if (ACPI_FAILURE (Status)) | 
| 191 |         { | 
| 192 |             goto Exit; | 
| 193 |         } | 
| 194 |  | 
| 195 |         /* Print table header for iASL/disassembler only */ | 
| 196 |  | 
| 197 | #ifdef ACPI_ASL_COMPILER | 
| 198 |  | 
| 199 |         AcpiTbPrintTableHeader (0, Table); | 
| 200 | #endif | 
| 201 |  | 
| 202 |         /* Allocate and link a table descriptor */ | 
| 203 |  | 
| 204 |         TableDesc = AcpiOsAllocate (sizeof (ACPI_NEW_TABLE_DESC)); | 
| 205 |         if (!TableDesc) | 
| 206 |         { | 
| 207 |             AcpiOsFree (Table); | 
| 208 |             Status = AE_NO_MEMORY; | 
| 209 |             goto Exit; | 
| 210 |         } | 
| 211 |  | 
| 212 |         TableDesc->Table = Table; | 
| 213 |         TableDesc->Next = NULL; | 
| 214 |  | 
| 215 |         /* Link at the end of the local table list */ | 
| 216 |  | 
| 217 |         if (!ListHead) | 
| 218 |         { | 
| 219 |             ListHead = TableDesc; | 
| 220 |             ListTail = TableDesc; | 
| 221 |         } | 
| 222 |         else | 
| 223 |         { | 
| 224 |             ListTail->Next = TableDesc; | 
| 225 |             ListTail = TableDesc; | 
| 226 |         } | 
| 227 |     } | 
| 228 |  | 
| 229 |     /* Add the local table list to the end of the global list */ | 
| 230 |  | 
| 231 |     if (*ReturnListHead) | 
| 232 |     { | 
| 233 |         ListTail = *ReturnListHead; | 
| 234 |         while (ListTail->Next) | 
| 235 |         { | 
| 236 |             ListTail = ListTail->Next; | 
| 237 |         } | 
| 238 |  | 
| 239 |         ListTail->Next = ListHead; | 
| 240 |     } | 
| 241 |     else | 
| 242 |     { | 
| 243 |         *ReturnListHead = ListHead; | 
| 244 |     } | 
| 245 |  | 
| 246 | Exit: | 
| 247 |     fclose(File); | 
| 248 |     return (Status); | 
| 249 | } | 
| 250 |  | 
| 251 |  | 
| 252 | /******************************************************************************* | 
| 253 |  * | 
| 254 |  * FUNCTION:    AcGetOneTableFromFile | 
| 255 |  * | 
| 256 |  * PARAMETERS:  Filename            - File where table is located | 
| 257 |  *              File                - Open FILE pointer to Filename | 
| 258 |  *              GetOnlyAmlTables    - TRUE if the tables must be AML tables. | 
| 259 |  *              ReturnTable         - Where a pointer to the table is returned | 
| 260 |  * | 
| 261 |  * RETURN:      Status | 
| 262 |  * | 
| 263 |  * DESCRIPTION: Read the next ACPI table from a file. Implements support | 
| 264 |  *              for multiple tables within a single file. File must already | 
| 265 |  *              be open. | 
| 266 |  * | 
| 267 |  * Note: Loading an RSDP is not supported. | 
| 268 |  * | 
| 269 |  ******************************************************************************/ | 
| 270 |  | 
| 271 | static ACPI_STATUS | 
| 272 | AcGetOneTableFromFile ( | 
| 273 |     char                    *Filename, | 
| 274 |     FILE                    *File, | 
| 275 |     UINT8                   GetOnlyAmlTables, | 
| 276 |     ACPI_TABLE_HEADER       **ReturnTable) | 
| 277 | { | 
| 278 |     ACPI_STATUS             Status = AE_OK; | 
| 279 |     ACPI_TABLE_HEADER       ; | 
| 280 |     ACPI_TABLE_HEADER       *Table; | 
| 281 |     INT32                   Count; | 
| 282 |     long                    TableOffset; | 
| 283 |  | 
| 284 |  | 
| 285 |     *ReturnTable = NULL; | 
| 286 |  | 
| 287 |     /* Get the table header to examine signature and length */ | 
| 288 |  | 
| 289 |     TableOffset = ftell (File); | 
| 290 |     Count = fread (&TableHeader, 1, sizeof (ACPI_TABLE_HEADER), File); | 
| 291 |     if (Count != sizeof (ACPI_TABLE_HEADER)) | 
| 292 |     { | 
| 293 |         return (AE_CTRL_TERMINATE); | 
| 294 |     } | 
| 295 |  | 
| 296 |     if (GetOnlyAmlTables) | 
| 297 |     { | 
| 298 |         /* Validate the table signature/header (limited ASCII chars) */ | 
| 299 |  | 
| 300 |         Status = AcValidateTableHeader (File, TableOffset); | 
| 301 |         if (ACPI_FAILURE (Status)) | 
| 302 |         { | 
| 303 |             return (Status); | 
| 304 |         } | 
| 305 |  | 
| 306 |         /* | 
| 307 |          * Table must be an AML table (DSDT/SSDT). | 
| 308 |          * Used for iASL -e option only. | 
| 309 |          */ | 
| 310 |         if (!AcpiUtIsAmlTable (&TableHeader)) | 
| 311 |         { | 
| 312 |             fprintf (stderr, | 
| 313 |                 "    %s: Table [%4.4s] is not an AML table - ignoring\n" , | 
| 314 |                 Filename, TableHeader.Signature); | 
| 315 |  | 
| 316 |             return (AE_TYPE); | 
| 317 |         } | 
| 318 |     } | 
| 319 |  | 
| 320 |     /* Allocate a buffer for the entire table */ | 
| 321 |  | 
| 322 |     Table = AcpiOsAllocate ((ACPI_SIZE) TableHeader.Length); | 
| 323 |     if (!Table) | 
| 324 |     { | 
| 325 |         return (AE_NO_MEMORY); | 
| 326 |     } | 
| 327 |  | 
| 328 |     /* Read the entire ACPI table, including header */ | 
| 329 |  | 
| 330 |     fseek (File, TableOffset, SEEK_SET); | 
| 331 |  | 
| 332 |     Count = fread (Table, 1, TableHeader.Length, File); | 
| 333 |  | 
| 334 |     /* | 
| 335 |      * Checks for data table headers happen later in the execution. Only verify | 
| 336 |      * for Aml tables at this point in the code. | 
| 337 |      */ | 
| 338 |     if (GetOnlyAmlTables && Count != (INT32) TableHeader.Length) | 
| 339 |     { | 
| 340 |         Status = AE_ERROR; | 
| 341 |         goto ErrorExit; | 
| 342 |     } | 
| 343 |  | 
| 344 |     /* Validate the checksum (just issue a warning) */ | 
| 345 |  | 
| 346 |     Status = AcpiTbVerifyChecksum (Table, TableHeader.Length); | 
| 347 |     if (ACPI_FAILURE (Status)) | 
| 348 |     { | 
| 349 |         Status = AcCheckTextModeCorruption (Table); | 
| 350 |         if (ACPI_FAILURE (Status)) | 
| 351 |         { | 
| 352 |             goto ErrorExit; | 
| 353 |         } | 
| 354 |     } | 
| 355 |  | 
| 356 |     *ReturnTable = Table; | 
| 357 |     return (AE_OK); | 
| 358 |  | 
| 359 |  | 
| 360 | ErrorExit: | 
| 361 |     AcpiOsFree (Table); | 
| 362 |     return (Status); | 
| 363 | } | 
| 364 |  | 
| 365 |  | 
| 366 | /******************************************************************************* | 
| 367 |  * | 
| 368 |  * FUNCTION:    AcIsFileBinary | 
| 369 |  * | 
| 370 |  * PARAMETERS:  File                - Open input file | 
| 371 |  * | 
| 372 |  * RETURN:      TRUE if file appears to be binary | 
| 373 |  * | 
| 374 |  * DESCRIPTION: Scan a file for any non-ASCII bytes. | 
| 375 |  * | 
| 376 |  * Note: Maintains current file position. | 
| 377 |  * | 
| 378 |  ******************************************************************************/ | 
| 379 |  | 
| 380 | BOOLEAN | 
| 381 | AcIsFileBinary ( | 
| 382 |     FILE                    *File) | 
| 383 | { | 
| 384 |     UINT8                   Byte; | 
| 385 |     BOOLEAN                 IsBinary = FALSE; | 
| 386 |     long                    FileOffset; | 
| 387 |  | 
| 388 |  | 
| 389 |     /* Scan entire file for any non-ASCII bytes */ | 
| 390 |  | 
| 391 |     FileOffset = ftell (File); | 
| 392 |     while (fread (&Byte, 1, 1, File) == 1) | 
| 393 |     { | 
| 394 |         if (!isprint (Byte) && !isspace (Byte)) | 
| 395 |         { | 
| 396 |             IsBinary = TRUE; | 
| 397 |             goto Exit; | 
| 398 |         } | 
| 399 |     } | 
| 400 |  | 
| 401 | Exit: | 
| 402 |     fseek (File, FileOffset, SEEK_SET); | 
| 403 |     return (IsBinary); | 
| 404 | } | 
| 405 |  | 
| 406 |  | 
| 407 | /******************************************************************************* | 
| 408 |  * | 
| 409 |  * FUNCTION:    AcValidateTableHeader | 
| 410 |  * | 
| 411 |  * PARAMETERS:  File                - Open input file | 
| 412 |  * | 
| 413 |  * RETURN:      Status | 
| 414 |  * | 
| 415 |  * DESCRIPTION: Determine if a file seems to contain one or more binary ACPI | 
| 416 |  *              tables, via the | 
| 417 |  *              following checks on what would be the table header: | 
| 418 |  *              1) File must be at least as long as an ACPI_TABLE_HEADER | 
| 419 |  *              2) There must be enough room in the file to hold entire table | 
| 420 |  *              3) Signature, OemId, OemTableId, AslCompilerId must be ASCII | 
| 421 |  * | 
| 422 |  * Note: There can be multiple definition blocks per file, so we cannot | 
| 423 |  * expect/compare the file size to be equal to the table length. 12/2015. | 
| 424 |  * | 
| 425 |  * Note: Maintains current file position. | 
| 426 |  * | 
| 427 |  ******************************************************************************/ | 
| 428 |  | 
| 429 | ACPI_STATUS | 
| 430 |  ( | 
| 431 |     FILE                    *File, | 
| 432 |     long                    TableOffset) | 
| 433 | { | 
| 434 |     ACPI_TABLE_HEADER       ; | 
| 435 |     ACPI_SIZE               Actual; | 
| 436 |     long                    OriginalOffset; | 
| 437 |     UINT32                  FileSize; | 
| 438 |     UINT32                  i; | 
| 439 |  | 
| 440 |  | 
| 441 |     ACPI_FUNCTION_TRACE (AcValidateTableHeader); | 
| 442 |  | 
| 443 |  | 
| 444 |     /* Read a potential table header */ | 
| 445 |  | 
| 446 |     OriginalOffset = ftell (File); | 
| 447 |     fseek (File, TableOffset, SEEK_SET); | 
| 448 |  | 
| 449 |     Actual = fread (&TableHeader, 1, sizeof (ACPI_TABLE_HEADER), File); | 
| 450 |     fseek (File, OriginalOffset, SEEK_SET); | 
| 451 |  | 
| 452 |     if (Actual < sizeof (ACPI_TABLE_HEADER)) | 
| 453 |     { | 
| 454 |         return (AE_ERROR); | 
| 455 |     } | 
| 456 |  | 
| 457 |     /* Validate the signature (limited ASCII chars) */ | 
| 458 |  | 
| 459 |     if (!AcpiUtValidNameseg (TableHeader.Signature)) | 
| 460 |     { | 
| 461 |         return (AE_BAD_SIGNATURE); | 
| 462 |     } | 
| 463 |  | 
| 464 |     /* Validate table length against bytes remaining in the file */ | 
| 465 |  | 
| 466 |     FileSize = CmGetFileSize (File); | 
| 467 |     if (TableHeader.Length > (UINT32) (FileSize - TableOffset)) | 
| 468 |     { | 
| 469 |         fprintf (stderr, "Table [%4.4s] is too long for file - "  | 
| 470 |             "needs: 0x%.2X, remaining in file: 0x%.2X\n" , | 
| 471 |             TableHeader.Signature, TableHeader.Length, | 
| 472 |             (UINT32) (FileSize - TableOffset)); | 
| 473 |         return (AE_BAD_HEADER); | 
| 474 |     } | 
| 475 |  | 
| 476 |     /* | 
| 477 |      * These fields must be ASCII: OemId, OemTableId, AslCompilerId. | 
| 478 |      * We allow a NULL terminator in OemId and OemTableId. | 
| 479 |      */ | 
| 480 |     for (i = 0; i < ACPI_NAMESEG_SIZE; i++) | 
| 481 |     { | 
| 482 |         if (!ACPI_IS_ASCII ((UINT8) TableHeader.AslCompilerId[i])) | 
| 483 |         { | 
| 484 |             goto BadCharacters; | 
| 485 |         } | 
| 486 |     } | 
| 487 |  | 
| 488 |     for (i = 0; (i < ACPI_OEM_ID_SIZE) && (TableHeader.OemId[i]); i++) | 
| 489 |     { | 
| 490 |         if (!ACPI_IS_ASCII ((UINT8) TableHeader.OemId[i])) | 
| 491 |         { | 
| 492 |             goto BadCharacters; | 
| 493 |         } | 
| 494 |     } | 
| 495 |  | 
| 496 |     for (i = 0; (i < ACPI_OEM_TABLE_ID_SIZE) && (TableHeader.OemTableId[i]); i++) | 
| 497 |     { | 
| 498 |         if (!ACPI_IS_ASCII ((UINT8) TableHeader.OemTableId[i])) | 
| 499 |         { | 
| 500 |             goto BadCharacters; | 
| 501 |         } | 
| 502 |     } | 
| 503 |  | 
| 504 |     return (AE_OK); | 
| 505 |  | 
| 506 |  | 
| 507 | BadCharacters: | 
| 508 |  | 
| 509 |     ACPI_WARNING ((AE_INFO, | 
| 510 |         "Table header for [%4.4s] has invalid ASCII character(s)" , | 
| 511 |         TableHeader.Signature)); | 
| 512 |     return (AE_OK); | 
| 513 | } | 
| 514 |  | 
| 515 |  | 
| 516 | /******************************************************************************* | 
| 517 |  * | 
| 518 |  * FUNCTION:    AcCheckTextModeCorruption | 
| 519 |  * | 
| 520 |  * PARAMETERS:  Table           - Table buffer starting with table header | 
| 521 |  * | 
| 522 |  * RETURN:      Status | 
| 523 |  * | 
| 524 |  * DESCRIPTION: Check table for text mode file corruption where all linefeed | 
| 525 |  *              characters (LF) have been replaced by carriage return linefeed | 
| 526 |  *              pairs (CR/LF). | 
| 527 |  * | 
| 528 |  ******************************************************************************/ | 
| 529 |  | 
| 530 | static ACPI_STATUS | 
| 531 | AcCheckTextModeCorruption ( | 
| 532 |     ACPI_TABLE_HEADER       *Table) | 
| 533 | { | 
| 534 |     UINT32                  i; | 
| 535 |     UINT32                  Pairs = 0; | 
| 536 |     UINT8                   *Buffer = ACPI_CAST_PTR (UINT8, Table); | 
| 537 |  | 
| 538 |  | 
| 539 |     /* Scan entire table to determine if each LF has been prefixed with a CR */ | 
| 540 |  | 
| 541 |     for (i = 1; i < Table->Length; i++) | 
| 542 |     { | 
| 543 |         if (Buffer[i] == 0x0A) | 
| 544 |         { | 
| 545 |             if (Buffer[i - 1] != 0x0D) | 
| 546 |             { | 
| 547 |                 /* The LF does not have a preceding CR, table not corrupted */ | 
| 548 |  | 
| 549 |                 return (AE_OK); | 
| 550 |             } | 
| 551 |             else | 
| 552 |             { | 
| 553 |                 /* Found a CR/LF pair */ | 
| 554 |  | 
| 555 |                 Pairs++; | 
| 556 |             } | 
| 557 |  | 
| 558 |             i++; | 
| 559 |         } | 
| 560 |     } | 
| 561 |  | 
| 562 |     if (!Pairs) | 
| 563 |     { | 
| 564 |         return (AE_OK); | 
| 565 |     } | 
| 566 |  | 
| 567 |     /* | 
| 568 |      * Entire table scanned, each CR is part of a CR/LF pair -- | 
| 569 |      * meaning that the table was treated as a text file somewhere. | 
| 570 |      * | 
| 571 |      * NOTE: We can't "fix" the table, because any existing CR/LF pairs in the | 
| 572 |      * original table are left untouched by the text conversion process -- | 
| 573 |      * meaning that we cannot simply replace CR/LF pairs with LFs. | 
| 574 |      */ | 
| 575 |     AcpiOsPrintf ("Table has been corrupted by text mode conversion\n" ); | 
| 576 |     AcpiOsPrintf ("All LFs (%u) were changed to CR/LF pairs\n" , Pairs); | 
| 577 |     AcpiOsPrintf ("Table cannot be repaired!\n" ); | 
| 578 |  | 
| 579 |     return (AE_BAD_VALUE); | 
| 580 | } | 
| 581 |  |