1291333Sjkim/******************************************************************************
2291333Sjkim *
3291333Sjkim * Module Name: acfileio - Get ACPI tables from file
4291333Sjkim *
5291333Sjkim *****************************************************************************/
6291333Sjkim
7291333Sjkim/*
8298714Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
9291333Sjkim * All rights reserved.
10291333Sjkim *
11291333Sjkim * Redistribution and use in source and binary forms, with or without
12291333Sjkim * modification, are permitted provided that the following conditions
13291333Sjkim * are met:
14291333Sjkim * 1. Redistributions of source code must retain the above copyright
15291333Sjkim *    notice, this list of conditions, and the following disclaimer,
16291333Sjkim *    without modification.
17291333Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18291333Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19291333Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20291333Sjkim *    including a substantially similar Disclaimer requirement for further
21291333Sjkim *    binary redistribution.
22291333Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23291333Sjkim *    of any contributors may be used to endorse or promote products derived
24291333Sjkim *    from this software without specific prior written permission.
25291333Sjkim *
26291333Sjkim * Alternatively, this software may be distributed under the terms of the
27291333Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28291333Sjkim * Software Foundation.
29291333Sjkim *
30291333Sjkim * NO WARRANTY
31291333Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32291333Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33291333Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34291333Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35291333Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36291333Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37291333Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38291333Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39291333Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40291333Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41291333Sjkim * POSSIBILITY OF SUCH DAMAGES.
42291333Sjkim */
43291333Sjkim
44298714Sjkim#include <contrib/dev/acpica/include/acpi.h>
45298714Sjkim#include <contrib/dev/acpica/include/accommon.h>
46298714Sjkim#include <contrib/dev/acpica/include/acapps.h>
47298714Sjkim#include <contrib/dev/acpica/include/actables.h>
48298714Sjkim#include <contrib/dev/acpica/include/acutils.h>
49291333Sjkim#include <errno.h>
50291333Sjkim
51291333Sjkim#define _COMPONENT          ACPI_UTILITIES
52291333Sjkim        ACPI_MODULE_NAME    ("acfileio")
53291333Sjkim
54291333Sjkim
55291333Sjkim/* Local prototypes */
56291333Sjkim
57291333Sjkimstatic ACPI_STATUS
58298714SjkimAcGetOneTableFromFile (
59291333Sjkim    char                    *Filename,
60291333Sjkim    FILE                    *File,
61291333Sjkim    UINT8                   GetOnlyAmlTables,
62291333Sjkim    ACPI_TABLE_HEADER       **Table);
63291333Sjkim
64291333Sjkimstatic ACPI_STATUS
65298714SjkimAcCheckTextModeCorruption (
66291333Sjkim    ACPI_TABLE_HEADER       *Table);
67291333Sjkim
68291333Sjkim
69291333Sjkim/*******************************************************************************
70291333Sjkim *
71298714Sjkim * FUNCTION:    AcGetAllTablesFromFile
72291333Sjkim *
73291333Sjkim * PARAMETERS:  Filename            - Table filename
74291333Sjkim *              GetOnlyAmlTables    - TRUE if the tables must be AML tables
75291333Sjkim *              ReturnListHead      - Where table list is returned
76291333Sjkim *
77291333Sjkim * RETURN:      Status
78291333Sjkim *
79291333Sjkim * DESCRIPTION: Get all ACPI tables from within a single file.
80291333Sjkim *
81291333Sjkim ******************************************************************************/
82291333Sjkim
83291333SjkimACPI_STATUS
84298714SjkimAcGetAllTablesFromFile (
85291333Sjkim    char                    *Filename,
86291333Sjkim    UINT8                   GetOnlyAmlTables,
87291333Sjkim    ACPI_NEW_TABLE_DESC     **ReturnListHead)
88291333Sjkim{
89291333Sjkim    ACPI_NEW_TABLE_DESC     *ListHead = NULL;
90291333Sjkim    ACPI_NEW_TABLE_DESC     *ListTail = NULL;
91291333Sjkim    ACPI_NEW_TABLE_DESC     *TableDesc;
92291333Sjkim    FILE                    *File;
93291333Sjkim    ACPI_TABLE_HEADER       *Table = NULL;
94291333Sjkim    UINT32                  FileSize;
95291333Sjkim    ACPI_STATUS             Status = AE_OK;
96291333Sjkim
97291333Sjkim
98291333Sjkim    File = fopen (Filename, "rb");
99291333Sjkim    if (!File)
100291333Sjkim    {
101291333Sjkim        perror ("Could not open input file");
102291333Sjkim        if (errno == ENOENT)
103291333Sjkim        {
104291333Sjkim            return (AE_NOT_EXIST);
105291333Sjkim        }
106291333Sjkim
107291333Sjkim        return (AE_ERROR);
108291333Sjkim    }
109291333Sjkim
110291333Sjkim    /* Get the file size */
111291333Sjkim
112291333Sjkim    FileSize = CmGetFileSize (File);
113291333Sjkim    if (FileSize == ACPI_UINT32_MAX)
114291333Sjkim    {
115298714Sjkim        Status = AE_ERROR;
116298714Sjkim        goto ErrorExit;
117291333Sjkim    }
118291333Sjkim
119298714Sjkim    fprintf (stderr,
120298714Sjkim        "Input file %s, Length 0x%X (%u) bytes\n",
121298714Sjkim        Filename, FileSize, FileSize);
122298714Sjkim
123298714Sjkim    /* We must have at least one ACPI table header */
124298714Sjkim
125298714Sjkim    if (FileSize < sizeof (ACPI_TABLE_HEADER))
126291333Sjkim    {
127298714Sjkim        Status = AE_BAD_HEADER;
128298714Sjkim        goto ErrorExit;
129291333Sjkim    }
130291333Sjkim
131298714Sjkim    /* Check for an non-binary file */
132298714Sjkim
133298714Sjkim    if (!AcIsFileBinary (File))
134298714Sjkim    {
135298714Sjkim        fprintf (stderr,
136298714Sjkim            "    %s: File does not appear to contain a valid AML table\n",
137298714Sjkim            Filename);
138298714Sjkim        return (AE_TYPE);
139298714Sjkim    }
140298714Sjkim
141291333Sjkim    /* Read all tables within the file */
142291333Sjkim
143291333Sjkim    while (ACPI_SUCCESS (Status))
144291333Sjkim    {
145291333Sjkim        /* Get one entire ACPI table */
146291333Sjkim
147298714Sjkim        Status = AcGetOneTableFromFile (
148291333Sjkim            Filename, File, GetOnlyAmlTables, &Table);
149298714Sjkim
150291333Sjkim        if (Status == AE_CTRL_TERMINATE)
151291333Sjkim        {
152291333Sjkim            Status = AE_OK;
153291333Sjkim            break;
154291333Sjkim        }
155291333Sjkim        else if (Status == AE_TYPE)
156291333Sjkim        {
157298714Sjkim            return (AE_OK);
158291333Sjkim        }
159291333Sjkim        else if (ACPI_FAILURE (Status))
160291333Sjkim        {
161298714Sjkim            goto ErrorExit;
162291333Sjkim        }
163291333Sjkim
164298714Sjkim        /* Print table header for iASL/disassembler only */
165298714Sjkim
166298714Sjkim#ifdef ACPI_ASL_COMPILER
167298714Sjkim
168298714Sjkim            AcpiTbPrintTableHeader (0, Table);
169298714Sjkim#endif
170298714Sjkim
171291333Sjkim        /* Allocate and link a table descriptor */
172291333Sjkim
173291333Sjkim        TableDesc = AcpiOsAllocate (sizeof (ACPI_NEW_TABLE_DESC));
174291333Sjkim        TableDesc->Table = Table;
175291333Sjkim        TableDesc->Next = NULL;
176291333Sjkim
177291333Sjkim        /* Link at the end of the local table list */
178291333Sjkim
179291333Sjkim        if (!ListHead)
180291333Sjkim        {
181291333Sjkim            ListHead = TableDesc;
182291333Sjkim            ListTail = TableDesc;
183291333Sjkim        }
184291333Sjkim        else
185291333Sjkim        {
186291333Sjkim            ListTail->Next = TableDesc;
187291333Sjkim            ListTail = TableDesc;
188291333Sjkim        }
189291333Sjkim    }
190291333Sjkim
191291333Sjkim    /* Add the local table list to the end of the global list */
192291333Sjkim
193291333Sjkim    if (*ReturnListHead)
194291333Sjkim    {
195291333Sjkim        ListTail = *ReturnListHead;
196291333Sjkim        while (ListTail->Next)
197291333Sjkim        {
198291333Sjkim            ListTail = ListTail->Next;
199291333Sjkim        }
200291333Sjkim
201291333Sjkim        ListTail->Next = ListHead;
202291333Sjkim    }
203291333Sjkim    else
204291333Sjkim    {
205291333Sjkim        *ReturnListHead = ListHead;
206291333Sjkim    }
207291333Sjkim
208298714SjkimErrorExit:
209291333Sjkim    fclose(File);
210291333Sjkim    return (Status);
211291333Sjkim}
212291333Sjkim
213291333Sjkim
214291333Sjkim/*******************************************************************************
215291333Sjkim *
216298714Sjkim * FUNCTION:    AcGetOneTableFromFile
217291333Sjkim *
218291333Sjkim * PARAMETERS:  Filename            - File where table is located
219291333Sjkim *              File                - Open FILE pointer to Filename
220291333Sjkim *              GetOnlyAmlTables    - TRUE if the tables must be AML tables.
221291333Sjkim *              ReturnTable         - Where a pointer to the table is returned
222291333Sjkim *
223291333Sjkim * RETURN:      Status
224291333Sjkim *
225291333Sjkim * DESCRIPTION: Read the next ACPI table from a file. Implements support
226291333Sjkim *              for multiple tables within a single file. File must already
227291333Sjkim *              be open.
228291333Sjkim *
229291333Sjkim * Note: Loading an RSDP is not supported.
230291333Sjkim *
231291333Sjkim ******************************************************************************/
232291333Sjkim
233291333Sjkimstatic ACPI_STATUS
234298714SjkimAcGetOneTableFromFile (
235291333Sjkim    char                    *Filename,
236291333Sjkim    FILE                    *File,
237291333Sjkim    UINT8                   GetOnlyAmlTables,
238291333Sjkim    ACPI_TABLE_HEADER       **ReturnTable)
239291333Sjkim{
240291333Sjkim    ACPI_STATUS             Status = AE_OK;
241291333Sjkim    ACPI_TABLE_HEADER       TableHeader;
242291333Sjkim    ACPI_TABLE_HEADER       *Table;
243291333Sjkim    INT32                   Count;
244298714Sjkim    long                    TableOffset;
245291333Sjkim
246291333Sjkim
247291333Sjkim    *ReturnTable = NULL;
248291333Sjkim
249298714Sjkim    /* Get the table header to examine signature and length */
250291333Sjkim
251298714Sjkim    TableOffset = ftell (File);
252291333Sjkim    Count = fread (&TableHeader, 1, sizeof (ACPI_TABLE_HEADER), File);
253291333Sjkim    if (Count != sizeof (ACPI_TABLE_HEADER))
254291333Sjkim    {
255291333Sjkim        return (AE_CTRL_TERMINATE);
256291333Sjkim    }
257291333Sjkim
258298714Sjkim    /* Validate the table signature/header (limited ASCII chars) */
259298714Sjkim
260298714Sjkim    Status = AcValidateTableHeader (File, TableOffset);
261298714Sjkim    if (ACPI_FAILURE (Status))
262298714Sjkim    {
263298714Sjkim        return (Status);
264298714Sjkim    }
265298714Sjkim
266291333Sjkim    if (GetOnlyAmlTables)
267291333Sjkim    {
268291333Sjkim        /* Table must be an AML table (DSDT/SSDT) or FADT */
269291333Sjkim
270291333Sjkim        if (!ACPI_COMPARE_NAME (TableHeader.Signature, ACPI_SIG_FADT) &&
271291333Sjkim            !AcpiUtIsAmlTable (&TableHeader))
272291333Sjkim        {
273291333Sjkim            fprintf (stderr,
274298714Sjkim                "    %s: Table [%4.4s] is not an AML table - ignoring\n",
275291333Sjkim                Filename, TableHeader.Signature);
276291333Sjkim
277291333Sjkim            return (AE_TYPE);
278291333Sjkim        }
279291333Sjkim    }
280291333Sjkim
281291333Sjkim    /* Allocate a buffer for the entire table */
282291333Sjkim
283291333Sjkim    Table = AcpiOsAllocate ((size_t) TableHeader.Length);
284291333Sjkim    if (!Table)
285291333Sjkim    {
286291333Sjkim        return (AE_NO_MEMORY);
287291333Sjkim    }
288291333Sjkim
289298714Sjkim    /* Read the entire ACPI table, including header */
290291333Sjkim
291298714Sjkim    fseek (File, TableOffset, SEEK_SET);
292291333Sjkim
293291333Sjkim    Count = fread (Table, 1, TableHeader.Length, File);
294291333Sjkim    if (Count != (INT32) TableHeader.Length)
295291333Sjkim    {
296291333Sjkim        Status = AE_ERROR;
297291333Sjkim        goto ErrorExit;
298291333Sjkim    }
299291333Sjkim
300291333Sjkim    /* Validate the checksum (just issue a warning) */
301291333Sjkim
302291333Sjkim    Status = AcpiTbVerifyChecksum (Table, TableHeader.Length);
303291333Sjkim    if (ACPI_FAILURE (Status))
304291333Sjkim    {
305298714Sjkim        Status = AcCheckTextModeCorruption (Table);
306291333Sjkim        if (ACPI_FAILURE (Status))
307291333Sjkim        {
308291333Sjkim            goto ErrorExit;
309291333Sjkim        }
310291333Sjkim    }
311291333Sjkim
312291333Sjkim    *ReturnTable = Table;
313291333Sjkim    return (AE_OK);
314291333Sjkim
315291333Sjkim
316291333SjkimErrorExit:
317291333Sjkim    AcpiOsFree (Table);
318291333Sjkim    return (Status);
319291333Sjkim}
320291333Sjkim
321291333Sjkim
322291333Sjkim/*******************************************************************************
323291333Sjkim *
324298714Sjkim * FUNCTION:    AcIsFileBinary
325291333Sjkim *
326298714Sjkim * PARAMETERS:  File                - Open input file
327298714Sjkim *
328298714Sjkim * RETURN:      TRUE if file appears to be binary
329298714Sjkim *
330298714Sjkim * DESCRIPTION: Scan a file for any non-ASCII bytes.
331298714Sjkim *
332298714Sjkim * Note: Maintains current file position.
333298714Sjkim *
334298714Sjkim ******************************************************************************/
335298714Sjkim
336298714SjkimBOOLEAN
337298714SjkimAcIsFileBinary (
338298714Sjkim    FILE                    *File)
339298714Sjkim{
340298714Sjkim    UINT8                   Byte;
341298714Sjkim    BOOLEAN                 IsBinary = FALSE;
342298714Sjkim    long                    FileOffset;
343298714Sjkim
344298714Sjkim
345298714Sjkim    /* Scan entire file for any non-ASCII bytes */
346298714Sjkim
347298714Sjkim    FileOffset = ftell (File);
348298714Sjkim    while (fread (&Byte, 1, 1, File) == 1)
349298714Sjkim    {
350298714Sjkim        if (!isprint (Byte) && !isspace (Byte))
351298714Sjkim        {
352298714Sjkim            IsBinary = TRUE;
353298714Sjkim            goto Exit;
354298714Sjkim        }
355298714Sjkim    }
356298714Sjkim
357298714SjkimExit:
358298714Sjkim    fseek (File, FileOffset, SEEK_SET);
359298714Sjkim    return (IsBinary);
360298714Sjkim}
361298714Sjkim
362298714Sjkim
363298714Sjkim/*******************************************************************************
364298714Sjkim *
365298714Sjkim * FUNCTION:    AcValidateTableHeader
366298714Sjkim *
367298714Sjkim * PARAMETERS:  File                - Open input file
368298714Sjkim *
369298714Sjkim * RETURN:      Status
370298714Sjkim *
371298714Sjkim * DESCRIPTION: Determine if a file seems to contain one or more binary ACPI
372298714Sjkim *              tables, via the
373298714Sjkim *              following checks on what would be the table header:
374298714Sjkim *              1) File must be at least as long as an ACPI_TABLE_HEADER
375298714Sjkim *              2) There must be enough room in the file to hold entire table
376298714Sjkim *              3) Signature, OemId, OemTableId, AslCompilerId must be ASCII
377298714Sjkim *
378298714Sjkim * Note: There can be multiple definition blocks per file, so we cannot
379298714Sjkim * expect/compare the file size to be equal to the table length. 12/2015.
380298714Sjkim *
381298714Sjkim * Note: Maintains current file position.
382298714Sjkim *
383298714Sjkim ******************************************************************************/
384298714Sjkim
385298714SjkimACPI_STATUS
386298714SjkimAcValidateTableHeader (
387298714Sjkim    FILE                    *File,
388298714Sjkim    long                    TableOffset)
389298714Sjkim{
390298714Sjkim    ACPI_TABLE_HEADER       TableHeader;
391298714Sjkim    size_t                  Actual;
392298714Sjkim    long                    OriginalOffset;
393298714Sjkim    UINT32                  FileSize;
394298714Sjkim    UINT32                  i;
395298714Sjkim
396298714Sjkim
397298714Sjkim    ACPI_FUNCTION_TRACE ("AcValidateTableHeader");
398298714Sjkim
399298714Sjkim
400298714Sjkim    /* Read a potential table header */
401298714Sjkim
402298714Sjkim    OriginalOffset = ftell (File);
403298714Sjkim    fseek (File, TableOffset, SEEK_SET);
404298714Sjkim
405298714Sjkim    Actual = fread (&TableHeader, 1, sizeof (ACPI_TABLE_HEADER), File);
406298714Sjkim    fseek (File, OriginalOffset, SEEK_SET);
407298714Sjkim
408298714Sjkim    if (Actual < sizeof (ACPI_TABLE_HEADER))
409298714Sjkim    {
410298714Sjkim        return (AE_ERROR);
411298714Sjkim    }
412298714Sjkim
413298714Sjkim    /* Validate the signature (limited ASCII chars) */
414298714Sjkim
415298714Sjkim    if (!AcpiUtValidNameseg (TableHeader.Signature))
416298714Sjkim    {
417298714Sjkim        fprintf (stderr, "Invalid table signature: 0x%8.8X\n",
418298714Sjkim            *ACPI_CAST_PTR (UINT32, TableHeader.Signature));
419298714Sjkim        return (AE_BAD_SIGNATURE);
420298714Sjkim    }
421298714Sjkim
422298714Sjkim    /* Validate table length against bytes remaining in the file */
423298714Sjkim
424298714Sjkim    FileSize = CmGetFileSize (File);
425298714Sjkim    if (TableHeader.Length > (UINT32) (FileSize - TableOffset))
426298714Sjkim    {
427298714Sjkim        fprintf (stderr, "Table [%4.4s] is too long for file - "
428298714Sjkim            "needs: 0x%.2X, remaining in file: 0x%.2X\n",
429298714Sjkim            TableHeader.Signature, TableHeader.Length,
430298714Sjkim            (UINT32) (FileSize - TableOffset));
431298714Sjkim        return (AE_BAD_HEADER);
432298714Sjkim    }
433298714Sjkim
434298714Sjkim    /*
435298714Sjkim     * These fields must be ASCII: OemId, OemTableId, AslCompilerId.
436298714Sjkim     * We allow a NULL terminator in OemId and OemTableId.
437298714Sjkim     */
438298714Sjkim    for (i = 0; i < ACPI_NAME_SIZE; i++)
439298714Sjkim    {
440298714Sjkim        if (!ACPI_IS_ASCII ((UINT8) TableHeader.AslCompilerId[i]))
441298714Sjkim        {
442298714Sjkim            goto BadCharacters;
443298714Sjkim        }
444298714Sjkim    }
445298714Sjkim
446298714Sjkim    for (i = 0; (i < ACPI_OEM_ID_SIZE) && (TableHeader.OemId[i]); i++)
447298714Sjkim    {
448298714Sjkim        if (!ACPI_IS_ASCII ((UINT8) TableHeader.OemId[i]))
449298714Sjkim        {
450298714Sjkim            goto BadCharacters;
451298714Sjkim        }
452298714Sjkim    }
453298714Sjkim
454298714Sjkim    for (i = 0; (i < ACPI_OEM_TABLE_ID_SIZE) && (TableHeader.OemTableId[i]); i++)
455298714Sjkim    {
456298714Sjkim        if (!ACPI_IS_ASCII ((UINT8) TableHeader.OemTableId[i]))
457298714Sjkim        {
458298714Sjkim            goto BadCharacters;
459298714Sjkim        }
460298714Sjkim    }
461298714Sjkim
462298714Sjkim    return (AE_OK);
463298714Sjkim
464298714Sjkim
465298714SjkimBadCharacters:
466298714Sjkim
467298714Sjkim    ACPI_WARNING ((AE_INFO,
468298714Sjkim        "Table header for [%4.4s] has invalid ASCII character(s)",
469298714Sjkim        TableHeader.Signature));
470298714Sjkim    return (AE_OK);
471298714Sjkim}
472298714Sjkim
473298714Sjkim
474298714Sjkim/*******************************************************************************
475298714Sjkim *
476298714Sjkim * FUNCTION:    AcCheckTextModeCorruption
477298714Sjkim *
478291333Sjkim * PARAMETERS:  Table           - Table buffer starting with table header
479291333Sjkim *
480291333Sjkim * RETURN:      Status
481291333Sjkim *
482291333Sjkim * DESCRIPTION: Check table for text mode file corruption where all linefeed
483291333Sjkim *              characters (LF) have been replaced by carriage return linefeed
484291333Sjkim *              pairs (CR/LF).
485291333Sjkim *
486291333Sjkim ******************************************************************************/
487291333Sjkim
488291333Sjkimstatic ACPI_STATUS
489298714SjkimAcCheckTextModeCorruption (
490291333Sjkim    ACPI_TABLE_HEADER       *Table)
491291333Sjkim{
492291333Sjkim    UINT32                  i;
493291333Sjkim    UINT32                  Pairs = 0;
494291333Sjkim    UINT8                   *Buffer = ACPI_CAST_PTR (UINT8, Table);
495291333Sjkim
496291333Sjkim
497291333Sjkim    /* Scan entire table to determine if each LF has been prefixed with a CR */
498291333Sjkim
499291333Sjkim    for (i = 1; i < Table->Length; i++)
500291333Sjkim    {
501291333Sjkim        if (Buffer[i] == 0x0A)
502291333Sjkim        {
503291333Sjkim            if (Buffer[i - 1] != 0x0D)
504291333Sjkim            {
505291333Sjkim                /* The LF does not have a preceding CR, table not corrupted */
506291333Sjkim
507291333Sjkim                return (AE_OK);
508291333Sjkim            }
509291333Sjkim            else
510291333Sjkim            {
511291333Sjkim                /* Found a CR/LF pair */
512291333Sjkim
513291333Sjkim                Pairs++;
514291333Sjkim            }
515291333Sjkim
516291333Sjkim            i++;
517291333Sjkim        }
518291333Sjkim    }
519291333Sjkim
520291333Sjkim    if (!Pairs)
521291333Sjkim    {
522291333Sjkim        return (AE_OK);
523291333Sjkim    }
524291333Sjkim
525291333Sjkim    /*
526291333Sjkim     * Entire table scanned, each CR is part of a CR/LF pair --
527291333Sjkim     * meaning that the table was treated as a text file somewhere.
528291333Sjkim     *
529291333Sjkim     * NOTE: We can't "fix" the table, because any existing CR/LF pairs in the
530291333Sjkim     * original table are left untouched by the text conversion process --
531291333Sjkim     * meaning that we cannot simply replace CR/LF pairs with LFs.
532291333Sjkim     */
533291333Sjkim    AcpiOsPrintf ("Table has been corrupted by text mode conversion\n");
534291333Sjkim    AcpiOsPrintf ("All LFs (%u) were changed to CR/LF pairs\n", Pairs);
535291333Sjkim    AcpiOsPrintf ("Table cannot be repaired!\n");
536291333Sjkim
537291333Sjkim    return (AE_BAD_VALUE);
538291333Sjkim}
539