Creation of Cybook 2416 (actually Gen4) repository
This commit is contained in:
7
drivers/acpi/tables/Makefile
Normal file
7
drivers/acpi/tables/Makefile
Normal file
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# Makefile for all Linux ACPI interpreter subdirectories
|
||||
#
|
||||
|
||||
obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o
|
||||
|
||||
EXTRA_CFLAGS += $(ACPI_CFLAGS)
|
||||
448
drivers/acpi/tables/tbfadt.c
Normal file
448
drivers/acpi/tables/tbfadt.c
Normal file
@@ -0,0 +1,448 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: tbfadt - FADT table utilities
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2007, R. Byron Moore
|
||||
* 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 <acpi/acpi.h>
|
||||
#include <acpi/actables.h>
|
||||
|
||||
#define _COMPONENT ACPI_TABLES
|
||||
ACPI_MODULE_NAME("tbfadt")
|
||||
|
||||
/* Local prototypes */
|
||||
static void inline
|
||||
acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
|
||||
u8 bit_width, u64 address);
|
||||
|
||||
static void acpi_tb_convert_fadt(void);
|
||||
|
||||
static void acpi_tb_validate_fadt(void);
|
||||
|
||||
/* Table for conversion of FADT to common internal format and FADT validation */
|
||||
|
||||
typedef struct acpi_fadt_info {
|
||||
char *name;
|
||||
u8 target;
|
||||
u8 source;
|
||||
u8 length;
|
||||
u8 type;
|
||||
|
||||
} acpi_fadt_info;
|
||||
|
||||
#define ACPI_FADT_REQUIRED 1
|
||||
#define ACPI_FADT_SEPARATE_LENGTH 2
|
||||
|
||||
static struct acpi_fadt_info fadt_info_table[] = {
|
||||
{"Pm1aEventBlock", ACPI_FADT_OFFSET(xpm1a_event_block),
|
||||
ACPI_FADT_OFFSET(pm1a_event_block),
|
||||
ACPI_FADT_OFFSET(pm1_event_length), ACPI_FADT_REQUIRED},
|
||||
|
||||
{"Pm1bEventBlock", ACPI_FADT_OFFSET(xpm1b_event_block),
|
||||
ACPI_FADT_OFFSET(pm1b_event_block),
|
||||
ACPI_FADT_OFFSET(pm1_event_length), 0},
|
||||
|
||||
{"Pm1aControlBlock", ACPI_FADT_OFFSET(xpm1a_control_block),
|
||||
ACPI_FADT_OFFSET(pm1a_control_block),
|
||||
ACPI_FADT_OFFSET(pm1_control_length), ACPI_FADT_REQUIRED},
|
||||
|
||||
{"Pm1bControlBlock", ACPI_FADT_OFFSET(xpm1b_control_block),
|
||||
ACPI_FADT_OFFSET(pm1b_control_block),
|
||||
ACPI_FADT_OFFSET(pm1_control_length), 0},
|
||||
|
||||
{"Pm2ControlBlock", ACPI_FADT_OFFSET(xpm2_control_block),
|
||||
ACPI_FADT_OFFSET(pm2_control_block),
|
||||
ACPI_FADT_OFFSET(pm2_control_length), ACPI_FADT_SEPARATE_LENGTH},
|
||||
|
||||
{"PmTimerBlock", ACPI_FADT_OFFSET(xpm_timer_block),
|
||||
ACPI_FADT_OFFSET(pm_timer_block),
|
||||
ACPI_FADT_OFFSET(pm_timer_length), ACPI_FADT_REQUIRED},
|
||||
|
||||
{"Gpe0Block", ACPI_FADT_OFFSET(xgpe0_block),
|
||||
ACPI_FADT_OFFSET(gpe0_block),
|
||||
ACPI_FADT_OFFSET(gpe0_block_length), ACPI_FADT_SEPARATE_LENGTH},
|
||||
|
||||
{"Gpe1Block", ACPI_FADT_OFFSET(xgpe1_block),
|
||||
ACPI_FADT_OFFSET(gpe1_block),
|
||||
ACPI_FADT_OFFSET(gpe1_block_length), ACPI_FADT_SEPARATE_LENGTH}
|
||||
};
|
||||
|
||||
#define ACPI_FADT_INFO_ENTRIES (sizeof (fadt_info_table) / sizeof (struct acpi_fadt_info))
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_init_generic_address
|
||||
*
|
||||
* PARAMETERS: generic_address - GAS struct to be initialized
|
||||
* bit_width - Width of this register
|
||||
* Address - Address of the register
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Initialize a Generic Address Structure (GAS)
|
||||
* See the ACPI specification for a full description and
|
||||
* definition of this structure.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void inline
|
||||
acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
|
||||
u8 bit_width, u64 address)
|
||||
{
|
||||
|
||||
/*
|
||||
* The 64-bit Address field is non-aligned in the byte packed
|
||||
* GAS struct.
|
||||
*/
|
||||
ACPI_MOVE_64_TO_64(&generic_address->address, &address);
|
||||
|
||||
/* All other fields are byte-wide */
|
||||
|
||||
generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO;
|
||||
generic_address->bit_width = bit_width;
|
||||
generic_address->bit_offset = 0;
|
||||
generic_address->access_width = 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_parse_fadt
|
||||
*
|
||||
* PARAMETERS: table_index - Index for the FADT
|
||||
* Flags - Flags
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Initialize the FADT, DSDT and FACS tables
|
||||
* (FADT contains the addresses of the DSDT and FACS)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags)
|
||||
{
|
||||
u32 length;
|
||||
struct acpi_table_header *table;
|
||||
|
||||
/*
|
||||
* The FADT has multiple versions with different lengths,
|
||||
* and it contains pointers to both the DSDT and FACS tables.
|
||||
*
|
||||
* Get a local copy of the FADT and convert it to a common format
|
||||
* Map entire FADT, assumed to be smaller than one page.
|
||||
*/
|
||||
length = acpi_gbl_root_table_list.tables[table_index].length;
|
||||
|
||||
table =
|
||||
acpi_os_map_memory(acpi_gbl_root_table_list.tables[table_index].
|
||||
address, length);
|
||||
if (!table) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate the FADT checksum before we copy the table. Ignore
|
||||
* checksum error as we want to try to get the DSDT and FACS.
|
||||
*/
|
||||
(void)acpi_tb_verify_checksum(table, length);
|
||||
|
||||
/* Obtain a local copy of the FADT in common ACPI 2.0+ format */
|
||||
|
||||
acpi_tb_create_local_fadt(table, length);
|
||||
|
||||
/* All done with the real FADT, unmap it */
|
||||
|
||||
acpi_os_unmap_memory(table, length);
|
||||
|
||||
/* Obtain the DSDT and FACS tables via their addresses within the FADT */
|
||||
|
||||
acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt,
|
||||
flags, ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT);
|
||||
|
||||
acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xfacs,
|
||||
flags, ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_create_local_fadt
|
||||
*
|
||||
* PARAMETERS: Table - Pointer to BIOS FADT
|
||||
* Length - Length of the table
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Get a local copy of the FADT and convert it to a common format.
|
||||
* Performs validation on some important FADT fields.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
|
||||
{
|
||||
|
||||
/*
|
||||
* Check if the FADT is larger than what we know about (ACPI 2.0 version).
|
||||
* Truncate the table, but make some noise.
|
||||
*/
|
||||
if (length > sizeof(struct acpi_table_fadt)) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"FADT (revision %u) is longer than ACPI 2.0 version, truncating length 0x%X to 0x%zX",
|
||||
table->revision, (unsigned)length,
|
||||
sizeof(struct acpi_table_fadt)));
|
||||
}
|
||||
|
||||
/* Copy the entire FADT locally. Zero first for tb_convert_fadt */
|
||||
|
||||
ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt));
|
||||
|
||||
ACPI_MEMCPY(&acpi_gbl_FADT, table,
|
||||
ACPI_MIN(length, sizeof(struct acpi_table_fadt)));
|
||||
|
||||
/*
|
||||
* 1) Convert the local copy of the FADT to the common internal format
|
||||
* 2) Validate some of the important values within the FADT
|
||||
*/
|
||||
acpi_tb_convert_fadt();
|
||||
acpi_tb_validate_fadt();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_convert_fadt
|
||||
*
|
||||
* PARAMETERS: None, uses acpi_gbl_FADT
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Converts all versions of the FADT to a common internal format.
|
||||
* -> Expand all 32-bit addresses to 64-bit.
|
||||
*
|
||||
* NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt),
|
||||
* and must contain a copy of the actual FADT.
|
||||
*
|
||||
* ACPICA will use the "X" fields of the FADT for all addresses.
|
||||
*
|
||||
* "X" fields are optional extensions to the original V1.0 fields. Even if
|
||||
* they are present in the structure, they can be optionally not used by
|
||||
* setting them to zero. Therefore, we must selectively expand V1.0 fields
|
||||
* if the corresponding X field is zero.
|
||||
*
|
||||
* For ACPI 1.0 FADTs, all address fields are expanded to the corresponding
|
||||
* "X" fields.
|
||||
*
|
||||
* For ACPI 2.0 FADTs, any "X" fields that are NULL are filled in by
|
||||
* expanding the corresponding ACPI 1.0 field.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void acpi_tb_convert_fadt(void)
|
||||
{
|
||||
u8 pm1_register_length;
|
||||
struct acpi_generic_address *target;
|
||||
acpi_native_uint i;
|
||||
|
||||
/* Update the local FADT table header length */
|
||||
|
||||
acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt);
|
||||
|
||||
/* Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary */
|
||||
|
||||
if (!acpi_gbl_FADT.Xfacs) {
|
||||
acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs;
|
||||
}
|
||||
|
||||
if (!acpi_gbl_FADT.Xdsdt) {
|
||||
acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand the 32-bit V1.0 addresses to the 64-bit "X" generic address
|
||||
* structures as necessary.
|
||||
*/
|
||||
for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
|
||||
target =
|
||||
ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT,
|
||||
fadt_info_table[i].target);
|
||||
|
||||
/* Expand only if the X target is null */
|
||||
|
||||
if (!target->address) {
|
||||
acpi_tb_init_generic_address(target,
|
||||
*ACPI_ADD_PTR(u8,
|
||||
&acpi_gbl_FADT,
|
||||
fadt_info_table
|
||||
[i].length),
|
||||
(u64) * ACPI_ADD_PTR(u32,
|
||||
&acpi_gbl_FADT,
|
||||
fadt_info_table
|
||||
[i].
|
||||
source));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate separate GAS structs for the PM1 Enable registers.
|
||||
* These addresses do not appear (directly) in the FADT, so it is
|
||||
* useful to calculate them once, here.
|
||||
*
|
||||
* The PM event blocks are split into two register blocks, first is the
|
||||
* PM Status Register block, followed immediately by the PM Enable Register
|
||||
* block. Each is of length (pm1_event_length/2)
|
||||
*/
|
||||
pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length);
|
||||
|
||||
/* The PM1A register block is required */
|
||||
|
||||
acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable,
|
||||
pm1_register_length,
|
||||
(acpi_gbl_FADT.xpm1a_event_block.address +
|
||||
pm1_register_length));
|
||||
/* Don't forget to copy space_id of the GAS */
|
||||
acpi_gbl_xpm1a_enable.space_id = acpi_gbl_FADT.xpm1a_event_block.space_id;
|
||||
|
||||
/* The PM1B register block is optional, ignore if not present */
|
||||
|
||||
if (acpi_gbl_FADT.xpm1b_event_block.address) {
|
||||
acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
|
||||
pm1_register_length,
|
||||
(acpi_gbl_FADT.xpm1b_event_block.
|
||||
address + pm1_register_length));
|
||||
/* Don't forget to copy space_id of the GAS */
|
||||
acpi_gbl_xpm1b_enable.space_id = acpi_gbl_FADT.xpm1a_event_block.space_id;
|
||||
|
||||
}
|
||||
/*
|
||||
* _CST object and C States change notification start with
|
||||
* ACPI 2.0 (FADT r3). Although the field should be Reserved
|
||||
* and 0 before then, some pre-r3 FADT set this field and
|
||||
* it results in SMM-related boot failures. For them, clear it.
|
||||
*/
|
||||
if ((acpi_gbl_FADT.header.revision < 3) &&
|
||||
(acpi_gbl_FADT.cst_control != 0)) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"Ignoring BIOS FADT r%u C-state control",
|
||||
acpi_gbl_FADT.header.revision));
|
||||
acpi_gbl_FADT.cst_control = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_validate_fadt
|
||||
*
|
||||
* PARAMETERS: Table - Pointer to the FADT to be validated
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Validate various important fields within the FADT. If a problem
|
||||
* is found, issue a message, but no status is returned.
|
||||
* Used by both the table manager and the disassembler.
|
||||
*
|
||||
* Possible additional checks:
|
||||
* (acpi_gbl_FADT.pm1_event_length >= 4)
|
||||
* (acpi_gbl_FADT.pm1_control_length >= 2)
|
||||
* (acpi_gbl_FADT.pm_timer_length >= 4)
|
||||
* Gpe block lengths must be multiple of 2
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void acpi_tb_validate_fadt(void)
|
||||
{
|
||||
u32 *address32;
|
||||
struct acpi_generic_address *address64;
|
||||
u8 length;
|
||||
acpi_native_uint i;
|
||||
|
||||
/* Examine all of the 64-bit extended address fields (X fields) */
|
||||
|
||||
for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
|
||||
|
||||
/* Generate pointers to the 32-bit and 64-bit addresses and get the length */
|
||||
|
||||
address64 =
|
||||
ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT,
|
||||
fadt_info_table[i].target);
|
||||
address32 =
|
||||
ACPI_ADD_PTR(u32, &acpi_gbl_FADT,
|
||||
fadt_info_table[i].source);
|
||||
length =
|
||||
*ACPI_ADD_PTR(u8, &acpi_gbl_FADT,
|
||||
fadt_info_table[i].length);
|
||||
|
||||
if (fadt_info_table[i].type & ACPI_FADT_REQUIRED) {
|
||||
/*
|
||||
* Field is required (Pm1a_event, Pm1a_control, pm_timer).
|
||||
* Both the address and length must be non-zero.
|
||||
*/
|
||||
if (!address64->address || !length) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Required field \"%s\" has zero address and/or length: %8.8X%8.8X/%X",
|
||||
fadt_info_table[i].name,
|
||||
ACPI_FORMAT_UINT64(address64->
|
||||
address),
|
||||
length));
|
||||
}
|
||||
} else if (fadt_info_table[i].type & ACPI_FADT_SEPARATE_LENGTH) {
|
||||
/*
|
||||
* Field is optional (PM2Control, GPE0, GPE1) AND has its own
|
||||
* length field. If present, both the address and length must be valid.
|
||||
*/
|
||||
if ((address64->address && !length)
|
||||
|| (!address64->address && length)) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"Optional field \"%s\" has zero address or length: %8.8X%8.8X/%X",
|
||||
fadt_info_table[i].name,
|
||||
ACPI_FORMAT_UINT64(address64->
|
||||
address),
|
||||
length));
|
||||
}
|
||||
}
|
||||
|
||||
/* If both 32- and 64-bit addresses are valid (non-zero), they must match */
|
||||
|
||||
if (address64->address && *address32 &&
|
||||
(address64->address != (u64) * address32)) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"32/64X address mismatch in \"%s\": [%8.8X] [%8.8X%8.8X], using 64X",
|
||||
fadt_info_table[i].name, *address32,
|
||||
ACPI_FORMAT_UINT64(address64->address)));
|
||||
}
|
||||
}
|
||||
}
|
||||
126
drivers/acpi/tables/tbfind.c
Normal file
126
drivers/acpi/tables/tbfind.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: tbfind - find table
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2007, R. Byron Moore
|
||||
* 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 <acpi/acpi.h>
|
||||
#include <acpi/actables.h>
|
||||
|
||||
#define _COMPONENT ACPI_TABLES
|
||||
ACPI_MODULE_NAME("tbfind")
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_find_table
|
||||
*
|
||||
* PARAMETERS: Signature - String with ACPI table signature
|
||||
* oem_id - String with the table OEM ID
|
||||
* oem_table_id - String with the OEM Table ID
|
||||
* table_index - Where the table index is returned
|
||||
*
|
||||
* RETURN: Status and table index
|
||||
*
|
||||
* DESCRIPTION: Find an ACPI table (in the RSDT/XSDT) that matches the
|
||||
* Signature, OEM ID and OEM Table ID. Returns an index that can
|
||||
* be used to get the table header or entire table.
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status
|
||||
acpi_tb_find_table(char *signature,
|
||||
char *oem_id,
|
||||
char *oem_table_id, acpi_native_uint * table_index)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
acpi_status status;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_find_table);
|
||||
|
||||
for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
|
||||
if (ACPI_MEMCMP(&(acpi_gbl_root_table_list.tables[i].signature),
|
||||
signature, ACPI_NAME_SIZE)) {
|
||||
|
||||
/* Not the requested table */
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Table with matching signature has been found */
|
||||
|
||||
if (!acpi_gbl_root_table_list.tables[i].pointer) {
|
||||
|
||||
/* Table is not currently mapped, map it */
|
||||
|
||||
status =
|
||||
acpi_tb_verify_table(&acpi_gbl_root_table_list.
|
||||
tables[i]);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
if (!acpi_gbl_root_table_list.tables[i].pointer) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for table match on all IDs */
|
||||
|
||||
if (!ACPI_MEMCMP
|
||||
(acpi_gbl_root_table_list.tables[i].pointer->signature,
|
||||
signature, ACPI_NAME_SIZE) && (!oem_id[0]
|
||||
||
|
||||
!ACPI_MEMCMP
|
||||
(acpi_gbl_root_table_list.
|
||||
tables[i].pointer->oem_id,
|
||||
oem_id, ACPI_OEM_ID_SIZE))
|
||||
&& (!oem_table_id[0]
|
||||
|| !ACPI_MEMCMP(acpi_gbl_root_table_list.tables[i].
|
||||
pointer->oem_table_id, oem_table_id,
|
||||
ACPI_OEM_TABLE_ID_SIZE))) {
|
||||
*table_index = i;
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
|
||||
"Found table [%4.4s]\n", signature));
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(AE_NOT_FOUND);
|
||||
}
|
||||
539
drivers/acpi/tables/tbinstal.c
Normal file
539
drivers/acpi/tables/tbinstal.c
Normal file
@@ -0,0 +1,539 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: tbinstal - ACPI table installation and removal
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2007, R. Byron Moore
|
||||
* 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 <acpi/acpi.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
#include <acpi/actables.h>
|
||||
|
||||
#define _COMPONENT ACPI_TABLES
|
||||
ACPI_MODULE_NAME("tbinstal")
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_verify_table
|
||||
*
|
||||
* PARAMETERS: table_desc - table
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: this function is called to verify and map table
|
||||
*
|
||||
*****************************************************************************/
|
||||
acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_verify_table);
|
||||
|
||||
/* Map the table if necessary */
|
||||
|
||||
if (!table_desc->pointer) {
|
||||
if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) ==
|
||||
ACPI_TABLE_ORIGIN_MAPPED) {
|
||||
table_desc->pointer =
|
||||
acpi_os_map_memory(table_desc->address,
|
||||
table_desc->length);
|
||||
}
|
||||
if (!table_desc->pointer) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
/* FACS is the odd table, has no standard ACPI header and no checksum */
|
||||
|
||||
if (!ACPI_COMPARE_NAME(&table_desc->signature, ACPI_SIG_FACS)) {
|
||||
|
||||
/* Always calculate checksum, ignore bad checksum if requested */
|
||||
|
||||
status =
|
||||
acpi_tb_verify_checksum(table_desc->pointer,
|
||||
table_desc->length);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_add_table
|
||||
*
|
||||
* PARAMETERS: table_desc - Table descriptor
|
||||
* table_index - Where the table index is returned
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: This function is called to add the ACPI table
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_tb_add_table(struct acpi_table_desc *table_desc,
|
||||
acpi_native_uint * table_index)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
acpi_native_uint length;
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_add_table);
|
||||
|
||||
if (!table_desc->pointer) {
|
||||
status = acpi_tb_verify_table(table_desc);
|
||||
if (ACPI_FAILURE(status) || !table_desc->pointer) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
}
|
||||
|
||||
/* The table must be either an SSDT or a PSDT */
|
||||
|
||||
if ((!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT))
|
||||
&&
|
||||
(!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)))
|
||||
{
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Table has invalid signature [%4.4s], must be SSDT or PSDT",
|
||||
table_desc->pointer->signature));
|
||||
return_ACPI_STATUS(AE_BAD_SIGNATURE);
|
||||
}
|
||||
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
|
||||
/* Check if table is already registered */
|
||||
|
||||
for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
|
||||
if (!acpi_gbl_root_table_list.tables[i].pointer) {
|
||||
status =
|
||||
acpi_tb_verify_table(&acpi_gbl_root_table_list.
|
||||
tables[i]);
|
||||
if (ACPI_FAILURE(status)
|
||||
|| !acpi_gbl_root_table_list.tables[i].pointer) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
length = ACPI_MIN(table_desc->length,
|
||||
acpi_gbl_root_table_list.tables[i].length);
|
||||
if (ACPI_MEMCMP(table_desc->pointer,
|
||||
acpi_gbl_root_table_list.tables[i].pointer,
|
||||
length)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Table is already registered */
|
||||
|
||||
acpi_tb_delete_table(table_desc);
|
||||
*table_index = i;
|
||||
goto release;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the table to the global table list
|
||||
*/
|
||||
status = acpi_tb_store_table(table_desc->address, table_desc->pointer,
|
||||
table_desc->length, table_desc->flags,
|
||||
table_index);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto release;
|
||||
}
|
||||
|
||||
acpi_tb_print_table_header(table_desc->address, table_desc->pointer);
|
||||
|
||||
release:
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_resize_root_table_list
|
||||
*
|
||||
* PARAMETERS: None
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Expand the size of global table array
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_tb_resize_root_table_list(void)
|
||||
{
|
||||
struct acpi_table_desc *tables;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
|
||||
|
||||
/* allow_resize flag is a parameter to acpi_initialize_tables */
|
||||
|
||||
if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Resize of Root Table Array is not allowed"));
|
||||
return_ACPI_STATUS(AE_SUPPORT);
|
||||
}
|
||||
|
||||
/* Increase the Table Array size */
|
||||
|
||||
tables = ACPI_ALLOCATE_ZEROED((acpi_gbl_root_table_list.size +
|
||||
ACPI_ROOT_TABLE_SIZE_INCREMENT)
|
||||
* sizeof(struct acpi_table_desc));
|
||||
if (!tables) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Could not allocate new root table array"));
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Copy and free the previous table array */
|
||||
|
||||
if (acpi_gbl_root_table_list.tables) {
|
||||
ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
|
||||
acpi_gbl_root_table_list.size *
|
||||
sizeof(struct acpi_table_desc));
|
||||
|
||||
if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
|
||||
ACPI_FREE(acpi_gbl_root_table_list.tables);
|
||||
}
|
||||
}
|
||||
|
||||
acpi_gbl_root_table_list.tables = tables;
|
||||
acpi_gbl_root_table_list.size += ACPI_ROOT_TABLE_SIZE_INCREMENT;
|
||||
acpi_gbl_root_table_list.flags |= (u8) ACPI_ROOT_ORIGIN_ALLOCATED;
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_store_table
|
||||
*
|
||||
* PARAMETERS: Address - Table address
|
||||
* Table - Table header
|
||||
* Length - Table length
|
||||
* Flags - flags
|
||||
*
|
||||
* RETURN: Status and table index.
|
||||
*
|
||||
* DESCRIPTION: Add an ACPI table to the global table list
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_tb_store_table(acpi_physical_address address,
|
||||
struct acpi_table_header *table,
|
||||
u32 length, u8 flags, acpi_native_uint * table_index)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
/* Ensure that there is room for the table in the Root Table List */
|
||||
|
||||
if (acpi_gbl_root_table_list.count >= acpi_gbl_root_table_list.size) {
|
||||
status = acpi_tb_resize_root_table_list();
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize added table */
|
||||
|
||||
acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
|
||||
address = address;
|
||||
acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
|
||||
pointer = table;
|
||||
acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].length =
|
||||
length;
|
||||
acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
|
||||
owner_id = 0;
|
||||
acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].flags =
|
||||
flags;
|
||||
|
||||
ACPI_MOVE_32_TO_32(&
|
||||
(acpi_gbl_root_table_list.
|
||||
tables[acpi_gbl_root_table_list.count].signature),
|
||||
table->signature);
|
||||
|
||||
*table_index = acpi_gbl_root_table_list.count;
|
||||
acpi_gbl_root_table_list.count++;
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_delete_table
|
||||
*
|
||||
* PARAMETERS: table_index - Table index
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Delete one internal ACPI table
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void acpi_tb_delete_table(struct acpi_table_desc *table_desc)
|
||||
{
|
||||
/* Table must be mapped or allocated */
|
||||
if (!table_desc->pointer) {
|
||||
return;
|
||||
}
|
||||
switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
|
||||
case ACPI_TABLE_ORIGIN_MAPPED:
|
||||
acpi_os_unmap_memory(table_desc->pointer, table_desc->length);
|
||||
break;
|
||||
case ACPI_TABLE_ORIGIN_ALLOCATED:
|
||||
ACPI_FREE(table_desc->pointer);
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
|
||||
table_desc->pointer = NULL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_terminate
|
||||
*
|
||||
* PARAMETERS: None
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Delete all internal ACPI tables
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void acpi_tb_terminate(void)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_terminate);
|
||||
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
|
||||
/* Delete the individual tables */
|
||||
|
||||
for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
|
||||
acpi_tb_delete_table(&acpi_gbl_root_table_list.tables[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete the root table array if allocated locally. Array cannot be
|
||||
* mapped, so we don't need to check for that flag.
|
||||
*/
|
||||
if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
|
||||
ACPI_FREE(acpi_gbl_root_table_list.tables);
|
||||
}
|
||||
|
||||
acpi_gbl_root_table_list.tables = NULL;
|
||||
acpi_gbl_root_table_list.flags = 0;
|
||||
acpi_gbl_root_table_list.count = 0;
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_delete_namespace_by_owner
|
||||
*
|
||||
* PARAMETERS: table_index - Table index
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Delete all namespace objects created when this table was loaded.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void acpi_tb_delete_namespace_by_owner(acpi_native_uint table_index)
|
||||
{
|
||||
acpi_owner_id owner_id;
|
||||
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
if (table_index < acpi_gbl_root_table_list.count) {
|
||||
owner_id =
|
||||
acpi_gbl_root_table_list.tables[table_index].owner_id;
|
||||
} else {
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
return;
|
||||
}
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
acpi_ns_delete_namespace_by_owner(owner_id);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_allocate_owner_id
|
||||
*
|
||||
* PARAMETERS: table_index - Table index
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Allocates owner_id in table_desc
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_tb_allocate_owner_id(acpi_native_uint table_index)
|
||||
{
|
||||
acpi_status status = AE_BAD_PARAMETER;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
|
||||
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
if (table_index < acpi_gbl_root_table_list.count) {
|
||||
status = acpi_ut_allocate_owner_id
|
||||
(&(acpi_gbl_root_table_list.tables[table_index].owner_id));
|
||||
}
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_release_owner_id
|
||||
*
|
||||
* PARAMETERS: table_index - Table index
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Releases owner_id in table_desc
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_tb_release_owner_id(acpi_native_uint table_index)
|
||||
{
|
||||
acpi_status status = AE_BAD_PARAMETER;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_release_owner_id);
|
||||
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
if (table_index < acpi_gbl_root_table_list.count) {
|
||||
acpi_ut_release_owner_id(&
|
||||
(acpi_gbl_root_table_list.
|
||||
tables[table_index].owner_id));
|
||||
status = AE_OK;
|
||||
}
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_get_owner_id
|
||||
*
|
||||
* PARAMETERS: table_index - Table index
|
||||
* owner_id - Where the table owner_id is returned
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: returns owner_id for the ACPI table
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_tb_get_owner_id(acpi_native_uint table_index, acpi_owner_id * owner_id)
|
||||
{
|
||||
acpi_status status = AE_BAD_PARAMETER;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_get_owner_id);
|
||||
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
if (table_index < acpi_gbl_root_table_list.count) {
|
||||
*owner_id =
|
||||
acpi_gbl_root_table_list.tables[table_index].owner_id;
|
||||
status = AE_OK;
|
||||
}
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_is_table_loaded
|
||||
*
|
||||
* PARAMETERS: table_index - Table index
|
||||
*
|
||||
* RETURN: Table Loaded Flag
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
u8 acpi_tb_is_table_loaded(acpi_native_uint table_index)
|
||||
{
|
||||
u8 is_loaded = FALSE;
|
||||
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
if (table_index < acpi_gbl_root_table_list.count) {
|
||||
is_loaded = (u8)
|
||||
(acpi_gbl_root_table_list.tables[table_index].
|
||||
flags & ACPI_TABLE_IS_LOADED);
|
||||
}
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
return (is_loaded);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_set_table_loaded_flag
|
||||
*
|
||||
* PARAMETERS: table_index - Table index
|
||||
* is_loaded - TRUE if table is loaded, FALSE otherwise
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void acpi_tb_set_table_loaded_flag(acpi_native_uint table_index, u8 is_loaded)
|
||||
{
|
||||
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
if (table_index < acpi_gbl_root_table_list.count) {
|
||||
if (is_loaded) {
|
||||
acpi_gbl_root_table_list.tables[table_index].flags |=
|
||||
ACPI_TABLE_IS_LOADED;
|
||||
} else {
|
||||
acpi_gbl_root_table_list.tables[table_index].flags &=
|
||||
~ACPI_TABLE_IS_LOADED;
|
||||
}
|
||||
}
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
}
|
||||
487
drivers/acpi/tables/tbutils.c
Normal file
487
drivers/acpi/tables/tbutils.c
Normal file
@@ -0,0 +1,487 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: tbutils - table utilities
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2007, R. Byron Moore
|
||||
* 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 <acpi/acpi.h>
|
||||
#include <acpi/actables.h>
|
||||
|
||||
#define _COMPONENT ACPI_TABLES
|
||||
ACPI_MODULE_NAME("tbutils")
|
||||
|
||||
/* Local prototypes */
|
||||
static acpi_physical_address
|
||||
acpi_tb_get_root_table_entry(u8 * table_entry,
|
||||
acpi_native_uint table_entry_size);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_tables_loaded
|
||||
*
|
||||
* PARAMETERS: None
|
||||
*
|
||||
* RETURN: TRUE if required ACPI tables are loaded
|
||||
*
|
||||
* DESCRIPTION: Determine if the minimum required ACPI tables are present
|
||||
* (FADT, FACS, DSDT)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
u8 acpi_tb_tables_loaded(void)
|
||||
{
|
||||
|
||||
if (acpi_gbl_root_table_list.count >= 3) {
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_print_table_header
|
||||
*
|
||||
* PARAMETERS: Address - Table physical address
|
||||
* Header - Table header
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_tb_print_table_header(acpi_physical_address address,
|
||||
struct acpi_table_header *header)
|
||||
{
|
||||
|
||||
if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) {
|
||||
|
||||
/* FACS only has signature and length fields of common table header */
|
||||
|
||||
ACPI_INFO((AE_INFO, "%4.4s %08lX, %04X",
|
||||
header->signature, (unsigned long)address,
|
||||
header->length));
|
||||
} else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) {
|
||||
|
||||
/* RSDP has no common fields */
|
||||
|
||||
ACPI_INFO((AE_INFO, "RSDP %08lX, %04X (r%d %6.6s)",
|
||||
(unsigned long)address,
|
||||
(ACPI_CAST_PTR(struct acpi_table_rsdp, header)->
|
||||
revision >
|
||||
0) ? ACPI_CAST_PTR(struct acpi_table_rsdp,
|
||||
header)->length : 20,
|
||||
ACPI_CAST_PTR(struct acpi_table_rsdp,
|
||||
header)->revision,
|
||||
ACPI_CAST_PTR(struct acpi_table_rsdp,
|
||||
header)->oem_id));
|
||||
} else {
|
||||
/* Standard ACPI table with full common header */
|
||||
|
||||
ACPI_INFO((AE_INFO,
|
||||
"%4.4s %08lX, %04X (r%d %6.6s %8.8s %8X %4.4s %8X)",
|
||||
header->signature, (unsigned long)address,
|
||||
header->length, header->revision, header->oem_id,
|
||||
header->oem_table_id, header->oem_revision,
|
||||
header->asl_compiler_id,
|
||||
header->asl_compiler_revision));
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_validate_checksum
|
||||
*
|
||||
* PARAMETERS: Table - ACPI table to verify
|
||||
* Length - Length of entire table
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Verifies that the table checksums to zero. Optionally returns
|
||||
* exception on bad checksum.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length)
|
||||
{
|
||||
u8 checksum;
|
||||
|
||||
/* Compute the checksum on the table */
|
||||
|
||||
checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length);
|
||||
|
||||
/* Checksum ok? (should be zero) */
|
||||
|
||||
if (checksum) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"Incorrect checksum in table [%4.4s] - %2.2X, should be %2.2X",
|
||||
table->signature, table->checksum,
|
||||
(u8) (table->checksum - checksum)));
|
||||
|
||||
#if (ACPI_CHECKSUM_ABORT)
|
||||
|
||||
return (AE_BAD_CHECKSUM);
|
||||
#endif
|
||||
}
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_checksum
|
||||
*
|
||||
* PARAMETERS: Buffer - Pointer to memory region to be checked
|
||||
* Length - Length of this memory region
|
||||
*
|
||||
* RETURN: Checksum (u8)
|
||||
*
|
||||
* DESCRIPTION: Calculates circular checksum of memory region.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
u8 acpi_tb_checksum(u8 * buffer, acpi_native_uint length)
|
||||
{
|
||||
u8 sum = 0;
|
||||
u8 *end = buffer + length;
|
||||
|
||||
while (buffer < end) {
|
||||
sum = (u8) (sum + *(buffer++));
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_install_table
|
||||
*
|
||||
* PARAMETERS: Address - Physical address of DSDT or FACS
|
||||
* Flags - Flags
|
||||
* Signature - Table signature, NULL if no need to
|
||||
* match
|
||||
* table_index - Index into root table array
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Install an ACPI table into the global data structure.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_tb_install_table(acpi_physical_address address,
|
||||
u8 flags, char *signature, acpi_native_uint table_index)
|
||||
{
|
||||
struct acpi_table_header *table;
|
||||
|
||||
if (!address) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Null physical address for ACPI table [%s]",
|
||||
signature));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Map just the table header */
|
||||
|
||||
table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
|
||||
if (!table) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If a particular signature is expected, signature must match */
|
||||
|
||||
if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Invalid signature 0x%X for ACPI table [%s]",
|
||||
*ACPI_CAST_PTR(u32, table->signature), signature));
|
||||
goto unmap_and_exit;
|
||||
}
|
||||
|
||||
/* Initialize the table entry */
|
||||
|
||||
acpi_gbl_root_table_list.tables[table_index].address = address;
|
||||
acpi_gbl_root_table_list.tables[table_index].length = table->length;
|
||||
acpi_gbl_root_table_list.tables[table_index].flags = flags;
|
||||
|
||||
ACPI_MOVE_32_TO_32(&
|
||||
(acpi_gbl_root_table_list.tables[table_index].
|
||||
signature), table->signature);
|
||||
|
||||
acpi_tb_print_table_header(address, table);
|
||||
|
||||
if (table_index == ACPI_TABLE_INDEX_DSDT) {
|
||||
|
||||
/* Global integer width is based upon revision of the DSDT */
|
||||
|
||||
acpi_ut_set_integer_width(table->revision);
|
||||
}
|
||||
|
||||
unmap_and_exit:
|
||||
acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_get_root_table_entry
|
||||
*
|
||||
* PARAMETERS: table_entry - Pointer to the RSDT/XSDT table entry
|
||||
* table_entry_size - sizeof 32 or 64 (RSDT or XSDT)
|
||||
*
|
||||
* RETURN: Physical address extracted from the root table
|
||||
*
|
||||
* DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on
|
||||
* both 32-bit and 64-bit platforms
|
||||
*
|
||||
* NOTE: acpi_physical_address is 32-bit on 32-bit platforms, 64-bit on
|
||||
* 64-bit platforms.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static acpi_physical_address
|
||||
acpi_tb_get_root_table_entry(u8 * table_entry,
|
||||
acpi_native_uint table_entry_size)
|
||||
{
|
||||
u64 address64;
|
||||
|
||||
/*
|
||||
* Get the table physical address (32-bit for RSDT, 64-bit for XSDT):
|
||||
* Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT
|
||||
*/
|
||||
if (table_entry_size == sizeof(u32)) {
|
||||
/*
|
||||
* 32-bit platform, RSDT: Return 32-bit table entry
|
||||
* 64-bit platform, RSDT: Expand 32-bit to 64-bit and return
|
||||
*/
|
||||
return ((acpi_physical_address)
|
||||
(*ACPI_CAST_PTR(u32, table_entry)));
|
||||
} else {
|
||||
/*
|
||||
* 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return
|
||||
* 64-bit platform, XSDT: Move (unaligned) 64-bit to local, return 64-bit
|
||||
*/
|
||||
ACPI_MOVE_64_TO_64(&address64, table_entry);
|
||||
|
||||
#if ACPI_MACHINE_WIDTH == 32
|
||||
if (address64 > ACPI_UINT32_MAX) {
|
||||
|
||||
/* Will truncate 64-bit address to 32 bits, issue warning */
|
||||
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"64-bit Physical Address in XSDT is too large (%8.8X%8.8X), truncating",
|
||||
ACPI_FORMAT_UINT64(address64)));
|
||||
}
|
||||
#endif
|
||||
return ((acpi_physical_address) (address64));
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_parse_root_table
|
||||
*
|
||||
* PARAMETERS: Rsdp - Pointer to the RSDP
|
||||
* Flags - Flags
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: This function is called to parse the Root System Description
|
||||
* Table (RSDT or XSDT)
|
||||
*
|
||||
* NOTE: Tables are mapped (not copied) for efficiency. The FACS must
|
||||
* be mapped and cannot be copied because it contains the actual
|
||||
* memory location of the ACPI Global Lock.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status __init
|
||||
acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
|
||||
{
|
||||
struct acpi_table_rsdp *rsdp;
|
||||
acpi_native_uint table_entry_size;
|
||||
acpi_native_uint i;
|
||||
u32 table_count;
|
||||
struct acpi_table_header *table;
|
||||
acpi_physical_address address;
|
||||
u32 length;
|
||||
u8 *table_entry;
|
||||
acpi_status status;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_parse_root_table);
|
||||
|
||||
/*
|
||||
* Map the entire RSDP and extract the address of the RSDT or XSDT
|
||||
*/
|
||||
rsdp = acpi_os_map_memory(rsdp_address, sizeof(struct acpi_table_rsdp));
|
||||
if (!rsdp) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
acpi_tb_print_table_header(rsdp_address,
|
||||
ACPI_CAST_PTR(struct acpi_table_header,
|
||||
rsdp));
|
||||
|
||||
/* Differentiate between RSDT and XSDT root tables */
|
||||
|
||||
if (rsdp->revision > 1 && rsdp->xsdt_physical_address) {
|
||||
/*
|
||||
* Root table is an XSDT (64-bit physical addresses). We must use the
|
||||
* XSDT if the revision is > 1 and the XSDT pointer is present, as per
|
||||
* the ACPI specification.
|
||||
*/
|
||||
address = (acpi_physical_address) rsdp->xsdt_physical_address;
|
||||
table_entry_size = sizeof(u64);
|
||||
} else {
|
||||
/* Root table is an RSDT (32-bit physical addresses) */
|
||||
|
||||
address = (acpi_physical_address) rsdp->rsdt_physical_address;
|
||||
table_entry_size = sizeof(u32);
|
||||
}
|
||||
|
||||
/*
|
||||
* It is not possible to map more than one entry in some environments,
|
||||
* so unmap the RSDP here before mapping other tables
|
||||
*/
|
||||
acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp));
|
||||
|
||||
/* Map the RSDT/XSDT table header to get the full table length */
|
||||
|
||||
table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
|
||||
if (!table) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
acpi_tb_print_table_header(address, table);
|
||||
|
||||
/* Get the length of the full table, verify length and map entire table */
|
||||
|
||||
length = table->length;
|
||||
acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
|
||||
|
||||
if (length < sizeof(struct acpi_table_header)) {
|
||||
ACPI_ERROR((AE_INFO, "Invalid length 0x%X in RSDT/XSDT",
|
||||
length));
|
||||
return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
|
||||
}
|
||||
|
||||
table = acpi_os_map_memory(address, length);
|
||||
if (!table) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Validate the root table checksum */
|
||||
|
||||
status = acpi_tb_verify_checksum(table, length);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
acpi_os_unmap_memory(table, length);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/* Calculate the number of tables described in the root table */
|
||||
|
||||
table_count =
|
||||
(u32) ((table->length -
|
||||
sizeof(struct acpi_table_header)) / table_entry_size);
|
||||
|
||||
/*
|
||||
* First two entries in the table array are reserved for the DSDT and FACS,
|
||||
* which are not actually present in the RSDT/XSDT - they come from the FADT
|
||||
*/
|
||||
table_entry =
|
||||
ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header);
|
||||
acpi_gbl_root_table_list.count = 2;
|
||||
|
||||
/*
|
||||
* Initialize the root table array from the RSDT/XSDT
|
||||
*/
|
||||
for (i = 0; i < table_count; i++) {
|
||||
if (acpi_gbl_root_table_list.count >=
|
||||
acpi_gbl_root_table_list.size) {
|
||||
|
||||
/* There is no more room in the root table array, attempt resize */
|
||||
|
||||
status = acpi_tb_resize_root_table_list();
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"Truncating %u table entries!",
|
||||
(unsigned)
|
||||
(acpi_gbl_root_table_list.size -
|
||||
acpi_gbl_root_table_list.
|
||||
count)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */
|
||||
|
||||
acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
|
||||
address =
|
||||
acpi_tb_get_root_table_entry(table_entry, table_entry_size);
|
||||
|
||||
table_entry += table_entry_size;
|
||||
acpi_gbl_root_table_list.count++;
|
||||
}
|
||||
|
||||
/*
|
||||
* It is not possible to map more than one entry in some environments,
|
||||
* so unmap the root table here before mapping other tables
|
||||
*/
|
||||
acpi_os_unmap_memory(table, length);
|
||||
|
||||
/*
|
||||
* Complete the initialization of the root table array by examining
|
||||
* the header of each table
|
||||
*/
|
||||
for (i = 2; i < acpi_gbl_root_table_list.count; i++) {
|
||||
acpi_tb_install_table(acpi_gbl_root_table_list.tables[i].
|
||||
address, flags, NULL, i);
|
||||
|
||||
/* Special case for FADT - get the DSDT and FACS */
|
||||
|
||||
if (ACPI_COMPARE_NAME
|
||||
(&acpi_gbl_root_table_list.tables[i].signature,
|
||||
ACPI_SIG_FADT)) {
|
||||
acpi_tb_parse_fadt(i, flags);
|
||||
}
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
624
drivers/acpi/tables/tbxface.c
Normal file
624
drivers/acpi/tables/tbxface.c
Normal file
@@ -0,0 +1,624 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: tbxface - Public interfaces to the ACPI subsystem
|
||||
* ACPI table oriented interfaces
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2007, R. Byron Moore
|
||||
* 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 <acpi/acpi.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
#include <acpi/actables.h>
|
||||
|
||||
#define _COMPONENT ACPI_TABLES
|
||||
ACPI_MODULE_NAME("tbxface")
|
||||
|
||||
/* Local prototypes */
|
||||
static acpi_status acpi_tb_load_namespace(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_allocate_root_table
|
||||
*
|
||||
* PARAMETERS: initial_table_count - Size of initial_table_array, in number of
|
||||
* struct acpi_table_desc structures
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Allocate a root table array. Used by i_aSL compiler and
|
||||
* acpi_initialize_tables.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_allocate_root_table(u32 initial_table_count)
|
||||
{
|
||||
|
||||
acpi_gbl_root_table_list.size = initial_table_count;
|
||||
acpi_gbl_root_table_list.flags = ACPI_ROOT_ALLOW_RESIZE;
|
||||
|
||||
return (acpi_tb_resize_root_table_list());
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_initialize_tables
|
||||
*
|
||||
* PARAMETERS: initial_table_array - Pointer to an array of pre-allocated
|
||||
* struct acpi_table_desc structures. If NULL, the
|
||||
* array is dynamically allocated.
|
||||
* initial_table_count - Size of initial_table_array, in number of
|
||||
* struct acpi_table_desc structures
|
||||
* allow_realloc - Flag to tell Table Manager if resize of
|
||||
* pre-allocated array is allowed. Ignored
|
||||
* if initial_table_array is NULL.
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT.
|
||||
*
|
||||
* NOTE: Allows static allocation of the initial table array in order
|
||||
* to avoid the use of dynamic memory in confined environments
|
||||
* such as the kernel boot sequence where it may not be available.
|
||||
*
|
||||
* If the host OS memory managers are initialized, use NULL for
|
||||
* initial_table_array, and the table will be dynamically allocated.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status __init
|
||||
acpi_initialize_tables(struct acpi_table_desc * initial_table_array,
|
||||
u32 initial_table_count, u8 allow_resize)
|
||||
{
|
||||
acpi_physical_address rsdp_address;
|
||||
acpi_status status;
|
||||
|
||||
ACPI_FUNCTION_TRACE(acpi_initialize_tables);
|
||||
|
||||
/*
|
||||
* Set up the Root Table Array
|
||||
* Allocate the table array if requested
|
||||
*/
|
||||
if (!initial_table_array) {
|
||||
status = acpi_allocate_root_table(initial_table_count);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
} else {
|
||||
/* Root Table Array has been statically allocated by the host */
|
||||
|
||||
ACPI_MEMSET(initial_table_array, 0,
|
||||
initial_table_count *
|
||||
sizeof(struct acpi_table_desc));
|
||||
|
||||
acpi_gbl_root_table_list.tables = initial_table_array;
|
||||
acpi_gbl_root_table_list.size = initial_table_count;
|
||||
acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN;
|
||||
if (allow_resize) {
|
||||
acpi_gbl_root_table_list.flags |=
|
||||
ACPI_ROOT_ALLOW_RESIZE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the address of the RSDP */
|
||||
|
||||
rsdp_address = acpi_os_get_root_pointer();
|
||||
if (!rsdp_address) {
|
||||
return_ACPI_STATUS(AE_NOT_FOUND);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the root table (RSDT or XSDT) and extract all entries to the local
|
||||
* Root Table Array. This array contains the information of the RSDT/XSDT
|
||||
* in a common, more useable format.
|
||||
*/
|
||||
status =
|
||||
acpi_tb_parse_root_table(rsdp_address, ACPI_TABLE_ORIGIN_MAPPED);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_reallocate_root_table
|
||||
*
|
||||
* PARAMETERS: None
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the
|
||||
* root list from the previously provided scratch area. Should
|
||||
* be called once dynamic memory allocation is available in the
|
||||
* kernel
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status acpi_reallocate_root_table(void)
|
||||
{
|
||||
struct acpi_table_desc *tables;
|
||||
acpi_size new_size;
|
||||
|
||||
ACPI_FUNCTION_TRACE(acpi_reallocate_root_table);
|
||||
|
||||
/*
|
||||
* Only reallocate the root table if the host provided a static buffer
|
||||
* for the table array in the call to acpi_initialize_tables.
|
||||
*/
|
||||
if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
|
||||
return_ACPI_STATUS(AE_SUPPORT);
|
||||
}
|
||||
|
||||
new_size =
|
||||
(acpi_gbl_root_table_list.count +
|
||||
ACPI_ROOT_TABLE_SIZE_INCREMENT) * sizeof(struct acpi_table_desc);
|
||||
|
||||
/* Create new array and copy the old array */
|
||||
|
||||
tables = ACPI_ALLOCATE_ZEROED(new_size);
|
||||
if (!tables) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, new_size);
|
||||
|
||||
acpi_gbl_root_table_list.size = acpi_gbl_root_table_list.count;
|
||||
acpi_gbl_root_table_list.tables = tables;
|
||||
acpi_gbl_root_table_list.flags =
|
||||
ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE;
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_load_table
|
||||
*
|
||||
* PARAMETERS: table_ptr - pointer to a buffer containing the entire
|
||||
* table to be loaded
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: This function is called to load a table from the caller's
|
||||
* buffer. The buffer must contain an entire ACPI Table including
|
||||
* a valid header. The header fields will be verified, and if it
|
||||
* is determined that the table is invalid, the call will fail.
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status acpi_load_table(struct acpi_table_header *table_ptr)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_native_uint table_index;
|
||||
struct acpi_table_desc table_desc;
|
||||
|
||||
if (!table_ptr)
|
||||
return AE_BAD_PARAMETER;
|
||||
|
||||
ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc));
|
||||
table_desc.pointer = table_ptr;
|
||||
table_desc.length = table_ptr->length;
|
||||
table_desc.flags = ACPI_TABLE_ORIGIN_UNKNOWN;
|
||||
|
||||
/*
|
||||
* Install the new table into the local data structures
|
||||
*/
|
||||
status = acpi_tb_add_table(&table_desc, &table_index);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return status;
|
||||
}
|
||||
status = acpi_ns_load_table(table_index, acpi_gbl_root_node);
|
||||
return status;
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_load_table)
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_get_table_header
|
||||
*
|
||||
* PARAMETERS: Signature - ACPI signature of needed table
|
||||
* Instance - Which instance (for SSDTs)
|
||||
* out_table_header - The pointer to the table header to fill
|
||||
*
|
||||
* RETURN: Status and pointer to mapped table header
|
||||
*
|
||||
* DESCRIPTION: Finds an ACPI table header.
|
||||
*
|
||||
* NOTE: Caller is responsible in unmapping the header with
|
||||
* acpi_os_unmap_memory
|
||||
*
|
||||
*****************************************************************************/
|
||||
acpi_status
|
||||
acpi_get_table_header(char *signature,
|
||||
acpi_native_uint instance,
|
||||
struct acpi_table_header *out_table_header)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
acpi_native_uint j;
|
||||
struct acpi_table_header *header;
|
||||
|
||||
/* Parameter validation */
|
||||
|
||||
if (!signature || !out_table_header) {
|
||||
return (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk the root table list
|
||||
*/
|
||||
for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) {
|
||||
if (!ACPI_COMPARE_NAME
|
||||
(&(acpi_gbl_root_table_list.tables[i].signature),
|
||||
signature)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (++j < instance) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!acpi_gbl_root_table_list.tables[i].pointer) {
|
||||
if ((acpi_gbl_root_table_list.tables[i].
|
||||
flags & ACPI_TABLE_ORIGIN_MASK) ==
|
||||
ACPI_TABLE_ORIGIN_MAPPED) {
|
||||
header =
|
||||
acpi_os_map_memory(acpi_gbl_root_table_list.
|
||||
tables[i].address,
|
||||
sizeof(struct
|
||||
acpi_table_header));
|
||||
if (!header) {
|
||||
return AE_NO_MEMORY;
|
||||
}
|
||||
ACPI_MEMCPY(out_table_header, header,
|
||||
sizeof(struct acpi_table_header));
|
||||
acpi_os_unmap_memory(header,
|
||||
sizeof(struct
|
||||
acpi_table_header));
|
||||
} else {
|
||||
return AE_NOT_FOUND;
|
||||
}
|
||||
} else {
|
||||
ACPI_MEMCPY(out_table_header,
|
||||
acpi_gbl_root_table_list.tables[i].pointer,
|
||||
sizeof(struct acpi_table_header));
|
||||
}
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
return (AE_NOT_FOUND);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_get_table_header)
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_unload_table_id
|
||||
*
|
||||
* PARAMETERS: id - Owner ID of the table to be removed.
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: This routine is used to force the unload of a table (by id)
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status acpi_unload_table_id(acpi_owner_id id)
|
||||
{
|
||||
int i;
|
||||
acpi_status status = AE_NOT_EXIST;
|
||||
|
||||
ACPI_FUNCTION_TRACE(acpi_unload_table_id);
|
||||
|
||||
/* Find table in the global table list */
|
||||
for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
|
||||
if (id != acpi_gbl_root_table_list.tables[i].owner_id) {
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* Delete all namespace objects owned by this table. Note that these
|
||||
* objects can appear anywhere in the namespace by virtue of the AML
|
||||
* "Scope" operator. Thus, we need to track ownership by an ID, not
|
||||
* simply a position within the hierarchy
|
||||
*/
|
||||
acpi_tb_delete_namespace_by_owner(i);
|
||||
status = acpi_tb_release_owner_id(i);
|
||||
acpi_tb_set_table_loaded_flag(i, FALSE);
|
||||
break;
|
||||
}
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_unload_table_id)
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_get_table
|
||||
*
|
||||
* PARAMETERS: Signature - ACPI signature of needed table
|
||||
* Instance - Which instance (for SSDTs)
|
||||
* out_table - Where the pointer to the table is returned
|
||||
*
|
||||
* RETURN: Status and pointer to table
|
||||
*
|
||||
* DESCRIPTION: Finds and verifies an ACPI table.
|
||||
*
|
||||
*****************************************************************************/
|
||||
acpi_status
|
||||
acpi_get_table(char *signature,
|
||||
acpi_native_uint instance, struct acpi_table_header ** out_table)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
acpi_native_uint j;
|
||||
acpi_status status;
|
||||
|
||||
/* Parameter validation */
|
||||
|
||||
if (!signature || !out_table) {
|
||||
return (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk the root table list
|
||||
*/
|
||||
for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) {
|
||||
if (!ACPI_COMPARE_NAME
|
||||
(&(acpi_gbl_root_table_list.tables[i].signature),
|
||||
signature)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (++j < instance) {
|
||||
continue;
|
||||
}
|
||||
|
||||
status =
|
||||
acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
*out_table = acpi_gbl_root_table_list.tables[i].pointer;
|
||||
}
|
||||
|
||||
if (!acpi_gbl_permanent_mmap) {
|
||||
acpi_gbl_root_table_list.tables[i].pointer = NULL;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
return (AE_NOT_FOUND);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_get_table)
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_get_table_by_index
|
||||
*
|
||||
* PARAMETERS: table_index - Table index
|
||||
* Table - Where the pointer to the table is returned
|
||||
*
|
||||
* RETURN: Status and pointer to the table
|
||||
*
|
||||
* DESCRIPTION: Obtain a table by an index into the global table list.
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status
|
||||
acpi_get_table_by_index(acpi_native_uint table_index,
|
||||
struct acpi_table_header ** table)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
ACPI_FUNCTION_TRACE(acpi_get_table_by_index);
|
||||
|
||||
/* Parameter validation */
|
||||
|
||||
if (!table) {
|
||||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
|
||||
/* Validate index */
|
||||
|
||||
if (table_index >= acpi_gbl_root_table_list.count) {
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
if (!acpi_gbl_root_table_list.tables[table_index].pointer) {
|
||||
|
||||
/* Table is not mapped, map it */
|
||||
|
||||
status =
|
||||
acpi_tb_verify_table(&acpi_gbl_root_table_list.
|
||||
tables[table_index]);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
}
|
||||
|
||||
*table = acpi_gbl_root_table_list.tables[table_index].pointer;
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_get_table_by_index)
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_load_namespace
|
||||
*
|
||||
* PARAMETERS: None
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in
|
||||
* the RSDT/XSDT.
|
||||
*
|
||||
******************************************************************************/
|
||||
static acpi_status acpi_tb_load_namespace(void)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_table_header *table;
|
||||
acpi_native_uint i;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_load_namespace);
|
||||
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
|
||||
/*
|
||||
* Load the namespace. The DSDT is required, but any SSDT and PSDT tables
|
||||
* are optional.
|
||||
*/
|
||||
if (!acpi_gbl_root_table_list.count ||
|
||||
!ACPI_COMPARE_NAME(&
|
||||
(acpi_gbl_root_table_list.
|
||||
tables[ACPI_TABLE_INDEX_DSDT].signature),
|
||||
ACPI_SIG_DSDT)
|
||||
||
|
||||
ACPI_FAILURE(acpi_tb_verify_table
|
||||
(&acpi_gbl_root_table_list.
|
||||
tables[ACPI_TABLE_INDEX_DSDT]))) {
|
||||
status = AE_NO_ACPI_TABLES;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find DSDT table
|
||||
*/
|
||||
status =
|
||||
acpi_os_table_override(acpi_gbl_root_table_list.
|
||||
tables[ACPI_TABLE_INDEX_DSDT].pointer,
|
||||
&table);
|
||||
if (ACPI_SUCCESS(status) && table) {
|
||||
/*
|
||||
* DSDT table has been found
|
||||
*/
|
||||
acpi_tb_delete_table(&acpi_gbl_root_table_list.
|
||||
tables[ACPI_TABLE_INDEX_DSDT]);
|
||||
acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer =
|
||||
table;
|
||||
acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length =
|
||||
table->length;
|
||||
acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags =
|
||||
ACPI_TABLE_ORIGIN_UNKNOWN;
|
||||
|
||||
ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS"));
|
||||
acpi_tb_print_table_header(0, table);
|
||||
}
|
||||
|
||||
status =
|
||||
acpi_tb_verify_table(&acpi_gbl_root_table_list.
|
||||
tables[ACPI_TABLE_INDEX_DSDT]);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
||||
/* A valid DSDT is required */
|
||||
|
||||
status = AE_NO_ACPI_TABLES;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
|
||||
/*
|
||||
* Load and parse tables.
|
||||
*/
|
||||
status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Load any SSDT or PSDT tables. Note: Loop leaves tables locked
|
||||
*/
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
|
||||
if ((!ACPI_COMPARE_NAME
|
||||
(&(acpi_gbl_root_table_list.tables[i].signature),
|
||||
ACPI_SIG_SSDT)
|
||||
&&
|
||||
!ACPI_COMPARE_NAME(&
|
||||
(acpi_gbl_root_table_list.tables[i].
|
||||
signature), ACPI_SIG_PSDT))
|
||||
||
|
||||
ACPI_FAILURE(acpi_tb_verify_table
|
||||
(&acpi_gbl_root_table_list.tables[i]))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Ignore errors while loading tables, get as many as possible */
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
(void)acpi_ns_load_table(i, acpi_gbl_root_node);
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n"));
|
||||
|
||||
unlock_and_exit:
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_load_tables
|
||||
*
|
||||
* PARAMETERS: None
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Load the ACPI tables from the RSDT/XSDT
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_load_tables(void)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
ACPI_FUNCTION_TRACE(acpi_load_tables);
|
||||
|
||||
/*
|
||||
* Load the namespace from the tables
|
||||
*/
|
||||
status = acpi_tb_load_namespace();
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_EXCEPTION((AE_INFO, status,
|
||||
"While loading namespace from ACPI tables"));
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_load_tables)
|
||||
275
drivers/acpi/tables/tbxfroot.c
Normal file
275
drivers/acpi/tables/tbxfroot.c
Normal file
@@ -0,0 +1,275 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: tbxfroot - Find the root ACPI table (RSDT)
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2007, R. Byron Moore
|
||||
* 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 <acpi/acpi.h>
|
||||
#include <acpi/actables.h>
|
||||
|
||||
#define _COMPONENT ACPI_TABLES
|
||||
ACPI_MODULE_NAME("tbxfroot")
|
||||
|
||||
/* Local prototypes */
|
||||
static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length);
|
||||
|
||||
static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_validate_rsdp
|
||||
*
|
||||
* PARAMETERS: Rsdp - Pointer to unvalidated RSDP
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Validate the RSDP (ptr)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
|
||||
{
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
/*
|
||||
* The signature and checksum must both be correct
|
||||
*
|
||||
* Note: Sometimes there exists more than one RSDP in memory; the valid
|
||||
* RSDP has a valid checksum, all others have an invalid checksum.
|
||||
*/
|
||||
if (ACPI_STRNCMP((char *)rsdp, ACPI_SIG_RSDP, sizeof(ACPI_SIG_RSDP) - 1)
|
||||
!= 0) {
|
||||
|
||||
/* Nope, BAD Signature */
|
||||
|
||||
return (AE_BAD_SIGNATURE);
|
||||
}
|
||||
|
||||
/* Check the standard checksum */
|
||||
|
||||
if (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
|
||||
return (AE_BAD_CHECKSUM);
|
||||
}
|
||||
|
||||
/* Check extended checksum if table version >= 2 */
|
||||
|
||||
if ((rsdp->revision >= 2) &&
|
||||
(acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) {
|
||||
return (AE_BAD_CHECKSUM);
|
||||
}
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_find_rsdp
|
||||
*
|
||||
* PARAMETERS: table_address - Where the table pointer is returned
|
||||
*
|
||||
* RETURN: Status, RSDP physical address
|
||||
*
|
||||
* DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor
|
||||
* pointer structure. If it is found, set *RSDP to point to it.
|
||||
*
|
||||
* NOTE1: The RSDP must be either in the first 1_k of the Extended
|
||||
* BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.)
|
||||
* Only a 32-bit physical address is necessary.
|
||||
*
|
||||
* NOTE2: This function is always available, regardless of the
|
||||
* initialization state of the rest of ACPI.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_find_root_pointer(acpi_native_uint * table_address)
|
||||
{
|
||||
u8 *table_ptr;
|
||||
u8 *mem_rover;
|
||||
u32 physical_address;
|
||||
|
||||
ACPI_FUNCTION_TRACE(acpi_find_root_pointer);
|
||||
|
||||
/* 1a) Get the location of the Extended BIOS Data Area (EBDA) */
|
||||
|
||||
table_ptr = acpi_os_map_memory((acpi_physical_address)
|
||||
ACPI_EBDA_PTR_LOCATION,
|
||||
ACPI_EBDA_PTR_LENGTH);
|
||||
if (!table_ptr) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Could not map memory at %8.8X for length %X",
|
||||
ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH));
|
||||
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
ACPI_MOVE_16_TO_32(&physical_address, table_ptr);
|
||||
|
||||
/* Convert segment part to physical address */
|
||||
|
||||
physical_address <<= 4;
|
||||
acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH);
|
||||
|
||||
/* EBDA present? */
|
||||
|
||||
if (physical_address > 0x400) {
|
||||
/*
|
||||
* 1b) Search EBDA paragraphs (EBDA is required to be a
|
||||
* minimum of 1_k length)
|
||||
*/
|
||||
table_ptr = acpi_os_map_memory((acpi_native_uint)
|
||||
physical_address,
|
||||
ACPI_EBDA_WINDOW_SIZE);
|
||||
if (!table_ptr) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Could not map memory at %8.8X for length %X",
|
||||
physical_address, ACPI_EBDA_WINDOW_SIZE));
|
||||
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
mem_rover =
|
||||
acpi_tb_scan_memory_for_rsdp(table_ptr,
|
||||
ACPI_EBDA_WINDOW_SIZE);
|
||||
acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE);
|
||||
|
||||
if (mem_rover) {
|
||||
|
||||
/* Return the physical address */
|
||||
|
||||
physical_address +=
|
||||
(u32) ACPI_PTR_DIFF(mem_rover, table_ptr);
|
||||
|
||||
*table_address = physical_address;
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
|
||||
*/
|
||||
table_ptr = acpi_os_map_memory((acpi_physical_address)
|
||||
ACPI_HI_RSDP_WINDOW_BASE,
|
||||
ACPI_HI_RSDP_WINDOW_SIZE);
|
||||
|
||||
if (!table_ptr) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Could not map memory at %8.8X for length %X",
|
||||
ACPI_HI_RSDP_WINDOW_BASE,
|
||||
ACPI_HI_RSDP_WINDOW_SIZE));
|
||||
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
mem_rover =
|
||||
acpi_tb_scan_memory_for_rsdp(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
|
||||
acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
|
||||
|
||||
if (mem_rover) {
|
||||
|
||||
/* Return the physical address */
|
||||
|
||||
physical_address = (u32)
|
||||
(ACPI_HI_RSDP_WINDOW_BASE +
|
||||
ACPI_PTR_DIFF(mem_rover, table_ptr));
|
||||
|
||||
*table_address = physical_address;
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/* A valid RSDP was not found */
|
||||
|
||||
ACPI_ERROR((AE_INFO, "A valid RSDP was not found"));
|
||||
return_ACPI_STATUS(AE_NOT_FOUND);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_find_root_pointer)
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_scan_memory_for_rsdp
|
||||
*
|
||||
* PARAMETERS: start_address - Starting pointer for search
|
||||
* Length - Maximum length to search
|
||||
*
|
||||
* RETURN: Pointer to the RSDP if found, otherwise NULL.
|
||||
*
|
||||
* DESCRIPTION: Search a block of memory for the RSDP signature
|
||||
*
|
||||
******************************************************************************/
|
||||
static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length)
|
||||
{
|
||||
acpi_status status;
|
||||
u8 *mem_rover;
|
||||
u8 *end_address;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_scan_memory_for_rsdp);
|
||||
|
||||
end_address = start_address + length;
|
||||
|
||||
/* Search from given start address for the requested length */
|
||||
|
||||
for (mem_rover = start_address; mem_rover < end_address;
|
||||
mem_rover += ACPI_RSDP_SCAN_STEP) {
|
||||
|
||||
/* The RSDP signature and checksum must both be correct */
|
||||
|
||||
status =
|
||||
acpi_tb_validate_rsdp(ACPI_CAST_PTR
|
||||
(struct acpi_table_rsdp, mem_rover));
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
|
||||
/* Sig and checksum valid, we have found a real RSDP */
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"RSDP located at physical address %p\n",
|
||||
mem_rover));
|
||||
return_PTR(mem_rover);
|
||||
}
|
||||
|
||||
/* No sig match or bad checksum, keep searching */
|
||||
}
|
||||
|
||||
/* Searched entire block, no RSDP was found */
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Searched entire block from %p, valid RSDP was not found\n",
|
||||
start_address));
|
||||
return_PTR(NULL);
|
||||
}
|
||||
Reference in New Issue
Block a user