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 "actables.h" 4795b482a8SLen Brown 4895b482a8SLen Brown #define _COMPONENT ACPI_TABLES 4995b482a8SLen Brown ACPI_MODULE_NAME("tbinstal") 5095b482a8SLen Brown 5186dfc6f3SLv Zheng /* Local prototypes */ 52*c418ce19SBob Moore static u8 53*c418ce19SBob Moore acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index); 5486dfc6f3SLv Zheng 55*c418ce19SBob Moore /******************************************************************************* 56*c418ce19SBob Moore * 57*c418ce19SBob Moore * FUNCTION: acpi_tb_compare_tables 58*c418ce19SBob Moore * 59*c418ce19SBob Moore * PARAMETERS: table_desc - Table 1 descriptor to be compared 60*c418ce19SBob Moore * table_index - Index of table 2 to be compared 61*c418ce19SBob Moore * 62*c418ce19SBob Moore * RETURN: TRUE if both tables are identical. 63*c418ce19SBob Moore * 64*c418ce19SBob Moore * DESCRIPTION: This function compares a table with another table that has 65*c418ce19SBob Moore * already been installed in the root table list. 66*c418ce19SBob Moore * 67*c418ce19SBob Moore ******************************************************************************/ 6886dfc6f3SLv Zheng 6986dfc6f3SLv Zheng static u8 70*c418ce19SBob Moore acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index) 717f9fc99cSLv Zheng { 727f9fc99cSLv Zheng acpi_status status = AE_OK; 73*c418ce19SBob Moore u8 is_identical; 74*c418ce19SBob Moore struct acpi_table_header *table; 75*c418ce19SBob Moore u32 table_length; 76*c418ce19SBob Moore u8 table_flags; 7786dfc6f3SLv Zheng 7886dfc6f3SLv Zheng status = 79*c418ce19SBob Moore acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index], 80*c418ce19SBob Moore &table, &table_length, &table_flags); 8186dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 82*c418ce19SBob Moore return (FALSE); 8386dfc6f3SLv Zheng } 8486dfc6f3SLv Zheng 8586dfc6f3SLv Zheng /* 86*c418ce19SBob Moore * Check for a table match on the entire table length, 87*c418ce19SBob Moore * not just the header. 8886dfc6f3SLv Zheng */ 89*c418ce19SBob Moore is_identical = (u8)((table_desc->length != table_length || 90*c418ce19SBob Moore ACPI_MEMCMP(table_desc->pointer, table, 91*c418ce19SBob Moore table_length)) ? FALSE : TRUE); 9286dfc6f3SLv Zheng 93*c418ce19SBob Moore /* Release the acquired table */ 9486dfc6f3SLv Zheng 95*c418ce19SBob Moore acpi_tb_release_table(table, table_length, table_flags); 96*c418ce19SBob Moore return (is_identical); 9786dfc6f3SLv Zheng } 9886dfc6f3SLv Zheng 9986dfc6f3SLv Zheng /******************************************************************************* 10086dfc6f3SLv Zheng * 101ed6f1d44SBob Moore * FUNCTION: acpi_tb_install_table_with_override 10286dfc6f3SLv Zheng * 10386dfc6f3SLv Zheng * PARAMETERS: table_index - Index into root table array 10486dfc6f3SLv Zheng * new_table_desc - New table descriptor to install 105caf4a15cSLv Zheng * override - Whether override should be performed 10686dfc6f3SLv Zheng * 10786dfc6f3SLv Zheng * RETURN: None 10886dfc6f3SLv Zheng * 10986dfc6f3SLv Zheng * DESCRIPTION: Install an ACPI table into the global data structure. The 11086dfc6f3SLv Zheng * table override mechanism is called to allow the host 11186dfc6f3SLv Zheng * OS to replace any table before it is installed in the root 11286dfc6f3SLv Zheng * table array. 11386dfc6f3SLv Zheng * 11486dfc6f3SLv Zheng ******************************************************************************/ 11586dfc6f3SLv Zheng 11686dfc6f3SLv Zheng void 117ed6f1d44SBob Moore acpi_tb_install_table_with_override(u32 table_index, 118caf4a15cSLv Zheng struct acpi_table_desc *new_table_desc, 119caf4a15cSLv Zheng u8 override) 12086dfc6f3SLv Zheng { 121ed6f1d44SBob Moore 12286dfc6f3SLv Zheng if (table_index >= acpi_gbl_root_table_list.current_table_count) { 12386dfc6f3SLv Zheng return; 12486dfc6f3SLv Zheng } 12586dfc6f3SLv Zheng 12686dfc6f3SLv Zheng /* 12786dfc6f3SLv Zheng * ACPI Table Override: 12886dfc6f3SLv Zheng * 12986dfc6f3SLv Zheng * Before we install the table, let the host OS override it with a new 13086dfc6f3SLv Zheng * one if desired. Any table within the RSDT/XSDT can be replaced, 13186dfc6f3SLv Zheng * including the DSDT which is pointed to by the FADT. 13286dfc6f3SLv Zheng */ 133caf4a15cSLv Zheng if (override) { 13486dfc6f3SLv Zheng acpi_tb_override_table(new_table_desc); 135caf4a15cSLv Zheng } 13686dfc6f3SLv Zheng 137ed6f1d44SBob Moore acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list. 138ed6f1d44SBob Moore tables[table_index], 139ed6f1d44SBob Moore new_table_desc->address, 140ed6f1d44SBob Moore new_table_desc->flags, 14186dfc6f3SLv Zheng new_table_desc->pointer); 14286dfc6f3SLv Zheng 14386dfc6f3SLv Zheng acpi_tb_print_table_header(new_table_desc->address, 14486dfc6f3SLv Zheng new_table_desc->pointer); 14586dfc6f3SLv Zheng 14686dfc6f3SLv Zheng /* Set the global integer width (based upon revision of the DSDT) */ 14786dfc6f3SLv Zheng 14886dfc6f3SLv Zheng if (table_index == ACPI_TABLE_INDEX_DSDT) { 14986dfc6f3SLv Zheng acpi_ut_set_integer_width(new_table_desc->pointer->revision); 15086dfc6f3SLv Zheng } 15186dfc6f3SLv Zheng } 15286dfc6f3SLv Zheng 15386dfc6f3SLv Zheng /******************************************************************************* 15486dfc6f3SLv Zheng * 15586dfc6f3SLv Zheng * FUNCTION: acpi_tb_install_fixed_table 15686dfc6f3SLv Zheng * 15786dfc6f3SLv Zheng * PARAMETERS: address - Physical address of DSDT or FACS 15886dfc6f3SLv Zheng * signature - Table signature, NULL if no need to 15986dfc6f3SLv Zheng * match 16086dfc6f3SLv Zheng * table_index - Index into root table array 16186dfc6f3SLv Zheng * 16286dfc6f3SLv Zheng * RETURN: Status 16386dfc6f3SLv Zheng * 16486dfc6f3SLv Zheng * DESCRIPTION: Install a fixed ACPI table (DSDT/FACS) into the global data 16586dfc6f3SLv Zheng * structure. 16695b482a8SLen Brown * 16795b482a8SLen Brown ******************************************************************************/ 16895b482a8SLen Brown 16995b482a8SLen Brown acpi_status 17086dfc6f3SLv Zheng acpi_tb_install_fixed_table(acpi_physical_address address, 17186dfc6f3SLv Zheng char *signature, u32 table_index) 17286dfc6f3SLv Zheng { 17386dfc6f3SLv Zheng struct acpi_table_desc new_table_desc; 17486dfc6f3SLv Zheng acpi_status status; 17586dfc6f3SLv Zheng 17686dfc6f3SLv Zheng ACPI_FUNCTION_TRACE(tb_install_fixed_table); 17786dfc6f3SLv Zheng 17886dfc6f3SLv Zheng if (!address) { 17986dfc6f3SLv Zheng ACPI_ERROR((AE_INFO, 18086dfc6f3SLv Zheng "Null physical address for ACPI table [%s]", 18186dfc6f3SLv Zheng signature)); 18286dfc6f3SLv Zheng return (AE_NO_MEMORY); 18386dfc6f3SLv Zheng } 18486dfc6f3SLv Zheng 18586dfc6f3SLv Zheng /* Fill a table descriptor for validation */ 18686dfc6f3SLv Zheng 187ed6f1d44SBob Moore status = acpi_tb_acquire_temp_table(&new_table_desc, address, 188ed6f1d44SBob Moore ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); 18986dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 19086dfc6f3SLv Zheng ACPI_ERROR((AE_INFO, "Could not acquire table length at %p", 19186dfc6f3SLv Zheng ACPI_CAST_PTR(void, address))); 19286dfc6f3SLv Zheng return_ACPI_STATUS(status); 19386dfc6f3SLv Zheng } 19486dfc6f3SLv Zheng 19586dfc6f3SLv Zheng /* Validate and verify a table before installation */ 19686dfc6f3SLv Zheng 19786dfc6f3SLv Zheng status = acpi_tb_verify_table(&new_table_desc, signature); 19886dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 19986dfc6f3SLv Zheng goto release_and_exit; 20086dfc6f3SLv Zheng } 20186dfc6f3SLv Zheng 202ed6f1d44SBob Moore acpi_tb_install_table_with_override(table_index, &new_table_desc, TRUE); 20386dfc6f3SLv Zheng 20486dfc6f3SLv Zheng release_and_exit: 20586dfc6f3SLv Zheng 206ed6f1d44SBob Moore /* Release the temporary table descriptor */ 20786dfc6f3SLv Zheng 208ed6f1d44SBob Moore acpi_tb_release_temp_table(&new_table_desc); 20986dfc6f3SLv Zheng return_ACPI_STATUS(status); 21086dfc6f3SLv Zheng } 21186dfc6f3SLv Zheng 21286dfc6f3SLv Zheng /******************************************************************************* 21386dfc6f3SLv Zheng * 214ed6f1d44SBob Moore * FUNCTION: acpi_tb_install_standard_table 21586dfc6f3SLv Zheng * 2168a216d7fSLv Zheng * PARAMETERS: address - Address of the table (might be a virtual 21786dfc6f3SLv Zheng * address depending on the table_flags) 21886dfc6f3SLv Zheng * flags - Flags for the table 21986dfc6f3SLv Zheng * reload - Whether reload should be performed 220caf4a15cSLv Zheng * override - Whether override should be performed 22186dfc6f3SLv Zheng * table_index - Where the table index is returned 22286dfc6f3SLv Zheng * 22386dfc6f3SLv Zheng * RETURN: Status 22486dfc6f3SLv Zheng * 22586dfc6f3SLv Zheng * DESCRIPTION: This function is called to install an ACPI table that is 226ed6f1d44SBob Moore * neither DSDT nor FACS (a "standard" table.) 22786dfc6f3SLv Zheng * When this function is called by "Load" or "LoadTable" opcodes, 22886dfc6f3SLv Zheng * or by acpi_load_table() API, the "Reload" parameter is set. 22986dfc6f3SLv Zheng * After sucessfully returning from this function, table is 23086dfc6f3SLv Zheng * "INSTALLED" but not "VALIDATED". 23186dfc6f3SLv Zheng * 23286dfc6f3SLv Zheng ******************************************************************************/ 23386dfc6f3SLv Zheng 23486dfc6f3SLv Zheng acpi_status 235ed6f1d44SBob Moore acpi_tb_install_standard_table(acpi_physical_address address, 236caf4a15cSLv Zheng u8 flags, 237caf4a15cSLv Zheng u8 reload, u8 override, u32 *table_index) 23895b482a8SLen Brown { 23995b482a8SLen Brown u32 i; 24095b482a8SLen Brown acpi_status status = AE_OK; 24186dfc6f3SLv Zheng struct acpi_table_desc new_table_desc; 24295b482a8SLen Brown 243ed6f1d44SBob Moore ACPI_FUNCTION_TRACE(tb_install_standard_table); 24495b482a8SLen Brown 245ed6f1d44SBob Moore /* Acquire a temporary table descriptor for validation */ 24686dfc6f3SLv Zheng 247ed6f1d44SBob Moore status = acpi_tb_acquire_temp_table(&new_table_desc, address, flags); 24886dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 24986dfc6f3SLv Zheng ACPI_ERROR((AE_INFO, "Could not acquire table length at %p", 25086dfc6f3SLv Zheng ACPI_CAST_PTR(void, address))); 25195b482a8SLen Brown return_ACPI_STATUS(status); 25295b482a8SLen Brown } 25386dfc6f3SLv Zheng 254a94e88cdSLv Zheng /* 255a94e88cdSLv Zheng * Optionally do not load any SSDTs from the RSDT/XSDT. This can 256a94e88cdSLv Zheng * be useful for debugging ACPI problems on some machines. 257a94e88cdSLv Zheng */ 258ed6f1d44SBob Moore if (!reload && 259ed6f1d44SBob Moore acpi_gbl_disable_ssdt_table_install && 260a94e88cdSLv Zheng ACPI_COMPARE_NAME(&new_table_desc.signature, ACPI_SIG_SSDT)) { 261a94e88cdSLv Zheng ACPI_INFO((AE_INFO, "Ignoring installation of %4.4s at %p", 262a94e88cdSLv Zheng new_table_desc.signature.ascii, ACPI_CAST_PTR(void, 263a94e88cdSLv Zheng address))); 264a94e88cdSLv Zheng goto release_and_exit; 265a94e88cdSLv Zheng } 266a94e88cdSLv Zheng 26786dfc6f3SLv Zheng /* Validate and verify a table before installation */ 26886dfc6f3SLv Zheng 26986dfc6f3SLv Zheng status = acpi_tb_verify_table(&new_table_desc, NULL); 27086dfc6f3SLv Zheng if (ACPI_FAILURE(status)) { 27186dfc6f3SLv Zheng goto release_and_exit; 27295b482a8SLen Brown } 27395b482a8SLen Brown 27486dfc6f3SLv Zheng if (reload) { 27595b482a8SLen Brown /* 276c8cefe30SBob Moore * Validate the incoming table signature. 277c8cefe30SBob Moore * 278c8cefe30SBob Moore * 1) Originally, we checked the table signature for "SSDT" or "PSDT". 279c8cefe30SBob Moore * 2) We added support for OEMx tables, signature "OEM". 280c8cefe30SBob Moore * 3) Valid tables were encountered with a null signature, so we just 281c8cefe30SBob Moore * gave up on validating the signature, (05/2008). 282c8cefe30SBob Moore * 4) We encountered non-AML tables such as the MADT, which caused 283c8cefe30SBob Moore * interpreter errors and kernel faults. So now, we once again allow 284c8cefe30SBob Moore * only "SSDT", "OEMx", and now, also a null signature. (05/2011). 28595b482a8SLen Brown */ 28686dfc6f3SLv Zheng if ((new_table_desc.signature.ascii[0] != 0x00) && 28786dfc6f3SLv Zheng (!ACPI_COMPARE_NAME 28886dfc6f3SLv Zheng (&new_table_desc.signature, ACPI_SIG_SSDT)) 28986dfc6f3SLv Zheng && (ACPI_STRNCMP(new_table_desc.signature.ascii, "OEM", 3))) 29086dfc6f3SLv Zheng { 2913b3ea775SBob Moore ACPI_BIOS_ERROR((AE_INFO, 2923b3ea775SBob Moore "Table has invalid signature [%4.4s] (0x%8.8X), " 2933b3ea775SBob Moore "must be SSDT or OEMx", 29486dfc6f3SLv Zheng acpi_ut_valid_acpi_name(new_table_desc. 29586dfc6f3SLv Zheng signature. 29686dfc6f3SLv Zheng ascii) ? 29786dfc6f3SLv Zheng new_table_desc.signature. 29886dfc6f3SLv Zheng ascii : "????", 29986dfc6f3SLv Zheng new_table_desc.signature.integer)); 300c8cefe30SBob Moore 30186dfc6f3SLv Zheng status = AE_BAD_SIGNATURE; 30286dfc6f3SLv Zheng goto release_and_exit; 303c8cefe30SBob Moore } 30495b482a8SLen Brown 30595b482a8SLen Brown /* Check if table is already registered */ 30695b482a8SLen Brown 30786dfc6f3SLv Zheng for (i = 0; i < acpi_gbl_root_table_list.current_table_count; 30886dfc6f3SLv Zheng ++i) { 30995b482a8SLen Brown /* 31095b482a8SLen Brown * Check for a table match on the entire table length, 31195b482a8SLen Brown * not just the header. 31295b482a8SLen Brown */ 313*c418ce19SBob Moore if (!acpi_tb_compare_tables(&new_table_desc, i)) { 31495b482a8SLen Brown continue; 31595b482a8SLen Brown } 31695b482a8SLen Brown 31795b482a8SLen Brown /* 31895b482a8SLen Brown * Note: the current mechanism does not unregister a table if it is 31995b482a8SLen Brown * dynamically unloaded. The related namespace entries are deleted, 32095b482a8SLen Brown * but the table remains in the root table list. 32195b482a8SLen Brown * 32295b482a8SLen Brown * The assumption here is that the number of different tables that 32395b482a8SLen Brown * will be loaded is actually small, and there is minimal overhead 32495b482a8SLen Brown * in just keeping the table in case it is needed again. 32595b482a8SLen Brown * 32695b482a8SLen Brown * If this assumption changes in the future (perhaps on large 32795b482a8SLen Brown * machines with many table load/unload operations), tables will 32895b482a8SLen Brown * need to be unregistered when they are unloaded, and slots in the 32995b482a8SLen Brown * root table list should be reused when empty. 33095b482a8SLen Brown */ 33195b482a8SLen Brown if (acpi_gbl_root_table_list.tables[i]. 33295b482a8SLen Brown flags & ACPI_TABLE_IS_LOADED) { 33395b482a8SLen Brown 33495b482a8SLen Brown /* Table is still loaded, this is an error */ 33595b482a8SLen Brown 33695b482a8SLen Brown status = AE_ALREADY_EXISTS; 33786dfc6f3SLv Zheng goto release_and_exit; 33895b482a8SLen Brown } else { 339d3ccaff8SBob Moore /* 34086dfc6f3SLv Zheng * Table was unloaded, allow it to be reloaded. 34186dfc6f3SLv Zheng * As we are going to return AE_OK to the caller, we should 34286dfc6f3SLv Zheng * take the responsibility of freeing the input descriptor. 34386dfc6f3SLv Zheng * Refill the input descriptor to ensure 344ed6f1d44SBob Moore * acpi_tb_install_table_with_override() can be called again to 34586dfc6f3SLv Zheng * indicate the re-installation. 346d3ccaff8SBob Moore */ 34786dfc6f3SLv Zheng acpi_tb_uninstall_table(&new_table_desc); 34886dfc6f3SLv Zheng *table_index = i; 34986dfc6f3SLv Zheng (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 35086dfc6f3SLv Zheng return_ACPI_STATUS(AE_OK); 35186dfc6f3SLv Zheng } 35286dfc6f3SLv Zheng } 3537f9fc99cSLv Zheng } 354d3ccaff8SBob Moore 35595b482a8SLen Brown /* Add the table to the global root table list */ 35695b482a8SLen Brown 357*c418ce19SBob Moore status = acpi_tb_get_next_root_index(&i); 35895b482a8SLen Brown if (ACPI_FAILURE(status)) { 35986dfc6f3SLv Zheng goto release_and_exit; 36095b482a8SLen Brown } 361ed6f1d44SBob Moore 36286dfc6f3SLv Zheng *table_index = i; 363ed6f1d44SBob Moore acpi_tb_install_table_with_override(i, &new_table_desc, override); 36495b482a8SLen Brown 36586dfc6f3SLv Zheng release_and_exit: 36695b482a8SLen Brown 367ed6f1d44SBob Moore /* Release the temporary table descriptor */ 36886dfc6f3SLv Zheng 369ed6f1d44SBob Moore acpi_tb_release_temp_table(&new_table_desc); 37095b482a8SLen Brown return_ACPI_STATUS(status); 37195b482a8SLen Brown } 37295b482a8SLen Brown 37395b482a8SLen Brown /******************************************************************************* 37495b482a8SLen Brown * 3757f9fc99cSLv Zheng * FUNCTION: acpi_tb_override_table 376f7b004a1SBob Moore * 37786dfc6f3SLv Zheng * PARAMETERS: old_table_desc - Validated table descriptor to be 37886dfc6f3SLv Zheng * overridden 379f7b004a1SBob Moore * 38086dfc6f3SLv Zheng * RETURN: None 381f7b004a1SBob Moore * 382f7b004a1SBob Moore * DESCRIPTION: Attempt table override by calling the OSL override functions. 383f7b004a1SBob Moore * Note: If the table is overridden, then the entire new table 3847f9fc99cSLv Zheng * is acquired and returned by this function. 38586dfc6f3SLv Zheng * Before/after invocation, the table descriptor is in a state 38686dfc6f3SLv Zheng * that is "VALIDATED". 387f7b004a1SBob Moore * 388f7b004a1SBob Moore ******************************************************************************/ 389f7b004a1SBob Moore 39086dfc6f3SLv Zheng void acpi_tb_override_table(struct acpi_table_desc *old_table_desc) 391f7b004a1SBob Moore { 392f7b004a1SBob Moore acpi_status status; 393f7b004a1SBob Moore char *override_type; 3947f9fc99cSLv Zheng struct acpi_table_desc new_table_desc; 39586dfc6f3SLv Zheng struct acpi_table_header *table; 39686dfc6f3SLv Zheng acpi_physical_address address; 39786dfc6f3SLv Zheng u32 length; 398f7b004a1SBob Moore 399f7b004a1SBob Moore /* (1) Attempt logical override (returns a logical address) */ 400f7b004a1SBob Moore 40186dfc6f3SLv Zheng status = acpi_os_table_override(old_table_desc->pointer, &table); 40286dfc6f3SLv Zheng if (ACPI_SUCCESS(status) && table) { 403ed6f1d44SBob Moore acpi_tb_acquire_temp_table(&new_table_desc, 40486dfc6f3SLv Zheng ACPI_PTR_TO_PHYSADDR(table), 405ed6f1d44SBob Moore ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL); 406f7b004a1SBob Moore override_type = "Logical"; 407f7b004a1SBob Moore goto finish_override; 408f7b004a1SBob Moore } 409f7b004a1SBob Moore 410f7b004a1SBob Moore /* (2) Attempt physical override (returns a physical address) */ 411f7b004a1SBob Moore 41286dfc6f3SLv Zheng status = acpi_os_physical_table_override(old_table_desc->pointer, 41386dfc6f3SLv Zheng &address, &length); 41486dfc6f3SLv Zheng if (ACPI_SUCCESS(status) && address && length) { 415ed6f1d44SBob Moore acpi_tb_acquire_temp_table(&new_table_desc, address, 416ed6f1d44SBob Moore ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); 417f7b004a1SBob Moore override_type = "Physical"; 418f7b004a1SBob Moore goto finish_override; 419f7b004a1SBob Moore } 420f7b004a1SBob Moore 42186dfc6f3SLv Zheng return; /* There was no override */ 422f7b004a1SBob Moore 423f7b004a1SBob Moore finish_override: 424f7b004a1SBob Moore 42586dfc6f3SLv Zheng /* Validate and verify a table before overriding */ 42686dfc6f3SLv Zheng 42786dfc6f3SLv Zheng status = acpi_tb_verify_table(&new_table_desc, NULL); 4287f9fc99cSLv Zheng if (ACPI_FAILURE(status)) { 42986dfc6f3SLv Zheng return; 4307f9fc99cSLv Zheng } 4317f9fc99cSLv Zheng 4322e19f8d0SBob Moore ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT 4332e19f8d0SBob Moore " %s table override, new table: " ACPI_PRINTF_UINT, 43486dfc6f3SLv Zheng old_table_desc->signature.ascii, 43586dfc6f3SLv Zheng ACPI_FORMAT_TO_UINT(old_table_desc->address), 4367f9fc99cSLv Zheng override_type, ACPI_FORMAT_TO_UINT(new_table_desc.address))); 437f7b004a1SBob Moore 43886dfc6f3SLv Zheng /* We can now uninstall the original table */ 439f7b004a1SBob Moore 44086dfc6f3SLv Zheng acpi_tb_uninstall_table(old_table_desc); 441f7b004a1SBob Moore 44286dfc6f3SLv Zheng /* 44386dfc6f3SLv Zheng * Replace the original table descriptor and keep its state as 44486dfc6f3SLv Zheng * "VALIDATED". 44586dfc6f3SLv Zheng */ 446ed6f1d44SBob Moore acpi_tb_init_table_descriptor(old_table_desc, new_table_desc.address, 447ed6f1d44SBob Moore new_table_desc.flags, 448ed6f1d44SBob Moore new_table_desc.pointer); 44986dfc6f3SLv Zheng acpi_tb_validate_table(old_table_desc); 450f7b004a1SBob Moore 451ed6f1d44SBob Moore /* Release the temporary table descriptor */ 452f7b004a1SBob Moore 453ed6f1d44SBob Moore acpi_tb_release_temp_table(&new_table_desc); 454f7b004a1SBob Moore } 455f7b004a1SBob Moore 456f7b004a1SBob Moore /******************************************************************************* 457f7b004a1SBob Moore * 45895b482a8SLen Brown * FUNCTION: acpi_tb_store_table 45995b482a8SLen Brown * 460ba494beeSBob Moore * PARAMETERS: address - Table address 461ba494beeSBob Moore * table - Table header 462ba494beeSBob Moore * length - Table length 463ed6f1d44SBob Moore * flags - Install flags 464ed6f1d44SBob Moore * table_index - Where the table index is returned 46595b482a8SLen Brown * 46695b482a8SLen Brown * RETURN: Status and table index. 46795b482a8SLen Brown * 46895b482a8SLen Brown * DESCRIPTION: Add an ACPI table to the global table list 46995b482a8SLen Brown * 47095b482a8SLen Brown ******************************************************************************/ 47195b482a8SLen Brown 47295b482a8SLen Brown acpi_status 47395b482a8SLen Brown acpi_tb_store_table(acpi_physical_address address, 47495b482a8SLen Brown struct acpi_table_header * table, 47595b482a8SLen Brown u32 length, u8 flags, u32 *table_index) 47695b482a8SLen Brown { 477b9ee2043SBob Moore acpi_status status; 47886dfc6f3SLv Zheng struct acpi_table_desc *table_desc; 47995b482a8SLen Brown 480*c418ce19SBob Moore status = acpi_tb_get_next_root_index(table_index); 48195b482a8SLen Brown if (ACPI_FAILURE(status)) { 48295b482a8SLen Brown return (status); 48395b482a8SLen Brown } 484b9ee2043SBob Moore 48595b482a8SLen Brown /* Initialize added table */ 48695b482a8SLen Brown 48786dfc6f3SLv Zheng table_desc = &acpi_gbl_root_table_list.tables[*table_index]; 488ed6f1d44SBob Moore acpi_tb_init_table_descriptor(table_desc, address, flags, table); 48986dfc6f3SLv Zheng table_desc->pointer = table; 490b9ee2043SBob Moore return (AE_OK); 49195b482a8SLen Brown } 49295b482a8SLen Brown 49395b482a8SLen Brown /******************************************************************************* 49495b482a8SLen Brown * 4957f9fc99cSLv Zheng * FUNCTION: acpi_tb_uninstall_table 49695b482a8SLen Brown * 4977f9fc99cSLv Zheng * PARAMETERS: table_desc - Table descriptor 49895b482a8SLen Brown * 49995b482a8SLen Brown * RETURN: None 50095b482a8SLen Brown * 50195b482a8SLen Brown * DESCRIPTION: Delete one internal ACPI table 50295b482a8SLen Brown * 50395b482a8SLen Brown ******************************************************************************/ 50495b482a8SLen Brown 5057f9fc99cSLv Zheng void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc) 50695b482a8SLen Brown { 5075582982dSLv Zheng 5087f9fc99cSLv Zheng ACPI_FUNCTION_TRACE(tb_uninstall_table); 5095582982dSLv Zheng 5107f9fc99cSLv Zheng /* Table must be installed */ 5117f9fc99cSLv Zheng 5127f9fc99cSLv Zheng if (!table_desc->address) { 5137f9fc99cSLv Zheng return_VOID; 51495b482a8SLen Brown } 5155582982dSLv Zheng 5167f9fc99cSLv Zheng acpi_tb_invalidate_table(table_desc); 5171d1ea1b7SChao Guan 5187f9fc99cSLv Zheng if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == 519ed6f1d44SBob Moore ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) { 5207f9fc99cSLv Zheng ACPI_FREE(ACPI_CAST_PTR(void, table_desc->address)); 5217f9fc99cSLv Zheng } 5221d1ea1b7SChao Guan 523dc156adfSLv Zheng table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL); 5247f9fc99cSLv Zheng return_VOID; 52595b482a8SLen Brown } 526