xref: /openbmc/linux/drivers/acpi/acpica/tbinstal.c (revision 86dfc6f339886559d80ee0d4bd20fe5ee90450f0)
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 
52*86dfc6f3SLv Zheng /* Local prototypes */
53*86dfc6f3SLv Zheng static acpi_status
54*86dfc6f3SLv Zheng acpi_tb_acquire_temporal_table(struct acpi_table_desc *table_desc,
55*86dfc6f3SLv Zheng 			       acpi_physical_address address, u8 flags);
56*86dfc6f3SLv Zheng 
57*86dfc6f3SLv Zheng static void acpi_tb_release_temporal_table(struct acpi_table_desc *table_desc);
58*86dfc6f3SLv Zheng 
59*86dfc6f3SLv Zheng static acpi_status acpi_tb_acquire_root_table_entry(u32 *table_index);
60*86dfc6f3SLv Zheng 
61*86dfc6f3SLv Zheng static u8
62*86dfc6f3SLv Zheng acpi_tb_is_equivalent_table(struct acpi_table_desc *table_desc,
63*86dfc6f3SLv Zheng 			    u32 table_index);
64*86dfc6f3SLv 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  ******************************************************************************/
80*86dfc6f3SLv 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) {
89dc156adfSLv Zheng 	case ACPI_TABLE_ORIGIN_MAPPED:
90dc156adfSLv Zheng 
917f9fc99cSLv Zheng 		table =
927f9fc99cSLv Zheng 		    acpi_os_map_memory(table_desc->address, table_desc->length);
93dc156adfSLv Zheng 		break;
94dc156adfSLv Zheng 
95dc156adfSLv Zheng 	case ACPI_TABLE_ORIGIN_ALLOCATED:
96dc156adfSLv Zheng 	case ACPI_TABLE_ORIGIN_UNKNOWN:
97dc156adfSLv Zheng 	case ACPI_TABLE_ORIGIN_OVERRIDE:
98dc156adfSLv Zheng 
997f9fc99cSLv Zheng 		table =
100dc156adfSLv Zheng 		    ACPI_CAST_PTR(struct acpi_table_header,
101dc156adfSLv Zheng 				  table_desc->address);
102dc156adfSLv Zheng 		break;
103dc156adfSLv Zheng 
104dc156adfSLv Zheng 	default:
105dc156adfSLv Zheng 
106dc156adfSLv Zheng 		break;
10795b482a8SLen Brown 	}
1085582982dSLv Zheng 
1097f9fc99cSLv Zheng 	/* Table is not valid yet */
1107f9fc99cSLv Zheng 
1117f9fc99cSLv Zheng 	if (!table) {
1127f9fc99cSLv Zheng 		return (AE_NO_MEMORY);
1137f9fc99cSLv Zheng 	}
1147f9fc99cSLv Zheng 
1157f9fc99cSLv Zheng 	/* Fill the return values */
1167f9fc99cSLv Zheng 
1177f9fc99cSLv Zheng 	*table_ptr = table;
1187f9fc99cSLv Zheng 	*table_length = table_desc->length;
1197f9fc99cSLv Zheng 	*table_flags = table_desc->flags;
1207f9fc99cSLv Zheng 
1217f9fc99cSLv Zheng 	return (AE_OK);
1227f9fc99cSLv Zheng }
1237f9fc99cSLv Zheng 
1247f9fc99cSLv Zheng /*******************************************************************************
1257f9fc99cSLv Zheng  *
1267f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_release_table
1277f9fc99cSLv Zheng  *
1287f9fc99cSLv Zheng  * PARAMETERS:  table               - Pointer for the table
1297f9fc99cSLv Zheng  *              table_length        - Length for the table
1307f9fc99cSLv Zheng  *              table_flags         - Allocation flags for the table
1317f9fc99cSLv Zheng  *
1327f9fc99cSLv Zheng  * RETURN:      None
1337f9fc99cSLv Zheng  *
1347f9fc99cSLv Zheng  * DESCRIPTION: Release a table. The reversal of acpi_tb_acquire_table().
1357f9fc99cSLv Zheng  *
1367f9fc99cSLv Zheng  ******************************************************************************/
1377f9fc99cSLv Zheng 
1387f9fc99cSLv Zheng void
1397f9fc99cSLv Zheng acpi_tb_release_table(struct acpi_table_header *table,
1407f9fc99cSLv Zheng 		      u32 table_length, u8 table_flags)
1417f9fc99cSLv Zheng {
1427f9fc99cSLv Zheng 	switch (table_flags & ACPI_TABLE_ORIGIN_MASK) {
1437f9fc99cSLv Zheng 	case ACPI_TABLE_ORIGIN_MAPPED:
1447f9fc99cSLv Zheng 
1457f9fc99cSLv Zheng 		acpi_os_unmap_memory(table, table_length);
1467f9fc99cSLv Zheng 		break;
1477f9fc99cSLv Zheng 
1487f9fc99cSLv Zheng 	case ACPI_TABLE_ORIGIN_ALLOCATED:
1497f9fc99cSLv Zheng 	case ACPI_TABLE_ORIGIN_UNKNOWN:
1507f9fc99cSLv Zheng 	case ACPI_TABLE_ORIGIN_OVERRIDE:
1517f9fc99cSLv Zheng 	default:
1527f9fc99cSLv Zheng 
1537f9fc99cSLv Zheng 		break;
1547f9fc99cSLv Zheng 	}
1557f9fc99cSLv Zheng }
1567f9fc99cSLv Zheng 
1577f9fc99cSLv Zheng /******************************************************************************
1587f9fc99cSLv Zheng  *
1597f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_validate_table
1607f9fc99cSLv Zheng  *
1617f9fc99cSLv Zheng  * PARAMETERS:  table_desc          - Table descriptor
1627f9fc99cSLv Zheng  *
1637f9fc99cSLv Zheng  * RETURN:      Status
1647f9fc99cSLv Zheng  *
165*86dfc6f3SLv Zheng  * DESCRIPTION: This function is called to validate the table, the returned
166*86dfc6f3SLv Zheng  *              table descriptor is in "VALIDATED" state.
1677f9fc99cSLv Zheng  *
1687f9fc99cSLv Zheng  *****************************************************************************/
1697f9fc99cSLv Zheng 
1707f9fc99cSLv Zheng acpi_status acpi_tb_validate_table(struct acpi_table_desc *table_desc)
1717f9fc99cSLv Zheng {
1727f9fc99cSLv Zheng 	acpi_status status = AE_OK;
1737f9fc99cSLv Zheng 
1747f9fc99cSLv Zheng 	ACPI_FUNCTION_TRACE(tb_validate_table);
1757f9fc99cSLv Zheng 
1767f9fc99cSLv Zheng 	/* Validate the table if necessary */
1777f9fc99cSLv Zheng 
17895b482a8SLen Brown 	if (!table_desc->pointer) {
1797f9fc99cSLv Zheng 		status = acpi_tb_acquire_table(table_desc, &table_desc->pointer,
1807f9fc99cSLv Zheng 					       &table_desc->length,
1817f9fc99cSLv Zheng 					       &table_desc->flags);
182*86dfc6f3SLv Zheng 		if (!table_desc->pointer) {
183*86dfc6f3SLv Zheng 			status = AE_NO_MEMORY;
18495b482a8SLen Brown 		}
18595b482a8SLen Brown 	}
18695b482a8SLen Brown 
18795b482a8SLen Brown 	return_ACPI_STATUS(status);
18895b482a8SLen Brown }
18995b482a8SLen Brown 
19095b482a8SLen Brown /*******************************************************************************
19195b482a8SLen Brown  *
1927f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_invalidate_table
1937f9fc99cSLv Zheng  *
1947f9fc99cSLv Zheng  * PARAMETERS:  table_desc          - Table descriptor
1957f9fc99cSLv Zheng  *
1967f9fc99cSLv Zheng  * RETURN:      None
1977f9fc99cSLv Zheng  *
1987f9fc99cSLv Zheng  * DESCRIPTION: Invalidate one internal ACPI table, this is reversal of
1997f9fc99cSLv Zheng  *              acpi_tb_validate_table().
2007f9fc99cSLv Zheng  *
2017f9fc99cSLv Zheng  ******************************************************************************/
2027f9fc99cSLv Zheng 
2037f9fc99cSLv Zheng void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc)
2047f9fc99cSLv Zheng {
2057f9fc99cSLv Zheng 
2067f9fc99cSLv Zheng 	ACPI_FUNCTION_TRACE(tb_invalidate_table);
2077f9fc99cSLv Zheng 
2087f9fc99cSLv Zheng 	/* Table must be validated */
2097f9fc99cSLv Zheng 
2107f9fc99cSLv Zheng 	if (!table_desc->pointer) {
2117f9fc99cSLv Zheng 		return_VOID;
2127f9fc99cSLv Zheng 	}
2137f9fc99cSLv Zheng 
2147f9fc99cSLv Zheng 	acpi_tb_release_table(table_desc->pointer, table_desc->length,
2157f9fc99cSLv Zheng 			      table_desc->flags);
2167f9fc99cSLv Zheng 	table_desc->pointer = NULL;
2177f9fc99cSLv Zheng 
2187f9fc99cSLv Zheng 	return_VOID;
2197f9fc99cSLv Zheng }
2207f9fc99cSLv Zheng 
221*86dfc6f3SLv Zheng /******************************************************************************
2227f9fc99cSLv Zheng  *
223*86dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_verify_table
22495b482a8SLen Brown  *
22595b482a8SLen Brown  * PARAMETERS:  table_desc          - Table descriptor
226*86dfc6f3SLv Zheng  *              signature           - Table signature to verify
22795b482a8SLen Brown  *
22895b482a8SLen Brown  * RETURN:      Status
22995b482a8SLen Brown  *
230*86dfc6f3SLv Zheng  * DESCRIPTION: This function is called to validate and verify the table, the
231*86dfc6f3SLv Zheng  *              returned table descriptor is in "VALIDATED" state.
232*86dfc6f3SLv Zheng  *
233*86dfc6f3SLv Zheng  *****************************************************************************/
234*86dfc6f3SLv Zheng 
235*86dfc6f3SLv Zheng acpi_status
236*86dfc6f3SLv Zheng acpi_tb_verify_table(struct acpi_table_desc *table_desc, char *signature)
237*86dfc6f3SLv Zheng {
238*86dfc6f3SLv Zheng 	acpi_status status = AE_OK;
239*86dfc6f3SLv Zheng 
240*86dfc6f3SLv Zheng 	ACPI_FUNCTION_TRACE(tb_verify_table);
241*86dfc6f3SLv Zheng 
242*86dfc6f3SLv Zheng 	/* Validate the table */
243*86dfc6f3SLv Zheng 
244*86dfc6f3SLv Zheng 	status = acpi_tb_validate_table(table_desc);
245*86dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
246*86dfc6f3SLv Zheng 		return_ACPI_STATUS(AE_NO_MEMORY);
247*86dfc6f3SLv Zheng 	}
248*86dfc6f3SLv Zheng 
249*86dfc6f3SLv Zheng 	/* If a particular signature is expected (DSDT/FACS), it must match */
250*86dfc6f3SLv Zheng 
251*86dfc6f3SLv Zheng 	if (signature && !ACPI_COMPARE_NAME(&table_desc->signature, signature)) {
252*86dfc6f3SLv Zheng 		ACPI_BIOS_ERROR((AE_INFO,
253*86dfc6f3SLv Zheng 				 "Invalid signature 0x%X for ACPI table, expected [%s]",
254*86dfc6f3SLv Zheng 				 table_desc->signature.integer, signature));
255*86dfc6f3SLv Zheng 		status = AE_BAD_SIGNATURE;
256*86dfc6f3SLv Zheng 		goto invalidate_and_exit;
257*86dfc6f3SLv Zheng 	}
258*86dfc6f3SLv Zheng 
259*86dfc6f3SLv Zheng 	/* Verify the checksum */
260*86dfc6f3SLv Zheng 
261*86dfc6f3SLv Zheng 	status =
262*86dfc6f3SLv Zheng 	    acpi_tb_verify_checksum(table_desc->pointer, table_desc->length);
263*86dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
264*86dfc6f3SLv Zheng 		ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
265*86dfc6f3SLv Zheng 				"%4.4s " ACPI_PRINTF_UINT
266*86dfc6f3SLv Zheng 				" Attempted table install failed",
267*86dfc6f3SLv Zheng 				acpi_ut_valid_acpi_name(table_desc->signature.
268*86dfc6f3SLv Zheng 							ascii) ? table_desc->
269*86dfc6f3SLv Zheng 				signature.ascii : "????",
270*86dfc6f3SLv Zheng 				ACPI_FORMAT_TO_UINT(table_desc->address)));
271*86dfc6f3SLv Zheng 		goto invalidate_and_exit;
272*86dfc6f3SLv Zheng 	}
273*86dfc6f3SLv Zheng 
274*86dfc6f3SLv Zheng 	return_ACPI_STATUS(AE_OK);
275*86dfc6f3SLv Zheng 
276*86dfc6f3SLv Zheng invalidate_and_exit:
277*86dfc6f3SLv Zheng 	acpi_tb_invalidate_table(table_desc);
278*86dfc6f3SLv Zheng 	return_ACPI_STATUS(status);
279*86dfc6f3SLv Zheng }
280*86dfc6f3SLv Zheng 
281*86dfc6f3SLv Zheng /*******************************************************************************
282*86dfc6f3SLv Zheng  *
283*86dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_install_table
284*86dfc6f3SLv Zheng  *
285*86dfc6f3SLv Zheng  * PARAMETERS:  table_desc              - Table descriptor
286*86dfc6f3SLv Zheng  *              address                 - Physical address of the table
287*86dfc6f3SLv Zheng  *              flags                   - Allocation flags of the table
288*86dfc6f3SLv Zheng  *              table                   - Pointer to the table
289*86dfc6f3SLv Zheng  *
290*86dfc6f3SLv Zheng  * RETURN:      None
291*86dfc6f3SLv Zheng  *
292*86dfc6f3SLv Zheng  * DESCRIPTION: Install an ACPI table into the global data structure.
293*86dfc6f3SLv Zheng  *
294*86dfc6f3SLv Zheng  ******************************************************************************/
295*86dfc6f3SLv Zheng 
296*86dfc6f3SLv Zheng void
297*86dfc6f3SLv Zheng acpi_tb_install_table(struct acpi_table_desc *table_desc,
298*86dfc6f3SLv Zheng 		      acpi_physical_address address,
299*86dfc6f3SLv Zheng 		      u8 flags, struct acpi_table_header *table)
300*86dfc6f3SLv Zheng {
301*86dfc6f3SLv Zheng 	/*
302*86dfc6f3SLv Zheng 	 * Initialize the table entry. Set the pointer to NULL, since the
303*86dfc6f3SLv Zheng 	 * table is not fully mapped at this time.
304*86dfc6f3SLv Zheng 	 */
305*86dfc6f3SLv Zheng 	ACPI_MEMSET(table_desc, 0, sizeof(struct acpi_table_desc));
306*86dfc6f3SLv Zheng 	table_desc->address = address;
307*86dfc6f3SLv Zheng 	table_desc->length = table->length;
308*86dfc6f3SLv Zheng 	table_desc->flags = flags;
309*86dfc6f3SLv Zheng 	ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature);
310*86dfc6f3SLv Zheng }
311*86dfc6f3SLv Zheng 
312*86dfc6f3SLv Zheng /*******************************************************************************
313*86dfc6f3SLv Zheng  *
314*86dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_acquire_temporal_table
315*86dfc6f3SLv Zheng  *
316*86dfc6f3SLv Zheng  * PARAMETERS:  table_desc          - Table descriptor to be acquired
317*86dfc6f3SLv Zheng  *              address             - Address of the table
318*86dfc6f3SLv Zheng  *              flags               - Allocation flags of the table
319*86dfc6f3SLv Zheng  *
320*86dfc6f3SLv Zheng  * RETURN:      Status
321*86dfc6f3SLv Zheng  *
322*86dfc6f3SLv Zheng  * DESCRIPTION: This function validates the table header to obtain the length
323*86dfc6f3SLv Zheng  *              of a table and fills the table descriptor to make its state as
324*86dfc6f3SLv Zheng  *              "INSTALLED".  Such table descriptor is only used for verified
325*86dfc6f3SLv Zheng  *              installation.
326*86dfc6f3SLv Zheng  *
327*86dfc6f3SLv Zheng  ******************************************************************************/
328*86dfc6f3SLv Zheng 
329*86dfc6f3SLv Zheng static acpi_status
330*86dfc6f3SLv Zheng acpi_tb_acquire_temporal_table(struct acpi_table_desc *table_desc,
331*86dfc6f3SLv Zheng 			       acpi_physical_address address, u8 flags)
332*86dfc6f3SLv Zheng {
333*86dfc6f3SLv Zheng 	struct acpi_table_header *table_header;
334*86dfc6f3SLv Zheng 
335*86dfc6f3SLv Zheng 	switch (flags & ACPI_TABLE_ORIGIN_MASK) {
336*86dfc6f3SLv Zheng 	case ACPI_TABLE_ORIGIN_MAPPED:
337*86dfc6f3SLv Zheng 
338*86dfc6f3SLv Zheng 		/* Try to obtain the length of the table */
339*86dfc6f3SLv Zheng 
340*86dfc6f3SLv Zheng 		table_header =
341*86dfc6f3SLv Zheng 		    acpi_os_map_memory(address,
342*86dfc6f3SLv Zheng 				       sizeof(struct acpi_table_header));
343*86dfc6f3SLv Zheng 		if (!table_header) {
344*86dfc6f3SLv Zheng 			return (AE_NO_MEMORY);
345*86dfc6f3SLv Zheng 		}
346*86dfc6f3SLv Zheng 		acpi_tb_install_table(table_desc, address, flags, table_header);
347*86dfc6f3SLv Zheng 		acpi_os_unmap_memory(table_header,
348*86dfc6f3SLv Zheng 				     sizeof(struct acpi_table_header));
349*86dfc6f3SLv Zheng 		return (AE_OK);
350*86dfc6f3SLv Zheng 
351*86dfc6f3SLv Zheng 	case ACPI_TABLE_ORIGIN_ALLOCATED:
352*86dfc6f3SLv Zheng 	case ACPI_TABLE_ORIGIN_UNKNOWN:
353*86dfc6f3SLv Zheng 	case ACPI_TABLE_ORIGIN_OVERRIDE:
354*86dfc6f3SLv Zheng 
355*86dfc6f3SLv Zheng 		table_header = ACPI_CAST_PTR(struct acpi_table_header, address);
356*86dfc6f3SLv Zheng 		if (!table_header) {
357*86dfc6f3SLv Zheng 			return (AE_NO_MEMORY);
358*86dfc6f3SLv Zheng 		}
359*86dfc6f3SLv Zheng 		acpi_tb_install_table(table_desc, address, flags, table_header);
360*86dfc6f3SLv Zheng 		return (AE_OK);
361*86dfc6f3SLv Zheng 
362*86dfc6f3SLv Zheng 	default:
363*86dfc6f3SLv Zheng 
364*86dfc6f3SLv Zheng 		break;
365*86dfc6f3SLv Zheng 	}
366*86dfc6f3SLv Zheng 
367*86dfc6f3SLv Zheng 	/* Table is not valid yet */
368*86dfc6f3SLv Zheng 
369*86dfc6f3SLv Zheng 	return (AE_NO_MEMORY);
370*86dfc6f3SLv Zheng }
371*86dfc6f3SLv Zheng 
372*86dfc6f3SLv Zheng /*******************************************************************************
373*86dfc6f3SLv Zheng  *
374*86dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_release_temporal_table
375*86dfc6f3SLv Zheng  *
376*86dfc6f3SLv Zheng  * PARAMETERS:  table_desc          - Table descriptor to be released
377*86dfc6f3SLv Zheng  *
378*86dfc6f3SLv Zheng  * RETURN:      Status
379*86dfc6f3SLv Zheng  *
380*86dfc6f3SLv Zheng  * DESCRIPTION: The reversal of acpi_tb_acquire_temporal_table().
381*86dfc6f3SLv Zheng  *
382*86dfc6f3SLv Zheng  ******************************************************************************/
383*86dfc6f3SLv Zheng 
384*86dfc6f3SLv Zheng static void acpi_tb_release_temporal_table(struct acpi_table_desc *table_desc)
385*86dfc6f3SLv Zheng {
386*86dfc6f3SLv Zheng 	/*
387*86dfc6f3SLv Zheng 	 * Note that the .Address is maintained by the callers of
388*86dfc6f3SLv Zheng 	 * acpi_tb_acquire_temporal_table(), thus do not invoke acpi_tb_uninstall_table()
389*86dfc6f3SLv Zheng 	 * where .Address will be freed.
390*86dfc6f3SLv Zheng 	 */
391*86dfc6f3SLv Zheng 	acpi_tb_invalidate_table(table_desc);
392*86dfc6f3SLv Zheng }
393*86dfc6f3SLv Zheng 
394*86dfc6f3SLv Zheng /*******************************************************************************
395*86dfc6f3SLv Zheng  *
396*86dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_install_and_override_table
397*86dfc6f3SLv Zheng  *
398*86dfc6f3SLv Zheng  * PARAMETERS:  table_index             - Index into root table array
399*86dfc6f3SLv Zheng  *              new_table_desc          - New table descriptor to install
400*86dfc6f3SLv Zheng  *
401*86dfc6f3SLv Zheng  * RETURN:      None
402*86dfc6f3SLv Zheng  *
403*86dfc6f3SLv Zheng  * DESCRIPTION: Install an ACPI table into the global data structure. The
404*86dfc6f3SLv Zheng  *              table override mechanism is called to allow the host
405*86dfc6f3SLv Zheng  *              OS to replace any table before it is installed in the root
406*86dfc6f3SLv Zheng  *              table array.
407*86dfc6f3SLv Zheng  *
408*86dfc6f3SLv Zheng  ******************************************************************************/
409*86dfc6f3SLv Zheng 
410*86dfc6f3SLv Zheng void
411*86dfc6f3SLv Zheng acpi_tb_install_and_override_table(u32 table_index,
412*86dfc6f3SLv Zheng 				   struct acpi_table_desc *new_table_desc)
413*86dfc6f3SLv Zheng {
414*86dfc6f3SLv Zheng 	if (table_index >= acpi_gbl_root_table_list.current_table_count) {
415*86dfc6f3SLv Zheng 		return;
416*86dfc6f3SLv Zheng 	}
417*86dfc6f3SLv Zheng 
418*86dfc6f3SLv Zheng 	/*
419*86dfc6f3SLv Zheng 	 * ACPI Table Override:
420*86dfc6f3SLv Zheng 	 *
421*86dfc6f3SLv Zheng 	 * Before we install the table, let the host OS override it with a new
422*86dfc6f3SLv Zheng 	 * one if desired. Any table within the RSDT/XSDT can be replaced,
423*86dfc6f3SLv Zheng 	 * including the DSDT which is pointed to by the FADT.
424*86dfc6f3SLv Zheng 	 */
425*86dfc6f3SLv Zheng 	acpi_tb_override_table(new_table_desc);
426*86dfc6f3SLv Zheng 
427*86dfc6f3SLv Zheng 	acpi_tb_install_table(&acpi_gbl_root_table_list.tables[table_index],
428*86dfc6f3SLv Zheng 			      new_table_desc->address, new_table_desc->flags,
429*86dfc6f3SLv Zheng 			      new_table_desc->pointer);
430*86dfc6f3SLv Zheng 
431*86dfc6f3SLv Zheng 	acpi_tb_print_table_header(new_table_desc->address,
432*86dfc6f3SLv Zheng 				   new_table_desc->pointer);
433*86dfc6f3SLv Zheng 
434*86dfc6f3SLv Zheng 	/* Set the global integer width (based upon revision of the DSDT) */
435*86dfc6f3SLv Zheng 
436*86dfc6f3SLv Zheng 	if (table_index == ACPI_TABLE_INDEX_DSDT) {
437*86dfc6f3SLv Zheng 		acpi_ut_set_integer_width(new_table_desc->pointer->revision);
438*86dfc6f3SLv Zheng 	}
439*86dfc6f3SLv Zheng }
440*86dfc6f3SLv Zheng 
441*86dfc6f3SLv Zheng /*******************************************************************************
442*86dfc6f3SLv Zheng  *
443*86dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_install_fixed_table
444*86dfc6f3SLv Zheng  *
445*86dfc6f3SLv Zheng  * PARAMETERS:  address                 - Physical address of DSDT or FACS
446*86dfc6f3SLv Zheng  *              signature               - Table signature, NULL if no need to
447*86dfc6f3SLv Zheng  *                                        match
448*86dfc6f3SLv Zheng  *              table_index             - Index into root table array
449*86dfc6f3SLv Zheng  *
450*86dfc6f3SLv Zheng  * RETURN:      Status
451*86dfc6f3SLv Zheng  *
452*86dfc6f3SLv Zheng  * DESCRIPTION: Install a fixed ACPI table (DSDT/FACS) into the global data
453*86dfc6f3SLv Zheng  *              structure.
45495b482a8SLen Brown  *
45595b482a8SLen Brown  ******************************************************************************/
45695b482a8SLen Brown 
45795b482a8SLen Brown acpi_status
458*86dfc6f3SLv Zheng acpi_tb_install_fixed_table(acpi_physical_address address,
459*86dfc6f3SLv Zheng 			    char *signature, u32 table_index)
460*86dfc6f3SLv Zheng {
461*86dfc6f3SLv Zheng 	struct acpi_table_desc new_table_desc;
462*86dfc6f3SLv Zheng 	acpi_status status;
463*86dfc6f3SLv Zheng 
464*86dfc6f3SLv Zheng 	ACPI_FUNCTION_TRACE(tb_install_fixed_table);
465*86dfc6f3SLv Zheng 
466*86dfc6f3SLv Zheng 	if (!address) {
467*86dfc6f3SLv Zheng 		ACPI_ERROR((AE_INFO,
468*86dfc6f3SLv Zheng 			    "Null physical address for ACPI table [%s]",
469*86dfc6f3SLv Zheng 			    signature));
470*86dfc6f3SLv Zheng 		return (AE_NO_MEMORY);
471*86dfc6f3SLv Zheng 	}
472*86dfc6f3SLv Zheng 
473*86dfc6f3SLv Zheng 	/* Fill a table descriptor for validation */
474*86dfc6f3SLv Zheng 
475*86dfc6f3SLv Zheng 	status = acpi_tb_acquire_temporal_table(&new_table_desc, address,
476*86dfc6f3SLv Zheng 						ACPI_TABLE_ORIGIN_MAPPED);
477*86dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
478*86dfc6f3SLv Zheng 		ACPI_ERROR((AE_INFO, "Could not acquire table length at %p",
479*86dfc6f3SLv Zheng 			    ACPI_CAST_PTR(void, address)));
480*86dfc6f3SLv Zheng 		return_ACPI_STATUS(status);
481*86dfc6f3SLv Zheng 	}
482*86dfc6f3SLv Zheng 
483*86dfc6f3SLv Zheng 	/* Validate and verify a table before installation */
484*86dfc6f3SLv Zheng 
485*86dfc6f3SLv Zheng 	status = acpi_tb_verify_table(&new_table_desc, signature);
486*86dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
487*86dfc6f3SLv Zheng 		goto release_and_exit;
488*86dfc6f3SLv Zheng 	}
489*86dfc6f3SLv Zheng 
490*86dfc6f3SLv Zheng 	acpi_tb_install_and_override_table(table_index, &new_table_desc);
491*86dfc6f3SLv Zheng 
492*86dfc6f3SLv Zheng release_and_exit:
493*86dfc6f3SLv Zheng 
494*86dfc6f3SLv Zheng 	/* Release the temporal table descriptor */
495*86dfc6f3SLv Zheng 
496*86dfc6f3SLv Zheng 	acpi_tb_release_temporal_table(&new_table_desc);
497*86dfc6f3SLv Zheng 	return_ACPI_STATUS(status);
498*86dfc6f3SLv Zheng }
499*86dfc6f3SLv Zheng 
500*86dfc6f3SLv Zheng /*******************************************************************************
501*86dfc6f3SLv Zheng  *
502*86dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_is_equivalent_table
503*86dfc6f3SLv Zheng  *
504*86dfc6f3SLv Zheng  * PARAMETERS:  table_desc          - Table 1 descriptor to be compared
505*86dfc6f3SLv Zheng  *              table_index         - Index of table 2 to be compared
506*86dfc6f3SLv Zheng  *
507*86dfc6f3SLv Zheng  * RETURN:      TRUE if 2 tables are equivalent
508*86dfc6f3SLv Zheng  *
509*86dfc6f3SLv Zheng  * DESCRIPTION: This function is called to compare a table with what have
510*86dfc6f3SLv Zheng  *              already been installed in the root table list.
511*86dfc6f3SLv Zheng  *
512*86dfc6f3SLv Zheng  ******************************************************************************/
513*86dfc6f3SLv Zheng 
514*86dfc6f3SLv Zheng static u8
515*86dfc6f3SLv Zheng acpi_tb_is_equivalent_table(struct acpi_table_desc *table_desc, u32 table_index)
516*86dfc6f3SLv Zheng {
517*86dfc6f3SLv Zheng 	acpi_status status = AE_OK;
518*86dfc6f3SLv Zheng 	u8 is_equivalent;
519*86dfc6f3SLv Zheng 	struct acpi_table_header *table;
520*86dfc6f3SLv Zheng 	u32 table_length;
521*86dfc6f3SLv Zheng 	u8 table_flags;
522*86dfc6f3SLv Zheng 
523*86dfc6f3SLv Zheng 	status =
524*86dfc6f3SLv Zheng 	    acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index],
525*86dfc6f3SLv Zheng 				  &table, &table_length, &table_flags);
526*86dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
527*86dfc6f3SLv Zheng 		return (FALSE);
528*86dfc6f3SLv Zheng 	}
529*86dfc6f3SLv Zheng 
530*86dfc6f3SLv Zheng 	/*
531*86dfc6f3SLv Zheng 	 * Check for a table match on the entire table length,
532*86dfc6f3SLv Zheng 	 * not just the header.
533*86dfc6f3SLv Zheng 	 */
534*86dfc6f3SLv Zheng 	is_equivalent = (u8)((table_desc->length != table_length ||
535*86dfc6f3SLv Zheng 			      ACPI_MEMCMP(table_desc->pointer, table,
536*86dfc6f3SLv Zheng 					  table_length)) ? FALSE : TRUE);
537*86dfc6f3SLv Zheng 
538*86dfc6f3SLv Zheng 	/* Release the acquired table */
539*86dfc6f3SLv Zheng 
540*86dfc6f3SLv Zheng 	acpi_tb_release_table(table, table_length, table_flags);
541*86dfc6f3SLv Zheng 
542*86dfc6f3SLv Zheng 	return (is_equivalent);
543*86dfc6f3SLv Zheng }
544*86dfc6f3SLv Zheng 
545*86dfc6f3SLv Zheng /*******************************************************************************
546*86dfc6f3SLv Zheng  *
547*86dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_install_non_fixed_table
548*86dfc6f3SLv Zheng  *
549*86dfc6f3SLv Zheng  * PARAMETERS:  address             - Address of the table (might be a logical
550*86dfc6f3SLv Zheng  *                                    address depending on the table_flags)
551*86dfc6f3SLv Zheng  *              flags               - Flags for the table
552*86dfc6f3SLv Zheng  *              reload              - Whether reload should be performed
553*86dfc6f3SLv Zheng  *              table_index         - Where the table index is returned
554*86dfc6f3SLv Zheng  *
555*86dfc6f3SLv Zheng  * RETURN:      Status
556*86dfc6f3SLv Zheng  *
557*86dfc6f3SLv Zheng  * DESCRIPTION: This function is called to install an ACPI table that is
558*86dfc6f3SLv Zheng  *              neither DSDT nor FACS.
559*86dfc6f3SLv Zheng  *              When this function is called by "Load" or "LoadTable" opcodes,
560*86dfc6f3SLv Zheng  *              or by acpi_load_table() API, the "Reload" parameter is set.
561*86dfc6f3SLv Zheng  *              After sucessfully returning from this function, table is
562*86dfc6f3SLv Zheng  *              "INSTALLED" but not "VALIDATED".
563*86dfc6f3SLv Zheng  *
564*86dfc6f3SLv Zheng  ******************************************************************************/
565*86dfc6f3SLv Zheng 
566*86dfc6f3SLv Zheng acpi_status
567*86dfc6f3SLv Zheng acpi_tb_install_non_fixed_table(acpi_physical_address address,
568*86dfc6f3SLv Zheng 				u8 flags, u8 reload, u32 *table_index)
56995b482a8SLen Brown {
57095b482a8SLen Brown 	u32 i;
57195b482a8SLen Brown 	acpi_status status = AE_OK;
572*86dfc6f3SLv Zheng 	struct acpi_table_desc new_table_desc;
57395b482a8SLen Brown 
574*86dfc6f3SLv Zheng 	ACPI_FUNCTION_TRACE(tb_install_non_fixed_table);
57595b482a8SLen Brown 
576*86dfc6f3SLv Zheng 	/* Acquire a temporal table descriptor for validation */
577*86dfc6f3SLv Zheng 
578*86dfc6f3SLv Zheng 	status =
579*86dfc6f3SLv Zheng 	    acpi_tb_acquire_temporal_table(&new_table_desc, address, flags);
580*86dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
581*86dfc6f3SLv Zheng 		ACPI_ERROR((AE_INFO, "Could not acquire table length at %p",
582*86dfc6f3SLv Zheng 			    ACPI_CAST_PTR(void, address)));
58395b482a8SLen Brown 		return_ACPI_STATUS(status);
58495b482a8SLen Brown 	}
585*86dfc6f3SLv Zheng 
586*86dfc6f3SLv Zheng 	/* Validate and verify a table before installation */
587*86dfc6f3SLv Zheng 
588*86dfc6f3SLv Zheng 	status = acpi_tb_verify_table(&new_table_desc, NULL);
589*86dfc6f3SLv Zheng 	if (ACPI_FAILURE(status)) {
590*86dfc6f3SLv Zheng 		goto release_and_exit;
59195b482a8SLen Brown 	}
59295b482a8SLen Brown 
593*86dfc6f3SLv Zheng 	if (reload) {
59495b482a8SLen Brown 		/*
595c8cefe30SBob Moore 		 * Validate the incoming table signature.
596c8cefe30SBob Moore 		 *
597c8cefe30SBob Moore 		 * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
598c8cefe30SBob Moore 		 * 2) We added support for OEMx tables, signature "OEM".
599c8cefe30SBob Moore 		 * 3) Valid tables were encountered with a null signature, so we just
600c8cefe30SBob Moore 		 *    gave up on validating the signature, (05/2008).
601c8cefe30SBob Moore 		 * 4) We encountered non-AML tables such as the MADT, which caused
602c8cefe30SBob Moore 		 *    interpreter errors and kernel faults. So now, we once again allow
603c8cefe30SBob Moore 		 *    only "SSDT", "OEMx", and now, also a null signature. (05/2011).
60495b482a8SLen Brown 		 */
605*86dfc6f3SLv Zheng 		if ((new_table_desc.signature.ascii[0] != 0x00) &&
606*86dfc6f3SLv Zheng 		    (!ACPI_COMPARE_NAME
607*86dfc6f3SLv Zheng 		     (&new_table_desc.signature, ACPI_SIG_SSDT))
608*86dfc6f3SLv Zheng 		    && (ACPI_STRNCMP(new_table_desc.signature.ascii, "OEM", 3)))
609*86dfc6f3SLv Zheng 		{
6103b3ea775SBob Moore 			ACPI_BIOS_ERROR((AE_INFO,
6113b3ea775SBob Moore 					 "Table has invalid signature [%4.4s] (0x%8.8X), "
6123b3ea775SBob Moore 					 "must be SSDT or OEMx",
613*86dfc6f3SLv Zheng 					 acpi_ut_valid_acpi_name(new_table_desc.
614*86dfc6f3SLv Zheng 								 signature.
615*86dfc6f3SLv Zheng 								 ascii) ?
616*86dfc6f3SLv Zheng 					 new_table_desc.signature.
617*86dfc6f3SLv Zheng 					 ascii : "????",
618*86dfc6f3SLv Zheng 					 new_table_desc.signature.integer));
619c8cefe30SBob Moore 
620*86dfc6f3SLv Zheng 			status = AE_BAD_SIGNATURE;
621*86dfc6f3SLv Zheng 			goto release_and_exit;
622c8cefe30SBob Moore 		}
62395b482a8SLen Brown 
62495b482a8SLen Brown 		/* Check if table is already registered */
62595b482a8SLen Brown 
626*86dfc6f3SLv Zheng 		for (i = 0; i < acpi_gbl_root_table_list.current_table_count;
627*86dfc6f3SLv Zheng 		     ++i) {
62895b482a8SLen Brown 			/*
62995b482a8SLen Brown 			 * Check for a table match on the entire table length,
63095b482a8SLen Brown 			 * not just the header.
63195b482a8SLen Brown 			 */
632*86dfc6f3SLv Zheng 			if (!acpi_tb_is_equivalent_table(&new_table_desc, i)) {
63395b482a8SLen Brown 				continue;
63495b482a8SLen Brown 			}
63595b482a8SLen Brown 
63695b482a8SLen Brown 			/*
63795b482a8SLen Brown 			 * Note: the current mechanism does not unregister a table if it is
63895b482a8SLen Brown 			 * dynamically unloaded. The related namespace entries are deleted,
63995b482a8SLen Brown 			 * but the table remains in the root table list.
64095b482a8SLen Brown 			 *
64195b482a8SLen Brown 			 * The assumption here is that the number of different tables that
64295b482a8SLen Brown 			 * will be loaded is actually small, and there is minimal overhead
64395b482a8SLen Brown 			 * in just keeping the table in case it is needed again.
64495b482a8SLen Brown 			 *
64595b482a8SLen Brown 			 * If this assumption changes in the future (perhaps on large
64695b482a8SLen Brown 			 * machines with many table load/unload operations), tables will
64795b482a8SLen Brown 			 * need to be unregistered when they are unloaded, and slots in the
64895b482a8SLen Brown 			 * root table list should be reused when empty.
64995b482a8SLen Brown 			 */
65095b482a8SLen Brown 			if (acpi_gbl_root_table_list.tables[i].
65195b482a8SLen Brown 			    flags & ACPI_TABLE_IS_LOADED) {
65295b482a8SLen Brown 
65395b482a8SLen Brown 				/* Table is still loaded, this is an error */
65495b482a8SLen Brown 
65595b482a8SLen Brown 				status = AE_ALREADY_EXISTS;
656*86dfc6f3SLv Zheng 				goto release_and_exit;
65795b482a8SLen Brown 			} else {
658d3ccaff8SBob Moore 				/*
659*86dfc6f3SLv Zheng 				 * Table was unloaded, allow it to be reloaded.
660*86dfc6f3SLv Zheng 				 * As we are going to return AE_OK to the caller, we should
661*86dfc6f3SLv Zheng 				 * take the responsibility of freeing the input descriptor.
662*86dfc6f3SLv Zheng 				 * Refill the input descriptor to ensure
663*86dfc6f3SLv Zheng 				 * acpi_tb_install_and_override_table() can be called again to
664*86dfc6f3SLv Zheng 				 * indicate the re-installation.
665d3ccaff8SBob Moore 				 */
666*86dfc6f3SLv Zheng 				acpi_tb_uninstall_table(&new_table_desc);
667*86dfc6f3SLv Zheng 				*table_index = i;
668*86dfc6f3SLv Zheng 				(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
669*86dfc6f3SLv Zheng 				return_ACPI_STATUS(AE_OK);
670*86dfc6f3SLv Zheng 			}
671*86dfc6f3SLv Zheng 		}
6727f9fc99cSLv Zheng 	}
673d3ccaff8SBob Moore 
67495b482a8SLen Brown 	/* Add the table to the global root table list */
67595b482a8SLen Brown 
676*86dfc6f3SLv Zheng 	status = acpi_tb_acquire_root_table_entry(&i);
67795b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
678*86dfc6f3SLv Zheng 		goto release_and_exit;
67995b482a8SLen Brown 	}
680*86dfc6f3SLv Zheng 	*table_index = i;
681*86dfc6f3SLv Zheng 	acpi_tb_install_and_override_table(i, &new_table_desc);
68295b482a8SLen Brown 
683*86dfc6f3SLv Zheng release_and_exit:
68495b482a8SLen Brown 
685*86dfc6f3SLv Zheng 	/* Release the temporal table descriptor */
686*86dfc6f3SLv Zheng 
687*86dfc6f3SLv Zheng 	acpi_tb_release_temporal_table(&new_table_desc);
68895b482a8SLen Brown 	return_ACPI_STATUS(status);
68995b482a8SLen Brown }
69095b482a8SLen Brown 
69195b482a8SLen Brown /*******************************************************************************
69295b482a8SLen Brown  *
6937f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_override_table
694f7b004a1SBob Moore  *
695*86dfc6f3SLv Zheng  * PARAMETERS:  old_table_desc      - Validated table descriptor to be
696*86dfc6f3SLv Zheng  *                                    overridden
697f7b004a1SBob Moore  *
698*86dfc6f3SLv Zheng  * RETURN:      None
699f7b004a1SBob Moore  *
700f7b004a1SBob Moore  * DESCRIPTION: Attempt table override by calling the OSL override functions.
701f7b004a1SBob Moore  *              Note: If the table is overridden, then the entire new table
7027f9fc99cSLv Zheng  *              is acquired and returned by this function.
703*86dfc6f3SLv Zheng  *              Before/after invocation, the table descriptor is in a state
704*86dfc6f3SLv Zheng  *              that is "VALIDATED".
705f7b004a1SBob Moore  *
706f7b004a1SBob Moore  ******************************************************************************/
707f7b004a1SBob Moore 
708*86dfc6f3SLv Zheng void acpi_tb_override_table(struct acpi_table_desc *old_table_desc)
709f7b004a1SBob Moore {
710f7b004a1SBob Moore 	acpi_status status;
711f7b004a1SBob Moore 	char *override_type;
7127f9fc99cSLv Zheng 	struct acpi_table_desc new_table_desc;
713*86dfc6f3SLv Zheng 	struct acpi_table_header *table;
714*86dfc6f3SLv Zheng 	acpi_physical_address address;
715*86dfc6f3SLv Zheng 	u32 length;
716f7b004a1SBob Moore 
717f7b004a1SBob Moore 	/* (1) Attempt logical override (returns a logical address) */
718f7b004a1SBob Moore 
719*86dfc6f3SLv Zheng 	status = acpi_os_table_override(old_table_desc->pointer, &table);
720*86dfc6f3SLv Zheng 	if (ACPI_SUCCESS(status) && table) {
721*86dfc6f3SLv Zheng 		acpi_tb_acquire_temporal_table(&new_table_desc,
722*86dfc6f3SLv Zheng 					       ACPI_PTR_TO_PHYSADDR(table),
723*86dfc6f3SLv Zheng 					       ACPI_TABLE_ORIGIN_OVERRIDE);
724f7b004a1SBob Moore 		override_type = "Logical";
725f7b004a1SBob Moore 		goto finish_override;
726f7b004a1SBob Moore 	}
727f7b004a1SBob Moore 
728f7b004a1SBob Moore 	/* (2) Attempt physical override (returns a physical address) */
729f7b004a1SBob Moore 
730*86dfc6f3SLv Zheng 	status = acpi_os_physical_table_override(old_table_desc->pointer,
731*86dfc6f3SLv Zheng 						 &address, &length);
732*86dfc6f3SLv Zheng 	if (ACPI_SUCCESS(status) && address && length) {
733*86dfc6f3SLv Zheng 		acpi_tb_acquire_temporal_table(&new_table_desc, address,
734*86dfc6f3SLv Zheng 					       ACPI_TABLE_ORIGIN_MAPPED);
735f7b004a1SBob Moore 		override_type = "Physical";
736f7b004a1SBob Moore 		goto finish_override;
737f7b004a1SBob Moore 	}
738f7b004a1SBob Moore 
739*86dfc6f3SLv Zheng 	return;			/* There was no override */
740f7b004a1SBob Moore 
741f7b004a1SBob Moore finish_override:
742f7b004a1SBob Moore 
743*86dfc6f3SLv Zheng 	/* Validate and verify a table before overriding */
744*86dfc6f3SLv Zheng 
745*86dfc6f3SLv Zheng 	status = acpi_tb_verify_table(&new_table_desc, NULL);
7467f9fc99cSLv Zheng 	if (ACPI_FAILURE(status)) {
747*86dfc6f3SLv Zheng 		return;
7487f9fc99cSLv Zheng 	}
7497f9fc99cSLv Zheng 
7502e19f8d0SBob Moore 	ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT
7512e19f8d0SBob Moore 		   " %s table override, new table: " ACPI_PRINTF_UINT,
752*86dfc6f3SLv Zheng 		   old_table_desc->signature.ascii,
753*86dfc6f3SLv Zheng 		   ACPI_FORMAT_TO_UINT(old_table_desc->address),
7547f9fc99cSLv Zheng 		   override_type, ACPI_FORMAT_TO_UINT(new_table_desc.address)));
755f7b004a1SBob Moore 
756*86dfc6f3SLv Zheng 	/* We can now uninstall the original table */
757f7b004a1SBob Moore 
758*86dfc6f3SLv Zheng 	acpi_tb_uninstall_table(old_table_desc);
759f7b004a1SBob Moore 
760*86dfc6f3SLv Zheng 	/*
761*86dfc6f3SLv Zheng 	 * Replace the original table descriptor and keep its state as
762*86dfc6f3SLv Zheng 	 * "VALIDATED".
763*86dfc6f3SLv Zheng 	 */
764*86dfc6f3SLv Zheng 	acpi_tb_install_table(old_table_desc, new_table_desc.address,
765*86dfc6f3SLv Zheng 			      new_table_desc.flags, new_table_desc.pointer);
766*86dfc6f3SLv Zheng 	acpi_tb_validate_table(old_table_desc);
767f7b004a1SBob Moore 
768*86dfc6f3SLv Zheng 	/* Release the temporal table descriptor */
769f7b004a1SBob Moore 
770*86dfc6f3SLv Zheng 	acpi_tb_release_temporal_table(&new_table_desc);
771f7b004a1SBob Moore }
772f7b004a1SBob Moore 
773f7b004a1SBob Moore /*******************************************************************************
774f7b004a1SBob Moore  *
77595b482a8SLen Brown  * FUNCTION:    acpi_tb_resize_root_table_list
77695b482a8SLen Brown  *
77795b482a8SLen Brown  * PARAMETERS:  None
77895b482a8SLen Brown  *
77995b482a8SLen Brown  * RETURN:      Status
78095b482a8SLen Brown  *
78195b482a8SLen Brown  * DESCRIPTION: Expand the size of global table array
78295b482a8SLen Brown  *
78395b482a8SLen Brown  ******************************************************************************/
78495b482a8SLen Brown 
78595b482a8SLen Brown acpi_status acpi_tb_resize_root_table_list(void)
78695b482a8SLen Brown {
78795b482a8SLen Brown 	struct acpi_table_desc *tables;
7882bc198c1SLv Zheng 	u32 table_count;
78995b482a8SLen Brown 
79095b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
79195b482a8SLen Brown 
79295b482a8SLen Brown 	/* allow_resize flag is a parameter to acpi_initialize_tables */
79395b482a8SLen Brown 
79495b482a8SLen Brown 	if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) {
79595b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
79695b482a8SLen Brown 			    "Resize of Root Table Array is not allowed"));
79795b482a8SLen Brown 		return_ACPI_STATUS(AE_SUPPORT);
79895b482a8SLen Brown 	}
79995b482a8SLen Brown 
80095b482a8SLen Brown 	/* Increase the Table Array size */
80195b482a8SLen Brown 
8022bc198c1SLv Zheng 	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
8032bc198c1SLv Zheng 		table_count = acpi_gbl_root_table_list.max_table_count;
8042bc198c1SLv Zheng 	} else {
8052bc198c1SLv Zheng 		table_count = acpi_gbl_root_table_list.current_table_count;
8062bc198c1SLv Zheng 	}
8072bc198c1SLv Zheng 
8082bc198c1SLv Zheng 	tables = ACPI_ALLOCATE_ZEROED(((acpi_size) table_count +
809ec41f193SBob Moore 				       ACPI_ROOT_TABLE_SIZE_INCREMENT) *
810ec41f193SBob Moore 				      sizeof(struct acpi_table_desc));
81195b482a8SLen Brown 	if (!tables) {
81295b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
81395b482a8SLen Brown 			    "Could not allocate new root table array"));
81495b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_MEMORY);
81595b482a8SLen Brown 	}
81695b482a8SLen Brown 
81795b482a8SLen Brown 	/* Copy and free the previous table array */
81895b482a8SLen Brown 
81995b482a8SLen Brown 	if (acpi_gbl_root_table_list.tables) {
82095b482a8SLen Brown 		ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
8212bc198c1SLv Zheng 			    (acpi_size) table_count *
8222bc198c1SLv Zheng 			    sizeof(struct acpi_table_desc));
82395b482a8SLen Brown 
82495b482a8SLen Brown 		if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
82595b482a8SLen Brown 			ACPI_FREE(acpi_gbl_root_table_list.tables);
82695b482a8SLen Brown 		}
82795b482a8SLen Brown 	}
82895b482a8SLen Brown 
82995b482a8SLen Brown 	acpi_gbl_root_table_list.tables = tables;
8302bc198c1SLv Zheng 	acpi_gbl_root_table_list.max_table_count =
8312bc198c1SLv Zheng 	    table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT;
8322bc198c1SLv Zheng 	acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
83395b482a8SLen Brown 
83495b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
83595b482a8SLen Brown }
83695b482a8SLen Brown 
83795b482a8SLen Brown /*******************************************************************************
83895b482a8SLen Brown  *
839*86dfc6f3SLv Zheng  * FUNCTION:    acpi_tb_acquire_root_table_entry
840*86dfc6f3SLv Zheng  *
841*86dfc6f3SLv Zheng  * PARAMETERS:  table_index         - Where table index is returned
842*86dfc6f3SLv Zheng  *
843*86dfc6f3SLv Zheng  * RETURN:      Status and table index.
844*86dfc6f3SLv Zheng  *
845*86dfc6f3SLv Zheng  * DESCRIPTION: Allocate a new ACPI table entry to the global table list
846*86dfc6f3SLv Zheng  *
847*86dfc6f3SLv Zheng  ******************************************************************************/
848*86dfc6f3SLv Zheng 
849*86dfc6f3SLv Zheng static acpi_status acpi_tb_acquire_root_table_entry(u32 *table_index)
850*86dfc6f3SLv Zheng {
851*86dfc6f3SLv Zheng 	acpi_status status;
852*86dfc6f3SLv Zheng 
853*86dfc6f3SLv Zheng 	/* Ensure that there is room for the table in the Root Table List */
854*86dfc6f3SLv Zheng 
855*86dfc6f3SLv Zheng 	if (acpi_gbl_root_table_list.current_table_count >=
856*86dfc6f3SLv Zheng 	    acpi_gbl_root_table_list.max_table_count) {
857*86dfc6f3SLv Zheng 		status = acpi_tb_resize_root_table_list();
858*86dfc6f3SLv Zheng 		if (ACPI_FAILURE(status)) {
859*86dfc6f3SLv Zheng 			return (status);
860*86dfc6f3SLv Zheng 		}
861*86dfc6f3SLv Zheng 	}
862*86dfc6f3SLv Zheng 
863*86dfc6f3SLv Zheng 	*table_index = acpi_gbl_root_table_list.current_table_count;
864*86dfc6f3SLv Zheng 	acpi_gbl_root_table_list.current_table_count++;
865*86dfc6f3SLv Zheng 	return (AE_OK);
866*86dfc6f3SLv Zheng }
867*86dfc6f3SLv Zheng 
868*86dfc6f3SLv Zheng /*******************************************************************************
869*86dfc6f3SLv Zheng  *
87095b482a8SLen Brown  * FUNCTION:    acpi_tb_store_table
87195b482a8SLen Brown  *
872ba494beeSBob Moore  * PARAMETERS:  address             - Table address
873ba494beeSBob Moore  *              table               - Table header
874ba494beeSBob Moore  *              length              - Table length
875ba494beeSBob Moore  *              flags               - flags
87695b482a8SLen Brown  *
87795b482a8SLen Brown  * RETURN:      Status and table index.
87895b482a8SLen Brown  *
87995b482a8SLen Brown  * DESCRIPTION: Add an ACPI table to the global table list
88095b482a8SLen Brown  *
88195b482a8SLen Brown  ******************************************************************************/
88295b482a8SLen Brown 
88395b482a8SLen Brown acpi_status
88495b482a8SLen Brown acpi_tb_store_table(acpi_physical_address address,
88595b482a8SLen Brown 		    struct acpi_table_header * table,
88695b482a8SLen Brown 		    u32 length, u8 flags, u32 *table_index)
88795b482a8SLen Brown {
888b9ee2043SBob Moore 	acpi_status status;
889*86dfc6f3SLv Zheng 	struct acpi_table_desc *table_desc;
89095b482a8SLen Brown 
891*86dfc6f3SLv Zheng 	status = acpi_tb_acquire_root_table_entry(table_index);
89295b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
89395b482a8SLen Brown 		return (status);
89495b482a8SLen Brown 	}
895b9ee2043SBob Moore 
89695b482a8SLen Brown 	/* Initialize added table */
89795b482a8SLen Brown 
898*86dfc6f3SLv Zheng 	table_desc = &acpi_gbl_root_table_list.tables[*table_index];
899*86dfc6f3SLv Zheng 	acpi_tb_install_table(table_desc, address, flags, table);
900*86dfc6f3SLv Zheng 	table_desc->pointer = table;
90195b482a8SLen Brown 
902b9ee2043SBob Moore 	return (AE_OK);
90395b482a8SLen Brown }
90495b482a8SLen Brown 
90595b482a8SLen Brown /*******************************************************************************
90695b482a8SLen Brown  *
9077f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_uninstall_table
90895b482a8SLen Brown  *
9097f9fc99cSLv Zheng  * PARAMETERS:  table_desc          - Table descriptor
91095b482a8SLen Brown  *
91195b482a8SLen Brown  * RETURN:      None
91295b482a8SLen Brown  *
91395b482a8SLen Brown  * DESCRIPTION: Delete one internal ACPI table
91495b482a8SLen Brown  *
91595b482a8SLen Brown  ******************************************************************************/
91695b482a8SLen Brown 
9177f9fc99cSLv Zheng void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc)
91895b482a8SLen Brown {
9195582982dSLv Zheng 
9207f9fc99cSLv Zheng 	ACPI_FUNCTION_TRACE(tb_uninstall_table);
9215582982dSLv Zheng 
9227f9fc99cSLv Zheng 	/* Table must be installed */
9237f9fc99cSLv Zheng 
9247f9fc99cSLv Zheng 	if (!table_desc->address) {
9257f9fc99cSLv Zheng 		return_VOID;
92695b482a8SLen Brown 	}
9275582982dSLv Zheng 
9287f9fc99cSLv Zheng 	acpi_tb_invalidate_table(table_desc);
9291d1ea1b7SChao Guan 
9307f9fc99cSLv Zheng 	if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) ==
9317f9fc99cSLv Zheng 	    ACPI_TABLE_ORIGIN_ALLOCATED) {
9327f9fc99cSLv Zheng 		ACPI_FREE(ACPI_CAST_PTR(void, table_desc->address));
9337f9fc99cSLv Zheng 	}
9341d1ea1b7SChao Guan 
935dc156adfSLv Zheng 	table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL);
936f7b004a1SBob Moore 
9377f9fc99cSLv Zheng 	return_VOID;
93895b482a8SLen Brown }
93995b482a8SLen Brown 
94095b482a8SLen Brown /*******************************************************************************
94195b482a8SLen Brown  *
94295b482a8SLen Brown  * FUNCTION:    acpi_tb_terminate
94395b482a8SLen Brown  *
94495b482a8SLen Brown  * PARAMETERS:  None
94595b482a8SLen Brown  *
94695b482a8SLen Brown  * RETURN:      None
94795b482a8SLen Brown  *
94895b482a8SLen Brown  * DESCRIPTION: Delete all internal ACPI tables
94995b482a8SLen Brown  *
95095b482a8SLen Brown  ******************************************************************************/
95195b482a8SLen Brown 
95295b482a8SLen Brown void acpi_tb_terminate(void)
95395b482a8SLen Brown {
95495b482a8SLen Brown 	u32 i;
95595b482a8SLen Brown 
95695b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_terminate);
95795b482a8SLen Brown 
95895b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
95995b482a8SLen Brown 
96095b482a8SLen Brown 	/* Delete the individual tables */
96195b482a8SLen Brown 
962b9ee2043SBob Moore 	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
9637f9fc99cSLv Zheng 		acpi_tb_uninstall_table(&acpi_gbl_root_table_list.tables[i]);
96495b482a8SLen Brown 	}
96595b482a8SLen Brown 
96695b482a8SLen Brown 	/*
96795b482a8SLen Brown 	 * Delete the root table array if allocated locally. Array cannot be
96895b482a8SLen Brown 	 * mapped, so we don't need to check for that flag.
96995b482a8SLen Brown 	 */
97095b482a8SLen Brown 	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
97195b482a8SLen Brown 		ACPI_FREE(acpi_gbl_root_table_list.tables);
97295b482a8SLen Brown 	}
97395b482a8SLen Brown 
97495b482a8SLen Brown 	acpi_gbl_root_table_list.tables = NULL;
97595b482a8SLen Brown 	acpi_gbl_root_table_list.flags = 0;
976b9ee2043SBob Moore 	acpi_gbl_root_table_list.current_table_count = 0;
97795b482a8SLen Brown 
97895b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
97995b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
98068aafc35SBob Moore 
98168aafc35SBob Moore 	return_VOID;
98295b482a8SLen Brown }
98395b482a8SLen Brown 
98495b482a8SLen Brown /*******************************************************************************
98595b482a8SLen Brown  *
98695b482a8SLen Brown  * FUNCTION:    acpi_tb_delete_namespace_by_owner
98795b482a8SLen Brown  *
98895b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
98995b482a8SLen Brown  *
9908a335a23SBob Moore  * RETURN:      Status
99195b482a8SLen Brown  *
99295b482a8SLen Brown  * DESCRIPTION: Delete all namespace objects created when this table was loaded.
99395b482a8SLen Brown  *
99495b482a8SLen Brown  ******************************************************************************/
99595b482a8SLen Brown 
9968a335a23SBob Moore acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index)
99795b482a8SLen Brown {
99895b482a8SLen Brown 	acpi_owner_id owner_id;
9998a335a23SBob Moore 	acpi_status status;
100095b482a8SLen Brown 
10018a335a23SBob Moore 	ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner);
10028a335a23SBob Moore 
10038a335a23SBob Moore 	status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
10048a335a23SBob Moore 	if (ACPI_FAILURE(status)) {
10058a335a23SBob Moore 		return_ACPI_STATUS(status);
100695b482a8SLen Brown 	}
100795b482a8SLen Brown 
1008b9ee2043SBob Moore 	if (table_index >= acpi_gbl_root_table_list.current_table_count) {
10098a335a23SBob Moore 
10108a335a23SBob Moore 		/* The table index does not exist */
10118a335a23SBob Moore 
101295b482a8SLen Brown 		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
10138a335a23SBob Moore 		return_ACPI_STATUS(AE_NOT_EXIST);
10148a335a23SBob Moore 	}
10158a335a23SBob Moore 
10168a335a23SBob Moore 	/* Get the owner ID for this table, used to delete namespace nodes */
10178a335a23SBob Moore 
10188a335a23SBob Moore 	owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id;
10198a335a23SBob Moore 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
10208a335a23SBob Moore 
10218a335a23SBob Moore 	/*
10228a335a23SBob Moore 	 * Need to acquire the namespace writer lock to prevent interference
10238a335a23SBob Moore 	 * with any concurrent namespace walks. The interpreter must be
10248a335a23SBob Moore 	 * released during the deletion since the acquisition of the deletion
10258a335a23SBob Moore 	 * lock may block, and also since the execution of a namespace walk
10268a335a23SBob Moore 	 * must be allowed to use the interpreter.
10278a335a23SBob Moore 	 */
1028e4c1ebfcSBob Moore 	(void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
10298a335a23SBob Moore 	status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock);
10308a335a23SBob Moore 
103195b482a8SLen Brown 	acpi_ns_delete_namespace_by_owner(owner_id);
10328a335a23SBob Moore 	if (ACPI_FAILURE(status)) {
10338a335a23SBob Moore 		return_ACPI_STATUS(status);
10348a335a23SBob Moore 	}
10358a335a23SBob Moore 
10368a335a23SBob Moore 	acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock);
10378a335a23SBob Moore 
10388a335a23SBob Moore 	status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
10398a335a23SBob Moore 	return_ACPI_STATUS(status);
104095b482a8SLen Brown }
104195b482a8SLen Brown 
104295b482a8SLen Brown /*******************************************************************************
104395b482a8SLen Brown  *
104495b482a8SLen Brown  * FUNCTION:    acpi_tb_allocate_owner_id
104595b482a8SLen Brown  *
104695b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
104795b482a8SLen Brown  *
104895b482a8SLen Brown  * RETURN:      Status
104995b482a8SLen Brown  *
105095b482a8SLen Brown  * DESCRIPTION: Allocates owner_id in table_desc
105195b482a8SLen Brown  *
105295b482a8SLen Brown  ******************************************************************************/
105395b482a8SLen Brown 
105495b482a8SLen Brown acpi_status acpi_tb_allocate_owner_id(u32 table_index)
105595b482a8SLen Brown {
105695b482a8SLen Brown 	acpi_status status = AE_BAD_PARAMETER;
105795b482a8SLen Brown 
105895b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
105995b482a8SLen Brown 
106095b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1061b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
106295b482a8SLen Brown 		status = acpi_ut_allocate_owner_id
106395b482a8SLen Brown 		    (&(acpi_gbl_root_table_list.tables[table_index].owner_id));
106495b482a8SLen Brown 	}
106595b482a8SLen Brown 
106695b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
106795b482a8SLen Brown 	return_ACPI_STATUS(status);
106895b482a8SLen Brown }
106995b482a8SLen Brown 
107095b482a8SLen Brown /*******************************************************************************
107195b482a8SLen Brown  *
107295b482a8SLen Brown  * FUNCTION:    acpi_tb_release_owner_id
107395b482a8SLen Brown  *
107495b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
107595b482a8SLen Brown  *
107695b482a8SLen Brown  * RETURN:      Status
107795b482a8SLen Brown  *
107895b482a8SLen Brown  * DESCRIPTION: Releases owner_id in table_desc
107995b482a8SLen Brown  *
108095b482a8SLen Brown  ******************************************************************************/
108195b482a8SLen Brown 
108295b482a8SLen Brown acpi_status acpi_tb_release_owner_id(u32 table_index)
108395b482a8SLen Brown {
108495b482a8SLen Brown 	acpi_status status = AE_BAD_PARAMETER;
108595b482a8SLen Brown 
108695b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_release_owner_id);
108795b482a8SLen Brown 
108895b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1089b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
109095b482a8SLen Brown 		acpi_ut_release_owner_id(&
109195b482a8SLen Brown 					 (acpi_gbl_root_table_list.
109295b482a8SLen Brown 					  tables[table_index].owner_id));
109395b482a8SLen Brown 		status = AE_OK;
109495b482a8SLen Brown 	}
109595b482a8SLen Brown 
109695b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
109795b482a8SLen Brown 	return_ACPI_STATUS(status);
109895b482a8SLen Brown }
109995b482a8SLen Brown 
110095b482a8SLen Brown /*******************************************************************************
110195b482a8SLen Brown  *
110295b482a8SLen Brown  * FUNCTION:    acpi_tb_get_owner_id
110395b482a8SLen Brown  *
110495b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
110595b482a8SLen Brown  *              owner_id            - Where the table owner_id is returned
110695b482a8SLen Brown  *
110795b482a8SLen Brown  * RETURN:      Status
110895b482a8SLen Brown  *
110995b482a8SLen Brown  * DESCRIPTION: returns owner_id for the ACPI table
111095b482a8SLen Brown  *
111195b482a8SLen Brown  ******************************************************************************/
111295b482a8SLen Brown 
111395b482a8SLen Brown acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id * owner_id)
111495b482a8SLen Brown {
111595b482a8SLen Brown 	acpi_status status = AE_BAD_PARAMETER;
111695b482a8SLen Brown 
111795b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_get_owner_id);
111895b482a8SLen Brown 
111995b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1120b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
112195b482a8SLen Brown 		*owner_id =
112295b482a8SLen Brown 		    acpi_gbl_root_table_list.tables[table_index].owner_id;
112395b482a8SLen Brown 		status = AE_OK;
112495b482a8SLen Brown 	}
112595b482a8SLen Brown 
112695b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
112795b482a8SLen Brown 	return_ACPI_STATUS(status);
112895b482a8SLen Brown }
112995b482a8SLen Brown 
113095b482a8SLen Brown /*******************************************************************************
113195b482a8SLen Brown  *
113295b482a8SLen Brown  * FUNCTION:    acpi_tb_is_table_loaded
113395b482a8SLen Brown  *
113495b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
113595b482a8SLen Brown  *
113695b482a8SLen Brown  * RETURN:      Table Loaded Flag
113795b482a8SLen Brown  *
113895b482a8SLen Brown  ******************************************************************************/
113995b482a8SLen Brown 
114095b482a8SLen Brown u8 acpi_tb_is_table_loaded(u32 table_index)
114195b482a8SLen Brown {
114295b482a8SLen Brown 	u8 is_loaded = FALSE;
114395b482a8SLen Brown 
114495b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1145b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
114695b482a8SLen Brown 		is_loaded = (u8)
1147ec41f193SBob Moore 		    (acpi_gbl_root_table_list.tables[table_index].flags &
1148ec41f193SBob Moore 		     ACPI_TABLE_IS_LOADED);
114995b482a8SLen Brown 	}
115095b482a8SLen Brown 
115195b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
115295b482a8SLen Brown 	return (is_loaded);
115395b482a8SLen Brown }
115495b482a8SLen Brown 
115595b482a8SLen Brown /*******************************************************************************
115695b482a8SLen Brown  *
115795b482a8SLen Brown  * FUNCTION:    acpi_tb_set_table_loaded_flag
115895b482a8SLen Brown  *
115995b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
116095b482a8SLen Brown  *              is_loaded           - TRUE if table is loaded, FALSE otherwise
116195b482a8SLen Brown  *
116295b482a8SLen Brown  * RETURN:      None
116395b482a8SLen Brown  *
116495b482a8SLen Brown  * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
116595b482a8SLen Brown  *
116695b482a8SLen Brown  ******************************************************************************/
116795b482a8SLen Brown 
116895b482a8SLen Brown void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded)
116995b482a8SLen Brown {
117095b482a8SLen Brown 
117195b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
1172b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
117395b482a8SLen Brown 		if (is_loaded) {
117495b482a8SLen Brown 			acpi_gbl_root_table_list.tables[table_index].flags |=
117595b482a8SLen Brown 			    ACPI_TABLE_IS_LOADED;
117695b482a8SLen Brown 		} else {
117795b482a8SLen Brown 			acpi_gbl_root_table_list.tables[table_index].flags &=
117895b482a8SLen Brown 			    ~ACPI_TABLE_IS_LOADED;
117995b482a8SLen Brown 		}
118095b482a8SLen Brown 	}
118195b482a8SLen Brown 
118295b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
118395b482a8SLen Brown }
1184