xref: /openbmc/linux/drivers/acpi/acpica/tbinstal.c (revision c418ce19030f8cd9304b4e97c8e0dd580a81ace5)
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