11.1Schristos/******************************************************************************
21.1Schristos *
31.1Schristos * Module Name: oslinuxtbl - Linux OSL for obtaining ACPI tables
41.1Schristos *
51.1Schristos *****************************************************************************/
61.1Schristos
71.17Schristos/******************************************************************************
81.17Schristos *
91.17Schristos * 1. Copyright Notice
101.17Schristos *
111.18Schristos * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
121.1Schristos * All rights reserved.
131.1Schristos *
141.17Schristos * 2. License
151.17Schristos *
161.17Schristos * 2.1. This is your license from Intel Corp. under its intellectual property
171.17Schristos * rights. You may have additional license terms from the party that provided
181.17Schristos * you this software, covering your right to use that party's intellectual
191.17Schristos * property rights.
201.17Schristos *
211.17Schristos * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
221.17Schristos * copy of the source code appearing in this file ("Covered Code") an
231.17Schristos * irrevocable, perpetual, worldwide license under Intel's copyrights in the
241.17Schristos * base code distributed originally by Intel ("Original Intel Code") to copy,
251.17Schristos * make derivatives, distribute, use and display any portion of the Covered
261.17Schristos * Code in any form, with the right to sublicense such rights; and
271.17Schristos *
281.17Schristos * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
291.17Schristos * license (with the right to sublicense), under only those claims of Intel
301.17Schristos * patents that are infringed by the Original Intel Code, to make, use, sell,
311.17Schristos * offer to sell, and import the Covered Code and derivative works thereof
321.17Schristos * solely to the minimum extent necessary to exercise the above copyright
331.17Schristos * license, and in no event shall the patent license extend to any additions
341.17Schristos * to or modifications of the Original Intel Code. No other license or right
351.17Schristos * is granted directly or by implication, estoppel or otherwise;
361.17Schristos *
371.17Schristos * The above copyright and patent license is granted only if the following
381.17Schristos * conditions are met:
391.17Schristos *
401.17Schristos * 3. Conditions
411.17Schristos *
421.17Schristos * 3.1. Redistribution of Source with Rights to Further Distribute Source.
431.17Schristos * Redistribution of source code of any substantial portion of the Covered
441.17Schristos * Code or modification with rights to further distribute source must include
451.17Schristos * the above Copyright Notice, the above License, this list of Conditions,
461.17Schristos * and the following Disclaimer and Export Compliance provision. In addition,
471.17Schristos * Licensee must cause all Covered Code to which Licensee contributes to
481.17Schristos * contain a file documenting the changes Licensee made to create that Covered
491.17Schristos * Code and the date of any change. Licensee must include in that file the
501.17Schristos * documentation of any changes made by any predecessor Licensee. Licensee
511.17Schristos * must include a prominent statement that the modification is derived,
521.17Schristos * directly or indirectly, from Original Intel Code.
531.17Schristos *
541.17Schristos * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
551.17Schristos * Redistribution of source code of any substantial portion of the Covered
561.17Schristos * Code or modification without rights to further distribute source must
571.17Schristos * include the following Disclaimer and Export Compliance provision in the
581.17Schristos * documentation and/or other materials provided with distribution. In
591.17Schristos * addition, Licensee may not authorize further sublicense of source of any
601.17Schristos * portion of the Covered Code, and must include terms to the effect that the
611.17Schristos * license from Licensee to its licensee is limited to the intellectual
621.17Schristos * property embodied in the software Licensee provides to its licensee, and
631.17Schristos * not to intellectual property embodied in modifications its licensee may
641.17Schristos * make.
651.17Schristos *
661.17Schristos * 3.3. Redistribution of Executable. Redistribution in executable form of any
671.17Schristos * substantial portion of the Covered Code or modification must reproduce the
681.17Schristos * above Copyright Notice, and the following Disclaimer and Export Compliance
691.17Schristos * provision in the documentation and/or other materials provided with the
701.17Schristos * distribution.
711.17Schristos *
721.17Schristos * 3.4. Intel retains all right, title, and interest in and to the Original
731.17Schristos * Intel Code.
741.17Schristos *
751.17Schristos * 3.5. Neither the name Intel nor any other trademark owned or controlled by
761.17Schristos * Intel shall be used in advertising or otherwise to promote the sale, use or
771.17Schristos * other dealings in products derived from or relating to the Covered Code
781.17Schristos * without prior written authorization from Intel.
791.17Schristos *
801.17Schristos * 4. Disclaimer and Export Compliance
811.17Schristos *
821.17Schristos * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
831.17Schristos * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
841.17Schristos * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
851.17Schristos * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
861.17Schristos * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
871.17Schristos * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
881.17Schristos * PARTICULAR PURPOSE.
891.17Schristos *
901.17Schristos * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
911.17Schristos * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
921.17Schristos * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
931.17Schristos * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
941.17Schristos * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
951.17Schristos * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
961.17Schristos * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
971.17Schristos * LIMITED REMEDY.
981.17Schristos *
991.17Schristos * 4.3. Licensee shall not export, either directly or indirectly, any of this
1001.17Schristos * software or system incorporating such software without first obtaining any
1011.17Schristos * required license or other approval from the U. S. Department of Commerce or
1021.17Schristos * any other agency or department of the United States Government. In the
1031.17Schristos * event Licensee exports any such software from the United States or
1041.17Schristos * re-exports any such software from a foreign destination, Licensee shall
1051.17Schristos * ensure that the distribution and export/re-export of the software is in
1061.17Schristos * compliance with all laws, regulations, orders, or other restrictions of the
1071.17Schristos * U.S. Export Administration Regulations. Licensee agrees that neither it nor
1081.17Schristos * any of its subsidiaries will export/re-export any technical data, process,
1091.17Schristos * software, or service, directly or indirectly, to any country for which the
1101.17Schristos * United States government or any agency thereof requires an export license,
1111.17Schristos * other governmental approval, or letter of assurance, without first obtaining
1121.17Schristos * such license, approval or letter.
1131.17Schristos *
1141.17Schristos *****************************************************************************
1151.17Schristos *
1161.17Schristos * Alternatively, you may choose to be licensed under the terms of the
1171.17Schristos * following license:
1181.17Schristos *
1191.1Schristos * Redistribution and use in source and binary forms, with or without
1201.1Schristos * modification, are permitted provided that the following conditions
1211.1Schristos * are met:
1221.1Schristos * 1. Redistributions of source code must retain the above copyright
1231.1Schristos *    notice, this list of conditions, and the following disclaimer,
1241.1Schristos *    without modification.
1251.1Schristos * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1261.1Schristos *    substantially similar to the "NO WARRANTY" disclaimer below
1271.1Schristos *    ("Disclaimer") and any redistribution must be conditioned upon
1281.1Schristos *    including a substantially similar Disclaimer requirement for further
1291.1Schristos *    binary redistribution.
1301.1Schristos * 3. Neither the names of the above-listed copyright holders nor the names
1311.1Schristos *    of any contributors may be used to endorse or promote products derived
1321.1Schristos *    from this software without specific prior written permission.
1331.1Schristos *
1341.1Schristos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1351.1Schristos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1361.14Schristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1371.1Schristos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1381.17Schristos * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1391.17Schristos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1401.17Schristos * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1411.17Schristos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1421.17Schristos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1431.17Schristos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1441.17Schristos * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1451.17Schristos *
1461.17Schristos * Alternatively, you may choose to be licensed under the terms of the
1471.17Schristos * GNU General Public License ("GPL") version 2 as published by the Free
1481.17Schristos * Software Foundation.
1491.17Schristos *
1501.17Schristos *****************************************************************************/
1511.1Schristos
1521.1Schristos#include "acpidump.h"
1531.1Schristos
1541.1Schristos
1551.1Schristos#define _COMPONENT          ACPI_OS_SERVICES
1561.1Schristos        ACPI_MODULE_NAME    ("oslinuxtbl")
1571.1Schristos
1581.1Schristos
1591.1Schristos#ifndef PATH_MAX
1601.1Schristos#define PATH_MAX 256
1611.1Schristos#endif
1621.1Schristos
1631.1Schristos
1641.1Schristos/* List of information about obtained ACPI tables */
1651.1Schristos
1661.3Schristostypedef struct osl_table_info
1671.1Schristos{
1681.3Schristos    struct osl_table_info   *Next;
1691.1Schristos    UINT32                  Instance;
1701.18Schristos    char                    Signature[ACPI_NAMESEG_SIZE] ACPI_NONSTRING;
1711.1Schristos
1721.1Schristos} OSL_TABLE_INFO;
1731.1Schristos
1741.1Schristos/* Local prototypes */
1751.1Schristos
1761.1Schristosstatic ACPI_STATUS
1771.1SchristosOslTableInitialize (
1781.1Schristos    void);
1791.1Schristos
1801.1Schristosstatic ACPI_STATUS
1811.1SchristosOslTableNameFromFile (
1821.1Schristos    char                    *Filename,
1831.1Schristos    char                    *Signature,
1841.1Schristos    UINT32                  *Instance);
1851.1Schristos
1861.1Schristosstatic ACPI_STATUS
1871.1SchristosOslAddTableToList (
1881.1Schristos    char                    *Signature,
1891.1Schristos    UINT32                  Instance);
1901.1Schristos
1911.1Schristosstatic ACPI_STATUS
1921.1SchristosOslReadTableFromFile (
1931.1Schristos    char                    *Filename,
1941.1Schristos    ACPI_SIZE               FileOffset,
1951.1Schristos    ACPI_TABLE_HEADER       **Table);
1961.1Schristos
1971.1Schristosstatic ACPI_STATUS
1981.1SchristosOslMapTable (
1991.1Schristos    ACPI_SIZE               Address,
2001.1Schristos    char                    *Signature,
2011.1Schristos    ACPI_TABLE_HEADER       **Table);
2021.1Schristos
2031.1Schristosstatic void
2041.1SchristosOslUnmapTable (
2051.1Schristos    ACPI_TABLE_HEADER       *Table);
2061.1Schristos
2071.1Schristosstatic ACPI_PHYSICAL_ADDRESS
2081.3SchristosOslFindRsdpViaEfiByKeyword (
2091.3Schristos    FILE                    *File,
2101.3Schristos    const char              *Keyword);
2111.3Schristos
2121.3Schristosstatic ACPI_PHYSICAL_ADDRESS
2131.1SchristosOslFindRsdpViaEfi (
2141.1Schristos    void);
2151.1Schristos
2161.1Schristosstatic ACPI_STATUS
2171.1SchristosOslLoadRsdp (
2181.1Schristos    void);
2191.1Schristos
2201.1Schristosstatic ACPI_STATUS
2211.1SchristosOslListCustomizedTables (
2221.1Schristos    char                    *Directory);
2231.1Schristos
2241.1Schristosstatic ACPI_STATUS
2251.1SchristosOslGetCustomizedTable (
2261.1Schristos    char                    *Pathname,
2271.1Schristos    char                    *Signature,
2281.1Schristos    UINT32                  Instance,
2291.1Schristos    ACPI_TABLE_HEADER       **Table,
2301.1Schristos    ACPI_PHYSICAL_ADDRESS   *Address);
2311.1Schristos
2321.1Schristosstatic ACPI_STATUS
2331.1SchristosOslListBiosTables (
2341.1Schristos    void);
2351.1Schristos
2361.1Schristosstatic ACPI_STATUS
2371.1SchristosOslGetBiosTable (
2381.1Schristos    char                    *Signature,
2391.1Schristos    UINT32                  Instance,
2401.1Schristos    ACPI_TABLE_HEADER       **Table,
2411.1Schristos    ACPI_PHYSICAL_ADDRESS   *Address);
2421.1Schristos
2431.1Schristosstatic ACPI_STATUS
2441.1SchristosOslGetLastStatus (
2451.1Schristos    ACPI_STATUS             DefaultStatus);
2461.1Schristos
2471.1Schristos
2481.1Schristos/* File locations */
2491.1Schristos
2501.1Schristos#define DYNAMIC_TABLE_DIR   "/sys/firmware/acpi/tables/dynamic"
2511.1Schristos#define STATIC_TABLE_DIR    "/sys/firmware/acpi/tables"
2521.1Schristos#define EFI_SYSTAB          "/sys/firmware/efi/systab"
2531.1Schristos
2541.1Schristos/* Should we get dynamically loaded SSDTs from DYNAMIC_TABLE_DIR? */
2551.1Schristos
2561.1SchristosUINT8                   Gbl_DumpDynamicTables = TRUE;
2571.1Schristos
2581.1Schristos/* Initialization flags */
2591.1Schristos
2601.1SchristosUINT8                   Gbl_TableListInitialized = FALSE;
2611.1Schristos
2621.1Schristos/* Local copies of main ACPI tables */
2631.1Schristos
2641.1SchristosACPI_TABLE_RSDP         Gbl_Rsdp;
2651.1SchristosACPI_TABLE_FADT         *Gbl_Fadt = NULL;
2661.1SchristosACPI_TABLE_RSDT         *Gbl_Rsdt = NULL;
2671.1SchristosACPI_TABLE_XSDT         *Gbl_Xsdt = NULL;
2681.1Schristos
2691.1Schristos/* Table addresses */
2701.1Schristos
2711.1SchristosACPI_PHYSICAL_ADDRESS   Gbl_FadtAddress = 0;
2721.1SchristosACPI_PHYSICAL_ADDRESS   Gbl_RsdpAddress = 0;
2731.1Schristos
2741.1Schristos/* Revision of RSD PTR */
2751.1Schristos
2761.1SchristosUINT8                   Gbl_Revision = 0;
2771.1Schristos
2781.1SchristosOSL_TABLE_INFO          *Gbl_TableListHead = NULL;
2791.1SchristosUINT32                  Gbl_TableCount = 0;
2801.1Schristos
2811.1Schristos
2821.1Schristos/******************************************************************************
2831.1Schristos *
2841.1Schristos * FUNCTION:    OslGetLastStatus
2851.1Schristos *
2861.1Schristos * PARAMETERS:  DefaultStatus   - Default error status to return
2871.1Schristos *
2881.1Schristos * RETURN:      Status; Converted from errno.
2891.1Schristos *
2901.13Schristos * DESCRIPTION: Get last errno and convert it to ACPI_STATUS.
2911.1Schristos *
2921.1Schristos *****************************************************************************/
2931.1Schristos
2941.1Schristosstatic ACPI_STATUS
2951.1SchristosOslGetLastStatus (
2961.1Schristos    ACPI_STATUS             DefaultStatus)
2971.1Schristos{
2981.1Schristos
2991.1Schristos    switch (errno)
3001.1Schristos    {
3011.1Schristos    case EACCES:
3021.1Schristos    case EPERM:
3031.1Schristos
3041.1Schristos        return (AE_ACCESS);
3051.1Schristos
3061.1Schristos    case ENOENT:
3071.1Schristos
3081.1Schristos        return (AE_NOT_FOUND);
3091.1Schristos
3101.1Schristos    case ENOMEM:
3111.1Schristos
3121.1Schristos        return (AE_NO_MEMORY);
3131.1Schristos
3141.1Schristos    default:
3151.1Schristos
3161.1Schristos        return (DefaultStatus);
3171.1Schristos    }
3181.1Schristos}
3191.1Schristos
3201.1Schristos
3211.1Schristos/******************************************************************************
3221.1Schristos *
3231.1Schristos * FUNCTION:    AcpiOsGetTableByAddress
3241.1Schristos *
3251.1Schristos * PARAMETERS:  Address         - Physical address of the ACPI table
3261.1Schristos *              Table           - Where a pointer to the table is returned
3271.1Schristos *
3281.1Schristos * RETURN:      Status; Table buffer is returned if AE_OK.
3291.1Schristos *              AE_NOT_FOUND: A valid table was not found at the address
3301.1Schristos *
3311.1Schristos * DESCRIPTION: Get an ACPI table via a physical memory address.
3321.1Schristos *
3331.1Schristos *****************************************************************************/
3341.1Schristos
3351.1SchristosACPI_STATUS
3361.1SchristosAcpiOsGetTableByAddress (
3371.1Schristos    ACPI_PHYSICAL_ADDRESS   Address,
3381.1Schristos    ACPI_TABLE_HEADER       **Table)
3391.1Schristos{
3401.1Schristos    UINT32                  TableLength;
3411.1Schristos    ACPI_TABLE_HEADER       *MappedTable;
3421.1Schristos    ACPI_TABLE_HEADER       *LocalTable = NULL;
3431.1Schristos    ACPI_STATUS             Status = AE_OK;
3441.1Schristos
3451.1Schristos
3461.1Schristos    /* Get main ACPI tables from memory on first invocation of this function */
3471.1Schristos
3481.1Schristos    Status = OslTableInitialize ();
3491.1Schristos    if (ACPI_FAILURE (Status))
3501.1Schristos    {
3511.1Schristos        return (Status);
3521.1Schristos    }
3531.1Schristos
3541.1Schristos    /* Map the table and validate it */
3551.1Schristos
3561.1Schristos    Status = OslMapTable (Address, NULL, &MappedTable);
3571.1Schristos    if (ACPI_FAILURE (Status))
3581.1Schristos    {
3591.1Schristos        return (Status);
3601.1Schristos    }
3611.1Schristos
3621.1Schristos    /* Copy table to local buffer and return it */
3631.1Schristos
3641.1Schristos    TableLength = ApGetTableLength (MappedTable);
3651.1Schristos    if (TableLength == 0)
3661.1Schristos    {
3671.1Schristos        Status = AE_BAD_HEADER;
3681.3Schristos        goto Exit;
3691.1Schristos    }
3701.1Schristos
3711.1Schristos    LocalTable = calloc (1, TableLength);
3721.1Schristos    if (!LocalTable)
3731.1Schristos    {
3741.1Schristos        Status = AE_NO_MEMORY;
3751.3Schristos        goto Exit;
3761.1Schristos    }
3771.1Schristos
3781.5Schristos    memcpy (LocalTable, MappedTable, TableLength);
3791.1Schristos
3801.3SchristosExit:
3811.1Schristos    OslUnmapTable (MappedTable);
3821.1Schristos    *Table = LocalTable;
3831.3Schristos    return (Status);
3841.1Schristos}
3851.1Schristos
3861.1Schristos
3871.1Schristos/******************************************************************************
3881.1Schristos *
3891.1Schristos * FUNCTION:    AcpiOsGetTableByName
3901.1Schristos *
3911.1Schristos * PARAMETERS:  Signature       - ACPI Signature for desired table. Must be
3921.1Schristos *                                a null terminated 4-character string.
3931.1Schristos *              Instance        - Multiple table support for SSDT/UEFI (0...n)
3941.1Schristos *                                Must be 0 for other tables.
3951.1Schristos *              Table           - Where a pointer to the table is returned
3961.1Schristos *              Address         - Where the table physical address is returned
3971.1Schristos *
3981.1Schristos * RETURN:      Status; Table buffer and physical address returned if AE_OK.
3991.1Schristos *              AE_LIMIT: Instance is beyond valid limit
4001.1Schristos *              AE_NOT_FOUND: A table with the signature was not found
4011.1Schristos *
4021.1Schristos * NOTE:        Assumes the input signature is uppercase.
4031.1Schristos *
4041.1Schristos *****************************************************************************/
4051.1Schristos
4061.1SchristosACPI_STATUS
4071.1SchristosAcpiOsGetTableByName (
4081.1Schristos    char                    *Signature,
4091.1Schristos    UINT32                  Instance,
4101.1Schristos    ACPI_TABLE_HEADER       **Table,
4111.1Schristos    ACPI_PHYSICAL_ADDRESS   *Address)
4121.1Schristos{
4131.1Schristos    ACPI_STATUS             Status;
4141.1Schristos
4151.1Schristos
4161.1Schristos    /* Get main ACPI tables from memory on first invocation of this function */
4171.1Schristos
4181.1Schristos    Status = OslTableInitialize ();
4191.1Schristos    if (ACPI_FAILURE (Status))
4201.1Schristos    {
4211.1Schristos        return (Status);
4221.1Schristos    }
4231.1Schristos
4241.1Schristos    /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */
4251.1Schristos
4261.1Schristos    if (!Gbl_DumpCustomizedTables)
4271.1Schristos    {
4281.1Schristos        /* Attempt to get the table from the memory */
4291.1Schristos
4301.1Schristos        Status = OslGetBiosTable (Signature, Instance, Table, Address);
4311.1Schristos    }
4321.1Schristos    else
4331.1Schristos    {
4341.1Schristos        /* Attempt to get the table from the static directory */
4351.1Schristos
4361.1Schristos        Status = OslGetCustomizedTable (STATIC_TABLE_DIR, Signature,
4371.1Schristos            Instance, Table, Address);
4381.1Schristos    }
4391.1Schristos
4401.1Schristos    if (ACPI_FAILURE (Status) && Status == AE_LIMIT)
4411.1Schristos    {
4421.1Schristos        if (Gbl_DumpDynamicTables)
4431.1Schristos        {
4441.1Schristos            /* Attempt to get a dynamic table */
4451.1Schristos
4461.1Schristos            Status = OslGetCustomizedTable (DYNAMIC_TABLE_DIR, Signature,
4471.1Schristos                Instance, Table, Address);
4481.1Schristos        }
4491.1Schristos    }
4501.1Schristos
4511.1Schristos    return (Status);
4521.1Schristos}
4531.1Schristos
4541.1Schristos
4551.1Schristos/******************************************************************************
4561.1Schristos *
4571.1Schristos * FUNCTION:    OslAddTableToList
4581.1Schristos *
4591.1Schristos * PARAMETERS:  Signature       - Table signature
4601.1Schristos *              Instance        - Table instance
4611.1Schristos *
4621.1Schristos * RETURN:      Status; Successfully added if AE_OK.
4631.1Schristos *              AE_NO_MEMORY: Memory allocation error
4641.1Schristos *
4651.1Schristos * DESCRIPTION: Insert a table structure into OSL table list.
4661.1Schristos *
4671.1Schristos *****************************************************************************/
4681.1Schristos
4691.1Schristosstatic ACPI_STATUS
4701.1SchristosOslAddTableToList (
4711.1Schristos    char                    *Signature,
4721.1Schristos    UINT32                  Instance)
4731.1Schristos{
4741.1Schristos    OSL_TABLE_INFO          *NewInfo;
4751.1Schristos    OSL_TABLE_INFO          *Next;
4761.1Schristos    UINT32                  NextInstance = 0;
4771.1Schristos    BOOLEAN                 Found = FALSE;
4781.1Schristos
4791.1Schristos
4801.1Schristos    NewInfo = calloc (1, sizeof (OSL_TABLE_INFO));
4811.1Schristos    if (!NewInfo)
4821.1Schristos    {
4831.1Schristos        return (AE_NO_MEMORY);
4841.1Schristos    }
4851.1Schristos
4861.10Schristos    ACPI_COPY_NAMESEG (NewInfo->Signature, Signature);
4871.1Schristos
4881.1Schristos    if (!Gbl_TableListHead)
4891.1Schristos    {
4901.1Schristos        Gbl_TableListHead = NewInfo;
4911.1Schristos    }
4921.1Schristos    else
4931.1Schristos    {
4941.1Schristos        Next = Gbl_TableListHead;
4951.1Schristos        while (1)
4961.1Schristos        {
4971.10Schristos            if (ACPI_COMPARE_NAMESEG (Next->Signature, Signature))
4981.1Schristos            {
4991.1Schristos                if (Next->Instance == Instance)
5001.1Schristos                {
5011.1Schristos                    Found = TRUE;
5021.1Schristos                }
5031.1Schristos                if (Next->Instance >= NextInstance)
5041.1Schristos                {
5051.1Schristos                    NextInstance = Next->Instance + 1;
5061.1Schristos                }
5071.1Schristos            }
5081.1Schristos
5091.1Schristos            if (!Next->Next)
5101.1Schristos            {
5111.1Schristos                break;
5121.1Schristos            }
5131.1Schristos            Next = Next->Next;
5141.1Schristos        }
5151.1Schristos        Next->Next = NewInfo;
5161.1Schristos    }
5171.1Schristos
5181.1Schristos    if (Found)
5191.1Schristos    {
5201.1Schristos        if (Instance)
5211.1Schristos        {
5221.1Schristos            fprintf (stderr,
5231.1Schristos                "%4.4s: Warning unmatched table instance %d, expected %d\n",
5241.1Schristos                Signature, Instance, NextInstance);
5251.1Schristos        }
5261.1Schristos        Instance = NextInstance;
5271.1Schristos    }
5281.1Schristos
5291.1Schristos    NewInfo->Instance = Instance;
5301.1Schristos    Gbl_TableCount++;
5311.1Schristos
5321.1Schristos    return (AE_OK);
5331.1Schristos}
5341.1Schristos
5351.1Schristos
5361.1Schristos/******************************************************************************
5371.1Schristos *
5381.1Schristos * FUNCTION:    AcpiOsGetTableByIndex
5391.1Schristos *
5401.1Schristos * PARAMETERS:  Index           - Which table to get
5411.1Schristos *              Table           - Where a pointer to the table is returned
5421.1Schristos *              Instance        - Where a pointer to the table instance no. is
5431.1Schristos *                                returned
5441.1Schristos *              Address         - Where the table physical address is returned
5451.1Schristos *
5461.1Schristos * RETURN:      Status; Table buffer and physical address returned if AE_OK.
5471.1Schristos *              AE_LIMIT: Index is beyond valid limit
5481.1Schristos *
5491.1Schristos * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
5501.1Schristos *              AE_LIMIT when an invalid index is reached. Index is not
5511.1Schristos *              necessarily an index into the RSDT/XSDT.
5521.1Schristos *
5531.1Schristos *****************************************************************************/
5541.1Schristos
5551.1SchristosACPI_STATUS
5561.1SchristosAcpiOsGetTableByIndex (
5571.1Schristos    UINT32                  Index,
5581.1Schristos    ACPI_TABLE_HEADER       **Table,
5591.1Schristos    UINT32                  *Instance,
5601.1Schristos    ACPI_PHYSICAL_ADDRESS   *Address)
5611.1Schristos{
5621.1Schristos    OSL_TABLE_INFO          *Info;
5631.1Schristos    ACPI_STATUS             Status;
5641.1Schristos    UINT32                  i;
5651.1Schristos
5661.1Schristos
5671.1Schristos    /* Get main ACPI tables from memory on first invocation of this function */
5681.1Schristos
5691.1Schristos    Status = OslTableInitialize ();
5701.1Schristos    if (ACPI_FAILURE (Status))
5711.1Schristos    {
5721.1Schristos        return (Status);
5731.1Schristos    }
5741.1Schristos
5751.1Schristos    /* Validate Index */
5761.1Schristos
5771.1Schristos    if (Index >= Gbl_TableCount)
5781.1Schristos    {
5791.1Schristos        return (AE_LIMIT);
5801.1Schristos    }
5811.1Schristos
5821.1Schristos    /* Point to the table list entry specified by the Index argument */
5831.1Schristos
5841.1Schristos    Info = Gbl_TableListHead;
5851.1Schristos    for (i = 0; i < Index; i++)
5861.1Schristos    {
5871.1Schristos        Info = Info->Next;
5881.1Schristos    }
5891.1Schristos
5901.1Schristos    /* Now we can just get the table via the signature */
5911.1Schristos
5921.1Schristos    Status = AcpiOsGetTableByName (Info->Signature, Info->Instance,
5931.1Schristos        Table, Address);
5941.1Schristos
5951.1Schristos    if (ACPI_SUCCESS (Status))
5961.1Schristos    {
5971.1Schristos        *Instance = Info->Instance;
5981.1Schristos    }
5991.1Schristos    return (Status);
6001.1Schristos}
6011.1Schristos
6021.1Schristos
6031.1Schristos/******************************************************************************
6041.1Schristos *
6051.3Schristos * FUNCTION:    OslFindRsdpViaEfiByKeyword
6061.3Schristos *
6071.3Schristos * PARAMETERS:  Keyword         - Character string indicating ACPI GUID version
6081.3Schristos *                                in the EFI table
6091.3Schristos *
6101.3Schristos * RETURN:      RSDP address if found
6111.3Schristos *
6121.3Schristos * DESCRIPTION: Find RSDP address via EFI using keyword indicating the ACPI
6131.3Schristos *              GUID version.
6141.3Schristos *
6151.3Schristos *****************************************************************************/
6161.3Schristos
6171.3Schristosstatic ACPI_PHYSICAL_ADDRESS
6181.3SchristosOslFindRsdpViaEfiByKeyword (
6191.3Schristos    FILE                    *File,
6201.3Schristos    const char              *Keyword)
6211.3Schristos{
6221.3Schristos    char                    Buffer[80];
6231.3Schristos    unsigned long long      Address = 0;
6241.3Schristos    char                    Format[32];
6251.3Schristos
6261.3Schristos
6271.3Schristos    snprintf (Format, 32, "%s=%s", Keyword, "%llx");
6281.3Schristos    fseek (File, 0, SEEK_SET);
6291.3Schristos    while (fgets (Buffer, 80, File))
6301.3Schristos    {
6311.3Schristos        if (sscanf (Buffer, Format, &Address) == 1)
6321.3Schristos        {
6331.3Schristos            break;
6341.3Schristos        }
6351.3Schristos    }
6361.3Schristos
6371.3Schristos    return ((ACPI_PHYSICAL_ADDRESS) (Address));
6381.3Schristos}
6391.3Schristos
6401.3Schristos
6411.3Schristos/******************************************************************************
6421.3Schristos *
6431.1Schristos * FUNCTION:    OslFindRsdpViaEfi
6441.1Schristos *
6451.1Schristos * PARAMETERS:  None
6461.1Schristos *
6471.1Schristos * RETURN:      RSDP address if found
6481.1Schristos *
6491.1Schristos * DESCRIPTION: Find RSDP address via EFI.
6501.1Schristos *
6511.1Schristos *****************************************************************************/
6521.1Schristos
6531.1Schristosstatic ACPI_PHYSICAL_ADDRESS
6541.1SchristosOslFindRsdpViaEfi (
6551.1Schristos    void)
6561.1Schristos{
6571.1Schristos    FILE                    *File;
6581.3Schristos    ACPI_PHYSICAL_ADDRESS   Address = 0;
6591.1Schristos
6601.1Schristos
6611.1Schristos    File = fopen (EFI_SYSTAB, "r");
6621.1Schristos    if (File)
6631.1Schristos    {
6641.3Schristos        Address = OslFindRsdpViaEfiByKeyword (File, "ACPI20");
6651.3Schristos        if (!Address)
6661.1Schristos        {
6671.3Schristos            Address = OslFindRsdpViaEfiByKeyword (File, "ACPI");
6681.1Schristos        }
6691.1Schristos        fclose (File);
6701.1Schristos    }
6711.1Schristos
6721.3Schristos    return (Address);
6731.1Schristos}
6741.1Schristos
6751.1Schristos
6761.1Schristos/******************************************************************************
6771.1Schristos *
6781.1Schristos * FUNCTION:    OslLoadRsdp
6791.1Schristos *
6801.1Schristos * PARAMETERS:  None
6811.1Schristos *
6821.1Schristos * RETURN:      Status
6831.1Schristos *
6841.1Schristos * DESCRIPTION: Scan and load RSDP.
6851.1Schristos *
6861.1Schristos *****************************************************************************/
6871.1Schristos
6881.1Schristosstatic ACPI_STATUS
6891.1SchristosOslLoadRsdp (
6901.1Schristos    void)
6911.1Schristos{
6921.1Schristos    ACPI_TABLE_HEADER       *MappedTable;
6931.1Schristos    UINT8                   *RsdpAddress;
6941.1Schristos    ACPI_PHYSICAL_ADDRESS   RsdpBase;
6951.1Schristos    ACPI_SIZE               RsdpSize;
6961.1Schristos
6971.1Schristos
6981.1Schristos    /* Get RSDP from memory */
6991.1Schristos
7001.1Schristos    RsdpSize = sizeof (ACPI_TABLE_RSDP);
7011.1Schristos    if (Gbl_RsdpBase)
7021.1Schristos    {
7031.1Schristos        RsdpBase = Gbl_RsdpBase;
7041.1Schristos    }
7051.1Schristos    else
7061.1Schristos    {
7071.1Schristos        RsdpBase = OslFindRsdpViaEfi ();
7081.1Schristos    }
7091.1Schristos
7101.1Schristos    if (!RsdpBase)
7111.1Schristos    {
7121.1Schristos        RsdpBase = ACPI_HI_RSDP_WINDOW_BASE;
7131.1Schristos        RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE;
7141.1Schristos    }
7151.1Schristos
7161.1Schristos    RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize);
7171.1Schristos    if (!RsdpAddress)
7181.1Schristos    {
7191.1Schristos        return (OslGetLastStatus (AE_BAD_ADDRESS));
7201.1Schristos    }
7211.1Schristos
7221.1Schristos    /* Search low memory for the RSDP */
7231.1Schristos
7241.1Schristos    MappedTable = ACPI_CAST_PTR (ACPI_TABLE_HEADER,
7251.1Schristos        AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize));
7261.1Schristos    if (!MappedTable)
7271.1Schristos    {
7281.1Schristos        AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
7291.1Schristos        return (AE_NOT_FOUND);
7301.1Schristos    }
7311.1Schristos
7321.1Schristos    Gbl_RsdpAddress = RsdpBase + (ACPI_CAST8 (MappedTable) - RsdpAddress);
7331.1Schristos
7341.5Schristos    memcpy (&Gbl_Rsdp, MappedTable, sizeof (ACPI_TABLE_RSDP));
7351.1Schristos    AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
7361.1Schristos
7371.1Schristos    return (AE_OK);
7381.1Schristos}
7391.1Schristos
7401.1Schristos
7411.1Schristos/******************************************************************************
7421.1Schristos *
7431.3Schristos * FUNCTION:    OslCanUseXsdt
7441.3Schristos *
7451.3Schristos * PARAMETERS:  None
7461.3Schristos *
7471.3Schristos * RETURN:      TRUE if XSDT is allowed to be used.
7481.3Schristos *
7491.3Schristos * DESCRIPTION: This function collects logic that can be used to determine if
7501.3Schristos *              XSDT should be used instead of RSDT.
7511.3Schristos *
7521.3Schristos *****************************************************************************/
7531.3Schristos
7541.3Schristosstatic BOOLEAN
7551.3SchristosOslCanUseXsdt (
7561.3Schristos    void)
7571.3Schristos{
7581.3Schristos    if (Gbl_Revision && !AcpiGbl_DoNotUseXsdt)
7591.3Schristos    {
7601.3Schristos        return (TRUE);
7611.3Schristos    }
7621.3Schristos    else
7631.3Schristos    {
7641.3Schristos        return (FALSE);
7651.3Schristos    }
7661.3Schristos}
7671.3Schristos
7681.3Schristos
7691.3Schristos/******************************************************************************
7701.3Schristos *
7711.1Schristos * FUNCTION:    OslTableInitialize
7721.1Schristos *
7731.1Schristos * PARAMETERS:  None
7741.1Schristos *
7751.1Schristos * RETURN:      Status
7761.1Schristos *
7771.1Schristos * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
7781.1Schristos *              local variables. Main ACPI tables include RSDT, FADT, RSDT,
7791.1Schristos *              and/or XSDT.
7801.1Schristos *
7811.1Schristos *****************************************************************************/
7821.1Schristos
7831.1Schristosstatic ACPI_STATUS
7841.1SchristosOslTableInitialize (
7851.1Schristos    void)
7861.1Schristos{
7871.1Schristos    ACPI_STATUS             Status;
7881.1Schristos    ACPI_PHYSICAL_ADDRESS   Address;
7891.1Schristos
7901.1Schristos
7911.1Schristos    if (Gbl_TableListInitialized)
7921.1Schristos    {
7931.1Schristos        return (AE_OK);
7941.1Schristos    }
7951.1Schristos
7961.5Schristos    if (!Gbl_DumpCustomizedTables)
7971.5Schristos    {
7981.5Schristos        /* Get RSDP from memory */
7991.1Schristos
8001.5Schristos        Status = OslLoadRsdp ();
8011.5Schristos        if (ACPI_FAILURE (Status))
8021.5Schristos        {
8031.5Schristos            return (Status);
8041.5Schristos        }
8051.1Schristos
8061.5Schristos        /* Get XSDT from memory */
8071.1Schristos
8081.5Schristos        if (Gbl_Rsdp.Revision && !Gbl_DoNotDumpXsdt)
8091.1Schristos        {
8101.5Schristos            if (Gbl_Xsdt)
8111.5Schristos            {
8121.5Schristos                free (Gbl_Xsdt);
8131.5Schristos                Gbl_Xsdt = NULL;
8141.5Schristos            }
8151.5Schristos
8161.5Schristos            Gbl_Revision = 2;
8171.5Schristos            Status = OslGetBiosTable (ACPI_SIG_XSDT, 0,
8181.5Schristos                ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Xsdt), &Address);
8191.5Schristos            if (ACPI_FAILURE (Status))
8201.5Schristos            {
8211.5Schristos                return (Status);
8221.5Schristos            }
8231.1Schristos        }
8241.1Schristos
8251.5Schristos        /* Get RSDT from memory */
8261.5Schristos
8271.5Schristos        if (Gbl_Rsdp.RsdtPhysicalAddress)
8281.1Schristos        {
8291.5Schristos            if (Gbl_Rsdt)
8301.5Schristos            {
8311.5Schristos                free (Gbl_Rsdt);
8321.5Schristos                Gbl_Rsdt = NULL;
8331.5Schristos            }
8341.5Schristos
8351.5Schristos            Status = OslGetBiosTable (ACPI_SIG_RSDT, 0,
8361.5Schristos                ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Rsdt), &Address);
8371.5Schristos            if (ACPI_FAILURE (Status))
8381.5Schristos            {
8391.5Schristos                return (Status);
8401.5Schristos            }
8411.1Schristos        }
8421.1Schristos
8431.5Schristos        /* Get FADT from memory */
8441.1Schristos
8451.5Schristos        if (Gbl_Fadt)
8461.1Schristos        {
8471.5Schristos            free (Gbl_Fadt);
8481.5Schristos            Gbl_Fadt = NULL;
8491.1Schristos        }
8501.1Schristos
8511.5Schristos        Status = OslGetBiosTable (ACPI_SIG_FADT, 0,
8521.5Schristos            ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Fadt), &Gbl_FadtAddress);
8531.1Schristos        if (ACPI_FAILURE (Status))
8541.1Schristos        {
8551.1Schristos            return (Status);
8561.1Schristos        }
8571.1Schristos
8581.1Schristos        /* Add mandatory tables to global table list first */
8591.1Schristos
8601.3Schristos        Status = OslAddTableToList (ACPI_RSDP_NAME, 0);
8611.1Schristos        if (ACPI_FAILURE (Status))
8621.1Schristos        {
8631.1Schristos            return (Status);
8641.1Schristos        }
8651.1Schristos
8661.1Schristos        Status = OslAddTableToList (ACPI_SIG_RSDT, 0);
8671.1Schristos        if (ACPI_FAILURE (Status))
8681.1Schristos        {
8691.1Schristos            return (Status);
8701.1Schristos        }
8711.1Schristos
8721.1Schristos        if (Gbl_Revision == 2)
8731.1Schristos        {
8741.1Schristos            Status = OslAddTableToList (ACPI_SIG_XSDT, 0);
8751.1Schristos            if (ACPI_FAILURE (Status))
8761.1Schristos            {
8771.1Schristos                return (Status);
8781.1Schristos            }
8791.1Schristos        }
8801.1Schristos
8811.1Schristos        Status = OslAddTableToList (ACPI_SIG_DSDT, 0);
8821.1Schristos        if (ACPI_FAILURE (Status))
8831.1Schristos        {
8841.1Schristos            return (Status);
8851.1Schristos        }
8861.1Schristos
8871.1Schristos        Status = OslAddTableToList (ACPI_SIG_FACS, 0);
8881.1Schristos        if (ACPI_FAILURE (Status))
8891.1Schristos        {
8901.1Schristos            return (Status);
8911.1Schristos        }
8921.1Schristos
8931.1Schristos        /* Add all tables found in the memory */
8941.1Schristos
8951.1Schristos        Status = OslListBiosTables ();
8961.1Schristos        if (ACPI_FAILURE (Status))
8971.1Schristos        {
8981.1Schristos            return (Status);
8991.1Schristos        }
9001.1Schristos    }
9011.1Schristos    else
9021.1Schristos    {
9031.1Schristos        /* Add all tables found in the static directory */
9041.1Schristos
9051.1Schristos        Status = OslListCustomizedTables (STATIC_TABLE_DIR);
9061.1Schristos        if (ACPI_FAILURE (Status))
9071.1Schristos        {
9081.1Schristos            return (Status);
9091.1Schristos        }
9101.1Schristos    }
9111.1Schristos
9121.1Schristos    if (Gbl_DumpDynamicTables)
9131.1Schristos    {
9141.1Schristos        /* Add all dynamically loaded tables in the dynamic directory */
9151.1Schristos
9161.1Schristos        Status = OslListCustomizedTables (DYNAMIC_TABLE_DIR);
9171.1Schristos        if (ACPI_FAILURE (Status))
9181.1Schristos        {
9191.1Schristos            return (Status);
9201.1Schristos        }
9211.1Schristos    }
9221.1Schristos
9231.1Schristos    Gbl_TableListInitialized = TRUE;
9241.1Schristos    return (AE_OK);
9251.1Schristos}
9261.1Schristos
9271.1Schristos
9281.1Schristos/******************************************************************************
9291.1Schristos *
9301.1Schristos * FUNCTION:    OslListBiosTables
9311.1Schristos *
9321.1Schristos * PARAMETERS:  None
9331.1Schristos *
9341.1Schristos * RETURN:      Status; Table list is initialized if AE_OK.
9351.1Schristos *
9361.1Schristos * DESCRIPTION: Add ACPI tables to the table list from memory.
9371.1Schristos *
9381.1Schristos * NOTE:        This works on Linux as table customization does not modify the
9391.1Schristos *              addresses stored in RSDP/RSDT/XSDT/FADT.
9401.1Schristos *
9411.1Schristos *****************************************************************************/
9421.1Schristos
9431.1Schristosstatic ACPI_STATUS
9441.1SchristosOslListBiosTables (
9451.1Schristos    void)
9461.1Schristos{
9471.1Schristos    ACPI_TABLE_HEADER       *MappedTable = NULL;
9481.1Schristos    UINT8                   *TableData;
9491.1Schristos    UINT8                   NumberOfTables;
9501.1Schristos    UINT8                   ItemSize;
9511.1Schristos    ACPI_PHYSICAL_ADDRESS   TableAddress = 0;
9521.1Schristos    ACPI_STATUS             Status = AE_OK;
9531.1Schristos    UINT32                  i;
9541.1Schristos
9551.1Schristos
9561.3Schristos    if (OslCanUseXsdt ())
9571.1Schristos    {
9581.1Schristos        ItemSize = sizeof (UINT64);
9591.1Schristos        TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER);
9601.1Schristos        NumberOfTables =
9611.1Schristos            (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
9621.1Schristos            / ItemSize);
9631.1Schristos    }
9641.1Schristos    else /* Use RSDT if XSDT is not available */
9651.1Schristos    {
9661.1Schristos        ItemSize = sizeof (UINT32);
9671.1Schristos        TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER);
9681.1Schristos        NumberOfTables =
9691.1Schristos            (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
9701.1Schristos            / ItemSize);
9711.1Schristos    }
9721.1Schristos
9731.1Schristos    /* Search RSDT/XSDT for the requested table */
9741.1Schristos
9751.1Schristos    for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize)
9761.1Schristos    {
9771.3Schristos        if (OslCanUseXsdt ())
9781.1Schristos        {
9791.1Schristos            TableAddress =
9801.1Schristos                (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData));
9811.1Schristos        }
9821.1Schristos        else
9831.1Schristos        {
9841.1Schristos            TableAddress =
9851.1Schristos                (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData));
9861.1Schristos        }
9871.1Schristos
9881.3Schristos        /* Skip NULL entries in RSDT/XSDT */
9891.3Schristos
9901.8Schristos        if (TableAddress == 0)
9911.3Schristos        {
9921.3Schristos            continue;
9931.3Schristos        }
9941.3Schristos
9951.1Schristos        Status = OslMapTable (TableAddress, NULL, &MappedTable);
9961.1Schristos        if (ACPI_FAILURE (Status))
9971.1Schristos        {
9981.1Schristos            return (Status);
9991.1Schristos        }
10001.1Schristos
10011.1Schristos        OslAddTableToList (MappedTable->Signature, 0);
10021.1Schristos        OslUnmapTable (MappedTable);
10031.1Schristos    }
10041.1Schristos
10051.1Schristos    return (AE_OK);
10061.1Schristos}
10071.1Schristos
10081.1Schristos
10091.1Schristos/******************************************************************************
10101.1Schristos *
10111.1Schristos * FUNCTION:    OslGetBiosTable
10121.1Schristos *
10131.1Schristos * PARAMETERS:  Signature       - ACPI Signature for common table. Must be
10141.1Schristos *                                a null terminated 4-character string.
10151.1Schristos *              Instance        - Multiple table support for SSDT/UEFI (0...n)
10161.1Schristos *                                Must be 0 for other tables.
10171.1Schristos *              Table           - Where a pointer to the table is returned
10181.1Schristos *              Address         - Where the table physical address is returned
10191.1Schristos *
10201.1Schristos * RETURN:      Status; Table buffer and physical address returned if AE_OK.
10211.1Schristos *              AE_LIMIT: Instance is beyond valid limit
10221.1Schristos *              AE_NOT_FOUND: A table with the signature was not found
10231.1Schristos *
10241.1Schristos * DESCRIPTION: Get a BIOS provided ACPI table
10251.1Schristos *
10261.1Schristos * NOTE:        Assumes the input signature is uppercase.
10271.1Schristos *
10281.1Schristos *****************************************************************************/
10291.1Schristos
10301.1Schristosstatic ACPI_STATUS
10311.1SchristosOslGetBiosTable (
10321.1Schristos    char                    *Signature,
10331.1Schristos    UINT32                  Instance,
10341.1Schristos    ACPI_TABLE_HEADER       **Table,
10351.1Schristos    ACPI_PHYSICAL_ADDRESS   *Address)
10361.1Schristos{
10371.1Schristos    ACPI_TABLE_HEADER       *LocalTable = NULL;
10381.1Schristos    ACPI_TABLE_HEADER       *MappedTable = NULL;
10391.1Schristos    UINT8                   *TableData;
10401.1Schristos    UINT8                   NumberOfTables;
10411.1Schristos    UINT8                   ItemSize;
10421.1Schristos    UINT32                  CurrentInstance = 0;
10431.8Schristos    ACPI_PHYSICAL_ADDRESS   TableAddress;
10441.8Schristos    ACPI_PHYSICAL_ADDRESS   FirstTableAddress = 0;
10451.1Schristos    UINT32                  TableLength = 0;
10461.1Schristos    ACPI_STATUS             Status = AE_OK;
10471.1Schristos    UINT32                  i;
10481.1Schristos
10491.1Schristos
10501.1Schristos    /* Handle special tables whose addresses are not in RSDT/XSDT */
10511.1Schristos
10521.10Schristos    if (ACPI_COMPARE_NAMESEG (Signature, ACPI_RSDP_NAME) ||
10531.10Schristos        ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_RSDT) ||
10541.10Schristos        ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_XSDT) ||
10551.10Schristos        ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_DSDT) ||
10561.10Schristos        ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FACS))
10571.1Schristos    {
10581.8Schristos
10591.8SchristosFindNextInstance:
10601.8Schristos
10611.8Schristos        TableAddress = 0;
10621.3Schristos
10631.1Schristos        /*
10641.1Schristos         * Get the appropriate address, either 32-bit or 64-bit. Be very
10651.1Schristos         * careful about the FADT length and validate table addresses.
10661.1Schristos         * Note: The 64-bit addresses have priority.
10671.1Schristos         */
10681.10Schristos        if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_DSDT))
10691.1Schristos        {
10701.8Schristos            if (CurrentInstance < 2)
10711.1Schristos            {
10721.8Schristos                if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
10731.8Schristos                    Gbl_Fadt->XDsdt && CurrentInstance == 0)
10741.8Schristos                {
10751.8Schristos                    TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
10761.8Schristos                }
10771.8Schristos                else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) &&
10781.8Schristos                    Gbl_Fadt->Dsdt != FirstTableAddress)
10791.8Schristos                {
10801.8Schristos                    TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
10811.8Schristos                }
10821.1Schristos            }
10831.1Schristos        }
10841.10Schristos        else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FACS))
10851.1Schristos        {
10861.8Schristos            if (CurrentInstance < 2)
10871.1Schristos            {
10881.8Schristos                if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
10891.8Schristos                    Gbl_Fadt->XFacs && CurrentInstance == 0)
10901.8Schristos                {
10911.8Schristos                    TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
10921.8Schristos                }
10931.8Schristos                else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) &&
10941.8Schristos                    Gbl_Fadt->Facs != FirstTableAddress)
10951.8Schristos                {
10961.8Schristos                    TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
10971.8Schristos                }
10981.1Schristos            }
10991.1Schristos        }
11001.10Schristos        else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_XSDT))
11011.1Schristos        {
11021.1Schristos            if (!Gbl_Revision)
11031.1Schristos            {
11041.1Schristos                return (AE_BAD_SIGNATURE);
11051.1Schristos            }
11061.8Schristos            if (CurrentInstance == 0)
11071.8Schristos            {
11081.8Schristos                TableAddress =
11091.8Schristos                    (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.XsdtPhysicalAddress;
11101.8Schristos            }
11111.1Schristos        }
11121.10Schristos        else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_RSDT))
11131.1Schristos        {
11141.8Schristos            if (CurrentInstance == 0)
11151.8Schristos            {
11161.8Schristos                TableAddress =
11171.8Schristos                    (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.RsdtPhysicalAddress;
11181.8Schristos            }
11191.1Schristos        }
11201.1Schristos        else
11211.1Schristos        {
11221.8Schristos            if (CurrentInstance == 0)
11231.8Schristos            {
11241.8Schristos                TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_RsdpAddress;
11251.8Schristos                Signature = ACPI_SIG_RSDP;
11261.8Schristos            }
11271.8Schristos        }
11281.8Schristos
11291.8Schristos        if (TableAddress == 0)
11301.8Schristos        {
11311.8Schristos            goto ExitFindTable;
11321.1Schristos        }
11331.1Schristos
11341.1Schristos        /* Now we can get the requested special table */
11351.1Schristos
11361.1Schristos        Status = OslMapTable (TableAddress, Signature, &MappedTable);
11371.1Schristos        if (ACPI_FAILURE (Status))
11381.1Schristos        {
11391.1Schristos            return (Status);
11401.1Schristos        }
11411.1Schristos
11421.1Schristos        TableLength = ApGetTableLength (MappedTable);
11431.8Schristos        if (FirstTableAddress == 0)
11441.8Schristos        {
11451.8Schristos            FirstTableAddress = TableAddress;
11461.8Schristos        }
11471.8Schristos
11481.8Schristos        /* Match table instance */
11491.8Schristos
11501.8Schristos        if (CurrentInstance != Instance)
11511.8Schristos        {
11521.8Schristos            OslUnmapTable (MappedTable);
11531.8Schristos            MappedTable = NULL;
11541.8Schristos            CurrentInstance++;
11551.8Schristos            goto FindNextInstance;
11561.8Schristos        }
11571.1Schristos    }
11581.1Schristos    else /* Case for a normal ACPI table */
11591.1Schristos    {
11601.3Schristos        if (OslCanUseXsdt ())
11611.1Schristos        {
11621.1Schristos            ItemSize = sizeof (UINT64);
11631.1Schristos            TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER);
11641.1Schristos            NumberOfTables =
11651.1Schristos                (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
11661.1Schristos                / ItemSize);
11671.1Schristos        }
11681.1Schristos        else /* Use RSDT if XSDT is not available */
11691.1Schristos        {
11701.1Schristos            ItemSize = sizeof (UINT32);
11711.1Schristos            TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER);
11721.1Schristos            NumberOfTables =
11731.1Schristos                (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
11741.1Schristos                / ItemSize);
11751.1Schristos        }
11761.1Schristos
11771.1Schristos        /* Search RSDT/XSDT for the requested table */
11781.1Schristos
11791.1Schristos        for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize)
11801.1Schristos        {
11811.3Schristos            if (OslCanUseXsdt ())
11821.1Schristos            {
11831.1Schristos                TableAddress =
11841.1Schristos                    (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData));
11851.1Schristos            }
11861.1Schristos            else
11871.1Schristos            {
11881.1Schristos                TableAddress =
11891.1Schristos                    (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData));
11901.1Schristos            }
11911.1Schristos
11921.3Schristos            /* Skip NULL entries in RSDT/XSDT */
11931.3Schristos
11941.8Schristos            if (TableAddress == 0)
11951.3Schristos            {
11961.3Schristos                continue;
11971.3Schristos            }
11981.3Schristos
11991.1Schristos            Status = OslMapTable (TableAddress, NULL, &MappedTable);
12001.1Schristos            if (ACPI_FAILURE (Status))
12011.1Schristos            {
12021.1Schristos                return (Status);
12031.1Schristos            }
12041.1Schristos            TableLength = MappedTable->Length;
12051.1Schristos
12061.1Schristos            /* Does this table match the requested signature? */
12071.1Schristos
12081.10Schristos            if (!ACPI_COMPARE_NAMESEG (MappedTable->Signature, Signature))
12091.1Schristos            {
12101.1Schristos                OslUnmapTable (MappedTable);
12111.1Schristos                MappedTable = NULL;
12121.1Schristos                continue;
12131.1Schristos            }
12141.1Schristos
12151.1Schristos            /* Match table instance (for SSDT/UEFI tables) */
12161.1Schristos
12171.1Schristos            if (CurrentInstance != Instance)
12181.1Schristos            {
12191.1Schristos                OslUnmapTable (MappedTable);
12201.1Schristos                MappedTable = NULL;
12211.1Schristos                CurrentInstance++;
12221.1Schristos                continue;
12231.1Schristos            }
12241.1Schristos
12251.1Schristos            break;
12261.1Schristos        }
12271.1Schristos    }
12281.1Schristos
12291.8SchristosExitFindTable:
12301.8Schristos
12311.1Schristos    if (!MappedTable)
12321.1Schristos    {
12331.1Schristos        return (AE_LIMIT);
12341.1Schristos    }
12351.1Schristos
12361.1Schristos    if (TableLength == 0)
12371.1Schristos    {
12381.1Schristos        Status = AE_BAD_HEADER;
12391.3Schristos        goto Exit;
12401.1Schristos    }
12411.1Schristos
12421.1Schristos    /* Copy table to local buffer and return it */
12431.1Schristos
12441.1Schristos    LocalTable = calloc (1, TableLength);
12451.1Schristos    if (!LocalTable)
12461.1Schristos    {
12471.1Schristos        Status = AE_NO_MEMORY;
12481.3Schristos        goto Exit;
12491.1Schristos    }
12501.1Schristos
12511.5Schristos    memcpy (LocalTable, MappedTable, TableLength);
12521.1Schristos    *Address = TableAddress;
12531.1Schristos    *Table = LocalTable;
12541.1Schristos
12551.3SchristosExit:
12561.1Schristos    OslUnmapTable (MappedTable);
12571.3Schristos    return (Status);
12581.1Schristos}
12591.1Schristos
12601.1Schristos
12611.1Schristos/******************************************************************************
12621.1Schristos *
12631.1Schristos * FUNCTION:    OslListCustomizedTables
12641.1Schristos *
12651.1Schristos * PARAMETERS:  Directory           - Directory that contains the tables
12661.1Schristos *
12671.1Schristos * RETURN:      Status; Table list is initialized if AE_OK.
12681.1Schristos *
12691.1Schristos * DESCRIPTION: Add ACPI tables to the table list from a directory.
12701.1Schristos *
12711.1Schristos *****************************************************************************/
12721.1Schristos
12731.1Schristosstatic ACPI_STATUS
12741.1SchristosOslListCustomizedTables (
12751.1Schristos    char                    *Directory)
12761.1Schristos{
12771.1Schristos    void                    *TableDir;
12781.1Schristos    UINT32                  Instance;
12791.18Schristos    char                    TempName[ACPI_NAMESEG_SIZE] ACPI_NONSTRING;
12801.1Schristos    char                    *Filename;
12811.1Schristos    ACPI_STATUS             Status = AE_OK;
12821.1Schristos
12831.1Schristos
12841.1Schristos    /* Open the requested directory */
12851.1Schristos
12861.1Schristos    TableDir = AcpiOsOpenDirectory (Directory, "*", REQUEST_FILE_ONLY);
12871.1Schristos    if (!TableDir)
12881.1Schristos    {
12891.1Schristos        return (OslGetLastStatus (AE_NOT_FOUND));
12901.1Schristos    }
12911.1Schristos
12921.1Schristos    /* Examine all entries in this directory */
12931.1Schristos
12941.1Schristos    while ((Filename = AcpiOsGetNextFilename (TableDir)))
12951.1Schristos    {
12961.1Schristos        /* Extract table name and instance number */
12971.1Schristos
12981.1Schristos        Status = OslTableNameFromFile (Filename, TempName, &Instance);
12991.1Schristos
13001.1Schristos        /* Ignore meaningless files */
13011.1Schristos
13021.1Schristos        if (ACPI_FAILURE (Status))
13031.1Schristos        {
13041.1Schristos            continue;
13051.1Schristos        }
13061.1Schristos
13071.1Schristos        /* Add new info node to global table list */
13081.1Schristos
13091.1Schristos        Status = OslAddTableToList (TempName, Instance);
13101.1Schristos        if (ACPI_FAILURE (Status))
13111.1Schristos        {
13121.1Schristos            break;
13131.1Schristos        }
13141.1Schristos    }
13151.1Schristos
13161.1Schristos    AcpiOsCloseDirectory (TableDir);
13171.1Schristos    return (Status);
13181.1Schristos}
13191.1Schristos
13201.1Schristos
13211.1Schristos/******************************************************************************
13221.1Schristos *
13231.1Schristos * FUNCTION:    OslMapTable
13241.1Schristos *
13251.1Schristos * PARAMETERS:  Address             - Address of the table in memory
13261.1Schristos *              Signature           - Optional ACPI Signature for desired table.
13271.1Schristos *                                    Null terminated 4-character string.
13281.1Schristos *              Table               - Where a pointer to the mapped table is
13291.1Schristos *                                    returned
13301.1Schristos *
13311.1Schristos * RETURN:      Status; Mapped table is returned if AE_OK.
13321.1Schristos *              AE_NOT_FOUND: A valid table was not found at the address
13331.1Schristos *
13341.1Schristos * DESCRIPTION: Map entire ACPI table into caller's address space.
13351.1Schristos *
13361.1Schristos *****************************************************************************/
13371.1Schristos
13381.1Schristosstatic ACPI_STATUS
13391.1SchristosOslMapTable (
13401.1Schristos    ACPI_SIZE               Address,
13411.1Schristos    char                    *Signature,
13421.1Schristos    ACPI_TABLE_HEADER       **Table)
13431.1Schristos{
13441.1Schristos    ACPI_TABLE_HEADER       *MappedTable;
13451.1Schristos    UINT32                  Length;
13461.1Schristos
13471.1Schristos
13481.1Schristos    if (!Address)
13491.1Schristos    {
13501.1Schristos        return (AE_BAD_ADDRESS);
13511.1Schristos    }
13521.1Schristos
13531.1Schristos    /*
13541.1Schristos     * Map the header so we can get the table length.
13551.1Schristos     * Use sizeof (ACPI_TABLE_HEADER) as:
13561.1Schristos     * 1. it is bigger than 24 to include RSDP->Length
13571.1Schristos     * 2. it is smaller than sizeof (ACPI_TABLE_RSDP)
13581.1Schristos     */
13591.1Schristos    MappedTable = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
13601.1Schristos    if (!MappedTable)
13611.1Schristos    {
13621.1Schristos        fprintf (stderr, "Could not map table header at 0x%8.8X%8.8X\n",
13631.1Schristos            ACPI_FORMAT_UINT64 (Address));
13641.1Schristos        return (OslGetLastStatus (AE_BAD_ADDRESS));
13651.1Schristos    }
13661.1Schristos
13671.1Schristos    /* If specified, signature must match */
13681.1Schristos
13691.3Schristos    if (Signature)
13701.1Schristos    {
13711.3Schristos        if (ACPI_VALIDATE_RSDP_SIG (Signature))
13721.3Schristos        {
13731.3Schristos            if (!ACPI_VALIDATE_RSDP_SIG (MappedTable->Signature))
13741.3Schristos            {
13751.3Schristos                AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
13761.3Schristos                return (AE_BAD_SIGNATURE);
13771.3Schristos            }
13781.3Schristos        }
13791.10Schristos        else if (!ACPI_COMPARE_NAMESEG (Signature, MappedTable->Signature))
13801.3Schristos        {
13811.3Schristos            AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
13821.3Schristos            return (AE_BAD_SIGNATURE);
13831.3Schristos        }
13841.1Schristos    }
13851.1Schristos
13861.1Schristos    /* Map the entire table */
13871.1Schristos
13881.1Schristos    Length = ApGetTableLength (MappedTable);
13891.1Schristos    AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
13901.1Schristos    if (Length == 0)
13911.1Schristos    {
13921.1Schristos        return (AE_BAD_HEADER);
13931.1Schristos    }
13941.1Schristos
13951.1Schristos    MappedTable = AcpiOsMapMemory (Address, Length);
13961.1Schristos    if (!MappedTable)
13971.1Schristos    {
13981.1Schristos        fprintf (stderr, "Could not map table at 0x%8.8X%8.8X length %8.8X\n",
13991.1Schristos            ACPI_FORMAT_UINT64 (Address), Length);
14001.1Schristos        return (OslGetLastStatus (AE_INVALID_TABLE_LENGTH));
14011.1Schristos    }
14021.1Schristos
14031.1Schristos    (void) ApIsValidChecksum (MappedTable);
14041.1Schristos
14051.1Schristos    *Table = MappedTable;
14061.1Schristos    return (AE_OK);
14071.1Schristos}
14081.1Schristos
14091.1Schristos
14101.1Schristos/******************************************************************************
14111.1Schristos *
14121.1Schristos * FUNCTION:    OslUnmapTable
14131.1Schristos *
14141.1Schristos * PARAMETERS:  Table               - A pointer to the mapped table
14151.1Schristos *
14161.1Schristos * RETURN:      None
14171.1Schristos *
14181.1Schristos * DESCRIPTION: Unmap entire ACPI table.
14191.1Schristos *
14201.1Schristos *****************************************************************************/
14211.1Schristos
14221.1Schristosstatic void
14231.1SchristosOslUnmapTable (
14241.1Schristos    ACPI_TABLE_HEADER       *Table)
14251.1Schristos{
14261.1Schristos    if (Table)
14271.1Schristos    {
14281.1Schristos        AcpiOsUnmapMemory (Table, ApGetTableLength (Table));
14291.1Schristos    }
14301.1Schristos}
14311.1Schristos
14321.1Schristos
14331.1Schristos/******************************************************************************
14341.1Schristos *
14351.1Schristos * FUNCTION:    OslTableNameFromFile
14361.1Schristos *
14371.1Schristos * PARAMETERS:  Filename            - File that contains the desired table
14381.1Schristos *              Signature           - Pointer to 4-character buffer to store
14391.1Schristos *                                    extracted table signature.
14401.1Schristos *              Instance            - Pointer to integer to store extracted
14411.1Schristos *                                    table instance number.
14421.1Schristos *
14431.1Schristos * RETURN:      Status; Table name is extracted if AE_OK.
14441.1Schristos *
14451.1Schristos * DESCRIPTION: Extract table signature and instance number from a table file
14461.1Schristos *              name.
14471.1Schristos *
14481.1Schristos *****************************************************************************/
14491.1Schristos
14501.1Schristosstatic ACPI_STATUS
14511.1SchristosOslTableNameFromFile (
14521.1Schristos    char                    *Filename,
14531.1Schristos    char                    *Signature,
14541.1Schristos    UINT32                  *Instance)
14551.1Schristos{
14561.1Schristos
14571.1Schristos    /* Ignore meaningless files */
14581.1Schristos
14591.10Schristos    if (strlen (Filename) < ACPI_NAMESEG_SIZE)
14601.1Schristos    {
14611.1Schristos        return (AE_BAD_SIGNATURE);
14621.1Schristos    }
14631.1Schristos
14641.1Schristos    /* Extract instance number */
14651.1Schristos
14661.10Schristos    if (isdigit ((int) Filename[ACPI_NAMESEG_SIZE]))
14671.1Schristos    {
14681.10Schristos        sscanf (&Filename[ACPI_NAMESEG_SIZE], "%u", Instance);
14691.1Schristos    }
14701.10Schristos    else if (strlen (Filename) != ACPI_NAMESEG_SIZE)
14711.1Schristos    {
14721.1Schristos        return (AE_BAD_SIGNATURE);
14731.1Schristos    }
14741.1Schristos    else
14751.1Schristos    {
14761.1Schristos        *Instance = 0;
14771.1Schristos    }
14781.1Schristos
14791.1Schristos    /* Extract signature */
14801.1Schristos
14811.10Schristos    ACPI_COPY_NAMESEG (Signature, Filename);
14821.1Schristos    return (AE_OK);
14831.1Schristos}
14841.1Schristos
14851.1Schristos
14861.1Schristos/******************************************************************************
14871.1Schristos *
14881.1Schristos * FUNCTION:    OslReadTableFromFile
14891.1Schristos *
14901.1Schristos * PARAMETERS:  Filename            - File that contains the desired table
14911.1Schristos *              FileOffset          - Offset of the table in file
14921.1Schristos *              Table               - Where a pointer to the table is returned
14931.1Schristos *
14941.1Schristos * RETURN:      Status; Table buffer is returned if AE_OK.
14951.1Schristos *
14961.1Schristos * DESCRIPTION: Read a ACPI table from a file.
14971.1Schristos *
14981.1Schristos *****************************************************************************/
14991.1Schristos
15001.1Schristosstatic ACPI_STATUS
15011.1SchristosOslReadTableFromFile (
15021.1Schristos    char                    *Filename,
15031.1Schristos    ACPI_SIZE               FileOffset,
15041.1Schristos    ACPI_TABLE_HEADER       **Table)
15051.1Schristos{
15061.1Schristos    FILE                    *TableFile;
15071.1Schristos    ACPI_TABLE_HEADER       Header;
15081.1Schristos    ACPI_TABLE_HEADER       *LocalTable = NULL;
15091.1Schristos    UINT32                  TableLength;
15101.1Schristos    INT32                   Count;
15111.1Schristos    ACPI_STATUS             Status = AE_OK;
15121.1Schristos
15131.1Schristos
15141.1Schristos    /* Open the file */
15151.1Schristos
15161.1Schristos    TableFile = fopen (Filename, "rb");
15171.1Schristos    if (TableFile == NULL)
15181.1Schristos    {
15191.1Schristos        fprintf (stderr, "Could not open table file: %s\n", Filename);
15201.1Schristos        return (OslGetLastStatus (AE_NOT_FOUND));
15211.1Schristos    }
15221.1Schristos
15231.1Schristos    fseek (TableFile, FileOffset, SEEK_SET);
15241.1Schristos
15251.1Schristos    /* Read the Table header to get the table length */
15261.1Schristos
15271.1Schristos    Count = fread (&Header, 1, sizeof (ACPI_TABLE_HEADER), TableFile);
15281.1Schristos    if (Count != sizeof (ACPI_TABLE_HEADER))
15291.1Schristos    {
15301.1Schristos        fprintf (stderr, "Could not read table header: %s\n", Filename);
15311.1Schristos        Status = AE_BAD_HEADER;
15321.3Schristos        goto Exit;
15331.1Schristos    }
15341.1Schristos
15351.12Schristos#ifdef ACPI_OBSOLETE_FUNCTIONS
15361.12Schristos
15371.1Schristos    /* If signature is specified, it must match the table */
15381.1Schristos
15391.3Schristos    if (Signature)
15401.1Schristos    {
15411.3Schristos        if (ACPI_VALIDATE_RSDP_SIG (Signature))
15421.3Schristos        {
15431.3Schristos            if (!ACPI_VALIDATE_RSDP_SIG (Header.Signature)) {
15441.3Schristos                fprintf (stderr, "Incorrect RSDP signature: found %8.8s\n",
15451.3Schristos                    Header.Signature);
15461.3Schristos                Status = AE_BAD_SIGNATURE;
15471.3Schristos                goto Exit;
15481.3Schristos            }
15491.3Schristos        }
15501.10Schristos        else if (!ACPI_COMPARE_NAMESEG (Signature, Header.Signature))
15511.3Schristos        {
15521.3Schristos            fprintf (stderr, "Incorrect signature: Expecting %4.4s, found %4.4s\n",
15531.3Schristos                Signature, Header.Signature);
15541.3Schristos            Status = AE_BAD_SIGNATURE;
15551.3Schristos            goto Exit;
15561.3Schristos        }
15571.1Schristos    }
15581.12Schristos#endif
15591.1Schristos
15601.1Schristos    TableLength = ApGetTableLength (&Header);
15611.1Schristos    if (TableLength == 0)
15621.1Schristos    {
15631.1Schristos        Status = AE_BAD_HEADER;
15641.3Schristos        goto Exit;
15651.1Schristos    }
15661.1Schristos
15671.1Schristos    /* Read the entire table into a local buffer */
15681.1Schristos
15691.1Schristos    LocalTable = calloc (1, TableLength);
15701.1Schristos    if (!LocalTable)
15711.1Schristos    {
15721.1Schristos        fprintf (stderr,
15731.1Schristos            "%4.4s: Could not allocate buffer for table of length %X\n",
15741.1Schristos            Header.Signature, TableLength);
15751.1Schristos        Status = AE_NO_MEMORY;
15761.3Schristos        goto Exit;
15771.1Schristos    }
15781.1Schristos
15791.1Schristos    fseek (TableFile, FileOffset, SEEK_SET);
15801.1Schristos
15811.3Schristos    Count = fread (LocalTable, 1, TableLength, TableFile);
15821.3Schristos    if (Count != TableLength)
15831.1Schristos    {
15841.3Schristos        fprintf (stderr, "%4.4s: Could not read table content\n",
15851.3Schristos            Header.Signature);
15861.3Schristos        Status = AE_INVALID_TABLE_LENGTH;
15871.3Schristos        goto Exit;
15881.1Schristos    }
15891.1Schristos
15901.1Schristos    /* Validate checksum */
15911.1Schristos
15921.1Schristos    (void) ApIsValidChecksum (LocalTable);
15931.1Schristos
15941.3SchristosExit:
15951.1Schristos    fclose (TableFile);
15961.1Schristos    *Table = LocalTable;
15971.1Schristos    return (Status);
15981.1Schristos}
15991.1Schristos
16001.1Schristos
16011.1Schristos/******************************************************************************
16021.1Schristos *
16031.1Schristos * FUNCTION:    OslGetCustomizedTable
16041.1Schristos *
16051.1Schristos * PARAMETERS:  Pathname        - Directory to find Linux customized table
16061.1Schristos *              Signature       - ACPI Signature for desired table. Must be
16071.1Schristos *                                a null terminated 4-character string.
16081.1Schristos *              Instance        - Multiple table support for SSDT/UEFI (0...n)
16091.1Schristos *                                Must be 0 for other tables.
16101.1Schristos *              Table           - Where a pointer to the table is returned
16111.1Schristos *              Address         - Where the table physical address is returned
16121.1Schristos *
16131.1Schristos * RETURN:      Status; Table buffer is returned if AE_OK.
16141.1Schristos *              AE_LIMIT: Instance is beyond valid limit
16151.1Schristos *              AE_NOT_FOUND: A table with the signature was not found
16161.1Schristos *
16171.1Schristos * DESCRIPTION: Get an OS customized table.
16181.1Schristos *
16191.1Schristos *****************************************************************************/
16201.1Schristos
16211.1Schristosstatic ACPI_STATUS
16221.1SchristosOslGetCustomizedTable (
16231.1Schristos    char                    *Pathname,
16241.1Schristos    char                    *Signature,
16251.1Schristos    UINT32                  Instance,
16261.1Schristos    ACPI_TABLE_HEADER       **Table,
16271.1Schristos    ACPI_PHYSICAL_ADDRESS   *Address)
16281.1Schristos{
16291.1Schristos    void                    *TableDir;
16301.1Schristos    UINT32                  CurrentInstance = 0;
16311.18Schristos    char                    TempName[ACPI_NAMESEG_SIZE] ACPI_NONSTRING;
16321.1Schristos    char                    TableFilename[PATH_MAX];
16331.1Schristos    char                    *Filename;
16341.1Schristos    ACPI_STATUS             Status;
16351.1Schristos
16361.1Schristos
16371.1Schristos    /* Open the directory for customized tables */
16381.1Schristos
16391.1Schristos    TableDir = AcpiOsOpenDirectory (Pathname, "*", REQUEST_FILE_ONLY);
16401.1Schristos    if (!TableDir)
16411.1Schristos    {
16421.1Schristos        return (OslGetLastStatus (AE_NOT_FOUND));
16431.1Schristos    }
16441.1Schristos
16451.1Schristos    /* Attempt to find the table in the directory */
16461.1Schristos
16471.1Schristos    while ((Filename = AcpiOsGetNextFilename (TableDir)))
16481.1Schristos    {
16491.1Schristos        /* Ignore meaningless files */
16501.1Schristos
16511.10Schristos        if (!ACPI_COMPARE_NAMESEG (Filename, Signature))
16521.1Schristos        {
16531.1Schristos            continue;
16541.1Schristos        }
16551.1Schristos
16561.1Schristos        /* Extract table name and instance number */
16571.1Schristos
16581.1Schristos        Status = OslTableNameFromFile (Filename, TempName, &CurrentInstance);
16591.1Schristos
16601.1Schristos        /* Ignore meaningless files */
16611.1Schristos
16621.1Schristos        if (ACPI_FAILURE (Status) || CurrentInstance != Instance)
16631.1Schristos        {
16641.1Schristos            continue;
16651.1Schristos        }
16661.1Schristos
16671.1Schristos        /* Create the table pathname */
16681.1Schristos
16691.1Schristos        if (Instance != 0)
16701.1Schristos        {
16711.2Schristos            snprintf (TableFilename, sizeof(TableFilename), "%s/%4.4s%d",
16721.2Schristos		Pathname, TempName, Instance);
16731.1Schristos        }
16741.1Schristos        else
16751.1Schristos        {
16761.2Schristos            snprintf (TableFilename, sizeof(TableFilename), "%s/%4.4s",
16771.2Schristos		Pathname, TempName);
16781.1Schristos        }
16791.1Schristos        break;
16801.1Schristos    }
16811.1Schristos
16821.1Schristos    AcpiOsCloseDirectory (TableDir);
16831.1Schristos
16841.1Schristos    if (!Filename)
16851.1Schristos    {
16861.1Schristos        return (AE_LIMIT);
16871.1Schristos    }
16881.1Schristos
16891.1Schristos    /* There is no physical address saved for customized tables, use zero */
16901.1Schristos
16911.1Schristos    *Address = 0;
16921.12Schristos    Status = OslReadTableFromFile (TableFilename, 0, Table);
16931.1Schristos
16941.1Schristos    return (Status);
16951.1Schristos}
1696