xref: /openbmc/linux/drivers/acpi/acpica/tbinstal.c (revision ed6f1d44dae8a4eec42a74acae95cc177ee2e1ad)
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
54*ed6f1d44SBob Moore acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc,
5586dfc6f3SLv Zheng 			   acpi_physical_address address, u8 flags);
5686dfc6f3SLv Zheng 
57*ed6f1d44SBob Moore static void acpi_tb_release_temp_table(struct acpi_table_desc *table_desc);
5886dfc6f3SLv Zheng 
59*ed6f1d44SBob Moore static acpi_status acpi_tb_get_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  *
76*ed6f1d44SBob Moore  * DESCRIPTION: Acquire an ACPI table. It can be used for tables not
77*ed6f1d44SBob Moore  *              maintained in the 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) {
89*ed6f1d44SBob Moore 	case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
90dc156adfSLv Zheng 
917f9fc99cSLv Zheng 		table =
927f9fc99cSLv Zheng 		    acpi_os_map_memory(table_desc->address, table_desc->length);
93dc156adfSLv Zheng 		break;
94dc156adfSLv Zheng 
95*ed6f1d44SBob Moore 	case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
96*ed6f1d44SBob Moore 	case ACPI_TABLE_ORIGIN_EXTERNAL_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 	return (AE_OK);
1207f9fc99cSLv Zheng }
1217f9fc99cSLv Zheng 
1227f9fc99cSLv Zheng /*******************************************************************************
1237f9fc99cSLv Zheng  *
1247f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_release_table
1257f9fc99cSLv Zheng  *
1267f9fc99cSLv Zheng  * PARAMETERS:  table               - Pointer for the table
1277f9fc99cSLv Zheng  *              table_length        - Length for the table
1287f9fc99cSLv Zheng  *              table_flags         - Allocation flags for the table
1297f9fc99cSLv Zheng  *
1307f9fc99cSLv Zheng  * RETURN:      None
1317f9fc99cSLv Zheng  *
132*ed6f1d44SBob Moore  * DESCRIPTION: Release a table. The inverse of acpi_tb_acquire_table().
1337f9fc99cSLv Zheng  *
1347f9fc99cSLv Zheng  ******************************************************************************/
1357f9fc99cSLv Zheng 
1367f9fc99cSLv Zheng void
1377f9fc99cSLv Zheng acpi_tb_release_table(struct acpi_table_header *table,
1387f9fc99cSLv Zheng 		      u32 table_length, u8 table_flags)
1397f9fc99cSLv Zheng {
140*ed6f1d44SBob Moore 
1417f9fc99cSLv Zheng 	switch (table_flags & ACPI_TABLE_ORIGIN_MASK) {
142*ed6f1d44SBob Moore 	case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
1437f9fc99cSLv Zheng 
1447f9fc99cSLv Zheng 		acpi_os_unmap_memory(table, table_length);
1457f9fc99cSLv Zheng 		break;
1467f9fc99cSLv Zheng 
147*ed6f1d44SBob Moore 	case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
148*ed6f1d44SBob Moore 	case ACPI_TABLE_ORIGIN_EXTERNAL_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  *
196*ed6f1d44SBob Moore  * DESCRIPTION: Invalidate one internal ACPI table, this is the inverse 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  *
281*ed6f1d44SBob Moore  * FUNCTION:    acpi_tb_init_table_descriptor
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  *
290*ed6f1d44SBob Moore  * DESCRIPTION: Initialize a new table descriptor
29186dfc6f3SLv Zheng  *
29286dfc6f3SLv Zheng  ******************************************************************************/
29386dfc6f3SLv Zheng 
29486dfc6f3SLv Zheng void
295*ed6f1d44SBob Moore acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc,
29686dfc6f3SLv Zheng 			      acpi_physical_address address,
29786dfc6f3SLv Zheng 			      u8 flags, struct acpi_table_header *table)
29886dfc6f3SLv Zheng {
299*ed6f1d44SBob Moore 
30086dfc6f3SLv Zheng 	/*
301*ed6f1d44SBob Moore 	 * Initialize the table descriptor. Set the pointer to NULL, since the
30286dfc6f3SLv Zheng 	 * table is not fully mapped at this time.
30386dfc6f3SLv Zheng 	 */
30486dfc6f3SLv Zheng 	ACPI_MEMSET(table_desc, 0, sizeof(struct acpi_table_desc));
30586dfc6f3SLv Zheng 	table_desc->address = address;
30686dfc6f3SLv Zheng 	table_desc->length = table->length;
30786dfc6f3SLv Zheng 	table_desc->flags = flags;
30886dfc6f3SLv Zheng 	ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature);
30986dfc6f3SLv Zheng }
31086dfc6f3SLv Zheng 
31186dfc6f3SLv Zheng /*******************************************************************************
31286dfc6f3SLv Zheng  *
313*ed6f1d44SBob Moore  * FUNCTION:    acpi_tb_acquire_temp_table
31486dfc6f3SLv Zheng  *
31586dfc6f3SLv Zheng  * PARAMETERS:  table_desc          - Table descriptor to be acquired
31686dfc6f3SLv Zheng  *              address             - Address of the table
31786dfc6f3SLv Zheng  *              flags               - Allocation flags of the table
31886dfc6f3SLv Zheng  *
31986dfc6f3SLv Zheng  * RETURN:      Status
32086dfc6f3SLv Zheng  *
32186dfc6f3SLv Zheng  * DESCRIPTION: This function validates the table header to obtain the length
32286dfc6f3SLv Zheng  *              of a table and fills the table descriptor to make its state as
323*ed6f1d44SBob Moore  *              "INSTALLED". Such a table descriptor is only used for verified
32486dfc6f3SLv Zheng  *              installation.
32586dfc6f3SLv Zheng  *
32686dfc6f3SLv Zheng  ******************************************************************************/
32786dfc6f3SLv Zheng 
32886dfc6f3SLv Zheng static acpi_status
329*ed6f1d44SBob Moore acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc,
33086dfc6f3SLv Zheng 			   acpi_physical_address address, u8 flags)
33186dfc6f3SLv Zheng {
33286dfc6f3SLv Zheng 	struct acpi_table_header *table_header;
33386dfc6f3SLv Zheng 
33486dfc6f3SLv Zheng 	switch (flags & ACPI_TABLE_ORIGIN_MASK) {
335*ed6f1d44SBob Moore 	case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
33686dfc6f3SLv Zheng 
337*ed6f1d44SBob Moore 		/* Get the length of the full table from the header */
33886dfc6f3SLv Zheng 
33986dfc6f3SLv Zheng 		table_header =
34086dfc6f3SLv Zheng 		    acpi_os_map_memory(address,
34186dfc6f3SLv Zheng 				       sizeof(struct acpi_table_header));
34286dfc6f3SLv Zheng 		if (!table_header) {
34386dfc6f3SLv Zheng 			return (AE_NO_MEMORY);
34486dfc6f3SLv Zheng 		}
345*ed6f1d44SBob Moore 
346*ed6f1d44SBob Moore 		acpi_tb_init_table_descriptor(table_desc, address, flags,
347*ed6f1d44SBob Moore 					      table_header);
34886dfc6f3SLv Zheng 		acpi_os_unmap_memory(table_header,
34986dfc6f3SLv Zheng 				     sizeof(struct acpi_table_header));
35086dfc6f3SLv Zheng 		return (AE_OK);
35186dfc6f3SLv Zheng 
352*ed6f1d44SBob Moore 	case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
353*ed6f1d44SBob Moore 	case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
35486dfc6f3SLv Zheng 
35586dfc6f3SLv Zheng 		table_header = ACPI_CAST_PTR(struct acpi_table_header, address);
35686dfc6f3SLv Zheng 		if (!table_header) {
35786dfc6f3SLv Zheng 			return (AE_NO_MEMORY);
35886dfc6f3SLv Zheng 		}
359*ed6f1d44SBob Moore 
360*ed6f1d44SBob Moore 		acpi_tb_init_table_descriptor(table_desc, address, flags,
361*ed6f1d44SBob Moore 					      table_header);
36286dfc6f3SLv Zheng 		return (AE_OK);
36386dfc6f3SLv Zheng 
36486dfc6f3SLv Zheng 	default:
36586dfc6f3SLv Zheng 
36686dfc6f3SLv Zheng 		break;
36786dfc6f3SLv Zheng 	}
36886dfc6f3SLv Zheng 
36986dfc6f3SLv Zheng 	/* Table is not valid yet */
37086dfc6f3SLv Zheng 
37186dfc6f3SLv Zheng 	return (AE_NO_MEMORY);
37286dfc6f3SLv Zheng }
37386dfc6f3SLv Zheng 
37486dfc6f3SLv Zheng /*******************************************************************************
37586dfc6f3SLv Zheng  *
376*ed6f1d44SBob Moore  * FUNCTION:    acpi_tb_release_temp_table
37786dfc6f3SLv Zheng  *
37886dfc6f3SLv Zheng  * PARAMETERS:  table_desc          - Table descriptor to be released
37986dfc6f3SLv Zheng  *
38086dfc6f3SLv Zheng  * RETURN:      Status
38186dfc6f3SLv Zheng  *
382*ed6f1d44SBob Moore  * DESCRIPTION: The inverse of acpi_tb_acquire_temp_table().
38386dfc6f3SLv Zheng  *
38486dfc6f3SLv Zheng  ******************************************************************************/
38586dfc6f3SLv Zheng 
386*ed6f1d44SBob Moore static void acpi_tb_release_temp_table(struct acpi_table_desc *table_desc)
38786dfc6f3SLv Zheng {
388*ed6f1d44SBob Moore 
38986dfc6f3SLv Zheng 	/*
39086dfc6f3SLv Zheng 	 * Note that the .Address is maintained by the callers of
391*ed6f1d44SBob Moore 	 * acpi_tb_acquire_temp_table(), thus do not invoke acpi_tb_uninstall_table()
39286dfc6f3SLv Zheng 	 * where .Address will be freed.
39386dfc6f3SLv Zheng 	 */
39486dfc6f3SLv Zheng 	acpi_tb_invalidate_table(table_desc);
39586dfc6f3SLv Zheng }
39686dfc6f3SLv Zheng 
39786dfc6f3SLv Zheng /*******************************************************************************
39886dfc6f3SLv Zheng  *
399*ed6f1d44SBob Moore  * FUNCTION:    acpi_tb_install_table_with_override
40086dfc6f3SLv Zheng  *
40186dfc6f3SLv Zheng  * PARAMETERS:  table_index             - Index into root table array
40286dfc6f3SLv Zheng  *              new_table_desc          - New table descriptor to install
403caf4a15cSLv Zheng  *              override                - Whether override should be performed
40486dfc6f3SLv Zheng  *
40586dfc6f3SLv Zheng  * RETURN:      None
40686dfc6f3SLv Zheng  *
40786dfc6f3SLv Zheng  * DESCRIPTION: Install an ACPI table into the global data structure. The
40886dfc6f3SLv Zheng  *              table override mechanism is called to allow the host
40986dfc6f3SLv Zheng  *              OS to replace any table before it is installed in the root
41086dfc6f3SLv Zheng  *              table array.
41186dfc6f3SLv Zheng  *
41286dfc6f3SLv Zheng  ******************************************************************************/
41386dfc6f3SLv Zheng 
41486dfc6f3SLv Zheng void
415*ed6f1d44SBob Moore acpi_tb_install_table_with_override(u32 table_index,
416caf4a15cSLv Zheng 				    struct acpi_table_desc *new_table_desc,
417caf4a15cSLv Zheng 				    u8 override)
41886dfc6f3SLv Zheng {
419*ed6f1d44SBob Moore 
42086dfc6f3SLv Zheng 	if (table_index >= acpi_gbl_root_table_list.current_table_count) {
42186dfc6f3SLv Zheng 		return;
42286dfc6f3SLv Zheng 	}
42386dfc6f3SLv Zheng 
42486dfc6f3SLv Zheng 	/*
42586dfc6f3SLv Zheng 	 * ACPI Table Override:
42686dfc6f3SLv Zheng 	 *
42786dfc6f3SLv Zheng 	 * Before we install the table, let the host OS override it with a new
42886dfc6f3SLv Zheng 	 * one if desired. Any table within the RSDT/XSDT can be replaced,
42986dfc6f3SLv Zheng 	 * including the DSDT which is pointed to by the FADT.
43086dfc6f3SLv Zheng 	 */
431caf4a15cSLv Zheng 	if (override) {
43286dfc6f3SLv Zheng 		acpi_tb_override_table(new_table_desc);
433caf4a15cSLv Zheng 	}
43486dfc6f3SLv Zheng 
435*ed6f1d44SBob Moore 	acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.
436*ed6f1d44SBob Moore 				      tables[table_index],
437*ed6f1d44SBob Moore 				      new_table_desc->address,
438*ed6f1d44SBob Moore 				      new_table_desc->flags,
43986dfc6f3SLv Zheng 				      new_table_desc->pointer);
44086dfc6f3SLv Zheng 
44186dfc6f3SLv Zheng 	acpi_tb_print_table_header(new_table_desc->address,
44286dfc6f3SLv Zheng 				   new_table_desc->pointer);
44386dfc6f3SLv Zheng 
44486dfc6f3SLv Zheng 	/* Set the global integer width (based upon revision of the DSDT) */
44586dfc6f3SLv Zheng 
44686dfc6f3SLv Zheng 	if (table_index == ACPI_TABLE_INDEX_DSDT) {
44786dfc6f3SLv Zheng 		acpi_ut_set_integer_width(new_table_desc->pointer->revision);
44886dfc6f3SLv Zheng 	}
44986dfc6f3SLv Zheng }
45086dfc6f3SLv Zheng 
45186dfc6f3SLv Zheng /*******************************************************************************
45286dfc6f3SLv Zheng  *
45386dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_install_fixed_table
45486dfc6f3SLv Zheng  *
45586dfc6f3SLv Zheng  * PARAMETERS:  address                 - Physical address of DSDT or FACS
45686dfc6f3SLv Zheng  *              signature               - Table signature, NULL if no need to
45786dfc6f3SLv Zheng  *                                        match
45886dfc6f3SLv Zheng  *              table_index             - Index into root table array
45986dfc6f3SLv Zheng  *
46086dfc6f3SLv Zheng  * RETURN:      Status
46186dfc6f3SLv Zheng  *
46286dfc6f3SLv Zheng  * DESCRIPTION: Install a fixed ACPI table (DSDT/FACS) into the global data
46386dfc6f3SLv Zheng  *              structure.
46495b482a8SLen Brown  *
46595b482a8SLen Brown  ******************************************************************************/
46695b482a8SLen Brown 
46795b482a8SLen Brown acpi_status
46886dfc6f3SLv Zheng acpi_tb_install_fixed_table(acpi_physical_address address,
46986dfc6f3SLv Zheng 			    char *signature, u32 table_index)
47086dfc6f3SLv Zheng {
47186dfc6f3SLv Zheng 	struct acpi_table_desc new_table_desc;
47286dfc6f3SLv Zheng 	acpi_status status;
47386dfc6f3SLv Zheng 
47486dfc6f3SLv Zheng 	ACPI_FUNCTION_TRACE(tb_install_fixed_table);
47586dfc6f3SLv Zheng 
47686dfc6f3SLv Zheng 	if (!address) {
47786dfc6f3SLv Zheng 		ACPI_ERROR((AE_INFO,
47886dfc6f3SLv Zheng 			    "Null physical address for ACPI table [%s]",
47986dfc6f3SLv Zheng 			    signature));
48086dfc6f3SLv Zheng 		return (AE_NO_MEMORY);
48186dfc6f3SLv Zheng 	}
48286dfc6f3SLv Zheng 
48386dfc6f3SLv Zheng 	/* Fill a table descriptor for validation */
48486dfc6f3SLv Zheng 
485*ed6f1d44SBob Moore 	status = acpi_tb_acquire_temp_table(&new_table_desc, address,
486*ed6f1d44SBob Moore 					    ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL);
48786dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
48886dfc6f3SLv Zheng 		ACPI_ERROR((AE_INFO, "Could not acquire table length at %p",
48986dfc6f3SLv Zheng 			    ACPI_CAST_PTR(void, address)));
49086dfc6f3SLv Zheng 		return_ACPI_STATUS(status);
49186dfc6f3SLv Zheng 	}
49286dfc6f3SLv Zheng 
49386dfc6f3SLv Zheng 	/* Validate and verify a table before installation */
49486dfc6f3SLv Zheng 
49586dfc6f3SLv Zheng 	status = acpi_tb_verify_table(&new_table_desc, signature);
49686dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
49786dfc6f3SLv Zheng 		goto release_and_exit;
49886dfc6f3SLv Zheng 	}
49986dfc6f3SLv Zheng 
500*ed6f1d44SBob Moore 	acpi_tb_install_table_with_override(table_index, &new_table_desc, TRUE);
50186dfc6f3SLv Zheng 
50286dfc6f3SLv Zheng release_and_exit:
50386dfc6f3SLv Zheng 
504*ed6f1d44SBob Moore 	/* Release the temporary table descriptor */
50586dfc6f3SLv Zheng 
506*ed6f1d44SBob Moore 	acpi_tb_release_temp_table(&new_table_desc);
50786dfc6f3SLv Zheng 	return_ACPI_STATUS(status);
50886dfc6f3SLv Zheng }
50986dfc6f3SLv Zheng 
51086dfc6f3SLv Zheng /*******************************************************************************
51186dfc6f3SLv Zheng  *
51286dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_is_equivalent_table
51386dfc6f3SLv Zheng  *
51486dfc6f3SLv Zheng  * PARAMETERS:  table_desc          - Table 1 descriptor to be compared
51586dfc6f3SLv Zheng  *              table_index         - Index of table 2 to be compared
51686dfc6f3SLv Zheng  *
51786dfc6f3SLv Zheng  * RETURN:      TRUE if 2 tables are equivalent
51886dfc6f3SLv Zheng  *
51986dfc6f3SLv Zheng  * DESCRIPTION: This function is called to compare a table with what have
52086dfc6f3SLv Zheng  *              already been installed in the root table list.
52186dfc6f3SLv Zheng  *
52286dfc6f3SLv Zheng  ******************************************************************************/
52386dfc6f3SLv Zheng 
52486dfc6f3SLv Zheng static u8
52586dfc6f3SLv Zheng acpi_tb_is_equivalent_table(struct acpi_table_desc *table_desc, u32 table_index)
52686dfc6f3SLv Zheng {
52786dfc6f3SLv Zheng 	acpi_status status = AE_OK;
52886dfc6f3SLv Zheng 	u8 is_equivalent;
52986dfc6f3SLv Zheng 	struct acpi_table_header *table;
53086dfc6f3SLv Zheng 	u32 table_length;
53186dfc6f3SLv Zheng 	u8 table_flags;
53286dfc6f3SLv Zheng 
53386dfc6f3SLv Zheng 	status =
53486dfc6f3SLv Zheng 	    acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index],
53586dfc6f3SLv Zheng 				  &table, &table_length, &table_flags);
53686dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
53786dfc6f3SLv Zheng 		return (FALSE);
53886dfc6f3SLv Zheng 	}
53986dfc6f3SLv Zheng 
54086dfc6f3SLv Zheng 	/*
54186dfc6f3SLv Zheng 	 * Check for a table match on the entire table length,
54286dfc6f3SLv Zheng 	 * not just the header.
54386dfc6f3SLv Zheng 	 */
54486dfc6f3SLv Zheng 	is_equivalent = (u8)((table_desc->length != table_length ||
54586dfc6f3SLv Zheng 			      ACPI_MEMCMP(table_desc->pointer, table,
54686dfc6f3SLv Zheng 					  table_length)) ? FALSE : TRUE);
54786dfc6f3SLv Zheng 
54886dfc6f3SLv Zheng 	/* Release the acquired table */
54986dfc6f3SLv Zheng 
55086dfc6f3SLv Zheng 	acpi_tb_release_table(table, table_length, table_flags);
55186dfc6f3SLv Zheng 	return (is_equivalent);
55286dfc6f3SLv Zheng }
55386dfc6f3SLv Zheng 
55486dfc6f3SLv Zheng /*******************************************************************************
55586dfc6f3SLv Zheng  *
556*ed6f1d44SBob Moore  * FUNCTION:    acpi_tb_install_standard_table
55786dfc6f3SLv Zheng  *
5588a216d7fSLv Zheng  * PARAMETERS:  address             - Address of the table (might be a virtual
55986dfc6f3SLv Zheng  *                                    address depending on the table_flags)
56086dfc6f3SLv Zheng  *              flags               - Flags for the table
56186dfc6f3SLv Zheng  *              reload              - Whether reload should be performed
562caf4a15cSLv Zheng  *              override            - Whether override should be performed
56386dfc6f3SLv Zheng  *              table_index         - Where the table index is returned
56486dfc6f3SLv Zheng  *
56586dfc6f3SLv Zheng  * RETURN:      Status
56686dfc6f3SLv Zheng  *
56786dfc6f3SLv Zheng  * DESCRIPTION: This function is called to install an ACPI table that is
568*ed6f1d44SBob Moore  *              neither DSDT nor FACS (a "standard" table.)
56986dfc6f3SLv Zheng  *              When this function is called by "Load" or "LoadTable" opcodes,
57086dfc6f3SLv Zheng  *              or by acpi_load_table() API, the "Reload" parameter is set.
57186dfc6f3SLv Zheng  *              After sucessfully returning from this function, table is
57286dfc6f3SLv Zheng  *              "INSTALLED" but not "VALIDATED".
57386dfc6f3SLv Zheng  *
57486dfc6f3SLv Zheng  ******************************************************************************/
57586dfc6f3SLv Zheng 
57686dfc6f3SLv Zheng acpi_status
577*ed6f1d44SBob Moore acpi_tb_install_standard_table(acpi_physical_address address,
578caf4a15cSLv Zheng 			       u8 flags,
579caf4a15cSLv Zheng 			       u8 reload, u8 override, u32 *table_index)
58095b482a8SLen Brown {
58195b482a8SLen Brown 	u32 i;
58295b482a8SLen Brown 	acpi_status status = AE_OK;
58386dfc6f3SLv Zheng 	struct acpi_table_desc new_table_desc;
58495b482a8SLen Brown 
585*ed6f1d44SBob Moore 	ACPI_FUNCTION_TRACE(tb_install_standard_table);
58695b482a8SLen Brown 
587*ed6f1d44SBob Moore 	/* Acquire a temporary table descriptor for validation */
58886dfc6f3SLv Zheng 
589*ed6f1d44SBob Moore 	status = acpi_tb_acquire_temp_table(&new_table_desc, address, flags);
59086dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
59186dfc6f3SLv Zheng 		ACPI_ERROR((AE_INFO, "Could not acquire table length at %p",
59286dfc6f3SLv Zheng 			    ACPI_CAST_PTR(void, address)));
59395b482a8SLen Brown 		return_ACPI_STATUS(status);
59495b482a8SLen Brown 	}
59586dfc6f3SLv Zheng 
596a94e88cdSLv Zheng 	/*
597a94e88cdSLv Zheng 	 * Optionally do not load any SSDTs from the RSDT/XSDT. This can
598a94e88cdSLv Zheng 	 * be useful for debugging ACPI problems on some machines.
599a94e88cdSLv Zheng 	 */
600*ed6f1d44SBob Moore 	if (!reload &&
601*ed6f1d44SBob Moore 	    acpi_gbl_disable_ssdt_table_install &&
602a94e88cdSLv Zheng 	    ACPI_COMPARE_NAME(&new_table_desc.signature, ACPI_SIG_SSDT)) {
603a94e88cdSLv Zheng 		ACPI_INFO((AE_INFO, "Ignoring installation of %4.4s at %p",
604a94e88cdSLv Zheng 			   new_table_desc.signature.ascii, ACPI_CAST_PTR(void,
605a94e88cdSLv Zheng 									 address)));
606a94e88cdSLv Zheng 		goto release_and_exit;
607a94e88cdSLv Zheng 	}
608a94e88cdSLv Zheng 
60986dfc6f3SLv Zheng 	/* Validate and verify a table before installation */
61086dfc6f3SLv Zheng 
61186dfc6f3SLv Zheng 	status = acpi_tb_verify_table(&new_table_desc, NULL);
61286dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
61386dfc6f3SLv Zheng 		goto release_and_exit;
61495b482a8SLen Brown 	}
61595b482a8SLen Brown 
61686dfc6f3SLv Zheng 	if (reload) {
61795b482a8SLen Brown 		/*
618c8cefe30SBob Moore 		 * Validate the incoming table signature.
619c8cefe30SBob Moore 		 *
620c8cefe30SBob Moore 		 * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
621c8cefe30SBob Moore 		 * 2) We added support for OEMx tables, signature "OEM".
622c8cefe30SBob Moore 		 * 3) Valid tables were encountered with a null signature, so we just
623c8cefe30SBob Moore 		 *    gave up on validating the signature, (05/2008).
624c8cefe30SBob Moore 		 * 4) We encountered non-AML tables such as the MADT, which caused
625c8cefe30SBob Moore 		 *    interpreter errors and kernel faults. So now, we once again allow
626c8cefe30SBob Moore 		 *    only "SSDT", "OEMx", and now, also a null signature. (05/2011).
62795b482a8SLen Brown 		 */
62886dfc6f3SLv Zheng 		if ((new_table_desc.signature.ascii[0] != 0x00) &&
62986dfc6f3SLv Zheng 		    (!ACPI_COMPARE_NAME
63086dfc6f3SLv Zheng 		     (&new_table_desc.signature, ACPI_SIG_SSDT))
63186dfc6f3SLv Zheng 		    && (ACPI_STRNCMP(new_table_desc.signature.ascii, "OEM", 3)))
63286dfc6f3SLv Zheng 		{
6333b3ea775SBob Moore 			ACPI_BIOS_ERROR((AE_INFO,
6343b3ea775SBob Moore 					 "Table has invalid signature [%4.4s] (0x%8.8X), "
6353b3ea775SBob Moore 					 "must be SSDT or OEMx",
63686dfc6f3SLv Zheng 					 acpi_ut_valid_acpi_name(new_table_desc.
63786dfc6f3SLv Zheng 								 signature.
63886dfc6f3SLv Zheng 								 ascii) ?
63986dfc6f3SLv Zheng 					 new_table_desc.signature.
64086dfc6f3SLv Zheng 					 ascii : "????",
64186dfc6f3SLv Zheng 					 new_table_desc.signature.integer));
642c8cefe30SBob Moore 
64386dfc6f3SLv Zheng 			status = AE_BAD_SIGNATURE;
64486dfc6f3SLv Zheng 			goto release_and_exit;
645c8cefe30SBob Moore 		}
64695b482a8SLen Brown 
64795b482a8SLen Brown 		/* Check if table is already registered */
64895b482a8SLen Brown 
64986dfc6f3SLv Zheng 		for (i = 0; i < acpi_gbl_root_table_list.current_table_count;
65086dfc6f3SLv Zheng 		     ++i) {
65195b482a8SLen Brown 			/*
65295b482a8SLen Brown 			 * Check for a table match on the entire table length,
65395b482a8SLen Brown 			 * not just the header.
65495b482a8SLen Brown 			 */
65586dfc6f3SLv Zheng 			if (!acpi_tb_is_equivalent_table(&new_table_desc, i)) {
65695b482a8SLen Brown 				continue;
65795b482a8SLen Brown 			}
65895b482a8SLen Brown 
65995b482a8SLen Brown 			/*
66095b482a8SLen Brown 			 * Note: the current mechanism does not unregister a table if it is
66195b482a8SLen Brown 			 * dynamically unloaded. The related namespace entries are deleted,
66295b482a8SLen Brown 			 * but the table remains in the root table list.
66395b482a8SLen Brown 			 *
66495b482a8SLen Brown 			 * The assumption here is that the number of different tables that
66595b482a8SLen Brown 			 * will be loaded is actually small, and there is minimal overhead
66695b482a8SLen Brown 			 * in just keeping the table in case it is needed again.
66795b482a8SLen Brown 			 *
66895b482a8SLen Brown 			 * If this assumption changes in the future (perhaps on large
66995b482a8SLen Brown 			 * machines with many table load/unload operations), tables will
67095b482a8SLen Brown 			 * need to be unregistered when they are unloaded, and slots in the
67195b482a8SLen Brown 			 * root table list should be reused when empty.
67295b482a8SLen Brown 			 */
67395b482a8SLen Brown 			if (acpi_gbl_root_table_list.tables[i].
67495b482a8SLen Brown 			    flags & ACPI_TABLE_IS_LOADED) {
67595b482a8SLen Brown 
67695b482a8SLen Brown 				/* Table is still loaded, this is an error */
67795b482a8SLen Brown 
67895b482a8SLen Brown 				status = AE_ALREADY_EXISTS;
67986dfc6f3SLv Zheng 				goto release_and_exit;
68095b482a8SLen Brown 			} else {
681d3ccaff8SBob Moore 				/*
68286dfc6f3SLv Zheng 				 * Table was unloaded, allow it to be reloaded.
68386dfc6f3SLv Zheng 				 * As we are going to return AE_OK to the caller, we should
68486dfc6f3SLv Zheng 				 * take the responsibility of freeing the input descriptor.
68586dfc6f3SLv Zheng 				 * Refill the input descriptor to ensure
686*ed6f1d44SBob Moore 				 * acpi_tb_install_table_with_override() can be called again to
68786dfc6f3SLv Zheng 				 * indicate the re-installation.
688d3ccaff8SBob Moore 				 */
68986dfc6f3SLv Zheng 				acpi_tb_uninstall_table(&new_table_desc);
69086dfc6f3SLv Zheng 				*table_index = i;
69186dfc6f3SLv Zheng 				(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
69286dfc6f3SLv Zheng 				return_ACPI_STATUS(AE_OK);
69386dfc6f3SLv Zheng 			}
69486dfc6f3SLv Zheng 		}
6957f9fc99cSLv Zheng 	}
696d3ccaff8SBob Moore 
69795b482a8SLen Brown 	/* Add the table to the global root table list */
69895b482a8SLen Brown 
699*ed6f1d44SBob Moore 	status = acpi_tb_get_root_table_entry(&i);
70095b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
70186dfc6f3SLv Zheng 		goto release_and_exit;
70295b482a8SLen Brown 	}
703*ed6f1d44SBob Moore 
70486dfc6f3SLv Zheng 	*table_index = i;
705*ed6f1d44SBob Moore 	acpi_tb_install_table_with_override(i, &new_table_desc, override);
70695b482a8SLen Brown 
70786dfc6f3SLv Zheng release_and_exit:
70895b482a8SLen Brown 
709*ed6f1d44SBob Moore 	/* Release the temporary table descriptor */
71086dfc6f3SLv Zheng 
711*ed6f1d44SBob Moore 	acpi_tb_release_temp_table(&new_table_desc);
71295b482a8SLen Brown 	return_ACPI_STATUS(status);
71395b482a8SLen Brown }
71495b482a8SLen Brown 
71595b482a8SLen Brown /*******************************************************************************
71695b482a8SLen Brown  *
7177f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_override_table
718f7b004a1SBob Moore  *
71986dfc6f3SLv Zheng  * PARAMETERS:  old_table_desc      - Validated table descriptor to be
72086dfc6f3SLv Zheng  *                                    overridden
721f7b004a1SBob Moore  *
72286dfc6f3SLv Zheng  * RETURN:      None
723f7b004a1SBob Moore  *
724f7b004a1SBob Moore  * DESCRIPTION: Attempt table override by calling the OSL override functions.
725f7b004a1SBob Moore  *              Note: If the table is overridden, then the entire new table
7267f9fc99cSLv Zheng  *              is acquired and returned by this function.
72786dfc6f3SLv Zheng  *              Before/after invocation, the table descriptor is in a state
72886dfc6f3SLv Zheng  *              that is "VALIDATED".
729f7b004a1SBob Moore  *
730f7b004a1SBob Moore  ******************************************************************************/
731f7b004a1SBob Moore 
73286dfc6f3SLv Zheng void acpi_tb_override_table(struct acpi_table_desc *old_table_desc)
733f7b004a1SBob Moore {
734f7b004a1SBob Moore 	acpi_status status;
735f7b004a1SBob Moore 	char *override_type;
7367f9fc99cSLv Zheng 	struct acpi_table_desc new_table_desc;
73786dfc6f3SLv Zheng 	struct acpi_table_header *table;
73886dfc6f3SLv Zheng 	acpi_physical_address address;
73986dfc6f3SLv Zheng 	u32 length;
740f7b004a1SBob Moore 
741f7b004a1SBob Moore 	/* (1) Attempt logical override (returns a logical address) */
742f7b004a1SBob Moore 
74386dfc6f3SLv Zheng 	status = acpi_os_table_override(old_table_desc->pointer, &table);
74486dfc6f3SLv Zheng 	if (ACPI_SUCCESS(status) && table) {
745*ed6f1d44SBob Moore 		acpi_tb_acquire_temp_table(&new_table_desc,
74686dfc6f3SLv Zheng 					   ACPI_PTR_TO_PHYSADDR(table),
747*ed6f1d44SBob Moore 					   ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL);
748f7b004a1SBob Moore 		override_type = "Logical";
749f7b004a1SBob Moore 		goto finish_override;
750f7b004a1SBob Moore 	}
751f7b004a1SBob Moore 
752f7b004a1SBob Moore 	/* (2) Attempt physical override (returns a physical address) */
753f7b004a1SBob Moore 
75486dfc6f3SLv Zheng 	status = acpi_os_physical_table_override(old_table_desc->pointer,
75586dfc6f3SLv Zheng 						 &address, &length);
75686dfc6f3SLv Zheng 	if (ACPI_SUCCESS(status) && address && length) {
757*ed6f1d44SBob Moore 		acpi_tb_acquire_temp_table(&new_table_desc, address,
758*ed6f1d44SBob Moore 					   ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL);
759f7b004a1SBob Moore 		override_type = "Physical";
760f7b004a1SBob Moore 		goto finish_override;
761f7b004a1SBob Moore 	}
762f7b004a1SBob Moore 
76386dfc6f3SLv Zheng 	return;			/* There was no override */
764f7b004a1SBob Moore 
765f7b004a1SBob Moore finish_override:
766f7b004a1SBob Moore 
76786dfc6f3SLv Zheng 	/* Validate and verify a table before overriding */
76886dfc6f3SLv Zheng 
76986dfc6f3SLv Zheng 	status = acpi_tb_verify_table(&new_table_desc, NULL);
7707f9fc99cSLv Zheng 	if (ACPI_FAILURE(status)) {
77186dfc6f3SLv Zheng 		return;
7727f9fc99cSLv Zheng 	}
7737f9fc99cSLv Zheng 
7742e19f8d0SBob Moore 	ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT
7752e19f8d0SBob Moore 		   " %s table override, new table: " ACPI_PRINTF_UINT,
77686dfc6f3SLv Zheng 		   old_table_desc->signature.ascii,
77786dfc6f3SLv Zheng 		   ACPI_FORMAT_TO_UINT(old_table_desc->address),
7787f9fc99cSLv Zheng 		   override_type, ACPI_FORMAT_TO_UINT(new_table_desc.address)));
779f7b004a1SBob Moore 
78086dfc6f3SLv Zheng 	/* We can now uninstall the original table */
781f7b004a1SBob Moore 
78286dfc6f3SLv Zheng 	acpi_tb_uninstall_table(old_table_desc);
783f7b004a1SBob Moore 
78486dfc6f3SLv Zheng 	/*
78586dfc6f3SLv Zheng 	 * Replace the original table descriptor and keep its state as
78686dfc6f3SLv Zheng 	 * "VALIDATED".
78786dfc6f3SLv Zheng 	 */
788*ed6f1d44SBob Moore 	acpi_tb_init_table_descriptor(old_table_desc, new_table_desc.address,
789*ed6f1d44SBob Moore 				      new_table_desc.flags,
790*ed6f1d44SBob Moore 				      new_table_desc.pointer);
79186dfc6f3SLv Zheng 	acpi_tb_validate_table(old_table_desc);
792f7b004a1SBob Moore 
793*ed6f1d44SBob Moore 	/* Release the temporary table descriptor */
794f7b004a1SBob Moore 
795*ed6f1d44SBob Moore 	acpi_tb_release_temp_table(&new_table_desc);
796f7b004a1SBob Moore }
797f7b004a1SBob Moore 
798f7b004a1SBob Moore /*******************************************************************************
799f7b004a1SBob Moore  *
80095b482a8SLen Brown  * FUNCTION:    acpi_tb_resize_root_table_list
80195b482a8SLen Brown  *
80295b482a8SLen Brown  * PARAMETERS:  None
80395b482a8SLen Brown  *
80495b482a8SLen Brown  * RETURN:      Status
80595b482a8SLen Brown  *
80695b482a8SLen Brown  * DESCRIPTION: Expand the size of global table array
80795b482a8SLen Brown  *
80895b482a8SLen Brown  ******************************************************************************/
80995b482a8SLen Brown 
81095b482a8SLen Brown acpi_status acpi_tb_resize_root_table_list(void)
81195b482a8SLen Brown {
81295b482a8SLen Brown 	struct acpi_table_desc *tables;
8132bc198c1SLv Zheng 	u32 table_count;
81495b482a8SLen Brown 
81595b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
81695b482a8SLen Brown 
81795b482a8SLen Brown 	/* allow_resize flag is a parameter to acpi_initialize_tables */
81895b482a8SLen Brown 
81995b482a8SLen Brown 	if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) {
82095b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
82195b482a8SLen Brown 			    "Resize of Root Table Array is not allowed"));
82295b482a8SLen Brown 		return_ACPI_STATUS(AE_SUPPORT);
82395b482a8SLen Brown 	}
82495b482a8SLen Brown 
82595b482a8SLen Brown 	/* Increase the Table Array size */
82695b482a8SLen Brown 
8272bc198c1SLv Zheng 	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
8282bc198c1SLv Zheng 		table_count = acpi_gbl_root_table_list.max_table_count;
8292bc198c1SLv Zheng 	} else {
8302bc198c1SLv Zheng 		table_count = acpi_gbl_root_table_list.current_table_count;
8312bc198c1SLv Zheng 	}
8322bc198c1SLv Zheng 
8332bc198c1SLv Zheng 	tables = ACPI_ALLOCATE_ZEROED(((acpi_size) table_count +
834ec41f193SBob Moore 				       ACPI_ROOT_TABLE_SIZE_INCREMENT) *
835ec41f193SBob Moore 				      sizeof(struct acpi_table_desc));
83695b482a8SLen Brown 	if (!tables) {
83795b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
83895b482a8SLen Brown 			    "Could not allocate new root table array"));
83995b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_MEMORY);
84095b482a8SLen Brown 	}
84195b482a8SLen Brown 
84295b482a8SLen Brown 	/* Copy and free the previous table array */
84395b482a8SLen Brown 
84495b482a8SLen Brown 	if (acpi_gbl_root_table_list.tables) {
84595b482a8SLen Brown 		ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
8462bc198c1SLv Zheng 			    (acpi_size) table_count *
8472bc198c1SLv Zheng 			    sizeof(struct acpi_table_desc));
84895b482a8SLen Brown 
84995b482a8SLen Brown 		if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
85095b482a8SLen Brown 			ACPI_FREE(acpi_gbl_root_table_list.tables);
85195b482a8SLen Brown 		}
85295b482a8SLen Brown 	}
85395b482a8SLen Brown 
85495b482a8SLen Brown 	acpi_gbl_root_table_list.tables = tables;
8552bc198c1SLv Zheng 	acpi_gbl_root_table_list.max_table_count =
8562bc198c1SLv Zheng 	    table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT;
8572bc198c1SLv Zheng 	acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
85895b482a8SLen Brown 
85995b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
86095b482a8SLen Brown }
86195b482a8SLen Brown 
86295b482a8SLen Brown /*******************************************************************************
86395b482a8SLen Brown  *
864*ed6f1d44SBob Moore  * FUNCTION:    acpi_tb_get_root_table_entry
86586dfc6f3SLv Zheng  *
86686dfc6f3SLv Zheng  * PARAMETERS:  table_index         - Where table index is returned
86786dfc6f3SLv Zheng  *
86886dfc6f3SLv Zheng  * RETURN:      Status and table index.
86986dfc6f3SLv Zheng  *
87086dfc6f3SLv Zheng  * DESCRIPTION: Allocate a new ACPI table entry to the global table list
87186dfc6f3SLv Zheng  *
87286dfc6f3SLv Zheng  ******************************************************************************/
87386dfc6f3SLv Zheng 
874*ed6f1d44SBob Moore static acpi_status acpi_tb_get_root_table_entry(u32 *table_index)
87586dfc6f3SLv Zheng {
87686dfc6f3SLv Zheng 	acpi_status status;
87786dfc6f3SLv Zheng 
87886dfc6f3SLv Zheng 	/* Ensure that there is room for the table in the Root Table List */
87986dfc6f3SLv Zheng 
88086dfc6f3SLv Zheng 	if (acpi_gbl_root_table_list.current_table_count >=
88186dfc6f3SLv Zheng 	    acpi_gbl_root_table_list.max_table_count) {
88286dfc6f3SLv Zheng 		status = acpi_tb_resize_root_table_list();
88386dfc6f3SLv Zheng 		if (ACPI_FAILURE(status)) {
88486dfc6f3SLv Zheng 			return (status);
88586dfc6f3SLv Zheng 		}
88686dfc6f3SLv Zheng 	}
88786dfc6f3SLv Zheng 
88886dfc6f3SLv Zheng 	*table_index = acpi_gbl_root_table_list.current_table_count;
88986dfc6f3SLv Zheng 	acpi_gbl_root_table_list.current_table_count++;
89086dfc6f3SLv Zheng 	return (AE_OK);
89186dfc6f3SLv Zheng }
89286dfc6f3SLv Zheng 
89386dfc6f3SLv Zheng /*******************************************************************************
89486dfc6f3SLv Zheng  *
89595b482a8SLen Brown  * FUNCTION:    acpi_tb_store_table
89695b482a8SLen Brown  *
897ba494beeSBob Moore  * PARAMETERS:  address             - Table address
898ba494beeSBob Moore  *              table               - Table header
899ba494beeSBob Moore  *              length              - Table length
900*ed6f1d44SBob Moore  *              flags               - Install flags
901*ed6f1d44SBob Moore  *              table_index         - Where the table index is returned
90295b482a8SLen Brown  *
90395b482a8SLen Brown  * RETURN:      Status and table index.
90495b482a8SLen Brown  *
90595b482a8SLen Brown  * DESCRIPTION: Add an ACPI table to the global table list
90695b482a8SLen Brown  *
90795b482a8SLen Brown  ******************************************************************************/
90895b482a8SLen Brown 
90995b482a8SLen Brown acpi_status
91095b482a8SLen Brown acpi_tb_store_table(acpi_physical_address address,
91195b482a8SLen Brown 		    struct acpi_table_header * table,
91295b482a8SLen Brown 		    u32 length, u8 flags, u32 *table_index)
91395b482a8SLen Brown {
914b9ee2043SBob Moore 	acpi_status status;
91586dfc6f3SLv Zheng 	struct acpi_table_desc *table_desc;
91695b482a8SLen Brown 
917*ed6f1d44SBob Moore 	status = acpi_tb_get_root_table_entry(table_index);
91895b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
91995b482a8SLen Brown 		return (status);
92095b482a8SLen Brown 	}
921b9ee2043SBob Moore 
92295b482a8SLen Brown 	/* Initialize added table */
92395b482a8SLen Brown 
92486dfc6f3SLv Zheng 	table_desc = &acpi_gbl_root_table_list.tables[*table_index];
925*ed6f1d44SBob Moore 	acpi_tb_init_table_descriptor(table_desc, address, flags, table);
92686dfc6f3SLv Zheng 	table_desc->pointer = table;
927b9ee2043SBob Moore 	return (AE_OK);
92895b482a8SLen Brown }
92995b482a8SLen Brown 
93095b482a8SLen Brown /*******************************************************************************
93195b482a8SLen Brown  *
9327f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_uninstall_table
93395b482a8SLen Brown  *
9347f9fc99cSLv Zheng  * PARAMETERS:  table_desc          - Table descriptor
93595b482a8SLen Brown  *
93695b482a8SLen Brown  * RETURN:      None
93795b482a8SLen Brown  *
93895b482a8SLen Brown  * DESCRIPTION: Delete one internal ACPI table
93995b482a8SLen Brown  *
94095b482a8SLen Brown  ******************************************************************************/
94195b482a8SLen Brown 
9427f9fc99cSLv Zheng void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc)
94395b482a8SLen Brown {
9445582982dSLv Zheng 
9457f9fc99cSLv Zheng 	ACPI_FUNCTION_TRACE(tb_uninstall_table);
9465582982dSLv Zheng 
9477f9fc99cSLv Zheng 	/* Table must be installed */
9487f9fc99cSLv Zheng 
9497f9fc99cSLv Zheng 	if (!table_desc->address) {
9507f9fc99cSLv Zheng 		return_VOID;
95195b482a8SLen Brown 	}
9525582982dSLv Zheng 
9537f9fc99cSLv Zheng 	acpi_tb_invalidate_table(table_desc);
9541d1ea1b7SChao Guan 
9557f9fc99cSLv Zheng 	if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) ==
956*ed6f1d44SBob Moore 	    ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) {
9577f9fc99cSLv Zheng 		ACPI_FREE(ACPI_CAST_PTR(void, table_desc->address));
9587f9fc99cSLv Zheng 	}
9591d1ea1b7SChao Guan 
960dc156adfSLv Zheng 	table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL);
9617f9fc99cSLv Zheng 	return_VOID;
96295b482a8SLen Brown }
96395b482a8SLen Brown 
96495b482a8SLen Brown /*******************************************************************************
96595b482a8SLen Brown  *
96695b482a8SLen Brown  * FUNCTION:    acpi_tb_terminate
96795b482a8SLen Brown  *
96895b482a8SLen Brown  * PARAMETERS:  None
96995b482a8SLen Brown  *
97095b482a8SLen Brown  * RETURN:      None
97195b482a8SLen Brown  *
97295b482a8SLen Brown  * DESCRIPTION: Delete all internal ACPI tables
97395b482a8SLen Brown  *
97495b482a8SLen Brown  ******************************************************************************/
97595b482a8SLen Brown 
97695b482a8SLen Brown void acpi_tb_terminate(void)
97795b482a8SLen Brown {
97895b482a8SLen Brown 	u32 i;
97995b482a8SLen Brown 
98095b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_terminate);
98195b482a8SLen Brown 
98295b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
98395b482a8SLen Brown 
98495b482a8SLen Brown 	/* Delete the individual tables */
98595b482a8SLen Brown 
986b9ee2043SBob Moore 	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
9877f9fc99cSLv Zheng 		acpi_tb_uninstall_table(&acpi_gbl_root_table_list.tables[i]);
98895b482a8SLen Brown 	}
98995b482a8SLen Brown 
99095b482a8SLen Brown 	/*
99195b482a8SLen Brown 	 * Delete the root table array if allocated locally. Array cannot be
99295b482a8SLen Brown 	 * mapped, so we don't need to check for that flag.
99395b482a8SLen Brown 	 */
99495b482a8SLen Brown 	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
99595b482a8SLen Brown 		ACPI_FREE(acpi_gbl_root_table_list.tables);
99695b482a8SLen Brown 	}
99795b482a8SLen Brown 
99895b482a8SLen Brown 	acpi_gbl_root_table_list.tables = NULL;
99995b482a8SLen Brown 	acpi_gbl_root_table_list.flags = 0;
1000b9ee2043SBob Moore 	acpi_gbl_root_table_list.current_table_count = 0;
100195b482a8SLen Brown 
100295b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
100368aafc35SBob Moore 
1004*ed6f1d44SBob Moore 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
100568aafc35SBob Moore 	return_VOID;
100695b482a8SLen Brown }
100795b482a8SLen Brown 
100895b482a8SLen Brown /*******************************************************************************
100995b482a8SLen Brown  *
101095b482a8SLen Brown  * FUNCTION:    acpi_tb_delete_namespace_by_owner
101195b482a8SLen Brown  *
101295b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
101395b482a8SLen Brown  *
10148a335a23SBob Moore  * RETURN:      Status
101595b482a8SLen Brown  *
101695b482a8SLen Brown  * DESCRIPTION: Delete all namespace objects created when this table was loaded.
101795b482a8SLen Brown  *
101895b482a8SLen Brown  ******************************************************************************/
101995b482a8SLen Brown 
10208a335a23SBob Moore acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index)
102195b482a8SLen Brown {
102295b482a8SLen Brown 	acpi_owner_id owner_id;
10238a335a23SBob Moore 	acpi_status status;
102495b482a8SLen Brown 
10258a335a23SBob Moore 	ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner);
10268a335a23SBob Moore 
10278a335a23SBob Moore 	status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
10288a335a23SBob Moore 	if (ACPI_FAILURE(status)) {
10298a335a23SBob Moore 		return_ACPI_STATUS(status);
103095b482a8SLen Brown 	}
103195b482a8SLen Brown 
1032b9ee2043SBob Moore 	if (table_index >= acpi_gbl_root_table_list.current_table_count) {
10338a335a23SBob Moore 
10348a335a23SBob Moore 		/* The table index does not exist */
10358a335a23SBob Moore 
103695b482a8SLen Brown 		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
10378a335a23SBob Moore 		return_ACPI_STATUS(AE_NOT_EXIST);
10388a335a23SBob Moore 	}
10398a335a23SBob Moore 
10408a335a23SBob Moore 	/* Get the owner ID for this table, used to delete namespace nodes */
10418a335a23SBob Moore 
10428a335a23SBob Moore 	owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id;
10438a335a23SBob Moore 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
10448a335a23SBob Moore 
10458a335a23SBob Moore 	/*
10468a335a23SBob Moore 	 * Need to acquire the namespace writer lock to prevent interference
10478a335a23SBob Moore 	 * with any concurrent namespace walks. The interpreter must be
10488a335a23SBob Moore 	 * released during the deletion since the acquisition of the deletion
10498a335a23SBob Moore 	 * lock may block, and also since the execution of a namespace walk
10508a335a23SBob Moore 	 * must be allowed to use the interpreter.
10518a335a23SBob Moore 	 */
1052e4c1ebfcSBob Moore 	(void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
10538a335a23SBob Moore 	status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock);
10548a335a23SBob Moore 
105595b482a8SLen Brown 	acpi_ns_delete_namespace_by_owner(owner_id);
10568a335a23SBob Moore 	if (ACPI_FAILURE(status)) {
10578a335a23SBob Moore 		return_ACPI_STATUS(status);
10588a335a23SBob Moore 	}
10598a335a23SBob Moore 
10608a335a23SBob Moore 	acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock);
10618a335a23SBob Moore 
10628a335a23SBob Moore 	status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
10638a335a23SBob Moore 	return_ACPI_STATUS(status);
106495b482a8SLen Brown }
106595b482a8SLen Brown 
106695b482a8SLen Brown /*******************************************************************************
106795b482a8SLen Brown  *
106895b482a8SLen Brown  * FUNCTION:    acpi_tb_allocate_owner_id
106995b482a8SLen Brown  *
107095b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
107195b482a8SLen Brown  *
107295b482a8SLen Brown  * RETURN:      Status
107395b482a8SLen Brown  *
107495b482a8SLen Brown  * DESCRIPTION: Allocates owner_id in table_desc
107595b482a8SLen Brown  *
107695b482a8SLen Brown  ******************************************************************************/
107795b482a8SLen Brown 
107895b482a8SLen Brown acpi_status acpi_tb_allocate_owner_id(u32 table_index)
107995b482a8SLen Brown {
108095b482a8SLen Brown 	acpi_status status = AE_BAD_PARAMETER;
108195b482a8SLen Brown 
108295b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
108395b482a8SLen Brown 
108495b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1085b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
1086*ed6f1d44SBob Moore 		status =
1087*ed6f1d44SBob Moore 		    acpi_ut_allocate_owner_id(&
1088*ed6f1d44SBob Moore 					      (acpi_gbl_root_table_list.
1089*ed6f1d44SBob Moore 					       tables[table_index].owner_id));
109095b482a8SLen Brown 	}
109195b482a8SLen Brown 
109295b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
109395b482a8SLen Brown 	return_ACPI_STATUS(status);
109495b482a8SLen Brown }
109595b482a8SLen Brown 
109695b482a8SLen Brown /*******************************************************************************
109795b482a8SLen Brown  *
109895b482a8SLen Brown  * FUNCTION:    acpi_tb_release_owner_id
109995b482a8SLen Brown  *
110095b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
110195b482a8SLen Brown  *
110295b482a8SLen Brown  * RETURN:      Status
110395b482a8SLen Brown  *
110495b482a8SLen Brown  * DESCRIPTION: Releases owner_id in table_desc
110595b482a8SLen Brown  *
110695b482a8SLen Brown  ******************************************************************************/
110795b482a8SLen Brown 
110895b482a8SLen Brown acpi_status acpi_tb_release_owner_id(u32 table_index)
110995b482a8SLen Brown {
111095b482a8SLen Brown 	acpi_status status = AE_BAD_PARAMETER;
111195b482a8SLen Brown 
111295b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_release_owner_id);
111395b482a8SLen Brown 
111495b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1115b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
111695b482a8SLen Brown 		acpi_ut_release_owner_id(&
111795b482a8SLen Brown 					 (acpi_gbl_root_table_list.
111895b482a8SLen Brown 					  tables[table_index].owner_id));
111995b482a8SLen Brown 		status = AE_OK;
112095b482a8SLen Brown 	}
112195b482a8SLen Brown 
112295b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
112395b482a8SLen Brown 	return_ACPI_STATUS(status);
112495b482a8SLen Brown }
112595b482a8SLen Brown 
112695b482a8SLen Brown /*******************************************************************************
112795b482a8SLen Brown  *
112895b482a8SLen Brown  * FUNCTION:    acpi_tb_get_owner_id
112995b482a8SLen Brown  *
113095b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
113195b482a8SLen Brown  *              owner_id            - Where the table owner_id is returned
113295b482a8SLen Brown  *
113395b482a8SLen Brown  * RETURN:      Status
113495b482a8SLen Brown  *
113595b482a8SLen Brown  * DESCRIPTION: returns owner_id for the ACPI table
113695b482a8SLen Brown  *
113795b482a8SLen Brown  ******************************************************************************/
113895b482a8SLen Brown 
113995b482a8SLen Brown acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id * owner_id)
114095b482a8SLen Brown {
114195b482a8SLen Brown 	acpi_status status = AE_BAD_PARAMETER;
114295b482a8SLen Brown 
114395b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_get_owner_id);
114495b482a8SLen Brown 
114595b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1146b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
114795b482a8SLen Brown 		*owner_id =
114895b482a8SLen Brown 		    acpi_gbl_root_table_list.tables[table_index].owner_id;
114995b482a8SLen Brown 		status = AE_OK;
115095b482a8SLen Brown 	}
115195b482a8SLen Brown 
115295b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
115395b482a8SLen Brown 	return_ACPI_STATUS(status);
115495b482a8SLen Brown }
115595b482a8SLen Brown 
115695b482a8SLen Brown /*******************************************************************************
115795b482a8SLen Brown  *
115895b482a8SLen Brown  * FUNCTION:    acpi_tb_is_table_loaded
115995b482a8SLen Brown  *
1160*ed6f1d44SBob Moore  * PARAMETERS:  table_index         - Index into the root table
116195b482a8SLen Brown  *
116295b482a8SLen Brown  * RETURN:      Table Loaded Flag
116395b482a8SLen Brown  *
116495b482a8SLen Brown  ******************************************************************************/
116595b482a8SLen Brown 
116695b482a8SLen Brown u8 acpi_tb_is_table_loaded(u32 table_index)
116795b482a8SLen Brown {
116895b482a8SLen Brown 	u8 is_loaded = FALSE;
116995b482a8SLen Brown 
117095b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1171b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
117295b482a8SLen Brown 		is_loaded = (u8)
1173ec41f193SBob Moore 		    (acpi_gbl_root_table_list.tables[table_index].flags &
1174ec41f193SBob Moore 		     ACPI_TABLE_IS_LOADED);
117595b482a8SLen Brown 	}
117695b482a8SLen Brown 
117795b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
117895b482a8SLen Brown 	return (is_loaded);
117995b482a8SLen Brown }
118095b482a8SLen Brown 
118195b482a8SLen Brown /*******************************************************************************
118295b482a8SLen Brown  *
118395b482a8SLen Brown  * FUNCTION:    acpi_tb_set_table_loaded_flag
118495b482a8SLen Brown  *
118595b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
118695b482a8SLen Brown  *              is_loaded           - TRUE if table is loaded, FALSE otherwise
118795b482a8SLen Brown  *
118895b482a8SLen Brown  * RETURN:      None
118995b482a8SLen Brown  *
119095b482a8SLen Brown  * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
119195b482a8SLen Brown  *
119295b482a8SLen Brown  ******************************************************************************/
119395b482a8SLen Brown 
119495b482a8SLen Brown void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded)
119595b482a8SLen Brown {
119695b482a8SLen Brown 
119795b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1198b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
119995b482a8SLen Brown 		if (is_loaded) {
120095b482a8SLen Brown 			acpi_gbl_root_table_list.tables[table_index].flags |=
120195b482a8SLen Brown 			    ACPI_TABLE_IS_LOADED;
120295b482a8SLen Brown 		} else {
120395b482a8SLen Brown 			acpi_gbl_root_table_list.tables[table_index].flags &=
120495b482a8SLen Brown 			    ~ACPI_TABLE_IS_LOADED;
120595b482a8SLen Brown 		}
120695b482a8SLen Brown 	}
120795b482a8SLen Brown 
120895b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
120995b482a8SLen Brown }
1210