xref: /openbmc/linux/drivers/acpi/acpica/tbinstal.c (revision 7f9fc99cde939187c1ee6dac115bdb76655cc798)
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*7f9fc99cSLv Zheng /*******************************************************************************
5395b482a8SLen Brown  *
54*7f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_acquire_table
5595b482a8SLen Brown  *
56*7f9fc99cSLv Zheng  * PARAMETERS:  table_desc          - Table descriptor
57*7f9fc99cSLv Zheng  *              table_ptr           - Where table is returned
58*7f9fc99cSLv Zheng  *              table_length        - Where table length is returned
59*7f9fc99cSLv Zheng  *              table_flags         - Where table allocation flags are returned
6095b482a8SLen Brown  *
6195b482a8SLen Brown  * RETURN:      Status
6295b482a8SLen Brown  *
63*7f9fc99cSLv Zheng  * DESCRIPTION: Acquire a table. It can be used for tables not maintained in
64*7f9fc99cSLv Zheng  *              acpi_gbl_root_table_list.
6595b482a8SLen Brown  *
66*7f9fc99cSLv Zheng  ******************************************************************************/
67*7f9fc99cSLv Zheng acpi_status
68*7f9fc99cSLv Zheng acpi_tb_acquire_table(struct acpi_table_desc *table_desc,
69*7f9fc99cSLv Zheng 		      struct acpi_table_header **table_ptr,
70*7f9fc99cSLv Zheng 		      u32 *table_length, u8 *table_flags)
7195b482a8SLen Brown {
72*7f9fc99cSLv Zheng 	struct acpi_table_header *table = NULL;
7395b482a8SLen Brown 
74dc156adfSLv Zheng 	switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
75dc156adfSLv Zheng 	case ACPI_TABLE_ORIGIN_MAPPED:
76dc156adfSLv Zheng 
77*7f9fc99cSLv Zheng 		table =
78*7f9fc99cSLv Zheng 		    acpi_os_map_memory(table_desc->address, table_desc->length);
79dc156adfSLv Zheng 		break;
80dc156adfSLv Zheng 
81dc156adfSLv Zheng 	case ACPI_TABLE_ORIGIN_ALLOCATED:
82dc156adfSLv Zheng 	case ACPI_TABLE_ORIGIN_UNKNOWN:
83dc156adfSLv Zheng 	case ACPI_TABLE_ORIGIN_OVERRIDE:
84dc156adfSLv Zheng 
85*7f9fc99cSLv Zheng 		table =
86dc156adfSLv Zheng 		    ACPI_CAST_PTR(struct acpi_table_header,
87dc156adfSLv Zheng 				  table_desc->address);
88dc156adfSLv Zheng 		break;
89dc156adfSLv Zheng 
90dc156adfSLv Zheng 	default:
91dc156adfSLv Zheng 
92dc156adfSLv Zheng 		break;
9395b482a8SLen Brown 	}
945582982dSLv Zheng 
95*7f9fc99cSLv Zheng 	/* Table is not valid yet */
96*7f9fc99cSLv Zheng 
97*7f9fc99cSLv Zheng 	if (!table) {
98*7f9fc99cSLv Zheng 		return (AE_NO_MEMORY);
99*7f9fc99cSLv Zheng 	}
100*7f9fc99cSLv Zheng 
101*7f9fc99cSLv Zheng 	/* Fill the return values */
102*7f9fc99cSLv Zheng 
103*7f9fc99cSLv Zheng 	*table_ptr = table;
104*7f9fc99cSLv Zheng 	*table_length = table_desc->length;
105*7f9fc99cSLv Zheng 	*table_flags = table_desc->flags;
106*7f9fc99cSLv Zheng 
107*7f9fc99cSLv Zheng 	return (AE_OK);
108*7f9fc99cSLv Zheng }
109*7f9fc99cSLv Zheng 
110*7f9fc99cSLv Zheng /*******************************************************************************
111*7f9fc99cSLv Zheng  *
112*7f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_release_table
113*7f9fc99cSLv Zheng  *
114*7f9fc99cSLv Zheng  * PARAMETERS:  table               - Pointer for the table
115*7f9fc99cSLv Zheng  *              table_length        - Length for the table
116*7f9fc99cSLv Zheng  *              table_flags         - Allocation flags for the table
117*7f9fc99cSLv Zheng  *
118*7f9fc99cSLv Zheng  * RETURN:      None
119*7f9fc99cSLv Zheng  *
120*7f9fc99cSLv Zheng  * DESCRIPTION: Release a table. The reversal of acpi_tb_acquire_table().
121*7f9fc99cSLv Zheng  *
122*7f9fc99cSLv Zheng  ******************************************************************************/
123*7f9fc99cSLv Zheng 
124*7f9fc99cSLv Zheng void
125*7f9fc99cSLv Zheng acpi_tb_release_table(struct acpi_table_header *table,
126*7f9fc99cSLv Zheng 		      u32 table_length, u8 table_flags)
127*7f9fc99cSLv Zheng {
128*7f9fc99cSLv Zheng 	switch (table_flags & ACPI_TABLE_ORIGIN_MASK) {
129*7f9fc99cSLv Zheng 	case ACPI_TABLE_ORIGIN_MAPPED:
130*7f9fc99cSLv Zheng 
131*7f9fc99cSLv Zheng 		acpi_os_unmap_memory(table, table_length);
132*7f9fc99cSLv Zheng 		break;
133*7f9fc99cSLv Zheng 
134*7f9fc99cSLv Zheng 	case ACPI_TABLE_ORIGIN_ALLOCATED:
135*7f9fc99cSLv Zheng 	case ACPI_TABLE_ORIGIN_UNKNOWN:
136*7f9fc99cSLv Zheng 	case ACPI_TABLE_ORIGIN_OVERRIDE:
137*7f9fc99cSLv Zheng 	default:
138*7f9fc99cSLv Zheng 
139*7f9fc99cSLv Zheng 		break;
140*7f9fc99cSLv Zheng 	}
141*7f9fc99cSLv Zheng }
142*7f9fc99cSLv Zheng 
143*7f9fc99cSLv Zheng /******************************************************************************
144*7f9fc99cSLv Zheng  *
145*7f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_validate_table
146*7f9fc99cSLv Zheng  *
147*7f9fc99cSLv Zheng  * PARAMETERS:  table_desc          - Table descriptor
148*7f9fc99cSLv Zheng  *
149*7f9fc99cSLv Zheng  * RETURN:      Status
150*7f9fc99cSLv Zheng  *
151*7f9fc99cSLv Zheng  * DESCRIPTION: This function is called to validate (ensure Pointer is valid)
152*7f9fc99cSLv Zheng  *              and verify the table.
153*7f9fc99cSLv Zheng  *
154*7f9fc99cSLv Zheng  *****************************************************************************/
155*7f9fc99cSLv Zheng 
156*7f9fc99cSLv Zheng acpi_status acpi_tb_validate_table(struct acpi_table_desc *table_desc)
157*7f9fc99cSLv Zheng {
158*7f9fc99cSLv Zheng 	acpi_status status = AE_OK;
159*7f9fc99cSLv Zheng 
160*7f9fc99cSLv Zheng 	ACPI_FUNCTION_TRACE(tb_validate_table);
161*7f9fc99cSLv Zheng 
162*7f9fc99cSLv Zheng 	/* Validate the table if necessary */
163*7f9fc99cSLv Zheng 
16495b482a8SLen Brown 	if (!table_desc->pointer) {
165*7f9fc99cSLv Zheng 		status = acpi_tb_acquire_table(table_desc, &table_desc->pointer,
166*7f9fc99cSLv Zheng 					       &table_desc->length,
167*7f9fc99cSLv Zheng 					       &table_desc->flags);
168*7f9fc99cSLv Zheng 		if (ACPI_FAILURE(status) || !table_desc->pointer) {
16995b482a8SLen Brown 			return_ACPI_STATUS(AE_NO_MEMORY);
17095b482a8SLen Brown 		}
17195b482a8SLen Brown 	}
17295b482a8SLen Brown 
17395b482a8SLen Brown 	/* Always calculate checksum, ignore bad checksum if requested */
17495b482a8SLen Brown 
17595b482a8SLen Brown 	status =
17694d4be67SLv Zheng 	    acpi_tb_verify_checksum(table_desc->pointer, table_desc->length);
17795b482a8SLen Brown 
17895b482a8SLen Brown 	return_ACPI_STATUS(status);
17995b482a8SLen Brown }
18095b482a8SLen Brown 
18195b482a8SLen Brown /*******************************************************************************
18295b482a8SLen Brown  *
183*7f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_invalidate_table
184*7f9fc99cSLv Zheng  *
185*7f9fc99cSLv Zheng  * PARAMETERS:  table_desc          - Table descriptor
186*7f9fc99cSLv Zheng  *
187*7f9fc99cSLv Zheng  * RETURN:      None
188*7f9fc99cSLv Zheng  *
189*7f9fc99cSLv Zheng  * DESCRIPTION: Invalidate one internal ACPI table, this is reversal of
190*7f9fc99cSLv Zheng  *              acpi_tb_validate_table().
191*7f9fc99cSLv Zheng  *
192*7f9fc99cSLv Zheng  ******************************************************************************/
193*7f9fc99cSLv Zheng 
194*7f9fc99cSLv Zheng void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc)
195*7f9fc99cSLv Zheng {
196*7f9fc99cSLv Zheng 
197*7f9fc99cSLv Zheng 	ACPI_FUNCTION_TRACE(tb_invalidate_table);
198*7f9fc99cSLv Zheng 
199*7f9fc99cSLv Zheng 	/* Table must be validated */
200*7f9fc99cSLv Zheng 
201*7f9fc99cSLv Zheng 	if (!table_desc->pointer) {
202*7f9fc99cSLv Zheng 		return_VOID;
203*7f9fc99cSLv Zheng 	}
204*7f9fc99cSLv Zheng 
205*7f9fc99cSLv Zheng 	acpi_tb_release_table(table_desc->pointer, table_desc->length,
206*7f9fc99cSLv Zheng 			      table_desc->flags);
207*7f9fc99cSLv Zheng 	table_desc->pointer = NULL;
208*7f9fc99cSLv Zheng 
209*7f9fc99cSLv Zheng 	return_VOID;
210*7f9fc99cSLv Zheng }
211*7f9fc99cSLv Zheng 
212*7f9fc99cSLv Zheng /*******************************************************************************
213*7f9fc99cSLv Zheng  *
21495b482a8SLen Brown  * FUNCTION:    acpi_tb_add_table
21595b482a8SLen Brown  *
21695b482a8SLen Brown  * PARAMETERS:  table_desc          - Table descriptor
21795b482a8SLen Brown  *              table_index         - Where the table index is returned
21895b482a8SLen Brown  *
21995b482a8SLen Brown  * RETURN:      Status
22095b482a8SLen Brown  *
221d3ccaff8SBob Moore  * DESCRIPTION: This function is called to add an ACPI table. It is used to
222d3ccaff8SBob Moore  *              dynamically load tables via the Load and load_table AML
223d3ccaff8SBob Moore  *              operators.
22495b482a8SLen Brown  *
22595b482a8SLen Brown  ******************************************************************************/
22695b482a8SLen Brown 
22795b482a8SLen Brown acpi_status
22895b482a8SLen Brown acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
22995b482a8SLen Brown {
23095b482a8SLen Brown 	u32 i;
23195b482a8SLen Brown 	acpi_status status = AE_OK;
232*7f9fc99cSLv Zheng 	struct acpi_table_header *final_table;
23395b482a8SLen Brown 
23495b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_add_table);
23595b482a8SLen Brown 
23695b482a8SLen Brown 	if (!table_desc->pointer) {
237*7f9fc99cSLv Zheng 		status = acpi_tb_validate_table(table_desc);
23895b482a8SLen Brown 		if (ACPI_FAILURE(status) || !table_desc->pointer) {
23995b482a8SLen Brown 			return_ACPI_STATUS(status);
24095b482a8SLen Brown 		}
24195b482a8SLen Brown 	}
24295b482a8SLen Brown 
24395b482a8SLen Brown 	/*
244c8cefe30SBob Moore 	 * Validate the incoming table signature.
245c8cefe30SBob Moore 	 *
246c8cefe30SBob Moore 	 * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
247c8cefe30SBob Moore 	 * 2) We added support for OEMx tables, signature "OEM".
248c8cefe30SBob Moore 	 * 3) Valid tables were encountered with a null signature, so we just
249c8cefe30SBob Moore 	 *    gave up on validating the signature, (05/2008).
250c8cefe30SBob Moore 	 * 4) We encountered non-AML tables such as the MADT, which caused
251c8cefe30SBob Moore 	 *    interpreter errors and kernel faults. So now, we once again allow
252c8cefe30SBob Moore 	 *    only "SSDT", "OEMx", and now, also a null signature. (05/2011).
25395b482a8SLen Brown 	 */
254c8cefe30SBob Moore 	if ((table_desc->pointer->signature[0] != 0x00) &&
255c8cefe30SBob Moore 	    (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT))
256c8cefe30SBob Moore 	    && (ACPI_STRNCMP(table_desc->pointer->signature, "OEM", 3))) {
2573b3ea775SBob Moore 		ACPI_BIOS_ERROR((AE_INFO,
2583b3ea775SBob Moore 				 "Table has invalid signature [%4.4s] (0x%8.8X), "
2593b3ea775SBob Moore 				 "must be SSDT or OEMx",
260de8e7db7SBob Moore 				 acpi_ut_valid_acpi_name(table_desc->pointer->
2613b3ea775SBob Moore 							 signature) ?
2623b3ea775SBob Moore 				 table_desc->pointer->signature : "????",
263c8cefe30SBob Moore 				 *(u32 *)table_desc->pointer->signature));
264c8cefe30SBob Moore 
265c8cefe30SBob Moore 		return_ACPI_STATUS(AE_BAD_SIGNATURE);
266c8cefe30SBob Moore 	}
26795b482a8SLen Brown 
26895b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
26995b482a8SLen Brown 
27095b482a8SLen Brown 	/* Check if table is already registered */
27195b482a8SLen Brown 
272b9ee2043SBob Moore 	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
27395b482a8SLen Brown 		if (!acpi_gbl_root_table_list.tables[i].pointer) {
27495b482a8SLen Brown 			status =
275*7f9fc99cSLv Zheng 			    acpi_tb_validate_table(&acpi_gbl_root_table_list.
27695b482a8SLen Brown 						   tables[i]);
27795b482a8SLen Brown 			if (ACPI_FAILURE(status)
27895b482a8SLen Brown 			    || !acpi_gbl_root_table_list.tables[i].pointer) {
27995b482a8SLen Brown 				continue;
28095b482a8SLen Brown 			}
28195b482a8SLen Brown 		}
28295b482a8SLen Brown 
28395b482a8SLen Brown 		/*
28495b482a8SLen Brown 		 * Check for a table match on the entire table length,
28595b482a8SLen Brown 		 * not just the header.
28695b482a8SLen Brown 		 */
28795b482a8SLen Brown 		if (table_desc->length !=
28895b482a8SLen Brown 		    acpi_gbl_root_table_list.tables[i].length) {
28995b482a8SLen Brown 			continue;
29095b482a8SLen Brown 		}
29195b482a8SLen Brown 
29295b482a8SLen Brown 		if (ACPI_MEMCMP(table_desc->pointer,
29395b482a8SLen Brown 				acpi_gbl_root_table_list.tables[i].pointer,
29495b482a8SLen Brown 				acpi_gbl_root_table_list.tables[i].length)) {
29595b482a8SLen Brown 			continue;
29695b482a8SLen Brown 		}
29795b482a8SLen Brown 
29895b482a8SLen Brown 		/*
29995b482a8SLen Brown 		 * Note: the current mechanism does not unregister a table if it is
30095b482a8SLen Brown 		 * dynamically unloaded. The related namespace entries are deleted,
30195b482a8SLen Brown 		 * but the table remains in the root table list.
30295b482a8SLen Brown 		 *
30395b482a8SLen Brown 		 * The assumption here is that the number of different tables that
30495b482a8SLen Brown 		 * will be loaded is actually small, and there is minimal overhead
30595b482a8SLen Brown 		 * in just keeping the table in case it is needed again.
30695b482a8SLen Brown 		 *
30795b482a8SLen Brown 		 * If this assumption changes in the future (perhaps on large
30895b482a8SLen Brown 		 * machines with many table load/unload operations), tables will
30995b482a8SLen Brown 		 * need to be unregistered when they are unloaded, and slots in the
31095b482a8SLen Brown 		 * root table list should be reused when empty.
31195b482a8SLen Brown 		 */
31295b482a8SLen Brown 		*table_index = i;
31395b482a8SLen Brown 
31495b482a8SLen Brown 		if (acpi_gbl_root_table_list.tables[i].
31595b482a8SLen Brown 		    flags & ACPI_TABLE_IS_LOADED) {
31695b482a8SLen Brown 
31795b482a8SLen Brown 			/* Table is still loaded, this is an error */
31895b482a8SLen Brown 
31995b482a8SLen Brown 			status = AE_ALREADY_EXISTS;
32095b482a8SLen Brown 			goto release;
32195b482a8SLen Brown 		} else {
32295b482a8SLen Brown 			/* Table was unloaded, allow it to be reloaded */
32395b482a8SLen Brown 
324*7f9fc99cSLv Zheng 			acpi_tb_uninstall_table(table_desc);
32595b482a8SLen Brown 			table_desc->pointer =
32695b482a8SLen Brown 			    acpi_gbl_root_table_list.tables[i].pointer;
32795b482a8SLen Brown 			table_desc->address =
32895b482a8SLen Brown 			    acpi_gbl_root_table_list.tables[i].address;
32995b482a8SLen Brown 			status = AE_OK;
33095b482a8SLen Brown 			goto print_header;
33195b482a8SLen Brown 		}
33295b482a8SLen Brown 	}
33395b482a8SLen Brown 
334d3ccaff8SBob Moore 	/*
335d3ccaff8SBob Moore 	 * ACPI Table Override:
336d3ccaff8SBob Moore 	 * Allow the host to override dynamically loaded tables.
337f7b004a1SBob Moore 	 * NOTE: the table is fully mapped at this point, and the mapping will
338*7f9fc99cSLv Zheng 	 * be deleted by acpi_tb_override_table if the table is actually overridden.
339d3ccaff8SBob Moore 	 */
340*7f9fc99cSLv Zheng 	final_table = acpi_tb_override_table(table_desc->pointer, table_desc);
341*7f9fc99cSLv Zheng 	if (final_table) {
342*7f9fc99cSLv Zheng 
343*7f9fc99cSLv Zheng 		/* Ensure table descriptor is in "VALIDATED" state */
344*7f9fc99cSLv Zheng 
345*7f9fc99cSLv Zheng 		table_desc->pointer = final_table;
346*7f9fc99cSLv Zheng 	}
347d3ccaff8SBob Moore 
34895b482a8SLen Brown 	/* Add the table to the global root table list */
34995b482a8SLen Brown 
35095b482a8SLen Brown 	status = acpi_tb_store_table(table_desc->address, table_desc->pointer,
35195b482a8SLen Brown 				     table_desc->length, table_desc->flags,
35295b482a8SLen Brown 				     table_index);
35395b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
35495b482a8SLen Brown 		goto release;
35595b482a8SLen Brown 	}
35695b482a8SLen Brown 
35795b482a8SLen Brown print_header:
35895b482a8SLen Brown 	acpi_tb_print_table_header(table_desc->address, table_desc->pointer);
35995b482a8SLen Brown 
36095b482a8SLen Brown release:
36195b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
36295b482a8SLen Brown 	return_ACPI_STATUS(status);
36395b482a8SLen Brown }
36495b482a8SLen Brown 
36595b482a8SLen Brown /*******************************************************************************
36695b482a8SLen Brown  *
367*7f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_override_table
368f7b004a1SBob Moore  *
369f7b004a1SBob Moore  * PARAMETERS:  table_header        - Header for the original table
370f7b004a1SBob Moore  *              table_desc          - Table descriptor initialized for the
371f7b004a1SBob Moore  *                                    original table. May or may not be mapped.
372f7b004a1SBob Moore  *
373f7b004a1SBob Moore  * RETURN:      Pointer to the entire new table. NULL if table not overridden.
374f7b004a1SBob Moore  *              If overridden, installs the new table within the input table
375f7b004a1SBob Moore  *              descriptor.
376f7b004a1SBob Moore  *
377f7b004a1SBob Moore  * DESCRIPTION: Attempt table override by calling the OSL override functions.
378f7b004a1SBob Moore  *              Note: If the table is overridden, then the entire new table
379*7f9fc99cSLv Zheng  *              is acquired and returned by this function.
380*7f9fc99cSLv Zheng  *              After invocation, the table descriptor is in a state that is
381*7f9fc99cSLv Zheng  *              "INSTALLED" but not "VALIDATED", thus the "Pointer" member is
382*7f9fc99cSLv Zheng  *              kept NULL.
383f7b004a1SBob Moore  *
384f7b004a1SBob Moore  ******************************************************************************/
385f7b004a1SBob Moore 
386*7f9fc99cSLv Zheng struct acpi_table_header *acpi_tb_override_table(struct acpi_table_header
387f7b004a1SBob Moore 						 *table_header,
388f7b004a1SBob Moore 						 struct acpi_table_desc
389f7b004a1SBob Moore 						 *table_desc)
390f7b004a1SBob Moore {
391f7b004a1SBob Moore 	acpi_status status;
392*7f9fc99cSLv Zheng 	struct acpi_table_header *new_table;
393*7f9fc99cSLv Zheng 	u32 new_table_length;
394f7b004a1SBob Moore 	u8 new_flags;
395f7b004a1SBob Moore 	char *override_type;
396*7f9fc99cSLv Zheng 	struct acpi_table_desc new_table_desc;
397*7f9fc99cSLv Zheng 
398*7f9fc99cSLv Zheng 	ACPI_MEMSET(&new_table_desc, 0, sizeof(struct acpi_table_desc));
399f7b004a1SBob Moore 
400f7b004a1SBob Moore 	/* (1) Attempt logical override (returns a logical address) */
401f7b004a1SBob Moore 
402*7f9fc99cSLv Zheng 	status = acpi_os_table_override(table_header, &new_table_desc.pointer);
403*7f9fc99cSLv Zheng 	if (ACPI_SUCCESS(status) && new_table_desc.pointer) {
404*7f9fc99cSLv Zheng 		new_table_desc.address =
405*7f9fc99cSLv Zheng 		    ACPI_PTR_TO_PHYSADDR(new_table_desc.pointer);
406*7f9fc99cSLv Zheng 		new_table_desc.length = new_table_desc.pointer->length;
407*7f9fc99cSLv Zheng 		new_table_desc.flags = ACPI_TABLE_ORIGIN_OVERRIDE;
408f7b004a1SBob Moore 		override_type = "Logical";
409f7b004a1SBob Moore 		goto finish_override;
410f7b004a1SBob Moore 	}
411f7b004a1SBob Moore 
412f7b004a1SBob Moore 	/* (2) Attempt physical override (returns a physical address) */
413f7b004a1SBob Moore 
414f7b004a1SBob Moore 	status = acpi_os_physical_table_override(table_header,
415*7f9fc99cSLv Zheng 						 &new_table_desc.address,
416*7f9fc99cSLv Zheng 						 &new_table_desc.length);
417*7f9fc99cSLv Zheng 	if (ACPI_SUCCESS(status) && new_table_desc.address
418*7f9fc99cSLv Zheng 	    && new_table_desc.length) {
419f7b004a1SBob Moore 		override_type = "Physical";
420*7f9fc99cSLv Zheng 		new_table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED;
421f7b004a1SBob Moore 		goto finish_override;
422f7b004a1SBob Moore 	}
423f7b004a1SBob Moore 
424f7b004a1SBob Moore 	return (NULL);		/* There was no override */
425f7b004a1SBob Moore 
426f7b004a1SBob Moore finish_override:
427f7b004a1SBob Moore 
428*7f9fc99cSLv Zheng 	/*
429*7f9fc99cSLv Zheng 	 * Acquire the entire new table to indicate overridden.
430*7f9fc99cSLv Zheng 	 * Note that this is required by the callers of this function.
431*7f9fc99cSLv Zheng 	 */
432*7f9fc99cSLv Zheng 	status = acpi_tb_acquire_table(&new_table_desc, &new_table,
433*7f9fc99cSLv Zheng 				       &new_table_length, &new_flags);
434*7f9fc99cSLv Zheng 	if (ACPI_FAILURE(status)) {
435*7f9fc99cSLv Zheng 		ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
436*7f9fc99cSLv Zheng 				"%4.4s " ACPI_PRINTF_UINT
437*7f9fc99cSLv Zheng 				" Attempted table override failed",
438*7f9fc99cSLv Zheng 				table_header->signature,
439*7f9fc99cSLv Zheng 				ACPI_FORMAT_TO_UINT(table_desc->address)));
440*7f9fc99cSLv Zheng 		return (NULL);
441*7f9fc99cSLv Zheng 	}
442*7f9fc99cSLv Zheng 
4432e19f8d0SBob Moore 	ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT
4442e19f8d0SBob Moore 		   " %s table override, new table: " ACPI_PRINTF_UINT,
445f7b004a1SBob Moore 		   table_header->signature,
4462e19f8d0SBob Moore 		   ACPI_FORMAT_TO_UINT(table_desc->address),
447*7f9fc99cSLv Zheng 		   override_type, ACPI_FORMAT_TO_UINT(new_table_desc.address)));
448f7b004a1SBob Moore 
449*7f9fc99cSLv Zheng 	/* We can now uninstall the original table (if fully mapped) */
450f7b004a1SBob Moore 
451*7f9fc99cSLv Zheng 	acpi_tb_uninstall_table(table_desc);
452f7b004a1SBob Moore 
453*7f9fc99cSLv Zheng 	/* Install the new table */
454f7b004a1SBob Moore 
455*7f9fc99cSLv Zheng 	table_desc->address = new_table_desc.address;
456*7f9fc99cSLv Zheng 	table_desc->length = new_table_desc.length;
457*7f9fc99cSLv Zheng 	table_desc->flags = new_table_desc.flags;
458f7b004a1SBob Moore 
459f7b004a1SBob Moore 	return (new_table);
460f7b004a1SBob Moore }
461f7b004a1SBob Moore 
462f7b004a1SBob Moore /*******************************************************************************
463f7b004a1SBob Moore  *
46495b482a8SLen Brown  * FUNCTION:    acpi_tb_resize_root_table_list
46595b482a8SLen Brown  *
46695b482a8SLen Brown  * PARAMETERS:  None
46795b482a8SLen Brown  *
46895b482a8SLen Brown  * RETURN:      Status
46995b482a8SLen Brown  *
47095b482a8SLen Brown  * DESCRIPTION: Expand the size of global table array
47195b482a8SLen Brown  *
47295b482a8SLen Brown  ******************************************************************************/
47395b482a8SLen Brown 
47495b482a8SLen Brown acpi_status acpi_tb_resize_root_table_list(void)
47595b482a8SLen Brown {
47695b482a8SLen Brown 	struct acpi_table_desc *tables;
4772bc198c1SLv Zheng 	u32 table_count;
47895b482a8SLen Brown 
47995b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
48095b482a8SLen Brown 
48195b482a8SLen Brown 	/* allow_resize flag is a parameter to acpi_initialize_tables */
48295b482a8SLen Brown 
48395b482a8SLen Brown 	if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) {
48495b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
48595b482a8SLen Brown 			    "Resize of Root Table Array is not allowed"));
48695b482a8SLen Brown 		return_ACPI_STATUS(AE_SUPPORT);
48795b482a8SLen Brown 	}
48895b482a8SLen Brown 
48995b482a8SLen Brown 	/* Increase the Table Array size */
49095b482a8SLen Brown 
4912bc198c1SLv Zheng 	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
4922bc198c1SLv Zheng 		table_count = acpi_gbl_root_table_list.max_table_count;
4932bc198c1SLv Zheng 	} else {
4942bc198c1SLv Zheng 		table_count = acpi_gbl_root_table_list.current_table_count;
4952bc198c1SLv Zheng 	}
4962bc198c1SLv Zheng 
4972bc198c1SLv Zheng 	tables = ACPI_ALLOCATE_ZEROED(((acpi_size) table_count +
498ec41f193SBob Moore 				       ACPI_ROOT_TABLE_SIZE_INCREMENT) *
499ec41f193SBob Moore 				      sizeof(struct acpi_table_desc));
50095b482a8SLen Brown 	if (!tables) {
50195b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
50295b482a8SLen Brown 			    "Could not allocate new root table array"));
50395b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_MEMORY);
50495b482a8SLen Brown 	}
50595b482a8SLen Brown 
50695b482a8SLen Brown 	/* Copy and free the previous table array */
50795b482a8SLen Brown 
50895b482a8SLen Brown 	if (acpi_gbl_root_table_list.tables) {
50995b482a8SLen Brown 		ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
5102bc198c1SLv Zheng 			    (acpi_size) table_count *
5112bc198c1SLv Zheng 			    sizeof(struct acpi_table_desc));
51295b482a8SLen Brown 
51395b482a8SLen Brown 		if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
51495b482a8SLen Brown 			ACPI_FREE(acpi_gbl_root_table_list.tables);
51595b482a8SLen Brown 		}
51695b482a8SLen Brown 	}
51795b482a8SLen Brown 
51895b482a8SLen Brown 	acpi_gbl_root_table_list.tables = tables;
5192bc198c1SLv Zheng 	acpi_gbl_root_table_list.max_table_count =
5202bc198c1SLv Zheng 	    table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT;
5212bc198c1SLv Zheng 	acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
52295b482a8SLen Brown 
52395b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
52495b482a8SLen Brown }
52595b482a8SLen Brown 
52695b482a8SLen Brown /*******************************************************************************
52795b482a8SLen Brown  *
52895b482a8SLen Brown  * FUNCTION:    acpi_tb_store_table
52995b482a8SLen Brown  *
530ba494beeSBob Moore  * PARAMETERS:  address             - Table address
531ba494beeSBob Moore  *              table               - Table header
532ba494beeSBob Moore  *              length              - Table length
533ba494beeSBob Moore  *              flags               - flags
53495b482a8SLen Brown  *
53595b482a8SLen Brown  * RETURN:      Status and table index.
53695b482a8SLen Brown  *
53795b482a8SLen Brown  * DESCRIPTION: Add an ACPI table to the global table list
53895b482a8SLen Brown  *
53995b482a8SLen Brown  ******************************************************************************/
54095b482a8SLen Brown 
54195b482a8SLen Brown acpi_status
54295b482a8SLen Brown acpi_tb_store_table(acpi_physical_address address,
54395b482a8SLen Brown 		    struct acpi_table_header *table,
54495b482a8SLen Brown 		    u32 length, u8 flags, u32 *table_index)
54595b482a8SLen Brown {
546b9ee2043SBob Moore 	acpi_status status;
547b9ee2043SBob Moore 	struct acpi_table_desc *new_table;
54895b482a8SLen Brown 
54995b482a8SLen Brown 	/* Ensure that there is room for the table in the Root Table List */
55095b482a8SLen Brown 
551b9ee2043SBob Moore 	if (acpi_gbl_root_table_list.current_table_count >=
552b9ee2043SBob Moore 	    acpi_gbl_root_table_list.max_table_count) {
55395b482a8SLen Brown 		status = acpi_tb_resize_root_table_list();
55495b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
55595b482a8SLen Brown 			return (status);
55695b482a8SLen Brown 		}
55795b482a8SLen Brown 	}
55895b482a8SLen Brown 
559b9ee2043SBob Moore 	new_table =
560b9ee2043SBob Moore 	    &acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.
561b9ee2043SBob Moore 					     current_table_count];
562b9ee2043SBob Moore 
56395b482a8SLen Brown 	/* Initialize added table */
56495b482a8SLen Brown 
565b9ee2043SBob Moore 	new_table->address = address;
566b9ee2043SBob Moore 	new_table->pointer = table;
567b9ee2043SBob Moore 	new_table->length = length;
568b9ee2043SBob Moore 	new_table->owner_id = 0;
569b9ee2043SBob Moore 	new_table->flags = flags;
57095b482a8SLen Brown 
571b9ee2043SBob Moore 	ACPI_MOVE_32_TO_32(&new_table->signature, table->signature);
57295b482a8SLen Brown 
573b9ee2043SBob Moore 	*table_index = acpi_gbl_root_table_list.current_table_count;
574b9ee2043SBob Moore 	acpi_gbl_root_table_list.current_table_count++;
575b9ee2043SBob Moore 	return (AE_OK);
57695b482a8SLen Brown }
57795b482a8SLen Brown 
57895b482a8SLen Brown /*******************************************************************************
57995b482a8SLen Brown  *
580*7f9fc99cSLv Zheng  * FUNCTION:    acpi_tb_uninstall_table
58195b482a8SLen Brown  *
582*7f9fc99cSLv Zheng  * PARAMETERS:  table_desc          - Table descriptor
58395b482a8SLen Brown  *
58495b482a8SLen Brown  * RETURN:      None
58595b482a8SLen Brown  *
58695b482a8SLen Brown  * DESCRIPTION: Delete one internal ACPI table
58795b482a8SLen Brown  *
58895b482a8SLen Brown  ******************************************************************************/
58995b482a8SLen Brown 
590*7f9fc99cSLv Zheng void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc)
59195b482a8SLen Brown {
5925582982dSLv Zheng 
593*7f9fc99cSLv Zheng 	ACPI_FUNCTION_TRACE(tb_uninstall_table);
5945582982dSLv Zheng 
595*7f9fc99cSLv Zheng 	/* Table must be installed */
596*7f9fc99cSLv Zheng 
597*7f9fc99cSLv Zheng 	if (!table_desc->address) {
598*7f9fc99cSLv Zheng 		return_VOID;
59995b482a8SLen Brown 	}
6005582982dSLv Zheng 
601*7f9fc99cSLv Zheng 	acpi_tb_invalidate_table(table_desc);
6021d1ea1b7SChao Guan 
603*7f9fc99cSLv Zheng 	if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) ==
604*7f9fc99cSLv Zheng 	    ACPI_TABLE_ORIGIN_ALLOCATED) {
605*7f9fc99cSLv Zheng 		ACPI_FREE(ACPI_CAST_PTR(void, table_desc->address));
606*7f9fc99cSLv Zheng 	}
6071d1ea1b7SChao Guan 
608dc156adfSLv Zheng 	table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL);
609f7b004a1SBob Moore 
610*7f9fc99cSLv Zheng 	return_VOID;
61195b482a8SLen Brown }
61295b482a8SLen Brown 
61395b482a8SLen Brown /*******************************************************************************
61495b482a8SLen Brown  *
61595b482a8SLen Brown  * FUNCTION:    acpi_tb_terminate
61695b482a8SLen Brown  *
61795b482a8SLen Brown  * PARAMETERS:  None
61895b482a8SLen Brown  *
61995b482a8SLen Brown  * RETURN:      None
62095b482a8SLen Brown  *
62195b482a8SLen Brown  * DESCRIPTION: Delete all internal ACPI tables
62295b482a8SLen Brown  *
62395b482a8SLen Brown  ******************************************************************************/
62495b482a8SLen Brown 
62595b482a8SLen Brown void acpi_tb_terminate(void)
62695b482a8SLen Brown {
62795b482a8SLen Brown 	u32 i;
62895b482a8SLen Brown 
62995b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_terminate);
63095b482a8SLen Brown 
63195b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
63295b482a8SLen Brown 
63395b482a8SLen Brown 	/* Delete the individual tables */
63495b482a8SLen Brown 
635b9ee2043SBob Moore 	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
636*7f9fc99cSLv Zheng 		acpi_tb_uninstall_table(&acpi_gbl_root_table_list.tables[i]);
63795b482a8SLen Brown 	}
63895b482a8SLen Brown 
63995b482a8SLen Brown 	/*
64095b482a8SLen Brown 	 * Delete the root table array if allocated locally. Array cannot be
64195b482a8SLen Brown 	 * mapped, so we don't need to check for that flag.
64295b482a8SLen Brown 	 */
64395b482a8SLen Brown 	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
64495b482a8SLen Brown 		ACPI_FREE(acpi_gbl_root_table_list.tables);
64595b482a8SLen Brown 	}
64695b482a8SLen Brown 
64795b482a8SLen Brown 	acpi_gbl_root_table_list.tables = NULL;
64895b482a8SLen Brown 	acpi_gbl_root_table_list.flags = 0;
649b9ee2043SBob Moore 	acpi_gbl_root_table_list.current_table_count = 0;
65095b482a8SLen Brown 
65195b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
65295b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
65368aafc35SBob Moore 
65468aafc35SBob Moore 	return_VOID;
65595b482a8SLen Brown }
65695b482a8SLen Brown 
65795b482a8SLen Brown /*******************************************************************************
65895b482a8SLen Brown  *
65995b482a8SLen Brown  * FUNCTION:    acpi_tb_delete_namespace_by_owner
66095b482a8SLen Brown  *
66195b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
66295b482a8SLen Brown  *
6638a335a23SBob Moore  * RETURN:      Status
66495b482a8SLen Brown  *
66595b482a8SLen Brown  * DESCRIPTION: Delete all namespace objects created when this table was loaded.
66695b482a8SLen Brown  *
66795b482a8SLen Brown  ******************************************************************************/
66895b482a8SLen Brown 
6698a335a23SBob Moore acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index)
67095b482a8SLen Brown {
67195b482a8SLen Brown 	acpi_owner_id owner_id;
6728a335a23SBob Moore 	acpi_status status;
67395b482a8SLen Brown 
6748a335a23SBob Moore 	ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner);
6758a335a23SBob Moore 
6768a335a23SBob Moore 	status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
6778a335a23SBob Moore 	if (ACPI_FAILURE(status)) {
6788a335a23SBob Moore 		return_ACPI_STATUS(status);
67995b482a8SLen Brown 	}
68095b482a8SLen Brown 
681b9ee2043SBob Moore 	if (table_index >= acpi_gbl_root_table_list.current_table_count) {
6828a335a23SBob Moore 
6838a335a23SBob Moore 		/* The table index does not exist */
6848a335a23SBob Moore 
68595b482a8SLen Brown 		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
6868a335a23SBob Moore 		return_ACPI_STATUS(AE_NOT_EXIST);
6878a335a23SBob Moore 	}
6888a335a23SBob Moore 
6898a335a23SBob Moore 	/* Get the owner ID for this table, used to delete namespace nodes */
6908a335a23SBob Moore 
6918a335a23SBob Moore 	owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id;
6928a335a23SBob Moore 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
6938a335a23SBob Moore 
6948a335a23SBob Moore 	/*
6958a335a23SBob Moore 	 * Need to acquire the namespace writer lock to prevent interference
6968a335a23SBob Moore 	 * with any concurrent namespace walks. The interpreter must be
6978a335a23SBob Moore 	 * released during the deletion since the acquisition of the deletion
6988a335a23SBob Moore 	 * lock may block, and also since the execution of a namespace walk
6998a335a23SBob Moore 	 * must be allowed to use the interpreter.
7008a335a23SBob Moore 	 */
701e4c1ebfcSBob Moore 	(void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
7028a335a23SBob Moore 	status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock);
7038a335a23SBob Moore 
70495b482a8SLen Brown 	acpi_ns_delete_namespace_by_owner(owner_id);
7058a335a23SBob Moore 	if (ACPI_FAILURE(status)) {
7068a335a23SBob Moore 		return_ACPI_STATUS(status);
7078a335a23SBob Moore 	}
7088a335a23SBob Moore 
7098a335a23SBob Moore 	acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock);
7108a335a23SBob Moore 
7118a335a23SBob Moore 	status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
7128a335a23SBob Moore 	return_ACPI_STATUS(status);
71395b482a8SLen Brown }
71495b482a8SLen Brown 
71595b482a8SLen Brown /*******************************************************************************
71695b482a8SLen Brown  *
71795b482a8SLen Brown  * FUNCTION:    acpi_tb_allocate_owner_id
71895b482a8SLen Brown  *
71995b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
72095b482a8SLen Brown  *
72195b482a8SLen Brown  * RETURN:      Status
72295b482a8SLen Brown  *
72395b482a8SLen Brown  * DESCRIPTION: Allocates owner_id in table_desc
72495b482a8SLen Brown  *
72595b482a8SLen Brown  ******************************************************************************/
72695b482a8SLen Brown 
72795b482a8SLen Brown acpi_status acpi_tb_allocate_owner_id(u32 table_index)
72895b482a8SLen Brown {
72995b482a8SLen Brown 	acpi_status status = AE_BAD_PARAMETER;
73095b482a8SLen Brown 
73195b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
73295b482a8SLen Brown 
73395b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
734b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
73595b482a8SLen Brown 		status = acpi_ut_allocate_owner_id
73695b482a8SLen Brown 		    (&(acpi_gbl_root_table_list.tables[table_index].owner_id));
73795b482a8SLen Brown 	}
73895b482a8SLen Brown 
73995b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
74095b482a8SLen Brown 	return_ACPI_STATUS(status);
74195b482a8SLen Brown }
74295b482a8SLen Brown 
74395b482a8SLen Brown /*******************************************************************************
74495b482a8SLen Brown  *
74595b482a8SLen Brown  * FUNCTION:    acpi_tb_release_owner_id
74695b482a8SLen Brown  *
74795b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
74895b482a8SLen Brown  *
74995b482a8SLen Brown  * RETURN:      Status
75095b482a8SLen Brown  *
75195b482a8SLen Brown  * DESCRIPTION: Releases owner_id in table_desc
75295b482a8SLen Brown  *
75395b482a8SLen Brown  ******************************************************************************/
75495b482a8SLen Brown 
75595b482a8SLen Brown acpi_status acpi_tb_release_owner_id(u32 table_index)
75695b482a8SLen Brown {
75795b482a8SLen Brown 	acpi_status status = AE_BAD_PARAMETER;
75895b482a8SLen Brown 
75995b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_release_owner_id);
76095b482a8SLen Brown 
76195b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
762b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
76395b482a8SLen Brown 		acpi_ut_release_owner_id(&
76495b482a8SLen Brown 					 (acpi_gbl_root_table_list.
76595b482a8SLen Brown 					  tables[table_index].owner_id));
76695b482a8SLen Brown 		status = AE_OK;
76795b482a8SLen Brown 	}
76895b482a8SLen Brown 
76995b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
77095b482a8SLen Brown 	return_ACPI_STATUS(status);
77195b482a8SLen Brown }
77295b482a8SLen Brown 
77395b482a8SLen Brown /*******************************************************************************
77495b482a8SLen Brown  *
77595b482a8SLen Brown  * FUNCTION:    acpi_tb_get_owner_id
77695b482a8SLen Brown  *
77795b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
77895b482a8SLen Brown  *              owner_id            - Where the table owner_id is returned
77995b482a8SLen Brown  *
78095b482a8SLen Brown  * RETURN:      Status
78195b482a8SLen Brown  *
78295b482a8SLen Brown  * DESCRIPTION: returns owner_id for the ACPI table
78395b482a8SLen Brown  *
78495b482a8SLen Brown  ******************************************************************************/
78595b482a8SLen Brown 
78695b482a8SLen Brown acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id * owner_id)
78795b482a8SLen Brown {
78895b482a8SLen Brown 	acpi_status status = AE_BAD_PARAMETER;
78995b482a8SLen Brown 
79095b482a8SLen Brown 	ACPI_FUNCTION_TRACE(tb_get_owner_id);
79195b482a8SLen Brown 
79295b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
793b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
79495b482a8SLen Brown 		*owner_id =
79595b482a8SLen Brown 		    acpi_gbl_root_table_list.tables[table_index].owner_id;
79695b482a8SLen Brown 		status = AE_OK;
79795b482a8SLen Brown 	}
79895b482a8SLen Brown 
79995b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
80095b482a8SLen Brown 	return_ACPI_STATUS(status);
80195b482a8SLen Brown }
80295b482a8SLen Brown 
80395b482a8SLen Brown /*******************************************************************************
80495b482a8SLen Brown  *
80595b482a8SLen Brown  * FUNCTION:    acpi_tb_is_table_loaded
80695b482a8SLen Brown  *
80795b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
80895b482a8SLen Brown  *
80995b482a8SLen Brown  * RETURN:      Table Loaded Flag
81095b482a8SLen Brown  *
81195b482a8SLen Brown  ******************************************************************************/
81295b482a8SLen Brown 
81395b482a8SLen Brown u8 acpi_tb_is_table_loaded(u32 table_index)
81495b482a8SLen Brown {
81595b482a8SLen Brown 	u8 is_loaded = FALSE;
81695b482a8SLen Brown 
81795b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
818b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
81995b482a8SLen Brown 		is_loaded = (u8)
820ec41f193SBob Moore 		    (acpi_gbl_root_table_list.tables[table_index].flags &
821ec41f193SBob Moore 		     ACPI_TABLE_IS_LOADED);
82295b482a8SLen Brown 	}
82395b482a8SLen Brown 
82495b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
82595b482a8SLen Brown 	return (is_loaded);
82695b482a8SLen Brown }
82795b482a8SLen Brown 
82895b482a8SLen Brown /*******************************************************************************
82995b482a8SLen Brown  *
83095b482a8SLen Brown  * FUNCTION:    acpi_tb_set_table_loaded_flag
83195b482a8SLen Brown  *
83295b482a8SLen Brown  * PARAMETERS:  table_index         - Table index
83395b482a8SLen Brown  *              is_loaded           - TRUE if table is loaded, FALSE otherwise
83495b482a8SLen Brown  *
83595b482a8SLen Brown  * RETURN:      None
83695b482a8SLen Brown  *
83795b482a8SLen Brown  * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
83895b482a8SLen Brown  *
83995b482a8SLen Brown  ******************************************************************************/
84095b482a8SLen Brown 
84195b482a8SLen Brown void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded)
84295b482a8SLen Brown {
84395b482a8SLen Brown 
84495b482a8SLen Brown 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
845b9ee2043SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
84695b482a8SLen Brown 		if (is_loaded) {
84795b482a8SLen Brown 			acpi_gbl_root_table_list.tables[table_index].flags |=
84895b482a8SLen Brown 			    ACPI_TABLE_IS_LOADED;
84995b482a8SLen Brown 		} else {
85095b482a8SLen Brown 			acpi_gbl_root_table_list.tables[table_index].flags &=
85195b482a8SLen Brown 			    ~ACPI_TABLE_IS_LOADED;
85295b482a8SLen Brown 		}
85395b482a8SLen Brown 	}
85495b482a8SLen Brown 
85595b482a8SLen Brown 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
85695b482a8SLen Brown }
857