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