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) { 898a216d7fSLv 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 958a216d7fSLv Zheng case ACPI_TABLE_ORIGIN_INTERN_VIRTUAL: 968a216d7fSLv 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) { 1428a216d7fSLv Zheng case ACPI_TABLE_ORIGIN_INTERN_PHYSICAL: 1437f9fc99cSLv Zheng 1447f9fc99cSLv Zheng acpi_os_unmap_memory(table, table_length); 1457f9fc99cSLv Zheng break; 1467f9fc99cSLv Zheng 1478a216d7fSLv Zheng case ACPI_TABLE_ORIGIN_INTERN_VIRTUAL: 1488a216d7fSLv 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) { 3348a216d7fSLv 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 3498a216d7fSLv Zheng case ACPI_TABLE_ORIGIN_INTERN_VIRTUAL: 3508a216d7fSLv 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 397*caf4a15cSLv Zheng * override - Whether override should be performed 39886dfc6f3SLv Zheng * 39986dfc6f3SLv Zheng * RETURN: None 40086dfc6f3SLv Zheng * 40186dfc6f3SLv Zheng * DESCRIPTION: Install an ACPI table into the global data structure. The 40286dfc6f3SLv Zheng * table override mechanism is called to allow the host 40386dfc6f3SLv Zheng * OS to replace any table before it is installed in the root 40486dfc6f3SLv Zheng * table array. 40586dfc6f3SLv Zheng * 40686dfc6f3SLv Zheng ******************************************************************************/ 40786dfc6f3SLv Zheng 40886dfc6f3SLv Zheng void 40986dfc6f3SLv Zheng acpi_tb_install_and_override_table(u32 table_index, 410*caf4a15cSLv Zheng struct acpi_table_desc *new_table_desc, 411*caf4a15cSLv Zheng u8 override) 41286dfc6f3SLv Zheng { 41386dfc6f3SLv Zheng if (table_index >= acpi_gbl_root_table_list.current_table_count) { 41486dfc6f3SLv Zheng return; 41586dfc6f3SLv Zheng } 41686dfc6f3SLv Zheng 41786dfc6f3SLv Zheng /* 41886dfc6f3SLv Zheng * ACPI Table Override: 41986dfc6f3SLv Zheng * 42086dfc6f3SLv Zheng * Before we install the table, let the host OS override it with a new 42186dfc6f3SLv Zheng * one if desired. Any table within the RSDT/XSDT can be replaced, 42286dfc6f3SLv Zheng * including the DSDT which is pointed to by the FADT. 42386dfc6f3SLv Zheng */ 424*caf4a15cSLv Zheng if (override) { 42586dfc6f3SLv Zheng acpi_tb_override_table(new_table_desc); 426*caf4a15cSLv Zheng } 42786dfc6f3SLv Zheng 42886dfc6f3SLv Zheng acpi_tb_install_table(&acpi_gbl_root_table_list.tables[table_index], 42986dfc6f3SLv Zheng new_table_desc->address, new_table_desc->flags, 43086dfc6f3SLv Zheng new_table_desc->pointer); 43186dfc6f3SLv Zheng 43286dfc6f3SLv Zheng acpi_tb_print_table_header(new_table_desc->address, 43386dfc6f3SLv Zheng new_table_desc->pointer); 43486dfc6f3SLv Zheng 43586dfc6f3SLv Zheng /* Set the global integer width (based upon revision of the DSDT) */ 43686dfc6f3SLv Zheng 43786dfc6f3SLv Zheng if (table_index == ACPI_TABLE_INDEX_DSDT) { 43886dfc6f3SLv Zheng acpi_ut_set_integer_width(new_table_desc->pointer->revision); 43986dfc6f3SLv Zheng } 44086dfc6f3SLv Zheng } 44186dfc6f3SLv Zheng 44286dfc6f3SLv Zheng /******************************************************************************* 44386dfc6f3SLv Zheng * 44486dfc6f3SLv Zheng * FUNCTION: acpi_tb_install_fixed_table 44586dfc6f3SLv Zheng * 44686dfc6f3SLv Zheng * PARAMETERS: address - Physical address of DSDT or FACS 44786dfc6f3SLv Zheng * signature - Table signature, NULL if no need to 44886dfc6f3SLv Zheng * match 44986dfc6f3SLv Zheng * table_index - Index into root table array 45086dfc6f3SLv Zheng * 45186dfc6f3SLv Zheng * RETURN: Status 45286dfc6f3SLv Zheng * 45386dfc6f3SLv Zheng * DESCRIPTION: Install a fixed ACPI table (DSDT/FACS) into the global data 45486dfc6f3SLv Zheng * structure. 45595b482a8SLen Brown * 45695b482a8SLen Brown ******************************************************************************/ 45795b482a8SLen Brown 45895b482a8SLen Brown acpi_status 45986dfc6f3SLv Zheng acpi_tb_install_fixed_table(acpi_physical_address address, 46086dfc6f3SLv Zheng char *signature, u32 table_index) 46186dfc6f3SLv Zheng { 46286dfc6f3SLv Zheng struct acpi_table_desc new_table_desc; 46386dfc6f3SLv Zheng acpi_status status; 46486dfc6f3SLv Zheng 46586dfc6f3SLv Zheng ACPI_FUNCTION_TRACE(tb_install_fixed_table); 46686dfc6f3SLv Zheng 46786dfc6f3SLv Zheng if (!address) { 46886dfc6f3SLv Zheng ACPI_ERROR((AE_INFO, 46986dfc6f3SLv Zheng "Null physical address for ACPI table [%s]", 47086dfc6f3SLv Zheng signature)); 47186dfc6f3SLv Zheng return (AE_NO_MEMORY); 47286dfc6f3SLv Zheng } 47386dfc6f3SLv Zheng 47486dfc6f3SLv Zheng /* Fill a table descriptor for validation */ 47586dfc6f3SLv Zheng 47686dfc6f3SLv Zheng status = acpi_tb_acquire_temporal_table(&new_table_desc, address, 4778a216d7fSLv Zheng ACPI_TABLE_ORIGIN_INTERN_PHYSICAL); 47886dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 47986dfc6f3SLv Zheng ACPI_ERROR((AE_INFO, "Could not acquire table length at %p", 48086dfc6f3SLv Zheng ACPI_CAST_PTR(void, address))); 48186dfc6f3SLv Zheng return_ACPI_STATUS(status); 48286dfc6f3SLv Zheng } 48386dfc6f3SLv Zheng 48486dfc6f3SLv Zheng /* Validate and verify a table before installation */ 48586dfc6f3SLv Zheng 48686dfc6f3SLv Zheng status = acpi_tb_verify_table(&new_table_desc, signature); 48786dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 48886dfc6f3SLv Zheng goto release_and_exit; 48986dfc6f3SLv Zheng } 49086dfc6f3SLv Zheng 491*caf4a15cSLv Zheng acpi_tb_install_and_override_table(table_index, &new_table_desc, TRUE); 49286dfc6f3SLv Zheng 49386dfc6f3SLv Zheng release_and_exit: 49486dfc6f3SLv Zheng 49586dfc6f3SLv Zheng /* Release the temporal table descriptor */ 49686dfc6f3SLv Zheng 49786dfc6f3SLv Zheng acpi_tb_release_temporal_table(&new_table_desc); 49886dfc6f3SLv Zheng return_ACPI_STATUS(status); 49986dfc6f3SLv Zheng } 50086dfc6f3SLv Zheng 50186dfc6f3SLv Zheng /******************************************************************************* 50286dfc6f3SLv Zheng * 50386dfc6f3SLv Zheng * FUNCTION: acpi_tb_is_equivalent_table 50486dfc6f3SLv Zheng * 50586dfc6f3SLv Zheng * PARAMETERS: table_desc - Table 1 descriptor to be compared 50686dfc6f3SLv Zheng * table_index - Index of table 2 to be compared 50786dfc6f3SLv Zheng * 50886dfc6f3SLv Zheng * RETURN: TRUE if 2 tables are equivalent 50986dfc6f3SLv Zheng * 51086dfc6f3SLv Zheng * DESCRIPTION: This function is called to compare a table with what have 51186dfc6f3SLv Zheng * already been installed in the root table list. 51286dfc6f3SLv Zheng * 51386dfc6f3SLv Zheng ******************************************************************************/ 51486dfc6f3SLv Zheng 51586dfc6f3SLv Zheng static u8 51686dfc6f3SLv Zheng acpi_tb_is_equivalent_table(struct acpi_table_desc *table_desc, u32 table_index) 51786dfc6f3SLv Zheng { 51886dfc6f3SLv Zheng acpi_status status = AE_OK; 51986dfc6f3SLv Zheng u8 is_equivalent; 52086dfc6f3SLv Zheng struct acpi_table_header *table; 52186dfc6f3SLv Zheng u32 table_length; 52286dfc6f3SLv Zheng u8 table_flags; 52386dfc6f3SLv Zheng 52486dfc6f3SLv Zheng status = 52586dfc6f3SLv Zheng acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index], 52686dfc6f3SLv Zheng &table, &table_length, &table_flags); 52786dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 52886dfc6f3SLv Zheng return (FALSE); 52986dfc6f3SLv Zheng } 53086dfc6f3SLv Zheng 53186dfc6f3SLv Zheng /* 53286dfc6f3SLv Zheng * Check for a table match on the entire table length, 53386dfc6f3SLv Zheng * not just the header. 53486dfc6f3SLv Zheng */ 53586dfc6f3SLv Zheng is_equivalent = (u8)((table_desc->length != table_length || 53686dfc6f3SLv Zheng ACPI_MEMCMP(table_desc->pointer, table, 53786dfc6f3SLv Zheng table_length)) ? FALSE : TRUE); 53886dfc6f3SLv Zheng 53986dfc6f3SLv Zheng /* Release the acquired table */ 54086dfc6f3SLv Zheng 54186dfc6f3SLv Zheng acpi_tb_release_table(table, table_length, table_flags); 54286dfc6f3SLv Zheng 54386dfc6f3SLv Zheng return (is_equivalent); 54486dfc6f3SLv Zheng } 54586dfc6f3SLv Zheng 54686dfc6f3SLv Zheng /******************************************************************************* 54786dfc6f3SLv Zheng * 54886dfc6f3SLv Zheng * FUNCTION: acpi_tb_install_non_fixed_table 54986dfc6f3SLv Zheng * 5508a216d7fSLv Zheng * PARAMETERS: address - Address of the table (might be a virtual 55186dfc6f3SLv Zheng * address depending on the table_flags) 55286dfc6f3SLv Zheng * flags - Flags for the table 55386dfc6f3SLv Zheng * reload - Whether reload should be performed 554*caf4a15cSLv Zheng * override - Whether override should be performed 55586dfc6f3SLv Zheng * table_index - Where the table index is returned 55686dfc6f3SLv Zheng * 55786dfc6f3SLv Zheng * RETURN: Status 55886dfc6f3SLv Zheng * 55986dfc6f3SLv Zheng * DESCRIPTION: This function is called to install an ACPI table that is 56086dfc6f3SLv Zheng * neither DSDT nor FACS. 56186dfc6f3SLv Zheng * When this function is called by "Load" or "LoadTable" opcodes, 56286dfc6f3SLv Zheng * or by acpi_load_table() API, the "Reload" parameter is set. 56386dfc6f3SLv Zheng * After sucessfully returning from this function, table is 56486dfc6f3SLv Zheng * "INSTALLED" but not "VALIDATED". 56586dfc6f3SLv Zheng * 56686dfc6f3SLv Zheng ******************************************************************************/ 56786dfc6f3SLv Zheng 56886dfc6f3SLv Zheng acpi_status 56986dfc6f3SLv Zheng acpi_tb_install_non_fixed_table(acpi_physical_address address, 570*caf4a15cSLv Zheng u8 flags, 571*caf4a15cSLv Zheng u8 reload, u8 override, u32 *table_index) 57295b482a8SLen Brown { 57395b482a8SLen Brown u32 i; 57495b482a8SLen Brown acpi_status status = AE_OK; 57586dfc6f3SLv Zheng struct acpi_table_desc new_table_desc; 57695b482a8SLen Brown 57786dfc6f3SLv Zheng ACPI_FUNCTION_TRACE(tb_install_non_fixed_table); 57895b482a8SLen Brown 57986dfc6f3SLv Zheng /* Acquire a temporal table descriptor for validation */ 58086dfc6f3SLv Zheng 58186dfc6f3SLv Zheng status = 58286dfc6f3SLv Zheng acpi_tb_acquire_temporal_table(&new_table_desc, address, flags); 58386dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 58486dfc6f3SLv Zheng ACPI_ERROR((AE_INFO, "Could not acquire table length at %p", 58586dfc6f3SLv Zheng ACPI_CAST_PTR(void, address))); 58695b482a8SLen Brown return_ACPI_STATUS(status); 58795b482a8SLen Brown } 58886dfc6f3SLv Zheng 589a94e88cdSLv Zheng /* 590a94e88cdSLv Zheng * Optionally do not load any SSDTs from the RSDT/XSDT. This can 591a94e88cdSLv Zheng * be useful for debugging ACPI problems on some machines. 592a94e88cdSLv Zheng */ 593a94e88cdSLv Zheng if (!reload && acpi_gbl_disable_ssdt_table_install && 594a94e88cdSLv Zheng ACPI_COMPARE_NAME(&new_table_desc.signature, ACPI_SIG_SSDT)) { 595a94e88cdSLv Zheng ACPI_INFO((AE_INFO, "Ignoring installation of %4.4s at %p", 596a94e88cdSLv Zheng new_table_desc.signature.ascii, ACPI_CAST_PTR(void, 597a94e88cdSLv Zheng address))); 598a94e88cdSLv Zheng goto release_and_exit; 599a94e88cdSLv Zheng } 600a94e88cdSLv Zheng 60186dfc6f3SLv Zheng /* Validate and verify a table before installation */ 60286dfc6f3SLv Zheng 60386dfc6f3SLv Zheng status = acpi_tb_verify_table(&new_table_desc, NULL); 60486dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 60586dfc6f3SLv Zheng goto release_and_exit; 60695b482a8SLen Brown } 60795b482a8SLen Brown 60886dfc6f3SLv Zheng if (reload) { 60995b482a8SLen Brown /* 610c8cefe30SBob Moore * Validate the incoming table signature. 611c8cefe30SBob Moore * 612c8cefe30SBob Moore * 1) Originally, we checked the table signature for "SSDT" or "PSDT". 613c8cefe30SBob Moore * 2) We added support for OEMx tables, signature "OEM". 614c8cefe30SBob Moore * 3) Valid tables were encountered with a null signature, so we just 615c8cefe30SBob Moore * gave up on validating the signature, (05/2008). 616c8cefe30SBob Moore * 4) We encountered non-AML tables such as the MADT, which caused 617c8cefe30SBob Moore * interpreter errors and kernel faults. So now, we once again allow 618c8cefe30SBob Moore * only "SSDT", "OEMx", and now, also a null signature. (05/2011). 61995b482a8SLen Brown */ 62086dfc6f3SLv Zheng if ((new_table_desc.signature.ascii[0] != 0x00) && 62186dfc6f3SLv Zheng (!ACPI_COMPARE_NAME 62286dfc6f3SLv Zheng (&new_table_desc.signature, ACPI_SIG_SSDT)) 62386dfc6f3SLv Zheng && (ACPI_STRNCMP(new_table_desc.signature.ascii, "OEM", 3))) 62486dfc6f3SLv Zheng { 6253b3ea775SBob Moore ACPI_BIOS_ERROR((AE_INFO, 6263b3ea775SBob Moore "Table has invalid signature [%4.4s] (0x%8.8X), " 6273b3ea775SBob Moore "must be SSDT or OEMx", 62886dfc6f3SLv Zheng acpi_ut_valid_acpi_name(new_table_desc. 62986dfc6f3SLv Zheng signature. 63086dfc6f3SLv Zheng ascii) ? 63186dfc6f3SLv Zheng new_table_desc.signature. 63286dfc6f3SLv Zheng ascii : "????", 63386dfc6f3SLv Zheng new_table_desc.signature.integer)); 634c8cefe30SBob Moore 63586dfc6f3SLv Zheng status = AE_BAD_SIGNATURE; 63686dfc6f3SLv Zheng goto release_and_exit; 637c8cefe30SBob Moore } 63895b482a8SLen Brown 63995b482a8SLen Brown /* Check if table is already registered */ 64095b482a8SLen Brown 64186dfc6f3SLv Zheng for (i = 0; i < acpi_gbl_root_table_list.current_table_count; 64286dfc6f3SLv Zheng ++i) { 64395b482a8SLen Brown /* 64495b482a8SLen Brown * Check for a table match on the entire table length, 64595b482a8SLen Brown * not just the header. 64695b482a8SLen Brown */ 64786dfc6f3SLv Zheng if (!acpi_tb_is_equivalent_table(&new_table_desc, i)) { 64895b482a8SLen Brown continue; 64995b482a8SLen Brown } 65095b482a8SLen Brown 65195b482a8SLen Brown /* 65295b482a8SLen Brown * Note: the current mechanism does not unregister a table if it is 65395b482a8SLen Brown * dynamically unloaded. The related namespace entries are deleted, 65495b482a8SLen Brown * but the table remains in the root table list. 65595b482a8SLen Brown * 65695b482a8SLen Brown * The assumption here is that the number of different tables that 65795b482a8SLen Brown * will be loaded is actually small, and there is minimal overhead 65895b482a8SLen Brown * in just keeping the table in case it is needed again. 65995b482a8SLen Brown * 66095b482a8SLen Brown * If this assumption changes in the future (perhaps on large 66195b482a8SLen Brown * machines with many table load/unload operations), tables will 66295b482a8SLen Brown * need to be unregistered when they are unloaded, and slots in the 66395b482a8SLen Brown * root table list should be reused when empty. 66495b482a8SLen Brown */ 66595b482a8SLen Brown if (acpi_gbl_root_table_list.tables[i]. 66695b482a8SLen Brown flags & ACPI_TABLE_IS_LOADED) { 66795b482a8SLen Brown 66895b482a8SLen Brown /* Table is still loaded, this is an error */ 66995b482a8SLen Brown 67095b482a8SLen Brown status = AE_ALREADY_EXISTS; 67186dfc6f3SLv Zheng goto release_and_exit; 67295b482a8SLen Brown } else { 673d3ccaff8SBob Moore /* 67486dfc6f3SLv Zheng * Table was unloaded, allow it to be reloaded. 67586dfc6f3SLv Zheng * As we are going to return AE_OK to the caller, we should 67686dfc6f3SLv Zheng * take the responsibility of freeing the input descriptor. 67786dfc6f3SLv Zheng * Refill the input descriptor to ensure 67886dfc6f3SLv Zheng * acpi_tb_install_and_override_table() can be called again to 67986dfc6f3SLv Zheng * indicate the re-installation. 680d3ccaff8SBob Moore */ 68186dfc6f3SLv Zheng acpi_tb_uninstall_table(&new_table_desc); 68286dfc6f3SLv Zheng *table_index = i; 68386dfc6f3SLv Zheng (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 68486dfc6f3SLv Zheng return_ACPI_STATUS(AE_OK); 68586dfc6f3SLv Zheng } 68686dfc6f3SLv Zheng } 6877f9fc99cSLv Zheng } 688d3ccaff8SBob Moore 68995b482a8SLen Brown /* Add the table to the global root table list */ 69095b482a8SLen Brown 69186dfc6f3SLv Zheng status = acpi_tb_acquire_root_table_entry(&i); 69295b482a8SLen Brown if (ACPI_FAILURE(status)) { 69386dfc6f3SLv Zheng goto release_and_exit; 69495b482a8SLen Brown } 69586dfc6f3SLv Zheng *table_index = i; 696*caf4a15cSLv Zheng acpi_tb_install_and_override_table(i, &new_table_desc, override); 69795b482a8SLen Brown 69886dfc6f3SLv Zheng release_and_exit: 69995b482a8SLen Brown 70086dfc6f3SLv Zheng /* Release the temporal table descriptor */ 70186dfc6f3SLv Zheng 70286dfc6f3SLv Zheng acpi_tb_release_temporal_table(&new_table_desc); 70395b482a8SLen Brown return_ACPI_STATUS(status); 70495b482a8SLen Brown } 70595b482a8SLen Brown 70695b482a8SLen Brown /******************************************************************************* 70795b482a8SLen Brown * 7087f9fc99cSLv Zheng * FUNCTION: acpi_tb_override_table 709f7b004a1SBob Moore * 71086dfc6f3SLv Zheng * PARAMETERS: old_table_desc - Validated table descriptor to be 71186dfc6f3SLv Zheng * overridden 712f7b004a1SBob Moore * 71386dfc6f3SLv Zheng * RETURN: None 714f7b004a1SBob Moore * 715f7b004a1SBob Moore * DESCRIPTION: Attempt table override by calling the OSL override functions. 716f7b004a1SBob Moore * Note: If the table is overridden, then the entire new table 7177f9fc99cSLv Zheng * is acquired and returned by this function. 71886dfc6f3SLv Zheng * Before/after invocation, the table descriptor is in a state 71986dfc6f3SLv Zheng * that is "VALIDATED". 720f7b004a1SBob Moore * 721f7b004a1SBob Moore ******************************************************************************/ 722f7b004a1SBob Moore 72386dfc6f3SLv Zheng void acpi_tb_override_table(struct acpi_table_desc *old_table_desc) 724f7b004a1SBob Moore { 725f7b004a1SBob Moore acpi_status status; 726f7b004a1SBob Moore char *override_type; 7277f9fc99cSLv Zheng struct acpi_table_desc new_table_desc; 72886dfc6f3SLv Zheng struct acpi_table_header *table; 72986dfc6f3SLv Zheng acpi_physical_address address; 73086dfc6f3SLv Zheng u32 length; 731f7b004a1SBob Moore 732f7b004a1SBob Moore /* (1) Attempt logical override (returns a logical address) */ 733f7b004a1SBob Moore 73486dfc6f3SLv Zheng status = acpi_os_table_override(old_table_desc->pointer, &table); 73586dfc6f3SLv Zheng if (ACPI_SUCCESS(status) && table) { 73686dfc6f3SLv Zheng acpi_tb_acquire_temporal_table(&new_table_desc, 73786dfc6f3SLv Zheng ACPI_PTR_TO_PHYSADDR(table), 7388a216d7fSLv Zheng ACPI_TABLE_ORIGIN_EXTERN_VIRTUAL); 739f7b004a1SBob Moore override_type = "Logical"; 740f7b004a1SBob Moore goto finish_override; 741f7b004a1SBob Moore } 742f7b004a1SBob Moore 743f7b004a1SBob Moore /* (2) Attempt physical override (returns a physical address) */ 744f7b004a1SBob Moore 74586dfc6f3SLv Zheng status = acpi_os_physical_table_override(old_table_desc->pointer, 74686dfc6f3SLv Zheng &address, &length); 74786dfc6f3SLv Zheng if (ACPI_SUCCESS(status) && address && length) { 74886dfc6f3SLv Zheng acpi_tb_acquire_temporal_table(&new_table_desc, address, 7498a216d7fSLv Zheng ACPI_TABLE_ORIGIN_INTERN_PHYSICAL); 750f7b004a1SBob Moore override_type = "Physical"; 751f7b004a1SBob Moore goto finish_override; 752f7b004a1SBob Moore } 753f7b004a1SBob Moore 75486dfc6f3SLv Zheng return; /* There was no override */ 755f7b004a1SBob Moore 756f7b004a1SBob Moore finish_override: 757f7b004a1SBob Moore 75886dfc6f3SLv Zheng /* Validate and verify a table before overriding */ 75986dfc6f3SLv Zheng 76086dfc6f3SLv Zheng status = acpi_tb_verify_table(&new_table_desc, NULL); 7617f9fc99cSLv Zheng if (ACPI_FAILURE(status)) { 76286dfc6f3SLv Zheng return; 7637f9fc99cSLv Zheng } 7647f9fc99cSLv Zheng 7652e19f8d0SBob Moore ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT 7662e19f8d0SBob Moore " %s table override, new table: " ACPI_PRINTF_UINT, 76786dfc6f3SLv Zheng old_table_desc->signature.ascii, 76886dfc6f3SLv Zheng ACPI_FORMAT_TO_UINT(old_table_desc->address), 7697f9fc99cSLv Zheng override_type, ACPI_FORMAT_TO_UINT(new_table_desc.address))); 770f7b004a1SBob Moore 77186dfc6f3SLv Zheng /* We can now uninstall the original table */ 772f7b004a1SBob Moore 77386dfc6f3SLv Zheng acpi_tb_uninstall_table(old_table_desc); 774f7b004a1SBob Moore 77586dfc6f3SLv Zheng /* 77686dfc6f3SLv Zheng * Replace the original table descriptor and keep its state as 77786dfc6f3SLv Zheng * "VALIDATED". 77886dfc6f3SLv Zheng */ 77986dfc6f3SLv Zheng acpi_tb_install_table(old_table_desc, new_table_desc.address, 78086dfc6f3SLv Zheng new_table_desc.flags, new_table_desc.pointer); 78186dfc6f3SLv Zheng acpi_tb_validate_table(old_table_desc); 782f7b004a1SBob Moore 78386dfc6f3SLv Zheng /* Release the temporal table descriptor */ 784f7b004a1SBob Moore 78586dfc6f3SLv Zheng acpi_tb_release_temporal_table(&new_table_desc); 786f7b004a1SBob Moore } 787f7b004a1SBob Moore 788f7b004a1SBob Moore /******************************************************************************* 789f7b004a1SBob Moore * 79095b482a8SLen Brown * FUNCTION: acpi_tb_resize_root_table_list 79195b482a8SLen Brown * 79295b482a8SLen Brown * PARAMETERS: None 79395b482a8SLen Brown * 79495b482a8SLen Brown * RETURN: Status 79595b482a8SLen Brown * 79695b482a8SLen Brown * DESCRIPTION: Expand the size of global table array 79795b482a8SLen Brown * 79895b482a8SLen Brown ******************************************************************************/ 79995b482a8SLen Brown 80095b482a8SLen Brown acpi_status acpi_tb_resize_root_table_list(void) 80195b482a8SLen Brown { 80295b482a8SLen Brown struct acpi_table_desc *tables; 8032bc198c1SLv Zheng u32 table_count; 80495b482a8SLen Brown 80595b482a8SLen Brown ACPI_FUNCTION_TRACE(tb_resize_root_table_list); 80695b482a8SLen Brown 80795b482a8SLen Brown /* allow_resize flag is a parameter to acpi_initialize_tables */ 80895b482a8SLen Brown 80995b482a8SLen Brown if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) { 81095b482a8SLen Brown ACPI_ERROR((AE_INFO, 81195b482a8SLen Brown "Resize of Root Table Array is not allowed")); 81295b482a8SLen Brown return_ACPI_STATUS(AE_SUPPORT); 81395b482a8SLen Brown } 81495b482a8SLen Brown 81595b482a8SLen Brown /* Increase the Table Array size */ 81695b482a8SLen Brown 8172bc198c1SLv Zheng if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { 8182bc198c1SLv Zheng table_count = acpi_gbl_root_table_list.max_table_count; 8192bc198c1SLv Zheng } else { 8202bc198c1SLv Zheng table_count = acpi_gbl_root_table_list.current_table_count; 8212bc198c1SLv Zheng } 8222bc198c1SLv Zheng 8232bc198c1SLv Zheng tables = ACPI_ALLOCATE_ZEROED(((acpi_size) table_count + 824ec41f193SBob Moore ACPI_ROOT_TABLE_SIZE_INCREMENT) * 825ec41f193SBob Moore sizeof(struct acpi_table_desc)); 82695b482a8SLen Brown if (!tables) { 82795b482a8SLen Brown ACPI_ERROR((AE_INFO, 82895b482a8SLen Brown "Could not allocate new root table array")); 82995b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 83095b482a8SLen Brown } 83195b482a8SLen Brown 83295b482a8SLen Brown /* Copy and free the previous table array */ 83395b482a8SLen Brown 83495b482a8SLen Brown if (acpi_gbl_root_table_list.tables) { 83595b482a8SLen Brown ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, 8362bc198c1SLv Zheng (acpi_size) table_count * 8372bc198c1SLv Zheng sizeof(struct acpi_table_desc)); 83895b482a8SLen Brown 83995b482a8SLen Brown if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { 84095b482a8SLen Brown ACPI_FREE(acpi_gbl_root_table_list.tables); 84195b482a8SLen Brown } 84295b482a8SLen Brown } 84395b482a8SLen Brown 84495b482a8SLen Brown acpi_gbl_root_table_list.tables = tables; 8452bc198c1SLv Zheng acpi_gbl_root_table_list.max_table_count = 8462bc198c1SLv Zheng table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT; 8472bc198c1SLv Zheng acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED; 84895b482a8SLen Brown 84995b482a8SLen Brown return_ACPI_STATUS(AE_OK); 85095b482a8SLen Brown } 85195b482a8SLen Brown 85295b482a8SLen Brown /******************************************************************************* 85395b482a8SLen Brown * 85486dfc6f3SLv Zheng * FUNCTION: acpi_tb_acquire_root_table_entry 85586dfc6f3SLv Zheng * 85686dfc6f3SLv Zheng * PARAMETERS: table_index - Where table index is returned 85786dfc6f3SLv Zheng * 85886dfc6f3SLv Zheng * RETURN: Status and table index. 85986dfc6f3SLv Zheng * 86086dfc6f3SLv Zheng * DESCRIPTION: Allocate a new ACPI table entry to the global table list 86186dfc6f3SLv Zheng * 86286dfc6f3SLv Zheng ******************************************************************************/ 86386dfc6f3SLv Zheng 86486dfc6f3SLv Zheng static acpi_status acpi_tb_acquire_root_table_entry(u32 *table_index) 86586dfc6f3SLv Zheng { 86686dfc6f3SLv Zheng acpi_status status; 86786dfc6f3SLv Zheng 86886dfc6f3SLv Zheng /* Ensure that there is room for the table in the Root Table List */ 86986dfc6f3SLv Zheng 87086dfc6f3SLv Zheng if (acpi_gbl_root_table_list.current_table_count >= 87186dfc6f3SLv Zheng acpi_gbl_root_table_list.max_table_count) { 87286dfc6f3SLv Zheng status = acpi_tb_resize_root_table_list(); 87386dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 87486dfc6f3SLv Zheng return (status); 87586dfc6f3SLv Zheng } 87686dfc6f3SLv Zheng } 87786dfc6f3SLv Zheng 87886dfc6f3SLv Zheng *table_index = acpi_gbl_root_table_list.current_table_count; 87986dfc6f3SLv Zheng acpi_gbl_root_table_list.current_table_count++; 88086dfc6f3SLv Zheng return (AE_OK); 88186dfc6f3SLv Zheng } 88286dfc6f3SLv Zheng 88386dfc6f3SLv Zheng /******************************************************************************* 88486dfc6f3SLv Zheng * 88595b482a8SLen Brown * FUNCTION: acpi_tb_store_table 88695b482a8SLen Brown * 887ba494beeSBob Moore * PARAMETERS: address - Table address 888ba494beeSBob Moore * table - Table header 889ba494beeSBob Moore * length - Table length 890ba494beeSBob Moore * flags - flags 89195b482a8SLen Brown * 89295b482a8SLen Brown * RETURN: Status and table index. 89395b482a8SLen Brown * 89495b482a8SLen Brown * DESCRIPTION: Add an ACPI table to the global table list 89595b482a8SLen Brown * 89695b482a8SLen Brown ******************************************************************************/ 89795b482a8SLen Brown 89895b482a8SLen Brown acpi_status 89995b482a8SLen Brown acpi_tb_store_table(acpi_physical_address address, 90095b482a8SLen Brown struct acpi_table_header * table, 90195b482a8SLen Brown u32 length, u8 flags, u32 *table_index) 90295b482a8SLen Brown { 903b9ee2043SBob Moore acpi_status status; 90486dfc6f3SLv Zheng struct acpi_table_desc *table_desc; 90595b482a8SLen Brown 90686dfc6f3SLv Zheng status = acpi_tb_acquire_root_table_entry(table_index); 90795b482a8SLen Brown if (ACPI_FAILURE(status)) { 90895b482a8SLen Brown return (status); 90995b482a8SLen Brown } 910b9ee2043SBob Moore 91195b482a8SLen Brown /* Initialize added table */ 91295b482a8SLen Brown 91386dfc6f3SLv Zheng table_desc = &acpi_gbl_root_table_list.tables[*table_index]; 91486dfc6f3SLv Zheng acpi_tb_install_table(table_desc, address, flags, table); 91586dfc6f3SLv Zheng table_desc->pointer = table; 91695b482a8SLen Brown 917b9ee2043SBob Moore return (AE_OK); 91895b482a8SLen Brown } 91995b482a8SLen Brown 92095b482a8SLen Brown /******************************************************************************* 92195b482a8SLen Brown * 9227f9fc99cSLv Zheng * FUNCTION: acpi_tb_uninstall_table 92395b482a8SLen Brown * 9247f9fc99cSLv Zheng * PARAMETERS: table_desc - Table descriptor 92595b482a8SLen Brown * 92695b482a8SLen Brown * RETURN: None 92795b482a8SLen Brown * 92895b482a8SLen Brown * DESCRIPTION: Delete one internal ACPI table 92995b482a8SLen Brown * 93095b482a8SLen Brown ******************************************************************************/ 93195b482a8SLen Brown 9327f9fc99cSLv Zheng void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc) 93395b482a8SLen Brown { 9345582982dSLv Zheng 9357f9fc99cSLv Zheng ACPI_FUNCTION_TRACE(tb_uninstall_table); 9365582982dSLv Zheng 9377f9fc99cSLv Zheng /* Table must be installed */ 9387f9fc99cSLv Zheng 9397f9fc99cSLv Zheng if (!table_desc->address) { 9407f9fc99cSLv Zheng return_VOID; 94195b482a8SLen Brown } 9425582982dSLv Zheng 9437f9fc99cSLv Zheng acpi_tb_invalidate_table(table_desc); 9441d1ea1b7SChao Guan 9457f9fc99cSLv Zheng if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == 9468a216d7fSLv Zheng ACPI_TABLE_ORIGIN_INTERN_VIRTUAL) { 9477f9fc99cSLv Zheng ACPI_FREE(ACPI_CAST_PTR(void, table_desc->address)); 9487f9fc99cSLv Zheng } 9491d1ea1b7SChao Guan 950dc156adfSLv Zheng table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL); 951f7b004a1SBob Moore 9527f9fc99cSLv Zheng return_VOID; 95395b482a8SLen Brown } 95495b482a8SLen Brown 95595b482a8SLen Brown /******************************************************************************* 95695b482a8SLen Brown * 95795b482a8SLen Brown * FUNCTION: acpi_tb_terminate 95895b482a8SLen Brown * 95995b482a8SLen Brown * PARAMETERS: None 96095b482a8SLen Brown * 96195b482a8SLen Brown * RETURN: None 96295b482a8SLen Brown * 96395b482a8SLen Brown * DESCRIPTION: Delete all internal ACPI tables 96495b482a8SLen Brown * 96595b482a8SLen Brown ******************************************************************************/ 96695b482a8SLen Brown 96795b482a8SLen Brown void acpi_tb_terminate(void) 96895b482a8SLen Brown { 96995b482a8SLen Brown u32 i; 97095b482a8SLen Brown 97195b482a8SLen Brown ACPI_FUNCTION_TRACE(tb_terminate); 97295b482a8SLen Brown 97395b482a8SLen Brown (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 97495b482a8SLen Brown 97595b482a8SLen Brown /* Delete the individual tables */ 97695b482a8SLen Brown 977b9ee2043SBob Moore for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { 9787f9fc99cSLv Zheng acpi_tb_uninstall_table(&acpi_gbl_root_table_list.tables[i]); 97995b482a8SLen Brown } 98095b482a8SLen Brown 98195b482a8SLen Brown /* 98295b482a8SLen Brown * Delete the root table array if allocated locally. Array cannot be 98395b482a8SLen Brown * mapped, so we don't need to check for that flag. 98495b482a8SLen Brown */ 98595b482a8SLen Brown if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { 98695b482a8SLen Brown ACPI_FREE(acpi_gbl_root_table_list.tables); 98795b482a8SLen Brown } 98895b482a8SLen Brown 98995b482a8SLen Brown acpi_gbl_root_table_list.tables = NULL; 99095b482a8SLen Brown acpi_gbl_root_table_list.flags = 0; 991b9ee2043SBob Moore acpi_gbl_root_table_list.current_table_count = 0; 99295b482a8SLen Brown 99395b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n")); 99495b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 99568aafc35SBob Moore 99668aafc35SBob Moore return_VOID; 99795b482a8SLen Brown } 99895b482a8SLen Brown 99995b482a8SLen Brown /******************************************************************************* 100095b482a8SLen Brown * 100195b482a8SLen Brown * FUNCTION: acpi_tb_delete_namespace_by_owner 100295b482a8SLen Brown * 100395b482a8SLen Brown * PARAMETERS: table_index - Table index 100495b482a8SLen Brown * 10058a335a23SBob Moore * RETURN: Status 100695b482a8SLen Brown * 100795b482a8SLen Brown * DESCRIPTION: Delete all namespace objects created when this table was loaded. 100895b482a8SLen Brown * 100995b482a8SLen Brown ******************************************************************************/ 101095b482a8SLen Brown 10118a335a23SBob Moore acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index) 101295b482a8SLen Brown { 101395b482a8SLen Brown acpi_owner_id owner_id; 10148a335a23SBob Moore acpi_status status; 101595b482a8SLen Brown 10168a335a23SBob Moore ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner); 10178a335a23SBob Moore 10188a335a23SBob Moore status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 10198a335a23SBob Moore if (ACPI_FAILURE(status)) { 10208a335a23SBob Moore return_ACPI_STATUS(status); 102195b482a8SLen Brown } 102295b482a8SLen Brown 1023b9ee2043SBob Moore if (table_index >= acpi_gbl_root_table_list.current_table_count) { 10248a335a23SBob Moore 10258a335a23SBob Moore /* The table index does not exist */ 10268a335a23SBob Moore 102795b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 10288a335a23SBob Moore return_ACPI_STATUS(AE_NOT_EXIST); 10298a335a23SBob Moore } 10308a335a23SBob Moore 10318a335a23SBob Moore /* Get the owner ID for this table, used to delete namespace nodes */ 10328a335a23SBob Moore 10338a335a23SBob Moore owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id; 10348a335a23SBob Moore (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 10358a335a23SBob Moore 10368a335a23SBob Moore /* 10378a335a23SBob Moore * Need to acquire the namespace writer lock to prevent interference 10388a335a23SBob Moore * with any concurrent namespace walks. The interpreter must be 10398a335a23SBob Moore * released during the deletion since the acquisition of the deletion 10408a335a23SBob Moore * lock may block, and also since the execution of a namespace walk 10418a335a23SBob Moore * must be allowed to use the interpreter. 10428a335a23SBob Moore */ 1043e4c1ebfcSBob Moore (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); 10448a335a23SBob Moore status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock); 10458a335a23SBob Moore 104695b482a8SLen Brown acpi_ns_delete_namespace_by_owner(owner_id); 10478a335a23SBob Moore if (ACPI_FAILURE(status)) { 10488a335a23SBob Moore return_ACPI_STATUS(status); 10498a335a23SBob Moore } 10508a335a23SBob Moore 10518a335a23SBob Moore acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock); 10528a335a23SBob Moore 10538a335a23SBob Moore status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); 10548a335a23SBob Moore return_ACPI_STATUS(status); 105595b482a8SLen Brown } 105695b482a8SLen Brown 105795b482a8SLen Brown /******************************************************************************* 105895b482a8SLen Brown * 105995b482a8SLen Brown * FUNCTION: acpi_tb_allocate_owner_id 106095b482a8SLen Brown * 106195b482a8SLen Brown * PARAMETERS: table_index - Table index 106295b482a8SLen Brown * 106395b482a8SLen Brown * RETURN: Status 106495b482a8SLen Brown * 106595b482a8SLen Brown * DESCRIPTION: Allocates owner_id in table_desc 106695b482a8SLen Brown * 106795b482a8SLen Brown ******************************************************************************/ 106895b482a8SLen Brown 106995b482a8SLen Brown acpi_status acpi_tb_allocate_owner_id(u32 table_index) 107095b482a8SLen Brown { 107195b482a8SLen Brown acpi_status status = AE_BAD_PARAMETER; 107295b482a8SLen Brown 107395b482a8SLen Brown ACPI_FUNCTION_TRACE(tb_allocate_owner_id); 107495b482a8SLen Brown 107595b482a8SLen Brown (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 1076b9ee2043SBob Moore if (table_index < acpi_gbl_root_table_list.current_table_count) { 107795b482a8SLen Brown status = acpi_ut_allocate_owner_id 107895b482a8SLen Brown (&(acpi_gbl_root_table_list.tables[table_index].owner_id)); 107995b482a8SLen Brown } 108095b482a8SLen Brown 108195b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 108295b482a8SLen Brown return_ACPI_STATUS(status); 108395b482a8SLen Brown } 108495b482a8SLen Brown 108595b482a8SLen Brown /******************************************************************************* 108695b482a8SLen Brown * 108795b482a8SLen Brown * FUNCTION: acpi_tb_release_owner_id 108895b482a8SLen Brown * 108995b482a8SLen Brown * PARAMETERS: table_index - Table index 109095b482a8SLen Brown * 109195b482a8SLen Brown * RETURN: Status 109295b482a8SLen Brown * 109395b482a8SLen Brown * DESCRIPTION: Releases owner_id in table_desc 109495b482a8SLen Brown * 109595b482a8SLen Brown ******************************************************************************/ 109695b482a8SLen Brown 109795b482a8SLen Brown acpi_status acpi_tb_release_owner_id(u32 table_index) 109895b482a8SLen Brown { 109995b482a8SLen Brown acpi_status status = AE_BAD_PARAMETER; 110095b482a8SLen Brown 110195b482a8SLen Brown ACPI_FUNCTION_TRACE(tb_release_owner_id); 110295b482a8SLen Brown 110395b482a8SLen Brown (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 1104b9ee2043SBob Moore if (table_index < acpi_gbl_root_table_list.current_table_count) { 110595b482a8SLen Brown acpi_ut_release_owner_id(& 110695b482a8SLen Brown (acpi_gbl_root_table_list. 110795b482a8SLen Brown tables[table_index].owner_id)); 110895b482a8SLen Brown status = AE_OK; 110995b482a8SLen Brown } 111095b482a8SLen Brown 111195b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 111295b482a8SLen Brown return_ACPI_STATUS(status); 111395b482a8SLen Brown } 111495b482a8SLen Brown 111595b482a8SLen Brown /******************************************************************************* 111695b482a8SLen Brown * 111795b482a8SLen Brown * FUNCTION: acpi_tb_get_owner_id 111895b482a8SLen Brown * 111995b482a8SLen Brown * PARAMETERS: table_index - Table index 112095b482a8SLen Brown * owner_id - Where the table owner_id is returned 112195b482a8SLen Brown * 112295b482a8SLen Brown * RETURN: Status 112395b482a8SLen Brown * 112495b482a8SLen Brown * DESCRIPTION: returns owner_id for the ACPI table 112595b482a8SLen Brown * 112695b482a8SLen Brown ******************************************************************************/ 112795b482a8SLen Brown 112895b482a8SLen Brown acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id * owner_id) 112995b482a8SLen Brown { 113095b482a8SLen Brown acpi_status status = AE_BAD_PARAMETER; 113195b482a8SLen Brown 113295b482a8SLen Brown ACPI_FUNCTION_TRACE(tb_get_owner_id); 113395b482a8SLen Brown 113495b482a8SLen Brown (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 1135b9ee2043SBob Moore if (table_index < acpi_gbl_root_table_list.current_table_count) { 113695b482a8SLen Brown *owner_id = 113795b482a8SLen Brown acpi_gbl_root_table_list.tables[table_index].owner_id; 113895b482a8SLen Brown status = AE_OK; 113995b482a8SLen Brown } 114095b482a8SLen Brown 114195b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 114295b482a8SLen Brown return_ACPI_STATUS(status); 114395b482a8SLen Brown } 114495b482a8SLen Brown 114595b482a8SLen Brown /******************************************************************************* 114695b482a8SLen Brown * 114795b482a8SLen Brown * FUNCTION: acpi_tb_is_table_loaded 114895b482a8SLen Brown * 114995b482a8SLen Brown * PARAMETERS: table_index - Table index 115095b482a8SLen Brown * 115195b482a8SLen Brown * RETURN: Table Loaded Flag 115295b482a8SLen Brown * 115395b482a8SLen Brown ******************************************************************************/ 115495b482a8SLen Brown 115595b482a8SLen Brown u8 acpi_tb_is_table_loaded(u32 table_index) 115695b482a8SLen Brown { 115795b482a8SLen Brown u8 is_loaded = FALSE; 115895b482a8SLen Brown 115995b482a8SLen Brown (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 1160b9ee2043SBob Moore if (table_index < acpi_gbl_root_table_list.current_table_count) { 116195b482a8SLen Brown is_loaded = (u8) 1162ec41f193SBob Moore (acpi_gbl_root_table_list.tables[table_index].flags & 1163ec41f193SBob Moore ACPI_TABLE_IS_LOADED); 116495b482a8SLen Brown } 116595b482a8SLen Brown 116695b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 116795b482a8SLen Brown return (is_loaded); 116895b482a8SLen Brown } 116995b482a8SLen Brown 117095b482a8SLen Brown /******************************************************************************* 117195b482a8SLen Brown * 117295b482a8SLen Brown * FUNCTION: acpi_tb_set_table_loaded_flag 117395b482a8SLen Brown * 117495b482a8SLen Brown * PARAMETERS: table_index - Table index 117595b482a8SLen Brown * is_loaded - TRUE if table is loaded, FALSE otherwise 117695b482a8SLen Brown * 117795b482a8SLen Brown * RETURN: None 117895b482a8SLen Brown * 117995b482a8SLen Brown * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE. 118095b482a8SLen Brown * 118195b482a8SLen Brown ******************************************************************************/ 118295b482a8SLen Brown 118395b482a8SLen Brown void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded) 118495b482a8SLen Brown { 118595b482a8SLen Brown 118695b482a8SLen Brown (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 1187b9ee2043SBob Moore if (table_index < acpi_gbl_root_table_list.current_table_count) { 118895b482a8SLen Brown if (is_loaded) { 118995b482a8SLen Brown acpi_gbl_root_table_list.tables[table_index].flags |= 119095b482a8SLen Brown ACPI_TABLE_IS_LOADED; 119195b482a8SLen Brown } else { 119295b482a8SLen Brown acpi_gbl_root_table_list.tables[table_index].flags &= 119395b482a8SLen Brown ~ACPI_TABLE_IS_LOADED; 119495b482a8SLen Brown } 119595b482a8SLen Brown } 119695b482a8SLen Brown 119795b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 119895b482a8SLen Brown } 1199