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