xref: /openbmc/linux/drivers/acpi/acpica/tbinstal.c (revision caf4a15c5f930aae41951b4916289e3e59dda8eb)
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 "acnamesp.h"
47e2f7a777SLen Brown #include "actables.h"
4895b482a8SLen Brown 
4995b482a8SLen Brown #define _COMPONENT          ACPI_TABLES
5095b482a8SLen Brown ACPI_MODULE_NAME("tbinstal")
5195b482a8SLen Brown 
5286dfc6f3SLv Zheng /* Local prototypes */
5386dfc6f3SLv Zheng static acpi_status
5486dfc6f3SLv Zheng acpi_tb_acquire_temporal_table(struct acpi_table_desc *table_desc,
5586dfc6f3SLv Zheng 			       acpi_physical_address address, u8 flags);
5686dfc6f3SLv Zheng 
5786dfc6f3SLv Zheng static void acpi_tb_release_temporal_table(struct acpi_table_desc *table_desc);
5886dfc6f3SLv Zheng 
5986dfc6f3SLv Zheng static acpi_status acpi_tb_acquire_root_table_entry(u32 *table_index);
6086dfc6f3SLv Zheng 
6186dfc6f3SLv Zheng static u8
6286dfc6f3SLv Zheng acpi_tb_is_equivalent_table(struct acpi_table_desc *table_desc,
6386dfc6f3SLv Zheng 			    u32 table_index);
6486dfc6f3SLv Zheng 
657f9fc99cSLv Zheng /*******************************************************************************
6695b482a8SLen Brown  *
677f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_acquire_table
6895b482a8SLen Brown  *
697f9fc99cSLv Zheng  * PARAMETERS:  table_desc          - Table descriptor
707f9fc99cSLv Zheng  *              table_ptr           - Where table is returned
717f9fc99cSLv Zheng  *              table_length        - Where table length is returned
727f9fc99cSLv Zheng  *              table_flags         - Where table allocation flags are returned
7395b482a8SLen Brown  *
7495b482a8SLen Brown  * RETURN:      Status
7595b482a8SLen Brown  *
767f9fc99cSLv Zheng  * DESCRIPTION: Acquire a table. It can be used for tables not maintained in
777f9fc99cSLv Zheng  *              acpi_gbl_root_table_list.
7895b482a8SLen Brown  *
797f9fc99cSLv Zheng  ******************************************************************************/
8086dfc6f3SLv Zheng 
817f9fc99cSLv Zheng acpi_status
827f9fc99cSLv Zheng acpi_tb_acquire_table(struct acpi_table_desc *table_desc,
837f9fc99cSLv Zheng 		      struct acpi_table_header **table_ptr,
847f9fc99cSLv Zheng 		      u32 *table_length, u8 *table_flags)
8595b482a8SLen Brown {
867f9fc99cSLv Zheng 	struct acpi_table_header *table = NULL;
8795b482a8SLen Brown 
88dc156adfSLv Zheng 	switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
898a216d7fSLv Zheng 	case ACPI_TABLE_ORIGIN_INTERN_PHYSICAL:
90dc156adfSLv Zheng 
917f9fc99cSLv Zheng 		table =
927f9fc99cSLv Zheng 		    acpi_os_map_memory(table_desc->address, table_desc->length);
93dc156adfSLv Zheng 		break;
94dc156adfSLv Zheng 
958a216d7fSLv Zheng 	case ACPI_TABLE_ORIGIN_INTERN_VIRTUAL:
968a216d7fSLv Zheng 	case ACPI_TABLE_ORIGIN_EXTERN_VIRTUAL:
97dc156adfSLv Zheng 
987f9fc99cSLv Zheng 		table =
99dc156adfSLv Zheng 		    ACPI_CAST_PTR(struct acpi_table_header,
100dc156adfSLv Zheng 				  table_desc->address);
101dc156adfSLv Zheng 		break;
102dc156adfSLv Zheng 
103dc156adfSLv Zheng 	default:
104dc156adfSLv Zheng 
105dc156adfSLv Zheng 		break;
10695b482a8SLen Brown 	}
1075582982dSLv Zheng 
1087f9fc99cSLv Zheng 	/* Table is not valid yet */
1097f9fc99cSLv Zheng 
1107f9fc99cSLv Zheng 	if (!table) {
1117f9fc99cSLv Zheng 		return (AE_NO_MEMORY);
1127f9fc99cSLv Zheng 	}
1137f9fc99cSLv Zheng 
1147f9fc99cSLv Zheng 	/* Fill the return values */
1157f9fc99cSLv Zheng 
1167f9fc99cSLv Zheng 	*table_ptr = table;
1177f9fc99cSLv Zheng 	*table_length = table_desc->length;
1187f9fc99cSLv Zheng 	*table_flags = table_desc->flags;
1197f9fc99cSLv Zheng 
1207f9fc99cSLv Zheng 	return (AE_OK);
1217f9fc99cSLv Zheng }
1227f9fc99cSLv Zheng 
1237f9fc99cSLv Zheng /*******************************************************************************
1247f9fc99cSLv Zheng  *
1257f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_release_table
1267f9fc99cSLv Zheng  *
1277f9fc99cSLv Zheng  * PARAMETERS:  table               - Pointer for the table
1287f9fc99cSLv Zheng  *              table_length        - Length for the table
1297f9fc99cSLv Zheng  *              table_flags         - Allocation flags for the table
1307f9fc99cSLv Zheng  *
1317f9fc99cSLv Zheng  * RETURN:      None
1327f9fc99cSLv Zheng  *
1337f9fc99cSLv Zheng  * DESCRIPTION: Release a table. The reversal of acpi_tb_acquire_table().
1347f9fc99cSLv Zheng  *
1357f9fc99cSLv Zheng  ******************************************************************************/
1367f9fc99cSLv Zheng 
1377f9fc99cSLv Zheng void
1387f9fc99cSLv Zheng acpi_tb_release_table(struct acpi_table_header *table,
1397f9fc99cSLv Zheng 		      u32 table_length, u8 table_flags)
1407f9fc99cSLv Zheng {
1417f9fc99cSLv Zheng 	switch (table_flags & ACPI_TABLE_ORIGIN_MASK) {
1428a216d7fSLv Zheng 	case ACPI_TABLE_ORIGIN_INTERN_PHYSICAL:
1437f9fc99cSLv Zheng 
1447f9fc99cSLv Zheng 		acpi_os_unmap_memory(table, table_length);
1457f9fc99cSLv Zheng 		break;
1467f9fc99cSLv Zheng 
1478a216d7fSLv Zheng 	case ACPI_TABLE_ORIGIN_INTERN_VIRTUAL:
1488a216d7fSLv Zheng 	case ACPI_TABLE_ORIGIN_EXTERN_VIRTUAL:
1497f9fc99cSLv Zheng 	default:
1507f9fc99cSLv Zheng 
1517f9fc99cSLv Zheng 		break;
1527f9fc99cSLv Zheng 	}
1537f9fc99cSLv Zheng }
1547f9fc99cSLv Zheng 
1557f9fc99cSLv Zheng /******************************************************************************
1567f9fc99cSLv Zheng  *
1577f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_validate_table
1587f9fc99cSLv Zheng  *
1597f9fc99cSLv Zheng  * PARAMETERS:  table_desc          - Table descriptor
1607f9fc99cSLv Zheng  *
1617f9fc99cSLv Zheng  * RETURN:      Status
1627f9fc99cSLv Zheng  *
16386dfc6f3SLv Zheng  * DESCRIPTION: This function is called to validate the table, the returned
16486dfc6f3SLv Zheng  *              table descriptor is in "VALIDATED" state.
1657f9fc99cSLv Zheng  *
1667f9fc99cSLv Zheng  *****************************************************************************/
1677f9fc99cSLv Zheng 
1687f9fc99cSLv Zheng acpi_status acpi_tb_validate_table(struct acpi_table_desc *table_desc)
1697f9fc99cSLv Zheng {
1707f9fc99cSLv Zheng 	acpi_status status = AE_OK;
1717f9fc99cSLv Zheng 
1727f9fc99cSLv Zheng 	ACPI_FUNCTION_TRACE(tb_validate_table);
1737f9fc99cSLv Zheng 
1747f9fc99cSLv Zheng 	/* Validate the table if necessary */
1757f9fc99cSLv Zheng 
17695b482a8SLen Brown 	if (!table_desc->pointer) {
1777f9fc99cSLv Zheng 		status = acpi_tb_acquire_table(table_desc, &table_desc->pointer,
1787f9fc99cSLv Zheng 					       &table_desc->length,
1797f9fc99cSLv Zheng 					       &table_desc->flags);
18086dfc6f3SLv Zheng 		if (!table_desc->pointer) {
18186dfc6f3SLv Zheng 			status = AE_NO_MEMORY;
18295b482a8SLen Brown 		}
18395b482a8SLen Brown 	}
18495b482a8SLen Brown 
18595b482a8SLen Brown 	return_ACPI_STATUS(status);
18695b482a8SLen Brown }
18795b482a8SLen Brown 
18895b482a8SLen Brown /*******************************************************************************
18995b482a8SLen Brown  *
1907f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_invalidate_table
1917f9fc99cSLv Zheng  *
1927f9fc99cSLv Zheng  * PARAMETERS:  table_desc          - Table descriptor
1937f9fc99cSLv Zheng  *
1947f9fc99cSLv Zheng  * RETURN:      None
1957f9fc99cSLv Zheng  *
1967f9fc99cSLv Zheng  * DESCRIPTION: Invalidate one internal ACPI table, this is reversal of
1977f9fc99cSLv Zheng  *              acpi_tb_validate_table().
1987f9fc99cSLv Zheng  *
1997f9fc99cSLv Zheng  ******************************************************************************/
2007f9fc99cSLv Zheng 
2017f9fc99cSLv Zheng void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc)
2027f9fc99cSLv Zheng {
2037f9fc99cSLv Zheng 
2047f9fc99cSLv Zheng 	ACPI_FUNCTION_TRACE(tb_invalidate_table);
2057f9fc99cSLv Zheng 
2067f9fc99cSLv Zheng 	/* Table must be validated */
2077f9fc99cSLv Zheng 
2087f9fc99cSLv Zheng 	if (!table_desc->pointer) {
2097f9fc99cSLv Zheng 		return_VOID;
2107f9fc99cSLv Zheng 	}
2117f9fc99cSLv Zheng 
2127f9fc99cSLv Zheng 	acpi_tb_release_table(table_desc->pointer, table_desc->length,
2137f9fc99cSLv Zheng 			      table_desc->flags);
2147f9fc99cSLv Zheng 	table_desc->pointer = NULL;
2157f9fc99cSLv Zheng 
2167f9fc99cSLv Zheng 	return_VOID;
2177f9fc99cSLv Zheng }
2187f9fc99cSLv Zheng 
21986dfc6f3SLv Zheng /******************************************************************************
2207f9fc99cSLv Zheng  *
22186dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_verify_table
22295b482a8SLen Brown  *
22395b482a8SLen Brown  * PARAMETERS:  table_desc          - Table descriptor
22486dfc6f3SLv Zheng  *              signature           - Table signature to verify
22595b482a8SLen Brown  *
22695b482a8SLen Brown  * RETURN:      Status
22795b482a8SLen Brown  *
22886dfc6f3SLv Zheng  * DESCRIPTION: This function is called to validate and verify the table, the
22986dfc6f3SLv Zheng  *              returned table descriptor is in "VALIDATED" state.
23086dfc6f3SLv Zheng  *
23186dfc6f3SLv Zheng  *****************************************************************************/
23286dfc6f3SLv Zheng 
23386dfc6f3SLv Zheng acpi_status
23486dfc6f3SLv Zheng acpi_tb_verify_table(struct acpi_table_desc *table_desc, char *signature)
23586dfc6f3SLv Zheng {
23686dfc6f3SLv Zheng 	acpi_status status = AE_OK;
23786dfc6f3SLv Zheng 
23886dfc6f3SLv Zheng 	ACPI_FUNCTION_TRACE(tb_verify_table);
23986dfc6f3SLv Zheng 
24086dfc6f3SLv Zheng 	/* Validate the table */
24186dfc6f3SLv Zheng 
24286dfc6f3SLv Zheng 	status = acpi_tb_validate_table(table_desc);
24386dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
24486dfc6f3SLv Zheng 		return_ACPI_STATUS(AE_NO_MEMORY);
24586dfc6f3SLv Zheng 	}
24686dfc6f3SLv Zheng 
24786dfc6f3SLv Zheng 	/* If a particular signature is expected (DSDT/FACS), it must match */
24886dfc6f3SLv Zheng 
24986dfc6f3SLv Zheng 	if (signature && !ACPI_COMPARE_NAME(&table_desc->signature, signature)) {
25086dfc6f3SLv Zheng 		ACPI_BIOS_ERROR((AE_INFO,
25186dfc6f3SLv Zheng 				 "Invalid signature 0x%X for ACPI table, expected [%s]",
25286dfc6f3SLv Zheng 				 table_desc->signature.integer, signature));
25386dfc6f3SLv Zheng 		status = AE_BAD_SIGNATURE;
25486dfc6f3SLv Zheng 		goto invalidate_and_exit;
25586dfc6f3SLv Zheng 	}
25686dfc6f3SLv Zheng 
25786dfc6f3SLv Zheng 	/* Verify the checksum */
25886dfc6f3SLv Zheng 
25986dfc6f3SLv Zheng 	status =
26086dfc6f3SLv Zheng 	    acpi_tb_verify_checksum(table_desc->pointer, table_desc->length);
26186dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
26286dfc6f3SLv Zheng 		ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
26386dfc6f3SLv Zheng 				"%4.4s " ACPI_PRINTF_UINT
26486dfc6f3SLv Zheng 				" Attempted table install failed",
26586dfc6f3SLv Zheng 				acpi_ut_valid_acpi_name(table_desc->signature.
26686dfc6f3SLv Zheng 							ascii) ? table_desc->
26786dfc6f3SLv Zheng 				signature.ascii : "????",
26886dfc6f3SLv Zheng 				ACPI_FORMAT_TO_UINT(table_desc->address)));
26986dfc6f3SLv Zheng 		goto invalidate_and_exit;
27086dfc6f3SLv Zheng 	}
27186dfc6f3SLv Zheng 
27286dfc6f3SLv Zheng 	return_ACPI_STATUS(AE_OK);
27386dfc6f3SLv Zheng 
27486dfc6f3SLv Zheng invalidate_and_exit:
27586dfc6f3SLv Zheng 	acpi_tb_invalidate_table(table_desc);
27686dfc6f3SLv Zheng 	return_ACPI_STATUS(status);
27786dfc6f3SLv Zheng }
27886dfc6f3SLv Zheng 
27986dfc6f3SLv Zheng /*******************************************************************************
28086dfc6f3SLv Zheng  *
28186dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_install_table
28286dfc6f3SLv Zheng  *
28386dfc6f3SLv Zheng  * PARAMETERS:  table_desc              - Table descriptor
28486dfc6f3SLv Zheng  *              address                 - Physical address of the table
28586dfc6f3SLv Zheng  *              flags                   - Allocation flags of the table
28686dfc6f3SLv Zheng  *              table                   - Pointer to the table
28786dfc6f3SLv Zheng  *
28886dfc6f3SLv Zheng  * RETURN:      None
28986dfc6f3SLv Zheng  *
29086dfc6f3SLv Zheng  * DESCRIPTION: Install an ACPI table into the global data structure.
29186dfc6f3SLv Zheng  *
29286dfc6f3SLv Zheng  ******************************************************************************/
29386dfc6f3SLv Zheng 
29486dfc6f3SLv Zheng void
29586dfc6f3SLv Zheng acpi_tb_install_table(struct acpi_table_desc *table_desc,
29686dfc6f3SLv Zheng 		      acpi_physical_address address,
29786dfc6f3SLv Zheng 		      u8 flags, struct acpi_table_header *table)
29886dfc6f3SLv Zheng {
29986dfc6f3SLv Zheng 	/*
30086dfc6f3SLv Zheng 	 * Initialize the table entry. Set the pointer to NULL, since the
30186dfc6f3SLv Zheng 	 * table is not fully mapped at this time.
30286dfc6f3SLv Zheng 	 */
30386dfc6f3SLv Zheng 	ACPI_MEMSET(table_desc, 0, sizeof(struct acpi_table_desc));
30486dfc6f3SLv Zheng 	table_desc->address = address;
30586dfc6f3SLv Zheng 	table_desc->length = table->length;
30686dfc6f3SLv Zheng 	table_desc->flags = flags;
30786dfc6f3SLv Zheng 	ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature);
30886dfc6f3SLv Zheng }
30986dfc6f3SLv Zheng 
31086dfc6f3SLv Zheng /*******************************************************************************
31186dfc6f3SLv Zheng  *
31286dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_acquire_temporal_table
31386dfc6f3SLv Zheng  *
31486dfc6f3SLv Zheng  * PARAMETERS:  table_desc          - Table descriptor to be acquired
31586dfc6f3SLv Zheng  *              address             - Address of the table
31686dfc6f3SLv Zheng  *              flags               - Allocation flags of the table
31786dfc6f3SLv Zheng  *
31886dfc6f3SLv Zheng  * RETURN:      Status
31986dfc6f3SLv Zheng  *
32086dfc6f3SLv Zheng  * DESCRIPTION: This function validates the table header to obtain the length
32186dfc6f3SLv Zheng  *              of a table and fills the table descriptor to make its state as
32286dfc6f3SLv Zheng  *              "INSTALLED".  Such table descriptor is only used for verified
32386dfc6f3SLv Zheng  *              installation.
32486dfc6f3SLv Zheng  *
32586dfc6f3SLv Zheng  ******************************************************************************/
32686dfc6f3SLv Zheng 
32786dfc6f3SLv Zheng static acpi_status
32886dfc6f3SLv Zheng acpi_tb_acquire_temporal_table(struct acpi_table_desc *table_desc,
32986dfc6f3SLv Zheng 			       acpi_physical_address address, u8 flags)
33086dfc6f3SLv Zheng {
33186dfc6f3SLv Zheng 	struct acpi_table_header *table_header;
33286dfc6f3SLv Zheng 
33386dfc6f3SLv Zheng 	switch (flags & ACPI_TABLE_ORIGIN_MASK) {
3348a216d7fSLv Zheng 	case ACPI_TABLE_ORIGIN_INTERN_PHYSICAL:
33586dfc6f3SLv Zheng 
33686dfc6f3SLv Zheng 		/* Try to obtain the length of the table */
33786dfc6f3SLv Zheng 
33886dfc6f3SLv Zheng 		table_header =
33986dfc6f3SLv Zheng 		    acpi_os_map_memory(address,
34086dfc6f3SLv Zheng 				       sizeof(struct acpi_table_header));
34186dfc6f3SLv Zheng 		if (!table_header) {
34286dfc6f3SLv Zheng 			return (AE_NO_MEMORY);
34386dfc6f3SLv Zheng 		}
34486dfc6f3SLv Zheng 		acpi_tb_install_table(table_desc, address, flags, table_header);
34586dfc6f3SLv Zheng 		acpi_os_unmap_memory(table_header,
34686dfc6f3SLv Zheng 				     sizeof(struct acpi_table_header));
34786dfc6f3SLv Zheng 		return (AE_OK);
34886dfc6f3SLv Zheng 
3498a216d7fSLv Zheng 	case ACPI_TABLE_ORIGIN_INTERN_VIRTUAL:
3508a216d7fSLv Zheng 	case ACPI_TABLE_ORIGIN_EXTERN_VIRTUAL:
35186dfc6f3SLv Zheng 
35286dfc6f3SLv Zheng 		table_header = ACPI_CAST_PTR(struct acpi_table_header, address);
35386dfc6f3SLv Zheng 		if (!table_header) {
35486dfc6f3SLv Zheng 			return (AE_NO_MEMORY);
35586dfc6f3SLv Zheng 		}
35686dfc6f3SLv Zheng 		acpi_tb_install_table(table_desc, address, flags, table_header);
35786dfc6f3SLv Zheng 		return (AE_OK);
35886dfc6f3SLv Zheng 
35986dfc6f3SLv Zheng 	default:
36086dfc6f3SLv Zheng 
36186dfc6f3SLv Zheng 		break;
36286dfc6f3SLv Zheng 	}
36386dfc6f3SLv Zheng 
36486dfc6f3SLv Zheng 	/* Table is not valid yet */
36586dfc6f3SLv Zheng 
36686dfc6f3SLv Zheng 	return (AE_NO_MEMORY);
36786dfc6f3SLv Zheng }
36886dfc6f3SLv Zheng 
36986dfc6f3SLv Zheng /*******************************************************************************
37086dfc6f3SLv Zheng  *
37186dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_release_temporal_table
37286dfc6f3SLv Zheng  *
37386dfc6f3SLv Zheng  * PARAMETERS:  table_desc          - Table descriptor to be released
37486dfc6f3SLv Zheng  *
37586dfc6f3SLv Zheng  * RETURN:      Status
37686dfc6f3SLv Zheng  *
37786dfc6f3SLv Zheng  * DESCRIPTION: The reversal of acpi_tb_acquire_temporal_table().
37886dfc6f3SLv Zheng  *
37986dfc6f3SLv Zheng  ******************************************************************************/
38086dfc6f3SLv Zheng 
38186dfc6f3SLv Zheng static void acpi_tb_release_temporal_table(struct acpi_table_desc *table_desc)
38286dfc6f3SLv Zheng {
38386dfc6f3SLv Zheng 	/*
38486dfc6f3SLv Zheng 	 * Note that the .Address is maintained by the callers of
38586dfc6f3SLv Zheng 	 * acpi_tb_acquire_temporal_table(), thus do not invoke acpi_tb_uninstall_table()
38686dfc6f3SLv Zheng 	 * where .Address will be freed.
38786dfc6f3SLv Zheng 	 */
38886dfc6f3SLv Zheng 	acpi_tb_invalidate_table(table_desc);
38986dfc6f3SLv Zheng }
39086dfc6f3SLv Zheng 
39186dfc6f3SLv Zheng /*******************************************************************************
39286dfc6f3SLv Zheng  *
39386dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_install_and_override_table
39486dfc6f3SLv Zheng  *
39586dfc6f3SLv Zheng  * PARAMETERS:  table_index             - Index into root table array
39686dfc6f3SLv Zheng  *              new_table_desc          - New table descriptor to install
397*caf4a15cSLv Zheng  *              override                - Whether override should be performed
39886dfc6f3SLv Zheng  *
39986dfc6f3SLv Zheng  * RETURN:      None
40086dfc6f3SLv Zheng  *
40186dfc6f3SLv Zheng  * DESCRIPTION: Install an ACPI table into the global data structure. The
40286dfc6f3SLv Zheng  *              table override mechanism is called to allow the host
40386dfc6f3SLv Zheng  *              OS to replace any table before it is installed in the root
40486dfc6f3SLv Zheng  *              table array.
40586dfc6f3SLv Zheng  *
40686dfc6f3SLv Zheng  ******************************************************************************/
40786dfc6f3SLv Zheng 
40886dfc6f3SLv Zheng void
40986dfc6f3SLv Zheng acpi_tb_install_and_override_table(u32 table_index,
410*caf4a15cSLv Zheng 				   struct acpi_table_desc *new_table_desc,
411*caf4a15cSLv Zheng 				   u8 override)
41286dfc6f3SLv Zheng {
41386dfc6f3SLv Zheng 	if (table_index >= acpi_gbl_root_table_list.current_table_count) {
41486dfc6f3SLv Zheng 		return;
41586dfc6f3SLv Zheng 	}
41686dfc6f3SLv Zheng 
41786dfc6f3SLv Zheng 	/*
41886dfc6f3SLv Zheng 	 * ACPI Table Override:
41986dfc6f3SLv Zheng 	 *
42086dfc6f3SLv Zheng 	 * Before we install the table, let the host OS override it with a new
42186dfc6f3SLv Zheng 	 * one if desired. Any table within the RSDT/XSDT can be replaced,
42286dfc6f3SLv Zheng 	 * including the DSDT which is pointed to by the FADT.
42386dfc6f3SLv Zheng 	 */
424*caf4a15cSLv Zheng 	if (override) {
42586dfc6f3SLv Zheng 		acpi_tb_override_table(new_table_desc);
426*caf4a15cSLv Zheng 	}
42786dfc6f3SLv Zheng 
42886dfc6f3SLv Zheng 	acpi_tb_install_table(&acpi_gbl_root_table_list.tables[table_index],
42986dfc6f3SLv Zheng 			      new_table_desc->address, new_table_desc->flags,
43086dfc6f3SLv Zheng 			      new_table_desc->pointer);
43186dfc6f3SLv Zheng 
43286dfc6f3SLv Zheng 	acpi_tb_print_table_header(new_table_desc->address,
43386dfc6f3SLv Zheng 				   new_table_desc->pointer);
43486dfc6f3SLv Zheng 
43586dfc6f3SLv Zheng 	/* Set the global integer width (based upon revision of the DSDT) */
43686dfc6f3SLv Zheng 
43786dfc6f3SLv Zheng 	if (table_index == ACPI_TABLE_INDEX_DSDT) {
43886dfc6f3SLv Zheng 		acpi_ut_set_integer_width(new_table_desc->pointer->revision);
43986dfc6f3SLv Zheng 	}
44086dfc6f3SLv Zheng }
44186dfc6f3SLv Zheng 
44286dfc6f3SLv Zheng /*******************************************************************************
44386dfc6f3SLv Zheng  *
44486dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_install_fixed_table
44586dfc6f3SLv Zheng  *
44686dfc6f3SLv Zheng  * PARAMETERS:  address                 - Physical address of DSDT or FACS
44786dfc6f3SLv Zheng  *              signature               - Table signature, NULL if no need to
44886dfc6f3SLv Zheng  *                                        match
44986dfc6f3SLv Zheng  *              table_index             - Index into root table array
45086dfc6f3SLv Zheng  *
45186dfc6f3SLv Zheng  * RETURN:      Status
45286dfc6f3SLv Zheng  *
45386dfc6f3SLv Zheng  * DESCRIPTION: Install a fixed ACPI table (DSDT/FACS) into the global data
45486dfc6f3SLv Zheng  *              structure.
45595b482a8SLen Brown  *
45695b482a8SLen Brown  ******************************************************************************/
45795b482a8SLen Brown 
45895b482a8SLen Brown acpi_status
45986dfc6f3SLv Zheng acpi_tb_install_fixed_table(acpi_physical_address address,
46086dfc6f3SLv Zheng 			    char *signature, u32 table_index)
46186dfc6f3SLv Zheng {
46286dfc6f3SLv Zheng 	struct acpi_table_desc new_table_desc;
46386dfc6f3SLv Zheng 	acpi_status status;
46486dfc6f3SLv Zheng 
46586dfc6f3SLv Zheng 	ACPI_FUNCTION_TRACE(tb_install_fixed_table);
46686dfc6f3SLv Zheng 
46786dfc6f3SLv Zheng 	if (!address) {
46886dfc6f3SLv Zheng 		ACPI_ERROR((AE_INFO,
46986dfc6f3SLv Zheng 			    "Null physical address for ACPI table [%s]",
47086dfc6f3SLv Zheng 			    signature));
47186dfc6f3SLv Zheng 		return (AE_NO_MEMORY);
47286dfc6f3SLv Zheng 	}
47386dfc6f3SLv Zheng 
47486dfc6f3SLv Zheng 	/* Fill a table descriptor for validation */
47586dfc6f3SLv Zheng 
47686dfc6f3SLv Zheng 	status = acpi_tb_acquire_temporal_table(&new_table_desc, address,
4778a216d7fSLv Zheng 						ACPI_TABLE_ORIGIN_INTERN_PHYSICAL);
47886dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
47986dfc6f3SLv Zheng 		ACPI_ERROR((AE_INFO, "Could not acquire table length at %p",
48086dfc6f3SLv Zheng 			    ACPI_CAST_PTR(void, address)));
48186dfc6f3SLv Zheng 		return_ACPI_STATUS(status);
48286dfc6f3SLv Zheng 	}
48386dfc6f3SLv Zheng 
48486dfc6f3SLv Zheng 	/* Validate and verify a table before installation */
48586dfc6f3SLv Zheng 
48686dfc6f3SLv Zheng 	status = acpi_tb_verify_table(&new_table_desc, signature);
48786dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
48886dfc6f3SLv Zheng 		goto release_and_exit;
48986dfc6f3SLv Zheng 	}
49086dfc6f3SLv Zheng 
491*caf4a15cSLv Zheng 	acpi_tb_install_and_override_table(table_index, &new_table_desc, TRUE);
49286dfc6f3SLv Zheng 
49386dfc6f3SLv Zheng release_and_exit:
49486dfc6f3SLv Zheng 
49586dfc6f3SLv Zheng 	/* Release the temporal table descriptor */
49686dfc6f3SLv Zheng 
49786dfc6f3SLv Zheng 	acpi_tb_release_temporal_table(&new_table_desc);
49886dfc6f3SLv Zheng 	return_ACPI_STATUS(status);
49986dfc6f3SLv Zheng }
50086dfc6f3SLv Zheng 
50186dfc6f3SLv Zheng /*******************************************************************************
50286dfc6f3SLv Zheng  *
50386dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_is_equivalent_table
50486dfc6f3SLv Zheng  *
50586dfc6f3SLv Zheng  * PARAMETERS:  table_desc          - Table 1 descriptor to be compared
50686dfc6f3SLv Zheng  *              table_index         - Index of table 2 to be compared
50786dfc6f3SLv Zheng  *
50886dfc6f3SLv Zheng  * RETURN:      TRUE if 2 tables are equivalent
50986dfc6f3SLv Zheng  *
51086dfc6f3SLv Zheng  * DESCRIPTION: This function is called to compare a table with what have
51186dfc6f3SLv Zheng  *              already been installed in the root table list.
51286dfc6f3SLv Zheng  *
51386dfc6f3SLv Zheng  ******************************************************************************/
51486dfc6f3SLv Zheng 
51586dfc6f3SLv Zheng static u8
51686dfc6f3SLv Zheng acpi_tb_is_equivalent_table(struct acpi_table_desc *table_desc, u32 table_index)
51786dfc6f3SLv Zheng {
51886dfc6f3SLv Zheng 	acpi_status status = AE_OK;
51986dfc6f3SLv Zheng 	u8 is_equivalent;
52086dfc6f3SLv Zheng 	struct acpi_table_header *table;
52186dfc6f3SLv Zheng 	u32 table_length;
52286dfc6f3SLv Zheng 	u8 table_flags;
52386dfc6f3SLv Zheng 
52486dfc6f3SLv Zheng 	status =
52586dfc6f3SLv Zheng 	    acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index],
52686dfc6f3SLv Zheng 				  &table, &table_length, &table_flags);
52786dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
52886dfc6f3SLv Zheng 		return (FALSE);
52986dfc6f3SLv Zheng 	}
53086dfc6f3SLv Zheng 
53186dfc6f3SLv Zheng 	/*
53286dfc6f3SLv Zheng 	 * Check for a table match on the entire table length,
53386dfc6f3SLv Zheng 	 * not just the header.
53486dfc6f3SLv Zheng 	 */
53586dfc6f3SLv Zheng 	is_equivalent = (u8)((table_desc->length != table_length ||
53686dfc6f3SLv Zheng 			      ACPI_MEMCMP(table_desc->pointer, table,
53786dfc6f3SLv Zheng 					  table_length)) ? FALSE : TRUE);
53886dfc6f3SLv Zheng 
53986dfc6f3SLv Zheng 	/* Release the acquired table */
54086dfc6f3SLv Zheng 
54186dfc6f3SLv Zheng 	acpi_tb_release_table(table, table_length, table_flags);
54286dfc6f3SLv Zheng 
54386dfc6f3SLv Zheng 	return (is_equivalent);
54486dfc6f3SLv Zheng }
54586dfc6f3SLv Zheng 
54686dfc6f3SLv Zheng /*******************************************************************************
54786dfc6f3SLv Zheng  *
54886dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_install_non_fixed_table
54986dfc6f3SLv Zheng  *
5508a216d7fSLv Zheng  * PARAMETERS:  address             - Address of the table (might be a virtual
55186dfc6f3SLv Zheng  *                                    address depending on the table_flags)
55286dfc6f3SLv Zheng  *              flags               - Flags for the table
55386dfc6f3SLv Zheng  *              reload              - Whether reload should be performed
554*caf4a15cSLv Zheng  *              override            - Whether override should be performed
55586dfc6f3SLv Zheng  *              table_index         - Where the table index is returned
55686dfc6f3SLv Zheng  *
55786dfc6f3SLv Zheng  * RETURN:      Status
55886dfc6f3SLv Zheng  *
55986dfc6f3SLv Zheng  * DESCRIPTION: This function is called to install an ACPI table that is
56086dfc6f3SLv Zheng  *              neither DSDT nor FACS.
56186dfc6f3SLv Zheng  *              When this function is called by "Load" or "LoadTable" opcodes,
56286dfc6f3SLv Zheng  *              or by acpi_load_table() API, the "Reload" parameter is set.
56386dfc6f3SLv Zheng  *              After sucessfully returning from this function, table is
56486dfc6f3SLv Zheng  *              "INSTALLED" but not "VALIDATED".
56586dfc6f3SLv Zheng  *
56686dfc6f3SLv Zheng  ******************************************************************************/
56786dfc6f3SLv Zheng 
56886dfc6f3SLv Zheng acpi_status
56986dfc6f3SLv Zheng acpi_tb_install_non_fixed_table(acpi_physical_address address,
570*caf4a15cSLv Zheng 				u8 flags,
571*caf4a15cSLv Zheng 				u8 reload, u8 override, u32 *table_index)
57295b482a8SLen Brown {
57395b482a8SLen Brown 	u32 i;
57495b482a8SLen Brown 	acpi_status status = AE_OK;
57586dfc6f3SLv Zheng 	struct acpi_table_desc new_table_desc;
57695b482a8SLen Brown 
57786dfc6f3SLv Zheng 	ACPI_FUNCTION_TRACE(tb_install_non_fixed_table);
57895b482a8SLen Brown 
57986dfc6f3SLv Zheng 	/* Acquire a temporal table descriptor for validation */
58086dfc6f3SLv Zheng 
58186dfc6f3SLv Zheng 	status =
58286dfc6f3SLv Zheng 	    acpi_tb_acquire_temporal_table(&new_table_desc, address, flags);
58386dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
58486dfc6f3SLv Zheng 		ACPI_ERROR((AE_INFO, "Could not acquire table length at %p",
58586dfc6f3SLv Zheng 			    ACPI_CAST_PTR(void, address)));
58695b482a8SLen Brown 		return_ACPI_STATUS(status);
58795b482a8SLen Brown 	}
58886dfc6f3SLv Zheng 
589a94e88cdSLv Zheng 	/*
590a94e88cdSLv Zheng 	 * Optionally do not load any SSDTs from the RSDT/XSDT. This can
591a94e88cdSLv Zheng 	 * be useful for debugging ACPI problems on some machines.
592a94e88cdSLv Zheng 	 */
593a94e88cdSLv Zheng 	if (!reload && acpi_gbl_disable_ssdt_table_install &&
594a94e88cdSLv Zheng 	    ACPI_COMPARE_NAME(&new_table_desc.signature, ACPI_SIG_SSDT)) {
595a94e88cdSLv Zheng 		ACPI_INFO((AE_INFO, "Ignoring installation of %4.4s at %p",
596a94e88cdSLv Zheng 			   new_table_desc.signature.ascii, ACPI_CAST_PTR(void,
597a94e88cdSLv Zheng 									 address)));
598a94e88cdSLv Zheng 		goto release_and_exit;
599a94e88cdSLv Zheng 	}
600a94e88cdSLv Zheng 
60186dfc6f3SLv Zheng 	/* Validate and verify a table before installation */
60286dfc6f3SLv Zheng 
60386dfc6f3SLv Zheng 	status = acpi_tb_verify_table(&new_table_desc, NULL);
60486dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
60586dfc6f3SLv Zheng 		goto release_and_exit;
60695b482a8SLen Brown 	}
60795b482a8SLen Brown 
60886dfc6f3SLv Zheng 	if (reload) {
60995b482a8SLen Brown 		/*
610c8cefe30SBob Moore 		 * Validate the incoming table signature.
611c8cefe30SBob Moore 		 *
612c8cefe30SBob Moore 		 * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
613c8cefe30SBob Moore 		 * 2) We added support for OEMx tables, signature "OEM".
614c8cefe30SBob Moore 		 * 3) Valid tables were encountered with a null signature, so we just
615c8cefe30SBob Moore 		 *    gave up on validating the signature, (05/2008).
616c8cefe30SBob Moore 		 * 4) We encountered non-AML tables such as the MADT, which caused
617c8cefe30SBob Moore 		 *    interpreter errors and kernel faults. So now, we once again allow
618c8cefe30SBob Moore 		 *    only "SSDT", "OEMx", and now, also a null signature. (05/2011).
61995b482a8SLen Brown 		 */
62086dfc6f3SLv Zheng 		if ((new_table_desc.signature.ascii[0] != 0x00) &&
62186dfc6f3SLv Zheng 		    (!ACPI_COMPARE_NAME
62286dfc6f3SLv Zheng 		     (&new_table_desc.signature, ACPI_SIG_SSDT))
62386dfc6f3SLv Zheng 		    && (ACPI_STRNCMP(new_table_desc.signature.ascii, "OEM", 3)))
62486dfc6f3SLv Zheng 		{
6253b3ea775SBob Moore 			ACPI_BIOS_ERROR((AE_INFO,
6263b3ea775SBob Moore 					 "Table has invalid signature [%4.4s] (0x%8.8X), "
6273b3ea775SBob Moore 					 "must be SSDT or OEMx",
62886dfc6f3SLv Zheng 					 acpi_ut_valid_acpi_name(new_table_desc.
62986dfc6f3SLv Zheng 								 signature.
63086dfc6f3SLv Zheng 								 ascii) ?
63186dfc6f3SLv Zheng 					 new_table_desc.signature.
63286dfc6f3SLv Zheng 					 ascii : "????",
63386dfc6f3SLv Zheng 					 new_table_desc.signature.integer));
634c8cefe30SBob Moore 
63586dfc6f3SLv Zheng 			status = AE_BAD_SIGNATURE;
63686dfc6f3SLv Zheng 			goto release_and_exit;
637c8cefe30SBob Moore 		}
63895b482a8SLen Brown 
63995b482a8SLen Brown 		/* Check if table is already registered */
64095b482a8SLen Brown 
64186dfc6f3SLv Zheng 		for (i = 0; i < acpi_gbl_root_table_list.current_table_count;
64286dfc6f3SLv Zheng 		     ++i) {
64395b482a8SLen Brown 			/*
64495b482a8SLen Brown 			 * Check for a table match on the entire table length,
64595b482a8SLen Brown 			 * not just the header.
64695b482a8SLen Brown 			 */
64786dfc6f3SLv Zheng 			if (!acpi_tb_is_equivalent_table(&new_table_desc, i)) {
64895b482a8SLen Brown 				continue;
64995b482a8SLen Brown 			}
65095b482a8SLen Brown 
65195b482a8SLen Brown 			/*
65295b482a8SLen Brown 			 * Note: the current mechanism does not unregister a table if it is
65395b482a8SLen Brown 			 * dynamically unloaded. The related namespace entries are deleted,
65495b482a8SLen Brown 			 * but the table remains in the root table list.
65595b482a8SLen Brown 			 *
65695b482a8SLen Brown 			 * The assumption here is that the number of different tables that
65795b482a8SLen Brown 			 * will be loaded is actually small, and there is minimal overhead
65895b482a8SLen Brown 			 * in just keeping the table in case it is needed again.
65995b482a8SLen Brown 			 *
66095b482a8SLen Brown 			 * If this assumption changes in the future (perhaps on large
66195b482a8SLen Brown 			 * machines with many table load/unload operations), tables will
66295b482a8SLen Brown 			 * need to be unregistered when they are unloaded, and slots in the
66395b482a8SLen Brown 			 * root table list should be reused when empty.
66495b482a8SLen Brown 			 */
66595b482a8SLen Brown 			if (acpi_gbl_root_table_list.tables[i].
66695b482a8SLen Brown 			    flags & ACPI_TABLE_IS_LOADED) {
66795b482a8SLen Brown 
66895b482a8SLen Brown 				/* Table is still loaded, this is an error */
66995b482a8SLen Brown 
67095b482a8SLen Brown 				status = AE_ALREADY_EXISTS;
67186dfc6f3SLv Zheng 				goto release_and_exit;
67295b482a8SLen Brown 			} else {
673d3ccaff8SBob Moore 				/*
67486dfc6f3SLv Zheng 				 * Table was unloaded, allow it to be reloaded.
67586dfc6f3SLv Zheng 				 * As we are going to return AE_OK to the caller, we should
67686dfc6f3SLv Zheng 				 * take the responsibility of freeing the input descriptor.
67786dfc6f3SLv Zheng 				 * Refill the input descriptor to ensure
67886dfc6f3SLv Zheng 				 * acpi_tb_install_and_override_table() can be called again to
67986dfc6f3SLv Zheng 				 * indicate the re-installation.
680d3ccaff8SBob Moore 				 */
68186dfc6f3SLv Zheng 				acpi_tb_uninstall_table(&new_table_desc);
68286dfc6f3SLv Zheng 				*table_index = i;
68386dfc6f3SLv Zheng 				(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
68486dfc6f3SLv Zheng 				return_ACPI_STATUS(AE_OK);
68586dfc6f3SLv Zheng 			}
68686dfc6f3SLv Zheng 		}
6877f9fc99cSLv Zheng 	}
688d3ccaff8SBob Moore 
68995b482a8SLen Brown 	/* Add the table to the global root table list */
69095b482a8SLen Brown 
69186dfc6f3SLv Zheng 	status = acpi_tb_acquire_root_table_entry(&i);
69295b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
69386dfc6f3SLv Zheng 		goto release_and_exit;
69495b482a8SLen Brown 	}
69586dfc6f3SLv Zheng 	*table_index = i;
696*caf4a15cSLv Zheng 	acpi_tb_install_and_override_table(i, &new_table_desc, override);
69795b482a8SLen Brown 
69886dfc6f3SLv Zheng release_and_exit:
69995b482a8SLen Brown 
70086dfc6f3SLv Zheng 	/* Release the temporal table descriptor */
70186dfc6f3SLv Zheng 
70286dfc6f3SLv Zheng 	acpi_tb_release_temporal_table(&new_table_desc);
70395b482a8SLen Brown 	return_ACPI_STATUS(status);
70495b482a8SLen Brown }
70595b482a8SLen Brown 
70695b482a8SLen Brown /*******************************************************************************
70795b482a8SLen Brown  *
7087f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_override_table
709f7b004a1SBob Moore  *
71086dfc6f3SLv Zheng  * PARAMETERS:  old_table_desc      - Validated table descriptor to be
71186dfc6f3SLv Zheng  *                                    overridden
712f7b004a1SBob Moore  *
71386dfc6f3SLv Zheng  * RETURN:      None
714f7b004a1SBob Moore  *
715f7b004a1SBob Moore  * DESCRIPTION: Attempt table override by calling the OSL override functions.
716f7b004a1SBob Moore  *              Note: If the table is overridden, then the entire new table
7177f9fc99cSLv Zheng  *              is acquired and returned by this function.
71886dfc6f3SLv Zheng  *              Before/after invocation, the table descriptor is in a state
71986dfc6f3SLv Zheng  *              that is "VALIDATED".
720f7b004a1SBob Moore  *
721f7b004a1SBob Moore  ******************************************************************************/
722f7b004a1SBob Moore 
72386dfc6f3SLv Zheng void acpi_tb_override_table(struct acpi_table_desc *old_table_desc)
724f7b004a1SBob Moore {
725f7b004a1SBob Moore 	acpi_status status;
726f7b004a1SBob Moore 	char *override_type;
7277f9fc99cSLv Zheng 	struct acpi_table_desc new_table_desc;
72886dfc6f3SLv Zheng 	struct acpi_table_header *table;
72986dfc6f3SLv Zheng 	acpi_physical_address address;
73086dfc6f3SLv Zheng 	u32 length;
731f7b004a1SBob Moore 
732f7b004a1SBob Moore 	/* (1) Attempt logical override (returns a logical address) */
733f7b004a1SBob Moore 
73486dfc6f3SLv Zheng 	status = acpi_os_table_override(old_table_desc->pointer, &table);
73586dfc6f3SLv Zheng 	if (ACPI_SUCCESS(status) && table) {
73686dfc6f3SLv Zheng 		acpi_tb_acquire_temporal_table(&new_table_desc,
73786dfc6f3SLv Zheng 					       ACPI_PTR_TO_PHYSADDR(table),
7388a216d7fSLv Zheng 					       ACPI_TABLE_ORIGIN_EXTERN_VIRTUAL);
739f7b004a1SBob Moore 		override_type = "Logical";
740f7b004a1SBob Moore 		goto finish_override;
741f7b004a1SBob Moore 	}
742f7b004a1SBob Moore 
743f7b004a1SBob Moore 	/* (2) Attempt physical override (returns a physical address) */
744f7b004a1SBob Moore 
74586dfc6f3SLv Zheng 	status = acpi_os_physical_table_override(old_table_desc->pointer,
74686dfc6f3SLv Zheng 						 &address, &length);
74786dfc6f3SLv Zheng 	if (ACPI_SUCCESS(status) && address && length) {
74886dfc6f3SLv Zheng 		acpi_tb_acquire_temporal_table(&new_table_desc, address,
7498a216d7fSLv Zheng 					       ACPI_TABLE_ORIGIN_INTERN_PHYSICAL);
750f7b004a1SBob Moore 		override_type = "Physical";
751f7b004a1SBob Moore 		goto finish_override;
752f7b004a1SBob Moore 	}
753f7b004a1SBob Moore 
75486dfc6f3SLv Zheng 	return;			/* There was no override */
755f7b004a1SBob Moore 
756f7b004a1SBob Moore finish_override:
757f7b004a1SBob Moore 
75886dfc6f3SLv Zheng 	/* Validate and verify a table before overriding */
75986dfc6f3SLv Zheng 
76086dfc6f3SLv Zheng 	status = acpi_tb_verify_table(&new_table_desc, NULL);
7617f9fc99cSLv Zheng 	if (ACPI_FAILURE(status)) {
76286dfc6f3SLv Zheng 		return;
7637f9fc99cSLv Zheng 	}
7647f9fc99cSLv Zheng 
7652e19f8d0SBob Moore 	ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT
7662e19f8d0SBob Moore 		   " %s table override, new table: " ACPI_PRINTF_UINT,
76786dfc6f3SLv Zheng 		   old_table_desc->signature.ascii,
76886dfc6f3SLv Zheng 		   ACPI_FORMAT_TO_UINT(old_table_desc->address),
7697f9fc99cSLv Zheng 		   override_type, ACPI_FORMAT_TO_UINT(new_table_desc.address)));
770f7b004a1SBob Moore 
77186dfc6f3SLv Zheng 	/* We can now uninstall the original table */
772f7b004a1SBob Moore 
77386dfc6f3SLv Zheng 	acpi_tb_uninstall_table(old_table_desc);
774f7b004a1SBob Moore 
77586dfc6f3SLv Zheng 	/*
77686dfc6f3SLv Zheng 	 * Replace the original table descriptor and keep its state as
77786dfc6f3SLv Zheng 	 * "VALIDATED".
77886dfc6f3SLv Zheng 	 */
77986dfc6f3SLv Zheng 	acpi_tb_install_table(old_table_desc, new_table_desc.address,
78086dfc6f3SLv Zheng 			      new_table_desc.flags, new_table_desc.pointer);
78186dfc6f3SLv Zheng 	acpi_tb_validate_table(old_table_desc);
782f7b004a1SBob Moore 
78386dfc6f3SLv Zheng 	/* Release the temporal table descriptor */
784f7b004a1SBob Moore 
78586dfc6f3SLv Zheng 	acpi_tb_release_temporal_table(&new_table_desc);
786f7b004a1SBob Moore }
787f7b004a1SBob Moore 
788f7b004a1SBob Moore /*******************************************************************************
789f7b004a1SBob Moore  *
79095b482a8SLen Brown  * FUNCTION:    acpi_tb_resize_root_table_list
79195b482a8SLen Brown  *
79295b482a8SLen Brown  * PARAMETERS:  None
79395b482a8SLen Brown  *
79495b482a8SLen Brown  * RETURN:      Status
79595b482a8SLen Brown  *
79695b482a8SLen Brown  * DESCRIPTION: Expand the size of global table array
79795b482a8SLen Brown  *
79895b482a8SLen Brown  ******************************************************************************/
79995b482a8SLen Brown 
80095b482a8SLen Brown acpi_status acpi_tb_resize_root_table_list(void)
80195b482a8SLen Brown {
80295b482a8SLen Brown 	struct acpi_table_desc *tables;
8032bc198c1SLv Zheng 	u32 table_count;
80495b482a8SLen Brown 
80595b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
80695b482a8SLen Brown 
80795b482a8SLen Brown 	/* allow_resize flag is a parameter to acpi_initialize_tables */
80895b482a8SLen Brown 
80995b482a8SLen Brown 	if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) {
81095b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
81195b482a8SLen Brown 			    "Resize of Root Table Array is not allowed"));
81295b482a8SLen Brown 		return_ACPI_STATUS(AE_SUPPORT);
81395b482a8SLen Brown 	}
81495b482a8SLen Brown 
81595b482a8SLen Brown 	/* Increase the Table Array size */
81695b482a8SLen Brown 
8172bc198c1SLv Zheng 	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
8182bc198c1SLv Zheng 		table_count = acpi_gbl_root_table_list.max_table_count;
8192bc198c1SLv Zheng 	} else {
8202bc198c1SLv Zheng 		table_count = acpi_gbl_root_table_list.current_table_count;
8212bc198c1SLv Zheng 	}
8222bc198c1SLv Zheng 
8232bc198c1SLv Zheng 	tables = ACPI_ALLOCATE_ZEROED(((acpi_size) table_count +
824ec41f193SBob Moore 				       ACPI_ROOT_TABLE_SIZE_INCREMENT) *
825ec41f193SBob Moore 				      sizeof(struct acpi_table_desc));
82695b482a8SLen Brown 	if (!tables) {
82795b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
82895b482a8SLen Brown 			    "Could not allocate new root table array"));
82995b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_MEMORY);
83095b482a8SLen Brown 	}
83195b482a8SLen Brown 
83295b482a8SLen Brown 	/* Copy and free the previous table array */
83395b482a8SLen Brown 
83495b482a8SLen Brown 	if (acpi_gbl_root_table_list.tables) {
83595b482a8SLen Brown 		ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
8362bc198c1SLv Zheng 			    (acpi_size) table_count *
8372bc198c1SLv Zheng 			    sizeof(struct acpi_table_desc));
83895b482a8SLen Brown 
83995b482a8SLen Brown 		if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
84095b482a8SLen Brown 			ACPI_FREE(acpi_gbl_root_table_list.tables);
84195b482a8SLen Brown 		}
84295b482a8SLen Brown 	}
84395b482a8SLen Brown 
84495b482a8SLen Brown 	acpi_gbl_root_table_list.tables = tables;
8452bc198c1SLv Zheng 	acpi_gbl_root_table_list.max_table_count =
8462bc198c1SLv Zheng 	    table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT;
8472bc198c1SLv Zheng 	acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
84895b482a8SLen Brown 
84995b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
85095b482a8SLen Brown }
85195b482a8SLen Brown 
85295b482a8SLen Brown /*******************************************************************************
85395b482a8SLen Brown  *
85486dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_acquire_root_table_entry
85586dfc6f3SLv Zheng  *
85686dfc6f3SLv Zheng  * PARAMETERS:  table_index         - Where table index is returned
85786dfc6f3SLv Zheng  *
85886dfc6f3SLv Zheng  * RETURN:      Status and table index.
85986dfc6f3SLv Zheng  *
86086dfc6f3SLv Zheng  * DESCRIPTION: Allocate a new ACPI table entry to the global table list
86186dfc6f3SLv Zheng  *
86286dfc6f3SLv Zheng  ******************************************************************************/
86386dfc6f3SLv Zheng 
86486dfc6f3SLv Zheng static acpi_status acpi_tb_acquire_root_table_entry(u32 *table_index)
86586dfc6f3SLv Zheng {
86686dfc6f3SLv Zheng 	acpi_status status;
86786dfc6f3SLv Zheng 
86886dfc6f3SLv Zheng 	/* Ensure that there is room for the table in the Root Table List */
86986dfc6f3SLv Zheng 
87086dfc6f3SLv Zheng 	if (acpi_gbl_root_table_list.current_table_count >=
87186dfc6f3SLv Zheng 	    acpi_gbl_root_table_list.max_table_count) {
87286dfc6f3SLv Zheng 		status = acpi_tb_resize_root_table_list();
87386dfc6f3SLv Zheng 		if (ACPI_FAILURE(status)) {
87486dfc6f3SLv Zheng 			return (status);
87586dfc6f3SLv Zheng 		}
87686dfc6f3SLv Zheng 	}
87786dfc6f3SLv Zheng 
87886dfc6f3SLv Zheng 	*table_index = acpi_gbl_root_table_list.current_table_count;
87986dfc6f3SLv Zheng 	acpi_gbl_root_table_list.current_table_count++;
88086dfc6f3SLv Zheng 	return (AE_OK);
88186dfc6f3SLv Zheng }
88286dfc6f3SLv Zheng 
88386dfc6f3SLv Zheng /*******************************************************************************
88486dfc6f3SLv Zheng  *
88595b482a8SLen Brown  * FUNCTION:    acpi_tb_store_table
88695b482a8SLen Brown  *
887ba494beeSBob Moore  * PARAMETERS:  address             - Table address
888ba494beeSBob Moore  *              table               - Table header
889ba494beeSBob Moore  *              length              - Table length
890ba494beeSBob Moore  *              flags               - flags
89195b482a8SLen Brown  *
89295b482a8SLen Brown  * RETURN:      Status and table index.
89395b482a8SLen Brown  *
89495b482a8SLen Brown  * DESCRIPTION: Add an ACPI table to the global table list
89595b482a8SLen Brown  *
89695b482a8SLen Brown  ******************************************************************************/
89795b482a8SLen Brown 
89895b482a8SLen Brown acpi_status
89995b482a8SLen Brown acpi_tb_store_table(acpi_physical_address address,
90095b482a8SLen Brown 		    struct acpi_table_header * table,
90195b482a8SLen Brown 		    u32 length, u8 flags, u32 *table_index)
90295b482a8SLen Brown {
903b9ee2043SBob Moore 	acpi_status status;
90486dfc6f3SLv Zheng 	struct acpi_table_desc *table_desc;
90595b482a8SLen Brown 
90686dfc6f3SLv Zheng 	status = acpi_tb_acquire_root_table_entry(table_index);
90795b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
90895b482a8SLen Brown 		return (status);
90995b482a8SLen Brown 	}
910b9ee2043SBob Moore 
91195b482a8SLen Brown 	/* Initialize added table */
91295b482a8SLen Brown 
91386dfc6f3SLv Zheng 	table_desc = &acpi_gbl_root_table_list.tables[*table_index];
91486dfc6f3SLv Zheng 	acpi_tb_install_table(table_desc, address, flags, table);
91586dfc6f3SLv Zheng 	table_desc->pointer = table;
91695b482a8SLen Brown 
917b9ee2043SBob Moore 	return (AE_OK);
91895b482a8SLen Brown }
91995b482a8SLen Brown 
92095b482a8SLen Brown /*******************************************************************************
92195b482a8SLen Brown  *
9227f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_uninstall_table
92395b482a8SLen Brown  *
9247f9fc99cSLv Zheng  * PARAMETERS:  table_desc          - Table descriptor
92595b482a8SLen Brown  *
92695b482a8SLen Brown  * RETURN:      None
92795b482a8SLen Brown  *
92895b482a8SLen Brown  * DESCRIPTION: Delete one internal ACPI table
92995b482a8SLen Brown  *
93095b482a8SLen Brown  ******************************************************************************/
93195b482a8SLen Brown 
9327f9fc99cSLv Zheng void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc)
93395b482a8SLen Brown {
9345582982dSLv Zheng 
9357f9fc99cSLv Zheng 	ACPI_FUNCTION_TRACE(tb_uninstall_table);
9365582982dSLv Zheng 
9377f9fc99cSLv Zheng 	/* Table must be installed */
9387f9fc99cSLv Zheng 
9397f9fc99cSLv Zheng 	if (!table_desc->address) {
9407f9fc99cSLv Zheng 		return_VOID;
94195b482a8SLen Brown 	}
9425582982dSLv Zheng 
9437f9fc99cSLv Zheng 	acpi_tb_invalidate_table(table_desc);
9441d1ea1b7SChao Guan 
9457f9fc99cSLv Zheng 	if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) ==
9468a216d7fSLv Zheng 	    ACPI_TABLE_ORIGIN_INTERN_VIRTUAL) {
9477f9fc99cSLv Zheng 		ACPI_FREE(ACPI_CAST_PTR(void, table_desc->address));
9487f9fc99cSLv Zheng 	}
9491d1ea1b7SChao Guan 
950dc156adfSLv Zheng 	table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL);
951f7b004a1SBob Moore 
9527f9fc99cSLv Zheng 	return_VOID;
95395b482a8SLen Brown }
95495b482a8SLen Brown 
95595b482a8SLen Brown /*******************************************************************************
95695b482a8SLen Brown  *
95795b482a8SLen Brown  * FUNCTION:    acpi_tb_terminate
95895b482a8SLen Brown  *
95995b482a8SLen Brown  * PARAMETERS:  None
96095b482a8SLen Brown  *
96195b482a8SLen Brown  * RETURN:      None
96295b482a8SLen Brown  *
96395b482a8SLen Brown  * DESCRIPTION: Delete all internal ACPI tables
96495b482a8SLen Brown  *
96595b482a8SLen Brown  ******************************************************************************/
96695b482a8SLen Brown 
96795b482a8SLen Brown void acpi_tb_terminate(void)
96895b482a8SLen Brown {
96995b482a8SLen Brown 	u32 i;
97095b482a8SLen Brown 
97195b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_terminate);
97295b482a8SLen Brown 
97395b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
97495b482a8SLen Brown 
97595b482a8SLen Brown 	/* Delete the individual tables */
97695b482a8SLen Brown 
977b9ee2043SBob Moore 	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
9787f9fc99cSLv Zheng 		acpi_tb_uninstall_table(&acpi_gbl_root_table_list.tables[i]);
97995b482a8SLen Brown 	}
98095b482a8SLen Brown 
98195b482a8SLen Brown 	/*
98295b482a8SLen Brown 	 * Delete the root table array if allocated locally. Array cannot be
98395b482a8SLen Brown 	 * mapped, so we don't need to check for that flag.
98495b482a8SLen Brown 	 */
98595b482a8SLen Brown 	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
98695b482a8SLen Brown 		ACPI_FREE(acpi_gbl_root_table_list.tables);
98795b482a8SLen Brown 	}
98895b482a8SLen Brown 
98995b482a8SLen Brown 	acpi_gbl_root_table_list.tables = NULL;
99095b482a8SLen Brown 	acpi_gbl_root_table_list.flags = 0;
991b9ee2043SBob Moore 	acpi_gbl_root_table_list.current_table_count = 0;
99295b482a8SLen Brown 
99395b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
99495b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
99568aafc35SBob Moore 
99668aafc35SBob Moore 	return_VOID;
99795b482a8SLen Brown }
99895b482a8SLen Brown 
99995b482a8SLen Brown /*******************************************************************************
100095b482a8SLen Brown  *
100195b482a8SLen Brown  * FUNCTION:    acpi_tb_delete_namespace_by_owner
100295b482a8SLen Brown  *
100395b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
100495b482a8SLen Brown  *
10058a335a23SBob Moore  * RETURN:      Status
100695b482a8SLen Brown  *
100795b482a8SLen Brown  * DESCRIPTION: Delete all namespace objects created when this table was loaded.
100895b482a8SLen Brown  *
100995b482a8SLen Brown  ******************************************************************************/
101095b482a8SLen Brown 
10118a335a23SBob Moore acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index)
101295b482a8SLen Brown {
101395b482a8SLen Brown 	acpi_owner_id owner_id;
10148a335a23SBob Moore 	acpi_status status;
101595b482a8SLen Brown 
10168a335a23SBob Moore 	ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner);
10178a335a23SBob Moore 
10188a335a23SBob Moore 	status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
10198a335a23SBob Moore 	if (ACPI_FAILURE(status)) {
10208a335a23SBob Moore 		return_ACPI_STATUS(status);
102195b482a8SLen Brown 	}
102295b482a8SLen Brown 
1023b9ee2043SBob Moore 	if (table_index >= acpi_gbl_root_table_list.current_table_count) {
10248a335a23SBob Moore 
10258a335a23SBob Moore 		/* The table index does not exist */
10268a335a23SBob Moore 
102795b482a8SLen Brown 		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
10288a335a23SBob Moore 		return_ACPI_STATUS(AE_NOT_EXIST);
10298a335a23SBob Moore 	}
10308a335a23SBob Moore 
10318a335a23SBob Moore 	/* Get the owner ID for this table, used to delete namespace nodes */
10328a335a23SBob Moore 
10338a335a23SBob Moore 	owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id;
10348a335a23SBob Moore 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
10358a335a23SBob Moore 
10368a335a23SBob Moore 	/*
10378a335a23SBob Moore 	 * Need to acquire the namespace writer lock to prevent interference
10388a335a23SBob Moore 	 * with any concurrent namespace walks. The interpreter must be
10398a335a23SBob Moore 	 * released during the deletion since the acquisition of the deletion
10408a335a23SBob Moore 	 * lock may block, and also since the execution of a namespace walk
10418a335a23SBob Moore 	 * must be allowed to use the interpreter.
10428a335a23SBob Moore 	 */
1043e4c1ebfcSBob Moore 	(void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
10448a335a23SBob Moore 	status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock);
10458a335a23SBob Moore 
104695b482a8SLen Brown 	acpi_ns_delete_namespace_by_owner(owner_id);
10478a335a23SBob Moore 	if (ACPI_FAILURE(status)) {
10488a335a23SBob Moore 		return_ACPI_STATUS(status);
10498a335a23SBob Moore 	}
10508a335a23SBob Moore 
10518a335a23SBob Moore 	acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock);
10528a335a23SBob Moore 
10538a335a23SBob Moore 	status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
10548a335a23SBob Moore 	return_ACPI_STATUS(status);
105595b482a8SLen Brown }
105695b482a8SLen Brown 
105795b482a8SLen Brown /*******************************************************************************
105895b482a8SLen Brown  *
105995b482a8SLen Brown  * FUNCTION:    acpi_tb_allocate_owner_id
106095b482a8SLen Brown  *
106195b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
106295b482a8SLen Brown  *
106395b482a8SLen Brown  * RETURN:      Status
106495b482a8SLen Brown  *
106595b482a8SLen Brown  * DESCRIPTION: Allocates owner_id in table_desc
106695b482a8SLen Brown  *
106795b482a8SLen Brown  ******************************************************************************/
106895b482a8SLen Brown 
106995b482a8SLen Brown acpi_status acpi_tb_allocate_owner_id(u32 table_index)
107095b482a8SLen Brown {
107195b482a8SLen Brown 	acpi_status status = AE_BAD_PARAMETER;
107295b482a8SLen Brown 
107395b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
107495b482a8SLen Brown 
107595b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1076b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
107795b482a8SLen Brown 		status = acpi_ut_allocate_owner_id
107895b482a8SLen Brown 		    (&(acpi_gbl_root_table_list.tables[table_index].owner_id));
107995b482a8SLen Brown 	}
108095b482a8SLen Brown 
108195b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
108295b482a8SLen Brown 	return_ACPI_STATUS(status);
108395b482a8SLen Brown }
108495b482a8SLen Brown 
108595b482a8SLen Brown /*******************************************************************************
108695b482a8SLen Brown  *
108795b482a8SLen Brown  * FUNCTION:    acpi_tb_release_owner_id
108895b482a8SLen Brown  *
108995b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
109095b482a8SLen Brown  *
109195b482a8SLen Brown  * RETURN:      Status
109295b482a8SLen Brown  *
109395b482a8SLen Brown  * DESCRIPTION: Releases owner_id in table_desc
109495b482a8SLen Brown  *
109595b482a8SLen Brown  ******************************************************************************/
109695b482a8SLen Brown 
109795b482a8SLen Brown acpi_status acpi_tb_release_owner_id(u32 table_index)
109895b482a8SLen Brown {
109995b482a8SLen Brown 	acpi_status status = AE_BAD_PARAMETER;
110095b482a8SLen Brown 
110195b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_release_owner_id);
110295b482a8SLen Brown 
110395b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1104b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
110595b482a8SLen Brown 		acpi_ut_release_owner_id(&
110695b482a8SLen Brown 					 (acpi_gbl_root_table_list.
110795b482a8SLen Brown 					  tables[table_index].owner_id));
110895b482a8SLen Brown 		status = AE_OK;
110995b482a8SLen Brown 	}
111095b482a8SLen Brown 
111195b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
111295b482a8SLen Brown 	return_ACPI_STATUS(status);
111395b482a8SLen Brown }
111495b482a8SLen Brown 
111595b482a8SLen Brown /*******************************************************************************
111695b482a8SLen Brown  *
111795b482a8SLen Brown  * FUNCTION:    acpi_tb_get_owner_id
111895b482a8SLen Brown  *
111995b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
112095b482a8SLen Brown  *              owner_id            - Where the table owner_id is returned
112195b482a8SLen Brown  *
112295b482a8SLen Brown  * RETURN:      Status
112395b482a8SLen Brown  *
112495b482a8SLen Brown  * DESCRIPTION: returns owner_id for the ACPI table
112595b482a8SLen Brown  *
112695b482a8SLen Brown  ******************************************************************************/
112795b482a8SLen Brown 
112895b482a8SLen Brown acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id * owner_id)
112995b482a8SLen Brown {
113095b482a8SLen Brown 	acpi_status status = AE_BAD_PARAMETER;
113195b482a8SLen Brown 
113295b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_get_owner_id);
113395b482a8SLen Brown 
113495b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1135b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
113695b482a8SLen Brown 		*owner_id =
113795b482a8SLen Brown 		    acpi_gbl_root_table_list.tables[table_index].owner_id;
113895b482a8SLen Brown 		status = AE_OK;
113995b482a8SLen Brown 	}
114095b482a8SLen Brown 
114195b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
114295b482a8SLen Brown 	return_ACPI_STATUS(status);
114395b482a8SLen Brown }
114495b482a8SLen Brown 
114595b482a8SLen Brown /*******************************************************************************
114695b482a8SLen Brown  *
114795b482a8SLen Brown  * FUNCTION:    acpi_tb_is_table_loaded
114895b482a8SLen Brown  *
114995b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
115095b482a8SLen Brown  *
115195b482a8SLen Brown  * RETURN:      Table Loaded Flag
115295b482a8SLen Brown  *
115395b482a8SLen Brown  ******************************************************************************/
115495b482a8SLen Brown 
115595b482a8SLen Brown u8 acpi_tb_is_table_loaded(u32 table_index)
115695b482a8SLen Brown {
115795b482a8SLen Brown 	u8 is_loaded = FALSE;
115895b482a8SLen Brown 
115995b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1160b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
116195b482a8SLen Brown 		is_loaded = (u8)
1162ec41f193SBob Moore 		    (acpi_gbl_root_table_list.tables[table_index].flags &
1163ec41f193SBob Moore 		     ACPI_TABLE_IS_LOADED);
116495b482a8SLen Brown 	}
116595b482a8SLen Brown 
116695b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
116795b482a8SLen Brown 	return (is_loaded);
116895b482a8SLen Brown }
116995b482a8SLen Brown 
117095b482a8SLen Brown /*******************************************************************************
117195b482a8SLen Brown  *
117295b482a8SLen Brown  * FUNCTION:    acpi_tb_set_table_loaded_flag
117395b482a8SLen Brown  *
117495b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
117595b482a8SLen Brown  *              is_loaded           - TRUE if table is loaded, FALSE otherwise
117695b482a8SLen Brown  *
117795b482a8SLen Brown  * RETURN:      None
117895b482a8SLen Brown  *
117995b482a8SLen Brown  * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
118095b482a8SLen Brown  *
118195b482a8SLen Brown  ******************************************************************************/
118295b482a8SLen Brown 
118395b482a8SLen Brown void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded)
118495b482a8SLen Brown {
118595b482a8SLen Brown 
118695b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1187b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
118895b482a8SLen Brown 		if (is_loaded) {
118995b482a8SLen Brown 			acpi_gbl_root_table_list.tables[table_index].flags |=
119095b482a8SLen Brown 			    ACPI_TABLE_IS_LOADED;
119195b482a8SLen Brown 		} else {
119295b482a8SLen Brown 			acpi_gbl_root_table_list.tables[table_index].flags &=
119395b482a8SLen Brown 			    ~ACPI_TABLE_IS_LOADED;
119495b482a8SLen Brown 		}
119595b482a8SLen Brown 	}
119695b482a8SLen Brown 
119795b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
119895b482a8SLen Brown }
1199