10d02842fSSascha Wildner /****************************************************************************** 20d02842fSSascha Wildner * 30d02842fSSascha Wildner * Module Name: oslinuxtbl - Linux OSL for obtaining ACPI tables 40d02842fSSascha Wildner * 50d02842fSSascha Wildner *****************************************************************************/ 60d02842fSSascha Wildner 70d02842fSSascha Wildner /* 8fe7b5cb4SSascha Wildner * Copyright (C) 2000 - 2015, Intel Corp. 90d02842fSSascha Wildner * All rights reserved. 100d02842fSSascha Wildner * 110d02842fSSascha Wildner * Redistribution and use in source and binary forms, with or without 120d02842fSSascha Wildner * modification, are permitted provided that the following conditions 130d02842fSSascha Wildner * are met: 140d02842fSSascha Wildner * 1. Redistributions of source code must retain the above copyright 150d02842fSSascha Wildner * notice, this list of conditions, and the following disclaimer, 160d02842fSSascha Wildner * without modification. 170d02842fSSascha Wildner * 2. Redistributions in binary form must reproduce at minimum a disclaimer 180d02842fSSascha Wildner * substantially similar to the "NO WARRANTY" disclaimer below 190d02842fSSascha Wildner * ("Disclaimer") and any redistribution must be conditioned upon 200d02842fSSascha Wildner * including a substantially similar Disclaimer requirement for further 210d02842fSSascha Wildner * binary redistribution. 220d02842fSSascha Wildner * 3. Neither the names of the above-listed copyright holders nor the names 230d02842fSSascha Wildner * of any contributors may be used to endorse or promote products derived 240d02842fSSascha Wildner * from this software without specific prior written permission. 250d02842fSSascha Wildner * 260d02842fSSascha Wildner * Alternatively, this software may be distributed under the terms of the 270d02842fSSascha Wildner * GNU General Public License ("GPL") version 2 as published by the Free 280d02842fSSascha Wildner * Software Foundation. 290d02842fSSascha Wildner * 300d02842fSSascha Wildner * NO WARRANTY 310d02842fSSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 320d02842fSSascha Wildner * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 330d02842fSSascha Wildner * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 340d02842fSSascha Wildner * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 350d02842fSSascha Wildner * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 360d02842fSSascha Wildner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 370d02842fSSascha Wildner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 380d02842fSSascha Wildner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 390d02842fSSascha Wildner * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 400d02842fSSascha Wildner * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 410d02842fSSascha Wildner * POSSIBILITY OF SUCH DAMAGES. 420d02842fSSascha Wildner */ 430d02842fSSascha Wildner 440d02842fSSascha Wildner #include "acpidump.h" 450d02842fSSascha Wildner 460d02842fSSascha Wildner 470d02842fSSascha Wildner #define _COMPONENT ACPI_OS_SERVICES 480d02842fSSascha Wildner ACPI_MODULE_NAME ("oslinuxtbl") 490d02842fSSascha Wildner 500d02842fSSascha Wildner 510d02842fSSascha Wildner #ifndef PATH_MAX 520d02842fSSascha Wildner #define PATH_MAX 256 530d02842fSSascha Wildner #endif 540d02842fSSascha Wildner 550d02842fSSascha Wildner 560d02842fSSascha Wildner /* List of information about obtained ACPI tables */ 570d02842fSSascha Wildner 58d4972a9cSSascha Wildner typedef struct osl_table_info 590d02842fSSascha Wildner { 60d4972a9cSSascha Wildner struct osl_table_info *Next; 610d02842fSSascha Wildner UINT32 Instance; 620d02842fSSascha Wildner char Signature[ACPI_NAME_SIZE]; 630d02842fSSascha Wildner 640d02842fSSascha Wildner } OSL_TABLE_INFO; 650d02842fSSascha Wildner 660d02842fSSascha Wildner /* Local prototypes */ 670d02842fSSascha Wildner 680d02842fSSascha Wildner static ACPI_STATUS 690d02842fSSascha Wildner OslTableInitialize ( 700d02842fSSascha Wildner void); 710d02842fSSascha Wildner 720d02842fSSascha Wildner static ACPI_STATUS 730d02842fSSascha Wildner OslTableNameFromFile ( 740d02842fSSascha Wildner char *Filename, 750d02842fSSascha Wildner char *Signature, 760d02842fSSascha Wildner UINT32 *Instance); 770d02842fSSascha Wildner 780d02842fSSascha Wildner static ACPI_STATUS 790d02842fSSascha Wildner OslAddTableToList ( 800d02842fSSascha Wildner char *Signature, 810d02842fSSascha Wildner UINT32 Instance); 820d02842fSSascha Wildner 830d02842fSSascha Wildner static ACPI_STATUS 840d02842fSSascha Wildner OslReadTableFromFile ( 850d02842fSSascha Wildner char *Filename, 860d02842fSSascha Wildner ACPI_SIZE FileOffset, 870d02842fSSascha Wildner char *Signature, 880d02842fSSascha Wildner ACPI_TABLE_HEADER **Table); 890d02842fSSascha Wildner 900d02842fSSascha Wildner static ACPI_STATUS 910d02842fSSascha Wildner OslMapTable ( 920d02842fSSascha Wildner ACPI_SIZE Address, 930d02842fSSascha Wildner char *Signature, 940d02842fSSascha Wildner ACPI_TABLE_HEADER **Table); 950d02842fSSascha Wildner 960d02842fSSascha Wildner static void 970d02842fSSascha Wildner OslUnmapTable ( 980d02842fSSascha Wildner ACPI_TABLE_HEADER *Table); 990d02842fSSascha Wildner 1000d02842fSSascha Wildner static ACPI_PHYSICAL_ADDRESS 1015f39c7e7SSascha Wildner OslFindRsdpViaEfiByKeyword ( 1025f39c7e7SSascha Wildner FILE *File, 1035f39c7e7SSascha Wildner const char *Keyword); 1045f39c7e7SSascha Wildner 1055f39c7e7SSascha Wildner static ACPI_PHYSICAL_ADDRESS 1060d02842fSSascha Wildner OslFindRsdpViaEfi ( 1070d02842fSSascha Wildner void); 1080d02842fSSascha Wildner 1090d02842fSSascha Wildner static ACPI_STATUS 1100d02842fSSascha Wildner OslLoadRsdp ( 1110d02842fSSascha Wildner void); 1120d02842fSSascha Wildner 1130d02842fSSascha Wildner static ACPI_STATUS 1140d02842fSSascha Wildner OslListCustomizedTables ( 1150d02842fSSascha Wildner char *Directory); 1160d02842fSSascha Wildner 1170d02842fSSascha Wildner static ACPI_STATUS 1180d02842fSSascha Wildner OslGetCustomizedTable ( 1190d02842fSSascha Wildner char *Pathname, 1200d02842fSSascha Wildner char *Signature, 1210d02842fSSascha Wildner UINT32 Instance, 1220d02842fSSascha Wildner ACPI_TABLE_HEADER **Table, 1230d02842fSSascha Wildner ACPI_PHYSICAL_ADDRESS *Address); 1240d02842fSSascha Wildner 1250d02842fSSascha Wildner static ACPI_STATUS 1260d02842fSSascha Wildner OslListBiosTables ( 1270d02842fSSascha Wildner void); 1280d02842fSSascha Wildner 1290d02842fSSascha Wildner static ACPI_STATUS 1300d02842fSSascha Wildner OslGetBiosTable ( 1310d02842fSSascha Wildner char *Signature, 1320d02842fSSascha Wildner UINT32 Instance, 1330d02842fSSascha Wildner ACPI_TABLE_HEADER **Table, 1340d02842fSSascha Wildner ACPI_PHYSICAL_ADDRESS *Address); 1350d02842fSSascha Wildner 1360d02842fSSascha Wildner static ACPI_STATUS 1370d02842fSSascha Wildner OslGetLastStatus ( 1380d02842fSSascha Wildner ACPI_STATUS DefaultStatus); 1390d02842fSSascha Wildner 1400d02842fSSascha Wildner 1410d02842fSSascha Wildner /* File locations */ 1420d02842fSSascha Wildner 1430d02842fSSascha Wildner #define DYNAMIC_TABLE_DIR "/sys/firmware/acpi/tables/dynamic" 1440d02842fSSascha Wildner #define STATIC_TABLE_DIR "/sys/firmware/acpi/tables" 1450d02842fSSascha Wildner #define EFI_SYSTAB "/sys/firmware/efi/systab" 1460d02842fSSascha Wildner 1470d02842fSSascha Wildner /* Should we get dynamically loaded SSDTs from DYNAMIC_TABLE_DIR? */ 1480d02842fSSascha Wildner 1490d02842fSSascha Wildner UINT8 Gbl_DumpDynamicTables = TRUE; 1500d02842fSSascha Wildner 1510d02842fSSascha Wildner /* Initialization flags */ 1520d02842fSSascha Wildner 1530d02842fSSascha Wildner UINT8 Gbl_TableListInitialized = FALSE; 1540d02842fSSascha Wildner 1550d02842fSSascha Wildner /* Local copies of main ACPI tables */ 1560d02842fSSascha Wildner 1570d02842fSSascha Wildner ACPI_TABLE_RSDP Gbl_Rsdp; 1580d02842fSSascha Wildner ACPI_TABLE_FADT *Gbl_Fadt = NULL; 1590d02842fSSascha Wildner ACPI_TABLE_RSDT *Gbl_Rsdt = NULL; 1600d02842fSSascha Wildner ACPI_TABLE_XSDT *Gbl_Xsdt = NULL; 1610d02842fSSascha Wildner 1620d02842fSSascha Wildner /* Table addresses */ 1630d02842fSSascha Wildner 1640d02842fSSascha Wildner ACPI_PHYSICAL_ADDRESS Gbl_FadtAddress = 0; 1650d02842fSSascha Wildner ACPI_PHYSICAL_ADDRESS Gbl_RsdpAddress = 0; 1660d02842fSSascha Wildner 1670d02842fSSascha Wildner /* Revision of RSD PTR */ 1680d02842fSSascha Wildner 1690d02842fSSascha Wildner UINT8 Gbl_Revision = 0; 1700d02842fSSascha Wildner 1710d02842fSSascha Wildner OSL_TABLE_INFO *Gbl_TableListHead = NULL; 1720d02842fSSascha Wildner UINT32 Gbl_TableCount = 0; 1730d02842fSSascha Wildner 1740d02842fSSascha Wildner 1750d02842fSSascha Wildner /****************************************************************************** 1760d02842fSSascha Wildner * 1770d02842fSSascha Wildner * FUNCTION: OslGetLastStatus 1780d02842fSSascha Wildner * 1790d02842fSSascha Wildner * PARAMETERS: DefaultStatus - Default error status to return 1800d02842fSSascha Wildner * 1810d02842fSSascha Wildner * RETURN: Status; Converted from errno. 1820d02842fSSascha Wildner * 1830d02842fSSascha Wildner * DESCRIPTION: Get last errno and conver it to ACPI_STATUS. 1840d02842fSSascha Wildner * 1850d02842fSSascha Wildner *****************************************************************************/ 1860d02842fSSascha Wildner 1870d02842fSSascha Wildner static ACPI_STATUS 1880d02842fSSascha Wildner OslGetLastStatus ( 1890d02842fSSascha Wildner ACPI_STATUS DefaultStatus) 1900d02842fSSascha Wildner { 1910d02842fSSascha Wildner 1920d02842fSSascha Wildner switch (errno) 1930d02842fSSascha Wildner { 1940d02842fSSascha Wildner case EACCES: 1950d02842fSSascha Wildner case EPERM: 1960d02842fSSascha Wildner 1970d02842fSSascha Wildner return (AE_ACCESS); 1980d02842fSSascha Wildner 1990d02842fSSascha Wildner case ENOENT: 2000d02842fSSascha Wildner 2010d02842fSSascha Wildner return (AE_NOT_FOUND); 2020d02842fSSascha Wildner 2030d02842fSSascha Wildner case ENOMEM: 2040d02842fSSascha Wildner 2050d02842fSSascha Wildner return (AE_NO_MEMORY); 2060d02842fSSascha Wildner 2070d02842fSSascha Wildner default: 2080d02842fSSascha Wildner 2090d02842fSSascha Wildner return (DefaultStatus); 2100d02842fSSascha Wildner } 2110d02842fSSascha Wildner } 2120d02842fSSascha Wildner 2130d02842fSSascha Wildner 2140d02842fSSascha Wildner /****************************************************************************** 2150d02842fSSascha Wildner * 2160d02842fSSascha Wildner * FUNCTION: AcpiOsGetTableByAddress 2170d02842fSSascha Wildner * 2180d02842fSSascha Wildner * PARAMETERS: Address - Physical address of the ACPI table 2190d02842fSSascha Wildner * Table - Where a pointer to the table is returned 2200d02842fSSascha Wildner * 2210d02842fSSascha Wildner * RETURN: Status; Table buffer is returned if AE_OK. 2220d02842fSSascha Wildner * AE_NOT_FOUND: A valid table was not found at the address 2230d02842fSSascha Wildner * 2240d02842fSSascha Wildner * DESCRIPTION: Get an ACPI table via a physical memory address. 2250d02842fSSascha Wildner * 2260d02842fSSascha Wildner *****************************************************************************/ 2270d02842fSSascha Wildner 2280d02842fSSascha Wildner ACPI_STATUS 2290d02842fSSascha Wildner AcpiOsGetTableByAddress ( 2300d02842fSSascha Wildner ACPI_PHYSICAL_ADDRESS Address, 2310d02842fSSascha Wildner ACPI_TABLE_HEADER **Table) 2320d02842fSSascha Wildner { 2330d02842fSSascha Wildner UINT32 TableLength; 2340d02842fSSascha Wildner ACPI_TABLE_HEADER *MappedTable; 2350d02842fSSascha Wildner ACPI_TABLE_HEADER *LocalTable = NULL; 2360d02842fSSascha Wildner ACPI_STATUS Status = AE_OK; 2370d02842fSSascha Wildner 2380d02842fSSascha Wildner 2390d02842fSSascha Wildner /* Get main ACPI tables from memory on first invocation of this function */ 2400d02842fSSascha Wildner 2410d02842fSSascha Wildner Status = OslTableInitialize (); 2420d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 2430d02842fSSascha Wildner { 2440d02842fSSascha Wildner return (Status); 2450d02842fSSascha Wildner } 2460d02842fSSascha Wildner 2470d02842fSSascha Wildner /* Map the table and validate it */ 2480d02842fSSascha Wildner 2490d02842fSSascha Wildner Status = OslMapTable (Address, NULL, &MappedTable); 2500d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 2510d02842fSSascha Wildner { 2520d02842fSSascha Wildner return (Status); 2530d02842fSSascha Wildner } 2540d02842fSSascha Wildner 2550d02842fSSascha Wildner /* Copy table to local buffer and return it */ 2560d02842fSSascha Wildner 2570d02842fSSascha Wildner TableLength = ApGetTableLength (MappedTable); 2580d02842fSSascha Wildner if (TableLength == 0) 2590d02842fSSascha Wildner { 2600d02842fSSascha Wildner Status = AE_BAD_HEADER; 261d4972a9cSSascha Wildner goto Exit; 2620d02842fSSascha Wildner } 2630d02842fSSascha Wildner 2640d02842fSSascha Wildner LocalTable = calloc (1, TableLength); 2650d02842fSSascha Wildner if (!LocalTable) 2660d02842fSSascha Wildner { 2670d02842fSSascha Wildner Status = AE_NO_MEMORY; 268d4972a9cSSascha Wildner goto Exit; 2690d02842fSSascha Wildner } 2700d02842fSSascha Wildner 271*25ca8c79SSascha Wildner memcpy (LocalTable, MappedTable, TableLength); 2720d02842fSSascha Wildner 273d4972a9cSSascha Wildner Exit: 2740d02842fSSascha Wildner OslUnmapTable (MappedTable); 2750d02842fSSascha Wildner *Table = LocalTable; 276d4972a9cSSascha Wildner return (Status); 2770d02842fSSascha Wildner } 2780d02842fSSascha Wildner 2790d02842fSSascha Wildner 2800d02842fSSascha Wildner /****************************************************************************** 2810d02842fSSascha Wildner * 2820d02842fSSascha Wildner * FUNCTION: AcpiOsGetTableByName 2830d02842fSSascha Wildner * 2840d02842fSSascha Wildner * PARAMETERS: Signature - ACPI Signature for desired table. Must be 2850d02842fSSascha Wildner * a null terminated 4-character string. 2860d02842fSSascha Wildner * Instance - Multiple table support for SSDT/UEFI (0...n) 2870d02842fSSascha Wildner * Must be 0 for other tables. 2880d02842fSSascha Wildner * Table - Where a pointer to the table is returned 2890d02842fSSascha Wildner * Address - Where the table physical address is returned 2900d02842fSSascha Wildner * 2910d02842fSSascha Wildner * RETURN: Status; Table buffer and physical address returned if AE_OK. 2920d02842fSSascha Wildner * AE_LIMIT: Instance is beyond valid limit 2930d02842fSSascha Wildner * AE_NOT_FOUND: A table with the signature was not found 2940d02842fSSascha Wildner * 2950d02842fSSascha Wildner * NOTE: Assumes the input signature is uppercase. 2960d02842fSSascha Wildner * 2970d02842fSSascha Wildner *****************************************************************************/ 2980d02842fSSascha Wildner 2990d02842fSSascha Wildner ACPI_STATUS 3000d02842fSSascha Wildner AcpiOsGetTableByName ( 3010d02842fSSascha Wildner char *Signature, 3020d02842fSSascha Wildner UINT32 Instance, 3030d02842fSSascha Wildner ACPI_TABLE_HEADER **Table, 3040d02842fSSascha Wildner ACPI_PHYSICAL_ADDRESS *Address) 3050d02842fSSascha Wildner { 3060d02842fSSascha Wildner ACPI_STATUS Status; 3070d02842fSSascha Wildner 3080d02842fSSascha Wildner 3090d02842fSSascha Wildner /* Get main ACPI tables from memory on first invocation of this function */ 3100d02842fSSascha Wildner 3110d02842fSSascha Wildner Status = OslTableInitialize (); 3120d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 3130d02842fSSascha Wildner { 3140d02842fSSascha Wildner return (Status); 3150d02842fSSascha Wildner } 3160d02842fSSascha Wildner 3170d02842fSSascha Wildner /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */ 3180d02842fSSascha Wildner 3190d02842fSSascha Wildner if (!Gbl_DumpCustomizedTables) 3200d02842fSSascha Wildner { 3210d02842fSSascha Wildner /* Attempt to get the table from the memory */ 3220d02842fSSascha Wildner 3230d02842fSSascha Wildner Status = OslGetBiosTable (Signature, Instance, Table, Address); 3240d02842fSSascha Wildner } 3250d02842fSSascha Wildner else 3260d02842fSSascha Wildner { 3270d02842fSSascha Wildner /* Attempt to get the table from the static directory */ 3280d02842fSSascha Wildner 3290d02842fSSascha Wildner Status = OslGetCustomizedTable (STATIC_TABLE_DIR, Signature, 3300d02842fSSascha Wildner Instance, Table, Address); 3310d02842fSSascha Wildner } 3320d02842fSSascha Wildner 3330d02842fSSascha Wildner if (ACPI_FAILURE (Status) && Status == AE_LIMIT) 3340d02842fSSascha Wildner { 3350d02842fSSascha Wildner if (Gbl_DumpDynamicTables) 3360d02842fSSascha Wildner { 3370d02842fSSascha Wildner /* Attempt to get a dynamic table */ 3380d02842fSSascha Wildner 3390d02842fSSascha Wildner Status = OslGetCustomizedTable (DYNAMIC_TABLE_DIR, Signature, 3400d02842fSSascha Wildner Instance, Table, Address); 3410d02842fSSascha Wildner } 3420d02842fSSascha Wildner } 3430d02842fSSascha Wildner 3440d02842fSSascha Wildner return (Status); 3450d02842fSSascha Wildner } 3460d02842fSSascha Wildner 3470d02842fSSascha Wildner 3480d02842fSSascha Wildner /****************************************************************************** 3490d02842fSSascha Wildner * 3500d02842fSSascha Wildner * FUNCTION: OslAddTableToList 3510d02842fSSascha Wildner * 3520d02842fSSascha Wildner * PARAMETERS: Signature - Table signature 3530d02842fSSascha Wildner * Instance - Table instance 3540d02842fSSascha Wildner * 3550d02842fSSascha Wildner * RETURN: Status; Successfully added if AE_OK. 3560d02842fSSascha Wildner * AE_NO_MEMORY: Memory allocation error 3570d02842fSSascha Wildner * 3580d02842fSSascha Wildner * DESCRIPTION: Insert a table structure into OSL table list. 3590d02842fSSascha Wildner * 3600d02842fSSascha Wildner *****************************************************************************/ 3610d02842fSSascha Wildner 3620d02842fSSascha Wildner static ACPI_STATUS 3630d02842fSSascha Wildner OslAddTableToList ( 3640d02842fSSascha Wildner char *Signature, 3650d02842fSSascha Wildner UINT32 Instance) 3660d02842fSSascha Wildner { 3670d02842fSSascha Wildner OSL_TABLE_INFO *NewInfo; 3680d02842fSSascha Wildner OSL_TABLE_INFO *Next; 3690d02842fSSascha Wildner UINT32 NextInstance = 0; 3700d02842fSSascha Wildner BOOLEAN Found = FALSE; 3710d02842fSSascha Wildner 3720d02842fSSascha Wildner 3730d02842fSSascha Wildner NewInfo = calloc (1, sizeof (OSL_TABLE_INFO)); 3740d02842fSSascha Wildner if (!NewInfo) 3750d02842fSSascha Wildner { 3760d02842fSSascha Wildner return (AE_NO_MEMORY); 3770d02842fSSascha Wildner } 3780d02842fSSascha Wildner 3790d02842fSSascha Wildner ACPI_MOVE_NAME (NewInfo->Signature, Signature); 3800d02842fSSascha Wildner 3810d02842fSSascha Wildner if (!Gbl_TableListHead) 3820d02842fSSascha Wildner { 3830d02842fSSascha Wildner Gbl_TableListHead = NewInfo; 3840d02842fSSascha Wildner } 3850d02842fSSascha Wildner else 3860d02842fSSascha Wildner { 3870d02842fSSascha Wildner Next = Gbl_TableListHead; 3880d02842fSSascha Wildner while (1) 3890d02842fSSascha Wildner { 3900d02842fSSascha Wildner if (ACPI_COMPARE_NAME (Next->Signature, Signature)) 3910d02842fSSascha Wildner { 3920d02842fSSascha Wildner if (Next->Instance == Instance) 3930d02842fSSascha Wildner { 3940d02842fSSascha Wildner Found = TRUE; 3950d02842fSSascha Wildner } 3960d02842fSSascha Wildner if (Next->Instance >= NextInstance) 3970d02842fSSascha Wildner { 3980d02842fSSascha Wildner NextInstance = Next->Instance + 1; 3990d02842fSSascha Wildner } 4000d02842fSSascha Wildner } 4010d02842fSSascha Wildner 4020d02842fSSascha Wildner if (!Next->Next) 4030d02842fSSascha Wildner { 4040d02842fSSascha Wildner break; 4050d02842fSSascha Wildner } 4060d02842fSSascha Wildner Next = Next->Next; 4070d02842fSSascha Wildner } 4080d02842fSSascha Wildner Next->Next = NewInfo; 4090d02842fSSascha Wildner } 4100d02842fSSascha Wildner 4110d02842fSSascha Wildner if (Found) 4120d02842fSSascha Wildner { 4130d02842fSSascha Wildner if (Instance) 4140d02842fSSascha Wildner { 4150d02842fSSascha Wildner fprintf (stderr, 4160d02842fSSascha Wildner "%4.4s: Warning unmatched table instance %d, expected %d\n", 4170d02842fSSascha Wildner Signature, Instance, NextInstance); 4180d02842fSSascha Wildner } 4190d02842fSSascha Wildner Instance = NextInstance; 4200d02842fSSascha Wildner } 4210d02842fSSascha Wildner 4220d02842fSSascha Wildner NewInfo->Instance = Instance; 4230d02842fSSascha Wildner Gbl_TableCount++; 4240d02842fSSascha Wildner 4250d02842fSSascha Wildner return (AE_OK); 4260d02842fSSascha Wildner } 4270d02842fSSascha Wildner 4280d02842fSSascha Wildner 4290d02842fSSascha Wildner /****************************************************************************** 4300d02842fSSascha Wildner * 4310d02842fSSascha Wildner * FUNCTION: AcpiOsGetTableByIndex 4320d02842fSSascha Wildner * 4330d02842fSSascha Wildner * PARAMETERS: Index - Which table to get 4340d02842fSSascha Wildner * Table - Where a pointer to the table is returned 4350d02842fSSascha Wildner * Instance - Where a pointer to the table instance no. is 4360d02842fSSascha Wildner * returned 4370d02842fSSascha Wildner * Address - Where the table physical address is returned 4380d02842fSSascha Wildner * 4390d02842fSSascha Wildner * RETURN: Status; Table buffer and physical address returned if AE_OK. 4400d02842fSSascha Wildner * AE_LIMIT: Index is beyond valid limit 4410d02842fSSascha Wildner * 4420d02842fSSascha Wildner * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns 4430d02842fSSascha Wildner * AE_LIMIT when an invalid index is reached. Index is not 4440d02842fSSascha Wildner * necessarily an index into the RSDT/XSDT. 4450d02842fSSascha Wildner * 4460d02842fSSascha Wildner *****************************************************************************/ 4470d02842fSSascha Wildner 4480d02842fSSascha Wildner ACPI_STATUS 4490d02842fSSascha Wildner AcpiOsGetTableByIndex ( 4500d02842fSSascha Wildner UINT32 Index, 4510d02842fSSascha Wildner ACPI_TABLE_HEADER **Table, 4520d02842fSSascha Wildner UINT32 *Instance, 4530d02842fSSascha Wildner ACPI_PHYSICAL_ADDRESS *Address) 4540d02842fSSascha Wildner { 4550d02842fSSascha Wildner OSL_TABLE_INFO *Info; 4560d02842fSSascha Wildner ACPI_STATUS Status; 4570d02842fSSascha Wildner UINT32 i; 4580d02842fSSascha Wildner 4590d02842fSSascha Wildner 4600d02842fSSascha Wildner /* Get main ACPI tables from memory on first invocation of this function */ 4610d02842fSSascha Wildner 4620d02842fSSascha Wildner Status = OslTableInitialize (); 4630d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 4640d02842fSSascha Wildner { 4650d02842fSSascha Wildner return (Status); 4660d02842fSSascha Wildner } 4670d02842fSSascha Wildner 4680d02842fSSascha Wildner /* Validate Index */ 4690d02842fSSascha Wildner 4700d02842fSSascha Wildner if (Index >= Gbl_TableCount) 4710d02842fSSascha Wildner { 4720d02842fSSascha Wildner return (AE_LIMIT); 4730d02842fSSascha Wildner } 4740d02842fSSascha Wildner 4750d02842fSSascha Wildner /* Point to the table list entry specified by the Index argument */ 4760d02842fSSascha Wildner 4770d02842fSSascha Wildner Info = Gbl_TableListHead; 4780d02842fSSascha Wildner for (i = 0; i < Index; i++) 4790d02842fSSascha Wildner { 4800d02842fSSascha Wildner Info = Info->Next; 4810d02842fSSascha Wildner } 4820d02842fSSascha Wildner 4830d02842fSSascha Wildner /* Now we can just get the table via the signature */ 4840d02842fSSascha Wildner 4850d02842fSSascha Wildner Status = AcpiOsGetTableByName (Info->Signature, Info->Instance, 4860d02842fSSascha Wildner Table, Address); 4870d02842fSSascha Wildner 4880d02842fSSascha Wildner if (ACPI_SUCCESS (Status)) 4890d02842fSSascha Wildner { 4900d02842fSSascha Wildner *Instance = Info->Instance; 4910d02842fSSascha Wildner } 4920d02842fSSascha Wildner return (Status); 4930d02842fSSascha Wildner } 4940d02842fSSascha Wildner 4950d02842fSSascha Wildner 4960d02842fSSascha Wildner /****************************************************************************** 4970d02842fSSascha Wildner * 4985f39c7e7SSascha Wildner * FUNCTION: OslFindRsdpViaEfiByKeyword 4995f39c7e7SSascha Wildner * 5005f39c7e7SSascha Wildner * PARAMETERS: Keyword - Character string indicating ACPI GUID version 5015f39c7e7SSascha Wildner * in the EFI table 5025f39c7e7SSascha Wildner * 5035f39c7e7SSascha Wildner * RETURN: RSDP address if found 5045f39c7e7SSascha Wildner * 5055f39c7e7SSascha Wildner * DESCRIPTION: Find RSDP address via EFI using keyword indicating the ACPI 5065f39c7e7SSascha Wildner * GUID version. 5075f39c7e7SSascha Wildner * 5085f39c7e7SSascha Wildner *****************************************************************************/ 5095f39c7e7SSascha Wildner 5105f39c7e7SSascha Wildner static ACPI_PHYSICAL_ADDRESS 5115f39c7e7SSascha Wildner OslFindRsdpViaEfiByKeyword ( 5125f39c7e7SSascha Wildner FILE *File, 5135f39c7e7SSascha Wildner const char *Keyword) 5145f39c7e7SSascha Wildner { 5155f39c7e7SSascha Wildner char Buffer[80]; 5165f39c7e7SSascha Wildner unsigned long long Address = 0; 5175f39c7e7SSascha Wildner char Format[32]; 5185f39c7e7SSascha Wildner 5195f39c7e7SSascha Wildner 5205f39c7e7SSascha Wildner snprintf (Format, 32, "%s=%s", Keyword, "%llx"); 5215f39c7e7SSascha Wildner fseek (File, 0, SEEK_SET); 5225f39c7e7SSascha Wildner while (fgets (Buffer, 80, File)) 5235f39c7e7SSascha Wildner { 5245f39c7e7SSascha Wildner if (sscanf (Buffer, Format, &Address) == 1) 5255f39c7e7SSascha Wildner { 5265f39c7e7SSascha Wildner break; 5275f39c7e7SSascha Wildner } 5285f39c7e7SSascha Wildner } 5295f39c7e7SSascha Wildner 5305f39c7e7SSascha Wildner return ((ACPI_PHYSICAL_ADDRESS) (Address)); 5315f39c7e7SSascha Wildner } 5325f39c7e7SSascha Wildner 5335f39c7e7SSascha Wildner 5345f39c7e7SSascha Wildner /****************************************************************************** 5355f39c7e7SSascha Wildner * 5360d02842fSSascha Wildner * FUNCTION: OslFindRsdpViaEfi 5370d02842fSSascha Wildner * 5380d02842fSSascha Wildner * PARAMETERS: None 5390d02842fSSascha Wildner * 5400d02842fSSascha Wildner * RETURN: RSDP address if found 5410d02842fSSascha Wildner * 5420d02842fSSascha Wildner * DESCRIPTION: Find RSDP address via EFI. 5430d02842fSSascha Wildner * 5440d02842fSSascha Wildner *****************************************************************************/ 5450d02842fSSascha Wildner 5460d02842fSSascha Wildner static ACPI_PHYSICAL_ADDRESS 5470d02842fSSascha Wildner OslFindRsdpViaEfi ( 5480d02842fSSascha Wildner void) 5490d02842fSSascha Wildner { 5500d02842fSSascha Wildner FILE *File; 5515f39c7e7SSascha Wildner ACPI_PHYSICAL_ADDRESS Address = 0; 5520d02842fSSascha Wildner 5530d02842fSSascha Wildner 5540d02842fSSascha Wildner File = fopen (EFI_SYSTAB, "r"); 5550d02842fSSascha Wildner if (File) 5560d02842fSSascha Wildner { 5575f39c7e7SSascha Wildner Address = OslFindRsdpViaEfiByKeyword (File, "ACPI20"); 5585f39c7e7SSascha Wildner if (!Address) 5590d02842fSSascha Wildner { 5605f39c7e7SSascha Wildner Address = OslFindRsdpViaEfiByKeyword (File, "ACPI"); 5610d02842fSSascha Wildner } 5620d02842fSSascha Wildner fclose (File); 5630d02842fSSascha Wildner } 5640d02842fSSascha Wildner 5655f39c7e7SSascha Wildner return (Address); 5660d02842fSSascha Wildner } 5670d02842fSSascha Wildner 5680d02842fSSascha Wildner 5690d02842fSSascha Wildner /****************************************************************************** 5700d02842fSSascha Wildner * 5710d02842fSSascha Wildner * FUNCTION: OslLoadRsdp 5720d02842fSSascha Wildner * 5730d02842fSSascha Wildner * PARAMETERS: None 5740d02842fSSascha Wildner * 5750d02842fSSascha Wildner * RETURN: Status 5760d02842fSSascha Wildner * 5770d02842fSSascha Wildner * DESCRIPTION: Scan and load RSDP. 5780d02842fSSascha Wildner * 5790d02842fSSascha Wildner *****************************************************************************/ 5800d02842fSSascha Wildner 5810d02842fSSascha Wildner static ACPI_STATUS 5820d02842fSSascha Wildner OslLoadRsdp ( 5830d02842fSSascha Wildner void) 5840d02842fSSascha Wildner { 5850d02842fSSascha Wildner ACPI_TABLE_HEADER *MappedTable; 5860d02842fSSascha Wildner UINT8 *RsdpAddress; 5870d02842fSSascha Wildner ACPI_PHYSICAL_ADDRESS RsdpBase; 5880d02842fSSascha Wildner ACPI_SIZE RsdpSize; 5890d02842fSSascha Wildner 5900d02842fSSascha Wildner 5910d02842fSSascha Wildner /* Get RSDP from memory */ 5920d02842fSSascha Wildner 5930d02842fSSascha Wildner RsdpSize = sizeof (ACPI_TABLE_RSDP); 5940d02842fSSascha Wildner if (Gbl_RsdpBase) 5950d02842fSSascha Wildner { 5960d02842fSSascha Wildner RsdpBase = Gbl_RsdpBase; 5970d02842fSSascha Wildner } 5980d02842fSSascha Wildner else 5990d02842fSSascha Wildner { 6000d02842fSSascha Wildner RsdpBase = OslFindRsdpViaEfi (); 6010d02842fSSascha Wildner } 6020d02842fSSascha Wildner 6030d02842fSSascha Wildner if (!RsdpBase) 6040d02842fSSascha Wildner { 6050d02842fSSascha Wildner RsdpBase = ACPI_HI_RSDP_WINDOW_BASE; 6060d02842fSSascha Wildner RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE; 6070d02842fSSascha Wildner } 6080d02842fSSascha Wildner 6090d02842fSSascha Wildner RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize); 6100d02842fSSascha Wildner if (!RsdpAddress) 6110d02842fSSascha Wildner { 6120d02842fSSascha Wildner return (OslGetLastStatus (AE_BAD_ADDRESS)); 6130d02842fSSascha Wildner } 6140d02842fSSascha Wildner 6150d02842fSSascha Wildner /* Search low memory for the RSDP */ 6160d02842fSSascha Wildner 6170d02842fSSascha Wildner MappedTable = ACPI_CAST_PTR (ACPI_TABLE_HEADER, 6180d02842fSSascha Wildner AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize)); 6190d02842fSSascha Wildner if (!MappedTable) 6200d02842fSSascha Wildner { 6210d02842fSSascha Wildner AcpiOsUnmapMemory (RsdpAddress, RsdpSize); 6220d02842fSSascha Wildner return (AE_NOT_FOUND); 6230d02842fSSascha Wildner } 6240d02842fSSascha Wildner 6250d02842fSSascha Wildner Gbl_RsdpAddress = RsdpBase + (ACPI_CAST8 (MappedTable) - RsdpAddress); 6260d02842fSSascha Wildner 627*25ca8c79SSascha Wildner memcpy (&Gbl_Rsdp, MappedTable, sizeof (ACPI_TABLE_RSDP)); 6280d02842fSSascha Wildner AcpiOsUnmapMemory (RsdpAddress, RsdpSize); 6290d02842fSSascha Wildner 6300d02842fSSascha Wildner return (AE_OK); 6310d02842fSSascha Wildner } 6320d02842fSSascha Wildner 6330d02842fSSascha Wildner 6340d02842fSSascha Wildner /****************************************************************************** 6350d02842fSSascha Wildner * 6369e1c0880SSascha Wildner * FUNCTION: OslCanUseXsdt 6379e1c0880SSascha Wildner * 6389e1c0880SSascha Wildner * PARAMETERS: None 6399e1c0880SSascha Wildner * 6409e1c0880SSascha Wildner * RETURN: TRUE if XSDT is allowed to be used. 6419e1c0880SSascha Wildner * 6429e1c0880SSascha Wildner * DESCRIPTION: This function collects logic that can be used to determine if 6439e1c0880SSascha Wildner * XSDT should be used instead of RSDT. 6449e1c0880SSascha Wildner * 6459e1c0880SSascha Wildner *****************************************************************************/ 6469e1c0880SSascha Wildner 6479e1c0880SSascha Wildner static BOOLEAN 6489e1c0880SSascha Wildner OslCanUseXsdt ( 6499e1c0880SSascha Wildner void) 6509e1c0880SSascha Wildner { 6519e1c0880SSascha Wildner if (Gbl_Revision && !AcpiGbl_DoNotUseXsdt) 6529e1c0880SSascha Wildner { 6539e1c0880SSascha Wildner return (TRUE); 6549e1c0880SSascha Wildner } 6559e1c0880SSascha Wildner else 6569e1c0880SSascha Wildner { 6579e1c0880SSascha Wildner return (FALSE); 6589e1c0880SSascha Wildner } 6599e1c0880SSascha Wildner } 6609e1c0880SSascha Wildner 6619e1c0880SSascha Wildner 6629e1c0880SSascha Wildner /****************************************************************************** 6639e1c0880SSascha Wildner * 6640d02842fSSascha Wildner * FUNCTION: OslTableInitialize 6650d02842fSSascha Wildner * 6660d02842fSSascha Wildner * PARAMETERS: None 6670d02842fSSascha Wildner * 6680d02842fSSascha Wildner * RETURN: Status 6690d02842fSSascha Wildner * 6700d02842fSSascha Wildner * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to 6710d02842fSSascha Wildner * local variables. Main ACPI tables include RSDT, FADT, RSDT, 6720d02842fSSascha Wildner * and/or XSDT. 6730d02842fSSascha Wildner * 6740d02842fSSascha Wildner *****************************************************************************/ 6750d02842fSSascha Wildner 6760d02842fSSascha Wildner static ACPI_STATUS 6770d02842fSSascha Wildner OslTableInitialize ( 6780d02842fSSascha Wildner void) 6790d02842fSSascha Wildner { 6800d02842fSSascha Wildner ACPI_STATUS Status; 6810d02842fSSascha Wildner ACPI_PHYSICAL_ADDRESS Address; 6820d02842fSSascha Wildner 6830d02842fSSascha Wildner 6840d02842fSSascha Wildner if (Gbl_TableListInitialized) 6850d02842fSSascha Wildner { 6860d02842fSSascha Wildner return (AE_OK); 6870d02842fSSascha Wildner } 6880d02842fSSascha Wildner 689*25ca8c79SSascha Wildner if (!Gbl_DumpCustomizedTables) 690*25ca8c79SSascha Wildner { 6910d02842fSSascha Wildner /* Get RSDP from memory */ 6920d02842fSSascha Wildner 6930d02842fSSascha Wildner Status = OslLoadRsdp (); 6940d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 6950d02842fSSascha Wildner { 6960d02842fSSascha Wildner return (Status); 6970d02842fSSascha Wildner } 6980d02842fSSascha Wildner 6990d02842fSSascha Wildner /* Get XSDT from memory */ 7000d02842fSSascha Wildner 7019e1c0880SSascha Wildner if (Gbl_Rsdp.Revision && !Gbl_DoNotDumpXsdt) 7020d02842fSSascha Wildner { 7030d02842fSSascha Wildner if (Gbl_Xsdt) 7040d02842fSSascha Wildner { 7050d02842fSSascha Wildner free (Gbl_Xsdt); 7060d02842fSSascha Wildner Gbl_Xsdt = NULL; 7070d02842fSSascha Wildner } 7080d02842fSSascha Wildner 7090d02842fSSascha Wildner Gbl_Revision = 2; 7100d02842fSSascha Wildner Status = OslGetBiosTable (ACPI_SIG_XSDT, 0, 7110d02842fSSascha Wildner ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Xsdt), &Address); 7120d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 7130d02842fSSascha Wildner { 7140d02842fSSascha Wildner return (Status); 7150d02842fSSascha Wildner } 7160d02842fSSascha Wildner } 7170d02842fSSascha Wildner 7180d02842fSSascha Wildner /* Get RSDT from memory */ 7190d02842fSSascha Wildner 7200d02842fSSascha Wildner if (Gbl_Rsdp.RsdtPhysicalAddress) 7210d02842fSSascha Wildner { 7220d02842fSSascha Wildner if (Gbl_Rsdt) 7230d02842fSSascha Wildner { 7240d02842fSSascha Wildner free (Gbl_Rsdt); 7250d02842fSSascha Wildner Gbl_Rsdt = NULL; 7260d02842fSSascha Wildner } 7270d02842fSSascha Wildner 7280d02842fSSascha Wildner Status = OslGetBiosTable (ACPI_SIG_RSDT, 0, 7290d02842fSSascha Wildner ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Rsdt), &Address); 7300d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 7310d02842fSSascha Wildner { 7320d02842fSSascha Wildner return (Status); 7330d02842fSSascha Wildner } 7340d02842fSSascha Wildner } 7350d02842fSSascha Wildner 7360d02842fSSascha Wildner /* Get FADT from memory */ 7370d02842fSSascha Wildner 7380d02842fSSascha Wildner if (Gbl_Fadt) 7390d02842fSSascha Wildner { 7400d02842fSSascha Wildner free (Gbl_Fadt); 7410d02842fSSascha Wildner Gbl_Fadt = NULL; 7420d02842fSSascha Wildner } 7430d02842fSSascha Wildner 7440d02842fSSascha Wildner Status = OslGetBiosTable (ACPI_SIG_FADT, 0, 7450d02842fSSascha Wildner ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Fadt), &Gbl_FadtAddress); 7460d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 7470d02842fSSascha Wildner { 7480d02842fSSascha Wildner return (Status); 7490d02842fSSascha Wildner } 7500d02842fSSascha Wildner 7510d02842fSSascha Wildner /* Add mandatory tables to global table list first */ 7520d02842fSSascha Wildner 75320294b7eSSascha Wildner Status = OslAddTableToList (ACPI_RSDP_NAME, 0); 7540d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 7550d02842fSSascha Wildner { 7560d02842fSSascha Wildner return (Status); 7570d02842fSSascha Wildner } 7580d02842fSSascha Wildner 7590d02842fSSascha Wildner Status = OslAddTableToList (ACPI_SIG_RSDT, 0); 7600d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 7610d02842fSSascha Wildner { 7620d02842fSSascha Wildner return (Status); 7630d02842fSSascha Wildner } 7640d02842fSSascha Wildner 7650d02842fSSascha Wildner if (Gbl_Revision == 2) 7660d02842fSSascha Wildner { 7670d02842fSSascha Wildner Status = OslAddTableToList (ACPI_SIG_XSDT, 0); 7680d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 7690d02842fSSascha Wildner { 7700d02842fSSascha Wildner return (Status); 7710d02842fSSascha Wildner } 7720d02842fSSascha Wildner } 7730d02842fSSascha Wildner 7740d02842fSSascha Wildner Status = OslAddTableToList (ACPI_SIG_DSDT, 0); 7750d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 7760d02842fSSascha Wildner { 7770d02842fSSascha Wildner return (Status); 7780d02842fSSascha Wildner } 7790d02842fSSascha Wildner 7800d02842fSSascha Wildner Status = OslAddTableToList (ACPI_SIG_FACS, 0); 7810d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 7820d02842fSSascha Wildner { 7830d02842fSSascha Wildner return (Status); 7840d02842fSSascha Wildner } 7850d02842fSSascha Wildner 7860d02842fSSascha Wildner /* Add all tables found in the memory */ 7870d02842fSSascha Wildner 7880d02842fSSascha Wildner Status = OslListBiosTables (); 7890d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 7900d02842fSSascha Wildner { 7910d02842fSSascha Wildner return (Status); 7920d02842fSSascha Wildner } 7930d02842fSSascha Wildner } 7940d02842fSSascha Wildner else 7950d02842fSSascha Wildner { 7960d02842fSSascha Wildner /* Add all tables found in the static directory */ 7970d02842fSSascha Wildner 7980d02842fSSascha Wildner Status = OslListCustomizedTables (STATIC_TABLE_DIR); 7990d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 8000d02842fSSascha Wildner { 8010d02842fSSascha Wildner return (Status); 8020d02842fSSascha Wildner } 8030d02842fSSascha Wildner } 8040d02842fSSascha Wildner 8050d02842fSSascha Wildner if (Gbl_DumpDynamicTables) 8060d02842fSSascha Wildner { 8070d02842fSSascha Wildner /* Add all dynamically loaded tables in the dynamic directory */ 8080d02842fSSascha Wildner 8090d02842fSSascha Wildner Status = OslListCustomizedTables (DYNAMIC_TABLE_DIR); 8100d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 8110d02842fSSascha Wildner { 8120d02842fSSascha Wildner return (Status); 8130d02842fSSascha Wildner } 8140d02842fSSascha Wildner } 8150d02842fSSascha Wildner 8160d02842fSSascha Wildner Gbl_TableListInitialized = TRUE; 8170d02842fSSascha Wildner return (AE_OK); 8180d02842fSSascha Wildner } 8190d02842fSSascha Wildner 8200d02842fSSascha Wildner 8210d02842fSSascha Wildner /****************************************************************************** 8220d02842fSSascha Wildner * 8230d02842fSSascha Wildner * FUNCTION: OslListBiosTables 8240d02842fSSascha Wildner * 8250d02842fSSascha Wildner * PARAMETERS: None 8260d02842fSSascha Wildner * 8270d02842fSSascha Wildner * RETURN: Status; Table list is initialized if AE_OK. 8280d02842fSSascha Wildner * 8290d02842fSSascha Wildner * DESCRIPTION: Add ACPI tables to the table list from memory. 8300d02842fSSascha Wildner * 8310d02842fSSascha Wildner * NOTE: This works on Linux as table customization does not modify the 8320d02842fSSascha Wildner * addresses stored in RSDP/RSDT/XSDT/FADT. 8330d02842fSSascha Wildner * 8340d02842fSSascha Wildner *****************************************************************************/ 8350d02842fSSascha Wildner 8360d02842fSSascha Wildner static ACPI_STATUS 8370d02842fSSascha Wildner OslListBiosTables ( 8380d02842fSSascha Wildner void) 8390d02842fSSascha Wildner { 8400d02842fSSascha Wildner ACPI_TABLE_HEADER *MappedTable = NULL; 8410d02842fSSascha Wildner UINT8 *TableData; 8420d02842fSSascha Wildner UINT8 NumberOfTables; 8430d02842fSSascha Wildner UINT8 ItemSize; 8440d02842fSSascha Wildner ACPI_PHYSICAL_ADDRESS TableAddress = 0; 8450d02842fSSascha Wildner ACPI_STATUS Status = AE_OK; 8460d02842fSSascha Wildner UINT32 i; 8470d02842fSSascha Wildner 8480d02842fSSascha Wildner 8499e1c0880SSascha Wildner if (OslCanUseXsdt ()) 8500d02842fSSascha Wildner { 8510d02842fSSascha Wildner ItemSize = sizeof (UINT64); 8520d02842fSSascha Wildner TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER); 8530d02842fSSascha Wildner NumberOfTables = 8540d02842fSSascha Wildner (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER)) 8550d02842fSSascha Wildner / ItemSize); 8560d02842fSSascha Wildner } 8570d02842fSSascha Wildner else /* Use RSDT if XSDT is not available */ 8580d02842fSSascha Wildner { 8590d02842fSSascha Wildner ItemSize = sizeof (UINT32); 8600d02842fSSascha Wildner TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER); 8610d02842fSSascha Wildner NumberOfTables = 8620d02842fSSascha Wildner (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER)) 8630d02842fSSascha Wildner / ItemSize); 8640d02842fSSascha Wildner } 8650d02842fSSascha Wildner 8660d02842fSSascha Wildner /* Search RSDT/XSDT for the requested table */ 8670d02842fSSascha Wildner 8680d02842fSSascha Wildner for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize) 8690d02842fSSascha Wildner { 8709e1c0880SSascha Wildner if (OslCanUseXsdt ()) 8710d02842fSSascha Wildner { 8720d02842fSSascha Wildner TableAddress = 8730d02842fSSascha Wildner (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData)); 8740d02842fSSascha Wildner } 8750d02842fSSascha Wildner else 8760d02842fSSascha Wildner { 8770d02842fSSascha Wildner TableAddress = 8780d02842fSSascha Wildner (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData)); 8790d02842fSSascha Wildner } 8800d02842fSSascha Wildner 8819e1c0880SSascha Wildner /* Skip NULL entries in RSDT/XSDT */ 8829e1c0880SSascha Wildner 8839e1c0880SSascha Wildner if (!TableAddress) 8849e1c0880SSascha Wildner { 8859e1c0880SSascha Wildner continue; 8869e1c0880SSascha Wildner } 8879e1c0880SSascha Wildner 8880d02842fSSascha Wildner Status = OslMapTable (TableAddress, NULL, &MappedTable); 8890d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 8900d02842fSSascha Wildner { 8910d02842fSSascha Wildner return (Status); 8920d02842fSSascha Wildner } 8930d02842fSSascha Wildner 8940d02842fSSascha Wildner OslAddTableToList (MappedTable->Signature, 0); 8950d02842fSSascha Wildner OslUnmapTable (MappedTable); 8960d02842fSSascha Wildner } 8970d02842fSSascha Wildner 8980d02842fSSascha Wildner return (AE_OK); 8990d02842fSSascha Wildner } 9000d02842fSSascha Wildner 9010d02842fSSascha Wildner 9020d02842fSSascha Wildner /****************************************************************************** 9030d02842fSSascha Wildner * 9040d02842fSSascha Wildner * FUNCTION: OslGetBiosTable 9050d02842fSSascha Wildner * 9060d02842fSSascha Wildner * PARAMETERS: Signature - ACPI Signature for common table. Must be 9070d02842fSSascha Wildner * a null terminated 4-character string. 9080d02842fSSascha Wildner * Instance - Multiple table support for SSDT/UEFI (0...n) 9090d02842fSSascha Wildner * Must be 0 for other tables. 9100d02842fSSascha Wildner * Table - Where a pointer to the table is returned 9110d02842fSSascha Wildner * Address - Where the table physical address is returned 9120d02842fSSascha Wildner * 9130d02842fSSascha Wildner * RETURN: Status; Table buffer and physical address returned if AE_OK. 9140d02842fSSascha Wildner * AE_LIMIT: Instance is beyond valid limit 9150d02842fSSascha Wildner * AE_NOT_FOUND: A table with the signature was not found 9160d02842fSSascha Wildner * 9170d02842fSSascha Wildner * DESCRIPTION: Get a BIOS provided ACPI table 9180d02842fSSascha Wildner * 9190d02842fSSascha Wildner * NOTE: Assumes the input signature is uppercase. 9200d02842fSSascha Wildner * 9210d02842fSSascha Wildner *****************************************************************************/ 9220d02842fSSascha Wildner 9230d02842fSSascha Wildner static ACPI_STATUS 9240d02842fSSascha Wildner OslGetBiosTable ( 9250d02842fSSascha Wildner char *Signature, 9260d02842fSSascha Wildner UINT32 Instance, 9270d02842fSSascha Wildner ACPI_TABLE_HEADER **Table, 9280d02842fSSascha Wildner ACPI_PHYSICAL_ADDRESS *Address) 9290d02842fSSascha Wildner { 9300d02842fSSascha Wildner ACPI_TABLE_HEADER *LocalTable = NULL; 9310d02842fSSascha Wildner ACPI_TABLE_HEADER *MappedTable = NULL; 9320d02842fSSascha Wildner UINT8 *TableData; 9330d02842fSSascha Wildner UINT8 NumberOfTables; 9340d02842fSSascha Wildner UINT8 ItemSize; 9350d02842fSSascha Wildner UINT32 CurrentInstance = 0; 9360d02842fSSascha Wildner ACPI_PHYSICAL_ADDRESS TableAddress = 0; 9370d02842fSSascha Wildner UINT32 TableLength = 0; 9380d02842fSSascha Wildner ACPI_STATUS Status = AE_OK; 9390d02842fSSascha Wildner UINT32 i; 9400d02842fSSascha Wildner 9410d02842fSSascha Wildner 9420d02842fSSascha Wildner /* Handle special tables whose addresses are not in RSDT/XSDT */ 9430d02842fSSascha Wildner 94420294b7eSSascha Wildner if (ACPI_COMPARE_NAME (Signature, ACPI_RSDP_NAME) || 9450d02842fSSascha Wildner ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT) || 9460d02842fSSascha Wildner ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT) || 9470d02842fSSascha Wildner ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT) || 9480d02842fSSascha Wildner ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS)) 9490d02842fSSascha Wildner { 9505f39c7e7SSascha Wildner if (Instance > 0) 9515f39c7e7SSascha Wildner { 9525f39c7e7SSascha Wildner return (AE_LIMIT); 9535f39c7e7SSascha Wildner } 9545f39c7e7SSascha Wildner 9550d02842fSSascha Wildner /* 9560d02842fSSascha Wildner * Get the appropriate address, either 32-bit or 64-bit. Be very 9570d02842fSSascha Wildner * careful about the FADT length and validate table addresses. 9580d02842fSSascha Wildner * Note: The 64-bit addresses have priority. 9590d02842fSSascha Wildner */ 9600d02842fSSascha Wildner if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT)) 9610d02842fSSascha Wildner { 9620d02842fSSascha Wildner if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) && 9630d02842fSSascha Wildner Gbl_Fadt->XDsdt) 9640d02842fSSascha Wildner { 9650d02842fSSascha Wildner TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt; 9660d02842fSSascha Wildner } 9670d02842fSSascha Wildner else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) && 9680d02842fSSascha Wildner Gbl_Fadt->Dsdt) 9690d02842fSSascha Wildner { 9700d02842fSSascha Wildner TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt; 9710d02842fSSascha Wildner } 9720d02842fSSascha Wildner } 9730d02842fSSascha Wildner else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS)) 9740d02842fSSascha Wildner { 9750d02842fSSascha Wildner if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) && 9760d02842fSSascha Wildner Gbl_Fadt->XFacs) 9770d02842fSSascha Wildner { 9780d02842fSSascha Wildner TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs; 9790d02842fSSascha Wildner } 9800d02842fSSascha Wildner else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) && 9810d02842fSSascha Wildner Gbl_Fadt->Facs) 9820d02842fSSascha Wildner { 9830d02842fSSascha Wildner TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs; 9840d02842fSSascha Wildner } 9850d02842fSSascha Wildner } 9860d02842fSSascha Wildner else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT)) 9870d02842fSSascha Wildner { 9880d02842fSSascha Wildner if (!Gbl_Revision) 9890d02842fSSascha Wildner { 9900d02842fSSascha Wildner return (AE_BAD_SIGNATURE); 9910d02842fSSascha Wildner } 9920d02842fSSascha Wildner TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.XsdtPhysicalAddress; 9930d02842fSSascha Wildner } 9940d02842fSSascha Wildner else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT)) 9950d02842fSSascha Wildner { 9960d02842fSSascha Wildner TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.RsdtPhysicalAddress; 9970d02842fSSascha Wildner } 9980d02842fSSascha Wildner else 9990d02842fSSascha Wildner { 10000d02842fSSascha Wildner TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_RsdpAddress; 10010d02842fSSascha Wildner Signature = ACPI_SIG_RSDP; 10020d02842fSSascha Wildner } 10030d02842fSSascha Wildner 10040d02842fSSascha Wildner /* Now we can get the requested special table */ 10050d02842fSSascha Wildner 10060d02842fSSascha Wildner Status = OslMapTable (TableAddress, Signature, &MappedTable); 10070d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 10080d02842fSSascha Wildner { 10090d02842fSSascha Wildner return (Status); 10100d02842fSSascha Wildner } 10110d02842fSSascha Wildner 10120d02842fSSascha Wildner TableLength = ApGetTableLength (MappedTable); 10130d02842fSSascha Wildner } 10140d02842fSSascha Wildner else /* Case for a normal ACPI table */ 10150d02842fSSascha Wildner { 10169e1c0880SSascha Wildner if (OslCanUseXsdt ()) 10170d02842fSSascha Wildner { 10180d02842fSSascha Wildner ItemSize = sizeof (UINT64); 10190d02842fSSascha Wildner TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER); 10200d02842fSSascha Wildner NumberOfTables = 10210d02842fSSascha Wildner (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER)) 10220d02842fSSascha Wildner / ItemSize); 10230d02842fSSascha Wildner } 10240d02842fSSascha Wildner else /* Use RSDT if XSDT is not available */ 10250d02842fSSascha Wildner { 10260d02842fSSascha Wildner ItemSize = sizeof (UINT32); 10270d02842fSSascha Wildner TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER); 10280d02842fSSascha Wildner NumberOfTables = 10290d02842fSSascha Wildner (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER)) 10300d02842fSSascha Wildner / ItemSize); 10310d02842fSSascha Wildner } 10320d02842fSSascha Wildner 10330d02842fSSascha Wildner /* Search RSDT/XSDT for the requested table */ 10340d02842fSSascha Wildner 10350d02842fSSascha Wildner for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize) 10360d02842fSSascha Wildner { 10379e1c0880SSascha Wildner if (OslCanUseXsdt ()) 10380d02842fSSascha Wildner { 10390d02842fSSascha Wildner TableAddress = 10400d02842fSSascha Wildner (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData)); 10410d02842fSSascha Wildner } 10420d02842fSSascha Wildner else 10430d02842fSSascha Wildner { 10440d02842fSSascha Wildner TableAddress = 10450d02842fSSascha Wildner (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData)); 10460d02842fSSascha Wildner } 10470d02842fSSascha Wildner 10489e1c0880SSascha Wildner /* Skip NULL entries in RSDT/XSDT */ 10499e1c0880SSascha Wildner 10509e1c0880SSascha Wildner if (!TableAddress) 10519e1c0880SSascha Wildner { 10529e1c0880SSascha Wildner continue; 10539e1c0880SSascha Wildner } 10549e1c0880SSascha Wildner 10550d02842fSSascha Wildner Status = OslMapTable (TableAddress, NULL, &MappedTable); 10560d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 10570d02842fSSascha Wildner { 10580d02842fSSascha Wildner return (Status); 10590d02842fSSascha Wildner } 10600d02842fSSascha Wildner TableLength = MappedTable->Length; 10610d02842fSSascha Wildner 10620d02842fSSascha Wildner /* Does this table match the requested signature? */ 10630d02842fSSascha Wildner 10640d02842fSSascha Wildner if (!ACPI_COMPARE_NAME (MappedTable->Signature, Signature)) 10650d02842fSSascha Wildner { 10660d02842fSSascha Wildner OslUnmapTable (MappedTable); 10670d02842fSSascha Wildner MappedTable = NULL; 10680d02842fSSascha Wildner continue; 10690d02842fSSascha Wildner } 10700d02842fSSascha Wildner 10710d02842fSSascha Wildner /* Match table instance (for SSDT/UEFI tables) */ 10720d02842fSSascha Wildner 10730d02842fSSascha Wildner if (CurrentInstance != Instance) 10740d02842fSSascha Wildner { 10750d02842fSSascha Wildner OslUnmapTable (MappedTable); 10760d02842fSSascha Wildner MappedTable = NULL; 10770d02842fSSascha Wildner CurrentInstance++; 10780d02842fSSascha Wildner continue; 10790d02842fSSascha Wildner } 10800d02842fSSascha Wildner 10810d02842fSSascha Wildner break; 10820d02842fSSascha Wildner } 10830d02842fSSascha Wildner } 10840d02842fSSascha Wildner 10850d02842fSSascha Wildner if (!MappedTable) 10860d02842fSSascha Wildner { 10870d02842fSSascha Wildner return (AE_LIMIT); 10880d02842fSSascha Wildner } 10890d02842fSSascha Wildner 10900d02842fSSascha Wildner if (TableLength == 0) 10910d02842fSSascha Wildner { 10920d02842fSSascha Wildner Status = AE_BAD_HEADER; 1093d4972a9cSSascha Wildner goto Exit; 10940d02842fSSascha Wildner } 10950d02842fSSascha Wildner 10960d02842fSSascha Wildner /* Copy table to local buffer and return it */ 10970d02842fSSascha Wildner 10980d02842fSSascha Wildner LocalTable = calloc (1, TableLength); 10990d02842fSSascha Wildner if (!LocalTable) 11000d02842fSSascha Wildner { 11010d02842fSSascha Wildner Status = AE_NO_MEMORY; 1102d4972a9cSSascha Wildner goto Exit; 11030d02842fSSascha Wildner } 11040d02842fSSascha Wildner 1105*25ca8c79SSascha Wildner memcpy (LocalTable, MappedTable, TableLength); 11060d02842fSSascha Wildner *Address = TableAddress; 11070d02842fSSascha Wildner *Table = LocalTable; 11080d02842fSSascha Wildner 1109d4972a9cSSascha Wildner Exit: 11100d02842fSSascha Wildner OslUnmapTable (MappedTable); 1111d4972a9cSSascha Wildner return (Status); 11120d02842fSSascha Wildner } 11130d02842fSSascha Wildner 11140d02842fSSascha Wildner 11150d02842fSSascha Wildner /****************************************************************************** 11160d02842fSSascha Wildner * 11170d02842fSSascha Wildner * FUNCTION: OslListCustomizedTables 11180d02842fSSascha Wildner * 11190d02842fSSascha Wildner * PARAMETERS: Directory - Directory that contains the tables 11200d02842fSSascha Wildner * 11210d02842fSSascha Wildner * RETURN: Status; Table list is initialized if AE_OK. 11220d02842fSSascha Wildner * 11230d02842fSSascha Wildner * DESCRIPTION: Add ACPI tables to the table list from a directory. 11240d02842fSSascha Wildner * 11250d02842fSSascha Wildner *****************************************************************************/ 11260d02842fSSascha Wildner 11270d02842fSSascha Wildner static ACPI_STATUS 11280d02842fSSascha Wildner OslListCustomizedTables ( 11290d02842fSSascha Wildner char *Directory) 11300d02842fSSascha Wildner { 11310d02842fSSascha Wildner void *TableDir; 11320d02842fSSascha Wildner UINT32 Instance; 11330d02842fSSascha Wildner char TempName[ACPI_NAME_SIZE]; 11340d02842fSSascha Wildner char *Filename; 11350d02842fSSascha Wildner ACPI_STATUS Status = AE_OK; 11360d02842fSSascha Wildner 11370d02842fSSascha Wildner 11380d02842fSSascha Wildner /* Open the requested directory */ 11390d02842fSSascha Wildner 11400d02842fSSascha Wildner TableDir = AcpiOsOpenDirectory (Directory, "*", REQUEST_FILE_ONLY); 11410d02842fSSascha Wildner if (!TableDir) 11420d02842fSSascha Wildner { 11430d02842fSSascha Wildner return (OslGetLastStatus (AE_NOT_FOUND)); 11440d02842fSSascha Wildner } 11450d02842fSSascha Wildner 11460d02842fSSascha Wildner /* Examine all entries in this directory */ 11470d02842fSSascha Wildner 11480d02842fSSascha Wildner while ((Filename = AcpiOsGetNextFilename (TableDir))) 11490d02842fSSascha Wildner { 11500d02842fSSascha Wildner /* Extract table name and instance number */ 11510d02842fSSascha Wildner 11520d02842fSSascha Wildner Status = OslTableNameFromFile (Filename, TempName, &Instance); 11530d02842fSSascha Wildner 11540d02842fSSascha Wildner /* Ignore meaningless files */ 11550d02842fSSascha Wildner 11560d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 11570d02842fSSascha Wildner { 11580d02842fSSascha Wildner continue; 11590d02842fSSascha Wildner } 11600d02842fSSascha Wildner 11610d02842fSSascha Wildner /* Add new info node to global table list */ 11620d02842fSSascha Wildner 11630d02842fSSascha Wildner Status = OslAddTableToList (TempName, Instance); 11640d02842fSSascha Wildner if (ACPI_FAILURE (Status)) 11650d02842fSSascha Wildner { 11660d02842fSSascha Wildner break; 11670d02842fSSascha Wildner } 11680d02842fSSascha Wildner } 11690d02842fSSascha Wildner 11700d02842fSSascha Wildner AcpiOsCloseDirectory (TableDir); 11710d02842fSSascha Wildner return (Status); 11720d02842fSSascha Wildner } 11730d02842fSSascha Wildner 11740d02842fSSascha Wildner 11750d02842fSSascha Wildner /****************************************************************************** 11760d02842fSSascha Wildner * 11770d02842fSSascha Wildner * FUNCTION: OslMapTable 11780d02842fSSascha Wildner * 11790d02842fSSascha Wildner * PARAMETERS: Address - Address of the table in memory 11800d02842fSSascha Wildner * Signature - Optional ACPI Signature for desired table. 11810d02842fSSascha Wildner * Null terminated 4-character string. 11820d02842fSSascha Wildner * Table - Where a pointer to the mapped table is 11830d02842fSSascha Wildner * returned 11840d02842fSSascha Wildner * 11850d02842fSSascha Wildner * RETURN: Status; Mapped table is returned if AE_OK. 11860d02842fSSascha Wildner * AE_NOT_FOUND: A valid table was not found at the address 11870d02842fSSascha Wildner * 11880d02842fSSascha Wildner * DESCRIPTION: Map entire ACPI table into caller's address space. 11890d02842fSSascha Wildner * 11900d02842fSSascha Wildner *****************************************************************************/ 11910d02842fSSascha Wildner 11920d02842fSSascha Wildner static ACPI_STATUS 11930d02842fSSascha Wildner OslMapTable ( 11940d02842fSSascha Wildner ACPI_SIZE Address, 11950d02842fSSascha Wildner char *Signature, 11960d02842fSSascha Wildner ACPI_TABLE_HEADER **Table) 11970d02842fSSascha Wildner { 11980d02842fSSascha Wildner ACPI_TABLE_HEADER *MappedTable; 11990d02842fSSascha Wildner UINT32 Length; 12000d02842fSSascha Wildner 12010d02842fSSascha Wildner 12020d02842fSSascha Wildner if (!Address) 12030d02842fSSascha Wildner { 12040d02842fSSascha Wildner return (AE_BAD_ADDRESS); 12050d02842fSSascha Wildner } 12060d02842fSSascha Wildner 12070d02842fSSascha Wildner /* 12080d02842fSSascha Wildner * Map the header so we can get the table length. 12090d02842fSSascha Wildner * Use sizeof (ACPI_TABLE_HEADER) as: 12100d02842fSSascha Wildner * 1. it is bigger than 24 to include RSDP->Length 12110d02842fSSascha Wildner * 2. it is smaller than sizeof (ACPI_TABLE_RSDP) 12120d02842fSSascha Wildner */ 12130d02842fSSascha Wildner MappedTable = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); 12140d02842fSSascha Wildner if (!MappedTable) 12150d02842fSSascha Wildner { 12160d02842fSSascha Wildner fprintf (stderr, "Could not map table header at 0x%8.8X%8.8X\n", 12170d02842fSSascha Wildner ACPI_FORMAT_UINT64 (Address)); 12180d02842fSSascha Wildner return (OslGetLastStatus (AE_BAD_ADDRESS)); 12190d02842fSSascha Wildner } 12200d02842fSSascha Wildner 12210d02842fSSascha Wildner /* If specified, signature must match */ 12220d02842fSSascha Wildner 12239e1c0880SSascha Wildner if (Signature) 12249e1c0880SSascha Wildner { 12259e1c0880SSascha Wildner if (ACPI_VALIDATE_RSDP_SIG (Signature)) 12269e1c0880SSascha Wildner { 12279e1c0880SSascha Wildner if (!ACPI_VALIDATE_RSDP_SIG (MappedTable->Signature)) 12280d02842fSSascha Wildner { 12290d02842fSSascha Wildner AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER)); 12300d02842fSSascha Wildner return (AE_BAD_SIGNATURE); 12310d02842fSSascha Wildner } 12329e1c0880SSascha Wildner } 12339e1c0880SSascha Wildner else if (!ACPI_COMPARE_NAME (Signature, MappedTable->Signature)) 12349e1c0880SSascha Wildner { 12359e1c0880SSascha Wildner AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER)); 12369e1c0880SSascha Wildner return (AE_BAD_SIGNATURE); 12379e1c0880SSascha Wildner } 12389e1c0880SSascha Wildner } 12390d02842fSSascha Wildner 12400d02842fSSascha Wildner /* Map the entire table */ 12410d02842fSSascha Wildner 12420d02842fSSascha Wildner Length = ApGetTableLength (MappedTable); 12430d02842fSSascha Wildner AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER)); 12440d02842fSSascha Wildner if (Length == 0) 12450d02842fSSascha Wildner { 12460d02842fSSascha Wildner return (AE_BAD_HEADER); 12470d02842fSSascha Wildner } 12480d02842fSSascha Wildner 12490d02842fSSascha Wildner MappedTable = AcpiOsMapMemory (Address, Length); 12500d02842fSSascha Wildner if (!MappedTable) 12510d02842fSSascha Wildner { 12520d02842fSSascha Wildner fprintf (stderr, "Could not map table at 0x%8.8X%8.8X length %8.8X\n", 12530d02842fSSascha Wildner ACPI_FORMAT_UINT64 (Address), Length); 12540d02842fSSascha Wildner return (OslGetLastStatus (AE_INVALID_TABLE_LENGTH)); 12550d02842fSSascha Wildner } 12560d02842fSSascha Wildner 12570d02842fSSascha Wildner (void) ApIsValidChecksum (MappedTable); 12580d02842fSSascha Wildner 12590d02842fSSascha Wildner *Table = MappedTable; 12600d02842fSSascha Wildner return (AE_OK); 12610d02842fSSascha Wildner } 12620d02842fSSascha Wildner 12630d02842fSSascha Wildner 12640d02842fSSascha Wildner /****************************************************************************** 12650d02842fSSascha Wildner * 12660d02842fSSascha Wildner * FUNCTION: OslUnmapTable 12670d02842fSSascha Wildner * 12680d02842fSSascha Wildner * PARAMETERS: Table - A pointer to the mapped table 12690d02842fSSascha Wildner * 12700d02842fSSascha Wildner * RETURN: None 12710d02842fSSascha Wildner * 12720d02842fSSascha Wildner * DESCRIPTION: Unmap entire ACPI table. 12730d02842fSSascha Wildner * 12740d02842fSSascha Wildner *****************************************************************************/ 12750d02842fSSascha Wildner 12760d02842fSSascha Wildner static void 12770d02842fSSascha Wildner OslUnmapTable ( 12780d02842fSSascha Wildner ACPI_TABLE_HEADER *Table) 12790d02842fSSascha Wildner { 12800d02842fSSascha Wildner if (Table) 12810d02842fSSascha Wildner { 12820d02842fSSascha Wildner AcpiOsUnmapMemory (Table, ApGetTableLength (Table)); 12830d02842fSSascha Wildner } 12840d02842fSSascha Wildner } 12850d02842fSSascha Wildner 12860d02842fSSascha Wildner 12870d02842fSSascha Wildner /****************************************************************************** 12880d02842fSSascha Wildner * 12890d02842fSSascha Wildner * FUNCTION: OslTableNameFromFile 12900d02842fSSascha Wildner * 12910d02842fSSascha Wildner * PARAMETERS: Filename - File that contains the desired table 12920d02842fSSascha Wildner * Signature - Pointer to 4-character buffer to store 12930d02842fSSascha Wildner * extracted table signature. 12940d02842fSSascha Wildner * Instance - Pointer to integer to store extracted 12950d02842fSSascha Wildner * table instance number. 12960d02842fSSascha Wildner * 12970d02842fSSascha Wildner * RETURN: Status; Table name is extracted if AE_OK. 12980d02842fSSascha Wildner * 12990d02842fSSascha Wildner * DESCRIPTION: Extract table signature and instance number from a table file 13000d02842fSSascha Wildner * name. 13010d02842fSSascha Wildner * 13020d02842fSSascha Wildner *****************************************************************************/ 13030d02842fSSascha Wildner 13040d02842fSSascha Wildner static ACPI_STATUS 13050d02842fSSascha Wildner OslTableNameFromFile ( 13060d02842fSSascha Wildner char *Filename, 13070d02842fSSascha Wildner char *Signature, 13080d02842fSSascha Wildner UINT32 *Instance) 13090d02842fSSascha Wildner { 13100d02842fSSascha Wildner 13110d02842fSSascha Wildner /* Ignore meaningless files */ 13120d02842fSSascha Wildner 13130d02842fSSascha Wildner if (strlen (Filename) < ACPI_NAME_SIZE) 13140d02842fSSascha Wildner { 13150d02842fSSascha Wildner return (AE_BAD_SIGNATURE); 13160d02842fSSascha Wildner } 13170d02842fSSascha Wildner 13180d02842fSSascha Wildner /* Extract instance number */ 13190d02842fSSascha Wildner 13200d02842fSSascha Wildner if (isdigit ((int) Filename[ACPI_NAME_SIZE])) 13210d02842fSSascha Wildner { 13225943f66cSSascha Wildner sscanf (&Filename[ACPI_NAME_SIZE], "%u", Instance); 13230d02842fSSascha Wildner } 13240d02842fSSascha Wildner else if (strlen (Filename) != ACPI_NAME_SIZE) 13250d02842fSSascha Wildner { 13260d02842fSSascha Wildner return (AE_BAD_SIGNATURE); 13270d02842fSSascha Wildner } 13280d02842fSSascha Wildner else 13290d02842fSSascha Wildner { 13300d02842fSSascha Wildner *Instance = 0; 13310d02842fSSascha Wildner } 13320d02842fSSascha Wildner 13330d02842fSSascha Wildner /* Extract signature */ 13340d02842fSSascha Wildner 13350d02842fSSascha Wildner ACPI_MOVE_NAME (Signature, Filename); 13360d02842fSSascha Wildner return (AE_OK); 13370d02842fSSascha Wildner } 13380d02842fSSascha Wildner 13390d02842fSSascha Wildner 13400d02842fSSascha Wildner /****************************************************************************** 13410d02842fSSascha Wildner * 13420d02842fSSascha Wildner * FUNCTION: OslReadTableFromFile 13430d02842fSSascha Wildner * 13440d02842fSSascha Wildner * PARAMETERS: Filename - File that contains the desired table 13450d02842fSSascha Wildner * FileOffset - Offset of the table in file 13460d02842fSSascha Wildner * Signature - Optional ACPI Signature for desired table. 13470d02842fSSascha Wildner * A null terminated 4-character string. 13480d02842fSSascha Wildner * Table - Where a pointer to the table is returned 13490d02842fSSascha Wildner * 13500d02842fSSascha Wildner * RETURN: Status; Table buffer is returned if AE_OK. 13510d02842fSSascha Wildner * 13520d02842fSSascha Wildner * DESCRIPTION: Read a ACPI table from a file. 13530d02842fSSascha Wildner * 13540d02842fSSascha Wildner *****************************************************************************/ 13550d02842fSSascha Wildner 13560d02842fSSascha Wildner static ACPI_STATUS 13570d02842fSSascha Wildner OslReadTableFromFile ( 13580d02842fSSascha Wildner char *Filename, 13590d02842fSSascha Wildner ACPI_SIZE FileOffset, 13600d02842fSSascha Wildner char *Signature, 13610d02842fSSascha Wildner ACPI_TABLE_HEADER **Table) 13620d02842fSSascha Wildner { 13630d02842fSSascha Wildner FILE *TableFile; 13640d02842fSSascha Wildner ACPI_TABLE_HEADER Header; 13650d02842fSSascha Wildner ACPI_TABLE_HEADER *LocalTable = NULL; 13660d02842fSSascha Wildner UINT32 TableLength; 13670d02842fSSascha Wildner INT32 Count; 13680d02842fSSascha Wildner ACPI_STATUS Status = AE_OK; 13690d02842fSSascha Wildner 13700d02842fSSascha Wildner 13710d02842fSSascha Wildner /* Open the file */ 13720d02842fSSascha Wildner 13730d02842fSSascha Wildner TableFile = fopen (Filename, "rb"); 13740d02842fSSascha Wildner if (TableFile == NULL) 13750d02842fSSascha Wildner { 13760d02842fSSascha Wildner fprintf (stderr, "Could not open table file: %s\n", Filename); 13770d02842fSSascha Wildner return (OslGetLastStatus (AE_NOT_FOUND)); 13780d02842fSSascha Wildner } 13790d02842fSSascha Wildner 13800d02842fSSascha Wildner fseek (TableFile, FileOffset, SEEK_SET); 13810d02842fSSascha Wildner 13820d02842fSSascha Wildner /* Read the Table header to get the table length */ 13830d02842fSSascha Wildner 13840d02842fSSascha Wildner Count = fread (&Header, 1, sizeof (ACPI_TABLE_HEADER), TableFile); 13850d02842fSSascha Wildner if (Count != sizeof (ACPI_TABLE_HEADER)) 13860d02842fSSascha Wildner { 13870d02842fSSascha Wildner fprintf (stderr, "Could not read table header: %s\n", Filename); 13880d02842fSSascha Wildner Status = AE_BAD_HEADER; 1389d4972a9cSSascha Wildner goto Exit; 13900d02842fSSascha Wildner } 13910d02842fSSascha Wildner 13920d02842fSSascha Wildner /* If signature is specified, it must match the table */ 13930d02842fSSascha Wildner 13949e1c0880SSascha Wildner if (Signature) 13959e1c0880SSascha Wildner { 13969e1c0880SSascha Wildner if (ACPI_VALIDATE_RSDP_SIG (Signature)) 13979e1c0880SSascha Wildner { 13989e1c0880SSascha Wildner if (!ACPI_VALIDATE_RSDP_SIG (Header.Signature)) { 13999e1c0880SSascha Wildner fprintf (stderr, "Incorrect RSDP signature: found %8.8s\n", 14009e1c0880SSascha Wildner Header.Signature); 14019e1c0880SSascha Wildner Status = AE_BAD_SIGNATURE; 14029e1c0880SSascha Wildner goto Exit; 14039e1c0880SSascha Wildner } 14049e1c0880SSascha Wildner } 14059e1c0880SSascha Wildner else if (!ACPI_COMPARE_NAME (Signature, Header.Signature)) 14060d02842fSSascha Wildner { 14070d02842fSSascha Wildner fprintf (stderr, "Incorrect signature: Expecting %4.4s, found %4.4s\n", 14080d02842fSSascha Wildner Signature, Header.Signature); 14090d02842fSSascha Wildner Status = AE_BAD_SIGNATURE; 1410d4972a9cSSascha Wildner goto Exit; 14110d02842fSSascha Wildner } 14129e1c0880SSascha Wildner } 14130d02842fSSascha Wildner 14140d02842fSSascha Wildner TableLength = ApGetTableLength (&Header); 14150d02842fSSascha Wildner if (TableLength == 0) 14160d02842fSSascha Wildner { 14170d02842fSSascha Wildner Status = AE_BAD_HEADER; 1418d4972a9cSSascha Wildner goto Exit; 14190d02842fSSascha Wildner } 14200d02842fSSascha Wildner 14210d02842fSSascha Wildner /* Read the entire table into a local buffer */ 14220d02842fSSascha Wildner 14230d02842fSSascha Wildner LocalTable = calloc (1, TableLength); 14240d02842fSSascha Wildner if (!LocalTable) 14250d02842fSSascha Wildner { 14260d02842fSSascha Wildner fprintf (stderr, 14270d02842fSSascha Wildner "%4.4s: Could not allocate buffer for table of length %X\n", 14280d02842fSSascha Wildner Header.Signature, TableLength); 14290d02842fSSascha Wildner Status = AE_NO_MEMORY; 1430d4972a9cSSascha Wildner goto Exit; 14310d02842fSSascha Wildner } 14320d02842fSSascha Wildner 14330d02842fSSascha Wildner fseek (TableFile, FileOffset, SEEK_SET); 14340d02842fSSascha Wildner 14359e1c0880SSascha Wildner Count = fread (LocalTable, 1, TableLength, TableFile); 14369e1c0880SSascha Wildner if (Count != TableLength) 14370d02842fSSascha Wildner { 14380d02842fSSascha Wildner fprintf (stderr, "%4.4s: Could not read table content\n", 14390d02842fSSascha Wildner Header.Signature); 14400d02842fSSascha Wildner Status = AE_INVALID_TABLE_LENGTH; 1441d4972a9cSSascha Wildner goto Exit; 14420d02842fSSascha Wildner } 14430d02842fSSascha Wildner 14440d02842fSSascha Wildner /* Validate checksum */ 14450d02842fSSascha Wildner 14460d02842fSSascha Wildner (void) ApIsValidChecksum (LocalTable); 14470d02842fSSascha Wildner 1448d4972a9cSSascha Wildner Exit: 14490d02842fSSascha Wildner fclose (TableFile); 14500d02842fSSascha Wildner *Table = LocalTable; 14510d02842fSSascha Wildner return (Status); 14520d02842fSSascha Wildner } 14530d02842fSSascha Wildner 14540d02842fSSascha Wildner 14550d02842fSSascha Wildner /****************************************************************************** 14560d02842fSSascha Wildner * 14570d02842fSSascha Wildner * FUNCTION: OslGetCustomizedTable 14580d02842fSSascha Wildner * 14590d02842fSSascha Wildner * PARAMETERS: Pathname - Directory to find Linux customized table 14600d02842fSSascha Wildner * Signature - ACPI Signature for desired table. Must be 14610d02842fSSascha Wildner * a null terminated 4-character string. 14620d02842fSSascha Wildner * Instance - Multiple table support for SSDT/UEFI (0...n) 14630d02842fSSascha Wildner * Must be 0 for other tables. 14640d02842fSSascha Wildner * Table - Where a pointer to the table is returned 14650d02842fSSascha Wildner * Address - Where the table physical address is returned 14660d02842fSSascha Wildner * 14670d02842fSSascha Wildner * RETURN: Status; Table buffer is returned if AE_OK. 14680d02842fSSascha Wildner * AE_LIMIT: Instance is beyond valid limit 14690d02842fSSascha Wildner * AE_NOT_FOUND: A table with the signature was not found 14700d02842fSSascha Wildner * 14710d02842fSSascha Wildner * DESCRIPTION: Get an OS customized table. 14720d02842fSSascha Wildner * 14730d02842fSSascha Wildner *****************************************************************************/ 14740d02842fSSascha Wildner 14750d02842fSSascha Wildner static ACPI_STATUS 14760d02842fSSascha Wildner OslGetCustomizedTable ( 14770d02842fSSascha Wildner char *Pathname, 14780d02842fSSascha Wildner char *Signature, 14790d02842fSSascha Wildner UINT32 Instance, 14800d02842fSSascha Wildner ACPI_TABLE_HEADER **Table, 14810d02842fSSascha Wildner ACPI_PHYSICAL_ADDRESS *Address) 14820d02842fSSascha Wildner { 14830d02842fSSascha Wildner void *TableDir; 14840d02842fSSascha Wildner UINT32 CurrentInstance = 0; 14850d02842fSSascha Wildner char TempName[ACPI_NAME_SIZE]; 14860d02842fSSascha Wildner char TableFilename[PATH_MAX]; 14870d02842fSSascha Wildner char *Filename; 14880d02842fSSascha Wildner ACPI_STATUS Status; 14890d02842fSSascha Wildner 14900d02842fSSascha Wildner 14910d02842fSSascha Wildner /* Open the directory for customized tables */ 14920d02842fSSascha Wildner 14930d02842fSSascha Wildner TableDir = AcpiOsOpenDirectory (Pathname, "*", REQUEST_FILE_ONLY); 14940d02842fSSascha Wildner if (!TableDir) 14950d02842fSSascha Wildner { 14960d02842fSSascha Wildner return (OslGetLastStatus (AE_NOT_FOUND)); 14970d02842fSSascha Wildner } 14980d02842fSSascha Wildner 14990d02842fSSascha Wildner /* Attempt to find the table in the directory */ 15000d02842fSSascha Wildner 15010d02842fSSascha Wildner while ((Filename = AcpiOsGetNextFilename (TableDir))) 15020d02842fSSascha Wildner { 15030d02842fSSascha Wildner /* Ignore meaningless files */ 15040d02842fSSascha Wildner 15050d02842fSSascha Wildner if (!ACPI_COMPARE_NAME (Filename, Signature)) 15060d02842fSSascha Wildner { 15070d02842fSSascha Wildner continue; 15080d02842fSSascha Wildner } 15090d02842fSSascha Wildner 15100d02842fSSascha Wildner /* Extract table name and instance number */ 15110d02842fSSascha Wildner 15120d02842fSSascha Wildner Status = OslTableNameFromFile (Filename, TempName, &CurrentInstance); 15130d02842fSSascha Wildner 15140d02842fSSascha Wildner /* Ignore meaningless files */ 15150d02842fSSascha Wildner 15160d02842fSSascha Wildner if (ACPI_FAILURE (Status) || CurrentInstance != Instance) 15170d02842fSSascha Wildner { 15180d02842fSSascha Wildner continue; 15190d02842fSSascha Wildner } 15200d02842fSSascha Wildner 15210d02842fSSascha Wildner /* Create the table pathname */ 15220d02842fSSascha Wildner 15230d02842fSSascha Wildner if (Instance != 0) 15240d02842fSSascha Wildner { 15250d02842fSSascha Wildner sprintf (TableFilename, "%s/%4.4s%d", Pathname, TempName, Instance); 15260d02842fSSascha Wildner } 15270d02842fSSascha Wildner else 15280d02842fSSascha Wildner { 15290d02842fSSascha Wildner sprintf (TableFilename, "%s/%4.4s", Pathname, TempName); 15300d02842fSSascha Wildner } 15310d02842fSSascha Wildner break; 15320d02842fSSascha Wildner } 15330d02842fSSascha Wildner 15340d02842fSSascha Wildner AcpiOsCloseDirectory (TableDir); 15350d02842fSSascha Wildner 15360d02842fSSascha Wildner if (!Filename) 15370d02842fSSascha Wildner { 15380d02842fSSascha Wildner return (AE_LIMIT); 15390d02842fSSascha Wildner } 15400d02842fSSascha Wildner 15410d02842fSSascha Wildner /* There is no physical address saved for customized tables, use zero */ 15420d02842fSSascha Wildner 15430d02842fSSascha Wildner *Address = 0; 15440d02842fSSascha Wildner Status = OslReadTableFromFile (TableFilename, 0, NULL, Table); 15450d02842fSSascha Wildner 15460d02842fSSascha Wildner return (Status); 15470d02842fSSascha Wildner } 1548