xref: /openbmc/linux/drivers/acpi/acpica/tbinstal.c (revision a94e88cdd8057fe8ea84bbb6d9a89a823c7bc49b)
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
39786dfc6f3SLv Zheng  *
39886dfc6f3SLv Zheng  * RETURN:      None
39986dfc6f3SLv Zheng  *
40086dfc6f3SLv Zheng  * DESCRIPTION: Install an ACPI table into the global data structure. The
40186dfc6f3SLv Zheng  *              table override mechanism is called to allow the host
40286dfc6f3SLv Zheng  *              OS to replace any table before it is installed in the root
40386dfc6f3SLv Zheng  *              table array.
40486dfc6f3SLv Zheng  *
40586dfc6f3SLv Zheng  ******************************************************************************/
40686dfc6f3SLv Zheng 
40786dfc6f3SLv Zheng void
40886dfc6f3SLv Zheng acpi_tb_install_and_override_table(u32 table_index,
40986dfc6f3SLv Zheng 				   struct acpi_table_desc *new_table_desc)
41086dfc6f3SLv Zheng {
41186dfc6f3SLv Zheng 	if (table_index >= acpi_gbl_root_table_list.current_table_count) {
41286dfc6f3SLv Zheng 		return;
41386dfc6f3SLv Zheng 	}
41486dfc6f3SLv Zheng 
41586dfc6f3SLv Zheng 	/*
41686dfc6f3SLv Zheng 	 * ACPI Table Override:
41786dfc6f3SLv Zheng 	 *
41886dfc6f3SLv Zheng 	 * Before we install the table, let the host OS override it with a new
41986dfc6f3SLv Zheng 	 * one if desired. Any table within the RSDT/XSDT can be replaced,
42086dfc6f3SLv Zheng 	 * including the DSDT which is pointed to by the FADT.
42186dfc6f3SLv Zheng 	 */
42286dfc6f3SLv Zheng 	acpi_tb_override_table(new_table_desc);
42386dfc6f3SLv Zheng 
42486dfc6f3SLv Zheng 	acpi_tb_install_table(&acpi_gbl_root_table_list.tables[table_index],
42586dfc6f3SLv Zheng 			      new_table_desc->address, new_table_desc->flags,
42686dfc6f3SLv Zheng 			      new_table_desc->pointer);
42786dfc6f3SLv Zheng 
42886dfc6f3SLv Zheng 	acpi_tb_print_table_header(new_table_desc->address,
42986dfc6f3SLv Zheng 				   new_table_desc->pointer);
43086dfc6f3SLv Zheng 
43186dfc6f3SLv Zheng 	/* Set the global integer width (based upon revision of the DSDT) */
43286dfc6f3SLv Zheng 
43386dfc6f3SLv Zheng 	if (table_index == ACPI_TABLE_INDEX_DSDT) {
43486dfc6f3SLv Zheng 		acpi_ut_set_integer_width(new_table_desc->pointer->revision);
43586dfc6f3SLv Zheng 	}
43686dfc6f3SLv Zheng }
43786dfc6f3SLv Zheng 
43886dfc6f3SLv Zheng /*******************************************************************************
43986dfc6f3SLv Zheng  *
44086dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_install_fixed_table
44186dfc6f3SLv Zheng  *
44286dfc6f3SLv Zheng  * PARAMETERS:  address                 - Physical address of DSDT or FACS
44386dfc6f3SLv Zheng  *              signature               - Table signature, NULL if no need to
44486dfc6f3SLv Zheng  *                                        match
44586dfc6f3SLv Zheng  *              table_index             - Index into root table array
44686dfc6f3SLv Zheng  *
44786dfc6f3SLv Zheng  * RETURN:      Status
44886dfc6f3SLv Zheng  *
44986dfc6f3SLv Zheng  * DESCRIPTION: Install a fixed ACPI table (DSDT/FACS) into the global data
45086dfc6f3SLv Zheng  *              structure.
45195b482a8SLen Brown  *
45295b482a8SLen Brown  ******************************************************************************/
45395b482a8SLen Brown 
45495b482a8SLen Brown acpi_status
45586dfc6f3SLv Zheng acpi_tb_install_fixed_table(acpi_physical_address address,
45686dfc6f3SLv Zheng 			    char *signature, u32 table_index)
45786dfc6f3SLv Zheng {
45886dfc6f3SLv Zheng 	struct acpi_table_desc new_table_desc;
45986dfc6f3SLv Zheng 	acpi_status status;
46086dfc6f3SLv Zheng 
46186dfc6f3SLv Zheng 	ACPI_FUNCTION_TRACE(tb_install_fixed_table);
46286dfc6f3SLv Zheng 
46386dfc6f3SLv Zheng 	if (!address) {
46486dfc6f3SLv Zheng 		ACPI_ERROR((AE_INFO,
46586dfc6f3SLv Zheng 			    "Null physical address for ACPI table [%s]",
46686dfc6f3SLv Zheng 			    signature));
46786dfc6f3SLv Zheng 		return (AE_NO_MEMORY);
46886dfc6f3SLv Zheng 	}
46986dfc6f3SLv Zheng 
47086dfc6f3SLv Zheng 	/* Fill a table descriptor for validation */
47186dfc6f3SLv Zheng 
47286dfc6f3SLv Zheng 	status = acpi_tb_acquire_temporal_table(&new_table_desc, address,
4738a216d7fSLv Zheng 						ACPI_TABLE_ORIGIN_INTERN_PHYSICAL);
47486dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
47586dfc6f3SLv Zheng 		ACPI_ERROR((AE_INFO, "Could not acquire table length at %p",
47686dfc6f3SLv Zheng 			    ACPI_CAST_PTR(void, address)));
47786dfc6f3SLv Zheng 		return_ACPI_STATUS(status);
47886dfc6f3SLv Zheng 	}
47986dfc6f3SLv Zheng 
48086dfc6f3SLv Zheng 	/* Validate and verify a table before installation */
48186dfc6f3SLv Zheng 
48286dfc6f3SLv Zheng 	status = acpi_tb_verify_table(&new_table_desc, signature);
48386dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
48486dfc6f3SLv Zheng 		goto release_and_exit;
48586dfc6f3SLv Zheng 	}
48686dfc6f3SLv Zheng 
48786dfc6f3SLv Zheng 	acpi_tb_install_and_override_table(table_index, &new_table_desc);
48886dfc6f3SLv Zheng 
48986dfc6f3SLv Zheng release_and_exit:
49086dfc6f3SLv Zheng 
49186dfc6f3SLv Zheng 	/* Release the temporal table descriptor */
49286dfc6f3SLv Zheng 
49386dfc6f3SLv Zheng 	acpi_tb_release_temporal_table(&new_table_desc);
49486dfc6f3SLv Zheng 	return_ACPI_STATUS(status);
49586dfc6f3SLv Zheng }
49686dfc6f3SLv Zheng 
49786dfc6f3SLv Zheng /*******************************************************************************
49886dfc6f3SLv Zheng  *
49986dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_is_equivalent_table
50086dfc6f3SLv Zheng  *
50186dfc6f3SLv Zheng  * PARAMETERS:  table_desc          - Table 1 descriptor to be compared
50286dfc6f3SLv Zheng  *              table_index         - Index of table 2 to be compared
50386dfc6f3SLv Zheng  *
50486dfc6f3SLv Zheng  * RETURN:      TRUE if 2 tables are equivalent
50586dfc6f3SLv Zheng  *
50686dfc6f3SLv Zheng  * DESCRIPTION: This function is called to compare a table with what have
50786dfc6f3SLv Zheng  *              already been installed in the root table list.
50886dfc6f3SLv Zheng  *
50986dfc6f3SLv Zheng  ******************************************************************************/
51086dfc6f3SLv Zheng 
51186dfc6f3SLv Zheng static u8
51286dfc6f3SLv Zheng acpi_tb_is_equivalent_table(struct acpi_table_desc *table_desc, u32 table_index)
51386dfc6f3SLv Zheng {
51486dfc6f3SLv Zheng 	acpi_status status = AE_OK;
51586dfc6f3SLv Zheng 	u8 is_equivalent;
51686dfc6f3SLv Zheng 	struct acpi_table_header *table;
51786dfc6f3SLv Zheng 	u32 table_length;
51886dfc6f3SLv Zheng 	u8 table_flags;
51986dfc6f3SLv Zheng 
52086dfc6f3SLv Zheng 	status =
52186dfc6f3SLv Zheng 	    acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index],
52286dfc6f3SLv Zheng 				  &table, &table_length, &table_flags);
52386dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
52486dfc6f3SLv Zheng 		return (FALSE);
52586dfc6f3SLv Zheng 	}
52686dfc6f3SLv Zheng 
52786dfc6f3SLv Zheng 	/*
52886dfc6f3SLv Zheng 	 * Check for a table match on the entire table length,
52986dfc6f3SLv Zheng 	 * not just the header.
53086dfc6f3SLv Zheng 	 */
53186dfc6f3SLv Zheng 	is_equivalent = (u8)((table_desc->length != table_length ||
53286dfc6f3SLv Zheng 			      ACPI_MEMCMP(table_desc->pointer, table,
53386dfc6f3SLv Zheng 					  table_length)) ? FALSE : TRUE);
53486dfc6f3SLv Zheng 
53586dfc6f3SLv Zheng 	/* Release the acquired table */
53686dfc6f3SLv Zheng 
53786dfc6f3SLv Zheng 	acpi_tb_release_table(table, table_length, table_flags);
53886dfc6f3SLv Zheng 
53986dfc6f3SLv Zheng 	return (is_equivalent);
54086dfc6f3SLv Zheng }
54186dfc6f3SLv Zheng 
54286dfc6f3SLv Zheng /*******************************************************************************
54386dfc6f3SLv Zheng  *
54486dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_install_non_fixed_table
54586dfc6f3SLv Zheng  *
5468a216d7fSLv Zheng  * PARAMETERS:  address             - Address of the table (might be a virtual
54786dfc6f3SLv Zheng  *                                    address depending on the table_flags)
54886dfc6f3SLv Zheng  *              flags               - Flags for the table
54986dfc6f3SLv Zheng  *              reload              - Whether reload should be performed
55086dfc6f3SLv Zheng  *              table_index         - Where the table index is returned
55186dfc6f3SLv Zheng  *
55286dfc6f3SLv Zheng  * RETURN:      Status
55386dfc6f3SLv Zheng  *
55486dfc6f3SLv Zheng  * DESCRIPTION: This function is called to install an ACPI table that is
55586dfc6f3SLv Zheng  *              neither DSDT nor FACS.
55686dfc6f3SLv Zheng  *              When this function is called by "Load" or "LoadTable" opcodes,
55786dfc6f3SLv Zheng  *              or by acpi_load_table() API, the "Reload" parameter is set.
55886dfc6f3SLv Zheng  *              After sucessfully returning from this function, table is
55986dfc6f3SLv Zheng  *              "INSTALLED" but not "VALIDATED".
56086dfc6f3SLv Zheng  *
56186dfc6f3SLv Zheng  ******************************************************************************/
56286dfc6f3SLv Zheng 
56386dfc6f3SLv Zheng acpi_status
56486dfc6f3SLv Zheng acpi_tb_install_non_fixed_table(acpi_physical_address address,
56586dfc6f3SLv Zheng 				u8 flags, u8 reload, u32 *table_index)
56695b482a8SLen Brown {
56795b482a8SLen Brown 	u32 i;
56895b482a8SLen Brown 	acpi_status status = AE_OK;
56986dfc6f3SLv Zheng 	struct acpi_table_desc new_table_desc;
57095b482a8SLen Brown 
57186dfc6f3SLv Zheng 	ACPI_FUNCTION_TRACE(tb_install_non_fixed_table);
57295b482a8SLen Brown 
57386dfc6f3SLv Zheng 	/* Acquire a temporal table descriptor for validation */
57486dfc6f3SLv Zheng 
57586dfc6f3SLv Zheng 	status =
57686dfc6f3SLv Zheng 	    acpi_tb_acquire_temporal_table(&new_table_desc, address, flags);
57786dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
57886dfc6f3SLv Zheng 		ACPI_ERROR((AE_INFO, "Could not acquire table length at %p",
57986dfc6f3SLv Zheng 			    ACPI_CAST_PTR(void, address)));
58095b482a8SLen Brown 		return_ACPI_STATUS(status);
58195b482a8SLen Brown 	}
58286dfc6f3SLv Zheng 
583*a94e88cdSLv Zheng 	/*
584*a94e88cdSLv Zheng 	 * Optionally do not load any SSDTs from the RSDT/XSDT. This can
585*a94e88cdSLv Zheng 	 * be useful for debugging ACPI problems on some machines.
586*a94e88cdSLv Zheng 	 */
587*a94e88cdSLv Zheng 	if (!reload && acpi_gbl_disable_ssdt_table_install &&
588*a94e88cdSLv Zheng 	    ACPI_COMPARE_NAME(&new_table_desc.signature, ACPI_SIG_SSDT)) {
589*a94e88cdSLv Zheng 		ACPI_INFO((AE_INFO, "Ignoring installation of %4.4s at %p",
590*a94e88cdSLv Zheng 			   new_table_desc.signature.ascii, ACPI_CAST_PTR(void,
591*a94e88cdSLv Zheng 									 address)));
592*a94e88cdSLv Zheng 		goto release_and_exit;
593*a94e88cdSLv Zheng 	}
594*a94e88cdSLv Zheng 
59586dfc6f3SLv Zheng 	/* Validate and verify a table before installation */
59686dfc6f3SLv Zheng 
59786dfc6f3SLv Zheng 	status = acpi_tb_verify_table(&new_table_desc, NULL);
59886dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
59986dfc6f3SLv Zheng 		goto release_and_exit;
60095b482a8SLen Brown 	}
60195b482a8SLen Brown 
60286dfc6f3SLv Zheng 	if (reload) {
60395b482a8SLen Brown 		/*
604c8cefe30SBob Moore 		 * Validate the incoming table signature.
605c8cefe30SBob Moore 		 *
606c8cefe30SBob Moore 		 * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
607c8cefe30SBob Moore 		 * 2) We added support for OEMx tables, signature "OEM".
608c8cefe30SBob Moore 		 * 3) Valid tables were encountered with a null signature, so we just
609c8cefe30SBob Moore 		 *    gave up on validating the signature, (05/2008).
610c8cefe30SBob Moore 		 * 4) We encountered non-AML tables such as the MADT, which caused
611c8cefe30SBob Moore 		 *    interpreter errors and kernel faults. So now, we once again allow
612c8cefe30SBob Moore 		 *    only "SSDT", "OEMx", and now, also a null signature. (05/2011).
61395b482a8SLen Brown 		 */
61486dfc6f3SLv Zheng 		if ((new_table_desc.signature.ascii[0] != 0x00) &&
61586dfc6f3SLv Zheng 		    (!ACPI_COMPARE_NAME
61686dfc6f3SLv Zheng 		     (&new_table_desc.signature, ACPI_SIG_SSDT))
61786dfc6f3SLv Zheng 		    && (ACPI_STRNCMP(new_table_desc.signature.ascii, "OEM", 3)))
61886dfc6f3SLv Zheng 		{
6193b3ea775SBob Moore 			ACPI_BIOS_ERROR((AE_INFO,
6203b3ea775SBob Moore 					 "Table has invalid signature [%4.4s] (0x%8.8X), "
6213b3ea775SBob Moore 					 "must be SSDT or OEMx",
62286dfc6f3SLv Zheng 					 acpi_ut_valid_acpi_name(new_table_desc.
62386dfc6f3SLv Zheng 								 signature.
62486dfc6f3SLv Zheng 								 ascii) ?
62586dfc6f3SLv Zheng 					 new_table_desc.signature.
62686dfc6f3SLv Zheng 					 ascii : "????",
62786dfc6f3SLv Zheng 					 new_table_desc.signature.integer));
628c8cefe30SBob Moore 
62986dfc6f3SLv Zheng 			status = AE_BAD_SIGNATURE;
63086dfc6f3SLv Zheng 			goto release_and_exit;
631c8cefe30SBob Moore 		}
63295b482a8SLen Brown 
63395b482a8SLen Brown 		/* Check if table is already registered */
63495b482a8SLen Brown 
63586dfc6f3SLv Zheng 		for (i = 0; i < acpi_gbl_root_table_list.current_table_count;
63686dfc6f3SLv Zheng 		     ++i) {
63795b482a8SLen Brown 			/*
63895b482a8SLen Brown 			 * Check for a table match on the entire table length,
63995b482a8SLen Brown 			 * not just the header.
64095b482a8SLen Brown 			 */
64186dfc6f3SLv Zheng 			if (!acpi_tb_is_equivalent_table(&new_table_desc, i)) {
64295b482a8SLen Brown 				continue;
64395b482a8SLen Brown 			}
64495b482a8SLen Brown 
64595b482a8SLen Brown 			/*
64695b482a8SLen Brown 			 * Note: the current mechanism does not unregister a table if it is
64795b482a8SLen Brown 			 * dynamically unloaded. The related namespace entries are deleted,
64895b482a8SLen Brown 			 * but the table remains in the root table list.
64995b482a8SLen Brown 			 *
65095b482a8SLen Brown 			 * The assumption here is that the number of different tables that
65195b482a8SLen Brown 			 * will be loaded is actually small, and there is minimal overhead
65295b482a8SLen Brown 			 * in just keeping the table in case it is needed again.
65395b482a8SLen Brown 			 *
65495b482a8SLen Brown 			 * If this assumption changes in the future (perhaps on large
65595b482a8SLen Brown 			 * machines with many table load/unload operations), tables will
65695b482a8SLen Brown 			 * need to be unregistered when they are unloaded, and slots in the
65795b482a8SLen Brown 			 * root table list should be reused when empty.
65895b482a8SLen Brown 			 */
65995b482a8SLen Brown 			if (acpi_gbl_root_table_list.tables[i].
66095b482a8SLen Brown 			    flags & ACPI_TABLE_IS_LOADED) {
66195b482a8SLen Brown 
66295b482a8SLen Brown 				/* Table is still loaded, this is an error */
66395b482a8SLen Brown 
66495b482a8SLen Brown 				status = AE_ALREADY_EXISTS;
66586dfc6f3SLv Zheng 				goto release_and_exit;
66695b482a8SLen Brown 			} else {
667d3ccaff8SBob Moore 				/*
66886dfc6f3SLv Zheng 				 * Table was unloaded, allow it to be reloaded.
66986dfc6f3SLv Zheng 				 * As we are going to return AE_OK to the caller, we should
67086dfc6f3SLv Zheng 				 * take the responsibility of freeing the input descriptor.
67186dfc6f3SLv Zheng 				 * Refill the input descriptor to ensure
67286dfc6f3SLv Zheng 				 * acpi_tb_install_and_override_table() can be called again to
67386dfc6f3SLv Zheng 				 * indicate the re-installation.
674d3ccaff8SBob Moore 				 */
67586dfc6f3SLv Zheng 				acpi_tb_uninstall_table(&new_table_desc);
67686dfc6f3SLv Zheng 				*table_index = i;
67786dfc6f3SLv Zheng 				(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
67886dfc6f3SLv Zheng 				return_ACPI_STATUS(AE_OK);
67986dfc6f3SLv Zheng 			}
68086dfc6f3SLv Zheng 		}
6817f9fc99cSLv Zheng 	}
682d3ccaff8SBob Moore 
68395b482a8SLen Brown 	/* Add the table to the global root table list */
68495b482a8SLen Brown 
68586dfc6f3SLv Zheng 	status = acpi_tb_acquire_root_table_entry(&i);
68695b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
68786dfc6f3SLv Zheng 		goto release_and_exit;
68895b482a8SLen Brown 	}
68986dfc6f3SLv Zheng 	*table_index = i;
69086dfc6f3SLv Zheng 	acpi_tb_install_and_override_table(i, &new_table_desc);
69195b482a8SLen Brown 
69286dfc6f3SLv Zheng release_and_exit:
69395b482a8SLen Brown 
69486dfc6f3SLv Zheng 	/* Release the temporal table descriptor */
69586dfc6f3SLv Zheng 
69686dfc6f3SLv Zheng 	acpi_tb_release_temporal_table(&new_table_desc);
69795b482a8SLen Brown 	return_ACPI_STATUS(status);
69895b482a8SLen Brown }
69995b482a8SLen Brown 
70095b482a8SLen Brown /*******************************************************************************
70195b482a8SLen Brown  *
7027f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_override_table
703f7b004a1SBob Moore  *
70486dfc6f3SLv Zheng  * PARAMETERS:  old_table_desc      - Validated table descriptor to be
70586dfc6f3SLv Zheng  *                                    overridden
706f7b004a1SBob Moore  *
70786dfc6f3SLv Zheng  * RETURN:      None
708f7b004a1SBob Moore  *
709f7b004a1SBob Moore  * DESCRIPTION: Attempt table override by calling the OSL override functions.
710f7b004a1SBob Moore  *              Note: If the table is overridden, then the entire new table
7117f9fc99cSLv Zheng  *              is acquired and returned by this function.
71286dfc6f3SLv Zheng  *              Before/after invocation, the table descriptor is in a state
71386dfc6f3SLv Zheng  *              that is "VALIDATED".
714f7b004a1SBob Moore  *
715f7b004a1SBob Moore  ******************************************************************************/
716f7b004a1SBob Moore 
71786dfc6f3SLv Zheng void acpi_tb_override_table(struct acpi_table_desc *old_table_desc)
718f7b004a1SBob Moore {
719f7b004a1SBob Moore 	acpi_status status;
720f7b004a1SBob Moore 	char *override_type;
7217f9fc99cSLv Zheng 	struct acpi_table_desc new_table_desc;
72286dfc6f3SLv Zheng 	struct acpi_table_header *table;
72386dfc6f3SLv Zheng 	acpi_physical_address address;
72486dfc6f3SLv Zheng 	u32 length;
725f7b004a1SBob Moore 
726f7b004a1SBob Moore 	/* (1) Attempt logical override (returns a logical address) */
727f7b004a1SBob Moore 
72886dfc6f3SLv Zheng 	status = acpi_os_table_override(old_table_desc->pointer, &table);
72986dfc6f3SLv Zheng 	if (ACPI_SUCCESS(status) && table) {
73086dfc6f3SLv Zheng 		acpi_tb_acquire_temporal_table(&new_table_desc,
73186dfc6f3SLv Zheng 					       ACPI_PTR_TO_PHYSADDR(table),
7328a216d7fSLv Zheng 					       ACPI_TABLE_ORIGIN_EXTERN_VIRTUAL);
733f7b004a1SBob Moore 		override_type = "Logical";
734f7b004a1SBob Moore 		goto finish_override;
735f7b004a1SBob Moore 	}
736f7b004a1SBob Moore 
737f7b004a1SBob Moore 	/* (2) Attempt physical override (returns a physical address) */
738f7b004a1SBob Moore 
73986dfc6f3SLv Zheng 	status = acpi_os_physical_table_override(old_table_desc->pointer,
74086dfc6f3SLv Zheng 						 &address, &length);
74186dfc6f3SLv Zheng 	if (ACPI_SUCCESS(status) && address && length) {
74286dfc6f3SLv Zheng 		acpi_tb_acquire_temporal_table(&new_table_desc, address,
7438a216d7fSLv Zheng 					       ACPI_TABLE_ORIGIN_INTERN_PHYSICAL);
744f7b004a1SBob Moore 		override_type = "Physical";
745f7b004a1SBob Moore 		goto finish_override;
746f7b004a1SBob Moore 	}
747f7b004a1SBob Moore 
74886dfc6f3SLv Zheng 	return;			/* There was no override */
749f7b004a1SBob Moore 
750f7b004a1SBob Moore finish_override:
751f7b004a1SBob Moore 
75286dfc6f3SLv Zheng 	/* Validate and verify a table before overriding */
75386dfc6f3SLv Zheng 
75486dfc6f3SLv Zheng 	status = acpi_tb_verify_table(&new_table_desc, NULL);
7557f9fc99cSLv Zheng 	if (ACPI_FAILURE(status)) {
75686dfc6f3SLv Zheng 		return;
7577f9fc99cSLv Zheng 	}
7587f9fc99cSLv Zheng 
7592e19f8d0SBob Moore 	ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT
7602e19f8d0SBob Moore 		   " %s table override, new table: " ACPI_PRINTF_UINT,
76186dfc6f3SLv Zheng 		   old_table_desc->signature.ascii,
76286dfc6f3SLv Zheng 		   ACPI_FORMAT_TO_UINT(old_table_desc->address),
7637f9fc99cSLv Zheng 		   override_type, ACPI_FORMAT_TO_UINT(new_table_desc.address)));
764f7b004a1SBob Moore 
76586dfc6f3SLv Zheng 	/* We can now uninstall the original table */
766f7b004a1SBob Moore 
76786dfc6f3SLv Zheng 	acpi_tb_uninstall_table(old_table_desc);
768f7b004a1SBob Moore 
76986dfc6f3SLv Zheng 	/*
77086dfc6f3SLv Zheng 	 * Replace the original table descriptor and keep its state as
77186dfc6f3SLv Zheng 	 * "VALIDATED".
77286dfc6f3SLv Zheng 	 */
77386dfc6f3SLv Zheng 	acpi_tb_install_table(old_table_desc, new_table_desc.address,
77486dfc6f3SLv Zheng 			      new_table_desc.flags, new_table_desc.pointer);
77586dfc6f3SLv Zheng 	acpi_tb_validate_table(old_table_desc);
776f7b004a1SBob Moore 
77786dfc6f3SLv Zheng 	/* Release the temporal table descriptor */
778f7b004a1SBob Moore 
77986dfc6f3SLv Zheng 	acpi_tb_release_temporal_table(&new_table_desc);
780f7b004a1SBob Moore }
781f7b004a1SBob Moore 
782f7b004a1SBob Moore /*******************************************************************************
783f7b004a1SBob Moore  *
78495b482a8SLen Brown  * FUNCTION:    acpi_tb_resize_root_table_list
78595b482a8SLen Brown  *
78695b482a8SLen Brown  * PARAMETERS:  None
78795b482a8SLen Brown  *
78895b482a8SLen Brown  * RETURN:      Status
78995b482a8SLen Brown  *
79095b482a8SLen Brown  * DESCRIPTION: Expand the size of global table array
79195b482a8SLen Brown  *
79295b482a8SLen Brown  ******************************************************************************/
79395b482a8SLen Brown 
79495b482a8SLen Brown acpi_status acpi_tb_resize_root_table_list(void)
79595b482a8SLen Brown {
79695b482a8SLen Brown 	struct acpi_table_desc *tables;
7972bc198c1SLv Zheng 	u32 table_count;
79895b482a8SLen Brown 
79995b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
80095b482a8SLen Brown 
80195b482a8SLen Brown 	/* allow_resize flag is a parameter to acpi_initialize_tables */
80295b482a8SLen Brown 
80395b482a8SLen Brown 	if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) {
80495b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
80595b482a8SLen Brown 			    "Resize of Root Table Array is not allowed"));
80695b482a8SLen Brown 		return_ACPI_STATUS(AE_SUPPORT);
80795b482a8SLen Brown 	}
80895b482a8SLen Brown 
80995b482a8SLen Brown 	/* Increase the Table Array size */
81095b482a8SLen Brown 
8112bc198c1SLv Zheng 	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
8122bc198c1SLv Zheng 		table_count = acpi_gbl_root_table_list.max_table_count;
8132bc198c1SLv Zheng 	} else {
8142bc198c1SLv Zheng 		table_count = acpi_gbl_root_table_list.current_table_count;
8152bc198c1SLv Zheng 	}
8162bc198c1SLv Zheng 
8172bc198c1SLv Zheng 	tables = ACPI_ALLOCATE_ZEROED(((acpi_size) table_count +
818ec41f193SBob Moore 				       ACPI_ROOT_TABLE_SIZE_INCREMENT) *
819ec41f193SBob Moore 				      sizeof(struct acpi_table_desc));
82095b482a8SLen Brown 	if (!tables) {
82195b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
82295b482a8SLen Brown 			    "Could not allocate new root table array"));
82395b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_MEMORY);
82495b482a8SLen Brown 	}
82595b482a8SLen Brown 
82695b482a8SLen Brown 	/* Copy and free the previous table array */
82795b482a8SLen Brown 
82895b482a8SLen Brown 	if (acpi_gbl_root_table_list.tables) {
82995b482a8SLen Brown 		ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
8302bc198c1SLv Zheng 			    (acpi_size) table_count *
8312bc198c1SLv Zheng 			    sizeof(struct acpi_table_desc));
83295b482a8SLen Brown 
83395b482a8SLen Brown 		if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
83495b482a8SLen Brown 			ACPI_FREE(acpi_gbl_root_table_list.tables);
83595b482a8SLen Brown 		}
83695b482a8SLen Brown 	}
83795b482a8SLen Brown 
83895b482a8SLen Brown 	acpi_gbl_root_table_list.tables = tables;
8392bc198c1SLv Zheng 	acpi_gbl_root_table_list.max_table_count =
8402bc198c1SLv Zheng 	    table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT;
8412bc198c1SLv Zheng 	acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
84295b482a8SLen Brown 
84395b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
84495b482a8SLen Brown }
84595b482a8SLen Brown 
84695b482a8SLen Brown /*******************************************************************************
84795b482a8SLen Brown  *
84886dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_acquire_root_table_entry
84986dfc6f3SLv Zheng  *
85086dfc6f3SLv Zheng  * PARAMETERS:  table_index         - Where table index is returned
85186dfc6f3SLv Zheng  *
85286dfc6f3SLv Zheng  * RETURN:      Status and table index.
85386dfc6f3SLv Zheng  *
85486dfc6f3SLv Zheng  * DESCRIPTION: Allocate a new ACPI table entry to the global table list
85586dfc6f3SLv Zheng  *
85686dfc6f3SLv Zheng  ******************************************************************************/
85786dfc6f3SLv Zheng 
85886dfc6f3SLv Zheng static acpi_status acpi_tb_acquire_root_table_entry(u32 *table_index)
85986dfc6f3SLv Zheng {
86086dfc6f3SLv Zheng 	acpi_status status;
86186dfc6f3SLv Zheng 
86286dfc6f3SLv Zheng 	/* Ensure that there is room for the table in the Root Table List */
86386dfc6f3SLv Zheng 
86486dfc6f3SLv Zheng 	if (acpi_gbl_root_table_list.current_table_count >=
86586dfc6f3SLv Zheng 	    acpi_gbl_root_table_list.max_table_count) {
86686dfc6f3SLv Zheng 		status = acpi_tb_resize_root_table_list();
86786dfc6f3SLv Zheng 		if (ACPI_FAILURE(status)) {
86886dfc6f3SLv Zheng 			return (status);
86986dfc6f3SLv Zheng 		}
87086dfc6f3SLv Zheng 	}
87186dfc6f3SLv Zheng 
87286dfc6f3SLv Zheng 	*table_index = acpi_gbl_root_table_list.current_table_count;
87386dfc6f3SLv Zheng 	acpi_gbl_root_table_list.current_table_count++;
87486dfc6f3SLv Zheng 	return (AE_OK);
87586dfc6f3SLv Zheng }
87686dfc6f3SLv Zheng 
87786dfc6f3SLv Zheng /*******************************************************************************
87886dfc6f3SLv Zheng  *
87995b482a8SLen Brown  * FUNCTION:    acpi_tb_store_table
88095b482a8SLen Brown  *
881ba494beeSBob Moore  * PARAMETERS:  address             - Table address
882ba494beeSBob Moore  *              table               - Table header
883ba494beeSBob Moore  *              length              - Table length
884ba494beeSBob Moore  *              flags               - flags
88595b482a8SLen Brown  *
88695b482a8SLen Brown  * RETURN:      Status and table index.
88795b482a8SLen Brown  *
88895b482a8SLen Brown  * DESCRIPTION: Add an ACPI table to the global table list
88995b482a8SLen Brown  *
89095b482a8SLen Brown  ******************************************************************************/
89195b482a8SLen Brown 
89295b482a8SLen Brown acpi_status
89395b482a8SLen Brown acpi_tb_store_table(acpi_physical_address address,
89495b482a8SLen Brown 		    struct acpi_table_header * table,
89595b482a8SLen Brown 		    u32 length, u8 flags, u32 *table_index)
89695b482a8SLen Brown {
897b9ee2043SBob Moore 	acpi_status status;
89886dfc6f3SLv Zheng 	struct acpi_table_desc *table_desc;
89995b482a8SLen Brown 
90086dfc6f3SLv Zheng 	status = acpi_tb_acquire_root_table_entry(table_index);
90195b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
90295b482a8SLen Brown 		return (status);
90395b482a8SLen Brown 	}
904b9ee2043SBob Moore 
90595b482a8SLen Brown 	/* Initialize added table */
90695b482a8SLen Brown 
90786dfc6f3SLv Zheng 	table_desc = &acpi_gbl_root_table_list.tables[*table_index];
90886dfc6f3SLv Zheng 	acpi_tb_install_table(table_desc, address, flags, table);
90986dfc6f3SLv Zheng 	table_desc->pointer = table;
91095b482a8SLen Brown 
911b9ee2043SBob Moore 	return (AE_OK);
91295b482a8SLen Brown }
91395b482a8SLen Brown 
91495b482a8SLen Brown /*******************************************************************************
91595b482a8SLen Brown  *
9167f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_uninstall_table
91795b482a8SLen Brown  *
9187f9fc99cSLv Zheng  * PARAMETERS:  table_desc          - Table descriptor
91995b482a8SLen Brown  *
92095b482a8SLen Brown  * RETURN:      None
92195b482a8SLen Brown  *
92295b482a8SLen Brown  * DESCRIPTION: Delete one internal ACPI table
92395b482a8SLen Brown  *
92495b482a8SLen Brown  ******************************************************************************/
92595b482a8SLen Brown 
9267f9fc99cSLv Zheng void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc)
92795b482a8SLen Brown {
9285582982dSLv Zheng 
9297f9fc99cSLv Zheng 	ACPI_FUNCTION_TRACE(tb_uninstall_table);
9305582982dSLv Zheng 
9317f9fc99cSLv Zheng 	/* Table must be installed */
9327f9fc99cSLv Zheng 
9337f9fc99cSLv Zheng 	if (!table_desc->address) {
9347f9fc99cSLv Zheng 		return_VOID;
93595b482a8SLen Brown 	}
9365582982dSLv Zheng 
9377f9fc99cSLv Zheng 	acpi_tb_invalidate_table(table_desc);
9381d1ea1b7SChao Guan 
9397f9fc99cSLv Zheng 	if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) ==
9408a216d7fSLv Zheng 	    ACPI_TABLE_ORIGIN_INTERN_VIRTUAL) {
9417f9fc99cSLv Zheng 		ACPI_FREE(ACPI_CAST_PTR(void, table_desc->address));
9427f9fc99cSLv Zheng 	}
9431d1ea1b7SChao Guan 
944dc156adfSLv Zheng 	table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL);
945f7b004a1SBob Moore 
9467f9fc99cSLv Zheng 	return_VOID;
94795b482a8SLen Brown }
94895b482a8SLen Brown 
94995b482a8SLen Brown /*******************************************************************************
95095b482a8SLen Brown  *
95195b482a8SLen Brown  * FUNCTION:    acpi_tb_terminate
95295b482a8SLen Brown  *
95395b482a8SLen Brown  * PARAMETERS:  None
95495b482a8SLen Brown  *
95595b482a8SLen Brown  * RETURN:      None
95695b482a8SLen Brown  *
95795b482a8SLen Brown  * DESCRIPTION: Delete all internal ACPI tables
95895b482a8SLen Brown  *
95995b482a8SLen Brown  ******************************************************************************/
96095b482a8SLen Brown 
96195b482a8SLen Brown void acpi_tb_terminate(void)
96295b482a8SLen Brown {
96395b482a8SLen Brown 	u32 i;
96495b482a8SLen Brown 
96595b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_terminate);
96695b482a8SLen Brown 
96795b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
96895b482a8SLen Brown 
96995b482a8SLen Brown 	/* Delete the individual tables */
97095b482a8SLen Brown 
971b9ee2043SBob Moore 	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
9727f9fc99cSLv Zheng 		acpi_tb_uninstall_table(&acpi_gbl_root_table_list.tables[i]);
97395b482a8SLen Brown 	}
97495b482a8SLen Brown 
97595b482a8SLen Brown 	/*
97695b482a8SLen Brown 	 * Delete the root table array if allocated locally. Array cannot be
97795b482a8SLen Brown 	 * mapped, so we don't need to check for that flag.
97895b482a8SLen Brown 	 */
97995b482a8SLen Brown 	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
98095b482a8SLen Brown 		ACPI_FREE(acpi_gbl_root_table_list.tables);
98195b482a8SLen Brown 	}
98295b482a8SLen Brown 
98395b482a8SLen Brown 	acpi_gbl_root_table_list.tables = NULL;
98495b482a8SLen Brown 	acpi_gbl_root_table_list.flags = 0;
985b9ee2043SBob Moore 	acpi_gbl_root_table_list.current_table_count = 0;
98695b482a8SLen Brown 
98795b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
98895b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
98968aafc35SBob Moore 
99068aafc35SBob Moore 	return_VOID;
99195b482a8SLen Brown }
99295b482a8SLen Brown 
99395b482a8SLen Brown /*******************************************************************************
99495b482a8SLen Brown  *
99595b482a8SLen Brown  * FUNCTION:    acpi_tb_delete_namespace_by_owner
99695b482a8SLen Brown  *
99795b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
99895b482a8SLen Brown  *
9998a335a23SBob Moore  * RETURN:      Status
100095b482a8SLen Brown  *
100195b482a8SLen Brown  * DESCRIPTION: Delete all namespace objects created when this table was loaded.
100295b482a8SLen Brown  *
100395b482a8SLen Brown  ******************************************************************************/
100495b482a8SLen Brown 
10058a335a23SBob Moore acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index)
100695b482a8SLen Brown {
100795b482a8SLen Brown 	acpi_owner_id owner_id;
10088a335a23SBob Moore 	acpi_status status;
100995b482a8SLen Brown 
10108a335a23SBob Moore 	ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner);
10118a335a23SBob Moore 
10128a335a23SBob Moore 	status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
10138a335a23SBob Moore 	if (ACPI_FAILURE(status)) {
10148a335a23SBob Moore 		return_ACPI_STATUS(status);
101595b482a8SLen Brown 	}
101695b482a8SLen Brown 
1017b9ee2043SBob Moore 	if (table_index >= acpi_gbl_root_table_list.current_table_count) {
10188a335a23SBob Moore 
10198a335a23SBob Moore 		/* The table index does not exist */
10208a335a23SBob Moore 
102195b482a8SLen Brown 		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
10228a335a23SBob Moore 		return_ACPI_STATUS(AE_NOT_EXIST);
10238a335a23SBob Moore 	}
10248a335a23SBob Moore 
10258a335a23SBob Moore 	/* Get the owner ID for this table, used to delete namespace nodes */
10268a335a23SBob Moore 
10278a335a23SBob Moore 	owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id;
10288a335a23SBob Moore 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
10298a335a23SBob Moore 
10308a335a23SBob Moore 	/*
10318a335a23SBob Moore 	 * Need to acquire the namespace writer lock to prevent interference
10328a335a23SBob Moore 	 * with any concurrent namespace walks. The interpreter must be
10338a335a23SBob Moore 	 * released during the deletion since the acquisition of the deletion
10348a335a23SBob Moore 	 * lock may block, and also since the execution of a namespace walk
10358a335a23SBob Moore 	 * must be allowed to use the interpreter.
10368a335a23SBob Moore 	 */
1037e4c1ebfcSBob Moore 	(void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
10388a335a23SBob Moore 	status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock);
10398a335a23SBob Moore 
104095b482a8SLen Brown 	acpi_ns_delete_namespace_by_owner(owner_id);
10418a335a23SBob Moore 	if (ACPI_FAILURE(status)) {
10428a335a23SBob Moore 		return_ACPI_STATUS(status);
10438a335a23SBob Moore 	}
10448a335a23SBob Moore 
10458a335a23SBob Moore 	acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock);
10468a335a23SBob Moore 
10478a335a23SBob Moore 	status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
10488a335a23SBob Moore 	return_ACPI_STATUS(status);
104995b482a8SLen Brown }
105095b482a8SLen Brown 
105195b482a8SLen Brown /*******************************************************************************
105295b482a8SLen Brown  *
105395b482a8SLen Brown  * FUNCTION:    acpi_tb_allocate_owner_id
105495b482a8SLen Brown  *
105595b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
105695b482a8SLen Brown  *
105795b482a8SLen Brown  * RETURN:      Status
105895b482a8SLen Brown  *
105995b482a8SLen Brown  * DESCRIPTION: Allocates owner_id in table_desc
106095b482a8SLen Brown  *
106195b482a8SLen Brown  ******************************************************************************/
106295b482a8SLen Brown 
106395b482a8SLen Brown acpi_status acpi_tb_allocate_owner_id(u32 table_index)
106495b482a8SLen Brown {
106595b482a8SLen Brown 	acpi_status status = AE_BAD_PARAMETER;
106695b482a8SLen Brown 
106795b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
106895b482a8SLen Brown 
106995b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1070b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
107195b482a8SLen Brown 		status = acpi_ut_allocate_owner_id
107295b482a8SLen Brown 		    (&(acpi_gbl_root_table_list.tables[table_index].owner_id));
107395b482a8SLen Brown 	}
107495b482a8SLen Brown 
107595b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
107695b482a8SLen Brown 	return_ACPI_STATUS(status);
107795b482a8SLen Brown }
107895b482a8SLen Brown 
107995b482a8SLen Brown /*******************************************************************************
108095b482a8SLen Brown  *
108195b482a8SLen Brown  * FUNCTION:    acpi_tb_release_owner_id
108295b482a8SLen Brown  *
108395b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
108495b482a8SLen Brown  *
108595b482a8SLen Brown  * RETURN:      Status
108695b482a8SLen Brown  *
108795b482a8SLen Brown  * DESCRIPTION: Releases owner_id in table_desc
108895b482a8SLen Brown  *
108995b482a8SLen Brown  ******************************************************************************/
109095b482a8SLen Brown 
109195b482a8SLen Brown acpi_status acpi_tb_release_owner_id(u32 table_index)
109295b482a8SLen Brown {
109395b482a8SLen Brown 	acpi_status status = AE_BAD_PARAMETER;
109495b482a8SLen Brown 
109595b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_release_owner_id);
109695b482a8SLen Brown 
109795b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1098b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
109995b482a8SLen Brown 		acpi_ut_release_owner_id(&
110095b482a8SLen Brown 					 (acpi_gbl_root_table_list.
110195b482a8SLen Brown 					  tables[table_index].owner_id));
110295b482a8SLen Brown 		status = AE_OK;
110395b482a8SLen Brown 	}
110495b482a8SLen Brown 
110595b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
110695b482a8SLen Brown 	return_ACPI_STATUS(status);
110795b482a8SLen Brown }
110895b482a8SLen Brown 
110995b482a8SLen Brown /*******************************************************************************
111095b482a8SLen Brown  *
111195b482a8SLen Brown  * FUNCTION:    acpi_tb_get_owner_id
111295b482a8SLen Brown  *
111395b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
111495b482a8SLen Brown  *              owner_id            - Where the table owner_id is returned
111595b482a8SLen Brown  *
111695b482a8SLen Brown  * RETURN:      Status
111795b482a8SLen Brown  *
111895b482a8SLen Brown  * DESCRIPTION: returns owner_id for the ACPI table
111995b482a8SLen Brown  *
112095b482a8SLen Brown  ******************************************************************************/
112195b482a8SLen Brown 
112295b482a8SLen Brown acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id * owner_id)
112395b482a8SLen Brown {
112495b482a8SLen Brown 	acpi_status status = AE_BAD_PARAMETER;
112595b482a8SLen Brown 
112695b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_get_owner_id);
112795b482a8SLen Brown 
112895b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1129b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
113095b482a8SLen Brown 		*owner_id =
113195b482a8SLen Brown 		    acpi_gbl_root_table_list.tables[table_index].owner_id;
113295b482a8SLen Brown 		status = AE_OK;
113395b482a8SLen Brown 	}
113495b482a8SLen Brown 
113595b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
113695b482a8SLen Brown 	return_ACPI_STATUS(status);
113795b482a8SLen Brown }
113895b482a8SLen Brown 
113995b482a8SLen Brown /*******************************************************************************
114095b482a8SLen Brown  *
114195b482a8SLen Brown  * FUNCTION:    acpi_tb_is_table_loaded
114295b482a8SLen Brown  *
114395b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
114495b482a8SLen Brown  *
114595b482a8SLen Brown  * RETURN:      Table Loaded Flag
114695b482a8SLen Brown  *
114795b482a8SLen Brown  ******************************************************************************/
114895b482a8SLen Brown 
114995b482a8SLen Brown u8 acpi_tb_is_table_loaded(u32 table_index)
115095b482a8SLen Brown {
115195b482a8SLen Brown 	u8 is_loaded = FALSE;
115295b482a8SLen Brown 
115395b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1154b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
115595b482a8SLen Brown 		is_loaded = (u8)
1156ec41f193SBob Moore 		    (acpi_gbl_root_table_list.tables[table_index].flags &
1157ec41f193SBob Moore 		     ACPI_TABLE_IS_LOADED);
115895b482a8SLen Brown 	}
115995b482a8SLen Brown 
116095b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
116195b482a8SLen Brown 	return (is_loaded);
116295b482a8SLen Brown }
116395b482a8SLen Brown 
116495b482a8SLen Brown /*******************************************************************************
116595b482a8SLen Brown  *
116695b482a8SLen Brown  * FUNCTION:    acpi_tb_set_table_loaded_flag
116795b482a8SLen Brown  *
116895b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
116995b482a8SLen Brown  *              is_loaded           - TRUE if table is loaded, FALSE otherwise
117095b482a8SLen Brown  *
117195b482a8SLen Brown  * RETURN:      None
117295b482a8SLen Brown  *
117395b482a8SLen Brown  * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
117495b482a8SLen Brown  *
117595b482a8SLen Brown  ******************************************************************************/
117695b482a8SLen Brown 
117795b482a8SLen Brown void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded)
117895b482a8SLen Brown {
117995b482a8SLen Brown 
118095b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1181b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
118295b482a8SLen Brown 		if (is_loaded) {
118395b482a8SLen Brown 			acpi_gbl_root_table_list.tables[table_index].flags |=
118495b482a8SLen Brown 			    ACPI_TABLE_IS_LOADED;
118595b482a8SLen Brown 		} else {
118695b482a8SLen Brown 			acpi_gbl_root_table_list.tables[table_index].flags &=
118795b482a8SLen Brown 			    ~ACPI_TABLE_IS_LOADED;
118895b482a8SLen Brown 		}
118995b482a8SLen Brown 	}
119095b482a8SLen Brown 
119195b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
119295b482a8SLen Brown }
1193