195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 295b482a8SLen Brown /****************************************************************************** 395b482a8SLen Brown * 495b482a8SLen Brown * Module Name: tbinstal - ACPI table installation and removal 595b482a8SLen Brown * 64441e55dSBob Moore * Copyright (C) 2000 - 2021, Intel Corp. 795b482a8SLen Brown * 895857638SErik Schmauss *****************************************************************************/ 995b482a8SLen Brown 1095b482a8SLen Brown #include <acpi/acpi.h> 11e2f7a777SLen Brown #include "accommon.h" 12e2f7a777SLen Brown #include "actables.h" 1395b482a8SLen Brown 1495b482a8SLen Brown #define _COMPONENT ACPI_TABLES 1595b482a8SLen Brown ACPI_MODULE_NAME("tbinstal") 1695b482a8SLen Brown 1786dfc6f3SLv Zheng /******************************************************************************* 1886dfc6f3SLv Zheng * 19ed6f1d44SBob Moore * FUNCTION: acpi_tb_install_table_with_override 2086dfc6f3SLv Zheng * 218ec3f459SLv Zheng * PARAMETERS: new_table_desc - New table descriptor to install 22caf4a15cSLv Zheng * override - Whether override should be performed 238ec3f459SLv Zheng * table_index - Where the table index is returned 2486dfc6f3SLv Zheng * 2586dfc6f3SLv Zheng * RETURN: None 2686dfc6f3SLv Zheng * 2786dfc6f3SLv Zheng * DESCRIPTION: Install an ACPI table into the global data structure. The 2886dfc6f3SLv Zheng * table override mechanism is called to allow the host 2986dfc6f3SLv Zheng * OS to replace any table before it is installed in the root 3086dfc6f3SLv Zheng * table array. 3186dfc6f3SLv Zheng * 3286dfc6f3SLv Zheng ******************************************************************************/ 3386dfc6f3SLv Zheng void 348ec3f459SLv Zheng acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc, 358ec3f459SLv Zheng u8 override, u32 *table_index) 3686dfc6f3SLv Zheng { 378ec3f459SLv Zheng u32 i; 388ec3f459SLv Zheng acpi_status status; 39ed6f1d44SBob Moore 408ec3f459SLv Zheng status = acpi_tb_get_next_table_descriptor(&i, NULL); 418ec3f459SLv Zheng if (ACPI_FAILURE(status)) { 4286dfc6f3SLv Zheng return; 4386dfc6f3SLv Zheng } 4486dfc6f3SLv Zheng 4586dfc6f3SLv Zheng /* 4686dfc6f3SLv Zheng * ACPI Table Override: 4786dfc6f3SLv Zheng * 4886dfc6f3SLv Zheng * Before we install the table, let the host OS override it with a new 4986dfc6f3SLv Zheng * one if desired. Any table within the RSDT/XSDT can be replaced, 5086dfc6f3SLv Zheng * including the DSDT which is pointed to by the FADT. 5186dfc6f3SLv Zheng */ 52caf4a15cSLv Zheng if (override) { 5386dfc6f3SLv Zheng acpi_tb_override_table(new_table_desc); 54caf4a15cSLv Zheng } 5586dfc6f3SLv Zheng 568ec3f459SLv Zheng acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.tables[i], 57ed6f1d44SBob Moore new_table_desc->address, 58ed6f1d44SBob Moore new_table_desc->flags, 5986dfc6f3SLv Zheng new_table_desc->pointer); 6086dfc6f3SLv Zheng 6186dfc6f3SLv Zheng acpi_tb_print_table_header(new_table_desc->address, 6286dfc6f3SLv Zheng new_table_desc->pointer); 6386dfc6f3SLv Zheng 648ec3f459SLv Zheng /* This synchronizes acpi_gbl_dsdt_index */ 658ec3f459SLv Zheng 668ec3f459SLv Zheng *table_index = i; 678ec3f459SLv Zheng 6886dfc6f3SLv Zheng /* Set the global integer width (based upon revision of the DSDT) */ 6986dfc6f3SLv Zheng 708ec3f459SLv Zheng if (i == acpi_gbl_dsdt_index) { 7186dfc6f3SLv Zheng acpi_ut_set_integer_width(new_table_desc->pointer->revision); 7286dfc6f3SLv Zheng } 7386dfc6f3SLv Zheng } 7486dfc6f3SLv Zheng 7586dfc6f3SLv Zheng /******************************************************************************* 7686dfc6f3SLv Zheng * 77ed6f1d44SBob Moore * FUNCTION: acpi_tb_install_standard_table 7886dfc6f3SLv Zheng * 798a216d7fSLv Zheng * PARAMETERS: address - Address of the table (might be a virtual 8086dfc6f3SLv Zheng * address depending on the table_flags) 8186dfc6f3SLv Zheng * flags - Flags for the table 82*5d6e5966SJessica Clarke * table - Pointer to the table (required for virtual 83*5d6e5966SJessica Clarke * origins, optional for physical) 8486dfc6f3SLv Zheng * reload - Whether reload should be performed 85caf4a15cSLv Zheng * override - Whether override should be performed 8686dfc6f3SLv Zheng * table_index - Where the table index is returned 8786dfc6f3SLv Zheng * 8886dfc6f3SLv Zheng * RETURN: Status 8986dfc6f3SLv Zheng * 90752db101SLv Zheng * DESCRIPTION: This function is called to verify and install an ACPI table. 9186dfc6f3SLv Zheng * When this function is called by "Load" or "LoadTable" opcodes, 9286dfc6f3SLv Zheng * or by acpi_load_table() API, the "Reload" parameter is set. 93c2fa79b8SColin Ian King * After successfully returning from this function, table is 9486dfc6f3SLv Zheng * "INSTALLED" but not "VALIDATED". 9586dfc6f3SLv Zheng * 9686dfc6f3SLv Zheng ******************************************************************************/ 9786dfc6f3SLv Zheng 9886dfc6f3SLv Zheng acpi_status 99ed6f1d44SBob Moore acpi_tb_install_standard_table(acpi_physical_address address, 100caf4a15cSLv Zheng u8 flags, 101*5d6e5966SJessica Clarke struct acpi_table_header *table, 102caf4a15cSLv Zheng u8 reload, u8 override, u32 *table_index) 10395b482a8SLen Brown { 10495b482a8SLen Brown u32 i; 10595b482a8SLen Brown acpi_status status = AE_OK; 10686dfc6f3SLv Zheng struct acpi_table_desc new_table_desc; 10795b482a8SLen Brown 108ed6f1d44SBob Moore ACPI_FUNCTION_TRACE(tb_install_standard_table); 10995b482a8SLen Brown 110ed6f1d44SBob Moore /* Acquire a temporary table descriptor for validation */ 11186dfc6f3SLv Zheng 112*5d6e5966SJessica Clarke status = 113*5d6e5966SJessica Clarke acpi_tb_acquire_temp_table(&new_table_desc, address, flags, table); 11486dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 115cc2080b0SLv Zheng ACPI_ERROR((AE_INFO, 116cc2080b0SLv Zheng "Could not acquire table length at %8.8X%8.8X", 117cc2080b0SLv Zheng ACPI_FORMAT_UINT64(address))); 11895b482a8SLen Brown return_ACPI_STATUS(status); 11995b482a8SLen Brown } 12086dfc6f3SLv Zheng 121a94e88cdSLv Zheng /* 122a94e88cdSLv Zheng * Optionally do not load any SSDTs from the RSDT/XSDT. This can 123a94e88cdSLv Zheng * be useful for debugging ACPI problems on some machines. 124a94e88cdSLv Zheng */ 125ed6f1d44SBob Moore if (!reload && 126ed6f1d44SBob Moore acpi_gbl_disable_ssdt_table_install && 1275599fb69SBob Moore ACPI_COMPARE_NAMESEG(&new_table_desc.signature, ACPI_SIG_SSDT)) { 12805fb04b5SBob Moore ACPI_INFO(("Ignoring installation of %4.4s at %8.8X%8.8X", 1296d3fd3ccSLv Zheng new_table_desc.signature.ascii, 130cc2080b0SLv Zheng ACPI_FORMAT_UINT64(address))); 131a94e88cdSLv Zheng goto release_and_exit; 132a94e88cdSLv Zheng } 133a94e88cdSLv Zheng 1347a37052aSLv Zheng /* Acquire the table lock */ 1357a37052aSLv Zheng 1367a37052aSLv Zheng (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 1377a37052aSLv Zheng 138f9d472eeSLv Zheng /* Validate and verify a table before installation */ 13995b482a8SLen Brown 140f9d472eeSLv Zheng status = acpi_tb_verify_temp_table(&new_table_desc, NULL, &i); 141f9d472eeSLv Zheng if (ACPI_FAILURE(status)) { 142f9d472eeSLv Zheng if (status == AE_CTRL_TERMINATE) { 143d3ccaff8SBob Moore /* 14486dfc6f3SLv Zheng * Table was unloaded, allow it to be reloaded. 14586dfc6f3SLv Zheng * As we are going to return AE_OK to the caller, we should 14686dfc6f3SLv Zheng * take the responsibility of freeing the input descriptor. 14786dfc6f3SLv Zheng * Refill the input descriptor to ensure 148ed6f1d44SBob Moore * acpi_tb_install_table_with_override() can be called again to 14986dfc6f3SLv Zheng * indicate the re-installation. 150d3ccaff8SBob Moore */ 15186dfc6f3SLv Zheng acpi_tb_uninstall_table(&new_table_desc); 1527a37052aSLv Zheng (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 15386dfc6f3SLv Zheng *table_index = i; 15486dfc6f3SLv Zheng return_ACPI_STATUS(AE_OK); 15586dfc6f3SLv Zheng } 156f9d472eeSLv Zheng goto unlock_and_exit; 1577f9fc99cSLv Zheng } 158d3ccaff8SBob Moore 15995b482a8SLen Brown /* Add the table to the global root table list */ 16095b482a8SLen Brown 1618ec3f459SLv Zheng acpi_tb_install_table_with_override(&new_table_desc, override, 1628ec3f459SLv Zheng table_index); 16395b482a8SLen Brown 1649b019b0fSLv Zheng /* Invoke table handler */ 165bdbe5df0SLv Zheng 1667a37052aSLv Zheng (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 1679b019b0fSLv Zheng acpi_tb_notify_table(ACPI_TABLE_EVENT_INSTALL, new_table_desc.pointer); 1687a37052aSLv Zheng (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 1697a37052aSLv Zheng 1707a37052aSLv Zheng unlock_and_exit: 1717a37052aSLv Zheng 1727a37052aSLv Zheng /* Release the table lock */ 1737a37052aSLv Zheng 1747a37052aSLv Zheng (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 175bdbe5df0SLv Zheng 17686dfc6f3SLv Zheng release_and_exit: 17795b482a8SLen Brown 178ed6f1d44SBob Moore /* Release the temporary table descriptor */ 17986dfc6f3SLv Zheng 180ed6f1d44SBob Moore acpi_tb_release_temp_table(&new_table_desc); 18195b482a8SLen Brown return_ACPI_STATUS(status); 18295b482a8SLen Brown } 18395b482a8SLen Brown 18495b482a8SLen Brown /******************************************************************************* 18595b482a8SLen Brown * 1867f9fc99cSLv Zheng * FUNCTION: acpi_tb_override_table 187f7b004a1SBob Moore * 18886dfc6f3SLv Zheng * PARAMETERS: old_table_desc - Validated table descriptor to be 18986dfc6f3SLv Zheng * overridden 190f7b004a1SBob Moore * 19186dfc6f3SLv Zheng * RETURN: None 192f7b004a1SBob Moore * 193f7b004a1SBob Moore * DESCRIPTION: Attempt table override by calling the OSL override functions. 194f7b004a1SBob Moore * Note: If the table is overridden, then the entire new table 1957f9fc99cSLv Zheng * is acquired and returned by this function. 19686dfc6f3SLv Zheng * Before/after invocation, the table descriptor is in a state 19786dfc6f3SLv Zheng * that is "VALIDATED". 198f7b004a1SBob Moore * 199f7b004a1SBob Moore ******************************************************************************/ 200f7b004a1SBob Moore 20186dfc6f3SLv Zheng void acpi_tb_override_table(struct acpi_table_desc *old_table_desc) 202f7b004a1SBob Moore { 203f7b004a1SBob Moore acpi_status status; 2047f9fc99cSLv Zheng struct acpi_table_desc new_table_desc; 20586dfc6f3SLv Zheng struct acpi_table_header *table; 20686dfc6f3SLv Zheng acpi_physical_address address; 20786dfc6f3SLv Zheng u32 length; 2080fe0bebfSErik Schmauss ACPI_ERROR_ONLY(char *override_type); 209f7b004a1SBob Moore 210f7b004a1SBob Moore /* (1) Attempt logical override (returns a logical address) */ 211f7b004a1SBob Moore 21286dfc6f3SLv Zheng status = acpi_os_table_override(old_table_desc->pointer, &table); 21386dfc6f3SLv Zheng if (ACPI_SUCCESS(status) && table) { 214ed6f1d44SBob Moore acpi_tb_acquire_temp_table(&new_table_desc, 21586dfc6f3SLv Zheng ACPI_PTR_TO_PHYSADDR(table), 216*5d6e5966SJessica Clarke ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, 217*5d6e5966SJessica Clarke table); 2180fe0bebfSErik Schmauss ACPI_ERROR_ONLY(override_type = "Logical"); 219f7b004a1SBob Moore goto finish_override; 220f7b004a1SBob Moore } 221f7b004a1SBob Moore 222f7b004a1SBob Moore /* (2) Attempt physical override (returns a physical address) */ 223f7b004a1SBob Moore 22486dfc6f3SLv Zheng status = acpi_os_physical_table_override(old_table_desc->pointer, 22586dfc6f3SLv Zheng &address, &length); 22686dfc6f3SLv Zheng if (ACPI_SUCCESS(status) && address && length) { 227ed6f1d44SBob Moore acpi_tb_acquire_temp_table(&new_table_desc, address, 228*5d6e5966SJessica Clarke ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, 229*5d6e5966SJessica Clarke NULL); 2300fe0bebfSErik Schmauss ACPI_ERROR_ONLY(override_type = "Physical"); 231f7b004a1SBob Moore goto finish_override; 232f7b004a1SBob Moore } 233f7b004a1SBob Moore 23486dfc6f3SLv Zheng return; /* There was no override */ 235f7b004a1SBob Moore 236f7b004a1SBob Moore finish_override: 237f7b004a1SBob Moore 238f9d472eeSLv Zheng /* 239f9d472eeSLv Zheng * Validate and verify a table before overriding, no nested table 240f9d472eeSLv Zheng * duplication check as it's too complicated and unnecessary. 241f9d472eeSLv Zheng */ 242f9d472eeSLv Zheng status = acpi_tb_verify_temp_table(&new_table_desc, NULL, NULL); 2437f9fc99cSLv Zheng if (ACPI_FAILURE(status)) { 24486dfc6f3SLv Zheng return; 2457f9fc99cSLv Zheng } 2467f9fc99cSLv Zheng 24705fb04b5SBob Moore ACPI_INFO(("%4.4s 0x%8.8X%8.8X" 2481d0a0b2fSLv Zheng " %s table override, new table: 0x%8.8X%8.8X", 24986dfc6f3SLv Zheng old_table_desc->signature.ascii, 2501d0a0b2fSLv Zheng ACPI_FORMAT_UINT64(old_table_desc->address), 2511d0a0b2fSLv Zheng override_type, ACPI_FORMAT_UINT64(new_table_desc.address))); 252f7b004a1SBob Moore 25386dfc6f3SLv Zheng /* We can now uninstall the original table */ 254f7b004a1SBob Moore 25586dfc6f3SLv Zheng acpi_tb_uninstall_table(old_table_desc); 256f7b004a1SBob Moore 25786dfc6f3SLv Zheng /* 25886dfc6f3SLv Zheng * Replace the original table descriptor and keep its state as 25986dfc6f3SLv Zheng * "VALIDATED". 26086dfc6f3SLv Zheng */ 261ed6f1d44SBob Moore acpi_tb_init_table_descriptor(old_table_desc, new_table_desc.address, 262ed6f1d44SBob Moore new_table_desc.flags, 263ed6f1d44SBob Moore new_table_desc.pointer); 26447d68c7fSLv Zheng acpi_tb_validate_temp_table(old_table_desc); 265f7b004a1SBob Moore 266ed6f1d44SBob Moore /* Release the temporary table descriptor */ 267f7b004a1SBob Moore 268ed6f1d44SBob Moore acpi_tb_release_temp_table(&new_table_desc); 269f7b004a1SBob Moore } 270f7b004a1SBob Moore 271f7b004a1SBob Moore /******************************************************************************* 272f7b004a1SBob Moore * 2737f9fc99cSLv Zheng * FUNCTION: acpi_tb_uninstall_table 27495b482a8SLen Brown * 2757f9fc99cSLv Zheng * PARAMETERS: table_desc - Table descriptor 27695b482a8SLen Brown * 27795b482a8SLen Brown * RETURN: None 27895b482a8SLen Brown * 27995b482a8SLen Brown * DESCRIPTION: Delete one internal ACPI table 28095b482a8SLen Brown * 28195b482a8SLen Brown ******************************************************************************/ 28295b482a8SLen Brown 2837f9fc99cSLv Zheng void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc) 28495b482a8SLen Brown { 2855582982dSLv Zheng 2867f9fc99cSLv Zheng ACPI_FUNCTION_TRACE(tb_uninstall_table); 2875582982dSLv Zheng 2887f9fc99cSLv Zheng /* Table must be installed */ 2897f9fc99cSLv Zheng 2907f9fc99cSLv Zheng if (!table_desc->address) { 2917f9fc99cSLv Zheng return_VOID; 29295b482a8SLen Brown } 2935582982dSLv Zheng 2947f9fc99cSLv Zheng acpi_tb_invalidate_table(table_desc); 2951d1ea1b7SChao Guan 2967f9fc99cSLv Zheng if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == 297ed6f1d44SBob Moore ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) { 298*5d6e5966SJessica Clarke ACPI_FREE(table_desc->pointer); 299*5d6e5966SJessica Clarke table_desc->pointer = NULL; 3007f9fc99cSLv Zheng } 3011d1ea1b7SChao Guan 302dc156adfSLv Zheng table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL); 3037f9fc99cSLv Zheng return_VOID; 30495b482a8SLen Brown } 305