osillumostbl.c revision 7b1019a6d29ccb7999dc76cba3dde1c627e8e609
/*
*
* Module Name: osillumostbl - illumos OSL for obtaining ACPI tables
* This file is derived from the Intel oslinuxtbl source file.
*
*/
/*
* 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.
*/
/*
* Copyright 2016 Joyent, Inc.
*/
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "acpidump.h"
#define _COMPONENT ACPI_OS_SERVICES
ACPI_MODULE_NAME("osillumostbl")
/* List of information about obtained ACPI tables */
typedef struct osl_table_info
{
struct osl_table_info *Next;
char Signature[ACPI_NAME_SIZE];
/* Local prototypes */
static ACPI_STATUS
OslTableInitialize(void);
static ACPI_STATUS OslAddTableToList(char *);
static void OslUnmapTable(ACPI_TABLE_HEADER *);
static ACPI_STATUS OslLoadRsdp(void);
static ACPI_STATUS OslListBiosTables(void);
static int pagesize;
/* Initialization flags */
/* Local copies of main ACPI tables */
/* Table addresses */
/* Revision of RSD PTR */
UINT8 Gbl_Revision = 0;
UINT32 Gbl_TableCount = 0;
/*
*
* FUNCTION: OslGetLastStatus
*
* PARAMETERS: DefaultStatus - Default error status to return
*
* RETURN: Status; Converted from errno.
*
* DESCRIPTION: Get last errno and conver it to ACPI_STATUS.
*
*/
static ACPI_STATUS
{
switch (errno) {
case EACCES:
case EPERM:
return (AE_ACCESS);
case ENOENT:
return (AE_NOT_FOUND);
case ENOMEM:
return (AE_NO_MEMORY);
default:
return (DefaultStatus);
}
}
/*
*
* 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.
*
*/
{
/*
* 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 */
if (ACPI_FAILURE(Status)) {
return (Status);
}
/* Copy table to local buffer and return it */
if (TableLength == 0) {
goto Exit;
}
if (!LocalTable) {
goto Exit;
}
Exit:
*Table = LocalTable;
return (Status);
}
/*
*
* FUNCTION: AcpiOsGetTableByName
*
* PARAMETERS: Signature - ACPI Signature for desired table. Must be
* a null terminated 4-character string.
* 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.
*
*/
{
/*
* Get main ACPI tables from memory on first invocation of this
* function
*/
Status = OslTableInitialize();
if (ACPI_FAILURE(Status)) {
return (Status);
}
return (Status);
}
/*
*
* FUNCTION: OslAddTableToList
*
* PARAMETERS: Signature - Table signature
*
* 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 NextInstance = 0;
return (AE_NO_MEMORY);
}
if (!Gbl_TableListHead) {
} else {
while (1) {
}
}
}
break;
}
}
}
if (Found) {
}
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
*
*/
{
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 */
for (i = 0; i < Index; i++) {
}
/* Now we can just get the table via the signature */
if (ACPI_SUCCESS(Status)) {
}
return (Status);
}
/*
*
* FUNCTION: OslLoadRsdp
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Scan and load RSDP.
* the kernel finds the RSDP. That algorithm matches AcpiFindRootPointer().
* The code here is derived from AcpiFindRootPointer, except that we will try
* the BIOS if the EBDA fails, and we will copy the table if found.
*/
static ACPI_STATUS
OslLoadRsdp(void)
{
/* 1a) Get the location of the Extended BIOS Data Area (EBDA) */
goto try_bios;
/* Convert segment part to physical address */
physaddr <<= 4;
/* EBDA present? */
if (physaddr <= 0x400)
goto try_bios;
/*
* 1b) Search EBDA paragraphs (EBDA is required to be a minimum of 1K
* length)
*/
"mappable\n", physaddr);
goto try_bios;
}
return (AE_OK);
}
/* Try to get RSDP from BIOS memory */
if (Gbl_RsdpBase != NULL) {
mapsize = sizeof (ACPI_TABLE_RSDP);
} else {
}
return (OslGetLastStatus(AE_BAD_ADDRESS));
/* Search low memory for the RSDP */
return (AE_NOT_FOUND);
}
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,
*
*/
static ACPI_STATUS
OslTableInitialize(void)
{
if (Gbl_TableListInitialized) {
return (AE_OK);
}
/* Get RSDP from memory */
Status = OslLoadRsdp();
if (ACPI_FAILURE(Status)) {
return (Status);
}
/* Get XSDT from memory */
if (Gbl_Xsdt) {
}
Gbl_Revision = 2;
if (ACPI_FAILURE(Status)) {
return (Status);
}
}
/* Get RSDT from memory */
if (Gbl_Rsdp.RsdtPhysicalAddress) {
if (Gbl_Rsdt) {
}
if (ACPI_FAILURE(Status)) {
return (Status);
}
}
/* Get FADT from memory */
if (Gbl_Fadt) {
}
if (ACPI_FAILURE(Status)) {
return (Status);
}
/* Add mandatory tables to global table list first */
if (ACPI_FAILURE(Status)) {
return (Status);
}
if (ACPI_FAILURE(Status)) {
return (Status);
}
if (Gbl_Revision == 2) {
if (ACPI_FAILURE(Status)) {
return (Status);
}
}
if (ACPI_FAILURE(Status)) {
return (Status);
}
if (ACPI_FAILURE(Status)) {
return (Status);
}
/* Add all tables found in the memory */
Status = OslListBiosTables();
if (ACPI_FAILURE(Status)) {
return (Status);
}
return (AE_OK);
}
/*
*
* FUNCTION: OslListBiosTables
*
* PARAMETERS: None
*
* RETURN: Status; Table list is initialized if AE_OK.
*
* DESCRIPTION: Add ACPI tables to the table list from memory.
*/
static ACPI_STATUS
OslListBiosTables(void)
{
UINT32 i;
if (OslCanUseXsdt()) {
NumberOfTables = (UINT32)
/ ItemSize);
} else {
/* Use RSDT if XSDT is not available */
NumberOfTables = (UINT32)
/ ItemSize);
}
if (OslCanUseXsdt()) {
} else {
}
if (TableAddress == NULL) {
continue;
}
if (ACPI_FAILURE(Status)) {
return (Status);
}
}
return (AE_OK);
}
/*
*
* FUNCTION: OslGetBiosTable
*
* PARAMETERS: Signature - ACPI Signature for common table. Must be
* a null terminated 4-character string.
* 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
{
UINT32 CurrentInstance = 0;
UINT32 TableLength = 0;
UINT32 i;
if (Instance > 0) {
return (AE_LIMIT);
}
/*
* 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 (!Gbl_Revision) {
return (AE_BAD_SIGNATURE);
}
} else {
}
/* Now we can get the requested special table */
if (ACPI_FAILURE(Status)) {
return (Status);
}
} else {
/* Case for a normal ACPI table */
if (OslCanUseXsdt()) {
sizeof (ACPI_TABLE_HEADER);
sizeof (ACPI_TABLE_HEADER))
/ ItemSize);
} else {
/* Use RSDT if XSDT is not available */
sizeof (ACPI_TABLE_HEADER);
sizeof (ACPI_TABLE_HEADER))
/ ItemSize);
}
if (OslCanUseXsdt()) {
(*ACPI_CAST64(TableData));
} else {
(*ACPI_CAST32(TableData));
}
if (TableAddress == NULL) {
continue;
}
if (ACPI_FAILURE(Status)) {
return (Status);
}
/* Does this table match the requested signature? */
Signature)) {
MappedTable = NULL;
continue;
}
if (CurrentInstance != Instance) {
MappedTable = NULL;
continue;
}
break;
}
}
if (MappedTable == NULL) {
return (AE_LIMIT);
}
if (TableLength == 0) {
goto Exit;
}
/* Copy table to local buffer and return it */
if (LocalTable == NULL) {
goto Exit;
}
*Address = TableAddress;
*Table = LocalTable;
Exit:
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
{
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)
*/
if (MappedTable == NULL) {
return (OslGetLastStatus(AE_BAD_ADDRESS));
}
/* If specified, signature must match */
if (ACPI_VALIDATE_RSDP_SIG(Signature)) {
sizeof (ACPI_TABLE_HEADER));
return (AE_BAD_SIGNATURE);
}
} else if (!ACPI_COMPARE_NAME(Signature,
MappedTable->Signature)) {
sizeof (ACPI_TABLE_HEADER));
return (AE_BAD_SIGNATURE);
}
}
/* Map the entire table */
if (Length == 0) {
return (AE_BAD_HEADER);
}
if (MappedTable == NULL) {
return (OslGetLastStatus(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
{
}
}
/*
*
* FUNCTION: OslTableNameFromFile
*
* PARAMETERS: Filename - File that contains the desired table
* Signature - Pointer to 4-character buffer to store
* extracted table signature.
* Instance - Pointer to integer to store extracted
* table instance number.
*
* RETURN: Status; Table name is extracted if AE_OK.
*
* DESCRIPTION: Extract table signature and instance number from a table file
* name.
*
*/
static ACPI_STATUS
{
/* Ignore meaningless files */
return (AE_BAD_SIGNATURE);
}
/* Extract instance number */
return (AE_BAD_SIGNATURE);
} else {
*Instance = 0;
}
/* Extract signature */
return (AE_OK);
}
{
int fd;
return (ACPI_UINT32_MAX);
}
void *
{
}
void
AcpiOsFree(void *p)
{
free(p);
}
{
char mode[3];
if ((Modes & ACPI_FILE_READING) != 0)
if ((Modes & ACPI_FILE_WRITING) != 0)
}
void
{
}
int
{
}
void *
{
int fd;
void *p;
return (NULL);
if (pagesize == 0) {
pagesize = getpagesize();
}
if (p == MAP_FAILED)
return (NULL);
p = (char *)p + offset;
return (p);
}
void
{
void *p;
p = (void *)((char *)LogicalAddress - offset);
}