195b482a8SLen Brown /****************************************************************************** 295b482a8SLen Brown * 395b482a8SLen Brown * Module Name: tbinstal - ACPI table installation and removal 495b482a8SLen Brown * 595b482a8SLen Brown *****************************************************************************/ 695b482a8SLen Brown 795b482a8SLen Brown /* 8fbb7a2dcSBob Moore * Copyright (C) 2000 - 2014, Intel Corp. 995b482a8SLen Brown * All rights reserved. 1095b482a8SLen Brown * 1195b482a8SLen Brown * Redistribution and use in source and binary forms, with or without 1295b482a8SLen Brown * modification, are permitted provided that the following conditions 1395b482a8SLen Brown * are met: 1495b482a8SLen Brown * 1. Redistributions of source code must retain the above copyright 1595b482a8SLen Brown * notice, this list of conditions, and the following disclaimer, 1695b482a8SLen Brown * without modification. 1795b482a8SLen Brown * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1895b482a8SLen Brown * substantially similar to the "NO WARRANTY" disclaimer below 1995b482a8SLen Brown * ("Disclaimer") and any redistribution must be conditioned upon 2095b482a8SLen Brown * including a substantially similar Disclaimer requirement for further 2195b482a8SLen Brown * binary redistribution. 2295b482a8SLen Brown * 3. Neither the names of the above-listed copyright holders nor the names 2395b482a8SLen Brown * of any contributors may be used to endorse or promote products derived 2495b482a8SLen Brown * from this software without specific prior written permission. 2595b482a8SLen Brown * 2695b482a8SLen Brown * Alternatively, this software may be distributed under the terms of the 2795b482a8SLen Brown * GNU General Public License ("GPL") version 2 as published by the Free 2895b482a8SLen Brown * Software Foundation. 2995b482a8SLen Brown * 3095b482a8SLen Brown * NO WARRANTY 3195b482a8SLen Brown * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3295b482a8SLen Brown * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3395b482a8SLen Brown * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3495b482a8SLen Brown * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3595b482a8SLen Brown * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3695b482a8SLen Brown * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3795b482a8SLen Brown * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3895b482a8SLen Brown * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3995b482a8SLen Brown * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4095b482a8SLen Brown * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4195b482a8SLen Brown * POSSIBILITY OF SUCH DAMAGES. 4295b482a8SLen Brown */ 4395b482a8SLen Brown 4495b482a8SLen Brown #include <acpi/acpi.h> 45e2f7a777SLen Brown #include "accommon.h" 46e2f7a777SLen Brown #include "acnamesp.h" 47e2f7a777SLen Brown #include "actables.h" 4895b482a8SLen Brown 4995b482a8SLen Brown #define _COMPONENT ACPI_TABLES 5095b482a8SLen Brown ACPI_MODULE_NAME("tbinstal") 5195b482a8SLen Brown 5286dfc6f3SLv Zheng /* Local prototypes */ 5386dfc6f3SLv Zheng static acpi_status 5486dfc6f3SLv Zheng acpi_tb_acquire_temporal_table(struct acpi_table_desc *table_desc, 5586dfc6f3SLv Zheng acpi_physical_address address, u8 flags); 5686dfc6f3SLv Zheng 5786dfc6f3SLv Zheng static void acpi_tb_release_temporal_table(struct acpi_table_desc *table_desc); 5886dfc6f3SLv Zheng 5986dfc6f3SLv Zheng static acpi_status acpi_tb_acquire_root_table_entry(u32 *table_index); 6086dfc6f3SLv Zheng 6186dfc6f3SLv Zheng static u8 6286dfc6f3SLv Zheng acpi_tb_is_equivalent_table(struct acpi_table_desc *table_desc, 6386dfc6f3SLv Zheng u32 table_index); 6486dfc6f3SLv Zheng 657f9fc99cSLv Zheng /******************************************************************************* 6695b482a8SLen Brown * 677f9fc99cSLv Zheng * FUNCTION: acpi_tb_acquire_table 6895b482a8SLen Brown * 697f9fc99cSLv Zheng * PARAMETERS: table_desc - Table descriptor 707f9fc99cSLv Zheng * table_ptr - Where table is returned 717f9fc99cSLv Zheng * table_length - Where table length is returned 727f9fc99cSLv Zheng * table_flags - Where table allocation flags are returned 7395b482a8SLen Brown * 7495b482a8SLen Brown * RETURN: Status 7595b482a8SLen Brown * 767f9fc99cSLv Zheng * DESCRIPTION: Acquire a table. It can be used for tables not maintained in 777f9fc99cSLv Zheng * acpi_gbl_root_table_list. 7895b482a8SLen Brown * 797f9fc99cSLv Zheng ******************************************************************************/ 8086dfc6f3SLv Zheng 817f9fc99cSLv Zheng acpi_status 827f9fc99cSLv Zheng acpi_tb_acquire_table(struct acpi_table_desc *table_desc, 837f9fc99cSLv Zheng struct acpi_table_header **table_ptr, 847f9fc99cSLv Zheng u32 *table_length, u8 *table_flags) 8595b482a8SLen Brown { 867f9fc99cSLv Zheng struct acpi_table_header *table = NULL; 8795b482a8SLen Brown 88dc156adfSLv Zheng switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { 89*8a216d7fSLv Zheng case ACPI_TABLE_ORIGIN_INTERN_PHYSICAL: 90dc156adfSLv Zheng 917f9fc99cSLv Zheng table = 927f9fc99cSLv Zheng acpi_os_map_memory(table_desc->address, table_desc->length); 93dc156adfSLv Zheng break; 94dc156adfSLv Zheng 95*8a216d7fSLv Zheng case ACPI_TABLE_ORIGIN_INTERN_VIRTUAL: 96*8a216d7fSLv Zheng case ACPI_TABLE_ORIGIN_EXTERN_VIRTUAL: 97dc156adfSLv Zheng 987f9fc99cSLv Zheng table = 99dc156adfSLv Zheng ACPI_CAST_PTR(struct acpi_table_header, 100dc156adfSLv Zheng table_desc->address); 101dc156adfSLv Zheng break; 102dc156adfSLv Zheng 103dc156adfSLv Zheng default: 104dc156adfSLv Zheng 105dc156adfSLv Zheng break; 10695b482a8SLen Brown } 1075582982dSLv Zheng 1087f9fc99cSLv Zheng /* Table is not valid yet */ 1097f9fc99cSLv Zheng 1107f9fc99cSLv Zheng if (!table) { 1117f9fc99cSLv Zheng return (AE_NO_MEMORY); 1127f9fc99cSLv Zheng } 1137f9fc99cSLv Zheng 1147f9fc99cSLv Zheng /* Fill the return values */ 1157f9fc99cSLv Zheng 1167f9fc99cSLv Zheng *table_ptr = table; 1177f9fc99cSLv Zheng *table_length = table_desc->length; 1187f9fc99cSLv Zheng *table_flags = table_desc->flags; 1197f9fc99cSLv Zheng 1207f9fc99cSLv Zheng return (AE_OK); 1217f9fc99cSLv Zheng } 1227f9fc99cSLv Zheng 1237f9fc99cSLv Zheng /******************************************************************************* 1247f9fc99cSLv Zheng * 1257f9fc99cSLv Zheng * FUNCTION: acpi_tb_release_table 1267f9fc99cSLv Zheng * 1277f9fc99cSLv Zheng * PARAMETERS: table - Pointer for the table 1287f9fc99cSLv Zheng * table_length - Length for the table 1297f9fc99cSLv Zheng * table_flags - Allocation flags for the table 1307f9fc99cSLv Zheng * 1317f9fc99cSLv Zheng * RETURN: None 1327f9fc99cSLv Zheng * 1337f9fc99cSLv Zheng * DESCRIPTION: Release a table. The reversal of acpi_tb_acquire_table(). 1347f9fc99cSLv Zheng * 1357f9fc99cSLv Zheng ******************************************************************************/ 1367f9fc99cSLv Zheng 1377f9fc99cSLv Zheng void 1387f9fc99cSLv Zheng acpi_tb_release_table(struct acpi_table_header *table, 1397f9fc99cSLv Zheng u32 table_length, u8 table_flags) 1407f9fc99cSLv Zheng { 1417f9fc99cSLv Zheng switch (table_flags & ACPI_TABLE_ORIGIN_MASK) { 142*8a216d7fSLv Zheng case ACPI_TABLE_ORIGIN_INTERN_PHYSICAL: 1437f9fc99cSLv Zheng 1447f9fc99cSLv Zheng acpi_os_unmap_memory(table, table_length); 1457f9fc99cSLv Zheng break; 1467f9fc99cSLv Zheng 147*8a216d7fSLv Zheng case ACPI_TABLE_ORIGIN_INTERN_VIRTUAL: 148*8a216d7fSLv Zheng case ACPI_TABLE_ORIGIN_EXTERN_VIRTUAL: 1497f9fc99cSLv Zheng default: 1507f9fc99cSLv Zheng 1517f9fc99cSLv Zheng break; 1527f9fc99cSLv Zheng } 1537f9fc99cSLv Zheng } 1547f9fc99cSLv Zheng 1557f9fc99cSLv Zheng /****************************************************************************** 1567f9fc99cSLv Zheng * 1577f9fc99cSLv Zheng * FUNCTION: acpi_tb_validate_table 1587f9fc99cSLv Zheng * 1597f9fc99cSLv Zheng * PARAMETERS: table_desc - Table descriptor 1607f9fc99cSLv Zheng * 1617f9fc99cSLv Zheng * RETURN: Status 1627f9fc99cSLv Zheng * 16386dfc6f3SLv Zheng * DESCRIPTION: This function is called to validate the table, the returned 16486dfc6f3SLv Zheng * table descriptor is in "VALIDATED" state. 1657f9fc99cSLv Zheng * 1667f9fc99cSLv Zheng *****************************************************************************/ 1677f9fc99cSLv Zheng 1687f9fc99cSLv Zheng acpi_status acpi_tb_validate_table(struct acpi_table_desc *table_desc) 1697f9fc99cSLv Zheng { 1707f9fc99cSLv Zheng acpi_status status = AE_OK; 1717f9fc99cSLv Zheng 1727f9fc99cSLv Zheng ACPI_FUNCTION_TRACE(tb_validate_table); 1737f9fc99cSLv Zheng 1747f9fc99cSLv Zheng /* Validate the table if necessary */ 1757f9fc99cSLv Zheng 17695b482a8SLen Brown if (!table_desc->pointer) { 1777f9fc99cSLv Zheng status = acpi_tb_acquire_table(table_desc, &table_desc->pointer, 1787f9fc99cSLv Zheng &table_desc->length, 1797f9fc99cSLv Zheng &table_desc->flags); 18086dfc6f3SLv Zheng if (!table_desc->pointer) { 18186dfc6f3SLv Zheng status = AE_NO_MEMORY; 18295b482a8SLen Brown } 18395b482a8SLen Brown } 18495b482a8SLen Brown 18595b482a8SLen Brown return_ACPI_STATUS(status); 18695b482a8SLen Brown } 18795b482a8SLen Brown 18895b482a8SLen Brown /******************************************************************************* 18995b482a8SLen Brown * 1907f9fc99cSLv Zheng * FUNCTION: acpi_tb_invalidate_table 1917f9fc99cSLv Zheng * 1927f9fc99cSLv Zheng * PARAMETERS: table_desc - Table descriptor 1937f9fc99cSLv Zheng * 1947f9fc99cSLv Zheng * RETURN: None 1957f9fc99cSLv Zheng * 1967f9fc99cSLv Zheng * DESCRIPTION: Invalidate one internal ACPI table, this is reversal of 1977f9fc99cSLv Zheng * acpi_tb_validate_table(). 1987f9fc99cSLv Zheng * 1997f9fc99cSLv Zheng ******************************************************************************/ 2007f9fc99cSLv Zheng 2017f9fc99cSLv Zheng void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc) 2027f9fc99cSLv Zheng { 2037f9fc99cSLv Zheng 2047f9fc99cSLv Zheng ACPI_FUNCTION_TRACE(tb_invalidate_table); 2057f9fc99cSLv Zheng 2067f9fc99cSLv Zheng /* Table must be validated */ 2077f9fc99cSLv Zheng 2087f9fc99cSLv Zheng if (!table_desc->pointer) { 2097f9fc99cSLv Zheng return_VOID; 2107f9fc99cSLv Zheng } 2117f9fc99cSLv Zheng 2127f9fc99cSLv Zheng acpi_tb_release_table(table_desc->pointer, table_desc->length, 2137f9fc99cSLv Zheng table_desc->flags); 2147f9fc99cSLv Zheng table_desc->pointer = NULL; 2157f9fc99cSLv Zheng 2167f9fc99cSLv Zheng return_VOID; 2177f9fc99cSLv Zheng } 2187f9fc99cSLv Zheng 21986dfc6f3SLv Zheng /****************************************************************************** 2207f9fc99cSLv Zheng * 22186dfc6f3SLv Zheng * FUNCTION: acpi_tb_verify_table 22295b482a8SLen Brown * 22395b482a8SLen Brown * PARAMETERS: table_desc - Table descriptor 22486dfc6f3SLv Zheng * signature - Table signature to verify 22595b482a8SLen Brown * 22695b482a8SLen Brown * RETURN: Status 22795b482a8SLen Brown * 22886dfc6f3SLv Zheng * DESCRIPTION: This function is called to validate and verify the table, the 22986dfc6f3SLv Zheng * returned table descriptor is in "VALIDATED" state. 23086dfc6f3SLv Zheng * 23186dfc6f3SLv Zheng *****************************************************************************/ 23286dfc6f3SLv Zheng 23386dfc6f3SLv Zheng acpi_status 23486dfc6f3SLv Zheng acpi_tb_verify_table(struct acpi_table_desc *table_desc, char *signature) 23586dfc6f3SLv Zheng { 23686dfc6f3SLv Zheng acpi_status status = AE_OK; 23786dfc6f3SLv Zheng 23886dfc6f3SLv Zheng ACPI_FUNCTION_TRACE(tb_verify_table); 23986dfc6f3SLv Zheng 24086dfc6f3SLv Zheng /* Validate the table */ 24186dfc6f3SLv Zheng 24286dfc6f3SLv Zheng status = acpi_tb_validate_table(table_desc); 24386dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 24486dfc6f3SLv Zheng return_ACPI_STATUS(AE_NO_MEMORY); 24586dfc6f3SLv Zheng } 24686dfc6f3SLv Zheng 24786dfc6f3SLv Zheng /* If a particular signature is expected (DSDT/FACS), it must match */ 24886dfc6f3SLv Zheng 24986dfc6f3SLv Zheng if (signature && !ACPI_COMPARE_NAME(&table_desc->signature, signature)) { 25086dfc6f3SLv Zheng ACPI_BIOS_ERROR((AE_INFO, 25186dfc6f3SLv Zheng "Invalid signature 0x%X for ACPI table, expected [%s]", 25286dfc6f3SLv Zheng table_desc->signature.integer, signature)); 25386dfc6f3SLv Zheng status = AE_BAD_SIGNATURE; 25486dfc6f3SLv Zheng goto invalidate_and_exit; 25586dfc6f3SLv Zheng } 25686dfc6f3SLv Zheng 25786dfc6f3SLv Zheng /* Verify the checksum */ 25886dfc6f3SLv Zheng 25986dfc6f3SLv Zheng status = 26086dfc6f3SLv Zheng acpi_tb_verify_checksum(table_desc->pointer, table_desc->length); 26186dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 26286dfc6f3SLv Zheng ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, 26386dfc6f3SLv Zheng "%4.4s " ACPI_PRINTF_UINT 26486dfc6f3SLv Zheng " Attempted table install failed", 26586dfc6f3SLv Zheng acpi_ut_valid_acpi_name(table_desc->signature. 26686dfc6f3SLv Zheng ascii) ? table_desc-> 26786dfc6f3SLv Zheng signature.ascii : "????", 26886dfc6f3SLv Zheng ACPI_FORMAT_TO_UINT(table_desc->address))); 26986dfc6f3SLv Zheng goto invalidate_and_exit; 27086dfc6f3SLv Zheng } 27186dfc6f3SLv Zheng 27286dfc6f3SLv Zheng return_ACPI_STATUS(AE_OK); 27386dfc6f3SLv Zheng 27486dfc6f3SLv Zheng invalidate_and_exit: 27586dfc6f3SLv Zheng acpi_tb_invalidate_table(table_desc); 27686dfc6f3SLv Zheng return_ACPI_STATUS(status); 27786dfc6f3SLv Zheng } 27886dfc6f3SLv Zheng 27986dfc6f3SLv Zheng /******************************************************************************* 28086dfc6f3SLv Zheng * 28186dfc6f3SLv Zheng * FUNCTION: acpi_tb_install_table 28286dfc6f3SLv Zheng * 28386dfc6f3SLv Zheng * PARAMETERS: table_desc - Table descriptor 28486dfc6f3SLv Zheng * address - Physical address of the table 28586dfc6f3SLv Zheng * flags - Allocation flags of the table 28686dfc6f3SLv Zheng * table - Pointer to the table 28786dfc6f3SLv Zheng * 28886dfc6f3SLv Zheng * RETURN: None 28986dfc6f3SLv Zheng * 29086dfc6f3SLv Zheng * DESCRIPTION: Install an ACPI table into the global data structure. 29186dfc6f3SLv Zheng * 29286dfc6f3SLv Zheng ******************************************************************************/ 29386dfc6f3SLv Zheng 29486dfc6f3SLv Zheng void 29586dfc6f3SLv Zheng acpi_tb_install_table(struct acpi_table_desc *table_desc, 29686dfc6f3SLv Zheng acpi_physical_address address, 29786dfc6f3SLv Zheng u8 flags, struct acpi_table_header *table) 29886dfc6f3SLv Zheng { 29986dfc6f3SLv Zheng /* 30086dfc6f3SLv Zheng * Initialize the table entry. Set the pointer to NULL, since the 30186dfc6f3SLv Zheng * table is not fully mapped at this time. 30286dfc6f3SLv Zheng */ 30386dfc6f3SLv Zheng ACPI_MEMSET(table_desc, 0, sizeof(struct acpi_table_desc)); 30486dfc6f3SLv Zheng table_desc->address = address; 30586dfc6f3SLv Zheng table_desc->length = table->length; 30686dfc6f3SLv Zheng table_desc->flags = flags; 30786dfc6f3SLv Zheng ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature); 30886dfc6f3SLv Zheng } 30986dfc6f3SLv Zheng 31086dfc6f3SLv Zheng /******************************************************************************* 31186dfc6f3SLv Zheng * 31286dfc6f3SLv Zheng * FUNCTION: acpi_tb_acquire_temporal_table 31386dfc6f3SLv Zheng * 31486dfc6f3SLv Zheng * PARAMETERS: table_desc - Table descriptor to be acquired 31586dfc6f3SLv Zheng * address - Address of the table 31686dfc6f3SLv Zheng * flags - Allocation flags of the table 31786dfc6f3SLv Zheng * 31886dfc6f3SLv Zheng * RETURN: Status 31986dfc6f3SLv Zheng * 32086dfc6f3SLv Zheng * DESCRIPTION: This function validates the table header to obtain the length 32186dfc6f3SLv Zheng * of a table and fills the table descriptor to make its state as 32286dfc6f3SLv Zheng * "INSTALLED". Such table descriptor is only used for verified 32386dfc6f3SLv Zheng * installation. 32486dfc6f3SLv Zheng * 32586dfc6f3SLv Zheng ******************************************************************************/ 32686dfc6f3SLv Zheng 32786dfc6f3SLv Zheng static acpi_status 32886dfc6f3SLv Zheng acpi_tb_acquire_temporal_table(struct acpi_table_desc *table_desc, 32986dfc6f3SLv Zheng acpi_physical_address address, u8 flags) 33086dfc6f3SLv Zheng { 33186dfc6f3SLv Zheng struct acpi_table_header *table_header; 33286dfc6f3SLv Zheng 33386dfc6f3SLv Zheng switch (flags & ACPI_TABLE_ORIGIN_MASK) { 334*8a216d7fSLv Zheng case ACPI_TABLE_ORIGIN_INTERN_PHYSICAL: 33586dfc6f3SLv Zheng 33686dfc6f3SLv Zheng /* Try to obtain the length of the table */ 33786dfc6f3SLv Zheng 33886dfc6f3SLv Zheng table_header = 33986dfc6f3SLv Zheng acpi_os_map_memory(address, 34086dfc6f3SLv Zheng sizeof(struct acpi_table_header)); 34186dfc6f3SLv Zheng if (!table_header) { 34286dfc6f3SLv Zheng return (AE_NO_MEMORY); 34386dfc6f3SLv Zheng } 34486dfc6f3SLv Zheng acpi_tb_install_table(table_desc, address, flags, table_header); 34586dfc6f3SLv Zheng acpi_os_unmap_memory(table_header, 34686dfc6f3SLv Zheng sizeof(struct acpi_table_header)); 34786dfc6f3SLv Zheng return (AE_OK); 34886dfc6f3SLv Zheng 349*8a216d7fSLv Zheng case ACPI_TABLE_ORIGIN_INTERN_VIRTUAL: 350*8a216d7fSLv Zheng case ACPI_TABLE_ORIGIN_EXTERN_VIRTUAL: 35186dfc6f3SLv Zheng 35286dfc6f3SLv Zheng table_header = ACPI_CAST_PTR(struct acpi_table_header, address); 35386dfc6f3SLv Zheng if (!table_header) { 35486dfc6f3SLv Zheng return (AE_NO_MEMORY); 35586dfc6f3SLv Zheng } 35686dfc6f3SLv Zheng acpi_tb_install_table(table_desc, address, flags, table_header); 35786dfc6f3SLv Zheng return (AE_OK); 35886dfc6f3SLv Zheng 35986dfc6f3SLv Zheng default: 36086dfc6f3SLv Zheng 36186dfc6f3SLv Zheng break; 36286dfc6f3SLv Zheng } 36386dfc6f3SLv Zheng 36486dfc6f3SLv Zheng /* Table is not valid yet */ 36586dfc6f3SLv Zheng 36686dfc6f3SLv Zheng return (AE_NO_MEMORY); 36786dfc6f3SLv Zheng } 36886dfc6f3SLv Zheng 36986dfc6f3SLv Zheng /******************************************************************************* 37086dfc6f3SLv Zheng * 37186dfc6f3SLv Zheng * FUNCTION: acpi_tb_release_temporal_table 37286dfc6f3SLv Zheng * 37386dfc6f3SLv Zheng * PARAMETERS: table_desc - Table descriptor to be released 37486dfc6f3SLv Zheng * 37586dfc6f3SLv Zheng * RETURN: Status 37686dfc6f3SLv Zheng * 37786dfc6f3SLv Zheng * DESCRIPTION: The reversal of acpi_tb_acquire_temporal_table(). 37886dfc6f3SLv Zheng * 37986dfc6f3SLv Zheng ******************************************************************************/ 38086dfc6f3SLv Zheng 38186dfc6f3SLv Zheng static void acpi_tb_release_temporal_table(struct acpi_table_desc *table_desc) 38286dfc6f3SLv Zheng { 38386dfc6f3SLv Zheng /* 38486dfc6f3SLv Zheng * Note that the .Address is maintained by the callers of 38586dfc6f3SLv Zheng * acpi_tb_acquire_temporal_table(), thus do not invoke acpi_tb_uninstall_table() 38686dfc6f3SLv Zheng * where .Address will be freed. 38786dfc6f3SLv Zheng */ 38886dfc6f3SLv Zheng acpi_tb_invalidate_table(table_desc); 38986dfc6f3SLv Zheng } 39086dfc6f3SLv Zheng 39186dfc6f3SLv Zheng /******************************************************************************* 39286dfc6f3SLv Zheng * 39386dfc6f3SLv Zheng * FUNCTION: acpi_tb_install_and_override_table 39486dfc6f3SLv Zheng * 39586dfc6f3SLv Zheng * PARAMETERS: table_index - Index into root table array 39686dfc6f3SLv Zheng * new_table_desc - New table descriptor to install 39786dfc6f3SLv Zheng * 39886dfc6f3SLv Zheng * RETURN: None 39986dfc6f3SLv Zheng * 40086dfc6f3SLv Zheng * DESCRIPTION: Install an ACPI table into the global data structure. The 40186dfc6f3SLv Zheng * table override mechanism is called to allow the host 40286dfc6f3SLv Zheng * OS to replace any table before it is installed in the root 40386dfc6f3SLv Zheng * table array. 40486dfc6f3SLv Zheng * 40586dfc6f3SLv Zheng ******************************************************************************/ 40686dfc6f3SLv Zheng 40786dfc6f3SLv Zheng void 40886dfc6f3SLv Zheng acpi_tb_install_and_override_table(u32 table_index, 40986dfc6f3SLv Zheng struct acpi_table_desc *new_table_desc) 41086dfc6f3SLv Zheng { 41186dfc6f3SLv Zheng if (table_index >= acpi_gbl_root_table_list.current_table_count) { 41286dfc6f3SLv Zheng return; 41386dfc6f3SLv Zheng } 41486dfc6f3SLv Zheng 41586dfc6f3SLv Zheng /* 41686dfc6f3SLv Zheng * ACPI Table Override: 41786dfc6f3SLv Zheng * 41886dfc6f3SLv Zheng * Before we install the table, let the host OS override it with a new 41986dfc6f3SLv Zheng * one if desired. Any table within the RSDT/XSDT can be replaced, 42086dfc6f3SLv Zheng * including the DSDT which is pointed to by the FADT. 42186dfc6f3SLv Zheng */ 42286dfc6f3SLv Zheng acpi_tb_override_table(new_table_desc); 42386dfc6f3SLv Zheng 42486dfc6f3SLv Zheng acpi_tb_install_table(&acpi_gbl_root_table_list.tables[table_index], 42586dfc6f3SLv Zheng new_table_desc->address, new_table_desc->flags, 42686dfc6f3SLv Zheng new_table_desc->pointer); 42786dfc6f3SLv Zheng 42886dfc6f3SLv Zheng acpi_tb_print_table_header(new_table_desc->address, 42986dfc6f3SLv Zheng new_table_desc->pointer); 43086dfc6f3SLv Zheng 43186dfc6f3SLv Zheng /* Set the global integer width (based upon revision of the DSDT) */ 43286dfc6f3SLv Zheng 43386dfc6f3SLv Zheng if (table_index == ACPI_TABLE_INDEX_DSDT) { 43486dfc6f3SLv Zheng acpi_ut_set_integer_width(new_table_desc->pointer->revision); 43586dfc6f3SLv Zheng } 43686dfc6f3SLv Zheng } 43786dfc6f3SLv Zheng 43886dfc6f3SLv Zheng /******************************************************************************* 43986dfc6f3SLv Zheng * 44086dfc6f3SLv Zheng * FUNCTION: acpi_tb_install_fixed_table 44186dfc6f3SLv Zheng * 44286dfc6f3SLv Zheng * PARAMETERS: address - Physical address of DSDT or FACS 44386dfc6f3SLv Zheng * signature - Table signature, NULL if no need to 44486dfc6f3SLv Zheng * match 44586dfc6f3SLv Zheng * table_index - Index into root table array 44686dfc6f3SLv Zheng * 44786dfc6f3SLv Zheng * RETURN: Status 44886dfc6f3SLv Zheng * 44986dfc6f3SLv Zheng * DESCRIPTION: Install a fixed ACPI table (DSDT/FACS) into the global data 45086dfc6f3SLv Zheng * structure. 45195b482a8SLen Brown * 45295b482a8SLen Brown ******************************************************************************/ 45395b482a8SLen Brown 45495b482a8SLen Brown acpi_status 45586dfc6f3SLv Zheng acpi_tb_install_fixed_table(acpi_physical_address address, 45686dfc6f3SLv Zheng char *signature, u32 table_index) 45786dfc6f3SLv Zheng { 45886dfc6f3SLv Zheng struct acpi_table_desc new_table_desc; 45986dfc6f3SLv Zheng acpi_status status; 46086dfc6f3SLv Zheng 46186dfc6f3SLv Zheng ACPI_FUNCTION_TRACE(tb_install_fixed_table); 46286dfc6f3SLv Zheng 46386dfc6f3SLv Zheng if (!address) { 46486dfc6f3SLv Zheng ACPI_ERROR((AE_INFO, 46586dfc6f3SLv Zheng "Null physical address for ACPI table [%s]", 46686dfc6f3SLv Zheng signature)); 46786dfc6f3SLv Zheng return (AE_NO_MEMORY); 46886dfc6f3SLv Zheng } 46986dfc6f3SLv Zheng 47086dfc6f3SLv Zheng /* Fill a table descriptor for validation */ 47186dfc6f3SLv Zheng 47286dfc6f3SLv Zheng status = acpi_tb_acquire_temporal_table(&new_table_desc, address, 473*8a216d7fSLv Zheng ACPI_TABLE_ORIGIN_INTERN_PHYSICAL); 47486dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 47586dfc6f3SLv Zheng ACPI_ERROR((AE_INFO, "Could not acquire table length at %p", 47686dfc6f3SLv Zheng ACPI_CAST_PTR(void, address))); 47786dfc6f3SLv Zheng return_ACPI_STATUS(status); 47886dfc6f3SLv Zheng } 47986dfc6f3SLv Zheng 48086dfc6f3SLv Zheng /* Validate and verify a table before installation */ 48186dfc6f3SLv Zheng 48286dfc6f3SLv Zheng status = acpi_tb_verify_table(&new_table_desc, signature); 48386dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 48486dfc6f3SLv Zheng goto release_and_exit; 48586dfc6f3SLv Zheng } 48686dfc6f3SLv Zheng 48786dfc6f3SLv Zheng acpi_tb_install_and_override_table(table_index, &new_table_desc); 48886dfc6f3SLv Zheng 48986dfc6f3SLv Zheng release_and_exit: 49086dfc6f3SLv Zheng 49186dfc6f3SLv Zheng /* Release the temporal table descriptor */ 49286dfc6f3SLv Zheng 49386dfc6f3SLv Zheng acpi_tb_release_temporal_table(&new_table_desc); 49486dfc6f3SLv Zheng return_ACPI_STATUS(status); 49586dfc6f3SLv Zheng } 49686dfc6f3SLv Zheng 49786dfc6f3SLv Zheng /******************************************************************************* 49886dfc6f3SLv Zheng * 49986dfc6f3SLv Zheng * FUNCTION: acpi_tb_is_equivalent_table 50086dfc6f3SLv Zheng * 50186dfc6f3SLv Zheng * PARAMETERS: table_desc - Table 1 descriptor to be compared 50286dfc6f3SLv Zheng * table_index - Index of table 2 to be compared 50386dfc6f3SLv Zheng * 50486dfc6f3SLv Zheng * RETURN: TRUE if 2 tables are equivalent 50586dfc6f3SLv Zheng * 50686dfc6f3SLv Zheng * DESCRIPTION: This function is called to compare a table with what have 50786dfc6f3SLv Zheng * already been installed in the root table list. 50886dfc6f3SLv Zheng * 50986dfc6f3SLv Zheng ******************************************************************************/ 51086dfc6f3SLv Zheng 51186dfc6f3SLv Zheng static u8 51286dfc6f3SLv Zheng acpi_tb_is_equivalent_table(struct acpi_table_desc *table_desc, u32 table_index) 51386dfc6f3SLv Zheng { 51486dfc6f3SLv Zheng acpi_status status = AE_OK; 51586dfc6f3SLv Zheng u8 is_equivalent; 51686dfc6f3SLv Zheng struct acpi_table_header *table; 51786dfc6f3SLv Zheng u32 table_length; 51886dfc6f3SLv Zheng u8 table_flags; 51986dfc6f3SLv Zheng 52086dfc6f3SLv Zheng status = 52186dfc6f3SLv Zheng acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index], 52286dfc6f3SLv Zheng &table, &table_length, &table_flags); 52386dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 52486dfc6f3SLv Zheng return (FALSE); 52586dfc6f3SLv Zheng } 52686dfc6f3SLv Zheng 52786dfc6f3SLv Zheng /* 52886dfc6f3SLv Zheng * Check for a table match on the entire table length, 52986dfc6f3SLv Zheng * not just the header. 53086dfc6f3SLv Zheng */ 53186dfc6f3SLv Zheng is_equivalent = (u8)((table_desc->length != table_length || 53286dfc6f3SLv Zheng ACPI_MEMCMP(table_desc->pointer, table, 53386dfc6f3SLv Zheng table_length)) ? FALSE : TRUE); 53486dfc6f3SLv Zheng 53586dfc6f3SLv Zheng /* Release the acquired table */ 53686dfc6f3SLv Zheng 53786dfc6f3SLv Zheng acpi_tb_release_table(table, table_length, table_flags); 53886dfc6f3SLv Zheng 53986dfc6f3SLv Zheng return (is_equivalent); 54086dfc6f3SLv Zheng } 54186dfc6f3SLv Zheng 54286dfc6f3SLv Zheng /******************************************************************************* 54386dfc6f3SLv Zheng * 54486dfc6f3SLv Zheng * FUNCTION: acpi_tb_install_non_fixed_table 54586dfc6f3SLv Zheng * 546*8a216d7fSLv Zheng * PARAMETERS: address - Address of the table (might be a virtual 54786dfc6f3SLv Zheng * address depending on the table_flags) 54886dfc6f3SLv Zheng * flags - Flags for the table 54986dfc6f3SLv Zheng * reload - Whether reload should be performed 55086dfc6f3SLv Zheng * table_index - Where the table index is returned 55186dfc6f3SLv Zheng * 55286dfc6f3SLv Zheng * RETURN: Status 55386dfc6f3SLv Zheng * 55486dfc6f3SLv Zheng * DESCRIPTION: This function is called to install an ACPI table that is 55586dfc6f3SLv Zheng * neither DSDT nor FACS. 55686dfc6f3SLv Zheng * When this function is called by "Load" or "LoadTable" opcodes, 55786dfc6f3SLv Zheng * or by acpi_load_table() API, the "Reload" parameter is set. 55886dfc6f3SLv Zheng * After sucessfully returning from this function, table is 55986dfc6f3SLv Zheng * "INSTALLED" but not "VALIDATED". 56086dfc6f3SLv Zheng * 56186dfc6f3SLv Zheng ******************************************************************************/ 56286dfc6f3SLv Zheng 56386dfc6f3SLv Zheng acpi_status 56486dfc6f3SLv Zheng acpi_tb_install_non_fixed_table(acpi_physical_address address, 56586dfc6f3SLv Zheng u8 flags, u8 reload, u32 *table_index) 56695b482a8SLen Brown { 56795b482a8SLen Brown u32 i; 56895b482a8SLen Brown acpi_status status = AE_OK; 56986dfc6f3SLv Zheng struct acpi_table_desc new_table_desc; 57095b482a8SLen Brown 57186dfc6f3SLv Zheng ACPI_FUNCTION_TRACE(tb_install_non_fixed_table); 57295b482a8SLen Brown 57386dfc6f3SLv Zheng /* Acquire a temporal table descriptor for validation */ 57486dfc6f3SLv Zheng 57586dfc6f3SLv Zheng status = 57686dfc6f3SLv Zheng acpi_tb_acquire_temporal_table(&new_table_desc, address, flags); 57786dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 57886dfc6f3SLv Zheng ACPI_ERROR((AE_INFO, "Could not acquire table length at %p", 57986dfc6f3SLv Zheng ACPI_CAST_PTR(void, address))); 58095b482a8SLen Brown return_ACPI_STATUS(status); 58195b482a8SLen Brown } 58286dfc6f3SLv Zheng 58386dfc6f3SLv Zheng /* Validate and verify a table before installation */ 58486dfc6f3SLv Zheng 58586dfc6f3SLv Zheng status = acpi_tb_verify_table(&new_table_desc, NULL); 58686dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 58786dfc6f3SLv Zheng goto release_and_exit; 58895b482a8SLen Brown } 58995b482a8SLen Brown 59086dfc6f3SLv Zheng if (reload) { 59195b482a8SLen Brown /* 592c8cefe30SBob Moore * Validate the incoming table signature. 593c8cefe30SBob Moore * 594c8cefe30SBob Moore * 1) Originally, we checked the table signature for "SSDT" or "PSDT". 595c8cefe30SBob Moore * 2) We added support for OEMx tables, signature "OEM". 596c8cefe30SBob Moore * 3) Valid tables were encountered with a null signature, so we just 597c8cefe30SBob Moore * gave up on validating the signature, (05/2008). 598c8cefe30SBob Moore * 4) We encountered non-AML tables such as the MADT, which caused 599c8cefe30SBob Moore * interpreter errors and kernel faults. So now, we once again allow 600c8cefe30SBob Moore * only "SSDT", "OEMx", and now, also a null signature. (05/2011). 60195b482a8SLen Brown */ 60286dfc6f3SLv Zheng if ((new_table_desc.signature.ascii[0] != 0x00) && 60386dfc6f3SLv Zheng (!ACPI_COMPARE_NAME 60486dfc6f3SLv Zheng (&new_table_desc.signature, ACPI_SIG_SSDT)) 60586dfc6f3SLv Zheng && (ACPI_STRNCMP(new_table_desc.signature.ascii, "OEM", 3))) 60686dfc6f3SLv Zheng { 6073b3ea775SBob Moore ACPI_BIOS_ERROR((AE_INFO, 6083b3ea775SBob Moore "Table has invalid signature [%4.4s] (0x%8.8X), " 6093b3ea775SBob Moore "must be SSDT or OEMx", 61086dfc6f3SLv Zheng acpi_ut_valid_acpi_name(new_table_desc. 61186dfc6f3SLv Zheng signature. 61286dfc6f3SLv Zheng ascii) ? 61386dfc6f3SLv Zheng new_table_desc.signature. 61486dfc6f3SLv Zheng ascii : "????", 61586dfc6f3SLv Zheng new_table_desc.signature.integer)); 616c8cefe30SBob Moore 61786dfc6f3SLv Zheng status = AE_BAD_SIGNATURE; 61886dfc6f3SLv Zheng goto release_and_exit; 619c8cefe30SBob Moore } 62095b482a8SLen Brown 62195b482a8SLen Brown /* Check if table is already registered */ 62295b482a8SLen Brown 62386dfc6f3SLv Zheng for (i = 0; i < acpi_gbl_root_table_list.current_table_count; 62486dfc6f3SLv Zheng ++i) { 62595b482a8SLen Brown /* 62695b482a8SLen Brown * Check for a table match on the entire table length, 62795b482a8SLen Brown * not just the header. 62895b482a8SLen Brown */ 62986dfc6f3SLv Zheng if (!acpi_tb_is_equivalent_table(&new_table_desc, i)) { 63095b482a8SLen Brown continue; 63195b482a8SLen Brown } 63295b482a8SLen Brown 63395b482a8SLen Brown /* 63495b482a8SLen Brown * Note: the current mechanism does not unregister a table if it is 63595b482a8SLen Brown * dynamically unloaded. The related namespace entries are deleted, 63695b482a8SLen Brown * but the table remains in the root table list. 63795b482a8SLen Brown * 63895b482a8SLen Brown * The assumption here is that the number of different tables that 63995b482a8SLen Brown * will be loaded is actually small, and there is minimal overhead 64095b482a8SLen Brown * in just keeping the table in case it is needed again. 64195b482a8SLen Brown * 64295b482a8SLen Brown * If this assumption changes in the future (perhaps on large 64395b482a8SLen Brown * machines with many table load/unload operations), tables will 64495b482a8SLen Brown * need to be unregistered when they are unloaded, and slots in the 64595b482a8SLen Brown * root table list should be reused when empty. 64695b482a8SLen Brown */ 64795b482a8SLen Brown if (acpi_gbl_root_table_list.tables[i]. 64895b482a8SLen Brown flags & ACPI_TABLE_IS_LOADED) { 64995b482a8SLen Brown 65095b482a8SLen Brown /* Table is still loaded, this is an error */ 65195b482a8SLen Brown 65295b482a8SLen Brown status = AE_ALREADY_EXISTS; 65386dfc6f3SLv Zheng goto release_and_exit; 65495b482a8SLen Brown } else { 655d3ccaff8SBob Moore /* 65686dfc6f3SLv Zheng * Table was unloaded, allow it to be reloaded. 65786dfc6f3SLv Zheng * As we are going to return AE_OK to the caller, we should 65886dfc6f3SLv Zheng * take the responsibility of freeing the input descriptor. 65986dfc6f3SLv Zheng * Refill the input descriptor to ensure 66086dfc6f3SLv Zheng * acpi_tb_install_and_override_table() can be called again to 66186dfc6f3SLv Zheng * indicate the re-installation. 662d3ccaff8SBob Moore */ 66386dfc6f3SLv Zheng acpi_tb_uninstall_table(&new_table_desc); 66486dfc6f3SLv Zheng *table_index = i; 66586dfc6f3SLv Zheng (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 66686dfc6f3SLv Zheng return_ACPI_STATUS(AE_OK); 66786dfc6f3SLv Zheng } 66886dfc6f3SLv Zheng } 6697f9fc99cSLv Zheng } 670d3ccaff8SBob Moore 67195b482a8SLen Brown /* Add the table to the global root table list */ 67295b482a8SLen Brown 67386dfc6f3SLv Zheng status = acpi_tb_acquire_root_table_entry(&i); 67495b482a8SLen Brown if (ACPI_FAILURE(status)) { 67586dfc6f3SLv Zheng goto release_and_exit; 67695b482a8SLen Brown } 67786dfc6f3SLv Zheng *table_index = i; 67886dfc6f3SLv Zheng acpi_tb_install_and_override_table(i, &new_table_desc); 67995b482a8SLen Brown 68086dfc6f3SLv Zheng release_and_exit: 68195b482a8SLen Brown 68286dfc6f3SLv Zheng /* Release the temporal table descriptor */ 68386dfc6f3SLv Zheng 68486dfc6f3SLv Zheng acpi_tb_release_temporal_table(&new_table_desc); 68595b482a8SLen Brown return_ACPI_STATUS(status); 68695b482a8SLen Brown } 68795b482a8SLen Brown 68895b482a8SLen Brown /******************************************************************************* 68995b482a8SLen Brown * 6907f9fc99cSLv Zheng * FUNCTION: acpi_tb_override_table 691f7b004a1SBob Moore * 69286dfc6f3SLv Zheng * PARAMETERS: old_table_desc - Validated table descriptor to be 69386dfc6f3SLv Zheng * overridden 694f7b004a1SBob Moore * 69586dfc6f3SLv Zheng * RETURN: None 696f7b004a1SBob Moore * 697f7b004a1SBob Moore * DESCRIPTION: Attempt table override by calling the OSL override functions. 698f7b004a1SBob Moore * Note: If the table is overridden, then the entire new table 6997f9fc99cSLv Zheng * is acquired and returned by this function. 70086dfc6f3SLv Zheng * Before/after invocation, the table descriptor is in a state 70186dfc6f3SLv Zheng * that is "VALIDATED". 702f7b004a1SBob Moore * 703f7b004a1SBob Moore ******************************************************************************/ 704f7b004a1SBob Moore 70586dfc6f3SLv Zheng void acpi_tb_override_table(struct acpi_table_desc *old_table_desc) 706f7b004a1SBob Moore { 707f7b004a1SBob Moore acpi_status status; 708f7b004a1SBob Moore char *override_type; 7097f9fc99cSLv Zheng struct acpi_table_desc new_table_desc; 71086dfc6f3SLv Zheng struct acpi_table_header *table; 71186dfc6f3SLv Zheng acpi_physical_address address; 71286dfc6f3SLv Zheng u32 length; 713f7b004a1SBob Moore 714f7b004a1SBob Moore /* (1) Attempt logical override (returns a logical address) */ 715f7b004a1SBob Moore 71686dfc6f3SLv Zheng status = acpi_os_table_override(old_table_desc->pointer, &table); 71786dfc6f3SLv Zheng if (ACPI_SUCCESS(status) && table) { 71886dfc6f3SLv Zheng acpi_tb_acquire_temporal_table(&new_table_desc, 71986dfc6f3SLv Zheng ACPI_PTR_TO_PHYSADDR(table), 720*8a216d7fSLv Zheng ACPI_TABLE_ORIGIN_EXTERN_VIRTUAL); 721f7b004a1SBob Moore override_type = "Logical"; 722f7b004a1SBob Moore goto finish_override; 723f7b004a1SBob Moore } 724f7b004a1SBob Moore 725f7b004a1SBob Moore /* (2) Attempt physical override (returns a physical address) */ 726f7b004a1SBob Moore 72786dfc6f3SLv Zheng status = acpi_os_physical_table_override(old_table_desc->pointer, 72886dfc6f3SLv Zheng &address, &length); 72986dfc6f3SLv Zheng if (ACPI_SUCCESS(status) && address && length) { 73086dfc6f3SLv Zheng acpi_tb_acquire_temporal_table(&new_table_desc, address, 731*8a216d7fSLv Zheng ACPI_TABLE_ORIGIN_INTERN_PHYSICAL); 732f7b004a1SBob Moore override_type = "Physical"; 733f7b004a1SBob Moore goto finish_override; 734f7b004a1SBob Moore } 735f7b004a1SBob Moore 73686dfc6f3SLv Zheng return; /* There was no override */ 737f7b004a1SBob Moore 738f7b004a1SBob Moore finish_override: 739f7b004a1SBob Moore 74086dfc6f3SLv Zheng /* Validate and verify a table before overriding */ 74186dfc6f3SLv Zheng 74286dfc6f3SLv Zheng status = acpi_tb_verify_table(&new_table_desc, NULL); 7437f9fc99cSLv Zheng if (ACPI_FAILURE(status)) { 74486dfc6f3SLv Zheng return; 7457f9fc99cSLv Zheng } 7467f9fc99cSLv Zheng 7472e19f8d0SBob Moore ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT 7482e19f8d0SBob Moore " %s table override, new table: " ACPI_PRINTF_UINT, 74986dfc6f3SLv Zheng old_table_desc->signature.ascii, 75086dfc6f3SLv Zheng ACPI_FORMAT_TO_UINT(old_table_desc->address), 7517f9fc99cSLv Zheng override_type, ACPI_FORMAT_TO_UINT(new_table_desc.address))); 752f7b004a1SBob Moore 75386dfc6f3SLv Zheng /* We can now uninstall the original table */ 754f7b004a1SBob Moore 75586dfc6f3SLv Zheng acpi_tb_uninstall_table(old_table_desc); 756f7b004a1SBob Moore 75786dfc6f3SLv Zheng /* 75886dfc6f3SLv Zheng * Replace the original table descriptor and keep its state as 75986dfc6f3SLv Zheng * "VALIDATED". 76086dfc6f3SLv Zheng */ 76186dfc6f3SLv Zheng acpi_tb_install_table(old_table_desc, new_table_desc.address, 76286dfc6f3SLv Zheng new_table_desc.flags, new_table_desc.pointer); 76386dfc6f3SLv Zheng acpi_tb_validate_table(old_table_desc); 764f7b004a1SBob Moore 76586dfc6f3SLv Zheng /* Release the temporal table descriptor */ 766f7b004a1SBob Moore 76786dfc6f3SLv Zheng acpi_tb_release_temporal_table(&new_table_desc); 768f7b004a1SBob Moore } 769f7b004a1SBob Moore 770f7b004a1SBob Moore /******************************************************************************* 771f7b004a1SBob Moore * 77295b482a8SLen Brown * FUNCTION: acpi_tb_resize_root_table_list 77395b482a8SLen Brown * 77495b482a8SLen Brown * PARAMETERS: None 77595b482a8SLen Brown * 77695b482a8SLen Brown * RETURN: Status 77795b482a8SLen Brown * 77895b482a8SLen Brown * DESCRIPTION: Expand the size of global table array 77995b482a8SLen Brown * 78095b482a8SLen Brown ******************************************************************************/ 78195b482a8SLen Brown 78295b482a8SLen Brown acpi_status acpi_tb_resize_root_table_list(void) 78395b482a8SLen Brown { 78495b482a8SLen Brown struct acpi_table_desc *tables; 7852bc198c1SLv Zheng u32 table_count; 78695b482a8SLen Brown 78795b482a8SLen Brown ACPI_FUNCTION_TRACE(tb_resize_root_table_list); 78895b482a8SLen Brown 78995b482a8SLen Brown /* allow_resize flag is a parameter to acpi_initialize_tables */ 79095b482a8SLen Brown 79195b482a8SLen Brown if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) { 79295b482a8SLen Brown ACPI_ERROR((AE_INFO, 79395b482a8SLen Brown "Resize of Root Table Array is not allowed")); 79495b482a8SLen Brown return_ACPI_STATUS(AE_SUPPORT); 79595b482a8SLen Brown } 79695b482a8SLen Brown 79795b482a8SLen Brown /* Increase the Table Array size */ 79895b482a8SLen Brown 7992bc198c1SLv Zheng if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { 8002bc198c1SLv Zheng table_count = acpi_gbl_root_table_list.max_table_count; 8012bc198c1SLv Zheng } else { 8022bc198c1SLv Zheng table_count = acpi_gbl_root_table_list.current_table_count; 8032bc198c1SLv Zheng } 8042bc198c1SLv Zheng 8052bc198c1SLv Zheng tables = ACPI_ALLOCATE_ZEROED(((acpi_size) table_count + 806ec41f193SBob Moore ACPI_ROOT_TABLE_SIZE_INCREMENT) * 807ec41f193SBob Moore sizeof(struct acpi_table_desc)); 80895b482a8SLen Brown if (!tables) { 80995b482a8SLen Brown ACPI_ERROR((AE_INFO, 81095b482a8SLen Brown "Could not allocate new root table array")); 81195b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 81295b482a8SLen Brown } 81395b482a8SLen Brown 81495b482a8SLen Brown /* Copy and free the previous table array */ 81595b482a8SLen Brown 81695b482a8SLen Brown if (acpi_gbl_root_table_list.tables) { 81795b482a8SLen Brown ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, 8182bc198c1SLv Zheng (acpi_size) table_count * 8192bc198c1SLv Zheng sizeof(struct acpi_table_desc)); 82095b482a8SLen Brown 82195b482a8SLen Brown if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { 82295b482a8SLen Brown ACPI_FREE(acpi_gbl_root_table_list.tables); 82395b482a8SLen Brown } 82495b482a8SLen Brown } 82595b482a8SLen Brown 82695b482a8SLen Brown acpi_gbl_root_table_list.tables = tables; 8272bc198c1SLv Zheng acpi_gbl_root_table_list.max_table_count = 8282bc198c1SLv Zheng table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT; 8292bc198c1SLv Zheng acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED; 83095b482a8SLen Brown 83195b482a8SLen Brown return_ACPI_STATUS(AE_OK); 83295b482a8SLen Brown } 83395b482a8SLen Brown 83495b482a8SLen Brown /******************************************************************************* 83595b482a8SLen Brown * 83686dfc6f3SLv Zheng * FUNCTION: acpi_tb_acquire_root_table_entry 83786dfc6f3SLv Zheng * 83886dfc6f3SLv Zheng * PARAMETERS: table_index - Where table index is returned 83986dfc6f3SLv Zheng * 84086dfc6f3SLv Zheng * RETURN: Status and table index. 84186dfc6f3SLv Zheng * 84286dfc6f3SLv Zheng * DESCRIPTION: Allocate a new ACPI table entry to the global table list 84386dfc6f3SLv Zheng * 84486dfc6f3SLv Zheng ******************************************************************************/ 84586dfc6f3SLv Zheng 84686dfc6f3SLv Zheng static acpi_status acpi_tb_acquire_root_table_entry(u32 *table_index) 84786dfc6f3SLv Zheng { 84886dfc6f3SLv Zheng acpi_status status; 84986dfc6f3SLv Zheng 85086dfc6f3SLv Zheng /* Ensure that there is room for the table in the Root Table List */ 85186dfc6f3SLv Zheng 85286dfc6f3SLv Zheng if (acpi_gbl_root_table_list.current_table_count >= 85386dfc6f3SLv Zheng acpi_gbl_root_table_list.max_table_count) { 85486dfc6f3SLv Zheng status = acpi_tb_resize_root_table_list(); 85586dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 85686dfc6f3SLv Zheng return (status); 85786dfc6f3SLv Zheng } 85886dfc6f3SLv Zheng } 85986dfc6f3SLv Zheng 86086dfc6f3SLv Zheng *table_index = acpi_gbl_root_table_list.current_table_count; 86186dfc6f3SLv Zheng acpi_gbl_root_table_list.current_table_count++; 86286dfc6f3SLv Zheng return (AE_OK); 86386dfc6f3SLv Zheng } 86486dfc6f3SLv Zheng 86586dfc6f3SLv Zheng /******************************************************************************* 86686dfc6f3SLv Zheng * 86795b482a8SLen Brown * FUNCTION: acpi_tb_store_table 86895b482a8SLen Brown * 869ba494beeSBob Moore * PARAMETERS: address - Table address 870ba494beeSBob Moore * table - Table header 871ba494beeSBob Moore * length - Table length 872ba494beeSBob Moore * flags - flags 87395b482a8SLen Brown * 87495b482a8SLen Brown * RETURN: Status and table index. 87595b482a8SLen Brown * 87695b482a8SLen Brown * DESCRIPTION: Add an ACPI table to the global table list 87795b482a8SLen Brown * 87895b482a8SLen Brown ******************************************************************************/ 87995b482a8SLen Brown 88095b482a8SLen Brown acpi_status 88195b482a8SLen Brown acpi_tb_store_table(acpi_physical_address address, 88295b482a8SLen Brown struct acpi_table_header * table, 88395b482a8SLen Brown u32 length, u8 flags, u32 *table_index) 88495b482a8SLen Brown { 885b9ee2043SBob Moore acpi_status status; 88686dfc6f3SLv Zheng struct acpi_table_desc *table_desc; 88795b482a8SLen Brown 88886dfc6f3SLv Zheng status = acpi_tb_acquire_root_table_entry(table_index); 88995b482a8SLen Brown if (ACPI_FAILURE(status)) { 89095b482a8SLen Brown return (status); 89195b482a8SLen Brown } 892b9ee2043SBob Moore 89395b482a8SLen Brown /* Initialize added table */ 89495b482a8SLen Brown 89586dfc6f3SLv Zheng table_desc = &acpi_gbl_root_table_list.tables[*table_index]; 89686dfc6f3SLv Zheng acpi_tb_install_table(table_desc, address, flags, table); 89786dfc6f3SLv Zheng table_desc->pointer = table; 89895b482a8SLen Brown 899b9ee2043SBob Moore return (AE_OK); 90095b482a8SLen Brown } 90195b482a8SLen Brown 90295b482a8SLen Brown /******************************************************************************* 90395b482a8SLen Brown * 9047f9fc99cSLv Zheng * FUNCTION: acpi_tb_uninstall_table 90595b482a8SLen Brown * 9067f9fc99cSLv Zheng * PARAMETERS: table_desc - Table descriptor 90795b482a8SLen Brown * 90895b482a8SLen Brown * RETURN: None 90995b482a8SLen Brown * 91095b482a8SLen Brown * DESCRIPTION: Delete one internal ACPI table 91195b482a8SLen Brown * 91295b482a8SLen Brown ******************************************************************************/ 91395b482a8SLen Brown 9147f9fc99cSLv Zheng void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc) 91595b482a8SLen Brown { 9165582982dSLv Zheng 9177f9fc99cSLv Zheng ACPI_FUNCTION_TRACE(tb_uninstall_table); 9185582982dSLv Zheng 9197f9fc99cSLv Zheng /* Table must be installed */ 9207f9fc99cSLv Zheng 9217f9fc99cSLv Zheng if (!table_desc->address) { 9227f9fc99cSLv Zheng return_VOID; 92395b482a8SLen Brown } 9245582982dSLv Zheng 9257f9fc99cSLv Zheng acpi_tb_invalidate_table(table_desc); 9261d1ea1b7SChao Guan 9277f9fc99cSLv Zheng if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == 928*8a216d7fSLv Zheng ACPI_TABLE_ORIGIN_INTERN_VIRTUAL) { 9297f9fc99cSLv Zheng ACPI_FREE(ACPI_CAST_PTR(void, table_desc->address)); 9307f9fc99cSLv Zheng } 9311d1ea1b7SChao Guan 932dc156adfSLv Zheng table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL); 933f7b004a1SBob Moore 9347f9fc99cSLv Zheng return_VOID; 93595b482a8SLen Brown } 93695b482a8SLen Brown 93795b482a8SLen Brown /******************************************************************************* 93895b482a8SLen Brown * 93995b482a8SLen Brown * FUNCTION: acpi_tb_terminate 94095b482a8SLen Brown * 94195b482a8SLen Brown * PARAMETERS: None 94295b482a8SLen Brown * 94395b482a8SLen Brown * RETURN: None 94495b482a8SLen Brown * 94595b482a8SLen Brown * DESCRIPTION: Delete all internal ACPI tables 94695b482a8SLen Brown * 94795b482a8SLen Brown ******************************************************************************/ 94895b482a8SLen Brown 94995b482a8SLen Brown void acpi_tb_terminate(void) 95095b482a8SLen Brown { 95195b482a8SLen Brown u32 i; 95295b482a8SLen Brown 95395b482a8SLen Brown ACPI_FUNCTION_TRACE(tb_terminate); 95495b482a8SLen Brown 95595b482a8SLen Brown (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 95695b482a8SLen Brown 95795b482a8SLen Brown /* Delete the individual tables */ 95895b482a8SLen Brown 959b9ee2043SBob Moore for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { 9607f9fc99cSLv Zheng acpi_tb_uninstall_table(&acpi_gbl_root_table_list.tables[i]); 96195b482a8SLen Brown } 96295b482a8SLen Brown 96395b482a8SLen Brown /* 96495b482a8SLen Brown * Delete the root table array if allocated locally. Array cannot be 96595b482a8SLen Brown * mapped, so we don't need to check for that flag. 96695b482a8SLen Brown */ 96795b482a8SLen Brown if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { 96895b482a8SLen Brown ACPI_FREE(acpi_gbl_root_table_list.tables); 96995b482a8SLen Brown } 97095b482a8SLen Brown 97195b482a8SLen Brown acpi_gbl_root_table_list.tables = NULL; 97295b482a8SLen Brown acpi_gbl_root_table_list.flags = 0; 973b9ee2043SBob Moore acpi_gbl_root_table_list.current_table_count = 0; 97495b482a8SLen Brown 97595b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n")); 97695b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 97768aafc35SBob Moore 97868aafc35SBob Moore return_VOID; 97995b482a8SLen Brown } 98095b482a8SLen Brown 98195b482a8SLen Brown /******************************************************************************* 98295b482a8SLen Brown * 98395b482a8SLen Brown * FUNCTION: acpi_tb_delete_namespace_by_owner 98495b482a8SLen Brown * 98595b482a8SLen Brown * PARAMETERS: table_index - Table index 98695b482a8SLen Brown * 9878a335a23SBob Moore * RETURN: Status 98895b482a8SLen Brown * 98995b482a8SLen Brown * DESCRIPTION: Delete all namespace objects created when this table was loaded. 99095b482a8SLen Brown * 99195b482a8SLen Brown ******************************************************************************/ 99295b482a8SLen Brown 9938a335a23SBob Moore acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index) 99495b482a8SLen Brown { 99595b482a8SLen Brown acpi_owner_id owner_id; 9968a335a23SBob Moore acpi_status status; 99795b482a8SLen Brown 9988a335a23SBob Moore ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner); 9998a335a23SBob Moore 10008a335a23SBob Moore status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 10018a335a23SBob Moore if (ACPI_FAILURE(status)) { 10028a335a23SBob Moore return_ACPI_STATUS(status); 100395b482a8SLen Brown } 100495b482a8SLen Brown 1005b9ee2043SBob Moore if (table_index >= acpi_gbl_root_table_list.current_table_count) { 10068a335a23SBob Moore 10078a335a23SBob Moore /* The table index does not exist */ 10088a335a23SBob Moore 100995b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 10108a335a23SBob Moore return_ACPI_STATUS(AE_NOT_EXIST); 10118a335a23SBob Moore } 10128a335a23SBob Moore 10138a335a23SBob Moore /* Get the owner ID for this table, used to delete namespace nodes */ 10148a335a23SBob Moore 10158a335a23SBob Moore owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id; 10168a335a23SBob Moore (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 10178a335a23SBob Moore 10188a335a23SBob Moore /* 10198a335a23SBob Moore * Need to acquire the namespace writer lock to prevent interference 10208a335a23SBob Moore * with any concurrent namespace walks. The interpreter must be 10218a335a23SBob Moore * released during the deletion since the acquisition of the deletion 10228a335a23SBob Moore * lock may block, and also since the execution of a namespace walk 10238a335a23SBob Moore * must be allowed to use the interpreter. 10248a335a23SBob Moore */ 1025e4c1ebfcSBob Moore (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); 10268a335a23SBob Moore status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock); 10278a335a23SBob Moore 102895b482a8SLen Brown acpi_ns_delete_namespace_by_owner(owner_id); 10298a335a23SBob Moore if (ACPI_FAILURE(status)) { 10308a335a23SBob Moore return_ACPI_STATUS(status); 10318a335a23SBob Moore } 10328a335a23SBob Moore 10338a335a23SBob Moore acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock); 10348a335a23SBob Moore 10358a335a23SBob Moore status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); 10368a335a23SBob Moore return_ACPI_STATUS(status); 103795b482a8SLen Brown } 103895b482a8SLen Brown 103995b482a8SLen Brown /******************************************************************************* 104095b482a8SLen Brown * 104195b482a8SLen Brown * FUNCTION: acpi_tb_allocate_owner_id 104295b482a8SLen Brown * 104395b482a8SLen Brown * PARAMETERS: table_index - Table index 104495b482a8SLen Brown * 104595b482a8SLen Brown * RETURN: Status 104695b482a8SLen Brown * 104795b482a8SLen Brown * DESCRIPTION: Allocates owner_id in table_desc 104895b482a8SLen Brown * 104995b482a8SLen Brown ******************************************************************************/ 105095b482a8SLen Brown 105195b482a8SLen Brown acpi_status acpi_tb_allocate_owner_id(u32 table_index) 105295b482a8SLen Brown { 105395b482a8SLen Brown acpi_status status = AE_BAD_PARAMETER; 105495b482a8SLen Brown 105595b482a8SLen Brown ACPI_FUNCTION_TRACE(tb_allocate_owner_id); 105695b482a8SLen Brown 105795b482a8SLen Brown (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 1058b9ee2043SBob Moore if (table_index < acpi_gbl_root_table_list.current_table_count) { 105995b482a8SLen Brown status = acpi_ut_allocate_owner_id 106095b482a8SLen Brown (&(acpi_gbl_root_table_list.tables[table_index].owner_id)); 106195b482a8SLen Brown } 106295b482a8SLen Brown 106395b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 106495b482a8SLen Brown return_ACPI_STATUS(status); 106595b482a8SLen Brown } 106695b482a8SLen Brown 106795b482a8SLen Brown /******************************************************************************* 106895b482a8SLen Brown * 106995b482a8SLen Brown * FUNCTION: acpi_tb_release_owner_id 107095b482a8SLen Brown * 107195b482a8SLen Brown * PARAMETERS: table_index - Table index 107295b482a8SLen Brown * 107395b482a8SLen Brown * RETURN: Status 107495b482a8SLen Brown * 107595b482a8SLen Brown * DESCRIPTION: Releases owner_id in table_desc 107695b482a8SLen Brown * 107795b482a8SLen Brown ******************************************************************************/ 107895b482a8SLen Brown 107995b482a8SLen Brown acpi_status acpi_tb_release_owner_id(u32 table_index) 108095b482a8SLen Brown { 108195b482a8SLen Brown acpi_status status = AE_BAD_PARAMETER; 108295b482a8SLen Brown 108395b482a8SLen Brown ACPI_FUNCTION_TRACE(tb_release_owner_id); 108495b482a8SLen Brown 108595b482a8SLen Brown (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 1086b9ee2043SBob Moore if (table_index < acpi_gbl_root_table_list.current_table_count) { 108795b482a8SLen Brown acpi_ut_release_owner_id(& 108895b482a8SLen Brown (acpi_gbl_root_table_list. 108995b482a8SLen Brown tables[table_index].owner_id)); 109095b482a8SLen Brown status = AE_OK; 109195b482a8SLen Brown } 109295b482a8SLen Brown 109395b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 109495b482a8SLen Brown return_ACPI_STATUS(status); 109595b482a8SLen Brown } 109695b482a8SLen Brown 109795b482a8SLen Brown /******************************************************************************* 109895b482a8SLen Brown * 109995b482a8SLen Brown * FUNCTION: acpi_tb_get_owner_id 110095b482a8SLen Brown * 110195b482a8SLen Brown * PARAMETERS: table_index - Table index 110295b482a8SLen Brown * owner_id - Where the table owner_id is returned 110395b482a8SLen Brown * 110495b482a8SLen Brown * RETURN: Status 110595b482a8SLen Brown * 110695b482a8SLen Brown * DESCRIPTION: returns owner_id for the ACPI table 110795b482a8SLen Brown * 110895b482a8SLen Brown ******************************************************************************/ 110995b482a8SLen Brown 111095b482a8SLen Brown acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id * owner_id) 111195b482a8SLen Brown { 111295b482a8SLen Brown acpi_status status = AE_BAD_PARAMETER; 111395b482a8SLen Brown 111495b482a8SLen Brown ACPI_FUNCTION_TRACE(tb_get_owner_id); 111595b482a8SLen Brown 111695b482a8SLen Brown (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 1117b9ee2043SBob Moore if (table_index < acpi_gbl_root_table_list.current_table_count) { 111895b482a8SLen Brown *owner_id = 111995b482a8SLen Brown acpi_gbl_root_table_list.tables[table_index].owner_id; 112095b482a8SLen Brown status = AE_OK; 112195b482a8SLen Brown } 112295b482a8SLen Brown 112395b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 112495b482a8SLen Brown return_ACPI_STATUS(status); 112595b482a8SLen Brown } 112695b482a8SLen Brown 112795b482a8SLen Brown /******************************************************************************* 112895b482a8SLen Brown * 112995b482a8SLen Brown * FUNCTION: acpi_tb_is_table_loaded 113095b482a8SLen Brown * 113195b482a8SLen Brown * PARAMETERS: table_index - Table index 113295b482a8SLen Brown * 113395b482a8SLen Brown * RETURN: Table Loaded Flag 113495b482a8SLen Brown * 113595b482a8SLen Brown ******************************************************************************/ 113695b482a8SLen Brown 113795b482a8SLen Brown u8 acpi_tb_is_table_loaded(u32 table_index) 113895b482a8SLen Brown { 113995b482a8SLen Brown u8 is_loaded = FALSE; 114095b482a8SLen Brown 114195b482a8SLen Brown (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 1142b9ee2043SBob Moore if (table_index < acpi_gbl_root_table_list.current_table_count) { 114395b482a8SLen Brown is_loaded = (u8) 1144ec41f193SBob Moore (acpi_gbl_root_table_list.tables[table_index].flags & 1145ec41f193SBob Moore ACPI_TABLE_IS_LOADED); 114695b482a8SLen Brown } 114795b482a8SLen Brown 114895b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 114995b482a8SLen Brown return (is_loaded); 115095b482a8SLen Brown } 115195b482a8SLen Brown 115295b482a8SLen Brown /******************************************************************************* 115395b482a8SLen Brown * 115495b482a8SLen Brown * FUNCTION: acpi_tb_set_table_loaded_flag 115595b482a8SLen Brown * 115695b482a8SLen Brown * PARAMETERS: table_index - Table index 115795b482a8SLen Brown * is_loaded - TRUE if table is loaded, FALSE otherwise 115895b482a8SLen Brown * 115995b482a8SLen Brown * RETURN: None 116095b482a8SLen Brown * 116195b482a8SLen Brown * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE. 116295b482a8SLen Brown * 116395b482a8SLen Brown ******************************************************************************/ 116495b482a8SLen Brown 116595b482a8SLen Brown void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded) 116695b482a8SLen Brown { 116795b482a8SLen Brown 116895b482a8SLen Brown (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 1169b9ee2043SBob Moore if (table_index < acpi_gbl_root_table_list.current_table_count) { 117095b482a8SLen Brown if (is_loaded) { 117195b482a8SLen Brown acpi_gbl_root_table_list.tables[table_index].flags |= 117295b482a8SLen Brown ACPI_TABLE_IS_LOADED; 117395b482a8SLen Brown } else { 117495b482a8SLen Brown acpi_gbl_root_table_list.tables[table_index].flags &= 117595b482a8SLen Brown ~ACPI_TABLE_IS_LOADED; 117695b482a8SLen Brown } 117795b482a8SLen Brown } 117895b482a8SLen Brown 117995b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 118095b482a8SLen Brown } 1181