xref: /OK3568_Linux_fs/kernel/drivers/acpi/acpica/tbdata.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /******************************************************************************
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Module Name: tbdata - Table manager data structure functions
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Copyright (C) 2000 - 2020, Intel Corp.
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  *****************************************************************************/
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <acpi/acpi.h>
11*4882a593Smuzhiyun #include "accommon.h"
12*4882a593Smuzhiyun #include "acnamesp.h"
13*4882a593Smuzhiyun #include "actables.h"
14*4882a593Smuzhiyun #include "acevents.h"
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #define _COMPONENT          ACPI_TABLES
17*4882a593Smuzhiyun ACPI_MODULE_NAME("tbdata")
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /* Local prototypes */
20*4882a593Smuzhiyun static acpi_status
21*4882a593Smuzhiyun acpi_tb_check_duplication(struct acpi_table_desc *table_desc, u32 *table_index);
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun static u8
24*4882a593Smuzhiyun acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index);
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun /*******************************************************************************
27*4882a593Smuzhiyun  *
28*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_compare_tables
29*4882a593Smuzhiyun  *
30*4882a593Smuzhiyun  * PARAMETERS:  table_desc          - Table 1 descriptor to be compared
31*4882a593Smuzhiyun  *              table_index         - Index of table 2 to be compared
32*4882a593Smuzhiyun  *
33*4882a593Smuzhiyun  * RETURN:      TRUE if both tables are identical.
34*4882a593Smuzhiyun  *
35*4882a593Smuzhiyun  * DESCRIPTION: This function compares a table with another table that has
36*4882a593Smuzhiyun  *              already been installed in the root table list.
37*4882a593Smuzhiyun  *
38*4882a593Smuzhiyun  ******************************************************************************/
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun static u8
acpi_tb_compare_tables(struct acpi_table_desc * table_desc,u32 table_index)41*4882a593Smuzhiyun acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun 	acpi_status status = AE_OK;
44*4882a593Smuzhiyun 	u8 is_identical;
45*4882a593Smuzhiyun 	struct acpi_table_header *table;
46*4882a593Smuzhiyun 	u32 table_length;
47*4882a593Smuzhiyun 	u8 table_flags;
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	status =
50*4882a593Smuzhiyun 	    acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index],
51*4882a593Smuzhiyun 				  &table, &table_length, &table_flags);
52*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
53*4882a593Smuzhiyun 		return (FALSE);
54*4882a593Smuzhiyun 	}
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	/*
57*4882a593Smuzhiyun 	 * Check for a table match on the entire table length,
58*4882a593Smuzhiyun 	 * not just the header.
59*4882a593Smuzhiyun 	 */
60*4882a593Smuzhiyun 	is_identical = (u8)((table_desc->length != table_length ||
61*4882a593Smuzhiyun 			     memcmp(table_desc->pointer, table, table_length)) ?
62*4882a593Smuzhiyun 			    FALSE : TRUE);
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	/* Release the acquired table */
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	acpi_tb_release_table(table, table_length, table_flags);
67*4882a593Smuzhiyun 	return (is_identical);
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun /*******************************************************************************
71*4882a593Smuzhiyun  *
72*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_init_table_descriptor
73*4882a593Smuzhiyun  *
74*4882a593Smuzhiyun  * PARAMETERS:  table_desc              - Table descriptor
75*4882a593Smuzhiyun  *              address                 - Physical address of the table
76*4882a593Smuzhiyun  *              flags                   - Allocation flags of the table
77*4882a593Smuzhiyun  *              table                   - Pointer to the table
78*4882a593Smuzhiyun  *
79*4882a593Smuzhiyun  * RETURN:      None
80*4882a593Smuzhiyun  *
81*4882a593Smuzhiyun  * DESCRIPTION: Initialize a new table descriptor
82*4882a593Smuzhiyun  *
83*4882a593Smuzhiyun  ******************************************************************************/
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun void
acpi_tb_init_table_descriptor(struct acpi_table_desc * table_desc,acpi_physical_address address,u8 flags,struct acpi_table_header * table)86*4882a593Smuzhiyun acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc,
87*4882a593Smuzhiyun 			      acpi_physical_address address,
88*4882a593Smuzhiyun 			      u8 flags, struct acpi_table_header *table)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	/*
92*4882a593Smuzhiyun 	 * Initialize the table descriptor. Set the pointer to NULL, since the
93*4882a593Smuzhiyun 	 * table is not fully mapped at this time.
94*4882a593Smuzhiyun 	 */
95*4882a593Smuzhiyun 	memset(table_desc, 0, sizeof(struct acpi_table_desc));
96*4882a593Smuzhiyun 	table_desc->address = address;
97*4882a593Smuzhiyun 	table_desc->length = table->length;
98*4882a593Smuzhiyun 	table_desc->flags = flags;
99*4882a593Smuzhiyun 	ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature);
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun /*******************************************************************************
103*4882a593Smuzhiyun  *
104*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_acquire_table
105*4882a593Smuzhiyun  *
106*4882a593Smuzhiyun  * PARAMETERS:  table_desc          - Table descriptor
107*4882a593Smuzhiyun  *              table_ptr           - Where table is returned
108*4882a593Smuzhiyun  *              table_length        - Where table length is returned
109*4882a593Smuzhiyun  *              table_flags         - Where table allocation flags are returned
110*4882a593Smuzhiyun  *
111*4882a593Smuzhiyun  * RETURN:      Status
112*4882a593Smuzhiyun  *
113*4882a593Smuzhiyun  * DESCRIPTION: Acquire an ACPI table. It can be used for tables not
114*4882a593Smuzhiyun  *              maintained in the acpi_gbl_root_table_list.
115*4882a593Smuzhiyun  *
116*4882a593Smuzhiyun  ******************************************************************************/
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun acpi_status
acpi_tb_acquire_table(struct acpi_table_desc * table_desc,struct acpi_table_header ** table_ptr,u32 * table_length,u8 * table_flags)119*4882a593Smuzhiyun acpi_tb_acquire_table(struct acpi_table_desc *table_desc,
120*4882a593Smuzhiyun 		      struct acpi_table_header **table_ptr,
121*4882a593Smuzhiyun 		      u32 *table_length, u8 *table_flags)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun 	struct acpi_table_header *table = NULL;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
126*4882a593Smuzhiyun 	case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 		table =
129*4882a593Smuzhiyun 		    acpi_os_map_memory(table_desc->address, table_desc->length);
130*4882a593Smuzhiyun 		break;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
133*4882a593Smuzhiyun 	case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 		table = ACPI_CAST_PTR(struct acpi_table_header,
136*4882a593Smuzhiyun 				      ACPI_PHYSADDR_TO_PTR(table_desc->
137*4882a593Smuzhiyun 							   address));
138*4882a593Smuzhiyun 		break;
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	default:
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 		break;
143*4882a593Smuzhiyun 	}
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	/* Table is not valid yet */
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	if (!table) {
148*4882a593Smuzhiyun 		return (AE_NO_MEMORY);
149*4882a593Smuzhiyun 	}
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	/* Fill the return values */
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	*table_ptr = table;
154*4882a593Smuzhiyun 	*table_length = table_desc->length;
155*4882a593Smuzhiyun 	*table_flags = table_desc->flags;
156*4882a593Smuzhiyun 	return (AE_OK);
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun /*******************************************************************************
160*4882a593Smuzhiyun  *
161*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_release_table
162*4882a593Smuzhiyun  *
163*4882a593Smuzhiyun  * PARAMETERS:  table               - Pointer for the table
164*4882a593Smuzhiyun  *              table_length        - Length for the table
165*4882a593Smuzhiyun  *              table_flags         - Allocation flags for the table
166*4882a593Smuzhiyun  *
167*4882a593Smuzhiyun  * RETURN:      None
168*4882a593Smuzhiyun  *
169*4882a593Smuzhiyun  * DESCRIPTION: Release a table. The inverse of acpi_tb_acquire_table().
170*4882a593Smuzhiyun  *
171*4882a593Smuzhiyun  ******************************************************************************/
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun void
acpi_tb_release_table(struct acpi_table_header * table,u32 table_length,u8 table_flags)174*4882a593Smuzhiyun acpi_tb_release_table(struct acpi_table_header *table,
175*4882a593Smuzhiyun 		      u32 table_length, u8 table_flags)
176*4882a593Smuzhiyun {
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	switch (table_flags & ACPI_TABLE_ORIGIN_MASK) {
179*4882a593Smuzhiyun 	case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 		acpi_os_unmap_memory(table, table_length);
182*4882a593Smuzhiyun 		break;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
185*4882a593Smuzhiyun 	case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
186*4882a593Smuzhiyun 	default:
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 		break;
189*4882a593Smuzhiyun 	}
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun /*******************************************************************************
193*4882a593Smuzhiyun  *
194*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_acquire_temp_table
195*4882a593Smuzhiyun  *
196*4882a593Smuzhiyun  * PARAMETERS:  table_desc          - Table descriptor to be acquired
197*4882a593Smuzhiyun  *              address             - Address of the table
198*4882a593Smuzhiyun  *              flags               - Allocation flags of the table
199*4882a593Smuzhiyun  *
200*4882a593Smuzhiyun  * RETURN:      Status
201*4882a593Smuzhiyun  *
202*4882a593Smuzhiyun  * DESCRIPTION: This function validates the table header to obtain the length
203*4882a593Smuzhiyun  *              of a table and fills the table descriptor to make its state as
204*4882a593Smuzhiyun  *              "INSTALLED". Such a table descriptor is only used for verified
205*4882a593Smuzhiyun  *              installation.
206*4882a593Smuzhiyun  *
207*4882a593Smuzhiyun  ******************************************************************************/
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun acpi_status
acpi_tb_acquire_temp_table(struct acpi_table_desc * table_desc,acpi_physical_address address,u8 flags)210*4882a593Smuzhiyun acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc,
211*4882a593Smuzhiyun 			   acpi_physical_address address, u8 flags)
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun 	struct acpi_table_header *table_header;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	switch (flags & ACPI_TABLE_ORIGIN_MASK) {
216*4882a593Smuzhiyun 	case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 		/* Get the length of the full table from the header */
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 		table_header =
221*4882a593Smuzhiyun 		    acpi_os_map_memory(address,
222*4882a593Smuzhiyun 				       sizeof(struct acpi_table_header));
223*4882a593Smuzhiyun 		if (!table_header) {
224*4882a593Smuzhiyun 			return (AE_NO_MEMORY);
225*4882a593Smuzhiyun 		}
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 		acpi_tb_init_table_descriptor(table_desc, address, flags,
228*4882a593Smuzhiyun 					      table_header);
229*4882a593Smuzhiyun 		acpi_os_unmap_memory(table_header,
230*4882a593Smuzhiyun 				     sizeof(struct acpi_table_header));
231*4882a593Smuzhiyun 		return (AE_OK);
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
234*4882a593Smuzhiyun 	case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 		table_header = ACPI_CAST_PTR(struct acpi_table_header,
237*4882a593Smuzhiyun 					     ACPI_PHYSADDR_TO_PTR(address));
238*4882a593Smuzhiyun 		if (!table_header) {
239*4882a593Smuzhiyun 			return (AE_NO_MEMORY);
240*4882a593Smuzhiyun 		}
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 		acpi_tb_init_table_descriptor(table_desc, address, flags,
243*4882a593Smuzhiyun 					      table_header);
244*4882a593Smuzhiyun 		return (AE_OK);
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	default:
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 		break;
249*4882a593Smuzhiyun 	}
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	/* Table is not valid yet */
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	return (AE_NO_MEMORY);
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun /*******************************************************************************
257*4882a593Smuzhiyun  *
258*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_release_temp_table
259*4882a593Smuzhiyun  *
260*4882a593Smuzhiyun  * PARAMETERS:  table_desc          - Table descriptor to be released
261*4882a593Smuzhiyun  *
262*4882a593Smuzhiyun  * RETURN:      Status
263*4882a593Smuzhiyun  *
264*4882a593Smuzhiyun  * DESCRIPTION: The inverse of acpi_tb_acquire_temp_table().
265*4882a593Smuzhiyun  *
266*4882a593Smuzhiyun  *****************************************************************************/
267*4882a593Smuzhiyun 
acpi_tb_release_temp_table(struct acpi_table_desc * table_desc)268*4882a593Smuzhiyun void acpi_tb_release_temp_table(struct acpi_table_desc *table_desc)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	/*
272*4882a593Smuzhiyun 	 * Note that the .Address is maintained by the callers of
273*4882a593Smuzhiyun 	 * acpi_tb_acquire_temp_table(), thus do not invoke acpi_tb_uninstall_table()
274*4882a593Smuzhiyun 	 * where .Address will be freed.
275*4882a593Smuzhiyun 	 */
276*4882a593Smuzhiyun 	acpi_tb_invalidate_table(table_desc);
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun /******************************************************************************
280*4882a593Smuzhiyun  *
281*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_validate_table
282*4882a593Smuzhiyun  *
283*4882a593Smuzhiyun  * PARAMETERS:  table_desc          - Table descriptor
284*4882a593Smuzhiyun  *
285*4882a593Smuzhiyun  * RETURN:      Status
286*4882a593Smuzhiyun  *
287*4882a593Smuzhiyun  * DESCRIPTION: This function is called to validate the table, the returned
288*4882a593Smuzhiyun  *              table descriptor is in "VALIDATED" state.
289*4882a593Smuzhiyun  *
290*4882a593Smuzhiyun  *****************************************************************************/
291*4882a593Smuzhiyun 
acpi_tb_validate_table(struct acpi_table_desc * table_desc)292*4882a593Smuzhiyun acpi_status acpi_tb_validate_table(struct acpi_table_desc *table_desc)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun 	acpi_status status = AE_OK;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(tb_validate_table);
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	/* Validate the table if necessary */
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	if (!table_desc->pointer) {
301*4882a593Smuzhiyun 		status = acpi_tb_acquire_table(table_desc, &table_desc->pointer,
302*4882a593Smuzhiyun 					       &table_desc->length,
303*4882a593Smuzhiyun 					       &table_desc->flags);
304*4882a593Smuzhiyun 		if (!table_desc->pointer) {
305*4882a593Smuzhiyun 			status = AE_NO_MEMORY;
306*4882a593Smuzhiyun 		}
307*4882a593Smuzhiyun 	}
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun /*******************************************************************************
313*4882a593Smuzhiyun  *
314*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_invalidate_table
315*4882a593Smuzhiyun  *
316*4882a593Smuzhiyun  * PARAMETERS:  table_desc          - Table descriptor
317*4882a593Smuzhiyun  *
318*4882a593Smuzhiyun  * RETURN:      None
319*4882a593Smuzhiyun  *
320*4882a593Smuzhiyun  * DESCRIPTION: Invalidate one internal ACPI table, this is the inverse of
321*4882a593Smuzhiyun  *              acpi_tb_validate_table().
322*4882a593Smuzhiyun  *
323*4882a593Smuzhiyun  ******************************************************************************/
324*4882a593Smuzhiyun 
acpi_tb_invalidate_table(struct acpi_table_desc * table_desc)325*4882a593Smuzhiyun void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(tb_invalidate_table);
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	/* Table must be validated */
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	if (!table_desc->pointer) {
333*4882a593Smuzhiyun 		return_VOID;
334*4882a593Smuzhiyun 	}
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	acpi_tb_release_table(table_desc->pointer, table_desc->length,
337*4882a593Smuzhiyun 			      table_desc->flags);
338*4882a593Smuzhiyun 	table_desc->pointer = NULL;
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	return_VOID;
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun /******************************************************************************
344*4882a593Smuzhiyun  *
345*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_validate_temp_table
346*4882a593Smuzhiyun  *
347*4882a593Smuzhiyun  * PARAMETERS:  table_desc          - Table descriptor
348*4882a593Smuzhiyun  *
349*4882a593Smuzhiyun  * RETURN:      Status
350*4882a593Smuzhiyun  *
351*4882a593Smuzhiyun  * DESCRIPTION: This function is called to validate the table, the returned
352*4882a593Smuzhiyun  *              table descriptor is in "VALIDATED" state.
353*4882a593Smuzhiyun  *
354*4882a593Smuzhiyun  *****************************************************************************/
355*4882a593Smuzhiyun 
acpi_tb_validate_temp_table(struct acpi_table_desc * table_desc)356*4882a593Smuzhiyun acpi_status acpi_tb_validate_temp_table(struct acpi_table_desc *table_desc)
357*4882a593Smuzhiyun {
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	if (!table_desc->pointer && !acpi_gbl_enable_table_validation) {
360*4882a593Smuzhiyun 		/*
361*4882a593Smuzhiyun 		 * Only validates the header of the table.
362*4882a593Smuzhiyun 		 * Note that Length contains the size of the mapping after invoking
363*4882a593Smuzhiyun 		 * this work around, this value is required by
364*4882a593Smuzhiyun 		 * acpi_tb_release_temp_table().
365*4882a593Smuzhiyun 		 * We can do this because in acpi_init_table_descriptor(), the Length
366*4882a593Smuzhiyun 		 * field of the installed descriptor is filled with the actual
367*4882a593Smuzhiyun 		 * table length obtaining from the table header.
368*4882a593Smuzhiyun 		 */
369*4882a593Smuzhiyun 		table_desc->length = sizeof(struct acpi_table_header);
370*4882a593Smuzhiyun 	}
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	return (acpi_tb_validate_table(table_desc));
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun /*******************************************************************************
376*4882a593Smuzhiyun  *
377*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_check_duplication
378*4882a593Smuzhiyun  *
379*4882a593Smuzhiyun  * PARAMETERS:  table_desc          - Table descriptor
380*4882a593Smuzhiyun  *              table_index         - Where the table index is returned
381*4882a593Smuzhiyun  *
382*4882a593Smuzhiyun  * RETURN:      Status
383*4882a593Smuzhiyun  *
384*4882a593Smuzhiyun  * DESCRIPTION: Avoid installing duplicated tables. However table override and
385*4882a593Smuzhiyun  *              user aided dynamic table load is allowed, thus comparing the
386*4882a593Smuzhiyun  *              address of the table is not sufficient, and checking the entire
387*4882a593Smuzhiyun  *              table content is required.
388*4882a593Smuzhiyun  *
389*4882a593Smuzhiyun  ******************************************************************************/
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun static acpi_status
acpi_tb_check_duplication(struct acpi_table_desc * table_desc,u32 * table_index)392*4882a593Smuzhiyun acpi_tb_check_duplication(struct acpi_table_desc *table_desc, u32 *table_index)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun 	u32 i;
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(tb_check_duplication);
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	/* Check if table is already registered */
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 		/* Do not compare with unverified tables */
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 		if (!
405*4882a593Smuzhiyun 		    (acpi_gbl_root_table_list.tables[i].
406*4882a593Smuzhiyun 		     flags & ACPI_TABLE_IS_VERIFIED)) {
407*4882a593Smuzhiyun 			continue;
408*4882a593Smuzhiyun 		}
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 		/*
411*4882a593Smuzhiyun 		 * Check for a table match on the entire table length,
412*4882a593Smuzhiyun 		 * not just the header.
413*4882a593Smuzhiyun 		 */
414*4882a593Smuzhiyun 		if (!acpi_tb_compare_tables(table_desc, i)) {
415*4882a593Smuzhiyun 			continue;
416*4882a593Smuzhiyun 		}
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 		/*
419*4882a593Smuzhiyun 		 * Note: the current mechanism does not unregister a table if it is
420*4882a593Smuzhiyun 		 * dynamically unloaded. The related namespace entries are deleted,
421*4882a593Smuzhiyun 		 * but the table remains in the root table list.
422*4882a593Smuzhiyun 		 *
423*4882a593Smuzhiyun 		 * The assumption here is that the number of different tables that
424*4882a593Smuzhiyun 		 * will be loaded is actually small, and there is minimal overhead
425*4882a593Smuzhiyun 		 * in just keeping the table in case it is needed again.
426*4882a593Smuzhiyun 		 *
427*4882a593Smuzhiyun 		 * If this assumption changes in the future (perhaps on large
428*4882a593Smuzhiyun 		 * machines with many table load/unload operations), tables will
429*4882a593Smuzhiyun 		 * need to be unregistered when they are unloaded, and slots in the
430*4882a593Smuzhiyun 		 * root table list should be reused when empty.
431*4882a593Smuzhiyun 		 */
432*4882a593Smuzhiyun 		if (acpi_gbl_root_table_list.tables[i].flags &
433*4882a593Smuzhiyun 		    ACPI_TABLE_IS_LOADED) {
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 			/* Table is still loaded, this is an error */
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 			return_ACPI_STATUS(AE_ALREADY_EXISTS);
438*4882a593Smuzhiyun 		} else {
439*4882a593Smuzhiyun 			*table_index = i;
440*4882a593Smuzhiyun 			return_ACPI_STATUS(AE_CTRL_TERMINATE);
441*4882a593Smuzhiyun 		}
442*4882a593Smuzhiyun 	}
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	/* Indicate no duplication to the caller */
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun /******************************************************************************
450*4882a593Smuzhiyun  *
451*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_verify_temp_table
452*4882a593Smuzhiyun  *
453*4882a593Smuzhiyun  * PARAMETERS:  table_desc          - Table descriptor
454*4882a593Smuzhiyun  *              signature           - Table signature to verify
455*4882a593Smuzhiyun  *              table_index         - Where the table index is returned
456*4882a593Smuzhiyun  *
457*4882a593Smuzhiyun  * RETURN:      Status
458*4882a593Smuzhiyun  *
459*4882a593Smuzhiyun  * DESCRIPTION: This function is called to validate and verify the table, the
460*4882a593Smuzhiyun  *              returned table descriptor is in "VALIDATED" state.
461*4882a593Smuzhiyun  *              Note that 'TableIndex' is required to be set to !NULL to
462*4882a593Smuzhiyun  *              enable duplication check.
463*4882a593Smuzhiyun  *
464*4882a593Smuzhiyun  *****************************************************************************/
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun acpi_status
acpi_tb_verify_temp_table(struct acpi_table_desc * table_desc,char * signature,u32 * table_index)467*4882a593Smuzhiyun acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc,
468*4882a593Smuzhiyun 			  char *signature, u32 *table_index)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun 	acpi_status status = AE_OK;
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(tb_verify_temp_table);
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun 	/* Validate the table */
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	status = acpi_tb_validate_temp_table(table_desc);
477*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
478*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_NO_MEMORY);
479*4882a593Smuzhiyun 	}
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	/* If a particular signature is expected (DSDT/FACS), it must match */
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	if (signature &&
484*4882a593Smuzhiyun 	    !ACPI_COMPARE_NAMESEG(&table_desc->signature, signature)) {
485*4882a593Smuzhiyun 		ACPI_BIOS_ERROR((AE_INFO,
486*4882a593Smuzhiyun 				 "Invalid signature 0x%X for ACPI table, expected [%s]",
487*4882a593Smuzhiyun 				 table_desc->signature.integer, signature));
488*4882a593Smuzhiyun 		status = AE_BAD_SIGNATURE;
489*4882a593Smuzhiyun 		goto invalidate_and_exit;
490*4882a593Smuzhiyun 	}
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 	if (acpi_gbl_enable_table_validation) {
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 		/* Verify the checksum */
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 		status =
497*4882a593Smuzhiyun 		    acpi_tb_verify_checksum(table_desc->pointer,
498*4882a593Smuzhiyun 					    table_desc->length);
499*4882a593Smuzhiyun 		if (ACPI_FAILURE(status)) {
500*4882a593Smuzhiyun 			ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
501*4882a593Smuzhiyun 					"%4.4s 0x%8.8X%8.8X"
502*4882a593Smuzhiyun 					" Attempted table install failed",
503*4882a593Smuzhiyun 					acpi_ut_valid_nameseg(table_desc->
504*4882a593Smuzhiyun 							      signature.
505*4882a593Smuzhiyun 							      ascii) ?
506*4882a593Smuzhiyun 					table_desc->signature.ascii : "????",
507*4882a593Smuzhiyun 					ACPI_FORMAT_UINT64(table_desc->
508*4882a593Smuzhiyun 							   address)));
509*4882a593Smuzhiyun 
510*4882a593Smuzhiyun 			goto invalidate_and_exit;
511*4882a593Smuzhiyun 		}
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 		/* Avoid duplications */
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 		if (table_index) {
516*4882a593Smuzhiyun 			status =
517*4882a593Smuzhiyun 			    acpi_tb_check_duplication(table_desc, table_index);
518*4882a593Smuzhiyun 			if (ACPI_FAILURE(status)) {
519*4882a593Smuzhiyun 				if (status != AE_CTRL_TERMINATE) {
520*4882a593Smuzhiyun 					ACPI_EXCEPTION((AE_INFO, status,
521*4882a593Smuzhiyun 							"%4.4s 0x%8.8X%8.8X"
522*4882a593Smuzhiyun 							" Table is already loaded",
523*4882a593Smuzhiyun 							acpi_ut_valid_nameseg
524*4882a593Smuzhiyun 							(table_desc->signature.
525*4882a593Smuzhiyun 							 ascii) ? table_desc->
526*4882a593Smuzhiyun 							signature.
527*4882a593Smuzhiyun 							ascii : "????",
528*4882a593Smuzhiyun 							ACPI_FORMAT_UINT64
529*4882a593Smuzhiyun 							(table_desc->address)));
530*4882a593Smuzhiyun 				}
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 				goto invalidate_and_exit;
533*4882a593Smuzhiyun 			}
534*4882a593Smuzhiyun 		}
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 		table_desc->flags |= ACPI_TABLE_IS_VERIFIED;
537*4882a593Smuzhiyun 	}
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun invalidate_and_exit:
542*4882a593Smuzhiyun 	acpi_tb_invalidate_table(table_desc);
543*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun /*******************************************************************************
547*4882a593Smuzhiyun  *
548*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_resize_root_table_list
549*4882a593Smuzhiyun  *
550*4882a593Smuzhiyun  * PARAMETERS:  None
551*4882a593Smuzhiyun  *
552*4882a593Smuzhiyun  * RETURN:      Status
553*4882a593Smuzhiyun  *
554*4882a593Smuzhiyun  * DESCRIPTION: Expand the size of global table array
555*4882a593Smuzhiyun  *
556*4882a593Smuzhiyun  ******************************************************************************/
557*4882a593Smuzhiyun 
acpi_tb_resize_root_table_list(void)558*4882a593Smuzhiyun acpi_status acpi_tb_resize_root_table_list(void)
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun 	struct acpi_table_desc *tables;
561*4882a593Smuzhiyun 	u32 table_count;
562*4882a593Smuzhiyun 	u32 current_table_count, max_table_count;
563*4882a593Smuzhiyun 	u32 i;
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	/* allow_resize flag is a parameter to acpi_initialize_tables */
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun 	if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) {
570*4882a593Smuzhiyun 		ACPI_ERROR((AE_INFO,
571*4882a593Smuzhiyun 			    "Resize of Root Table Array is not allowed"));
572*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_SUPPORT);
573*4882a593Smuzhiyun 	}
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun 	/* Increase the Table Array size */
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun 	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
578*4882a593Smuzhiyun 		table_count = acpi_gbl_root_table_list.max_table_count;
579*4882a593Smuzhiyun 	} else {
580*4882a593Smuzhiyun 		table_count = acpi_gbl_root_table_list.current_table_count;
581*4882a593Smuzhiyun 	}
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 	max_table_count = table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT;
584*4882a593Smuzhiyun 	tables = ACPI_ALLOCATE_ZEROED(((acpi_size)max_table_count) *
585*4882a593Smuzhiyun 				      sizeof(struct acpi_table_desc));
586*4882a593Smuzhiyun 	if (!tables) {
587*4882a593Smuzhiyun 		ACPI_ERROR((AE_INFO,
588*4882a593Smuzhiyun 			    "Could not allocate new root table array"));
589*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_NO_MEMORY);
590*4882a593Smuzhiyun 	}
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun 	/* Copy and free the previous table array */
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun 	current_table_count = 0;
595*4882a593Smuzhiyun 	if (acpi_gbl_root_table_list.tables) {
596*4882a593Smuzhiyun 		for (i = 0; i < table_count; i++) {
597*4882a593Smuzhiyun 			if (acpi_gbl_root_table_list.tables[i].address) {
598*4882a593Smuzhiyun 				memcpy(tables + current_table_count,
599*4882a593Smuzhiyun 				       acpi_gbl_root_table_list.tables + i,
600*4882a593Smuzhiyun 				       sizeof(struct acpi_table_desc));
601*4882a593Smuzhiyun 				current_table_count++;
602*4882a593Smuzhiyun 			}
603*4882a593Smuzhiyun 		}
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun 		if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
606*4882a593Smuzhiyun 			ACPI_FREE(acpi_gbl_root_table_list.tables);
607*4882a593Smuzhiyun 		}
608*4882a593Smuzhiyun 	}
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun 	acpi_gbl_root_table_list.tables = tables;
611*4882a593Smuzhiyun 	acpi_gbl_root_table_list.max_table_count = max_table_count;
612*4882a593Smuzhiyun 	acpi_gbl_root_table_list.current_table_count = current_table_count;
613*4882a593Smuzhiyun 	acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
616*4882a593Smuzhiyun }
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun /*******************************************************************************
619*4882a593Smuzhiyun  *
620*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_get_next_table_descriptor
621*4882a593Smuzhiyun  *
622*4882a593Smuzhiyun  * PARAMETERS:  table_index         - Where table index is returned
623*4882a593Smuzhiyun  *              table_desc          - Where table descriptor is returned
624*4882a593Smuzhiyun  *
625*4882a593Smuzhiyun  * RETURN:      Status and table index/descriptor.
626*4882a593Smuzhiyun  *
627*4882a593Smuzhiyun  * DESCRIPTION: Allocate a new ACPI table entry to the global table list
628*4882a593Smuzhiyun  *
629*4882a593Smuzhiyun  ******************************************************************************/
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun acpi_status
acpi_tb_get_next_table_descriptor(u32 * table_index,struct acpi_table_desc ** table_desc)632*4882a593Smuzhiyun acpi_tb_get_next_table_descriptor(u32 *table_index,
633*4882a593Smuzhiyun 				  struct acpi_table_desc **table_desc)
634*4882a593Smuzhiyun {
635*4882a593Smuzhiyun 	acpi_status status;
636*4882a593Smuzhiyun 	u32 i;
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 	/* Ensure that there is room for the table in the Root Table List */
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun 	if (acpi_gbl_root_table_list.current_table_count >=
641*4882a593Smuzhiyun 	    acpi_gbl_root_table_list.max_table_count) {
642*4882a593Smuzhiyun 		status = acpi_tb_resize_root_table_list();
643*4882a593Smuzhiyun 		if (ACPI_FAILURE(status)) {
644*4882a593Smuzhiyun 			return (status);
645*4882a593Smuzhiyun 		}
646*4882a593Smuzhiyun 	}
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 	i = acpi_gbl_root_table_list.current_table_count;
649*4882a593Smuzhiyun 	acpi_gbl_root_table_list.current_table_count++;
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun 	if (table_index) {
652*4882a593Smuzhiyun 		*table_index = i;
653*4882a593Smuzhiyun 	}
654*4882a593Smuzhiyun 	if (table_desc) {
655*4882a593Smuzhiyun 		*table_desc = &acpi_gbl_root_table_list.tables[i];
656*4882a593Smuzhiyun 	}
657*4882a593Smuzhiyun 
658*4882a593Smuzhiyun 	return (AE_OK);
659*4882a593Smuzhiyun }
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun /*******************************************************************************
662*4882a593Smuzhiyun  *
663*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_terminate
664*4882a593Smuzhiyun  *
665*4882a593Smuzhiyun  * PARAMETERS:  None
666*4882a593Smuzhiyun  *
667*4882a593Smuzhiyun  * RETURN:      None
668*4882a593Smuzhiyun  *
669*4882a593Smuzhiyun  * DESCRIPTION: Delete all internal ACPI tables
670*4882a593Smuzhiyun  *
671*4882a593Smuzhiyun  ******************************************************************************/
672*4882a593Smuzhiyun 
acpi_tb_terminate(void)673*4882a593Smuzhiyun void acpi_tb_terminate(void)
674*4882a593Smuzhiyun {
675*4882a593Smuzhiyun 	u32 i;
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(tb_terminate);
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
680*4882a593Smuzhiyun 
681*4882a593Smuzhiyun 	/* Delete the individual tables */
682*4882a593Smuzhiyun 
683*4882a593Smuzhiyun 	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
684*4882a593Smuzhiyun 		acpi_tb_uninstall_table(&acpi_gbl_root_table_list.tables[i]);
685*4882a593Smuzhiyun 	}
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun 	/*
688*4882a593Smuzhiyun 	 * Delete the root table array if allocated locally. Array cannot be
689*4882a593Smuzhiyun 	 * mapped, so we don't need to check for that flag.
690*4882a593Smuzhiyun 	 */
691*4882a593Smuzhiyun 	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
692*4882a593Smuzhiyun 		ACPI_FREE(acpi_gbl_root_table_list.tables);
693*4882a593Smuzhiyun 	}
694*4882a593Smuzhiyun 
695*4882a593Smuzhiyun 	acpi_gbl_root_table_list.tables = NULL;
696*4882a593Smuzhiyun 	acpi_gbl_root_table_list.flags = 0;
697*4882a593Smuzhiyun 	acpi_gbl_root_table_list.current_table_count = 0;
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
702*4882a593Smuzhiyun 	return_VOID;
703*4882a593Smuzhiyun }
704*4882a593Smuzhiyun 
705*4882a593Smuzhiyun /*******************************************************************************
706*4882a593Smuzhiyun  *
707*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_delete_namespace_by_owner
708*4882a593Smuzhiyun  *
709*4882a593Smuzhiyun  * PARAMETERS:  table_index         - Table index
710*4882a593Smuzhiyun  *
711*4882a593Smuzhiyun  * RETURN:      Status
712*4882a593Smuzhiyun  *
713*4882a593Smuzhiyun  * DESCRIPTION: Delete all namespace objects created when this table was loaded.
714*4882a593Smuzhiyun  *
715*4882a593Smuzhiyun  ******************************************************************************/
716*4882a593Smuzhiyun 
acpi_tb_delete_namespace_by_owner(u32 table_index)717*4882a593Smuzhiyun acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index)
718*4882a593Smuzhiyun {
719*4882a593Smuzhiyun 	acpi_owner_id owner_id;
720*4882a593Smuzhiyun 	acpi_status status;
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner);
723*4882a593Smuzhiyun 
724*4882a593Smuzhiyun 	status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
725*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
726*4882a593Smuzhiyun 		return_ACPI_STATUS(status);
727*4882a593Smuzhiyun 	}
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 	if (table_index >= acpi_gbl_root_table_list.current_table_count) {
730*4882a593Smuzhiyun 
731*4882a593Smuzhiyun 		/* The table index does not exist */
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun 		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
734*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_NOT_EXIST);
735*4882a593Smuzhiyun 	}
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun 	/* Get the owner ID for this table, used to delete namespace nodes */
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id;
740*4882a593Smuzhiyun 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 	/*
743*4882a593Smuzhiyun 	 * Need to acquire the namespace writer lock to prevent interference
744*4882a593Smuzhiyun 	 * with any concurrent namespace walks. The interpreter must be
745*4882a593Smuzhiyun 	 * released during the deletion since the acquisition of the deletion
746*4882a593Smuzhiyun 	 * lock may block, and also since the execution of a namespace walk
747*4882a593Smuzhiyun 	 * must be allowed to use the interpreter.
748*4882a593Smuzhiyun 	 */
749*4882a593Smuzhiyun 	status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock);
750*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
751*4882a593Smuzhiyun 		return_ACPI_STATUS(status);
752*4882a593Smuzhiyun 	}
753*4882a593Smuzhiyun 
754*4882a593Smuzhiyun 	acpi_ns_delete_namespace_by_owner(owner_id);
755*4882a593Smuzhiyun 	acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock);
756*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
757*4882a593Smuzhiyun }
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun /*******************************************************************************
760*4882a593Smuzhiyun  *
761*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_allocate_owner_id
762*4882a593Smuzhiyun  *
763*4882a593Smuzhiyun  * PARAMETERS:  table_index         - Table index
764*4882a593Smuzhiyun  *
765*4882a593Smuzhiyun  * RETURN:      Status
766*4882a593Smuzhiyun  *
767*4882a593Smuzhiyun  * DESCRIPTION: Allocates owner_id in table_desc
768*4882a593Smuzhiyun  *
769*4882a593Smuzhiyun  ******************************************************************************/
770*4882a593Smuzhiyun 
acpi_tb_allocate_owner_id(u32 table_index)771*4882a593Smuzhiyun acpi_status acpi_tb_allocate_owner_id(u32 table_index)
772*4882a593Smuzhiyun {
773*4882a593Smuzhiyun 	acpi_status status = AE_BAD_PARAMETER;
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
776*4882a593Smuzhiyun 
777*4882a593Smuzhiyun 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
778*4882a593Smuzhiyun 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
779*4882a593Smuzhiyun 		status =
780*4882a593Smuzhiyun 		    acpi_ut_allocate_owner_id(&
781*4882a593Smuzhiyun 					      (acpi_gbl_root_table_list.
782*4882a593Smuzhiyun 					       tables[table_index].owner_id));
783*4882a593Smuzhiyun 	}
784*4882a593Smuzhiyun 
785*4882a593Smuzhiyun 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
786*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
787*4882a593Smuzhiyun }
788*4882a593Smuzhiyun 
789*4882a593Smuzhiyun /*******************************************************************************
790*4882a593Smuzhiyun  *
791*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_release_owner_id
792*4882a593Smuzhiyun  *
793*4882a593Smuzhiyun  * PARAMETERS:  table_index         - Table index
794*4882a593Smuzhiyun  *
795*4882a593Smuzhiyun  * RETURN:      Status
796*4882a593Smuzhiyun  *
797*4882a593Smuzhiyun  * DESCRIPTION: Releases owner_id in table_desc
798*4882a593Smuzhiyun  *
799*4882a593Smuzhiyun  ******************************************************************************/
800*4882a593Smuzhiyun 
acpi_tb_release_owner_id(u32 table_index)801*4882a593Smuzhiyun acpi_status acpi_tb_release_owner_id(u32 table_index)
802*4882a593Smuzhiyun {
803*4882a593Smuzhiyun 	acpi_status status = AE_BAD_PARAMETER;
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(tb_release_owner_id);
806*4882a593Smuzhiyun 
807*4882a593Smuzhiyun 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
808*4882a593Smuzhiyun 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
809*4882a593Smuzhiyun 		acpi_ut_release_owner_id(&
810*4882a593Smuzhiyun 					 (acpi_gbl_root_table_list.
811*4882a593Smuzhiyun 					  tables[table_index].owner_id));
812*4882a593Smuzhiyun 		status = AE_OK;
813*4882a593Smuzhiyun 	}
814*4882a593Smuzhiyun 
815*4882a593Smuzhiyun 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
816*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
817*4882a593Smuzhiyun }
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun /*******************************************************************************
820*4882a593Smuzhiyun  *
821*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_get_owner_id
822*4882a593Smuzhiyun  *
823*4882a593Smuzhiyun  * PARAMETERS:  table_index         - Table index
824*4882a593Smuzhiyun  *              owner_id            - Where the table owner_id is returned
825*4882a593Smuzhiyun  *
826*4882a593Smuzhiyun  * RETURN:      Status
827*4882a593Smuzhiyun  *
828*4882a593Smuzhiyun  * DESCRIPTION: returns owner_id for the ACPI table
829*4882a593Smuzhiyun  *
830*4882a593Smuzhiyun  ******************************************************************************/
831*4882a593Smuzhiyun 
acpi_tb_get_owner_id(u32 table_index,acpi_owner_id * owner_id)832*4882a593Smuzhiyun acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id)
833*4882a593Smuzhiyun {
834*4882a593Smuzhiyun 	acpi_status status = AE_BAD_PARAMETER;
835*4882a593Smuzhiyun 
836*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(tb_get_owner_id);
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
839*4882a593Smuzhiyun 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
840*4882a593Smuzhiyun 		*owner_id =
841*4882a593Smuzhiyun 		    acpi_gbl_root_table_list.tables[table_index].owner_id;
842*4882a593Smuzhiyun 		status = AE_OK;
843*4882a593Smuzhiyun 	}
844*4882a593Smuzhiyun 
845*4882a593Smuzhiyun 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
846*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
847*4882a593Smuzhiyun }
848*4882a593Smuzhiyun 
849*4882a593Smuzhiyun /*******************************************************************************
850*4882a593Smuzhiyun  *
851*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_is_table_loaded
852*4882a593Smuzhiyun  *
853*4882a593Smuzhiyun  * PARAMETERS:  table_index         - Index into the root table
854*4882a593Smuzhiyun  *
855*4882a593Smuzhiyun  * RETURN:      Table Loaded Flag
856*4882a593Smuzhiyun  *
857*4882a593Smuzhiyun  ******************************************************************************/
858*4882a593Smuzhiyun 
acpi_tb_is_table_loaded(u32 table_index)859*4882a593Smuzhiyun u8 acpi_tb_is_table_loaded(u32 table_index)
860*4882a593Smuzhiyun {
861*4882a593Smuzhiyun 	u8 is_loaded = FALSE;
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
864*4882a593Smuzhiyun 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
865*4882a593Smuzhiyun 		is_loaded = (u8)
866*4882a593Smuzhiyun 		    (acpi_gbl_root_table_list.tables[table_index].flags &
867*4882a593Smuzhiyun 		     ACPI_TABLE_IS_LOADED);
868*4882a593Smuzhiyun 	}
869*4882a593Smuzhiyun 
870*4882a593Smuzhiyun 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
871*4882a593Smuzhiyun 	return (is_loaded);
872*4882a593Smuzhiyun }
873*4882a593Smuzhiyun 
874*4882a593Smuzhiyun /*******************************************************************************
875*4882a593Smuzhiyun  *
876*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_set_table_loaded_flag
877*4882a593Smuzhiyun  *
878*4882a593Smuzhiyun  * PARAMETERS:  table_index         - Table index
879*4882a593Smuzhiyun  *              is_loaded           - TRUE if table is loaded, FALSE otherwise
880*4882a593Smuzhiyun  *
881*4882a593Smuzhiyun  * RETURN:      None
882*4882a593Smuzhiyun  *
883*4882a593Smuzhiyun  * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
884*4882a593Smuzhiyun  *
885*4882a593Smuzhiyun  ******************************************************************************/
886*4882a593Smuzhiyun 
acpi_tb_set_table_loaded_flag(u32 table_index,u8 is_loaded)887*4882a593Smuzhiyun void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded)
888*4882a593Smuzhiyun {
889*4882a593Smuzhiyun 
890*4882a593Smuzhiyun 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
891*4882a593Smuzhiyun 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
892*4882a593Smuzhiyun 		if (is_loaded) {
893*4882a593Smuzhiyun 			acpi_gbl_root_table_list.tables[table_index].flags |=
894*4882a593Smuzhiyun 			    ACPI_TABLE_IS_LOADED;
895*4882a593Smuzhiyun 		} else {
896*4882a593Smuzhiyun 			acpi_gbl_root_table_list.tables[table_index].flags &=
897*4882a593Smuzhiyun 			    ~ACPI_TABLE_IS_LOADED;
898*4882a593Smuzhiyun 		}
899*4882a593Smuzhiyun 	}
900*4882a593Smuzhiyun 
901*4882a593Smuzhiyun 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
902*4882a593Smuzhiyun }
903*4882a593Smuzhiyun 
904*4882a593Smuzhiyun /*******************************************************************************
905*4882a593Smuzhiyun  *
906*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_load_table
907*4882a593Smuzhiyun  *
908*4882a593Smuzhiyun  * PARAMETERS:  table_index             - Table index
909*4882a593Smuzhiyun  *              parent_node             - Where table index is returned
910*4882a593Smuzhiyun  *
911*4882a593Smuzhiyun  * RETURN:      Status
912*4882a593Smuzhiyun  *
913*4882a593Smuzhiyun  * DESCRIPTION: Load an ACPI table
914*4882a593Smuzhiyun  *
915*4882a593Smuzhiyun  ******************************************************************************/
916*4882a593Smuzhiyun 
917*4882a593Smuzhiyun acpi_status
acpi_tb_load_table(u32 table_index,struct acpi_namespace_node * parent_node)918*4882a593Smuzhiyun acpi_tb_load_table(u32 table_index, struct acpi_namespace_node *parent_node)
919*4882a593Smuzhiyun {
920*4882a593Smuzhiyun 	struct acpi_table_header *table;
921*4882a593Smuzhiyun 	acpi_status status;
922*4882a593Smuzhiyun 	acpi_owner_id owner_id;
923*4882a593Smuzhiyun 
924*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(tb_load_table);
925*4882a593Smuzhiyun 
926*4882a593Smuzhiyun 	/*
927*4882a593Smuzhiyun 	 * Note: Now table is "INSTALLED", it must be validated before
928*4882a593Smuzhiyun 	 * using.
929*4882a593Smuzhiyun 	 */
930*4882a593Smuzhiyun 	status = acpi_get_table_by_index(table_index, &table);
931*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
932*4882a593Smuzhiyun 		return_ACPI_STATUS(status);
933*4882a593Smuzhiyun 	}
934*4882a593Smuzhiyun 
935*4882a593Smuzhiyun 	status = acpi_ns_load_table(table_index, parent_node);
936*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
937*4882a593Smuzhiyun 		return_ACPI_STATUS(status);
938*4882a593Smuzhiyun 	}
939*4882a593Smuzhiyun 
940*4882a593Smuzhiyun 	/*
941*4882a593Smuzhiyun 	 * Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is
942*4882a593Smuzhiyun 	 * responsible for discovering any new wake GPEs by running _PRW methods
943*4882a593Smuzhiyun 	 * that may have been loaded by this table.
944*4882a593Smuzhiyun 	 */
945*4882a593Smuzhiyun 	status = acpi_tb_get_owner_id(table_index, &owner_id);
946*4882a593Smuzhiyun 	if (ACPI_SUCCESS(status)) {
947*4882a593Smuzhiyun 		acpi_ev_update_gpes(owner_id);
948*4882a593Smuzhiyun 	}
949*4882a593Smuzhiyun 
950*4882a593Smuzhiyun 	/* Invoke table handler */
951*4882a593Smuzhiyun 
952*4882a593Smuzhiyun 	acpi_tb_notify_table(ACPI_TABLE_EVENT_LOAD, table);
953*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
954*4882a593Smuzhiyun }
955*4882a593Smuzhiyun 
956*4882a593Smuzhiyun /*******************************************************************************
957*4882a593Smuzhiyun  *
958*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_install_and_load_table
959*4882a593Smuzhiyun  *
960*4882a593Smuzhiyun  * PARAMETERS:  address                 - Physical address of the table
961*4882a593Smuzhiyun  *              flags                   - Allocation flags of the table
962*4882a593Smuzhiyun  *              override                - Whether override should be performed
963*4882a593Smuzhiyun  *              table_index             - Where table index is returned
964*4882a593Smuzhiyun  *
965*4882a593Smuzhiyun  * RETURN:      Status
966*4882a593Smuzhiyun  *
967*4882a593Smuzhiyun  * DESCRIPTION: Install and load an ACPI table
968*4882a593Smuzhiyun  *
969*4882a593Smuzhiyun  ******************************************************************************/
970*4882a593Smuzhiyun 
971*4882a593Smuzhiyun acpi_status
acpi_tb_install_and_load_table(acpi_physical_address address,u8 flags,u8 override,u32 * table_index)972*4882a593Smuzhiyun acpi_tb_install_and_load_table(acpi_physical_address address,
973*4882a593Smuzhiyun 			       u8 flags, u8 override, u32 *table_index)
974*4882a593Smuzhiyun {
975*4882a593Smuzhiyun 	acpi_status status;
976*4882a593Smuzhiyun 	u32 i;
977*4882a593Smuzhiyun 
978*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(tb_install_and_load_table);
979*4882a593Smuzhiyun 
980*4882a593Smuzhiyun 	/* Install the table and load it into the namespace */
981*4882a593Smuzhiyun 
982*4882a593Smuzhiyun 	status = acpi_tb_install_standard_table(address, flags, TRUE,
983*4882a593Smuzhiyun 						override, &i);
984*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
985*4882a593Smuzhiyun 		goto exit;
986*4882a593Smuzhiyun 	}
987*4882a593Smuzhiyun 
988*4882a593Smuzhiyun 	status = acpi_tb_load_table(i, acpi_gbl_root_node);
989*4882a593Smuzhiyun 
990*4882a593Smuzhiyun exit:
991*4882a593Smuzhiyun 	*table_index = i;
992*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
993*4882a593Smuzhiyun }
994*4882a593Smuzhiyun 
ACPI_EXPORT_SYMBOL(acpi_tb_install_and_load_table)995*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_tb_install_and_load_table)
996*4882a593Smuzhiyun 
997*4882a593Smuzhiyun /*******************************************************************************
998*4882a593Smuzhiyun  *
999*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_unload_table
1000*4882a593Smuzhiyun  *
1001*4882a593Smuzhiyun  * PARAMETERS:  table_index             - Table index
1002*4882a593Smuzhiyun  *
1003*4882a593Smuzhiyun  * RETURN:      Status
1004*4882a593Smuzhiyun  *
1005*4882a593Smuzhiyun  * DESCRIPTION: Unload an ACPI table
1006*4882a593Smuzhiyun  *
1007*4882a593Smuzhiyun  ******************************************************************************/
1008*4882a593Smuzhiyun 
1009*4882a593Smuzhiyun acpi_status acpi_tb_unload_table(u32 table_index)
1010*4882a593Smuzhiyun {
1011*4882a593Smuzhiyun 	acpi_status status = AE_OK;
1012*4882a593Smuzhiyun 	struct acpi_table_header *table;
1013*4882a593Smuzhiyun 
1014*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(tb_unload_table);
1015*4882a593Smuzhiyun 
1016*4882a593Smuzhiyun 	/* Ensure the table is still loaded */
1017*4882a593Smuzhiyun 
1018*4882a593Smuzhiyun 	if (!acpi_tb_is_table_loaded(table_index)) {
1019*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_NOT_EXIST);
1020*4882a593Smuzhiyun 	}
1021*4882a593Smuzhiyun 
1022*4882a593Smuzhiyun 	/* Invoke table handler */
1023*4882a593Smuzhiyun 
1024*4882a593Smuzhiyun 	status = acpi_get_table_by_index(table_index, &table);
1025*4882a593Smuzhiyun 	if (ACPI_SUCCESS(status)) {
1026*4882a593Smuzhiyun 		acpi_tb_notify_table(ACPI_TABLE_EVENT_UNLOAD, table);
1027*4882a593Smuzhiyun 	}
1028*4882a593Smuzhiyun 
1029*4882a593Smuzhiyun 	/* Delete the portion of the namespace owned by this table */
1030*4882a593Smuzhiyun 
1031*4882a593Smuzhiyun 	status = acpi_tb_delete_namespace_by_owner(table_index);
1032*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
1033*4882a593Smuzhiyun 		return_ACPI_STATUS(status);
1034*4882a593Smuzhiyun 	}
1035*4882a593Smuzhiyun 
1036*4882a593Smuzhiyun 	(void)acpi_tb_release_owner_id(table_index);
1037*4882a593Smuzhiyun 	acpi_tb_set_table_loaded_flag(table_index, FALSE);
1038*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
1039*4882a593Smuzhiyun }
1040*4882a593Smuzhiyun 
ACPI_EXPORT_SYMBOL(acpi_tb_unload_table)1041*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_tb_unload_table)
1042*4882a593Smuzhiyun 
1043*4882a593Smuzhiyun /*******************************************************************************
1044*4882a593Smuzhiyun  *
1045*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_notify_table
1046*4882a593Smuzhiyun  *
1047*4882a593Smuzhiyun  * PARAMETERS:  event               - Table event
1048*4882a593Smuzhiyun  *              table               - Validated table pointer
1049*4882a593Smuzhiyun  *
1050*4882a593Smuzhiyun  * RETURN:      None
1051*4882a593Smuzhiyun  *
1052*4882a593Smuzhiyun  * DESCRIPTION: Notify a table event to the users.
1053*4882a593Smuzhiyun  *
1054*4882a593Smuzhiyun  ******************************************************************************/
1055*4882a593Smuzhiyun 
1056*4882a593Smuzhiyun void acpi_tb_notify_table(u32 event, void *table)
1057*4882a593Smuzhiyun {
1058*4882a593Smuzhiyun 	/* Invoke table handler if present */
1059*4882a593Smuzhiyun 
1060*4882a593Smuzhiyun 	if (acpi_gbl_table_handler) {
1061*4882a593Smuzhiyun 		(void)acpi_gbl_table_handler(event, table,
1062*4882a593Smuzhiyun 					     acpi_gbl_table_handler_context);
1063*4882a593Smuzhiyun 	}
1064*4882a593Smuzhiyun }
1065