195b482a8SLen Brown /****************************************************************************** 295b482a8SLen Brown * 395b482a8SLen Brown * Module Name: tbinstal - ACPI table installation and removal 495b482a8SLen Brown * 595b482a8SLen Brown *****************************************************************************/ 695b482a8SLen Brown 795b482a8SLen Brown /* 8da6f8320SBob Moore * Copyright (C) 2000 - 2018, 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 "actables.h" 4795b482a8SLen Brown 4895b482a8SLen Brown #define _COMPONENT ACPI_TABLES 4995b482a8SLen Brown ACPI_MODULE_NAME("tbinstal") 5095b482a8SLen Brown 5186dfc6f3SLv Zheng /******************************************************************************* 5286dfc6f3SLv Zheng * 53ed6f1d44SBob Moore * FUNCTION: acpi_tb_install_table_with_override 5486dfc6f3SLv Zheng * 558ec3f459SLv Zheng * PARAMETERS: new_table_desc - New table descriptor to install 56caf4a15cSLv Zheng * override - Whether override should be performed 578ec3f459SLv Zheng * table_index - Where the table index is returned 5886dfc6f3SLv Zheng * 5986dfc6f3SLv Zheng * RETURN: None 6086dfc6f3SLv Zheng * 6186dfc6f3SLv Zheng * DESCRIPTION: Install an ACPI table into the global data structure. The 6286dfc6f3SLv Zheng * table override mechanism is called to allow the host 6386dfc6f3SLv Zheng * OS to replace any table before it is installed in the root 6486dfc6f3SLv Zheng * table array. 6586dfc6f3SLv Zheng * 6686dfc6f3SLv Zheng ******************************************************************************/ 6786dfc6f3SLv Zheng void 688ec3f459SLv Zheng acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc, 698ec3f459SLv Zheng u8 override, u32 *table_index) 7086dfc6f3SLv Zheng { 718ec3f459SLv Zheng u32 i; 728ec3f459SLv Zheng acpi_status status; 73ed6f1d44SBob Moore 748ec3f459SLv Zheng status = acpi_tb_get_next_table_descriptor(&i, NULL); 758ec3f459SLv Zheng if (ACPI_FAILURE(status)) { 7686dfc6f3SLv Zheng return; 7786dfc6f3SLv Zheng } 7886dfc6f3SLv Zheng 7986dfc6f3SLv Zheng /* 8086dfc6f3SLv Zheng * ACPI Table Override: 8186dfc6f3SLv Zheng * 8286dfc6f3SLv Zheng * Before we install the table, let the host OS override it with a new 8386dfc6f3SLv Zheng * one if desired. Any table within the RSDT/XSDT can be replaced, 8486dfc6f3SLv Zheng * including the DSDT which is pointed to by the FADT. 8586dfc6f3SLv Zheng */ 86caf4a15cSLv Zheng if (override) { 8786dfc6f3SLv Zheng acpi_tb_override_table(new_table_desc); 88caf4a15cSLv Zheng } 8986dfc6f3SLv Zheng 908ec3f459SLv Zheng acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.tables[i], 91ed6f1d44SBob Moore new_table_desc->address, 92ed6f1d44SBob Moore new_table_desc->flags, 9386dfc6f3SLv Zheng new_table_desc->pointer); 9486dfc6f3SLv Zheng 9586dfc6f3SLv Zheng acpi_tb_print_table_header(new_table_desc->address, 9686dfc6f3SLv Zheng new_table_desc->pointer); 9786dfc6f3SLv Zheng 988ec3f459SLv Zheng /* This synchronizes acpi_gbl_dsdt_index */ 998ec3f459SLv Zheng 1008ec3f459SLv Zheng *table_index = i; 1018ec3f459SLv Zheng 10286dfc6f3SLv Zheng /* Set the global integer width (based upon revision of the DSDT) */ 10386dfc6f3SLv Zheng 1048ec3f459SLv Zheng if (i == acpi_gbl_dsdt_index) { 10586dfc6f3SLv Zheng acpi_ut_set_integer_width(new_table_desc->pointer->revision); 10686dfc6f3SLv Zheng } 10786dfc6f3SLv Zheng } 10886dfc6f3SLv Zheng 10986dfc6f3SLv Zheng /******************************************************************************* 11086dfc6f3SLv Zheng * 111ed6f1d44SBob Moore * FUNCTION: acpi_tb_install_standard_table 11286dfc6f3SLv Zheng * 1138a216d7fSLv Zheng * PARAMETERS: address - Address of the table (might be a virtual 11486dfc6f3SLv Zheng * address depending on the table_flags) 11586dfc6f3SLv Zheng * flags - Flags for the table 11686dfc6f3SLv Zheng * reload - Whether reload should be performed 117caf4a15cSLv Zheng * override - Whether override should be performed 11886dfc6f3SLv Zheng * table_index - Where the table index is returned 11986dfc6f3SLv Zheng * 12086dfc6f3SLv Zheng * RETURN: Status 12186dfc6f3SLv Zheng * 122752db101SLv Zheng * DESCRIPTION: This function is called to verify and install an ACPI table. 12386dfc6f3SLv Zheng * When this function is called by "Load" or "LoadTable" opcodes, 12486dfc6f3SLv Zheng * or by acpi_load_table() API, the "Reload" parameter is set. 12586dfc6f3SLv Zheng * After sucessfully returning from this function, table is 12686dfc6f3SLv Zheng * "INSTALLED" but not "VALIDATED". 12786dfc6f3SLv Zheng * 12886dfc6f3SLv Zheng ******************************************************************************/ 12986dfc6f3SLv Zheng 13086dfc6f3SLv Zheng acpi_status 131ed6f1d44SBob Moore acpi_tb_install_standard_table(acpi_physical_address address, 132caf4a15cSLv Zheng u8 flags, 133caf4a15cSLv Zheng u8 reload, u8 override, u32 *table_index) 13495b482a8SLen Brown { 13595b482a8SLen Brown u32 i; 13695b482a8SLen Brown acpi_status status = AE_OK; 13786dfc6f3SLv Zheng struct acpi_table_desc new_table_desc; 13895b482a8SLen Brown 139ed6f1d44SBob Moore ACPI_FUNCTION_TRACE(tb_install_standard_table); 14095b482a8SLen Brown 141ed6f1d44SBob Moore /* Acquire a temporary table descriptor for validation */ 14286dfc6f3SLv Zheng 143ed6f1d44SBob Moore status = acpi_tb_acquire_temp_table(&new_table_desc, address, flags); 14486dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 145cc2080b0SLv Zheng ACPI_ERROR((AE_INFO, 146cc2080b0SLv Zheng "Could not acquire table length at %8.8X%8.8X", 147cc2080b0SLv Zheng ACPI_FORMAT_UINT64(address))); 14895b482a8SLen Brown return_ACPI_STATUS(status); 14995b482a8SLen Brown } 15086dfc6f3SLv Zheng 151a94e88cdSLv Zheng /* 152a94e88cdSLv Zheng * Optionally do not load any SSDTs from the RSDT/XSDT. This can 153a94e88cdSLv Zheng * be useful for debugging ACPI problems on some machines. 154a94e88cdSLv Zheng */ 155ed6f1d44SBob Moore if (!reload && 156ed6f1d44SBob Moore acpi_gbl_disable_ssdt_table_install && 157a94e88cdSLv Zheng ACPI_COMPARE_NAME(&new_table_desc.signature, ACPI_SIG_SSDT)) { 15805fb04b5SBob Moore ACPI_INFO(("Ignoring installation of %4.4s at %8.8X%8.8X", 1596d3fd3ccSLv Zheng new_table_desc.signature.ascii, 160cc2080b0SLv Zheng ACPI_FORMAT_UINT64(address))); 161a94e88cdSLv Zheng goto release_and_exit; 162a94e88cdSLv Zheng } 163a94e88cdSLv Zheng 1647a37052aSLv Zheng /* Acquire the table lock */ 1657a37052aSLv Zheng 1667a37052aSLv Zheng (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 1677a37052aSLv Zheng 168f9d472eeSLv Zheng /* Validate and verify a table before installation */ 16995b482a8SLen Brown 170f9d472eeSLv Zheng status = acpi_tb_verify_temp_table(&new_table_desc, NULL, &i); 171f9d472eeSLv Zheng if (ACPI_FAILURE(status)) { 172f9d472eeSLv Zheng if (status == AE_CTRL_TERMINATE) { 173d3ccaff8SBob Moore /* 17486dfc6f3SLv Zheng * Table was unloaded, allow it to be reloaded. 17586dfc6f3SLv Zheng * As we are going to return AE_OK to the caller, we should 17686dfc6f3SLv Zheng * take the responsibility of freeing the input descriptor. 17786dfc6f3SLv Zheng * Refill the input descriptor to ensure 178ed6f1d44SBob Moore * acpi_tb_install_table_with_override() can be called again to 17986dfc6f3SLv Zheng * indicate the re-installation. 180d3ccaff8SBob Moore */ 18186dfc6f3SLv Zheng acpi_tb_uninstall_table(&new_table_desc); 1827a37052aSLv Zheng (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 18386dfc6f3SLv Zheng *table_index = i; 18486dfc6f3SLv Zheng return_ACPI_STATUS(AE_OK); 18586dfc6f3SLv Zheng } 186f9d472eeSLv Zheng goto unlock_and_exit; 1877f9fc99cSLv Zheng } 188d3ccaff8SBob Moore 18995b482a8SLen Brown /* Add the table to the global root table list */ 19095b482a8SLen Brown 1918ec3f459SLv Zheng acpi_tb_install_table_with_override(&new_table_desc, override, 1928ec3f459SLv Zheng table_index); 19395b482a8SLen Brown 1949b019b0fSLv Zheng /* Invoke table handler */ 195bdbe5df0SLv Zheng 1967a37052aSLv Zheng (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 1979b019b0fSLv Zheng acpi_tb_notify_table(ACPI_TABLE_EVENT_INSTALL, new_table_desc.pointer); 1987a37052aSLv Zheng (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 1997a37052aSLv Zheng 2007a37052aSLv Zheng unlock_and_exit: 2017a37052aSLv Zheng 2027a37052aSLv Zheng /* Release the table lock */ 2037a37052aSLv Zheng 2047a37052aSLv Zheng (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 205bdbe5df0SLv Zheng 20686dfc6f3SLv Zheng release_and_exit: 20795b482a8SLen Brown 208ed6f1d44SBob Moore /* Release the temporary table descriptor */ 20986dfc6f3SLv Zheng 210ed6f1d44SBob Moore acpi_tb_release_temp_table(&new_table_desc); 21195b482a8SLen Brown return_ACPI_STATUS(status); 21295b482a8SLen Brown } 21395b482a8SLen Brown 21495b482a8SLen Brown /******************************************************************************* 21595b482a8SLen Brown * 2167f9fc99cSLv Zheng * FUNCTION: acpi_tb_override_table 217f7b004a1SBob Moore * 21886dfc6f3SLv Zheng * PARAMETERS: old_table_desc - Validated table descriptor to be 21986dfc6f3SLv Zheng * overridden 220f7b004a1SBob Moore * 22186dfc6f3SLv Zheng * RETURN: None 222f7b004a1SBob Moore * 223f7b004a1SBob Moore * DESCRIPTION: Attempt table override by calling the OSL override functions. 224f7b004a1SBob Moore * Note: If the table is overridden, then the entire new table 2257f9fc99cSLv Zheng * is acquired and returned by this function. 22686dfc6f3SLv Zheng * Before/after invocation, the table descriptor is in a state 22786dfc6f3SLv Zheng * that is "VALIDATED". 228f7b004a1SBob Moore * 229f7b004a1SBob Moore ******************************************************************************/ 230f7b004a1SBob Moore 23186dfc6f3SLv Zheng void acpi_tb_override_table(struct acpi_table_desc *old_table_desc) 232f7b004a1SBob Moore { 233f7b004a1SBob Moore acpi_status status; 2347f9fc99cSLv Zheng struct acpi_table_desc new_table_desc; 23586dfc6f3SLv Zheng struct acpi_table_header *table; 23686dfc6f3SLv Zheng acpi_physical_address address; 23786dfc6f3SLv Zheng u32 length; 238*0fe0bebfSErik Schmauss ACPI_ERROR_ONLY(char *override_type); 239f7b004a1SBob Moore 240f7b004a1SBob Moore /* (1) Attempt logical override (returns a logical address) */ 241f7b004a1SBob Moore 24286dfc6f3SLv Zheng status = acpi_os_table_override(old_table_desc->pointer, &table); 24386dfc6f3SLv Zheng if (ACPI_SUCCESS(status) && table) { 244ed6f1d44SBob Moore acpi_tb_acquire_temp_table(&new_table_desc, 24586dfc6f3SLv Zheng ACPI_PTR_TO_PHYSADDR(table), 246ed6f1d44SBob Moore ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL); 247*0fe0bebfSErik Schmauss ACPI_ERROR_ONLY(override_type = "Logical"); 248f7b004a1SBob Moore goto finish_override; 249f7b004a1SBob Moore } 250f7b004a1SBob Moore 251f7b004a1SBob Moore /* (2) Attempt physical override (returns a physical address) */ 252f7b004a1SBob Moore 25386dfc6f3SLv Zheng status = acpi_os_physical_table_override(old_table_desc->pointer, 25486dfc6f3SLv Zheng &address, &length); 25586dfc6f3SLv Zheng if (ACPI_SUCCESS(status) && address && length) { 256ed6f1d44SBob Moore acpi_tb_acquire_temp_table(&new_table_desc, address, 257ed6f1d44SBob Moore ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); 258*0fe0bebfSErik Schmauss ACPI_ERROR_ONLY(override_type = "Physical"); 259f7b004a1SBob Moore goto finish_override; 260f7b004a1SBob Moore } 261f7b004a1SBob Moore 26286dfc6f3SLv Zheng return; /* There was no override */ 263f7b004a1SBob Moore 264f7b004a1SBob Moore finish_override: 265f7b004a1SBob Moore 266f9d472eeSLv Zheng /* 267f9d472eeSLv Zheng * Validate and verify a table before overriding, no nested table 268f9d472eeSLv Zheng * duplication check as it's too complicated and unnecessary. 269f9d472eeSLv Zheng */ 270f9d472eeSLv Zheng status = acpi_tb_verify_temp_table(&new_table_desc, NULL, NULL); 2717f9fc99cSLv Zheng if (ACPI_FAILURE(status)) { 27286dfc6f3SLv Zheng return; 2737f9fc99cSLv Zheng } 2747f9fc99cSLv Zheng 27505fb04b5SBob Moore ACPI_INFO(("%4.4s 0x%8.8X%8.8X" 2761d0a0b2fSLv Zheng " %s table override, new table: 0x%8.8X%8.8X", 27786dfc6f3SLv Zheng old_table_desc->signature.ascii, 2781d0a0b2fSLv Zheng ACPI_FORMAT_UINT64(old_table_desc->address), 2791d0a0b2fSLv Zheng override_type, ACPI_FORMAT_UINT64(new_table_desc.address))); 280f7b004a1SBob Moore 28186dfc6f3SLv Zheng /* We can now uninstall the original table */ 282f7b004a1SBob Moore 28386dfc6f3SLv Zheng acpi_tb_uninstall_table(old_table_desc); 284f7b004a1SBob Moore 28586dfc6f3SLv Zheng /* 28686dfc6f3SLv Zheng * Replace the original table descriptor and keep its state as 28786dfc6f3SLv Zheng * "VALIDATED". 28886dfc6f3SLv Zheng */ 289ed6f1d44SBob Moore acpi_tb_init_table_descriptor(old_table_desc, new_table_desc.address, 290ed6f1d44SBob Moore new_table_desc.flags, 291ed6f1d44SBob Moore new_table_desc.pointer); 29247d68c7fSLv Zheng acpi_tb_validate_temp_table(old_table_desc); 293f7b004a1SBob Moore 294ed6f1d44SBob Moore /* Release the temporary table descriptor */ 295f7b004a1SBob Moore 296ed6f1d44SBob Moore acpi_tb_release_temp_table(&new_table_desc); 297f7b004a1SBob Moore } 298f7b004a1SBob Moore 299f7b004a1SBob Moore /******************************************************************************* 300f7b004a1SBob Moore * 3017f9fc99cSLv Zheng * FUNCTION: acpi_tb_uninstall_table 30295b482a8SLen Brown * 3037f9fc99cSLv Zheng * PARAMETERS: table_desc - Table descriptor 30495b482a8SLen Brown * 30595b482a8SLen Brown * RETURN: None 30695b482a8SLen Brown * 30795b482a8SLen Brown * DESCRIPTION: Delete one internal ACPI table 30895b482a8SLen Brown * 30995b482a8SLen Brown ******************************************************************************/ 31095b482a8SLen Brown 3117f9fc99cSLv Zheng void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc) 31295b482a8SLen Brown { 3135582982dSLv Zheng 3147f9fc99cSLv Zheng ACPI_FUNCTION_TRACE(tb_uninstall_table); 3155582982dSLv Zheng 3167f9fc99cSLv Zheng /* Table must be installed */ 3177f9fc99cSLv Zheng 3187f9fc99cSLv Zheng if (!table_desc->address) { 3197f9fc99cSLv Zheng return_VOID; 32095b482a8SLen Brown } 3215582982dSLv Zheng 3227f9fc99cSLv Zheng acpi_tb_invalidate_table(table_desc); 3231d1ea1b7SChao Guan 3247f9fc99cSLv Zheng if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == 325ed6f1d44SBob Moore ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) { 3266d3fd3ccSLv Zheng ACPI_FREE(ACPI_PHYSADDR_TO_PTR(table_desc->address)); 3277f9fc99cSLv Zheng } 3281d1ea1b7SChao Guan 329dc156adfSLv Zheng table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL); 3307f9fc99cSLv Zheng return_VOID; 33195b482a8SLen Brown } 332