blob: 0fa499f1fed552c03856fae2c044c0cf21082f4c [file] [log] [blame]
/******************************************************************************
*
* Module Name: osbsdtbl - BSD 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"
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include <kenv.h>
#endif
#include <unistd.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#define _COMPONENT ACPI_OS_SERVICES
ACPI_MODULE_NAME ("osbsdtbl")
/* Local prototypes */
static ACPI_STATUS
OslTableInitialize (
void);
static ACPI_STATUS
OslMapTable (
ACPI_SIZE Address,
char *Signature,
ACPI_TABLE_HEADER **Table);
static ACPI_STATUS
OslAddTablesToList (
void);
static ACPI_STATUS
OslGetTableViaRoot (
char *Signature,
UINT32 Instance,
ACPI_TABLE_HEADER **Table,
ACPI_PHYSICAL_ADDRESS *Address);
/* Hints for RSDP */
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
#define SYSTEM_KENV "hint.acpi.0.rsdp"
#define SYSTEM_SYSCTL "machdep.acpi_root"
#elif defined(__NetBSD__)
#define SYSTEM_SYSCTL "hw.acpi.root"
#endif
/* Initialization flags */
UINT8 Gbl_TableListInitialized = FALSE;
UINT8 Gbl_MainTableObtained = FALSE;
/* Local copies of main ACPI tables */
ACPI_TABLE_RSDP Gbl_Rsdp;
ACPI_TABLE_FADT *Gbl_Fadt;
ACPI_TABLE_RSDT *Gbl_Rsdt;
ACPI_TABLE_XSDT *Gbl_Xsdt;
/* Fadt address */
ACPI_PHYSICAL_ADDRESS Gbl_FadtAddress;
/* Revision of RSD PTR */
UINT8 Gbl_Revision;
/* List of information about obtained ACPI tables */
typedef struct table_info
{
struct table_info *Next;
char Signature[4];
UINT32 Instance;
ACPI_PHYSICAL_ADDRESS Address;
} OSL_TABLE_INFO;
OSL_TABLE_INFO *Gbl_TableListHead = NULL;
/******************************************************************************
*
* 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)
{
ACPI_TABLE_HEADER *MappedTable;
ACPI_TABLE_HEADER *LocalTable;
ACPI_STATUS Status;
/* Validate the input physical address to avoid program crash */
if (Address < ACPI_HI_RSDP_WINDOW_BASE)
{
fprintf (stderr, "Invalid table address: 0x%8.8X%8.8X\n",
ACPI_FORMAT_UINT64 (Address));
return (AE_BAD_ADDRESS);
}
/* 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 */
LocalTable = calloc (1, MappedTable->Length);
if (!LocalTable)
{
AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
return (AE_NO_MEMORY);
}
memcpy (LocalTable, MappedTable, MappedTable->Length);
AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
*Table = LocalTable;
return (AE_OK);
}
/******************************************************************************
*
* 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;
/* Instance is only valid for SSDT/UEFI tables */
if (Instance &&
!ACPI_COMPARE_NAME (Signature, ACPI_SIG_SSDT) &&
!ACPI_COMPARE_NAME (Signature, ACPI_SIG_UEFI))
{
return (AE_LIMIT);
}
/* Initialize main tables */
Status = OslTableInitialize ();
if (ACPI_FAILURE (Status))
{
return (Status);
}
/*
* If one of the main ACPI tables was requested (RSDT/XSDT/FADT),
* simply return it immediately.
*/
if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT))
{
if (!Gbl_Revision)
{
return (AE_NOT_FOUND);
}
*Address = Gbl_Rsdp.XsdtPhysicalAddress;
*Table = (ACPI_TABLE_HEADER *) Gbl_Xsdt;
return (AE_OK);
}
if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT))
{
if (!Gbl_Rsdp.RsdtPhysicalAddress)
{
return (AE_NOT_FOUND);
}
*Address = Gbl_Rsdp.RsdtPhysicalAddress;
*Table = (ACPI_TABLE_HEADER *) Gbl_Rsdt;
return (AE_OK);
}
if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FADT))
{
*Address = Gbl_FadtAddress;
*Table = (ACPI_TABLE_HEADER *) Gbl_Fadt;
return (AE_OK);
}
/* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */
Status = OslGetTableViaRoot (Signature, Instance, Table, Address);
if (ACPI_FAILURE (Status))
{
return (Status);
}
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;
/* Initialize main tables */
Status = OslTableInitialize ();
if (ACPI_FAILURE (Status))
{
return (Status);
}
/* Add all tables to list */
Status = OslAddTablesToList ();
if (ACPI_FAILURE (Status))
{
return (Status);
}
/* Validate Index */
if (Index >= Gbl_TableListHead->Instance)
{
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 address or name */
if (Info->Address)
{
Status = AcpiOsGetTableByAddress (Info->Address, Table);
if (ACPI_SUCCESS (Status))
{
*Address = Info->Address;
}
}
else
{
Status = AcpiOsGetTableByName (Info->Signature, Info->Instance,
Table, Address);
}
if (ACPI_SUCCESS (Status))
{
*Instance = Info->Instance;
}
return (Status);
}
/******************************************************************************
*
* FUNCTION: OslTableInitialize
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
* local variables. Main ACPI tables include RSDP, FADT, RSDT,
* and/or XSDT.
*
*****************************************************************************/
static ACPI_STATUS
OslTableInitialize (
void)
{
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
char Buffer[32];
#endif
ACPI_TABLE_HEADER *MappedTable;
UINT8 *TableAddress;
UINT8 *RsdpAddress;
ACPI_PHYSICAL_ADDRESS RsdpBase;
ACPI_SIZE RsdpSize;
ACPI_STATUS Status;
u_long Address = 0;
size_t Length = sizeof (Address);
/* Get main ACPI tables from memory on first invocation of this function */
if (Gbl_MainTableObtained)
{
return (AE_OK);
}
/* Attempt to use kenv or sysctl to find RSD PTR record. */
if (Gbl_RsdpBase)
{
Address = Gbl_RsdpBase;
}
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
else if (kenv (KENV_GET, SYSTEM_KENV, Buffer, sizeof (Buffer)) > 0)
{
Address = strtoul (Buffer, NULL, 0);
}
#endif
if (!Address)
{
if (sysctlbyname (SYSTEM_SYSCTL, &Address, &Length, NULL, 0) != 0)
{
Address = 0;
}
}
if (Address)
{
RsdpBase = Address;
RsdpSize = sizeof (Gbl_Rsdp);
}
else
{
RsdpBase = ACPI_HI_RSDP_WINDOW_BASE;
RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE;
}
/* Get RSDP from memory */
RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize);
if (!RsdpAddress)
{
return (AE_BAD_ADDRESS);
}
/* Search low memory for the RSDP */
TableAddress = AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize);
if (!TableAddress)
{
AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
return (AE_ERROR);
}
memcpy (&Gbl_Rsdp, TableAddress, sizeof (Gbl_Rsdp));
AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
/* Get XSDT from memory */
if (Gbl_Rsdp.Revision)
{
Status = OslMapTable (Gbl_Rsdp.XsdtPhysicalAddress,
ACPI_SIG_XSDT, &MappedTable);
if (ACPI_FAILURE (Status))
{
return (Status);
}
Gbl_Revision = 2;
Gbl_Xsdt = calloc (1, MappedTable->Length);
if (!Gbl_Xsdt)
{
fprintf (stderr,
"XSDT: Could not allocate buffer for table of length %X\n",
MappedTable->Length);
AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
return (AE_NO_MEMORY);
}
memcpy (Gbl_Xsdt, MappedTable, MappedTable->Length);
AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
}
/* Get RSDT from memory */
if (Gbl_Rsdp.RsdtPhysicalAddress)
{
Status = OslMapTable (Gbl_Rsdp.RsdtPhysicalAddress,
ACPI_SIG_RSDT, &MappedTable);
if (ACPI_FAILURE (Status))
{
return (Status);
}
Gbl_Rsdt = calloc (1, MappedTable->Length);
if (!Gbl_Rsdt)
{
fprintf (stderr,
"RSDT: Could not allocate buffer for table of length %X\n",
MappedTable->Length);
AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
return (AE_NO_MEMORY);
}
memcpy (Gbl_Rsdt, MappedTable, MappedTable->Length);
AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
}
/* Get FADT from memory */
if (Gbl_Revision)
{
Gbl_FadtAddress = Gbl_Xsdt->TableOffsetEntry[0];
}
else
{
Gbl_FadtAddress = Gbl_Rsdt->TableOffsetEntry[0];
}
if (!Gbl_FadtAddress)
{
fprintf(stderr, "FADT: Table could not be found\n");
return (AE_ERROR);
}
Status = OslMapTable (Gbl_FadtAddress, ACPI_SIG_FADT, &MappedTable);
if (ACPI_FAILURE (Status))
{
return (Status);
}
Gbl_Fadt = calloc (1, MappedTable->Length);
if (!Gbl_Fadt)
{
fprintf (stderr,
"FADT: Could not allocate buffer for table of length %X\n",
MappedTable->Length);
AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
return (AE_NO_MEMORY);
}
memcpy (Gbl_Fadt, MappedTable, MappedTable->Length);
AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
Gbl_MainTableObtained = TRUE;
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: OslGetTableViaRoot
*
* 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 an ACPI table via the root table (RSDT/XSDT)
*
* NOTE: Assumes the input signature is uppercase.
*
*****************************************************************************/
static ACPI_STATUS
OslGetTableViaRoot (
char *Signature,
UINT32 Instance,
ACPI_TABLE_HEADER **Table,
ACPI_PHYSICAL_ADDRESS *Address)
{
ACPI_TABLE_HEADER *LocalTable = NULL;
ACPI_TABLE_HEADER *MappedTable = NULL;
UINT8 NumberOfTables;
UINT32 CurrentInstance = 0;
ACPI_PHYSICAL_ADDRESS TableAddress = 0;
ACPI_STATUS Status;
UINT32 i;
/* DSDT and FACS address must be extracted from the FADT */
if (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 /* 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 /* Case for a normal ACPI table */
{
if (Gbl_Revision)
{
NumberOfTables =
(Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header))
/ sizeof (Gbl_Xsdt->TableOffsetEntry[0]);
}
else /* Use RSDT if XSDT is not available */
{
NumberOfTables =
(Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header))
/ sizeof (Gbl_Rsdt->TableOffsetEntry[0]);
}
/* Search RSDT/XSDT for the requested table */
for (i = 0; i < NumberOfTables; i++)
{
if (Gbl_Revision)
{
TableAddress = Gbl_Xsdt->TableOffsetEntry[i];
}
else
{
TableAddress = Gbl_Rsdt->TableOffsetEntry[i];
}
MappedTable = AcpiOsMapMemory (TableAddress, sizeof (*MappedTable));
if (!MappedTable)
{
return (AE_BAD_ADDRESS);
}
/* Does this table match the requested signature? */
if (ACPI_COMPARE_NAME (MappedTable->Signature, Signature))
{
/* Match table instance (for SSDT/UEFI tables) */
if (CurrentInstance == Instance)
{
AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
break;
}
CurrentInstance++;
}
AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
TableAddress = 0;
}
}
if (!TableAddress)
{
if (CurrentInstance)
{
return (AE_LIMIT);
}
return (AE_NOT_FOUND);
}
/* Now we can get the requested table */
Status = OslMapTable (TableAddress, Signature, &MappedTable);
if (ACPI_FAILURE (Status))
{
return (Status);
}
/* Copy table to local buffer and return it */
LocalTable = calloc (1, MappedTable->Length);
if (!LocalTable)
{
AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
return (AE_NO_MEMORY);
}
memcpy (LocalTable, MappedTable, MappedTable->Length);
AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
*Table = LocalTable;
*Address = TableAddress;
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: OslAddTablesToList
*
* PARAMETERS: None
*
* RETURN: Status; Table list is initialized if AE_OK.
*
* DESCRIPTION: Add ACPI tables to the table list.
*
*****************************************************************************/
static ACPI_STATUS
OslAddTablesToList(
void)
{
ACPI_PHYSICAL_ADDRESS TableAddress;
OSL_TABLE_INFO *Info = NULL;
OSL_TABLE_INFO *NewInfo;
ACPI_TABLE_HEADER *Table;
UINT8 Instance;
UINT8 NumberOfTables;
int i;
/* Initialize the table list on first invocation */
if (Gbl_TableListInitialized)
{
return (AE_OK);
}
/* Add mandatory tables to global table list first */
for (i = 0; i < 4; i++)
{
NewInfo = calloc (1, sizeof (*NewInfo));
if (!NewInfo)
{
return (AE_NO_MEMORY);
}
switch (i) {
case 0:
Gbl_TableListHead = Info = NewInfo;
continue;
case 1:
ACPI_MOVE_NAME (NewInfo->Signature,
Gbl_Revision ? ACPI_SIG_XSDT : ACPI_SIG_RSDT);
break;
case 2:
ACPI_MOVE_NAME (NewInfo->Signature, ACPI_SIG_FACS);
break;
default:
ACPI_MOVE_NAME (NewInfo->Signature, ACPI_SIG_DSDT);
}
Info->Next = NewInfo;
Info = NewInfo;
Gbl_TableListHead->Instance++;
}
/* Add normal tables from RSDT/XSDT to global list */
if (Gbl_Revision)
{
NumberOfTables =
(Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header))
/ sizeof (Gbl_Xsdt->TableOffsetEntry[0]);
}
else
{
NumberOfTables =
(Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header))
/ sizeof (Gbl_Rsdt->TableOffsetEntry[0]);
}
for (i = 0; i < NumberOfTables; i++)
{
if (Gbl_Revision)
{
TableAddress = Gbl_Xsdt->TableOffsetEntry[i];
}
else
{
TableAddress = Gbl_Rsdt->TableOffsetEntry[i];
}
Table = AcpiOsMapMemory (TableAddress, sizeof (*Table));
if (!Table)
{
return (AE_BAD_ADDRESS);
}
Instance = 0;
NewInfo = Gbl_TableListHead;
while (NewInfo->Next != NULL)
{
NewInfo = NewInfo->Next;
if (ACPI_COMPARE_NAME (Table->Signature, NewInfo->Signature))
{
Instance++;
}
}
NewInfo = calloc (1, sizeof (*NewInfo));
if (!NewInfo)
{
AcpiOsUnmapMemory (Table, sizeof (*Table));
return (AE_NO_MEMORY);
}
ACPI_MOVE_NAME (NewInfo->Signature, Table->Signature);
AcpiOsUnmapMemory (Table, sizeof (*Table));
NewInfo->Instance = Instance;
NewInfo->Address = TableAddress;
Info->Next = NewInfo;
Info = NewInfo;
Gbl_TableListHead->Instance++;
}
Gbl_TableListInitialized = TRUE;
return (AE_OK);
}
/******************************************************************************
*
* 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.
*
* DESCRIPTION: Map entire ACPI table into caller's address space. Also
* validates the table and checksum.
*
*****************************************************************************/
static ACPI_STATUS
OslMapTable (
ACPI_SIZE Address,
char *Signature,
ACPI_TABLE_HEADER **Table)
{
ACPI_TABLE_HEADER *MappedTable;
UINT32 Length;
/* Map the header so we can get the table length */
MappedTable = AcpiOsMapMemory (Address, sizeof (*MappedTable));
if (!MappedTable)
{
return (AE_BAD_ADDRESS);
}
/* Check if table is valid */
if (!ApIsValidHeader (MappedTable))
{
AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
return (AE_BAD_HEADER);
}
/* If specified, signature must match */
if (Signature &&
!ACPI_COMPARE_NAME (Signature, MappedTable->Signature))
{
AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
return (AE_NOT_EXIST);
}
/* Map the entire table */
Length = MappedTable->Length;
AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
MappedTable = AcpiOsMapMemory (Address, Length);
if (!MappedTable)
{
return (AE_BAD_ADDRESS);
}
(void) ApIsValidChecksum (MappedTable);
*Table = MappedTable;
return (AE_OK);
}