| /****************************************************************************** |
| * |
| * Module Name: osefitbl - EFI OSL for obtaining ACPI tables |
| * |
| *****************************************************************************/ |
| |
| /* |
| * Copyright (C) 2000 - 2016, Intel Corp. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions, and the following disclaimer, |
| * without modification. |
| * 2. Redistributions in binary form must reproduce at minimum a disclaimer |
| * substantially similar to the "NO WARRANTY" disclaimer below |
| * ("Disclaimer") and any redistribution must be conditioned upon |
| * including a substantially similar Disclaimer requirement for further |
| * binary redistribution. |
| * 3. Neither the names of the above-listed copyright holders nor the names |
| * of any contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * Alternatively, this software may be distributed under the terms of the |
| * GNU General Public License ("GPL") version 2 as published by the Free |
| * Software Foundation. |
| * |
| * NO WARRANTY |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
| * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGES. |
| */ |
| |
| #include "acpidump.h" |
| |
| |
| #define _COMPONENT ACPI_OS_SERVICES |
| ACPI_MODULE_NAME ("osefitbl") |
| |
| |
| #ifndef PATH_MAX |
| #define PATH_MAX 256 |
| #endif |
| |
| |
| /* List of information about obtained ACPI tables */ |
| |
| typedef struct osl_table_info |
| { |
| struct osl_table_info *Next; |
| UINT32 Instance; |
| char Signature[ACPI_NAME_SIZE]; |
| |
| } OSL_TABLE_INFO; |
| |
| /* Local prototypes */ |
| |
| static ACPI_STATUS |
| OslTableInitialize ( |
| void); |
| |
| static ACPI_STATUS |
| OslAddTableToList ( |
| char *Signature, |
| UINT32 Instance); |
| |
| static ACPI_STATUS |
| OslMapTable ( |
| ACPI_SIZE Address, |
| char *Signature, |
| ACPI_TABLE_HEADER **Table); |
| |
| static void |
| OslUnmapTable ( |
| ACPI_TABLE_HEADER *Table); |
| |
| static ACPI_STATUS |
| OslLoadRsdp ( |
| void); |
| |
| static ACPI_STATUS |
| OslListTables ( |
| void); |
| |
| static ACPI_STATUS |
| OslGetTable ( |
| char *Signature, |
| UINT32 Instance, |
| ACPI_TABLE_HEADER **Table, |
| ACPI_PHYSICAL_ADDRESS *Address); |
| |
| |
| /* File locations */ |
| |
| #define EFI_SYSTAB "/sys/firmware/efi/systab" |
| |
| /* Initialization flags */ |
| |
| UINT8 Gbl_TableListInitialized = FALSE; |
| |
| /* Local copies of main ACPI tables */ |
| |
| ACPI_TABLE_RSDP Gbl_Rsdp; |
| ACPI_TABLE_FADT *Gbl_Fadt = NULL; |
| ACPI_TABLE_RSDT *Gbl_Rsdt = NULL; |
| ACPI_TABLE_XSDT *Gbl_Xsdt = NULL; |
| |
| /* Table addresses */ |
| |
| ACPI_PHYSICAL_ADDRESS Gbl_FadtAddress = 0; |
| ACPI_PHYSICAL_ADDRESS Gbl_RsdpAddress = 0; |
| |
| /* Revision of RSD PTR */ |
| |
| UINT8 Gbl_Revision = 0; |
| |
| OSL_TABLE_INFO *Gbl_TableListHead = NULL; |
| UINT32 Gbl_TableCount = 0; |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: AcpiOsGetTableByAddress |
| * |
| * PARAMETERS: Address - Physical address of the ACPI table |
| * Table - Where a pointer to the table is returned |
| * |
| * RETURN: Status; Table buffer is returned if AE_OK. |
| * AE_NOT_FOUND: A valid table was not found at the address |
| * |
| * DESCRIPTION: Get an ACPI table via a physical memory address. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| AcpiOsGetTableByAddress ( |
| ACPI_PHYSICAL_ADDRESS Address, |
| ACPI_TABLE_HEADER **Table) |
| { |
| UINT32 TableLength; |
| ACPI_TABLE_HEADER *MappedTable; |
| ACPI_TABLE_HEADER *LocalTable = NULL; |
| ACPI_STATUS Status = AE_OK; |
| |
| |
| /* Get main ACPI tables from memory on first invocation of this function */ |
| |
| Status = OslTableInitialize (); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| /* Map the table and validate it */ |
| |
| Status = OslMapTable (Address, NULL, &MappedTable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| /* Copy table to local buffer and return it */ |
| |
| TableLength = ApGetTableLength (MappedTable); |
| if (TableLength == 0) |
| { |
| Status = AE_BAD_HEADER; |
| goto Exit; |
| } |
| |
| LocalTable = ACPI_ALLOCATE_ZEROED (TableLength); |
| if (!LocalTable) |
| { |
| Status = AE_NO_MEMORY; |
| goto Exit; |
| } |
| |
| memcpy (LocalTable, MappedTable, TableLength); |
| |
| Exit: |
| OslUnmapTable (MappedTable); |
| *Table = LocalTable; |
| return (Status); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: AcpiOsGetTableByName |
| * |
| * PARAMETERS: Signature - ACPI Signature for desired table. Must be |
| * a null terminated 4-character string. |
| * Instance - Multiple table support for SSDT/UEFI (0...n) |
| * Must be 0 for other tables. |
| * Table - Where a pointer to the table is returned |
| * Address - Where the table physical address is returned |
| * |
| * RETURN: Status; Table buffer and physical address returned if AE_OK. |
| * AE_LIMIT: Instance is beyond valid limit |
| * AE_NOT_FOUND: A table with the signature was not found |
| * |
| * NOTE: Assumes the input signature is uppercase. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| AcpiOsGetTableByName ( |
| char *Signature, |
| UINT32 Instance, |
| ACPI_TABLE_HEADER **Table, |
| ACPI_PHYSICAL_ADDRESS *Address) |
| { |
| ACPI_STATUS Status; |
| |
| |
| /* Get main ACPI tables from memory on first invocation of this function */ |
| |
| Status = OslTableInitialize (); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */ |
| |
| if (!Gbl_DumpCustomizedTables) |
| { |
| /* Attempt to get the table from the memory */ |
| |
| Status = OslGetTable (Signature, Instance, Table, Address); |
| } |
| else |
| { |
| /* Attempt to get the table from the static directory */ |
| |
| Status = AE_SUPPORT; |
| } |
| |
| return (Status); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: OslAddTableToList |
| * |
| * PARAMETERS: Signature - Table signature |
| * Instance - Table instance |
| * |
| * RETURN: Status; Successfully added if AE_OK. |
| * AE_NO_MEMORY: Memory allocation error |
| * |
| * DESCRIPTION: Insert a table structure into OSL table list. |
| * |
| *****************************************************************************/ |
| |
| static ACPI_STATUS |
| OslAddTableToList ( |
| char *Signature, |
| UINT32 Instance) |
| { |
| OSL_TABLE_INFO *NewInfo; |
| OSL_TABLE_INFO *Next; |
| UINT32 NextInstance = 0; |
| BOOLEAN Found = FALSE; |
| |
| |
| NewInfo = ACPI_ALLOCATE_ZEROED (sizeof (OSL_TABLE_INFO)); |
| if (!NewInfo) |
| { |
| return (AE_NO_MEMORY); |
| } |
| |
| ACPI_MOVE_NAME (NewInfo->Signature, Signature); |
| |
| if (!Gbl_TableListHead) |
| { |
| Gbl_TableListHead = NewInfo; |
| } |
| else |
| { |
| Next = Gbl_TableListHead; |
| while (1) |
| { |
| if (ACPI_COMPARE_NAME (Next->Signature, Signature)) |
| { |
| if (Next->Instance == Instance) |
| { |
| Found = TRUE; |
| } |
| if (Next->Instance >= NextInstance) |
| { |
| NextInstance = Next->Instance + 1; |
| } |
| } |
| |
| if (!Next->Next) |
| { |
| break; |
| } |
| Next = Next->Next; |
| } |
| Next->Next = NewInfo; |
| } |
| |
| if (Found) |
| { |
| if (Instance) |
| { |
| AcpiLogError ( |
| "%4.4s: Warning unmatched table instance %d, expected %d\n", |
| Signature, Instance, NextInstance); |
| } |
| Instance = NextInstance; |
| } |
| |
| NewInfo->Instance = Instance; |
| Gbl_TableCount++; |
| |
| return (AE_OK); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: AcpiOsGetTableByIndex |
| * |
| * PARAMETERS: Index - Which table to get |
| * Table - Where a pointer to the table is returned |
| * Instance - Where a pointer to the table instance no. is |
| * returned |
| * Address - Where the table physical address is returned |
| * |
| * RETURN: Status; Table buffer and physical address returned if AE_OK. |
| * AE_LIMIT: Index is beyond valid limit |
| * |
| * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns |
| * AE_LIMIT when an invalid index is reached. Index is not |
| * necessarily an index into the RSDT/XSDT. |
| * |
| *****************************************************************************/ |
| |
| ACPI_STATUS |
| AcpiOsGetTableByIndex ( |
| UINT32 Index, |
| ACPI_TABLE_HEADER **Table, |
| UINT32 *Instance, |
| ACPI_PHYSICAL_ADDRESS *Address) |
| { |
| OSL_TABLE_INFO *Info; |
| ACPI_STATUS Status; |
| UINT32 i; |
| |
| |
| /* Get main ACPI tables from memory on first invocation of this function */ |
| |
| Status = OslTableInitialize (); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| /* Validate Index */ |
| |
| if (Index >= Gbl_TableCount) |
| { |
| return (AE_LIMIT); |
| } |
| |
| /* Point to the table list entry specified by the Index argument */ |
| |
| Info = Gbl_TableListHead; |
| for (i = 0; i < Index; i++) |
| { |
| Info = Info->Next; |
| } |
| |
| /* Now we can just get the table via the signature */ |
| |
| Status = AcpiOsGetTableByName (Info->Signature, Info->Instance, |
| Table, Address); |
| |
| if (ACPI_SUCCESS (Status)) |
| { |
| *Instance = Info->Instance; |
| } |
| return (Status); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: OslLoadRsdp |
| * |
| * PARAMETERS: None |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Scan and load RSDP. |
| * |
| *****************************************************************************/ |
| |
| static ACPI_STATUS |
| OslLoadRsdp ( |
| void) |
| { |
| ACPI_TABLE_HEADER *MappedTable; |
| UINT8 *RsdpAddress; |
| ACPI_PHYSICAL_ADDRESS RsdpBase; |
| ACPI_SIZE RsdpSize; |
| |
| |
| /* Get RSDP from memory */ |
| |
| RsdpSize = sizeof (ACPI_TABLE_RSDP); |
| if (Gbl_RsdpBase) |
| { |
| RsdpBase = Gbl_RsdpBase; |
| } |
| else |
| { |
| RsdpBase = AcpiOsGetRootPointer (); |
| } |
| |
| if (!RsdpBase) |
| { |
| RsdpBase = ACPI_HI_RSDP_WINDOW_BASE; |
| RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE; |
| } |
| |
| RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize); |
| if (!RsdpAddress) |
| { |
| return (AE_BAD_ADDRESS); |
| } |
| |
| /* Search low memory for the RSDP */ |
| |
| MappedTable = ACPI_CAST_PTR (ACPI_TABLE_HEADER, |
| AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize)); |
| if (!MappedTable) |
| { |
| AcpiOsUnmapMemory (RsdpAddress, RsdpSize); |
| return (AE_NOT_FOUND); |
| } |
| |
| Gbl_RsdpAddress = RsdpBase + (ACPI_CAST8 (MappedTable) - RsdpAddress); |
| |
| memcpy (&Gbl_Rsdp, MappedTable, sizeof (ACPI_TABLE_RSDP)); |
| AcpiOsUnmapMemory (RsdpAddress, RsdpSize); |
| |
| return (AE_OK); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: OslCanUseXsdt |
| * |
| * PARAMETERS: None |
| * |
| * RETURN: TRUE if XSDT is allowed to be used. |
| * |
| * DESCRIPTION: This function collects logic that can be used to determine if |
| * XSDT should be used instead of RSDT. |
| * |
| *****************************************************************************/ |
| |
| static BOOLEAN |
| OslCanUseXsdt ( |
| void) |
| { |
| if (Gbl_Revision && !AcpiGbl_DoNotUseXsdt) |
| { |
| return (TRUE); |
| } |
| else |
| { |
| return (FALSE); |
| } |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: OslTableInitialize |
| * |
| * PARAMETERS: None |
| * |
| * RETURN: Status |
| * |
| * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to |
| * local variables. Main ACPI tables include RSDT, FADT, RSDT, |
| * and/or XSDT. |
| * |
| *****************************************************************************/ |
| |
| static ACPI_STATUS |
| OslTableInitialize ( |
| void) |
| { |
| ACPI_STATUS Status; |
| ACPI_PHYSICAL_ADDRESS Address; |
| |
| |
| if (Gbl_TableListInitialized) |
| { |
| return (AE_OK); |
| } |
| |
| /* Get RSDP from memory */ |
| |
| Status = OslLoadRsdp (); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| /* Get XSDT from memory */ |
| |
| if (Gbl_Rsdp.Revision && !Gbl_DoNotDumpXsdt) |
| { |
| if (Gbl_Xsdt) |
| { |
| ACPI_FREE (Gbl_Xsdt); |
| Gbl_Xsdt = NULL; |
| } |
| |
| Gbl_Revision = 2; |
| Status = OslGetTable (ACPI_SIG_XSDT, 0, |
| ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Xsdt), &Address); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| } |
| |
| /* Get RSDT from memory */ |
| |
| if (Gbl_Rsdp.RsdtPhysicalAddress) |
| { |
| if (Gbl_Rsdt) |
| { |
| ACPI_FREE (Gbl_Rsdt); |
| Gbl_Rsdt = NULL; |
| } |
| |
| Status = OslGetTable (ACPI_SIG_RSDT, 0, |
| ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Rsdt), &Address); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| } |
| |
| /* Get FADT from memory */ |
| |
| if (Gbl_Fadt) |
| { |
| ACPI_FREE (Gbl_Fadt); |
| Gbl_Fadt = NULL; |
| } |
| |
| Status = OslGetTable (ACPI_SIG_FADT, 0, |
| ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Fadt), &Gbl_FadtAddress); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| if (!Gbl_DumpCustomizedTables) |
| { |
| /* Add mandatory tables to global table list first */ |
| |
| Status = OslAddTableToList (ACPI_RSDP_NAME, 0); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| Status = OslAddTableToList (ACPI_SIG_RSDT, 0); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| if (Gbl_Revision == 2) |
| { |
| Status = OslAddTableToList (ACPI_SIG_XSDT, 0); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| } |
| |
| Status = OslAddTableToList (ACPI_SIG_DSDT, 0); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| Status = OslAddTableToList (ACPI_SIG_FACS, 0); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| /* Add all tables found in the memory */ |
| |
| Status = OslListTables (); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| } |
| else |
| { |
| /* Add all tables found in the static directory */ |
| |
| Status = AE_SUPPORT; |
| } |
| |
| Gbl_TableListInitialized = TRUE; |
| return (AE_OK); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: OslListTables |
| * |
| * PARAMETERS: None |
| * |
| * RETURN: Status; Table list is initialized if AE_OK. |
| * |
| * DESCRIPTION: Add ACPI tables to the table list from memory. |
| * |
| *****************************************************************************/ |
| |
| static ACPI_STATUS |
| OslListTables ( |
| void) |
| { |
| ACPI_TABLE_HEADER *MappedTable = NULL; |
| UINT8 *TableData; |
| UINT8 NumberOfTables; |
| UINT8 ItemSize; |
| ACPI_PHYSICAL_ADDRESS TableAddress = 0; |
| ACPI_STATUS Status = AE_OK; |
| UINT32 i; |
| |
| |
| if (OslCanUseXsdt ()) |
| { |
| ItemSize = sizeof (UINT64); |
| TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER); |
| NumberOfTables = |
| (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER)) |
| / ItemSize); |
| } |
| else /* Use RSDT if XSDT is not available */ |
| { |
| ItemSize = sizeof (UINT32); |
| TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER); |
| NumberOfTables = |
| (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER)) |
| / ItemSize); |
| } |
| |
| /* Search RSDT/XSDT for the requested table */ |
| |
| for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize) |
| { |
| if (OslCanUseXsdt ()) |
| { |
| TableAddress = |
| (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData)); |
| } |
| else |
| { |
| TableAddress = |
| (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData)); |
| } |
| |
| /* Skip NULL entries in RSDT/XSDT */ |
| |
| if (!TableAddress) |
| { |
| continue; |
| } |
| |
| Status = OslMapTable (TableAddress, NULL, &MappedTable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| OslAddTableToList (MappedTable->Signature, 0); |
| OslUnmapTable (MappedTable); |
| } |
| |
| return (AE_OK); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: OslGetTable |
| * |
| * PARAMETERS: Signature - ACPI Signature for common table. Must be |
| * a null terminated 4-character string. |
| * Instance - Multiple table support for SSDT/UEFI (0...n) |
| * Must be 0 for other tables. |
| * Table - Where a pointer to the table is returned |
| * Address - Where the table physical address is returned |
| * |
| * RETURN: Status; Table buffer and physical address returned if AE_OK. |
| * AE_LIMIT: Instance is beyond valid limit |
| * AE_NOT_FOUND: A table with the signature was not found |
| * |
| * DESCRIPTION: Get a BIOS provided ACPI table |
| * |
| * NOTE: Assumes the input signature is uppercase. |
| * |
| *****************************************************************************/ |
| |
| static ACPI_STATUS |
| OslGetTable ( |
| char *Signature, |
| UINT32 Instance, |
| ACPI_TABLE_HEADER **Table, |
| ACPI_PHYSICAL_ADDRESS *Address) |
| { |
| ACPI_TABLE_HEADER *LocalTable = NULL; |
| ACPI_TABLE_HEADER *MappedTable = NULL; |
| UINT8 *TableData; |
| UINT8 NumberOfTables; |
| UINT8 ItemSize; |
| UINT32 CurrentInstance = 0; |
| ACPI_PHYSICAL_ADDRESS TableAddress = 0; |
| UINT32 TableLength = 0; |
| ACPI_STATUS Status = AE_OK; |
| UINT32 i; |
| |
| |
| /* Handle special tables whose addresses are not in RSDT/XSDT */ |
| |
| if (ACPI_COMPARE_NAME (Signature, ACPI_RSDP_NAME) || |
| ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT) || |
| ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT) || |
| ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT) || |
| ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS)) |
| { |
| /* |
| * Get the appropriate address, either 32-bit or 64-bit. Be very |
| * careful about the FADT length and validate table addresses. |
| * Note: The 64-bit addresses have priority. |
| */ |
| if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT)) |
| { |
| if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) && |
| Gbl_Fadt->XDsdt) |
| { |
| TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt; |
| } |
| else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) && |
| Gbl_Fadt->Dsdt) |
| { |
| TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt; |
| } |
| } |
| else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS)) |
| { |
| if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) && |
| Gbl_Fadt->XFacs) |
| { |
| TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs; |
| } |
| else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) && |
| Gbl_Fadt->Facs) |
| { |
| TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs; |
| } |
| } |
| else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT)) |
| { |
| if (!Gbl_Revision) |
| { |
| return (AE_BAD_SIGNATURE); |
| } |
| TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.XsdtPhysicalAddress; |
| } |
| else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT)) |
| { |
| TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.RsdtPhysicalAddress; |
| } |
| else |
| { |
| TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_RsdpAddress; |
| Signature = ACPI_SIG_RSDP; |
| } |
| |
| /* Now we can get the requested special table */ |
| |
| Status = OslMapTable (TableAddress, Signature, &MappedTable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| |
| TableLength = ApGetTableLength (MappedTable); |
| } |
| else /* Case for a normal ACPI table */ |
| { |
| if (OslCanUseXsdt ()) |
| { |
| ItemSize = sizeof (UINT64); |
| TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER); |
| NumberOfTables = |
| (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER)) |
| / ItemSize); |
| } |
| else /* Use RSDT if XSDT is not available */ |
| { |
| ItemSize = sizeof (UINT32); |
| TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER); |
| NumberOfTables = |
| (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER)) |
| / ItemSize); |
| } |
| |
| /* Search RSDT/XSDT for the requested table */ |
| |
| for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize) |
| { |
| if (OslCanUseXsdt ()) |
| { |
| TableAddress = |
| (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData)); |
| } |
| else |
| { |
| TableAddress = |
| (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData)); |
| } |
| |
| /* Skip NULL entries in RSDT/XSDT */ |
| |
| if (!TableAddress) |
| { |
| continue; |
| } |
| |
| Status = OslMapTable (TableAddress, NULL, &MappedTable); |
| if (ACPI_FAILURE (Status)) |
| { |
| return (Status); |
| } |
| TableLength = MappedTable->Length; |
| |
| /* Does this table match the requested signature? */ |
| |
| if (!ACPI_COMPARE_NAME (MappedTable->Signature, Signature)) |
| { |
| OslUnmapTable (MappedTable); |
| MappedTable = NULL; |
| continue; |
| } |
| |
| /* Match table instance (for SSDT/UEFI tables) */ |
| |
| if (CurrentInstance != Instance) |
| { |
| OslUnmapTable (MappedTable); |
| MappedTable = NULL; |
| CurrentInstance++; |
| continue; |
| } |
| |
| break; |
| } |
| } |
| |
| if (!MappedTable) |
| { |
| return (AE_LIMIT); |
| } |
| |
| if (TableLength == 0) |
| { |
| Status = AE_BAD_HEADER; |
| goto Exit; |
| } |
| |
| /* Copy table to local buffer and return it */ |
| |
| LocalTable = ACPI_ALLOCATE_ZEROED (TableLength); |
| if (!LocalTable) |
| { |
| Status = AE_NO_MEMORY; |
| goto Exit; |
| } |
| |
| memcpy (LocalTable, MappedTable, TableLength); |
| *Address = TableAddress; |
| *Table = LocalTable; |
| |
| Exit: |
| OslUnmapTable (MappedTable); |
| return (Status); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: OslMapTable |
| * |
| * PARAMETERS: Address - Address of the table in memory |
| * Signature - Optional ACPI Signature for desired table. |
| * Null terminated 4-character string. |
| * Table - Where a pointer to the mapped table is |
| * returned |
| * |
| * RETURN: Status; Mapped table is returned if AE_OK. |
| * AE_NOT_FOUND: A valid table was not found at the address |
| * |
| * DESCRIPTION: Map entire ACPI table into caller's address space. |
| * |
| *****************************************************************************/ |
| |
| static ACPI_STATUS |
| OslMapTable ( |
| ACPI_SIZE Address, |
| char *Signature, |
| ACPI_TABLE_HEADER **Table) |
| { |
| ACPI_TABLE_HEADER *MappedTable; |
| UINT32 Length; |
| |
| |
| if (!Address) |
| { |
| return (AE_BAD_ADDRESS); |
| } |
| |
| /* |
| * Map the header so we can get the table length. |
| * Use sizeof (ACPI_TABLE_HEADER) as: |
| * 1. it is bigger than 24 to include RSDP->Length |
| * 2. it is smaller than sizeof (ACPI_TABLE_RSDP) |
| */ |
| MappedTable = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); |
| if (!MappedTable) |
| { |
| AcpiLogError ("Could not map table header at 0x%8.8X%8.8X\n", |
| ACPI_FORMAT_UINT64 (Address)); |
| return (AE_BAD_ADDRESS); |
| } |
| |
| /* If specified, signature must match */ |
| |
| if (Signature) |
| { |
| if (ACPI_VALIDATE_RSDP_SIG (Signature)) |
| { |
| if (!ACPI_VALIDATE_RSDP_SIG (MappedTable->Signature)) |
| { |
| AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER)); |
| return (AE_BAD_SIGNATURE); |
| } |
| } |
| else if (!ACPI_COMPARE_NAME (Signature, MappedTable->Signature)) |
| { |
| AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER)); |
| return (AE_BAD_SIGNATURE); |
| } |
| } |
| |
| /* Map the entire table */ |
| |
| Length = ApGetTableLength (MappedTable); |
| AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER)); |
| if (Length == 0) |
| { |
| return (AE_BAD_HEADER); |
| } |
| |
| MappedTable = AcpiOsMapMemory (Address, Length); |
| if (!MappedTable) |
| { |
| AcpiLogError ("Could not map table at 0x%8.8X%8.8X length %8.8X\n", |
| ACPI_FORMAT_UINT64 (Address), Length); |
| return (AE_INVALID_TABLE_LENGTH); |
| } |
| |
| (void) ApIsValidChecksum (MappedTable); |
| |
| *Table = MappedTable; |
| return (AE_OK); |
| } |
| |
| |
| /****************************************************************************** |
| * |
| * FUNCTION: OslUnmapTable |
| * |
| * PARAMETERS: Table - A pointer to the mapped table |
| * |
| * RETURN: None |
| * |
| * DESCRIPTION: Unmap entire ACPI table. |
| * |
| *****************************************************************************/ |
| |
| static void |
| OslUnmapTable ( |
| ACPI_TABLE_HEADER *Table) |
| { |
| if (Table) |
| { |
| AcpiOsUnmapMemory (Table, ApGetTableLength (Table)); |
| } |
| } |