diff options
author | Bob Moore <robert.moore@intel.com> | 2007-02-02 19:48:18 +0300 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-02-02 21:14:21 -0500 |
commit | f3d2e7865c816258c699ff965768e46b50d536d3 (patch) | |
tree | 83d21269e506109275b77d3ed161883bba8a39cf /drivers/acpi/tables | |
parent | 2e42005bcdb4f63bed1cea7f537a5534d4bd7a57 (diff) | |
download | linux-f3d2e7865c816258c699ff965768e46b50d536d3.tar.gz linux-f3d2e7865c816258c699ff965768e46b50d536d3.tar.bz2 linux-f3d2e7865c816258c699ff965768e46b50d536d3.zip |
ACPICA: Implement simplified Table Manager
The Table Manager component has been completely
redesigned and reimplemented. The new design is much
simpler, and reduces the overall code and data size of
the kernel-resident ACPICA by approximately 5%. Also,
it is now possible to obtain the ACPI tables very early
during kernel initialization, even before dynamic memory
management is initialized.
Signed-off-by: Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/tables')
-rw-r--r-- | drivers/acpi/tables/tbconvrt.c | 622 | ||||
-rw-r--r-- | drivers/acpi/tables/tbfind.c | 126 | ||||
-rw-r--r-- | drivers/acpi/tables/tbget.c | 471 | ||||
-rw-r--r-- | drivers/acpi/tables/tbgetall.c | 311 | ||||
-rw-r--r-- | drivers/acpi/tables/tbinstal.c | 650 | ||||
-rw-r--r-- | drivers/acpi/tables/tbrsdt.c | 307 | ||||
-rw-r--r-- | drivers/acpi/tables/tbutils.c | 600 | ||||
-rw-r--r-- | drivers/acpi/tables/tbxface.c | 620 | ||||
-rw-r--r-- | drivers/acpi/tables/tbxfroot.c | 550 |
9 files changed, 1290 insertions, 2967 deletions
diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c deleted file mode 100644 index d697fcb35d52..000000000000 --- a/drivers/acpi/tables/tbconvrt.c +++ /dev/null @@ -1,622 +0,0 @@ -/****************************************************************************** - * - * Module Name: tbconvrt - ACPI Table conversion utilities - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2006, 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("tbconvrt") - -/* Local prototypes */ -static void -acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct, - u8 register_bit_width, - acpi_physical_address address); - -static void -acpi_tb_convert_fadt1(struct fadt_descriptor *local_fadt, - struct fadt_descriptor_rev1 *original_fadt); - -static void -acpi_tb_convert_fadt2(struct fadt_descriptor *local_fadt, - struct fadt_descriptor *original_fadt); - -u8 acpi_fadt_is_v1; -ACPI_EXPORT_SYMBOL(acpi_fadt_is_v1) - -/******************************************************************************* - * - * FUNCTION: acpi_tb_get_table_count - * - * PARAMETERS: RSDP - Pointer to the RSDP - * RSDT - Pointer to the RSDT/XSDT - * - * RETURN: The number of tables pointed to by the RSDT or XSDT. - * - * DESCRIPTION: Calculate the number of tables. Automatically handles either - * an RSDT or XSDT. - * - ******************************************************************************/ - -u32 -acpi_tb_get_table_count(struct rsdp_descriptor *RSDP, - struct acpi_table_header *RSDT) -{ - u32 pointer_size; - - ACPI_FUNCTION_ENTRY(); - - /* RSDT pointers are 32 bits, XSDT pointers are 64 bits */ - - if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { - pointer_size = sizeof(u32); - } else { - pointer_size = sizeof(u64); - } - - /* - * Determine the number of tables pointed to by the RSDT/XSDT. - * This is defined by the ACPI Specification to be the number of - * pointers contained within the RSDT/XSDT. The size of the pointers - * is architecture-dependent. - */ - return ((RSDT->length - - sizeof(struct acpi_table_header)) / pointer_size); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_convert_to_xsdt - * - * PARAMETERS: table_info - Info about the RSDT - * - * RETURN: Status - * - * DESCRIPTION: Convert an RSDT to an XSDT (internal common format) - * - ******************************************************************************/ - -acpi_status acpi_tb_convert_to_xsdt(struct acpi_table_desc *table_info) -{ - acpi_size table_size; - u32 i; - struct xsdt_descriptor *new_table; - - ACPI_FUNCTION_ENTRY(); - - /* Compute size of the converted XSDT */ - - table_size = ((acpi_size) acpi_gbl_rsdt_table_count * sizeof(u64)) + - sizeof(struct acpi_table_header); - - /* Allocate an XSDT */ - - new_table = ACPI_ALLOCATE_ZEROED(table_size); - if (!new_table) { - return (AE_NO_MEMORY); - } - - /* Copy the header and set the length */ - - ACPI_MEMCPY(new_table, table_info->pointer, - sizeof(struct acpi_table_header)); - new_table->length = (u32) table_size; - - /* Copy the table pointers */ - - for (i = 0; i < acpi_gbl_rsdt_table_count; i++) { - - /* RSDT pointers are 32 bits, XSDT pointers are 64 bits */ - - if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { - ACPI_STORE_ADDRESS(new_table->table_offset_entry[i], - (ACPI_CAST_PTR - (struct rsdt_descriptor, - table_info->pointer))-> - table_offset_entry[i]); - } else { - new_table->table_offset_entry[i] = - (ACPI_CAST_PTR(struct xsdt_descriptor, - table_info->pointer))-> - table_offset_entry[i]; - } - } - - /* Delete the original table (either mapped or in a buffer) */ - - acpi_tb_delete_single_table(table_info); - - /* Point the table descriptor to the new table */ - - table_info->pointer = - ACPI_CAST_PTR(struct acpi_table_header, new_table); - table_info->length = table_size; - table_info->allocation = ACPI_MEM_ALLOCATED; - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_init_generic_address - * - * PARAMETERS: new_gas_struct - GAS struct to be initialized - * register_bit_width - Width of this register - * Address - Address of the register - * - * RETURN: None - * - * DESCRIPTION: Initialize a GAS structure. - * - ******************************************************************************/ - -static void -acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct, - u8 register_bit_width, - acpi_physical_address address) -{ - - ACPI_STORE_ADDRESS(new_gas_struct->address, address); - - new_gas_struct->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO; - new_gas_struct->register_bit_width = register_bit_width; - new_gas_struct->register_bit_offset = 0; - new_gas_struct->access_width = 0; -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_convert_fadt1 - * - * PARAMETERS: local_fadt - Pointer to new FADT - * original_fadt - Pointer to old FADT - * - * RETURN: None, populates local_fadt - * - * DESCRIPTION: Convert an ACPI 1.0 FADT to common internal format - * - ******************************************************************************/ - -static void -acpi_tb_convert_fadt1(struct fadt_descriptor *local_fadt, - struct fadt_descriptor_rev1 *original_fadt) -{ - - /* ACPI 1.0 FACS */ - /* The BIOS stored FADT should agree with Revision 1.0 */ - acpi_fadt_is_v1 = 1; - - /* - * Copy the table header and the common part of the tables. - * - * The 2.0 table is an extension of the 1.0 table, so the entire 1.0 - * table can be copied first, then expand some fields to 64 bits. - */ - ACPI_MEMCPY(local_fadt, original_fadt, - sizeof(struct fadt_descriptor_rev1)); - - /* Convert table pointers to 64-bit fields */ - - ACPI_STORE_ADDRESS(local_fadt->xfirmware_ctrl, - local_fadt->V1_firmware_ctrl); - ACPI_STORE_ADDRESS(local_fadt->Xdsdt, local_fadt->V1_dsdt); - - /* - * System Interrupt Model isn't used in ACPI 2.0 - * (local_fadt->Reserved1 = 0;) - */ - - /* - * This field is set by the OEM to convey the preferred power management - * profile to OSPM. It doesn't have any 1.0 equivalence. Since we don't - * know what kind of 32-bit system this is, we will use "unspecified". - */ - local_fadt->prefer_PM_profile = PM_UNSPECIFIED; - - /* - * Processor Performance State Control. This is the value OSPM writes to - * the SMI_CMD register to assume processor performance state control - * responsibility. There isn't any equivalence in 1.0, but as many 1.x - * ACPI tables contain _PCT and _PSS we also keep this value, unless - * acpi_strict is set. - */ - if (acpi_strict) - local_fadt->pstate_cnt = 0; - - /* - * Support for the _CST object and C States change notification. - * This data item hasn't any 1.0 equivalence so leave it zero. - */ - local_fadt->cst_cnt = 0; - - /* - * FADT Rev 2 was an interim FADT released between ACPI 1.0 and ACPI 2.0. - * It primarily adds the FADT reset mechanism. - */ - if ((original_fadt->revision == 2) && - (original_fadt->length == - sizeof(struct fadt_descriptor_rev2_minus))) { - /* - * Grab the entire generic address struct, plus the 1-byte reset value - * that immediately follows. - */ - ACPI_MEMCPY(&local_fadt->reset_register, - &(ACPI_CAST_PTR(struct fadt_descriptor_rev2_minus, - original_fadt))->reset_register, - sizeof(struct acpi_generic_address) + 1); - } else { - /* - * Since there isn't any equivalence in 1.0 and since it is highly - * likely that a 1.0 system has legacy support. - */ - local_fadt->iapc_boot_arch = BAF_LEGACY_DEVICES; - } - - /* - * Convert the V1.0 block addresses to V2.0 GAS structures - */ - acpi_tb_init_generic_address(&local_fadt->xpm1a_evt_blk, - local_fadt->pm1_evt_len, - (acpi_physical_address) local_fadt-> - V1_pm1a_evt_blk); - acpi_tb_init_generic_address(&local_fadt->xpm1b_evt_blk, - local_fadt->pm1_evt_len, - (acpi_physical_address) local_fadt-> - V1_pm1b_evt_blk); - acpi_tb_init_generic_address(&local_fadt->xpm1a_cnt_blk, - local_fadt->pm1_cnt_len, - (acpi_physical_address) local_fadt-> - V1_pm1a_cnt_blk); - acpi_tb_init_generic_address(&local_fadt->xpm1b_cnt_blk, - local_fadt->pm1_cnt_len, - (acpi_physical_address) local_fadt-> - V1_pm1b_cnt_blk); - acpi_tb_init_generic_address(&local_fadt->xpm2_cnt_blk, - local_fadt->pm2_cnt_len, - (acpi_physical_address) local_fadt-> - V1_pm2_cnt_blk); - acpi_tb_init_generic_address(&local_fadt->xpm_tmr_blk, - local_fadt->pm_tm_len, - (acpi_physical_address) local_fadt-> - V1_pm_tmr_blk); - acpi_tb_init_generic_address(&local_fadt->xgpe0_blk, 0, - (acpi_physical_address) local_fadt-> - V1_gpe0_blk); - acpi_tb_init_generic_address(&local_fadt->xgpe1_blk, 0, - (acpi_physical_address) local_fadt-> - V1_gpe1_blk); - - /* Create separate GAS structs for the PM1 Enable registers */ - - acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, - (u8) ACPI_DIV_2(acpi_gbl_FADT-> - pm1_evt_len), - (acpi_physical_address) - (local_fadt->xpm1a_evt_blk.address + - ACPI_DIV_2(acpi_gbl_FADT->pm1_evt_len))); - - /* PM1B is optional; leave null if not present */ - - if (local_fadt->xpm1b_evt_blk.address) { - acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, - (u8) ACPI_DIV_2(acpi_gbl_FADT-> - pm1_evt_len), - (acpi_physical_address) - (local_fadt->xpm1b_evt_blk. - address + - ACPI_DIV_2(acpi_gbl_FADT-> - pm1_evt_len))); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_convert_fadt2 - * - * PARAMETERS: local_fadt - Pointer to new FADT - * original_fadt - Pointer to old FADT - * - * RETURN: None, populates local_fadt - * - * DESCRIPTION: Convert an ACPI 2.0 FADT to common internal format. - * Handles optional "X" fields. - * - ******************************************************************************/ - -static void -acpi_tb_convert_fadt2(struct fadt_descriptor *local_fadt, - struct fadt_descriptor *original_fadt) -{ - - /* We have an ACPI 2.0 FADT but we must copy it to our local buffer */ - - ACPI_MEMCPY(local_fadt, original_fadt, sizeof(struct fadt_descriptor)); - - /* - * "X" fields are optional extensions to the original V1.0 fields, so - * we must selectively expand V1.0 fields if the corresponding X field - * is zero. - */ - if (!(local_fadt->xfirmware_ctrl)) { - ACPI_STORE_ADDRESS(local_fadt->xfirmware_ctrl, - local_fadt->V1_firmware_ctrl); - } - - if (!(local_fadt->Xdsdt)) { - ACPI_STORE_ADDRESS(local_fadt->Xdsdt, local_fadt->V1_dsdt); - } - - if (!(local_fadt->xpm1a_evt_blk.address)) { - acpi_tb_init_generic_address(&local_fadt->xpm1a_evt_blk, - local_fadt->pm1_evt_len, - (acpi_physical_address) - local_fadt->V1_pm1a_evt_blk); - } - - if (!(local_fadt->xpm1b_evt_blk.address)) { - acpi_tb_init_generic_address(&local_fadt->xpm1b_evt_blk, - local_fadt->pm1_evt_len, - (acpi_physical_address) - local_fadt->V1_pm1b_evt_blk); - } - - if (!(local_fadt->xpm1a_cnt_blk.address)) { - acpi_tb_init_generic_address(&local_fadt->xpm1a_cnt_blk, - local_fadt->pm1_cnt_len, - (acpi_physical_address) - local_fadt->V1_pm1a_cnt_blk); - } - - if (!(local_fadt->xpm1b_cnt_blk.address)) { - acpi_tb_init_generic_address(&local_fadt->xpm1b_cnt_blk, - local_fadt->pm1_cnt_len, - (acpi_physical_address) - local_fadt->V1_pm1b_cnt_blk); - } - - if (!(local_fadt->xpm2_cnt_blk.address)) { - acpi_tb_init_generic_address(&local_fadt->xpm2_cnt_blk, - local_fadt->pm2_cnt_len, - (acpi_physical_address) - local_fadt->V1_pm2_cnt_blk); - } - - if (!(local_fadt->xpm_tmr_blk.address)) { - acpi_tb_init_generic_address(&local_fadt->xpm_tmr_blk, - local_fadt->pm_tm_len, - (acpi_physical_address) - local_fadt->V1_pm_tmr_blk); - } - - if (!(local_fadt->xgpe0_blk.address)) { - acpi_tb_init_generic_address(&local_fadt->xgpe0_blk, - 0, - (acpi_physical_address) - local_fadt->V1_gpe0_blk); - } - - if (!(local_fadt->xgpe1_blk.address)) { - acpi_tb_init_generic_address(&local_fadt->xgpe1_blk, - 0, - (acpi_physical_address) - local_fadt->V1_gpe1_blk); - } - - /* Create separate GAS structs for the PM1 Enable registers */ - - acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, - (u8) ACPI_DIV_2(acpi_gbl_FADT-> - pm1_evt_len), - (acpi_physical_address) - (local_fadt->xpm1a_evt_blk.address + - ACPI_DIV_2(acpi_gbl_FADT->pm1_evt_len))); - - acpi_gbl_xpm1a_enable.address_space_id = - local_fadt->xpm1a_evt_blk.address_space_id; - - /* PM1B is optional; leave null if not present */ - - if (local_fadt->xpm1b_evt_blk.address) { - acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, - (u8) ACPI_DIV_2(acpi_gbl_FADT-> - pm1_evt_len), - (acpi_physical_address) - (local_fadt->xpm1b_evt_blk. - address + - ACPI_DIV_2(acpi_gbl_FADT-> - pm1_evt_len))); - - acpi_gbl_xpm1b_enable.address_space_id = - local_fadt->xpm1b_evt_blk.address_space_id; - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_convert_table_fadt - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Converts a BIOS supplied ACPI 1.0 FADT to a local - * ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply - * copied to the local FADT. The ACPI CA software uses this - * local FADT. Thus a significant amount of special #ifdef - * type codeing is saved. - * - ******************************************************************************/ - -acpi_status acpi_tb_convert_table_fadt(void) -{ - struct fadt_descriptor *local_fadt; - struct acpi_table_desc *table_desc; - - ACPI_FUNCTION_TRACE(tb_convert_table_fadt); - - /* - * acpi_gbl_FADT is valid. Validate the FADT length. The table must be - * at least as long as the version 1.0 FADT - */ - if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev1)) { - ACPI_ERROR((AE_INFO, "FADT is invalid, too short: 0x%X", - acpi_gbl_FADT->length)); - return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); - } - - /* Allocate buffer for the ACPI 2.0(+) FADT */ - - local_fadt = ACPI_ALLOCATE_ZEROED(sizeof(struct fadt_descriptor)); - if (!local_fadt) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - if (acpi_gbl_FADT->revision >= FADT2_REVISION_ID) { - if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor)) { - - /* Length is too short to be a V2.0 table */ - - ACPI_WARNING((AE_INFO, - "Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table", - acpi_gbl_FADT->length, - acpi_gbl_FADT->revision)); - - acpi_tb_convert_fadt1(local_fadt, - (void *)acpi_gbl_FADT); - } else { - /* Valid V2.0 table */ - - acpi_tb_convert_fadt2(local_fadt, acpi_gbl_FADT); - } - } else { - /* Valid V1.0 table */ - - acpi_tb_convert_fadt1(local_fadt, (void *)acpi_gbl_FADT); - } - - /* Global FADT pointer will point to the new common V2.0 FADT */ - - acpi_gbl_FADT = local_fadt; - acpi_gbl_FADT->length = sizeof(struct fadt_descriptor); - - /* Free the original table */ - - table_desc = acpi_gbl_table_lists[ACPI_TABLE_ID_FADT].next; - acpi_tb_delete_single_table(table_desc); - - /* Install the new table */ - - table_desc->pointer = - ACPI_CAST_PTR(struct acpi_table_header, acpi_gbl_FADT); - table_desc->allocation = ACPI_MEM_ALLOCATED; - table_desc->length = sizeof(struct fadt_descriptor); - - /* Dump the entire FADT */ - - ACPI_DEBUG_PRINT((ACPI_DB_TABLES, - "Hex dump of common internal FADT, size %d (%X)\n", - acpi_gbl_FADT->length, acpi_gbl_FADT->length)); - - ACPI_DUMP_BUFFER(ACPI_CAST_PTR(u8, acpi_gbl_FADT), - acpi_gbl_FADT->length); - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_build_common_facs - * - * PARAMETERS: table_info - Info for currently installed FACS - * - * RETURN: Status - * - * DESCRIPTION: Convert ACPI 1.0 and ACPI 2.0 FACS to a common internal - * table format. - * - ******************************************************************************/ - -acpi_status acpi_tb_build_common_facs(struct acpi_table_desc *table_info) -{ - - ACPI_FUNCTION_TRACE(tb_build_common_facs); - - /* Absolute minimum length is 24, but the ACPI spec says 64 */ - - if (acpi_gbl_FACS->length < 24) { - ACPI_ERROR((AE_INFO, "Invalid FACS table length: 0x%X", - acpi_gbl_FACS->length)); - return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); - } - - if (acpi_gbl_FACS->length < 64) { - ACPI_WARNING((AE_INFO, - "FACS is shorter than the ACPI specification allows: 0x%X, using anyway", - acpi_gbl_FACS->length)); - } - - /* Copy fields to the new FACS */ - - acpi_gbl_common_fACS.global_lock = &(acpi_gbl_FACS->global_lock); - - if ((acpi_gbl_RSDP->revision < 2) || - (acpi_gbl_FACS->length < 32) || - (!(acpi_gbl_FACS->xfirmware_waking_vector))) { - - /* ACPI 1.0 FACS or short table or optional X_ field is zero */ - - acpi_gbl_common_fACS.firmware_waking_vector = ACPI_CAST_PTR(u64, - & - (acpi_gbl_FACS-> - firmware_waking_vector)); - acpi_gbl_common_fACS.vector_width = 32; - } else { - /* ACPI 2.0 FACS with valid X_ field */ - - acpi_gbl_common_fACS.firmware_waking_vector = - &acpi_gbl_FACS->xfirmware_waking_vector; - acpi_gbl_common_fACS.vector_width = 64; - } - - return_ACPI_STATUS(AE_OK); -} diff --git a/drivers/acpi/tables/tbfind.c b/drivers/acpi/tables/tbfind.c new file mode 100644 index 000000000000..769213c74c16 --- /dev/null +++ b/drivers/acpi/tables/tbfind.c @@ -0,0 +1,126 @@ +/****************************************************************************** + * + * Module Name: tbfind - find table + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2006, 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); +} diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c deleted file mode 100644 index 11e2d4454e05..000000000000 --- a/drivers/acpi/tables/tbget.c +++ /dev/null @@ -1,471 +0,0 @@ -/****************************************************************************** - * - * Module Name: tbget - ACPI Table get* routines - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2006, 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("tbget") - -/* Local prototypes */ -static acpi_status -acpi_tb_get_this_table(struct acpi_pointer *address, - struct acpi_table_header *header, - struct acpi_table_desc *table_info); - -static acpi_status -acpi_tb_table_override(struct acpi_table_header *header, - struct acpi_table_desc *table_info); - -/******************************************************************************* - * - * FUNCTION: acpi_tb_get_table - * - * PARAMETERS: Address - Address of table to retrieve. Can be - * Logical or Physical - * table_info - Where table info is returned - * - * RETURN: None - * - * DESCRIPTION: Get entire table of unknown size. - * - ******************************************************************************/ - -acpi_status -acpi_tb_get_table(struct acpi_pointer *address, - struct acpi_table_desc *table_info) -{ - acpi_status status; - struct acpi_table_header header; - - ACPI_FUNCTION_TRACE(tb_get_table); - - /* Get the header in order to get signature and table size */ - - status = acpi_tb_get_table_header(address, &header); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Get the entire table */ - - status = acpi_tb_get_table_body(address, &header, table_info); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Could not get ACPI table (size %X)", - header.length)); - return_ACPI_STATUS(status); - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_get_table_header - * - * PARAMETERS: Address - Address of table to retrieve. Can be - * Logical or Physical - * return_header - Where the table header is returned - * - * RETURN: Status - * - * DESCRIPTION: Get an ACPI table header. Works in both physical or virtual - * addressing mode. Works with both physical or logical pointers. - * Table is either copied or mapped, depending on the pointer - * type and mode of the processor. - * - ******************************************************************************/ - -acpi_status -acpi_tb_get_table_header(struct acpi_pointer *address, - struct acpi_table_header *return_header) -{ - acpi_status status = AE_OK; - struct acpi_table_header *header = NULL; - - ACPI_FUNCTION_TRACE(tb_get_table_header); - - /* - * Flags contains the current processor mode (Virtual or Physical - * addressing) The pointer_type is either Logical or Physical - */ - switch (address->pointer_type) { - case ACPI_PHYSMODE_PHYSPTR: - case ACPI_LOGMODE_LOGPTR: - - /* Pointer matches processor mode, copy the header */ - - ACPI_MEMCPY(return_header, address->pointer.logical, - sizeof(struct acpi_table_header)); - break; - - case ACPI_LOGMODE_PHYSPTR: - - /* Create a logical address for the physical pointer */ - - status = acpi_os_map_memory(address->pointer.physical, - sizeof(struct acpi_table_header), - (void *)&header); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not map memory at %8.8X%8.8X for table header", - ACPI_FORMAT_UINT64(address->pointer. - physical))); - return_ACPI_STATUS(status); - } - - /* Copy header and delete mapping */ - - ACPI_MEMCPY(return_header, header, - sizeof(struct acpi_table_header)); - acpi_os_unmap_memory(header, sizeof(struct acpi_table_header)); - break; - - default: - - ACPI_ERROR((AE_INFO, "Invalid address flags %X", - address->pointer_type)); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "Table Signature: [%4.4s]\n", - return_header->signature)); - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_get_table_body - * - * PARAMETERS: Address - Address of table to retrieve. Can be - * Logical or Physical - * Header - Header of the table to retrieve - * table_info - Where the table info is returned - * - * RETURN: Status - * - * DESCRIPTION: Get an entire ACPI table with support to allow the host OS to - * replace the table with a newer version (table override.) - * Works in both physical or virtual - * addressing mode. Works with both physical or logical pointers. - * Table is either copied or mapped, depending on the pointer - * type and mode of the processor. - * - ******************************************************************************/ - -acpi_status -acpi_tb_get_table_body(struct acpi_pointer *address, - struct acpi_table_header *header, - struct acpi_table_desc *table_info) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(tb_get_table_body); - - if (!table_info || !address) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Attempt table override. */ - - status = acpi_tb_table_override(header, table_info); - if (ACPI_SUCCESS(status)) { - - /* Table was overridden by the host OS */ - - return_ACPI_STATUS(status); - } - - /* No override, get the original table */ - - status = acpi_tb_get_this_table(address, header, table_info); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_table_override - * - * PARAMETERS: Header - Pointer to table header - * table_info - Return info if table is overridden - * - * RETURN: None - * - * DESCRIPTION: Attempts override of current table with a new one if provided - * by the host OS. - * - ******************************************************************************/ - -static acpi_status -acpi_tb_table_override(struct acpi_table_header *header, - struct acpi_table_desc *table_info) -{ - struct acpi_table_header *new_table; - acpi_status status; - struct acpi_pointer address; - - ACPI_FUNCTION_TRACE(tb_table_override); - - /* - * The OSL will examine the header and decide whether to override this - * table. If it decides to override, a table will be returned in new_table, - * which we will then copy. - */ - status = acpi_os_table_override(header, &new_table); - if (ACPI_FAILURE(status)) { - - /* Some severe error from the OSL, but we basically ignore it */ - - ACPI_EXCEPTION((AE_INFO, status, - "Could not override ACPI table")); - return_ACPI_STATUS(status); - } - - if (!new_table) { - - /* No table override */ - - return_ACPI_STATUS(AE_NO_ACPI_TABLES); - } - - /* - * We have a new table to override the old one. Get a copy of - * the new one. We know that the new table has a logical pointer. - */ - address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING; - address.pointer.logical = new_table; - - status = acpi_tb_get_this_table(&address, new_table, table_info); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Could not copy ACPI table")); - return_ACPI_STATUS(status); - } - - /* Copy the table info */ - - ACPI_INFO((AE_INFO, "Table [%4.4s] replaced by host OS", - table_info->pointer->signature)); - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_get_this_table - * - * PARAMETERS: Address - Address of table to retrieve. Can be - * Logical or Physical - * Header - Header of the table to retrieve - * table_info - Where the table info is returned - * - * RETURN: Status - * - * DESCRIPTION: Get an entire ACPI table. Works in both physical or virtual - * addressing mode. Works with both physical or logical pointers. - * Table is either copied or mapped, depending on the pointer - * type and mode of the processor. - * - ******************************************************************************/ - -static acpi_status -acpi_tb_get_this_table(struct acpi_pointer *address, - struct acpi_table_header *header, - struct acpi_table_desc *table_info) -{ - struct acpi_table_header *full_table = NULL; - u8 allocation; - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(tb_get_this_table); - - /* Validate minimum length */ - - if (header->length < sizeof(struct acpi_table_header)) { - ACPI_ERROR((AE_INFO, - "Table length (%X) is smaller than minimum (%zX)", - header->length, sizeof(struct acpi_table_header))); - - return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); - } - - /* - * Flags contains the current processor mode (Virtual or Physical - * addressing) The pointer_type is either Logical or Physical - */ - switch (address->pointer_type) { - case ACPI_PHYSMODE_PHYSPTR: - case ACPI_LOGMODE_LOGPTR: - - /* Pointer matches processor mode, copy the table to a new buffer */ - - full_table = ACPI_ALLOCATE(header->length); - if (!full_table) { - ACPI_ERROR((AE_INFO, - "Could not allocate table memory for [%4.4s] length %X", - header->signature, header->length)); - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Copy the entire table (including header) to the local buffer */ - - ACPI_MEMCPY(full_table, address->pointer.logical, - header->length); - - /* Save allocation type */ - - allocation = ACPI_MEM_ALLOCATED; - break; - - case ACPI_LOGMODE_PHYSPTR: - - /* - * Just map the table's physical memory - * into our address space. - */ - status = acpi_os_map_memory(address->pointer.physical, - (acpi_size) header->length, - ACPI_CAST_PTR(void, &full_table)); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X", - header->signature, - ACPI_FORMAT_UINT64(address->pointer. - physical), - header->length)); - return (status); - } - - /* Save allocation type */ - - allocation = ACPI_MEM_MAPPED; - break; - - default: - - ACPI_ERROR((AE_INFO, "Invalid address flags %X", - address->pointer_type)); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* - * Validate checksum for _most_ tables, - * even the ones whose signature we don't recognize - */ - if (table_info->type != ACPI_TABLE_ID_FACS) { - status = acpi_tb_verify_table_checksum(full_table); - -#if (!ACPI_CHECKSUM_ABORT) - if (ACPI_FAILURE(status)) { - - /* Ignore the error if configuration says so */ - - status = AE_OK; - } -#endif - } - - /* Return values */ - - table_info->pointer = full_table; - table_info->length = (acpi_size) header->length; - table_info->allocation = allocation; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Found table [%4.4s] at %8.8X%8.8X, mapped/copied to %p\n", - full_table->signature, - ACPI_FORMAT_UINT64(address->pointer.physical), - full_table)); - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_get_table_ptr - * - * PARAMETERS: table_type - one of the defined table types - * Instance - Which table of this type - * return_table - pointer to location to place the pointer for - * return - * - * RETURN: Status - * - * DESCRIPTION: This function is called to get the pointer to an ACPI table. - * - ******************************************************************************/ - -acpi_status -acpi_tb_get_table_ptr(acpi_table_type table_type, - u32 instance, struct acpi_table_header **return_table) -{ - struct acpi_table_desc *table_desc; - u32 i; - - ACPI_FUNCTION_TRACE(tb_get_table_ptr); - - if (table_type > ACPI_TABLE_ID_MAX) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Check for instance out of range of the current table count */ - - if (instance > acpi_gbl_table_lists[table_type].count) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - /* - * Walk the list to get the desired table - * Note: Instance is one-based - */ - table_desc = acpi_gbl_table_lists[table_type].next; - for (i = 1; i < instance; i++) { - table_desc = table_desc->next; - } - - /* We are now pointing to the requested table's descriptor */ - - *return_table = table_desc->pointer; - return_ACPI_STATUS(AE_OK); -} diff --git a/drivers/acpi/tables/tbgetall.c b/drivers/acpi/tables/tbgetall.c deleted file mode 100644 index ad982112e4c6..000000000000 --- a/drivers/acpi/tables/tbgetall.c +++ /dev/null @@ -1,311 +0,0 @@ -/****************************************************************************** - * - * Module Name: tbgetall - Get all required ACPI tables - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2006, 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("tbgetall") - -/* Local prototypes */ -static acpi_status -acpi_tb_get_primary_table(struct acpi_pointer *address, - struct acpi_table_desc *table_info); - -static acpi_status -acpi_tb_get_secondary_table(struct acpi_pointer *address, - acpi_string signature, - struct acpi_table_desc *table_info); - -/******************************************************************************* - * - * FUNCTION: acpi_tb_get_primary_table - * - * PARAMETERS: Address - Physical address of table to retrieve - * *table_info - Where the table info is returned - * - * RETURN: Status - * - * DESCRIPTION: Maps the physical address of table into a logical address - * - ******************************************************************************/ - -static acpi_status -acpi_tb_get_primary_table(struct acpi_pointer *address, - struct acpi_table_desc *table_info) -{ - acpi_status status; - struct acpi_table_header header; - - ACPI_FUNCTION_TRACE(tb_get_primary_table); - - /* Ignore a NULL address in the RSDT */ - - if (!address->pointer.value) { - return_ACPI_STATUS(AE_OK); - } - - /* Get the header in order to get signature and table size */ - - status = acpi_tb_get_table_header(address, &header); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Clear the table_info */ - - ACPI_MEMSET(table_info, 0, sizeof(struct acpi_table_desc)); - - /* - * Check the table signature and make sure it is recognized. - * Also checks the header checksum - */ - table_info->pointer = &header; - status = acpi_tb_recognize_table(table_info, ACPI_TABLE_PRIMARY); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Get the entire table */ - - status = acpi_tb_get_table_body(address, &header, table_info); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Install the table */ - - status = acpi_tb_install_table(table_info); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_get_secondary_table - * - * PARAMETERS: Address - Physical address of table to retrieve - * *table_info - Where the table info is returned - * - * RETURN: Status - * - * DESCRIPTION: Maps the physical address of table into a logical address - * - ******************************************************************************/ - -static acpi_status -acpi_tb_get_secondary_table(struct acpi_pointer *address, - acpi_string signature, - struct acpi_table_desc *table_info) -{ - acpi_status status; - struct acpi_table_header header; - - ACPI_FUNCTION_TRACE_STR(tb_get_secondary_table, signature); - - /* Get the header in order to match the signature */ - - status = acpi_tb_get_table_header(address, &header); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Signature must match request */ - - if (!ACPI_COMPARE_NAME(header.signature, signature)) { - ACPI_ERROR((AE_INFO, - "Incorrect table signature - wanted [%s] found [%4.4s]", - signature, header.signature)); - return_ACPI_STATUS(AE_BAD_SIGNATURE); - } - - /* - * Check the table signature and make sure it is recognized. - * Also checks the header checksum - */ - table_info->pointer = &header; - status = acpi_tb_recognize_table(table_info, ACPI_TABLE_SECONDARY); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Get the entire table */ - - status = acpi_tb_get_table_body(address, &header, table_info); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Install the table */ - - status = acpi_tb_install_table(table_info); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_get_required_tables - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Load and validate tables other than the RSDT. The RSDT must - * already be loaded and validated. - * - * Get the minimum set of ACPI tables, namely: - * - * 1) FADT (via RSDT in loop below) - * 2) FACS (via FADT) - * 3) DSDT (via FADT) - * - ******************************************************************************/ - -acpi_status acpi_tb_get_required_tables(void) -{ - acpi_status status = AE_OK; - u32 i; - struct acpi_table_desc table_info; - struct acpi_pointer address; - - ACPI_FUNCTION_TRACE(tb_get_required_tables); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%d ACPI tables in RSDT\n", - acpi_gbl_rsdt_table_count)); - - address.pointer_type = acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING; - - /* - * Loop through all table pointers found in RSDT. - * This will NOT include the FACS and DSDT - we must get - * them after the loop. - * - * The only tables we are interested in getting here is the FADT and - * any SSDTs. - */ - for (i = 0; i < acpi_gbl_rsdt_table_count; i++) { - - /* Get the table address from the common internal XSDT */ - - address.pointer.value = acpi_gbl_XSDT->table_offset_entry[i]; - - /* - * Get the tables needed by this subsystem (FADT and any SSDTs). - * NOTE: All other tables are completely ignored at this time. - */ - status = acpi_tb_get_primary_table(&address, &table_info); - if ((status != AE_OK) && (status != AE_TABLE_NOT_SUPPORTED)) { - ACPI_WARNING((AE_INFO, - "%s, while getting table at %8.8X%8.8X", - acpi_format_exception(status), - ACPI_FORMAT_UINT64(address.pointer. - value))); - } - } - - /* We must have a FADT to continue */ - - if (!acpi_gbl_FADT) { - ACPI_ERROR((AE_INFO, "No FADT present in RSDT/XSDT")); - return_ACPI_STATUS(AE_NO_ACPI_TABLES); - } - - /* - * Convert the FADT to a common format. This allows earlier revisions of - * the table to coexist with newer versions, using common access code. - */ - status = acpi_tb_convert_table_fadt(); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not convert FADT to internal common format")); - return_ACPI_STATUS(status); - } - - /* Get the FACS (Pointed to by the FADT) */ - - address.pointer.value = acpi_gbl_FADT->xfirmware_ctrl; - - status = acpi_tb_get_secondary_table(&address, FACS_SIG, &table_info); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Could not get/install the FACS")); - return_ACPI_STATUS(status); - } - - /* - * Create the common FACS pointer table - * (Contains pointers to the original table) - */ - status = acpi_tb_build_common_facs(&table_info); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Get/install the DSDT (Pointed to by the FADT) */ - - address.pointer.value = acpi_gbl_FADT->Xdsdt; - - status = acpi_tb_get_secondary_table(&address, DSDT_SIG, &table_info); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, "Could not get/install the DSDT")); - return_ACPI_STATUS(status); - } - - /* Set Integer Width (32/64) based upon DSDT revision */ - - acpi_ut_set_integer_width(acpi_gbl_DSDT->revision); - - /* Dump the entire DSDT */ - - ACPI_DEBUG_PRINT((ACPI_DB_TABLES, - "Hex dump of entire DSDT, size %d (0x%X), Integer width = %d\n", - acpi_gbl_DSDT->length, acpi_gbl_DSDT->length, - acpi_gbl_integer_bit_width)); - - ACPI_DUMP_BUFFER(ACPI_CAST_PTR(u8, acpi_gbl_DSDT), - acpi_gbl_DSDT->length); - - /* Always delete the RSDP mapping, we are done with it */ - - acpi_tb_delete_tables_by_type(ACPI_TABLE_ID_RSDP); - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index 1668a232fb67..9076ca0913b7 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c @@ -42,510 +42,494 @@ */ #include <acpi/acpi.h> +#include <acpi/acnamesp.h> #include <acpi/actables.h> #define _COMPONENT ACPI_TABLES ACPI_MODULE_NAME("tbinstal") -/* Local prototypes */ -static acpi_status -acpi_tb_match_signature(char *signature, - struct acpi_table_desc *table_info, u8 search_type); - -/******************************************************************************* +/****************************************************************************** * - * FUNCTION: acpi_tb_match_signature + * FUNCTION: acpi_tb_verify_table * - * PARAMETERS: Signature - Table signature to match - * table_info - Return data - * search_type - Table type to match (primary/secondary) + * PARAMETERS: table_desc - table * * RETURN: Status * - * DESCRIPTION: Compare signature against the list of "ACPI-subsystem-owned" - * tables (DSDT/FADT/SSDT, etc.) Returns the table_type_iD on match. + * DESCRIPTION: this function is called to verify and map table * - ******************************************************************************/ - -static acpi_status -acpi_tb_match_signature(char *signature, - struct acpi_table_desc *table_info, u8 search_type) + *****************************************************************************/ +acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc) { - acpi_native_uint i; + u8 checksum; - ACPI_FUNCTION_TRACE(tb_match_signature); + ACPI_FUNCTION_TRACE(tb_verify_table); - /* Search for a signature match among the known table types */ + /* Map the table if necessary */ - for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) { - if (!(acpi_gbl_table_data[i].flags & search_type)) { - continue; + if (!table_desc->pointer) { + table_desc->pointer = + acpi_tb_map(table_desc->address, table_desc->length, + table_desc->flags & ACPI_TABLE_ORIGIN_MASK); + if (!table_desc->pointer) { + return_ACPI_STATUS(AE_NO_MEMORY); } + } - if (!ACPI_STRNCMP(signature, acpi_gbl_table_data[i].signature, - acpi_gbl_table_data[i].sig_length)) { + /* FACS is the odd table, has no standard ACPI header and no checksum */ - /* Found a signature match, return index if requested */ + if (ACPI_COMPARE_NAME(&(table_desc->signature), ACPI_SIG_FACS)) { + return_ACPI_STATUS(AE_OK); + } - if (table_info) { - table_info->type = (u8) i; - } + /* Always calculate checksum, ignore bad checksum if requested */ - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Table [%4.4s] is an ACPI table consumed by the core subsystem\n", - (char *)acpi_gbl_table_data[i]. - signature)); + checksum = acpi_tb_checksum(ACPI_CAST_PTR(void, table_desc->pointer), + table_desc->length); - return_ACPI_STATUS(AE_OK); - } - } +#if (ACPI_CHECKSUM_ABORT) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Table [%4.4s] is not an ACPI table consumed by the core subsystem - ignored\n", - (char *)signature)); + if (checksum) { + return_ACPI_STATUS(AE_BAD_CHECKSUM); + } +#endif - return_ACPI_STATUS(AE_TABLE_NOT_SUPPORTED); + return_ACPI_STATUS(AE_OK); } /******************************************************************************* * - * FUNCTION: acpi_tb_install_table + * FUNCTION: acpi_tb_add_table * - * PARAMETERS: table_info - Return value from acpi_tb_get_table_body + * PARAMETERS: Table - Pointer to the table header + * table_index - Where the table index is returned * * RETURN: Status * - * DESCRIPTION: Install the table into the global data structures. + * DESCRIPTION: This function is called to add the ACPI table * ******************************************************************************/ -acpi_status acpi_tb_install_table(struct acpi_table_desc *table_info) +acpi_status +acpi_tb_add_table(struct acpi_table_header *table, + acpi_native_uint * table_index) { - acpi_status status; + acpi_native_uint i; + acpi_native_uint length; + acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE(tb_install_table); + ACPI_FUNCTION_TRACE(tb_add_table); - /* Lock tables while installing */ + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Could not acquire table mutex")); - return_ACPI_STATUS(status); + /* 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->length, + acpi_gbl_root_table_list.tables[i].pointer-> + length); + if (ACPI_MEMCMP + (table, acpi_gbl_root_table_list.tables[i].pointer, + length)) { + continue; + } + + /* Table is already registered */ + + ACPI_FREE(table); + *table_index = i; + goto release; } /* - * Ignore a table that is already installed. For example, some BIOS - * ASL code will repeatedly attempt to load the same SSDT. + * Add the table to the global table list */ - status = acpi_tb_is_table_installed(table_info); + status = acpi_tb_store_table(ACPI_TO_INTEGER(table), + table, table->length, + ACPI_TABLE_ORIGIN_ALLOCATED, table_index); if (ACPI_FAILURE(status)) { - goto unlock_and_exit; + goto release; } - /* Install the table into the global data structure */ + acpi_tb_print_table_header(0, table); - status = acpi_tb_init_table_descriptor(table_info->type, table_info); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Could not install table [%4.4s]", - table_info->pointer->signature)); - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s located at %p\n", - acpi_gbl_table_data[table_info->type].name, - table_info->pointer)); - - unlock_and_exit: + release: (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); return_ACPI_STATUS(status); } /******************************************************************************* * - * FUNCTION: acpi_tb_recognize_table + * FUNCTION: acpi_tb_resize_root_table_list * - * PARAMETERS: table_info - Return value from acpi_tb_get_table_body - * search_type - Table type to match (primary/secondary) + * PARAMETERS: None * * RETURN: Status * - * DESCRIPTION: Check a table signature for a match against known table types - * - * NOTE: All table pointers are validated as follows: - * 1) Table pointer must point to valid physical memory - * 2) Signature must be 4 ASCII chars, even if we don't recognize the - * name - * 3) Table must be readable for length specified in the header - * 4) Table checksum must be valid (with the exception of the FACS - * which has no checksum for some odd reason) + * DESCRIPTION: Expand the size of global table array * ******************************************************************************/ -acpi_status -acpi_tb_recognize_table(struct acpi_table_desc *table_info, u8 search_type) +acpi_status acpi_tb_resize_root_table_list(void) { - struct acpi_table_header *table_header; - acpi_status status; + struct acpi_table_desc *tables; - ACPI_FUNCTION_TRACE(tb_recognize_table); + ACPI_FUNCTION_TRACE(tb_resize_root_table_list); - /* Ensure that we have a valid table pointer */ + /* allow_resize flag is a parameter to acpi_initialize_tables */ - table_header = (struct acpi_table_header *)table_info->pointer; - if (!table_header) { - return_ACPI_STATUS(AE_BAD_PARAMETER); + if (!(acpi_gbl_root_table_list.flags & ACPI_TABLE_FLAGS_ALLOW_RESIZE)) { + ACPI_ERROR((AE_INFO, + "Resize of Root Table Array is not allowed")); + return_ACPI_STATUS(AE_SUPPORT); } - /* - * We only "recognize" a limited number of ACPI tables -- namely, the - * ones that are used by the subsystem (DSDT, FADT, etc.) - * - * An AE_TABLE_NOT_SUPPORTED means that the table was not recognized. - * This can be any one of many valid ACPI tables, it just isn't one of - * the tables that is consumed by the core subsystem - */ - status = acpi_tb_match_signature(table_header->signature, - table_info, search_type); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + /* 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); } - status = acpi_tb_validate_table_header(table_header); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + /* 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_TABLE_ORIGIN_MASK == + ACPI_TABLE_ORIGIN_ALLOCATED) { + ACPI_FREE(acpi_gbl_root_table_list.tables); + } } - /* Return the table type and length via the info struct */ + 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_TABLE_ORIGIN_ALLOCATED | + (acpi_gbl_root_table_list. + flags & + ~ACPI_TABLE_ORIGIN_MASK)); - table_info->length = (acpi_size) table_header->length; - return_ACPI_STATUS(status); + return_ACPI_STATUS(AE_OK); } /******************************************************************************* * - * FUNCTION: acpi_tb_init_table_descriptor + * FUNCTION: acpi_tb_store_table * - * PARAMETERS: table_type - The type of the table - * table_info - A table info struct + * PARAMETERS: Address - Table address + * Table - Table header + * Length - Table length + * Flags - flags * - * RETURN: None. + * RETURN: Status and table index. * - * DESCRIPTION: Install a table into the global data structs. + * DESCRIPTION: Add an ACPI table to the global table list * ******************************************************************************/ acpi_status -acpi_tb_init_table_descriptor(acpi_table_type table_type, - struct acpi_table_desc *table_info) +acpi_tb_store_table(acpi_physical_address address, + struct acpi_table_header *table, + u32 length, u8 flags, acpi_native_uint * table_index) { - struct acpi_table_list *list_head; - struct acpi_table_desc *table_desc; - acpi_status status; - - ACPI_FUNCTION_TRACE_U32(tb_init_table_descriptor, table_type); - - /* Allocate a descriptor for this table */ + acpi_status status = AE_OK; - table_desc = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_table_desc)); - if (!table_desc) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Get a new owner ID for the table */ + /* Ensure that there is room for the table in the Root Table List */ - status = acpi_ut_allocate_owner_id(&table_desc->owner_id); - if (ACPI_FAILURE(status)) { - goto error_exit1; + 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); + } } - /* Install the table into the global data structure */ - - list_head = &acpi_gbl_table_lists[table_type]; + /* 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); +} - /* - * Two major types of tables: 1) Only one instance is allowed. This - * includes most ACPI tables such as the DSDT. 2) Multiple instances of - * the table are allowed. This includes SSDT and PSDTs. - */ - if (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags)) { - /* - * Only one table allowed, and a table has alread been installed - * at this location, so return an error. - */ - if (list_head->next) { - status = AE_ALREADY_EXISTS; - goto error_exit2; - } +/******************************************************************************* + * + * FUNCTION: acpi_tb_delete_table + * + * PARAMETERS: table_index - Table index + * + * RETURN: None + * + * DESCRIPTION: Delete one internal ACPI table + * + ******************************************************************************/ - table_desc->next = list_head->next; - list_head->next = table_desc; +void acpi_tb_delete_table(acpi_native_uint table_index) +{ + struct acpi_table_desc *table_desc; - if (table_desc->next) { - table_desc->next->prev = table_desc; - } + /* table_index assumed valid */ - list_head->count++; - } else { - /* - * Link the new table in to the list of tables of this type. - * Insert at the end of the list, order IS IMPORTANT. - * - * table_desc->Prev & Next are already NULL from calloc() - */ - list_head->count++; - - if (!list_head->next) { - list_head->next = table_desc; - } else { - table_desc->next = list_head->next; + table_desc = &acpi_gbl_root_table_list.tables[table_index]; - while (table_desc->next->next) { - table_desc->next = table_desc->next->next; - } + /* Table must be mapped or allocated */ - table_desc->next->next = table_desc; - table_desc->prev = table_desc->next; - table_desc->next = NULL; - } + if (!table_desc->pointer) { + return; } - /* Finish initialization of the table descriptor */ - - table_desc->loaded_into_namespace = FALSE; - table_desc->type = (u8) table_type; - table_desc->pointer = table_info->pointer; - table_desc->length = table_info->length; - table_desc->allocation = table_info->allocation; - table_desc->aml_start = (u8 *) (table_desc->pointer + 1), - table_desc->aml_length = (u32) - (table_desc->length - (u32) sizeof(struct acpi_table_header)); - - /* - * Set the appropriate global pointer (if there is one) to point to the - * newly installed table - */ - if (acpi_gbl_table_data[table_type].global_ptr) { - *(acpi_gbl_table_data[table_type].global_ptr) = - table_info->pointer; + if (table_desc->flags & ACPI_TABLE_ORIGIN_MAPPED) { + acpi_tb_unmap(table_desc->pointer, table_desc->length, + table_desc->flags & ACPI_TABLE_ORIGIN_MASK); + } else if (table_desc->flags & ACPI_TABLE_ORIGIN_ALLOCATED) { + ACPI_FREE(table_desc->pointer); } - /* Return Data */ - - table_info->owner_id = table_desc->owner_id; - table_info->installed_desc = table_desc; - return_ACPI_STATUS(AE_OK); - - /* Error exit with cleanup */ - - error_exit2: - - acpi_ut_release_owner_id(&table_desc->owner_id); - - error_exit1: - - ACPI_FREE(table_desc); - return_ACPI_STATUS(status); + table_desc->pointer = NULL; } /******************************************************************************* * - * FUNCTION: acpi_tb_delete_all_tables + * FUNCTION: acpi_tb_terminate * - * PARAMETERS: None. + * PARAMETERS: None * - * RETURN: None. + * RETURN: None * * DESCRIPTION: Delete all internal ACPI tables * ******************************************************************************/ -void acpi_tb_delete_all_tables(void) +void acpi_tb_terminate(void) { - acpi_table_type type; + 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(i); + } /* - * Free memory allocated for ACPI tables - * Memory can either be mapped or allocated + * Delete the root table array if allocated locally. Array cannot be + * mapped, so we don't need to check for that flag. */ - for (type = 0; type < (ACPI_TABLE_ID_MAX + 1); type++) { - acpi_tb_delete_tables_by_type(type); + if ((acpi_gbl_root_table_list.flags & ACPI_TABLE_ORIGIN_MASK) == + ACPI_TABLE_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_tables_by_type + * FUNCTION: acpi_tb_delete_namespace_by_owner * - * PARAMETERS: Type - The table type to be deleted + * PARAMETERS: table_index - Table index * - * RETURN: None. + * RETURN: None * - * DESCRIPTION: Delete an internal ACPI table - * Locks the ACPI table mutex + * DESCRIPTION: Delete all namespace objects created when this table was loaded. * ******************************************************************************/ -void acpi_tb_delete_tables_by_type(acpi_table_type type) +void acpi_tb_delete_namespace_by_owner(acpi_native_uint table_index) { - struct acpi_table_desc *table_desc; - u32 count; - u32 i; - - ACPI_FUNCTION_TRACE_U32(tb_delete_tables_by_type, type); - - if (type > ACPI_TABLE_ID_MAX) { - return_VOID; - } + acpi_owner_id owner_id; - if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_TABLES))) { + (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; } - /* Clear the appropriate "typed" global table pointer */ - - switch (type) { - case ACPI_TABLE_ID_RSDP: - acpi_gbl_RSDP = NULL; - break; - - case ACPI_TABLE_ID_DSDT: - acpi_gbl_DSDT = NULL; - break; - - case ACPI_TABLE_ID_FADT: - acpi_gbl_FADT = NULL; - break; - - case ACPI_TABLE_ID_FACS: - acpi_gbl_FACS = NULL; - break; + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + acpi_ns_delete_namespace_by_owner(owner_id); +} - case ACPI_TABLE_ID_XSDT: - acpi_gbl_XSDT = NULL; - break; +/******************************************************************************* + * + * FUNCTION: acpi_tb_allocate_owner_id + * + * PARAMETERS: table_index - Table index + * + * RETURN: Status + * + * DESCRIPTION: Allocates owner_id in table_desc + * + ******************************************************************************/ - case ACPI_TABLE_ID_SSDT: - case ACPI_TABLE_ID_PSDT: - default: - break; - } +acpi_status acpi_tb_allocate_owner_id(acpi_native_uint table_index) +{ + acpi_status status = AE_BAD_PARAMETER; - /* - * Free the table - * 1) Get the head of the list - */ - table_desc = acpi_gbl_table_lists[type].next; - count = acpi_gbl_table_lists[type].count; + ACPI_FUNCTION_TRACE(tb_allocate_owner_id); - /* - * 2) Walk the entire list, deleting both the allocated tables - * and the table descriptors - */ - for (i = 0; i < count; i++) { - table_desc = acpi_tb_uninstall_table(table_desc); + (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_VOID; + return_ACPI_STATUS(status); } /******************************************************************************* * - * FUNCTION: acpi_tb_delete_single_table + * FUNCTION: acpi_tb_release_owner_id * - * PARAMETERS: table_info - A table info struct + * PARAMETERS: table_index - Table index * - * RETURN: None. + * RETURN: Status * - * DESCRIPTION: Low-level free for a single ACPI table. Handles cases where - * the table was allocated a buffer or was mapped. + * DESCRIPTION: Releases owner_id in table_desc * ******************************************************************************/ -void acpi_tb_delete_single_table(struct acpi_table_desc *table_desc) +acpi_status acpi_tb_release_owner_id(acpi_native_uint table_index) { + acpi_status status = AE_BAD_PARAMETER; - /* Must have a valid table descriptor and pointer */ + ACPI_FUNCTION_TRACE(tb_release_owner_id); - if ((!table_desc) || (!table_desc->pointer)) { - return; + (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; } - /* Valid table, determine type of memory allocation */ - - switch (table_desc->allocation) { - case ACPI_MEM_NOT_ALLOCATED: - break; - - case ACPI_MEM_ALLOCATED: - - ACPI_FREE(table_desc->pointer); - break; - - case ACPI_MEM_MAPPED: - - acpi_os_unmap_memory(table_desc->pointer, table_desc->length); - break; - - default: - break; - } + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(status); } /******************************************************************************* * - * FUNCTION: acpi_tb_uninstall_table + * FUNCTION: acpi_tb_get_owner_id * - * PARAMETERS: table_info - A table info struct + * PARAMETERS: table_index - Table index + * owner_id - Where the table owner_id is returned * - * RETURN: Pointer to the next table in the list (of same type) + * RETURN: Status * - * DESCRIPTION: Free the memory associated with an internal ACPI table that - * is either installed or has never been installed. - * Table mutex should be locked. + * DESCRIPTION: returns owner_id for the ACPI table * ******************************************************************************/ -struct acpi_table_desc *acpi_tb_uninstall_table(struct acpi_table_desc - *table_desc) +acpi_status +acpi_tb_get_owner_id(acpi_native_uint table_index, acpi_owner_id * owner_id) { - struct acpi_table_desc *next_desc; + acpi_status status = AE_BAD_PARAMETER; - ACPI_FUNCTION_TRACE_PTR(tb_uninstall_table, table_desc); + ACPI_FUNCTION_TRACE(tb_get_owner_id); - if (!table_desc) { - return_PTR(NULL); + (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; } - /* Unlink the descriptor from the doubly linked list */ + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(status); +} - if (table_desc->prev) { - table_desc->prev->next = table_desc->next; - } else { - /* Is first on list, update list head */ +/******************************************************************************* + * + * FUNCTION: acpi_tb_is_table_loaded + * + * PARAMETERS: table_index - Table index + * + * RETURN: Table Loaded Flag + * + ******************************************************************************/ - acpi_gbl_table_lists[table_desc->type].next = table_desc->next; - } +u8 acpi_tb_is_table_loaded(acpi_native_uint table_index) +{ + u8 is_loaded = FALSE; - if (table_desc->next) { - table_desc->next->prev = table_desc->prev; + (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_FLAGS_LOADED); } - /* Free the memory allocated for the table itself */ - - acpi_tb_delete_single_table(table_desc); - - /* Free the owner ID associated with this table */ - - acpi_ut_release_owner_id(&table_desc->owner_id); + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return (is_loaded); +} - /* Free the table descriptor */ +/******************************************************************************* + * + * 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. + * + ******************************************************************************/ - next_desc = table_desc->next; - ACPI_FREE(table_desc); +void acpi_tb_set_table_loaded_flag(acpi_native_uint table_index, u8 is_loaded) +{ - /* Return pointer to the next descriptor */ + (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_FLAGS_LOADED; + } else { + acpi_gbl_root_table_list.tables[table_index].flags &= + ~ACPI_TABLE_FLAGS_LOADED; + } + } - return_PTR(next_desc); + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); } diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c deleted file mode 100644 index 86a5fca9b739..000000000000 --- a/drivers/acpi/tables/tbrsdt.c +++ /dev/null @@ -1,307 +0,0 @@ -/****************************************************************************** - * - * Module Name: tbrsdt - ACPI RSDT table utilities - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2006, 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("tbrsdt") - -/******************************************************************************* - * - * FUNCTION: acpi_tb_verify_rsdp - * - * PARAMETERS: Address - RSDP (Pointer to RSDT) - * - * RETURN: Status - * - * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table) - * - ******************************************************************************/ -acpi_status acpi_tb_verify_rsdp(struct acpi_pointer *address) -{ - struct acpi_table_desc table_info; - acpi_status status; - struct rsdp_descriptor *rsdp; - - ACPI_FUNCTION_TRACE(tb_verify_rsdp); - - switch (address->pointer_type) { - case ACPI_LOGICAL_POINTER: - - rsdp = address->pointer.logical; - break; - - case ACPI_PHYSICAL_POINTER: - /* - * Obtain access to the RSDP structure - */ - status = acpi_os_map_memory(address->pointer.physical, - sizeof(struct rsdp_descriptor), - ACPI_CAST_PTR(void, &rsdp)); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - break; - - default: - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Verify RSDP signature and checksum */ - - status = acpi_tb_validate_rsdp(rsdp); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* RSDP is ok. Init the table info */ - - table_info.pointer = ACPI_CAST_PTR(struct acpi_table_header, rsdp); - table_info.length = sizeof(struct rsdp_descriptor); - - if (address->pointer_type == ACPI_PHYSICAL_POINTER) { - table_info.allocation = ACPI_MEM_MAPPED; - } else { - table_info.allocation = ACPI_MEM_NOT_ALLOCATED; - } - - /* Save the table pointers and allocation info */ - - status = acpi_tb_init_table_descriptor(ACPI_TABLE_ID_RSDP, &table_info); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* Save the RSDP in a global for easy access */ - - acpi_gbl_RSDP = - ACPI_CAST_PTR(struct rsdp_descriptor, table_info.pointer); - return_ACPI_STATUS(status); - - /* Error exit */ - cleanup: - - if (acpi_gbl_table_flags & ACPI_PHYSICAL_POINTER) { - acpi_os_unmap_memory(rsdp, sizeof(struct rsdp_descriptor)); - } - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_get_rsdt_address - * - * PARAMETERS: out_address - Where the address is returned - * - * RETURN: None, Address - * - * DESCRIPTION: Extract the address of either the RSDT or XSDT, depending on the - * version of the RSDP and whether the XSDT pointer is valid - * - ******************************************************************************/ - -void acpi_tb_get_rsdt_address(struct acpi_pointer *out_address) -{ - - ACPI_FUNCTION_ENTRY(); - - out_address->pointer_type = - acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING; - - /* Use XSDT if it is present */ - - if ((acpi_gbl_RSDP->revision >= 2) && - acpi_gbl_RSDP->xsdt_physical_address) { - out_address->pointer.value = - acpi_gbl_RSDP->xsdt_physical_address; - acpi_gbl_root_table_type = ACPI_TABLE_TYPE_XSDT; - } else { - /* No XSDT, use the RSDT */ - - out_address->pointer.value = - acpi_gbl_RSDP->rsdt_physical_address; - acpi_gbl_root_table_type = ACPI_TABLE_TYPE_RSDT; - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_validate_rsdt - * - * PARAMETERS: table_ptr - Addressable pointer to the RSDT. - * - * RETURN: Status - * - * DESCRIPTION: Validate signature for the RSDT or XSDT - * - ******************************************************************************/ - -acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr) -{ - char *signature; - - ACPI_FUNCTION_ENTRY(); - - /* Validate minimum length */ - - if (table_ptr->length < sizeof(struct acpi_table_header)) { - ACPI_ERROR((AE_INFO, - "RSDT/XSDT length (%X) is smaller than minimum (%zX)", - table_ptr->length, - sizeof(struct acpi_table_header))); - - return (AE_INVALID_TABLE_LENGTH); - } - - /* Search for appropriate signature, RSDT or XSDT */ - - if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { - signature = RSDT_SIG; - } else { - signature = XSDT_SIG; - } - - if (!ACPI_COMPARE_NAME(table_ptr->signature, signature)) { - - /* Invalid RSDT or XSDT signature */ - - ACPI_ERROR((AE_INFO, - "Invalid signature where RSDP indicates RSDT/XSDT should be located. RSDP:")); - - ACPI_DUMP_BUFFER(acpi_gbl_RSDP, 20); - - ACPI_ERROR((AE_INFO, - "RSDT/XSDT signature at %X is invalid", - acpi_gbl_RSDP->rsdt_physical_address)); - - if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { - ACPI_ERROR((AE_INFO, "Looking for RSDT")); - } else { - ACPI_ERROR((AE_INFO, "Looking for XSDT")); - } - - ACPI_DUMP_BUFFER(ACPI_CAST_PTR(char, table_ptr), 48); - return (AE_BAD_SIGNATURE); - } - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_get_table_rsdt - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table) - * - ******************************************************************************/ - -acpi_status acpi_tb_get_table_rsdt(void) -{ - struct acpi_table_desc table_info; - acpi_status status; - struct acpi_pointer address; - - ACPI_FUNCTION_TRACE(tb_get_table_rsdt); - - /* Get the RSDT/XSDT via the RSDP */ - - acpi_tb_get_rsdt_address(&address); - - table_info.type = ACPI_TABLE_ID_XSDT; - status = acpi_tb_get_table(&address, &table_info); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Could not get the RSDT/XSDT")); - return_ACPI_STATUS(status); - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "RSDP located at %p, points to RSDT physical=%8.8X%8.8X\n", - acpi_gbl_RSDP, - ACPI_FORMAT_UINT64(address.pointer.value))); - - /* Check the RSDT or XSDT signature */ - - status = acpi_tb_validate_rsdt(table_info.pointer); - if (ACPI_FAILURE(status)) { - goto error_cleanup; - } - - /* Get the number of tables defined in the RSDT or XSDT */ - - acpi_gbl_rsdt_table_count = acpi_tb_get_table_count(acpi_gbl_RSDP, - table_info.pointer); - - /* Convert and/or copy to an XSDT structure */ - - status = acpi_tb_convert_to_xsdt(&table_info); - if (ACPI_FAILURE(status)) { - goto error_cleanup; - } - - /* Save the table pointers and allocation info */ - - status = acpi_tb_init_table_descriptor(ACPI_TABLE_ID_XSDT, &table_info); - if (ACPI_FAILURE(status)) { - goto error_cleanup; - } - - acpi_gbl_XSDT = - ACPI_CAST_PTR(struct xsdt_descriptor, table_info.pointer); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "XSDT located at %p\n", acpi_gbl_XSDT)); - return_ACPI_STATUS(status); - - error_cleanup: - - /* Free table allocated by acpi_tb_get_table */ - - acpi_tb_delete_single_table(&table_info); - - return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index 209a401801e3..3620ac5f8681 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Module Name: tbutils - Table manipulation utilities + * Module Name: tbutils - table utilities * *****************************************************************************/ @@ -48,295 +48,507 @@ ACPI_MODULE_NAME("tbutils") /* Local prototypes */ -#ifdef ACPI_OBSOLETE_FUNCTIONS -acpi_status -acpi_tb_handle_to_object(u16 table_id, struct acpi_table_desc **table_desc); -#endif +static void acpi_tb_parse_fadt(struct acpi_table_fadt *fadt, u8 flags); + +static void inline +acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct, + u8 bit_width, acpi_physical_address address); /******************************************************************************* * - * FUNCTION: acpi_tb_is_table_installed + * FUNCTION: acpi_tb_print_table_header * - * PARAMETERS: new_table_desc - Descriptor for new table being installed + * PARAMETERS: Address - Table physical address + * Header - Table header * - * RETURN: Status - AE_ALREADY_EXISTS if the table is already installed + * RETURN: None * - * DESCRIPTION: Determine if an ACPI table is already installed - * - * MUTEX: Table data structures should be locked + * DESCRIPTION: Print an ACPI table header * ******************************************************************************/ -acpi_status acpi_tb_is_table_installed(struct acpi_table_desc *new_table_desc) +void +acpi_tb_print_table_header(acpi_physical_address address, + struct acpi_table_header *header) { - struct acpi_table_desc *table_desc; - - ACPI_FUNCTION_TRACE(tb_is_table_installed); - - /* Get the list descriptor and first table descriptor */ - - table_desc = acpi_gbl_table_lists[new_table_desc->type].next; - - /* Examine all installed tables of this type */ - - while (table_desc) { - /* - * If the table lengths match, perform a full bytewise compare. This - * means that we will allow tables with duplicate oem_table_id(s), as - * long as the tables are different in some way. - * - * Checking if the table has been loaded into the namespace means that - * we don't check for duplicate tables during the initial installation - * of tables within the RSDT/XSDT. - */ - if ((table_desc->loaded_into_namespace) && - (table_desc->pointer->length == - new_table_desc->pointer->length) - && - (!ACPI_MEMCMP - (table_desc->pointer, new_table_desc->pointer, - new_table_desc->pointer->length))) { - - /* Match: this table is already installed */ - - ACPI_DEBUG_PRINT((ACPI_DB_TABLES, - "Table [%4.4s] already installed: Rev %X OemTableId [%8.8s]\n", - new_table_desc->pointer->signature, - new_table_desc->pointer->revision, - new_table_desc->pointer-> - oem_table_id)); - - new_table_desc->owner_id = table_desc->owner_id; - new_table_desc->installed_desc = table_desc; - - return_ACPI_STATUS(AE_ALREADY_EXISTS); - } - - /* Get next table on the list */ - table_desc = table_desc->next; - } - - return_ACPI_STATUS(AE_OK); + ACPI_INFO((AE_INFO, + "%4.4s @ 0x%p Length 0x%04X (v%3.3d %6.6s %8.8s 0x%08X %4.4s 0x%08X)", + header->signature, ACPI_CAST_PTR(void, 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_table_header - * - * PARAMETERS: table_header - Logical pointer to the table + * FUNCTION: acpi_tb_init_generic_address * - * RETURN: Status + * PARAMETERS: new_gas_struct - GAS struct to be initialized + * bit_width - Width of this register + * Address - Address of the register * - * DESCRIPTION: Check an ACPI table header for validity + * RETURN: None * - * NOTE: Table pointers are validated as follows: - * 1) Table pointer must point to valid physical memory - * 2) Signature must be 4 ASCII chars, even if we don't recognize the - * name - * 3) Table must be readable for length specified in the header - * 4) Table checksum must be valid (with the exception of the FACS - * which has no checksum because it contains variable fields) + * DESCRIPTION: Initialize a GAS structure. * ******************************************************************************/ -acpi_status -acpi_tb_validate_table_header(struct acpi_table_header *table_header) +static void inline +acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct, + u8 bit_width, acpi_physical_address address) { - acpi_name signature; - - ACPI_FUNCTION_ENTRY(); - - /* Verify that this is a valid address */ - - if (!acpi_os_readable(table_header, sizeof(struct acpi_table_header))) { - ACPI_ERROR((AE_INFO, - "Cannot read table header at %p", table_header)); - - return (AE_BAD_ADDRESS); - } - - /* Ensure that the signature is 4 ASCII characters */ - - ACPI_MOVE_32_TO_32(&signature, table_header->signature); - if (!acpi_ut_valid_acpi_name(signature)) { - ACPI_ERROR((AE_INFO, "Invalid table signature 0x%8.8X", - signature)); - ACPI_DUMP_BUFFER(table_header, - sizeof(struct acpi_table_header)); - return (AE_BAD_SIGNATURE); - } - - /* Validate the table length */ - - if (table_header->length < sizeof(struct acpi_table_header)) { - ACPI_ERROR((AE_INFO, - "Invalid length 0x%X in table with signature %4.4s", - (u32) table_header->length, - ACPI_CAST_PTR(char, &signature))); - - ACPI_DUMP_BUFFER(table_header, - sizeof(struct acpi_table_header)); - return (AE_BAD_HEADER); - } - - return (AE_OK); + ACPI_STORE_ADDRESS(new_gas_struct->address, address); + new_gas_struct->space_id = ACPI_ADR_SPACE_SYSTEM_IO; + new_gas_struct->bit_width = bit_width; + new_gas_struct->bit_offset = 0; + new_gas_struct->access_width = 0; } /******************************************************************************* * - * FUNCTION: acpi_tb_sum_table + * FUNCTION: acpi_tb_checksum * - * PARAMETERS: Buffer - Buffer to sum - * Length - Size of the buffer + * PARAMETERS: Buffer - Pointer to memory region to be checked + * Length - Length of this memory region * - * RETURN: 8 bit sum of buffer + * RETURN: Checksum (u8) * - * DESCRIPTION: Computes an 8 bit sum of the buffer(length) and returns it. + * DESCRIPTION: Calculates circular checksum of memory region. * ******************************************************************************/ -u8 acpi_tb_sum_table(void *buffer, u32 length) +u8 acpi_tb_checksum(u8 * buffer, acpi_native_uint length) { - acpi_native_uint i; u8 sum = 0; + u8 *end = buffer + length; - if (!buffer || !length) { - return (0); + while (buffer < end) { + sum = (u8) (sum + *(buffer++)); } - for (i = 0; i < length; i++) { - sum = (u8) (sum + ((u8 *) buffer)[i]); - } - return (sum); + return sum; } /******************************************************************************* * - * FUNCTION: acpi_tb_generate_checksum + * FUNCTION: acpi_tb_convert_fadt * - * PARAMETERS: Table - Pointer to a valid ACPI table (with a - * standard ACPI header) + * PARAMETERS: Fadt - FADT table to be converted * - * RETURN: 8 bit checksum of buffer + * RETURN: None * - * DESCRIPTION: Computes an 8 bit checksum of the table. + * DESCRIPTION: Converts a BIOS supplied ACPI 1.0 FADT to a local + * ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply + * copied to the local FADT. The ACPI CA software uses this + * local FADT. Thus a significant amount of special #ifdef + * type codeing is saved. * ******************************************************************************/ -u8 acpi_tb_generate_checksum(struct acpi_table_header * table) +void acpi_tb_convert_fadt(struct acpi_table_fadt *fadt) { - u8 checksum; - - /* Sum the entire table as-is */ - checksum = acpi_tb_sum_table(table, table->length); + /* + * Convert table pointers to 64-bit fields + */ + if (!acpi_gbl_FADT.Xfacs) { + acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs; + } - /* Subtract off the existing checksum value in the table */ + if (!acpi_gbl_FADT.Xdsdt) { + acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt; + } - checksum = (u8) (checksum - table->checksum); + /* + * Convert the V1.0 block addresses to V2.0 GAS structures + */ + acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm1a_event_block, + acpi_gbl_FADT.pm1_event_length, + (acpi_physical_address) acpi_gbl_FADT. + pm1a_event_block); + acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm1b_event_block, + acpi_gbl_FADT.pm1_event_length, + (acpi_physical_address) acpi_gbl_FADT. + pm1b_event_block); + acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm1a_control_block, + acpi_gbl_FADT.pm1_control_length, + (acpi_physical_address) acpi_gbl_FADT. + pm1a_control_block); + acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm1b_control_block, + acpi_gbl_FADT.pm1_control_length, + (acpi_physical_address) acpi_gbl_FADT. + pm1b_control_block); + acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm2_control_block, + acpi_gbl_FADT.pm2_control_length, + (acpi_physical_address) acpi_gbl_FADT. + pm2_control_block); + acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm_timer_block, + acpi_gbl_FADT.pm_timer_length, + (acpi_physical_address) acpi_gbl_FADT. + pm_timer_block); + acpi_tb_init_generic_address(&acpi_gbl_FADT.xgpe0_block, 0, + (acpi_physical_address) acpi_gbl_FADT. + gpe0_block); + acpi_tb_init_generic_address(&acpi_gbl_FADT.xgpe1_block, 0, + (acpi_physical_address) acpi_gbl_FADT. + gpe1_block); + + /* + * Create separate GAS structs for the PM1 Enable registers + */ + acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, + (u8) ACPI_DIV_2(acpi_gbl_FADT. + pm1_event_length), + (acpi_physical_address) + (acpi_gbl_FADT.xpm1a_event_block.address + + ACPI_DIV_2(acpi_gbl_FADT. + pm1_event_length))); + + /* + * PM1B is optional; leave null if not present + */ + if (acpi_gbl_FADT.xpm1b_event_block.address) { + acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, + (u8) ACPI_DIV_2(acpi_gbl_FADT. + pm1_event_length), + (acpi_physical_address) + (acpi_gbl_FADT.xpm1b_event_block. + address + + ACPI_DIV_2(acpi_gbl_FADT. + pm1_event_length))); + } - /* Compute the final checksum */ + /* Global FADT is the new common V2.0 FADT */ - checksum = (u8) (0 - checksum); - return (checksum); + acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); } /******************************************************************************* * - * FUNCTION: acpi_tb_set_checksum + * FUNCTION: acpi_tb_parse_fadt * - * PARAMETERS: Table - Pointer to a valid ACPI table (with a - * standard ACPI header) + * PARAMETERS: Fadt - Pointer to FADT table + * Flags - Flags * - * RETURN: None. Sets the table checksum field + * RETURN: none * - * DESCRIPTION: Computes an 8 bit checksum of the table and inserts the - * checksum into the table header. + * DESCRIPTION: This function is called to initialise the FADT, DSDT and FACS + * tables (FADT contains the addresses of the DSDT and FACS) * ******************************************************************************/ -void acpi_tb_set_checksum(struct acpi_table_header *table) +static void acpi_tb_parse_fadt(struct acpi_table_fadt *fadt, u8 flags) { + acpi_physical_address dsdt_address = + (acpi_physical_address) fadt->Xdsdt; + acpi_physical_address facs_address = + (acpi_physical_address) fadt->Xfacs; + struct acpi_table_header *table; + + if (!dsdt_address) { + goto no_dsdt; + } + + table = + acpi_os_map_memory(dsdt_address, sizeof(struct acpi_table_header)); + if (!table) { + goto no_dsdt; + } + + /* Initialize the DSDT table */ + + ACPI_MOVE_32_TO_32(& + (acpi_gbl_root_table_list. + tables[ACPI_TABLE_INDEX_DSDT].signature), + ACPI_SIG_DSDT); + + acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].address = + dsdt_address; + acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length = + table->length; + acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags = flags; + + acpi_tb_print_table_header(dsdt_address, table); + + /* Global integer width is based upon revision of the DSDT */ + + acpi_ut_set_integer_width(table->revision); + acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); + + no_dsdt: + if (!facs_address) { + return; + } - table->checksum = acpi_tb_generate_checksum(table); + table = + acpi_os_map_memory(facs_address, sizeof(struct acpi_table_header)); + if (!table) { + return; + } + + /* Initialize the FACS table */ + + ACPI_MOVE_32_TO_32(& + (acpi_gbl_root_table_list. + tables[ACPI_TABLE_INDEX_FACS].signature), + ACPI_SIG_FACS); + + acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_FACS].address = + facs_address; + acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_FACS].length = + table->length; + acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_FACS].flags = flags; + + ACPI_INFO((AE_INFO, "%4.4s @ 0x%p", + table->signature, ACPI_CAST_PTR(void, facs_address))); + + acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); } /******************************************************************************* * - * FUNCTION: acpi_tb_verify_table_checksum + * FUNCTION: acpi_tb_parse_root_table * - * PARAMETERS: *table_header - ACPI table to verify + * PARAMETERS: Rsdp - Pointer to the RSDP + * Flags - Flags + * + * RETURN: Status * - * RETURN: 8 bit checksum of table + * DESCRIPTION: This function is called to parse the Root System Description + * Table (RSDT or XSDT) * - * DESCRIPTION: Generates an 8 bit checksum of table and returns and compares - * it to the existing checksum value. + * 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 -acpi_tb_verify_table_checksum(struct acpi_table_header *table_header) +acpi_status acpi_tb_parse_root_table(struct acpi_table_rsdp *rsdp, u8 flags) { + struct acpi_table_header *table; + acpi_physical_address address; + u32 length; + u8 *table_entry; + acpi_native_uint i; + acpi_native_uint pointer_size; + u32 table_count; u8 checksum; + acpi_status status; + + ACPI_FUNCTION_TRACE(tb_parse_root_table); + + /* 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_native_uint) rsdp->xsdt_physical_address; + pointer_size = sizeof(u64); + } else { + /* Root table is an RSDT (32-bit physical addresses) */ + + address = (acpi_native_uint) rsdp->rsdt_physical_address; + pointer_size = sizeof(u32); + } - ACPI_FUNCTION_TRACE(tb_verify_table_checksum); + /* Map the table header to get the full table length */ - /* Compute the checksum on the table */ + table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); + if (!table) { + return (AE_NO_MEMORY); + } + + /* 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 (AE_INVALID_TABLE_LENGTH); + } + + table = acpi_os_map_memory(address, length); + if (!table) { + return (AE_NO_MEMORY); + } + + /* Validate the root table checksum */ + + checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length); +#if (ACPI_CHECKSUM_ABORT) + + if (checksum) { + acpi_os_unmap_memory(table, length); + return (AE_BAD_CHECKSUM); + } +#endif + + acpi_tb_print_table_header(address, table); + + /* Calculate the number of tables described in the root table */ + + table_count = + (table->length - sizeof(struct acpi_table_header)) / pointer_size; + + /* Setup loop */ - checksum = acpi_tb_generate_checksum(table_header); + table_entry = + ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header); + acpi_gbl_root_table_list.count = 2; - /* Checksum ok? */ + /* + * Initialize the ACPI table entries + * First two entries in the table array are reserved for the DSDT and FACS + */ + for (i = 0; i < table_count; ++i, table_entry += pointer_size) { - if (checksum == table_header->checksum) { - return_ACPI_STATUS(AE_OK); + /* Ensure there is room for another table entry */ + + if (acpi_gbl_root_table_list.count >= + acpi_gbl_root_table_list.size) { + 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 physical address (32-bit for RSDT, 64-bit for XSDT) */ + + if (pointer_size == sizeof(u32)) { + acpi_gbl_root_table_list. + tables[acpi_gbl_root_table_list.count].address = + (acpi_physical_address) (*ACPI_CAST_PTR + (u32, table_entry)); + } else { + acpi_gbl_root_table_list. + tables[acpi_gbl_root_table_list.count].address = + (acpi_physical_address) (*ACPI_CAST_PTR + (u64, table_entry)); + } + + acpi_gbl_root_table_list.count++; } - ACPI_WARNING((AE_INFO, - "Incorrect checksum in table [%4.4s] - is %2.2X, should be %2.2X", - table_header->signature, table_header->checksum, - checksum)); + /* + * 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); + + /* Initialize all tables other than the DSDT and FACS */ + + for (i = 2; i < acpi_gbl_root_table_list.count; i++) { + address = acpi_gbl_root_table_list.tables[i].address; + length = sizeof(struct acpi_table_header); + + table = acpi_os_map_memory(address, length); + if (!table) { + continue; + } + + acpi_gbl_root_table_list.tables[i].length = table->length; + acpi_gbl_root_table_list.tables[i].flags = flags; + + ACPI_MOVE_32_TO_32(& + (acpi_gbl_root_table_list.tables[i]. + signature), table->signature); + + acpi_tb_print_table_header(address, table); + + /* + * Special case for the FADT because of multiple versions - + * get a local copy and convert to common format + */ + if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_FADT)) { + acpi_os_unmap_memory(table, length); + length = table->length; + + table = acpi_os_map_memory(address, length); + if (!table) { + continue; + } + + /* Copy the entire FADT locally */ + + ACPI_MEMCPY(&acpi_gbl_FADT, table, + ACPI_MIN(table->length, + sizeof(struct acpi_table_fadt))); + + /* Small table means old revision, convert to new */ + + if (table->length < sizeof(struct acpi_table_fadt)) { + acpi_tb_convert_fadt(ACPI_CAST_PTR + (struct acpi_table_fadt, + table)); + } + + /* Unmap original FADT */ - return_ACPI_STATUS(AE_BAD_CHECKSUM); + acpi_os_unmap_memory(table, length); + acpi_tb_parse_fadt(&acpi_gbl_FADT, flags); + } else { + acpi_os_unmap_memory(table, length); + } + } + + return_ACPI_STATUS(AE_OK); } -#ifdef ACPI_OBSOLETE_FUNCTIONS -/******************************************************************************* +/****************************************************************************** * - * FUNCTION: acpi_tb_handle_to_object + * FUNCTION: acpi_tb_map * - * PARAMETERS: table_id - Id for which the function is searching - * table_desc - Pointer to return the matching table - * descriptor. + * PARAMETERS: Address - Address to be mapped + * Length - Length to be mapped + * Flags - Logical or physical addressing mode * - * RETURN: Search the tables to find one with a matching table_id and - * return a pointer to that table descriptor. + * RETURN: Pointer to mapped region * - ******************************************************************************/ + * DESCRIPTION: Maps memory according to flag + * + *****************************************************************************/ -acpi_status -acpi_tb_handle_to_object(u16 table_id, - struct acpi_table_desc **return_table_desc) +void *acpi_tb_map(acpi_physical_address address, u32 length, u32 flags) { - u32 i; - struct acpi_table_desc *table_desc; - ACPI_FUNCTION_NAME(tb_handle_to_object); + if (flags == ACPI_TABLE_ORIGIN_MAPPED) { + return (acpi_os_map_memory(address, length)); + } else { + return (ACPI_CAST_PTR(void, address)); + } +} - for (i = 0; i < ACPI_TABLE_MAX; i++) { - table_desc = acpi_gbl_table_lists[i].next; - while (table_desc) { - if (table_desc->table_id == table_id) { - *return_table_desc = table_desc; - return (AE_OK); - } +/****************************************************************************** + * + * FUNCTION: acpi_tb_unmap + * + * PARAMETERS: Pointer - To mapped region + * Length - Length to be unmapped + * Flags - Logical or physical addressing mode + * + * RETURN: None + * + * DESCRIPTION: Unmaps memory according to flag + * + *****************************************************************************/ - table_desc = table_desc->next; - } - } +void acpi_tb_unmap(void *pointer, u32 length, u32 flags) +{ - ACPI_ERROR((AE_INFO, "TableId=%X does not exist", table_id)); - return (AE_BAD_PARAMETER); + if (flags == ACPI_TABLE_ORIGIN_MAPPED) { + acpi_os_unmap_memory(pointer, length); + } } -#endif diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index 5ba9303293ad..77439fc36c32 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c @@ -49,80 +49,146 @@ #define _COMPONENT ACPI_TABLES ACPI_MODULE_NAME("tbxface") +/* Local prototypes */ +static acpi_status acpi_tb_load_namespace(void); + /******************************************************************************* * - * FUNCTION: acpi_load_tables + * FUNCTION: acpi_initialize_tables * - * PARAMETERS: None + * 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: This function is called to load the ACPI tables from the - * provided RSDT + * 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 acpi_load_tables(void) + +acpi_status +acpi_initialize_tables(struct acpi_table_desc *initial_table_array, + u32 initial_table_count, u8 allow_resize) { - struct acpi_pointer rsdp_address; + acpi_physical_address address; acpi_status status; + struct acpi_table_rsdp *rsdp; - ACPI_FUNCTION_TRACE(acpi_load_tables); + ACPI_FUNCTION_TRACE(acpi_initialize_tables); - /* Get the RSDP */ + /* + * Set up the Root Table Array + * Allocate the table array if requested + */ + if (!initial_table_array) { + acpi_gbl_root_table_list.size = initial_table_count; + acpi_gbl_root_table_list.flags = ACPI_TABLE_FLAGS_ALLOW_RESIZE; - status = acpi_os_get_root_pointer(ACPI_LOGICAL_ADDRESSING, - &rsdp_address); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Could not get the RSDP")); - goto error_exit; + status = acpi_tb_resize_root_table_list(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } else { + /* Root Table Array has been statically allocated by the host */ + + 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_TABLE_ORIGIN_UNKNOWN; + if (allow_resize) { + acpi_gbl_root_table_list.flags = + ACPI_TABLE_FLAGS_ALLOW_RESIZE; + } } - /* Map and validate the RSDP */ + /* Get the RSDP and map it */ - acpi_gbl_table_flags = rsdp_address.pointer_type; + address = acpi_os_get_root_pointer(); + if (!address) { + return_ACPI_STATUS(AE_NOT_FOUND); + } - status = acpi_tb_verify_rsdp(&rsdp_address); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During RSDP validation")); - goto error_exit; + rsdp = acpi_os_map_memory(address, sizeof(struct acpi_table_rsdp)); + if (!rsdp) { + return_ACPI_STATUS(AE_NO_MEMORY); } - /* Get the RSDT via the RSDP */ + ACPI_INFO((AE_INFO, "%.8s @ 0x%p", + rsdp->signature, ACPI_CAST_PTR(void, address))); - status = acpi_tb_get_table_rsdt(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Could not load RSDT")); - goto error_exit; - } + /* + * 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, ACPI_TABLE_ORIGIN_MAPPED); + acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp)); + return_ACPI_STATUS(status); +} - /* Now get the tables needed by this subsystem (FADT, DSDT, etc.) */ +ACPI_EXPORT_SYMBOL(acpi_initialize_tables) - status = acpi_tb_get_required_tables(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Could not get all required tables (DSDT/FADT/FACS)")); - goto error_exit; +/******************************************************************************* + * + * 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_TABLE_ORIGIN_MASK) != + ACPI_TABLE_ORIGIN_UNKNOWN) { + return_ACPI_STATUS(AE_SUPPORT); } - ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); + new_size = + (acpi_gbl_root_table_list.count + + ACPI_ROOT_TABLE_SIZE_INCREMENT) * sizeof(struct acpi_table_desc); - /* Load the namespace from the tables */ + /* Create new array and copy the old array */ - status = acpi_ns_load_namespace(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Could not load namespace")); - goto error_exit; + tables = ACPI_ALLOCATE_ZEROED(new_size); + if (!tables) { + return_ACPI_STATUS(AE_NO_MEMORY); } - return_ACPI_STATUS(AE_OK); + ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, new_size); - error_exit: - ACPI_EXCEPTION((AE_INFO, status, "Could not load tables")); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_load_tables) + 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_TABLE_ORIGIN_ALLOCATED | ACPI_TABLE_FLAGS_ALLOW_RESIZE; + return_ACPI_STATUS(AE_OK); +} /******************************************************************************* * * FUNCTION: acpi_load_table @@ -141,342 +207,358 @@ ACPI_EXPORT_SYMBOL(acpi_load_tables) acpi_status acpi_load_table(struct acpi_table_header *table_ptr) { acpi_status status; - struct acpi_table_desc table_info; - struct acpi_pointer address; - - ACPI_FUNCTION_TRACE(acpi_load_table); - - if (!table_ptr) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } + acpi_native_uint table_index; - /* Copy the table to a local buffer */ - - address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING; - address.pointer.logical = table_ptr; - - status = acpi_tb_get_table_body(&address, table_ptr, &table_info); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Check signature for a valid table type */ - - status = acpi_tb_recognize_table(&table_info, ACPI_TABLE_ALL); + /* + * Install the new table into the local data structures + */ + status = acpi_tb_add_table(table_ptr, &table_index); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } + status = acpi_ns_load_table(table_index, acpi_gbl_root_node); + return_ACPI_STATUS(status); +} - /* Install the new table into the local data structures */ - - status = acpi_tb_install_table(&table_info); - if (ACPI_FAILURE(status)) { - if (status == AE_ALREADY_EXISTS) { +ACPI_EXPORT_SYMBOL(acpi_load_table) - /* Table already exists, no error */ +/****************************************************************************** + * + * FUNCTION: acpi_get_table_header + * + * PARAMETERS: Signature - ACPI signature of needed table + * Instance - Which instance (for SSDTs) + * out_table_header - Where the pointer to the table header + * is returned + * + * 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; - status = AE_OK; + /* + * 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; } - /* Free table allocated by acpi_tb_get_table_body */ - - acpi_tb_delete_single_table(&table_info); - return_ACPI_STATUS(status); - } - - /* Convert the table to common format if necessary */ - - switch (table_info.type) { - case ACPI_TABLE_ID_FADT: - - status = acpi_tb_convert_table_fadt(); - break; - - case ACPI_TABLE_ID_FACS: - - status = acpi_tb_build_common_facs(&table_info); - break; - - default: - /* Load table into namespace if it contains executable AML */ - - status = - acpi_ns_load_table(table_info.installed_desc, - acpi_gbl_root_node); - break; - } + if (++j < instance) { + continue; + } - if (ACPI_FAILURE(status)) { + *out_table_header = + acpi_tb_map(acpi_gbl_root_table_list.tables[i].address, + (u32) sizeof(struct acpi_table_header), + acpi_gbl_root_table_list.tables[i]. + flags & ACPI_TABLE_ORIGIN_MASK); - /* Uninstall table and free the buffer */ + if (!out_table_header) { + return (AE_NO_MEMORY); + } - (void)acpi_tb_uninstall_table(table_info.installed_desc); + return (AE_OK); } - return_ACPI_STATUS(status); + return (AE_NOT_FOUND); } -ACPI_EXPORT_SYMBOL(acpi_load_table) +ACPI_EXPORT_SYMBOL(acpi_get_table_header) -/******************************************************************************* + +/****************************************************************************** * * FUNCTION: acpi_unload_table_id * - * PARAMETERS: table_type - Type of table to be unloaded - * id - Owner ID of the table to be removed. + * 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_table_type table_type, acpi_owner_id id) +acpi_status acpi_unload_table_id(acpi_owner_id id) { - struct acpi_table_desc *table_desc; - acpi_status status; + int i; + acpi_status status = AE_NOT_EXIST; ACPI_FUNCTION_TRACE(acpi_unload_table); - /* Parameter validation */ - if (table_type > ACPI_TABLE_ID_MAX) - return_ACPI_STATUS(AE_BAD_PARAMETER); - /* Find table from the requested type list */ - table_desc = acpi_gbl_table_lists[table_type].next; - while (table_desc && table_desc->owner_id != id) - table_desc = table_desc->next; - - if (!table_desc) - return_ACPI_STATUS(AE_NOT_EXIST); - - /* - * 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_ns_delete_namespace_by_owner(table_desc->owner_id); - - status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (ACPI_FAILURE(status)) - return_ACPI_STATUS(status); - - (void)acpi_tb_uninstall_table(table_desc); - - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - - return_ACPI_STATUS(AE_OK); + 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); + acpi_tb_release_owner_id(i); + acpi_tb_set_table_loaded_flag(i, FALSE); + } + return_ACPI_STATUS(status); } ACPI_EXPORT_SYMBOL(acpi_unload_table_id) -#ifdef ACPI_FUTURE_USAGE /******************************************************************************* * - * FUNCTION: acpi_unload_table + * FUNCTION: acpi_get_table * - * PARAMETERS: table_type - Type of table to be unloaded + * PARAMETERS: Signature - ACPI signature of needed table + * Instance - Which instance (for SSDTs) + * out_table - Where the pointer to the table is returned * - * RETURN: Status + * RETURN: Status and pointer to table * - * DESCRIPTION: This routine is used to force the unload of a table + * DESCRIPTION: Finds and verifies an ACPI table. * - ******************************************************************************/ -acpi_status acpi_unload_table(acpi_table_type table_type) + *****************************************************************************/ +acpi_status +acpi_get_table(char *signature, + acpi_native_uint instance, struct acpi_table_header ** out_table) { - struct acpi_table_desc *table_desc; - - ACPI_FUNCTION_TRACE(acpi_unload_table); - - /* Parameter validation */ + acpi_native_uint i; + acpi_native_uint j; + acpi_status status; - if (table_type > ACPI_TABLE_ID_MAX) { - return_ACPI_STATUS(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; + } - /* Find all tables of the requested type */ + if (++j < instance) { + continue; + } - table_desc = acpi_gbl_table_lists[table_type].next; - if (!table_desc) { - return_ACPI_STATUS(AE_NOT_EXIST); - } + 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; + } - while (table_desc) { - /* - * 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_ns_delete_namespace_by_owner(table_desc->owner_id); - table_desc = table_desc->next; + return (status); } - /* Delete (or unmap) all tables of this type */ - - acpi_tb_delete_tables_by_type(table_type); - return_ACPI_STATUS(AE_OK); + return (AE_NOT_FOUND); } -ACPI_EXPORT_SYMBOL(acpi_unload_table) +ACPI_EXPORT_SYMBOL(acpi_get_table) /******************************************************************************* * - * FUNCTION: acpi_get_table_header + * FUNCTION: acpi_get_table_by_index * - * PARAMETERS: table_type - one of the defined table types - * Instance - the non zero instance of the table, allows - * support for multiple tables of the same type - * see acpi_gbl_acpi_table_flag - * out_table_header - pointer to the struct acpi_table_header if successful + * PARAMETERS: table_index - Table index + * Table - Where the pointer to the table is returned * - * DESCRIPTION: This function is called to get an ACPI table header. The caller - * supplies an pointer to a data area sufficient to contain an ACPI - * struct acpi_table_header structure. + * RETURN: Status and pointer to the table * - * The header contains a length field that can be used to determine - * the size of the buffer needed to contain the entire table. This - * function is not valid for the RSD PTR table since it does not - * have a standard header and is fixed length. + * DESCRIPTION: Obtain a table by an index into the global table list. * ******************************************************************************/ acpi_status -acpi_get_table_header(acpi_table_type table_type, - u32 instance, struct acpi_table_header *out_table_header) +acpi_get_table_by_index(acpi_native_uint table_index, + struct acpi_table_header ** table) { - struct acpi_table_header *tbl_ptr; acpi_status status; - ACPI_FUNCTION_TRACE(acpi_get_table_header); + ACPI_FUNCTION_TRACE(acpi_get_table_by_index); - if ((instance == 0) || - (table_type == ACPI_TABLE_ID_RSDP) || (!out_table_header)) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - /* Check the table type and instance */ + /* Validate index */ - if ((table_type > ACPI_TABLE_ID_MAX) || - (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) && - instance > 1)) { + if (table_index >= acpi_gbl_root_table_list.count) { + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Get a pointer to the entire table */ + if (!acpi_gbl_root_table_list.tables[table_index].pointer) { - status = acpi_tb_get_table_ptr(table_type, instance, &tbl_ptr); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + /* Table is not mapped, map it */ - /* The function will return a NULL pointer if the table is not loaded */ - - if (tbl_ptr == NULL) { - return_ACPI_STATUS(AE_NOT_EXIST); + 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); + } } - /* Copy the header to the caller's buffer */ - - ACPI_MEMCPY(ACPI_CAST_PTR(void, out_table_header), - ACPI_CAST_PTR(void, tbl_ptr), - sizeof(struct acpi_table_header)); - - 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_header) -#endif /* ACPI_FUTURE_USAGE */ +ACPI_EXPORT_SYMBOL(acpi_get_table_by_index) /******************************************************************************* * - * FUNCTION: acpi_get_table + * FUNCTION: acpi_tb_load_namespace * - * PARAMETERS: table_type - one of the defined table types - * Instance - the non zero instance of the table, allows - * support for multiple tables of the same type - * see acpi_gbl_acpi_table_flag - * ret_buffer - pointer to a structure containing a buffer to - * receive the table + * PARAMETERS: None * * RETURN: Status * - * DESCRIPTION: This function is called to get an ACPI table. The caller - * supplies an out_buffer large enough to contain the entire ACPI - * table. The caller should call the acpi_get_table_header function - * first to determine the buffer size needed. Upon completion - * the out_buffer->Length field will indicate the number of bytes - * copied into the out_buffer->buf_ptr buffer. This table will be - * a complete table including the header. + * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in + * the RSDT/XSDT. * ******************************************************************************/ -acpi_status -acpi_get_table(acpi_table_type table_type, - u32 instance, struct acpi_buffer *ret_buffer) +static acpi_status acpi_tb_load_namespace(void) { - struct acpi_table_header *tbl_ptr; acpi_status status; - acpi_size table_length; + struct acpi_table_header *table; + acpi_native_uint i; - ACPI_FUNCTION_TRACE(acpi_get_table); + ACPI_FUNCTION_TRACE(tb_load_namespace); - /* Parameter validation */ + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (instance == 0) { - return_ACPI_STATUS(AE_BAD_PARAMETER); + /* + * 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; } - status = acpi_ut_validate_buffer(ret_buffer); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + /* + * 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_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); } - /* Check the table type and instance */ + status = + acpi_tb_verify_table(&acpi_gbl_root_table_list. + tables[ACPI_TABLE_INDEX_DSDT]); + if (ACPI_FAILURE(status)) { + + /* A valid DSDT is required */ - if ((table_type > ACPI_TABLE_ID_MAX) || - (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) && - instance > 1)) { - return_ACPI_STATUS(AE_BAD_PARAMETER); + status = AE_NO_ACPI_TABLES; + goto unlock_and_exit; } - /* Get a pointer to the entire table */ + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - status = acpi_tb_get_table_ptr(table_type, instance, &tbl_ptr); + /* + * 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); } /* - * acpi_tb_get_table_ptr will return a NULL pointer if the - * table is not loaded. + * Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ - if (tbl_ptr == NULL) { - return_ACPI_STATUS(AE_NOT_EXIST); + (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); } - /* Get the table length */ + ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); - if (table_type == ACPI_TABLE_ID_RSDP) { + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(status); +} - /* RSD PTR is the only "table" without a header */ +/******************************************************************************* + * + * FUNCTION: acpi_load_tables + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT + * + ******************************************************************************/ - table_length = sizeof(struct rsdp_descriptor); - } else { - table_length = (acpi_size) tbl_ptr->length; - } +acpi_status acpi_load_tables(void) +{ + acpi_status status; - /* Validate/Allocate/Clear caller buffer */ + ACPI_FUNCTION_TRACE(acpi_load_tables); - status = acpi_ut_initialize_buffer(ret_buffer, table_length); + /* + * Load the namespace from the tables + */ + status = acpi_tb_load_namespace(); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + ACPI_EXCEPTION((AE_INFO, status, + "While loading namespace from ACPI tables")); } - /* Copy the table to the buffer */ - - ACPI_MEMCPY(ACPI_CAST_PTR(void, ret_buffer->pointer), - ACPI_CAST_PTR(void, tbl_ptr), table_length); - - return_ACPI_STATUS(AE_OK); + return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_get_table) +ACPI_EXPORT_SYMBOL(acpi_load_tables) diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c index da2648bbdbc0..5c6e88251c1a 100644 --- a/drivers/acpi/tables/tbxfroot.c +++ b/drivers/acpi/tables/tbxfroot.c @@ -48,16 +48,15 @@ ACPI_MODULE_NAME("tbxfroot") /* Local prototypes */ -static acpi_status -acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags); - 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 + * PARAMETERS: Rsdp - Pointer to unvalidated RSDP * * RETURN: Status * @@ -65,14 +64,18 @@ static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length); * ******************************************************************************/ -acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp) +static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) { ACPI_FUNCTION_ENTRY(); /* - * The signature and checksum must both be correct + * 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, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0) { + if (ACPI_STRNCMP((char *)rsdp, ACPI_SIG_RSDP, sizeof(ACPI_SIG_RSDP) - 1) + != 0) { /* Nope, BAD Signature */ @@ -81,330 +84,141 @@ acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp) /* Check the standard checksum */ - if (acpi_tb_sum_table(rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { + 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_sum_table(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) { + (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) { return (AE_BAD_CHECKSUM); } return (AE_OK); } +#if ACPI_MACHINE_WIDTH != 16 + /******************************************************************************* * - * 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_ptr - Where the table pointer is returned - * - * RETURN: Status + * FUNCTION: acpi_tb_find_rsdp * - * DESCRIPTION: Find an ACPI table (in the RSDT/XSDT) that matches the - * Signature, OEM ID and OEM Table ID. + * PARAMETERS: table_address - Where the table pointer is returned * - ******************************************************************************/ - -acpi_status -acpi_tb_find_table(char *signature, - char *oem_id, - char *oem_table_id, struct acpi_table_header ** table_ptr) -{ - acpi_status status; - struct acpi_table_header *table; - - ACPI_FUNCTION_TRACE(tb_find_table); - - /* Validate string lengths */ - - if ((ACPI_STRLEN(signature) > ACPI_NAME_SIZE) || - (ACPI_STRLEN(oem_id) > sizeof(table->oem_id)) || - (ACPI_STRLEN(oem_table_id) > sizeof(table->oem_table_id))) { - return_ACPI_STATUS(AE_AML_STRING_LIMIT); - } - - if (ACPI_COMPARE_NAME(signature, DSDT_SIG)) { - /* - * The DSDT pointer is contained in the FADT, not the RSDT. - * This code should suffice, because the only code that would perform - * a "find" on the DSDT is the data_table_region() AML opcode -- in - * which case, the DSDT is guaranteed to be already loaded. - * If this becomes insufficient, the FADT will have to be found first. - */ - if (!acpi_gbl_DSDT) { - return_ACPI_STATUS(AE_NO_ACPI_TABLES); - } - table = acpi_gbl_DSDT; - } else { - /* Find the table */ - - status = acpi_get_firmware_table(signature, 1, - ACPI_LOGICAL_ADDRESSING, - &table); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* Check oem_id and oem_table_id */ - - if ((oem_id[0] && - ACPI_STRNCMP(oem_id, table->oem_id, - sizeof(table->oem_id))) || - (oem_table_id[0] && - ACPI_STRNCMP(oem_table_id, table->oem_table_id, - sizeof(table->oem_table_id)))) { - return_ACPI_STATUS(AE_AML_NAME_NOT_FOUND); - } - - ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "Found table [%4.4s]\n", - table->signature)); - - *table_ptr = table; - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_get_firmware_table + * RETURN: Status, RSDP physical address * - * PARAMETERS: Signature - Any ACPI table signature - * Instance - the non zero instance of the table, allows - * support for multiple tables of the same type - * Flags - Physical/Virtual support - * table_pointer - Where a buffer containing the table is - * returned + * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor + * pointer structure. If it is found, set *RSDP to point to it. * - * RETURN: Status + * 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. * - * DESCRIPTION: This function is called to get an ACPI table. A buffer is - * allocated for the table and returned in table_pointer. - * This table will be a complete table including the header. + * NOTE2: This function is always available, regardless of the + * initialization state of the rest of ACPI. * ******************************************************************************/ -acpi_status -acpi_get_firmware_table(acpi_string signature, - u32 instance, - u32 flags, struct acpi_table_header **table_pointer) +acpi_status acpi_find_root_pointer(acpi_native_uint * table_address) { - acpi_status status; - struct acpi_pointer address; - struct acpi_table_header *header = NULL; - struct acpi_table_desc *table_info = NULL; - struct acpi_table_desc *rsdt_info; - u32 table_count; - u32 i; - u32 j; - - ACPI_FUNCTION_TRACE(acpi_get_firmware_table); - - /* - * Ensure that at least the table manager is initialized. We don't - * require that the entire ACPI subsystem is up for this interface. - * If we have a buffer, we must have a length too - */ - if ((instance == 0) || (!signature) || (!table_pointer)) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Ensure that we have a RSDP */ - - if (!acpi_gbl_RSDP) { - - /* Get the RSDP */ - - status = acpi_os_get_root_pointer(flags, &address); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "RSDP not found\n")); - return_ACPI_STATUS(AE_NO_ACPI_TABLES); - } - - /* Map and validate the RSDP */ - - if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { - status = acpi_os_map_memory(address.pointer.physical, - sizeof(struct - rsdp_descriptor), - (void *)&acpi_gbl_RSDP); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } else { - acpi_gbl_RSDP = address.pointer.logical; - } - - /* The RDSP signature and checksum must both be correct */ - - status = acpi_tb_validate_rsdp(acpi_gbl_RSDP); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* Get the RSDT address via the RSDP */ - - acpi_tb_get_rsdt_address(&address); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "RSDP located at %p, RSDT physical=%8.8X%8.8X\n", - acpi_gbl_RSDP, - ACPI_FORMAT_UINT64(address.pointer.value))); + u8 *table_ptr; + u8 *mem_rover; + u32 physical_address; - /* Insert processor_mode flags */ + ACPI_FUNCTION_TRACE(acpi_find_root_pointer); - address.pointer_type |= flags; + /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ - /* Get and validate the RSDT */ + 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)); - rsdt_info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_table_desc)); - if (!rsdt_info) { return_ACPI_STATUS(AE_NO_MEMORY); } - status = acpi_tb_get_table(&address, rsdt_info); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - status = acpi_tb_validate_rsdt(rsdt_info->pointer); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* Allocate a scratch table header and table descriptor */ - - header = ACPI_ALLOCATE(sizeof(struct acpi_table_header)); - if (!header) { - status = AE_NO_MEMORY; - goto cleanup; - } + ACPI_MOVE_16_TO_32(&physical_address, table_ptr); - table_info = ACPI_ALLOCATE(sizeof(struct acpi_table_desc)); - if (!table_info) { - status = AE_NO_MEMORY; - goto cleanup; - } + /* Convert segment part to physical address */ - /* Get the number of table pointers within the RSDT */ + physical_address <<= 4; + acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH); - table_count = - acpi_tb_get_table_count(acpi_gbl_RSDP, rsdt_info->pointer); - address.pointer_type = acpi_gbl_table_flags | flags; + /* EBDA present? */ - /* - * Search the RSDT/XSDT for the correct instance of the - * requested table - */ - for (i = 0, j = 0; i < table_count; i++) { + if (physical_address > 0x400) { /* - * Get the next table pointer, handle RSDT vs. XSDT - * RSDT pointers are 32 bits, XSDT pointers are 64 bits + * 1b) Search EBDA paragraphs (EBDA is required to be a + * minimum of 1_k length) */ - if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { - address.pointer.value = - (ACPI_CAST_PTR - (struct rsdt_descriptor, - rsdt_info->pointer))->table_offset_entry[i]; - } else { - address.pointer.value = - (ACPI_CAST_PTR - (struct xsdt_descriptor, - rsdt_info->pointer))->table_offset_entry[i]; - } - - /* Get the table header */ + 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)); - status = acpi_tb_get_table_header(&address, header); - if (ACPI_FAILURE(status)) { - goto cleanup; + return_ACPI_STATUS(AE_NO_MEMORY); } - /* Compare table signatures and table instance */ - - if (ACPI_COMPARE_NAME(header->signature, signature)) { - - /* An instance of the table was found */ + mem_rover = + acpi_tb_scan_memory_for_rsdp(table_ptr, + ACPI_EBDA_WINDOW_SIZE); + acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE); - j++; - if (j >= instance) { + if (mem_rover) { - /* Found the correct instance, get the entire table */ + /* Return the physical address */ - status = - acpi_tb_get_table_body(&address, header, - table_info); - if (ACPI_FAILURE(status)) { - goto cleanup; - } + physical_address += + (u32) ACPI_PTR_DIFF(mem_rover, table_ptr); - *table_pointer = table_info->pointer; - goto cleanup; - } + *table_address = physical_address; + return_ACPI_STATUS(AE_OK); } } - /* Did not find the table */ + /* + * 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); - status = AE_NOT_EXIST; + 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)); - cleanup: - if (rsdt_info->pointer) { - acpi_os_unmap_memory(rsdt_info->pointer, - (acpi_size) rsdt_info->pointer->length); + return_ACPI_STATUS(AE_NO_MEMORY); } - ACPI_FREE(rsdt_info); - if (header) { - ACPI_FREE(header); - } - if (table_info) { - ACPI_FREE(table_info); - } - return_ACPI_STATUS(status); -} + 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); -ACPI_EXPORT_SYMBOL(acpi_get_firmware_table) + if (mem_rover) { -/* TBD: Move to a new file */ -#if ACPI_MACHINE_WIDTH != 16 -/******************************************************************************* - * - * FUNCTION: acpi_find_root_pointer - * - * PARAMETERS: Flags - Logical/Physical addressing - * rsdp_address - Where to place the RSDP address - * - * RETURN: Status, Physical address of the RSDP - * - * DESCRIPTION: Find the RSDP - * - ******************************************************************************/ -acpi_status acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address) -{ - struct acpi_table_desc table_info; - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_find_root_pointer); + /* Return the physical address */ - /* Get the RSDP */ + physical_address = (u32) + (ACPI_HI_RSDP_WINDOW_BASE + + ACPI_PTR_DIFF(mem_rover, table_ptr)); - status = acpi_tb_find_rsdp(&table_info, flags); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "RSDP structure not found - Flags=%X", flags)); - - return_ACPI_STATUS(AE_NO_ACPI_TABLES); + *table_address = physical_address; + return_ACPI_STATUS(AE_OK); } - rsdp_address->pointer_type = ACPI_PHYSICAL_POINTER; - rsdp_address->pointer.physical = table_info.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) @@ -440,7 +254,7 @@ static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length) status = acpi_tb_validate_rsdp(ACPI_CAST_PTR - (struct rsdp_descriptor, mem_rover)); + (struct acpi_table_rsdp, mem_rover)); if (ACPI_SUCCESS(status)) { /* Sig and checksum valid, we have found a real RSDP */ @@ -462,188 +276,4 @@ static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length) return_PTR(NULL); } -/******************************************************************************* - * - * FUNCTION: acpi_tb_find_rsdp - * - * PARAMETERS: table_info - Where the table info is returned - * Flags - Current memory mode (logical vs. - * physical addressing) - * - * 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. - * - ******************************************************************************/ - -static acpi_status -acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) -{ - u8 *table_ptr; - u8 *mem_rover; - u32 physical_address; - acpi_status status; - - ACPI_FUNCTION_TRACE(tb_find_rsdp); - - /* - * Scan supports either logical addressing or physical addressing - */ - if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { - - /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ - - status = acpi_os_map_memory((acpi_physical_address) - ACPI_EBDA_PTR_LOCATION, - ACPI_EBDA_PTR_LENGTH, - (void *)&table_ptr); - if (ACPI_FAILURE(status)) { - 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(status); - } - - 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) - */ - status = acpi_os_map_memory((acpi_physical_address) - physical_address, - ACPI_EBDA_WINDOW_SIZE, - (void *)&table_ptr); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not map memory at %8.8X for length %X", - physical_address, - ACPI_EBDA_WINDOW_SIZE)); - - return_ACPI_STATUS(status); - } - - 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_info->physical_address = - (acpi_physical_address) physical_address; - return_ACPI_STATUS(AE_OK); - } - } - - /* - * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh - */ - status = acpi_os_map_memory((acpi_physical_address) - ACPI_HI_RSDP_WINDOW_BASE, - ACPI_HI_RSDP_WINDOW_SIZE, - (void *)&table_ptr); - - if (ACPI_FAILURE(status)) { - 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(status); - } - - 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_info->physical_address = - (acpi_physical_address) physical_address; - return_ACPI_STATUS(AE_OK); - } - } - - /* - * Physical addressing - */ - else { - /* 1a) Get the location of the EBDA */ - - ACPI_MOVE_16_TO_32(&physical_address, ACPI_EBDA_PTR_LOCATION); - physical_address <<= 4; /* Convert segment to physical address */ - - /* EBDA present? */ - - if (physical_address > 0x400) { - /* - * 1b) Search EBDA paragraphs (EBDA is required to be a minimum of - * 1_k length) - */ - mem_rover = - acpi_tb_scan_memory_for_rsdp(ACPI_PHYSADDR_TO_PTR - (physical_address), - ACPI_EBDA_WINDOW_SIZE); - if (mem_rover) { - - /* Return the physical address */ - - table_info->physical_address = - ACPI_TO_INTEGER(mem_rover); - return_ACPI_STATUS(AE_OK); - } - } - - /* 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh */ - - mem_rover = - acpi_tb_scan_memory_for_rsdp(ACPI_PHYSADDR_TO_PTR - (ACPI_HI_RSDP_WINDOW_BASE), - ACPI_HI_RSDP_WINDOW_SIZE); - if (mem_rover) { - - /* Found it, return the physical address */ - - table_info->physical_address = - ACPI_TO_INTEGER(mem_rover); - return_ACPI_STATUS(AE_OK); - } - } - - /* A valid RSDP was not found */ - - ACPI_ERROR((AE_INFO, "No valid RSDP was found")); - return_ACPI_STATUS(AE_NOT_FOUND); -} - #endif |