xref: /openbmc/linux/drivers/acpi/acpica/tbdata.c (revision 612c2932)
195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2c418ce19SBob Moore /******************************************************************************
3c418ce19SBob Moore  *
4c418ce19SBob Moore  * Module Name: tbdata - Table manager data structure functions
5c418ce19SBob Moore  *
6*612c2932SBob Moore  * Copyright (C) 2000 - 2023, Intel Corp.
7c418ce19SBob Moore  *
895857638SErik Schmauss  *****************************************************************************/
9c418ce19SBob Moore 
10c418ce19SBob Moore #include <acpi/acpi.h>
11c418ce19SBob Moore #include "accommon.h"
12c418ce19SBob Moore #include "acnamesp.h"
13c418ce19SBob Moore #include "actables.h"
14ac0f06ebSLv Zheng #include "acevents.h"
15c418ce19SBob Moore 
16c418ce19SBob Moore #define _COMPONENT          ACPI_TABLES
17c418ce19SBob Moore ACPI_MODULE_NAME("tbdata")
18c418ce19SBob Moore 
19f9d472eeSLv Zheng /* Local prototypes */
20f9d472eeSLv Zheng static acpi_status
21f9d472eeSLv Zheng acpi_tb_check_duplication(struct acpi_table_desc *table_desc, u32 *table_index);
22f9d472eeSLv Zheng 
23f9d472eeSLv Zheng static u8
24f9d472eeSLv Zheng acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index);
25f9d472eeSLv Zheng 
26f9d472eeSLv Zheng /*******************************************************************************
27f9d472eeSLv Zheng  *
28f9d472eeSLv Zheng  * FUNCTION:    acpi_tb_compare_tables
29f9d472eeSLv Zheng  *
30f9d472eeSLv Zheng  * PARAMETERS:  table_desc          - Table 1 descriptor to be compared
31f9d472eeSLv Zheng  *              table_index         - Index of table 2 to be compared
32f9d472eeSLv Zheng  *
33f9d472eeSLv Zheng  * RETURN:      TRUE if both tables are identical.
34f9d472eeSLv Zheng  *
35f9d472eeSLv Zheng  * DESCRIPTION: This function compares a table with another table that has
36f9d472eeSLv Zheng  *              already been installed in the root table list.
37f9d472eeSLv Zheng  *
38f9d472eeSLv Zheng  ******************************************************************************/
39f9d472eeSLv Zheng 
40f9d472eeSLv Zheng static u8
acpi_tb_compare_tables(struct acpi_table_desc * table_desc,u32 table_index)41f9d472eeSLv Zheng acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index)
42f9d472eeSLv Zheng {
43f9d472eeSLv Zheng 	acpi_status status = AE_OK;
44f9d472eeSLv Zheng 	u8 is_identical;
45f9d472eeSLv Zheng 	struct acpi_table_header *table;
46f9d472eeSLv Zheng 	u32 table_length;
47f9d472eeSLv Zheng 	u8 table_flags;
48f9d472eeSLv Zheng 
49f9d472eeSLv Zheng 	status =
50f9d472eeSLv Zheng 	    acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index],
51f9d472eeSLv Zheng 				  &table, &table_length, &table_flags);
52f9d472eeSLv Zheng 	if (ACPI_FAILURE(status)) {
53f9d472eeSLv Zheng 		return (FALSE);
54f9d472eeSLv Zheng 	}
55f9d472eeSLv Zheng 
56f9d472eeSLv Zheng 	/*
57f9d472eeSLv Zheng 	 * Check for a table match on the entire table length,
58f9d472eeSLv Zheng 	 * not just the header.
59f9d472eeSLv Zheng 	 */
60f9d472eeSLv Zheng 	is_identical = (u8)((table_desc->length != table_length ||
61f9d472eeSLv Zheng 			     memcmp(table_desc->pointer, table, table_length)) ?
62f9d472eeSLv Zheng 			    FALSE : TRUE);
63f9d472eeSLv Zheng 
64f9d472eeSLv Zheng 	/* Release the acquired table */
65f9d472eeSLv Zheng 
66f9d472eeSLv Zheng 	acpi_tb_release_table(table, table_length, table_flags);
67f9d472eeSLv Zheng 	return (is_identical);
68f9d472eeSLv Zheng }
69f9d472eeSLv Zheng 
70c418ce19SBob Moore /*******************************************************************************
71c418ce19SBob Moore  *
72c418ce19SBob Moore  * FUNCTION:    acpi_tb_init_table_descriptor
73c418ce19SBob Moore  *
74c418ce19SBob Moore  * PARAMETERS:  table_desc              - Table descriptor
75c418ce19SBob Moore  *              address                 - Physical address of the table
76c418ce19SBob Moore  *              flags                   - Allocation flags of the table
77c418ce19SBob Moore  *              table                   - Pointer to the table
78c418ce19SBob Moore  *
79c418ce19SBob Moore  * RETURN:      None
80c418ce19SBob Moore  *
81c418ce19SBob Moore  * DESCRIPTION: Initialize a new table descriptor
82c418ce19SBob Moore  *
83c418ce19SBob Moore  ******************************************************************************/
84f9d472eeSLv Zheng 
85c418ce19SBob Moore void
acpi_tb_init_table_descriptor(struct acpi_table_desc * table_desc,acpi_physical_address address,u8 flags,struct acpi_table_header * table)86c418ce19SBob Moore acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc,
87c418ce19SBob Moore 			      acpi_physical_address address,
88c418ce19SBob Moore 			      u8 flags, struct acpi_table_header *table)
89c418ce19SBob Moore {
90c418ce19SBob Moore 
91c418ce19SBob Moore 	/*
925d6e5966SJessica Clarke 	 * Initialize the table descriptor. Set the pointer to NULL for external
935d6e5966SJessica Clarke 	 * tables, since the table is not fully mapped at this time.
94c418ce19SBob Moore 	 */
954fa4616eSBob Moore 	memset(table_desc, 0, sizeof(struct acpi_table_desc));
96c418ce19SBob Moore 	table_desc->address = address;
97c418ce19SBob Moore 	table_desc->length = table->length;
98c418ce19SBob Moore 	table_desc->flags = flags;
99c418ce19SBob Moore 	ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature);
1005d6e5966SJessica Clarke 
1015d6e5966SJessica Clarke 	switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
1025d6e5966SJessica Clarke 	case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
1035d6e5966SJessica Clarke 	case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
1045d6e5966SJessica Clarke 
1055d6e5966SJessica Clarke 		table_desc->pointer = table;
1065d6e5966SJessica Clarke 		break;
1075d6e5966SJessica Clarke 
1085d6e5966SJessica Clarke 	case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
1095d6e5966SJessica Clarke 	default:
1105d6e5966SJessica Clarke 
1115d6e5966SJessica Clarke 		break;
1125d6e5966SJessica Clarke 	}
113c418ce19SBob Moore }
114c418ce19SBob Moore 
115c418ce19SBob Moore /*******************************************************************************
116c418ce19SBob Moore  *
117c418ce19SBob Moore  * FUNCTION:    acpi_tb_acquire_table
118c418ce19SBob Moore  *
119c418ce19SBob Moore  * PARAMETERS:  table_desc          - Table descriptor
120c418ce19SBob Moore  *              table_ptr           - Where table is returned
121c418ce19SBob Moore  *              table_length        - Where table length is returned
122c418ce19SBob Moore  *              table_flags         - Where table allocation flags are returned
123c418ce19SBob Moore  *
124c418ce19SBob Moore  * RETURN:      Status
125c418ce19SBob Moore  *
126c418ce19SBob Moore  * DESCRIPTION: Acquire an ACPI table. It can be used for tables not
127c418ce19SBob Moore  *              maintained in the acpi_gbl_root_table_list.
128c418ce19SBob Moore  *
129c418ce19SBob Moore  ******************************************************************************/
130c418ce19SBob Moore 
131c418ce19SBob Moore acpi_status
acpi_tb_acquire_table(struct acpi_table_desc * table_desc,struct acpi_table_header ** table_ptr,u32 * table_length,u8 * table_flags)132c418ce19SBob Moore acpi_tb_acquire_table(struct acpi_table_desc *table_desc,
133c418ce19SBob Moore 		      struct acpi_table_header **table_ptr,
134c418ce19SBob Moore 		      u32 *table_length, u8 *table_flags)
135c418ce19SBob Moore {
136c418ce19SBob Moore 	struct acpi_table_header *table = NULL;
137c418ce19SBob Moore 
138c418ce19SBob Moore 	switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
139c418ce19SBob Moore 	case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
140c418ce19SBob Moore 
141c418ce19SBob Moore 		table =
142c418ce19SBob Moore 		    acpi_os_map_memory(table_desc->address, table_desc->length);
143c418ce19SBob Moore 		break;
144c418ce19SBob Moore 
145c418ce19SBob Moore 	case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
146c418ce19SBob Moore 	case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
147c418ce19SBob Moore 
1485d6e5966SJessica Clarke 		table = table_desc->pointer;
149c418ce19SBob Moore 		break;
150c418ce19SBob Moore 
151c418ce19SBob Moore 	default:
152c418ce19SBob Moore 
153c418ce19SBob Moore 		break;
154c418ce19SBob Moore 	}
155c418ce19SBob Moore 
156c418ce19SBob Moore 	/* Table is not valid yet */
157c418ce19SBob Moore 
158c418ce19SBob Moore 	if (!table) {
159c418ce19SBob Moore 		return (AE_NO_MEMORY);
160c418ce19SBob Moore 	}
161c418ce19SBob Moore 
162c418ce19SBob Moore 	/* Fill the return values */
163c418ce19SBob Moore 
164c418ce19SBob Moore 	*table_ptr = table;
165c418ce19SBob Moore 	*table_length = table_desc->length;
166c418ce19SBob Moore 	*table_flags = table_desc->flags;
167c418ce19SBob Moore 	return (AE_OK);
168c418ce19SBob Moore }
169c418ce19SBob Moore 
170c418ce19SBob Moore /*******************************************************************************
171c418ce19SBob Moore  *
172c418ce19SBob Moore  * FUNCTION:    acpi_tb_release_table
173c418ce19SBob Moore  *
174c418ce19SBob Moore  * PARAMETERS:  table               - Pointer for the table
175c418ce19SBob Moore  *              table_length        - Length for the table
176c418ce19SBob Moore  *              table_flags         - Allocation flags for the table
177c418ce19SBob Moore  *
178c418ce19SBob Moore  * RETURN:      None
179c418ce19SBob Moore  *
180c418ce19SBob Moore  * DESCRIPTION: Release a table. The inverse of acpi_tb_acquire_table().
181c418ce19SBob Moore  *
182c418ce19SBob Moore  ******************************************************************************/
183c418ce19SBob Moore 
184c418ce19SBob Moore void
acpi_tb_release_table(struct acpi_table_header * table,u32 table_length,u8 table_flags)185c418ce19SBob Moore acpi_tb_release_table(struct acpi_table_header *table,
186c418ce19SBob Moore 		      u32 table_length, u8 table_flags)
187c418ce19SBob Moore {
188c418ce19SBob Moore 
189c418ce19SBob Moore 	switch (table_flags & ACPI_TABLE_ORIGIN_MASK) {
190c418ce19SBob Moore 	case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
191c418ce19SBob Moore 
192c418ce19SBob Moore 		acpi_os_unmap_memory(table, table_length);
193c418ce19SBob Moore 		break;
194c418ce19SBob Moore 
195c418ce19SBob Moore 	case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
196c418ce19SBob Moore 	case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
197c418ce19SBob Moore 	default:
198c418ce19SBob Moore 
199c418ce19SBob Moore 		break;
200c418ce19SBob Moore 	}
201c418ce19SBob Moore }
202c418ce19SBob Moore 
203c418ce19SBob Moore /*******************************************************************************
204c418ce19SBob Moore  *
205c418ce19SBob Moore  * FUNCTION:    acpi_tb_acquire_temp_table
206c418ce19SBob Moore  *
207c418ce19SBob Moore  * PARAMETERS:  table_desc          - Table descriptor to be acquired
208c418ce19SBob Moore  *              address             - Address of the table
209c418ce19SBob Moore  *              flags               - Allocation flags of the table
2105d6e5966SJessica Clarke  *              table               - Pointer to the table (required for virtual
2115d6e5966SJessica Clarke  *                                    origins, optional for physical)
212c418ce19SBob Moore  *
213c418ce19SBob Moore  * RETURN:      Status
214c418ce19SBob Moore  *
215c418ce19SBob Moore  * DESCRIPTION: This function validates the table header to obtain the length
216c418ce19SBob Moore  *              of a table and fills the table descriptor to make its state as
217c418ce19SBob Moore  *              "INSTALLED". Such a table descriptor is only used for verified
218c418ce19SBob Moore  *              installation.
219c418ce19SBob Moore  *
220c418ce19SBob Moore  ******************************************************************************/
221c418ce19SBob Moore 
222c418ce19SBob Moore acpi_status
acpi_tb_acquire_temp_table(struct acpi_table_desc * table_desc,acpi_physical_address address,u8 flags,struct acpi_table_header * table)223c418ce19SBob Moore acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc,
2245d6e5966SJessica Clarke 			   acpi_physical_address address,
2255d6e5966SJessica Clarke 			   u8 flags, struct acpi_table_header *table)
226c418ce19SBob Moore {
2275d6e5966SJessica Clarke 	u8 mapped_table = FALSE;
228c418ce19SBob Moore 
229c418ce19SBob Moore 	switch (flags & ACPI_TABLE_ORIGIN_MASK) {
230c418ce19SBob Moore 	case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
231c418ce19SBob Moore 
232c418ce19SBob Moore 		/* Get the length of the full table from the header */
233c418ce19SBob Moore 
2345d6e5966SJessica Clarke 		if (!table) {
2355d6e5966SJessica Clarke 			table =
236c418ce19SBob Moore 			    acpi_os_map_memory(address,
2375d6e5966SJessica Clarke 					       sizeof(struct
2385d6e5966SJessica Clarke 						      acpi_table_header));
2395d6e5966SJessica Clarke 			if (!table) {
240c418ce19SBob Moore 				return (AE_NO_MEMORY);
241c418ce19SBob Moore 			}
242c418ce19SBob Moore 
2435d6e5966SJessica Clarke 			mapped_table = TRUE;
2445d6e5966SJessica Clarke 		}
2455d6e5966SJessica Clarke 
2465d6e5966SJessica Clarke 		break;
247c418ce19SBob Moore 
248c418ce19SBob Moore 	case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
249c418ce19SBob Moore 	case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
250c418ce19SBob Moore 
2515d6e5966SJessica Clarke 		if (!table) {
2529f528154SBob Moore 			return (AE_BAD_PARAMETER);
253c418ce19SBob Moore 		}
254c418ce19SBob Moore 
255c418ce19SBob Moore 		break;
2565d6e5966SJessica Clarke 
2575d6e5966SJessica Clarke 	default:
258c418ce19SBob Moore 
259c418ce19SBob Moore 		/* Table is not valid yet */
260c418ce19SBob Moore 
261c418ce19SBob Moore 		return (AE_NO_MEMORY);
262c418ce19SBob Moore 	}
263c418ce19SBob Moore 
2645d6e5966SJessica Clarke 	acpi_tb_init_table_descriptor(table_desc, address, flags, table);
2655d6e5966SJessica Clarke 	if (mapped_table) {
2665d6e5966SJessica Clarke 		acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
2675d6e5966SJessica Clarke 	}
2685d6e5966SJessica Clarke 
2695d6e5966SJessica Clarke 	return (AE_OK);
2705d6e5966SJessica Clarke }
2715d6e5966SJessica Clarke 
272c418ce19SBob Moore /*******************************************************************************
273c418ce19SBob Moore  *
274c418ce19SBob Moore  * FUNCTION:    acpi_tb_release_temp_table
275c418ce19SBob Moore  *
276c418ce19SBob Moore  * PARAMETERS:  table_desc          - Table descriptor to be released
277c418ce19SBob Moore  *
278c418ce19SBob Moore  * RETURN:      Status
279c418ce19SBob Moore  *
280c418ce19SBob Moore  * DESCRIPTION: The inverse of acpi_tb_acquire_temp_table().
281c418ce19SBob Moore  *
282c418ce19SBob Moore  *****************************************************************************/
283c418ce19SBob Moore 
acpi_tb_release_temp_table(struct acpi_table_desc * table_desc)284c418ce19SBob Moore void acpi_tb_release_temp_table(struct acpi_table_desc *table_desc)
285c418ce19SBob Moore {
286c418ce19SBob Moore 
287c418ce19SBob Moore 	/*
288c418ce19SBob Moore 	 * Note that the .Address is maintained by the callers of
289c418ce19SBob Moore 	 * acpi_tb_acquire_temp_table(), thus do not invoke acpi_tb_uninstall_table()
290c418ce19SBob Moore 	 * where .Address will be freed.
291c418ce19SBob Moore 	 */
292c418ce19SBob Moore 	acpi_tb_invalidate_table(table_desc);
293c418ce19SBob Moore }
294c418ce19SBob Moore 
295c418ce19SBob Moore /******************************************************************************
296c418ce19SBob Moore  *
297c418ce19SBob Moore  * FUNCTION:    acpi_tb_validate_table
298c418ce19SBob Moore  *
299c418ce19SBob Moore  * PARAMETERS:  table_desc          - Table descriptor
300c418ce19SBob Moore  *
301c418ce19SBob Moore  * RETURN:      Status
302c418ce19SBob Moore  *
303c418ce19SBob Moore  * DESCRIPTION: This function is called to validate the table, the returned
304c418ce19SBob Moore  *              table descriptor is in "VALIDATED" state.
305c418ce19SBob Moore  *
306c418ce19SBob Moore  *****************************************************************************/
307c418ce19SBob Moore 
acpi_tb_validate_table(struct acpi_table_desc * table_desc)308c418ce19SBob Moore acpi_status acpi_tb_validate_table(struct acpi_table_desc *table_desc)
309c418ce19SBob Moore {
310c418ce19SBob Moore 	acpi_status status = AE_OK;
311c418ce19SBob Moore 
312c418ce19SBob Moore 	ACPI_FUNCTION_TRACE(tb_validate_table);
313c418ce19SBob Moore 
314c418ce19SBob Moore 	/* Validate the table if necessary */
315c418ce19SBob Moore 
316c418ce19SBob Moore 	if (!table_desc->pointer) {
317c418ce19SBob Moore 		status = acpi_tb_acquire_table(table_desc, &table_desc->pointer,
318c418ce19SBob Moore 					       &table_desc->length,
319c418ce19SBob Moore 					       &table_desc->flags);
320c418ce19SBob Moore 		if (!table_desc->pointer) {
321c418ce19SBob Moore 			status = AE_NO_MEMORY;
322c418ce19SBob Moore 		}
323c418ce19SBob Moore 	}
324c418ce19SBob Moore 
325c418ce19SBob Moore 	return_ACPI_STATUS(status);
326c418ce19SBob Moore }
327c418ce19SBob Moore 
328c418ce19SBob Moore /*******************************************************************************
329c418ce19SBob Moore  *
330c418ce19SBob Moore  * FUNCTION:    acpi_tb_invalidate_table
331c418ce19SBob Moore  *
332c418ce19SBob Moore  * PARAMETERS:  table_desc          - Table descriptor
333c418ce19SBob Moore  *
334c418ce19SBob Moore  * RETURN:      None
335c418ce19SBob Moore  *
336c418ce19SBob Moore  * DESCRIPTION: Invalidate one internal ACPI table, this is the inverse of
337c418ce19SBob Moore  *              acpi_tb_validate_table().
338c418ce19SBob Moore  *
339c418ce19SBob Moore  ******************************************************************************/
340c418ce19SBob Moore 
acpi_tb_invalidate_table(struct acpi_table_desc * table_desc)341c418ce19SBob Moore void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc)
342c418ce19SBob Moore {
343c418ce19SBob Moore 
344c418ce19SBob Moore 	ACPI_FUNCTION_TRACE(tb_invalidate_table);
345c418ce19SBob Moore 
346c418ce19SBob Moore 	/* Table must be validated */
347c418ce19SBob Moore 
348c418ce19SBob Moore 	if (!table_desc->pointer) {
349c418ce19SBob Moore 		return_VOID;
350c418ce19SBob Moore 	}
351c418ce19SBob Moore 
352c418ce19SBob Moore 	acpi_tb_release_table(table_desc->pointer, table_desc->length,
353c418ce19SBob Moore 			      table_desc->flags);
3545d6e5966SJessica Clarke 
3555d6e5966SJessica Clarke 	switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
3565d6e5966SJessica Clarke 	case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
3575d6e5966SJessica Clarke 
358c418ce19SBob Moore 		table_desc->pointer = NULL;
3595d6e5966SJessica Clarke 		break;
3605d6e5966SJessica Clarke 
3615d6e5966SJessica Clarke 	case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
3625d6e5966SJessica Clarke 	case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
3635d6e5966SJessica Clarke 	default:
3645d6e5966SJessica Clarke 
3655d6e5966SJessica Clarke 		break;
3665d6e5966SJessica Clarke 	}
367c418ce19SBob Moore 
368c418ce19SBob Moore 	return_VOID;
369c418ce19SBob Moore }
370c418ce19SBob Moore 
371c418ce19SBob Moore /******************************************************************************
372c418ce19SBob Moore  *
37347d68c7fSLv Zheng  * FUNCTION:    acpi_tb_validate_temp_table
37447d68c7fSLv Zheng  *
37547d68c7fSLv Zheng  * PARAMETERS:  table_desc          - Table descriptor
37647d68c7fSLv Zheng  *
37747d68c7fSLv Zheng  * RETURN:      Status
37847d68c7fSLv Zheng  *
37947d68c7fSLv Zheng  * DESCRIPTION: This function is called to validate the table, the returned
38047d68c7fSLv Zheng  *              table descriptor is in "VALIDATED" state.
38147d68c7fSLv Zheng  *
38247d68c7fSLv Zheng  *****************************************************************************/
38347d68c7fSLv Zheng 
acpi_tb_validate_temp_table(struct acpi_table_desc * table_desc)38447d68c7fSLv Zheng acpi_status acpi_tb_validate_temp_table(struct acpi_table_desc *table_desc)
38547d68c7fSLv Zheng {
38647d68c7fSLv Zheng 
387023e2ee1SLv Zheng 	if (!table_desc->pointer && !acpi_gbl_enable_table_validation) {
38847d68c7fSLv Zheng 		/*
38947d68c7fSLv Zheng 		 * Only validates the header of the table.
39047d68c7fSLv Zheng 		 * Note that Length contains the size of the mapping after invoking
39147d68c7fSLv Zheng 		 * this work around, this value is required by
39247d68c7fSLv Zheng 		 * acpi_tb_release_temp_table().
39347d68c7fSLv Zheng 		 * We can do this because in acpi_init_table_descriptor(), the Length
39447d68c7fSLv Zheng 		 * field of the installed descriptor is filled with the actual
39547d68c7fSLv Zheng 		 * table length obtaining from the table header.
39647d68c7fSLv Zheng 		 */
39747d68c7fSLv Zheng 		table_desc->length = sizeof(struct acpi_table_header);
39847d68c7fSLv Zheng 	}
39947d68c7fSLv Zheng 
40047d68c7fSLv Zheng 	return (acpi_tb_validate_table(table_desc));
40147d68c7fSLv Zheng }
40247d68c7fSLv Zheng 
403f9d472eeSLv Zheng /*******************************************************************************
404f9d472eeSLv Zheng  *
405f9d472eeSLv Zheng  * FUNCTION:    acpi_tb_check_duplication
406f9d472eeSLv Zheng  *
407f9d472eeSLv Zheng  * PARAMETERS:  table_desc          - Table descriptor
408f9d472eeSLv Zheng  *              table_index         - Where the table index is returned
409f9d472eeSLv Zheng  *
410f9d472eeSLv Zheng  * RETURN:      Status
411f9d472eeSLv Zheng  *
412f9d472eeSLv Zheng  * DESCRIPTION: Avoid installing duplicated tables. However table override and
413f9d472eeSLv Zheng  *              user aided dynamic table load is allowed, thus comparing the
414f9d472eeSLv Zheng  *              address of the table is not sufficient, and checking the entire
415f9d472eeSLv Zheng  *              table content is required.
416f9d472eeSLv Zheng  *
417f9d472eeSLv Zheng  ******************************************************************************/
418f9d472eeSLv Zheng 
419f9d472eeSLv Zheng static acpi_status
acpi_tb_check_duplication(struct acpi_table_desc * table_desc,u32 * table_index)420f9d472eeSLv Zheng acpi_tb_check_duplication(struct acpi_table_desc *table_desc, u32 *table_index)
421f9d472eeSLv Zheng {
422f9d472eeSLv Zheng 	u32 i;
423f9d472eeSLv Zheng 
424f9d472eeSLv Zheng 	ACPI_FUNCTION_TRACE(tb_check_duplication);
425f9d472eeSLv Zheng 
426f9d472eeSLv Zheng 	/* Check if table is already registered */
427f9d472eeSLv Zheng 
428f9d472eeSLv Zheng 	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
42919df56bdSLv Zheng 
43019df56bdSLv Zheng 		/* Do not compare with unverified tables */
43119df56bdSLv Zheng 
43219df56bdSLv Zheng 		if (!
43319df56bdSLv Zheng 		    (acpi_gbl_root_table_list.tables[i].
43419df56bdSLv Zheng 		     flags & ACPI_TABLE_IS_VERIFIED)) {
43519df56bdSLv Zheng 			continue;
43619df56bdSLv Zheng 		}
43719df56bdSLv Zheng 
438f9d472eeSLv Zheng 		/*
439f9d472eeSLv Zheng 		 * Check for a table match on the entire table length,
440f9d472eeSLv Zheng 		 * not just the header.
441f9d472eeSLv Zheng 		 */
442f9d472eeSLv Zheng 		if (!acpi_tb_compare_tables(table_desc, i)) {
443f9d472eeSLv Zheng 			continue;
444f9d472eeSLv Zheng 		}
445f9d472eeSLv Zheng 
446f9d472eeSLv Zheng 		/*
447f9d472eeSLv Zheng 		 * Note: the current mechanism does not unregister a table if it is
448f9d472eeSLv Zheng 		 * dynamically unloaded. The related namespace entries are deleted,
449f9d472eeSLv Zheng 		 * but the table remains in the root table list.
450f9d472eeSLv Zheng 		 *
451f9d472eeSLv Zheng 		 * The assumption here is that the number of different tables that
452f9d472eeSLv Zheng 		 * will be loaded is actually small, and there is minimal overhead
453f9d472eeSLv Zheng 		 * in just keeping the table in case it is needed again.
454f9d472eeSLv Zheng 		 *
455f9d472eeSLv Zheng 		 * If this assumption changes in the future (perhaps on large
456f9d472eeSLv Zheng 		 * machines with many table load/unload operations), tables will
457f9d472eeSLv Zheng 		 * need to be unregistered when they are unloaded, and slots in the
458f9d472eeSLv Zheng 		 * root table list should be reused when empty.
459f9d472eeSLv Zheng 		 */
460f9d472eeSLv Zheng 		if (acpi_gbl_root_table_list.tables[i].flags &
461f9d472eeSLv Zheng 		    ACPI_TABLE_IS_LOADED) {
462f9d472eeSLv Zheng 
463f9d472eeSLv Zheng 			/* Table is still loaded, this is an error */
464f9d472eeSLv Zheng 
465f9d472eeSLv Zheng 			return_ACPI_STATUS(AE_ALREADY_EXISTS);
466f9d472eeSLv Zheng 		} else {
467f9d472eeSLv Zheng 			*table_index = i;
468f9d472eeSLv Zheng 			return_ACPI_STATUS(AE_CTRL_TERMINATE);
469f9d472eeSLv Zheng 		}
470f9d472eeSLv Zheng 	}
471f9d472eeSLv Zheng 
472f9d472eeSLv Zheng 	/* Indicate no duplication to the caller */
473f9d472eeSLv Zheng 
474f9d472eeSLv Zheng 	return_ACPI_STATUS(AE_OK);
475f9d472eeSLv Zheng }
476f9d472eeSLv Zheng 
47747d68c7fSLv Zheng /******************************************************************************
47847d68c7fSLv Zheng  *
47947d68c7fSLv Zheng  * FUNCTION:    acpi_tb_verify_temp_table
480c418ce19SBob Moore  *
481c418ce19SBob Moore  * PARAMETERS:  table_desc          - Table descriptor
482c418ce19SBob Moore  *              signature           - Table signature to verify
483f9d472eeSLv Zheng  *              table_index         - Where the table index is returned
484c418ce19SBob Moore  *
485c418ce19SBob Moore  * RETURN:      Status
486c418ce19SBob Moore  *
487c418ce19SBob Moore  * DESCRIPTION: This function is called to validate and verify the table, the
488c418ce19SBob Moore  *              returned table descriptor is in "VALIDATED" state.
48919df56bdSLv Zheng  *              Note that 'TableIndex' is required to be set to !NULL to
49019df56bdSLv Zheng  *              enable duplication check.
491c418ce19SBob Moore  *
492c418ce19SBob Moore  *****************************************************************************/
493c418ce19SBob Moore 
494c418ce19SBob Moore acpi_status
acpi_tb_verify_temp_table(struct acpi_table_desc * table_desc,char * signature,u32 * table_index)495f9d472eeSLv Zheng acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc,
496f9d472eeSLv Zheng 			  char *signature, u32 *table_index)
497c418ce19SBob Moore {
498c418ce19SBob Moore 	acpi_status status = AE_OK;
499c418ce19SBob Moore 
50047d68c7fSLv Zheng 	ACPI_FUNCTION_TRACE(tb_verify_temp_table);
501c418ce19SBob Moore 
502c418ce19SBob Moore 	/* Validate the table */
503c418ce19SBob Moore 
50447d68c7fSLv Zheng 	status = acpi_tb_validate_temp_table(table_desc);
505c418ce19SBob Moore 	if (ACPI_FAILURE(status)) {
506c418ce19SBob Moore 		return_ACPI_STATUS(AE_NO_MEMORY);
507c418ce19SBob Moore 	}
508c418ce19SBob Moore 
509c418ce19SBob Moore 	/* If a particular signature is expected (DSDT/FACS), it must match */
510c418ce19SBob Moore 
5115599fb69SBob Moore 	if (signature &&
5125599fb69SBob Moore 	    !ACPI_COMPARE_NAMESEG(&table_desc->signature, signature)) {
513c418ce19SBob Moore 		ACPI_BIOS_ERROR((AE_INFO,
514c418ce19SBob Moore 				 "Invalid signature 0x%X for ACPI table, expected [%s]",
515c418ce19SBob Moore 				 table_desc->signature.integer, signature));
516c418ce19SBob Moore 		status = AE_BAD_SIGNATURE;
517c418ce19SBob Moore 		goto invalidate_and_exit;
518c418ce19SBob Moore 	}
519c418ce19SBob Moore 
520f9d472eeSLv Zheng 	if (acpi_gbl_enable_table_validation) {
521f9d472eeSLv Zheng 
522c418ce19SBob Moore 		/* Verify the checksum */
523c418ce19SBob Moore 
524c418ce19SBob Moore 		status =
52551aad1a6SBob Moore 		    acpi_ut_verify_checksum(table_desc->pointer,
52647d68c7fSLv Zheng 					    table_desc->length);
527c418ce19SBob Moore 		if (ACPI_FAILURE(status)) {
528c418ce19SBob Moore 			ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
5291d0a0b2fSLv Zheng 					"%4.4s 0x%8.8X%8.8X"
530c418ce19SBob Moore 					" Attempted table install failed",
5316a0df32cSBob Moore 					acpi_ut_valid_nameseg(table_desc->
53247d68c7fSLv Zheng 							      signature.
53347d68c7fSLv Zheng 							      ascii) ?
53447d68c7fSLv Zheng 					table_desc->signature.ascii : "????",
5351d0a0b2fSLv Zheng 					ACPI_FORMAT_UINT64(table_desc->
53647d68c7fSLv Zheng 							   address)));
5371fad8738SBob Moore 
538c418ce19SBob Moore 			goto invalidate_and_exit;
539c418ce19SBob Moore 		}
540f9d472eeSLv Zheng 
541f9d472eeSLv Zheng 		/* Avoid duplications */
542f9d472eeSLv Zheng 
543f9d472eeSLv Zheng 		if (table_index) {
544f9d472eeSLv Zheng 			status =
545f9d472eeSLv Zheng 			    acpi_tb_check_duplication(table_desc, table_index);
546f9d472eeSLv Zheng 			if (ACPI_FAILURE(status)) {
547f9d472eeSLv Zheng 				if (status != AE_CTRL_TERMINATE) {
5488a55c696SBob Moore 					ACPI_EXCEPTION((AE_INFO, status,
549f9d472eeSLv Zheng 							"%4.4s 0x%8.8X%8.8X"
5508a55c696SBob Moore 							" Table is already loaded",
551f9d472eeSLv Zheng 							acpi_ut_valid_nameseg
552f9d472eeSLv Zheng 							(table_desc->signature.
553f9d472eeSLv Zheng 							 ascii) ? table_desc->
554f9d472eeSLv Zheng 							signature.
555f9d472eeSLv Zheng 							ascii : "????",
556f9d472eeSLv Zheng 							ACPI_FORMAT_UINT64
557f9d472eeSLv Zheng 							(table_desc->address)));
55847d68c7fSLv Zheng 				}
559c418ce19SBob Moore 
560f9d472eeSLv Zheng 				goto invalidate_and_exit;
561f9d472eeSLv Zheng 			}
562f9d472eeSLv Zheng 		}
56319df56bdSLv Zheng 
56419df56bdSLv Zheng 		table_desc->flags |= ACPI_TABLE_IS_VERIFIED;
565f9d472eeSLv Zheng 	}
566f9d472eeSLv Zheng 
567f9d472eeSLv Zheng 	return_ACPI_STATUS(status);
568c418ce19SBob Moore 
569c418ce19SBob Moore invalidate_and_exit:
570c418ce19SBob Moore 	acpi_tb_invalidate_table(table_desc);
571c418ce19SBob Moore 	return_ACPI_STATUS(status);
572c418ce19SBob Moore }
573c418ce19SBob Moore 
574c418ce19SBob Moore /*******************************************************************************
575c418ce19SBob Moore  *
576c418ce19SBob Moore  * FUNCTION:    acpi_tb_resize_root_table_list
577c418ce19SBob Moore  *
578c418ce19SBob Moore  * PARAMETERS:  None
579c418ce19SBob Moore  *
580c418ce19SBob Moore  * RETURN:      Status
581c418ce19SBob Moore  *
582c418ce19SBob Moore  * DESCRIPTION: Expand the size of global table array
583c418ce19SBob Moore  *
584c418ce19SBob Moore  ******************************************************************************/
585c418ce19SBob Moore 
acpi_tb_resize_root_table_list(void)586c418ce19SBob Moore acpi_status acpi_tb_resize_root_table_list(void)
587c418ce19SBob Moore {
588c418ce19SBob Moore 	struct acpi_table_desc *tables;
589c418ce19SBob Moore 	u32 table_count;
59019df56bdSLv Zheng 	u32 current_table_count, max_table_count;
59119df56bdSLv Zheng 	u32 i;
592c418ce19SBob Moore 
593c418ce19SBob Moore 	ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
594c418ce19SBob Moore 
595c418ce19SBob Moore 	/* allow_resize flag is a parameter to acpi_initialize_tables */
596c418ce19SBob Moore 
597c418ce19SBob Moore 	if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) {
598c418ce19SBob Moore 		ACPI_ERROR((AE_INFO,
599c418ce19SBob Moore 			    "Resize of Root Table Array is not allowed"));
600c418ce19SBob Moore 		return_ACPI_STATUS(AE_SUPPORT);
601c418ce19SBob Moore 	}
602c418ce19SBob Moore 
603c418ce19SBob Moore 	/* Increase the Table Array size */
604c418ce19SBob Moore 
605c418ce19SBob Moore 	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
606c418ce19SBob Moore 		table_count = acpi_gbl_root_table_list.max_table_count;
607c418ce19SBob Moore 	} else {
608c418ce19SBob Moore 		table_count = acpi_gbl_root_table_list.current_table_count;
609c418ce19SBob Moore 	}
610c418ce19SBob Moore 
61119df56bdSLv Zheng 	max_table_count = table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT;
61219df56bdSLv Zheng 	tables = ACPI_ALLOCATE_ZEROED(((acpi_size)max_table_count) *
613c418ce19SBob Moore 				      sizeof(struct acpi_table_desc));
614c418ce19SBob Moore 	if (!tables) {
615c418ce19SBob Moore 		ACPI_ERROR((AE_INFO,
616c418ce19SBob Moore 			    "Could not allocate new root table array"));
617c418ce19SBob Moore 		return_ACPI_STATUS(AE_NO_MEMORY);
618c418ce19SBob Moore 	}
619c418ce19SBob Moore 
620c418ce19SBob Moore 	/* Copy and free the previous table array */
621c418ce19SBob Moore 
62219df56bdSLv Zheng 	current_table_count = 0;
623c418ce19SBob Moore 	if (acpi_gbl_root_table_list.tables) {
62419df56bdSLv Zheng 		for (i = 0; i < table_count; i++) {
62519df56bdSLv Zheng 			if (acpi_gbl_root_table_list.tables[i].address) {
62619df56bdSLv Zheng 				memcpy(tables + current_table_count,
62719df56bdSLv Zheng 				       acpi_gbl_root_table_list.tables + i,
62819df56bdSLv Zheng 				       sizeof(struct acpi_table_desc));
62919df56bdSLv Zheng 				current_table_count++;
63019df56bdSLv Zheng 			}
63119df56bdSLv Zheng 		}
632c418ce19SBob Moore 
633c418ce19SBob Moore 		if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
634c418ce19SBob Moore 			ACPI_FREE(acpi_gbl_root_table_list.tables);
635c418ce19SBob Moore 		}
636c418ce19SBob Moore 	}
637c418ce19SBob Moore 
638c418ce19SBob Moore 	acpi_gbl_root_table_list.tables = tables;
63919df56bdSLv Zheng 	acpi_gbl_root_table_list.max_table_count = max_table_count;
64019df56bdSLv Zheng 	acpi_gbl_root_table_list.current_table_count = current_table_count;
641c418ce19SBob Moore 	acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
642c418ce19SBob Moore 
643c418ce19SBob Moore 	return_ACPI_STATUS(AE_OK);
644c418ce19SBob Moore }
645c418ce19SBob Moore 
646c418ce19SBob Moore /*******************************************************************************
647c418ce19SBob Moore  *
64876cffa79SLv Zheng  * FUNCTION:    acpi_tb_get_next_table_descriptor
649c418ce19SBob Moore  *
650c418ce19SBob Moore  * PARAMETERS:  table_index         - Where table index is returned
65176cffa79SLv Zheng  *              table_desc          - Where table descriptor is returned
652c418ce19SBob Moore  *
65376cffa79SLv Zheng  * RETURN:      Status and table index/descriptor.
654c418ce19SBob Moore  *
655c418ce19SBob Moore  * DESCRIPTION: Allocate a new ACPI table entry to the global table list
656c418ce19SBob Moore  *
657c418ce19SBob Moore  ******************************************************************************/
658c418ce19SBob Moore 
65976cffa79SLv Zheng acpi_status
acpi_tb_get_next_table_descriptor(u32 * table_index,struct acpi_table_desc ** table_desc)66076cffa79SLv Zheng acpi_tb_get_next_table_descriptor(u32 *table_index,
66176cffa79SLv Zheng 				  struct acpi_table_desc **table_desc)
662c418ce19SBob Moore {
663c418ce19SBob Moore 	acpi_status status;
66476cffa79SLv Zheng 	u32 i;
665c418ce19SBob Moore 
666c418ce19SBob Moore 	/* Ensure that there is room for the table in the Root Table List */
667c418ce19SBob Moore 
668c418ce19SBob Moore 	if (acpi_gbl_root_table_list.current_table_count >=
669c418ce19SBob Moore 	    acpi_gbl_root_table_list.max_table_count) {
670c418ce19SBob Moore 		status = acpi_tb_resize_root_table_list();
671c418ce19SBob Moore 		if (ACPI_FAILURE(status)) {
672c418ce19SBob Moore 			return (status);
673c418ce19SBob Moore 		}
674c418ce19SBob Moore 	}
675c418ce19SBob Moore 
67676cffa79SLv Zheng 	i = acpi_gbl_root_table_list.current_table_count;
677c418ce19SBob Moore 	acpi_gbl_root_table_list.current_table_count++;
67876cffa79SLv Zheng 
67976cffa79SLv Zheng 	if (table_index) {
68076cffa79SLv Zheng 		*table_index = i;
68176cffa79SLv Zheng 	}
68276cffa79SLv Zheng 	if (table_desc) {
68376cffa79SLv Zheng 		*table_desc = &acpi_gbl_root_table_list.tables[i];
68476cffa79SLv Zheng 	}
68576cffa79SLv Zheng 
686c418ce19SBob Moore 	return (AE_OK);
687c418ce19SBob Moore }
688c418ce19SBob Moore 
689c418ce19SBob Moore /*******************************************************************************
690c418ce19SBob Moore  *
691c418ce19SBob Moore  * FUNCTION:    acpi_tb_terminate
692c418ce19SBob Moore  *
693c418ce19SBob Moore  * PARAMETERS:  None
694c418ce19SBob Moore  *
695c418ce19SBob Moore  * RETURN:      None
696c418ce19SBob Moore  *
697c418ce19SBob Moore  * DESCRIPTION: Delete all internal ACPI tables
698c418ce19SBob Moore  *
699c418ce19SBob Moore  ******************************************************************************/
700c418ce19SBob Moore 
acpi_tb_terminate(void)701c418ce19SBob Moore void acpi_tb_terminate(void)
702c418ce19SBob Moore {
703c418ce19SBob Moore 	u32 i;
704c418ce19SBob Moore 
705c418ce19SBob Moore 	ACPI_FUNCTION_TRACE(tb_terminate);
706c418ce19SBob Moore 
707c418ce19SBob Moore 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
708c418ce19SBob Moore 
709c418ce19SBob Moore 	/* Delete the individual tables */
710c418ce19SBob Moore 
711c418ce19SBob Moore 	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
712c418ce19SBob Moore 		acpi_tb_uninstall_table(&acpi_gbl_root_table_list.tables[i]);
713c418ce19SBob Moore 	}
714c418ce19SBob Moore 
715c418ce19SBob Moore 	/*
716c418ce19SBob Moore 	 * Delete the root table array if allocated locally. Array cannot be
717c418ce19SBob Moore 	 * mapped, so we don't need to check for that flag.
718c418ce19SBob Moore 	 */
719c418ce19SBob Moore 	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
720c418ce19SBob Moore 		ACPI_FREE(acpi_gbl_root_table_list.tables);
721c418ce19SBob Moore 	}
722c418ce19SBob Moore 
723c418ce19SBob Moore 	acpi_gbl_root_table_list.tables = NULL;
724c418ce19SBob Moore 	acpi_gbl_root_table_list.flags = 0;
725c418ce19SBob Moore 	acpi_gbl_root_table_list.current_table_count = 0;
726c418ce19SBob Moore 
727c418ce19SBob Moore 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
728c418ce19SBob Moore 
729c418ce19SBob Moore 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
730c418ce19SBob Moore 	return_VOID;
731c418ce19SBob Moore }
732c418ce19SBob Moore 
733c418ce19SBob Moore /*******************************************************************************
734c418ce19SBob Moore  *
735c418ce19SBob Moore  * FUNCTION:    acpi_tb_delete_namespace_by_owner
736c418ce19SBob Moore  *
737c418ce19SBob Moore  * PARAMETERS:  table_index         - Table index
738c418ce19SBob Moore  *
739c418ce19SBob Moore  * RETURN:      Status
740c418ce19SBob Moore  *
741c418ce19SBob Moore  * DESCRIPTION: Delete all namespace objects created when this table was loaded.
742c418ce19SBob Moore  *
743c418ce19SBob Moore  ******************************************************************************/
744c418ce19SBob Moore 
acpi_tb_delete_namespace_by_owner(u32 table_index)745c418ce19SBob Moore acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index)
746c418ce19SBob Moore {
747c418ce19SBob Moore 	acpi_owner_id owner_id;
748c418ce19SBob Moore 	acpi_status status;
749c418ce19SBob Moore 
750c418ce19SBob Moore 	ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner);
751c418ce19SBob Moore 
752c418ce19SBob Moore 	status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
753c418ce19SBob Moore 	if (ACPI_FAILURE(status)) {
754c418ce19SBob Moore 		return_ACPI_STATUS(status);
755c418ce19SBob Moore 	}
756c418ce19SBob Moore 
757c418ce19SBob Moore 	if (table_index >= acpi_gbl_root_table_list.current_table_count) {
758c418ce19SBob Moore 
759c418ce19SBob Moore 		/* The table index does not exist */
760c418ce19SBob Moore 
761c418ce19SBob Moore 		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
762c418ce19SBob Moore 		return_ACPI_STATUS(AE_NOT_EXIST);
763c418ce19SBob Moore 	}
764c418ce19SBob Moore 
765c418ce19SBob Moore 	/* Get the owner ID for this table, used to delete namespace nodes */
766c418ce19SBob Moore 
767c418ce19SBob Moore 	owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id;
768c418ce19SBob Moore 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
769c418ce19SBob Moore 
770c418ce19SBob Moore 	/*
771c418ce19SBob Moore 	 * Need to acquire the namespace writer lock to prevent interference
772c418ce19SBob Moore 	 * with any concurrent namespace walks. The interpreter must be
773c418ce19SBob Moore 	 * released during the deletion since the acquisition of the deletion
774c418ce19SBob Moore 	 * lock may block, and also since the execution of a namespace walk
775c418ce19SBob Moore 	 * must be allowed to use the interpreter.
776c418ce19SBob Moore 	 */
777c418ce19SBob Moore 	status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock);
778c418ce19SBob Moore 	if (ACPI_FAILURE(status)) {
779c418ce19SBob Moore 		return_ACPI_STATUS(status);
780c418ce19SBob Moore 	}
78167a72420SBob Moore 
7829febcdc0SLv Zheng 	acpi_ns_delete_namespace_by_owner(owner_id);
783c418ce19SBob Moore 	acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock);
784c418ce19SBob Moore 	return_ACPI_STATUS(status);
785c418ce19SBob Moore }
786c418ce19SBob Moore 
787c418ce19SBob Moore /*******************************************************************************
788c418ce19SBob Moore  *
789c418ce19SBob Moore  * FUNCTION:    acpi_tb_allocate_owner_id
790c418ce19SBob Moore  *
791c418ce19SBob Moore  * PARAMETERS:  table_index         - Table index
792c418ce19SBob Moore  *
793c418ce19SBob Moore  * RETURN:      Status
794c418ce19SBob Moore  *
795c418ce19SBob Moore  * DESCRIPTION: Allocates owner_id in table_desc
796c418ce19SBob Moore  *
797c418ce19SBob Moore  ******************************************************************************/
798c418ce19SBob Moore 
acpi_tb_allocate_owner_id(u32 table_index)799c418ce19SBob Moore acpi_status acpi_tb_allocate_owner_id(u32 table_index)
800c418ce19SBob Moore {
801c418ce19SBob Moore 	acpi_status status = AE_BAD_PARAMETER;
802c418ce19SBob Moore 
803c418ce19SBob Moore 	ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
804c418ce19SBob Moore 
805c418ce19SBob Moore 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
806c418ce19SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
807c418ce19SBob Moore 		status =
808c418ce19SBob Moore 		    acpi_ut_allocate_owner_id(&
809c418ce19SBob Moore 					      (acpi_gbl_root_table_list.
810c418ce19SBob Moore 					       tables[table_index].owner_id));
811c418ce19SBob Moore 	}
812c418ce19SBob Moore 
813c418ce19SBob Moore 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
814c418ce19SBob Moore 	return_ACPI_STATUS(status);
815c418ce19SBob Moore }
816c418ce19SBob Moore 
817c418ce19SBob Moore /*******************************************************************************
818c418ce19SBob Moore  *
819c418ce19SBob Moore  * FUNCTION:    acpi_tb_release_owner_id
820c418ce19SBob Moore  *
821c418ce19SBob Moore  * PARAMETERS:  table_index         - Table index
822c418ce19SBob Moore  *
823c418ce19SBob Moore  * RETURN:      Status
824c418ce19SBob Moore  *
825c418ce19SBob Moore  * DESCRIPTION: Releases owner_id in table_desc
826c418ce19SBob Moore  *
827c418ce19SBob Moore  ******************************************************************************/
828c418ce19SBob Moore 
acpi_tb_release_owner_id(u32 table_index)829c418ce19SBob Moore acpi_status acpi_tb_release_owner_id(u32 table_index)
830c418ce19SBob Moore {
831c418ce19SBob Moore 	acpi_status status = AE_BAD_PARAMETER;
832c418ce19SBob Moore 
833c418ce19SBob Moore 	ACPI_FUNCTION_TRACE(tb_release_owner_id);
834c418ce19SBob Moore 
835c418ce19SBob Moore 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
836c418ce19SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
837c418ce19SBob Moore 		acpi_ut_release_owner_id(&
838c418ce19SBob Moore 					 (acpi_gbl_root_table_list.
839c418ce19SBob Moore 					  tables[table_index].owner_id));
840c418ce19SBob Moore 		status = AE_OK;
841c418ce19SBob Moore 	}
842c418ce19SBob Moore 
843c418ce19SBob Moore 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
844c418ce19SBob Moore 	return_ACPI_STATUS(status);
845c418ce19SBob Moore }
846c418ce19SBob Moore 
847c418ce19SBob Moore /*******************************************************************************
848c418ce19SBob Moore  *
849c418ce19SBob Moore  * FUNCTION:    acpi_tb_get_owner_id
850c418ce19SBob Moore  *
851c418ce19SBob Moore  * PARAMETERS:  table_index         - Table index
852c418ce19SBob Moore  *              owner_id            - Where the table owner_id is returned
853c418ce19SBob Moore  *
854c418ce19SBob Moore  * RETURN:      Status
855c418ce19SBob Moore  *
856c418ce19SBob Moore  * DESCRIPTION: returns owner_id for the ACPI table
857c418ce19SBob Moore  *
858c418ce19SBob Moore  ******************************************************************************/
859c418ce19SBob Moore 
acpi_tb_get_owner_id(u32 table_index,acpi_owner_id * owner_id)860c418ce19SBob Moore acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id)
861c418ce19SBob Moore {
862c418ce19SBob Moore 	acpi_status status = AE_BAD_PARAMETER;
863c418ce19SBob Moore 
864c418ce19SBob Moore 	ACPI_FUNCTION_TRACE(tb_get_owner_id);
865c418ce19SBob Moore 
866c418ce19SBob Moore 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
867c418ce19SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
868c418ce19SBob Moore 		*owner_id =
869c418ce19SBob Moore 		    acpi_gbl_root_table_list.tables[table_index].owner_id;
870c418ce19SBob Moore 		status = AE_OK;
871c418ce19SBob Moore 	}
872c418ce19SBob Moore 
873c418ce19SBob Moore 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
874c418ce19SBob Moore 	return_ACPI_STATUS(status);
875c418ce19SBob Moore }
876c418ce19SBob Moore 
877c418ce19SBob Moore /*******************************************************************************
878c418ce19SBob Moore  *
879c418ce19SBob Moore  * FUNCTION:    acpi_tb_is_table_loaded
880c418ce19SBob Moore  *
881c418ce19SBob Moore  * PARAMETERS:  table_index         - Index into the root table
882c418ce19SBob Moore  *
883c418ce19SBob Moore  * RETURN:      Table Loaded Flag
884c418ce19SBob Moore  *
885c418ce19SBob Moore  ******************************************************************************/
886c418ce19SBob Moore 
acpi_tb_is_table_loaded(u32 table_index)887c418ce19SBob Moore u8 acpi_tb_is_table_loaded(u32 table_index)
888c418ce19SBob Moore {
889c418ce19SBob Moore 	u8 is_loaded = FALSE;
890c418ce19SBob Moore 
891c418ce19SBob Moore 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
892c418ce19SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
893c418ce19SBob Moore 		is_loaded = (u8)
894c418ce19SBob Moore 		    (acpi_gbl_root_table_list.tables[table_index].flags &
895c418ce19SBob Moore 		     ACPI_TABLE_IS_LOADED);
896c418ce19SBob Moore 	}
897c418ce19SBob Moore 
898c418ce19SBob Moore 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
899c418ce19SBob Moore 	return (is_loaded);
900c418ce19SBob Moore }
901c418ce19SBob Moore 
902c418ce19SBob Moore /*******************************************************************************
903c418ce19SBob Moore  *
904c418ce19SBob Moore  * FUNCTION:    acpi_tb_set_table_loaded_flag
905c418ce19SBob Moore  *
906c418ce19SBob Moore  * PARAMETERS:  table_index         - Table index
907c418ce19SBob Moore  *              is_loaded           - TRUE if table is loaded, FALSE otherwise
908c418ce19SBob Moore  *
909c418ce19SBob Moore  * RETURN:      None
910c418ce19SBob Moore  *
911c418ce19SBob Moore  * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
912c418ce19SBob Moore  *
913c418ce19SBob Moore  ******************************************************************************/
914c418ce19SBob Moore 
acpi_tb_set_table_loaded_flag(u32 table_index,u8 is_loaded)915c418ce19SBob Moore void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded)
916c418ce19SBob Moore {
917c418ce19SBob Moore 
918c418ce19SBob Moore 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
919c418ce19SBob Moore 	if (table_index < acpi_gbl_root_table_list.current_table_count) {
920c418ce19SBob Moore 		if (is_loaded) {
921c418ce19SBob Moore 			acpi_gbl_root_table_list.tables[table_index].flags |=
922c418ce19SBob Moore 			    ACPI_TABLE_IS_LOADED;
923c418ce19SBob Moore 		} else {
924c418ce19SBob Moore 			acpi_gbl_root_table_list.tables[table_index].flags &=
925c418ce19SBob Moore 			    ~ACPI_TABLE_IS_LOADED;
926c418ce19SBob Moore 		}
927c418ce19SBob Moore 	}
928c418ce19SBob Moore 
929c418ce19SBob Moore 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
930c418ce19SBob Moore }
931ac0f06ebSLv Zheng 
932ac0f06ebSLv Zheng /*******************************************************************************
933ac0f06ebSLv Zheng  *
934ac0f06ebSLv Zheng  * FUNCTION:    acpi_tb_load_table
935ac0f06ebSLv Zheng  *
936ac0f06ebSLv Zheng  * PARAMETERS:  table_index             - Table index
937ac0f06ebSLv Zheng  *              parent_node             - Where table index is returned
938ac0f06ebSLv Zheng  *
939ac0f06ebSLv Zheng  * RETURN:      Status
940ac0f06ebSLv Zheng  *
941ac0f06ebSLv Zheng  * DESCRIPTION: Load an ACPI table
942ac0f06ebSLv Zheng  *
943ac0f06ebSLv Zheng  ******************************************************************************/
944ac0f06ebSLv Zheng 
945ac0f06ebSLv Zheng acpi_status
acpi_tb_load_table(u32 table_index,struct acpi_namespace_node * parent_node)946ac0f06ebSLv Zheng acpi_tb_load_table(u32 table_index, struct acpi_namespace_node *parent_node)
947ac0f06ebSLv Zheng {
948ac0f06ebSLv Zheng 	struct acpi_table_header *table;
949ac0f06ebSLv Zheng 	acpi_status status;
950ac0f06ebSLv Zheng 	acpi_owner_id owner_id;
951ac0f06ebSLv Zheng 
952ac0f06ebSLv Zheng 	ACPI_FUNCTION_TRACE(tb_load_table);
953ac0f06ebSLv Zheng 
954ac0f06ebSLv Zheng 	/*
955ac0f06ebSLv Zheng 	 * Note: Now table is "INSTALLED", it must be validated before
956ac0f06ebSLv Zheng 	 * using.
957ac0f06ebSLv Zheng 	 */
958ac0f06ebSLv Zheng 	status = acpi_get_table_by_index(table_index, &table);
959ac0f06ebSLv Zheng 	if (ACPI_FAILURE(status)) {
960ac0f06ebSLv Zheng 		return_ACPI_STATUS(status);
961ac0f06ebSLv Zheng 	}
962ac0f06ebSLv Zheng 
963ac0f06ebSLv Zheng 	status = acpi_ns_load_table(table_index, parent_node);
964aaf7566fSBob Moore 	if (ACPI_FAILURE(status)) {
965aaf7566fSBob Moore 		return_ACPI_STATUS(status);
966aaf7566fSBob Moore 	}
967ac0f06ebSLv Zheng 
968a406dea8SBob Moore 	/*
969ac0f06ebSLv Zheng 	 * Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is
970ac0f06ebSLv Zheng 	 * responsible for discovering any new wake GPEs by running _PRW methods
971ac0f06ebSLv Zheng 	 * that may have been loaded by this table.
972ac0f06ebSLv Zheng 	 */
973ac0f06ebSLv Zheng 	status = acpi_tb_get_owner_id(table_index, &owner_id);
974ac0f06ebSLv Zheng 	if (ACPI_SUCCESS(status)) {
975ac0f06ebSLv Zheng 		acpi_ev_update_gpes(owner_id);
976ac0f06ebSLv Zheng 	}
977ac0f06ebSLv Zheng 
9789b019b0fSLv Zheng 	/* Invoke table handler */
979ac0f06ebSLv Zheng 
9809b019b0fSLv Zheng 	acpi_tb_notify_table(ACPI_TABLE_EVENT_LOAD, table);
981ac0f06ebSLv Zheng 	return_ACPI_STATUS(status);
982ac0f06ebSLv Zheng }
983ac0f06ebSLv Zheng 
984ac0f06ebSLv Zheng /*******************************************************************************
985ac0f06ebSLv Zheng  *
986ac0f06ebSLv Zheng  * FUNCTION:    acpi_tb_install_and_load_table
987ac0f06ebSLv Zheng  *
98842cc87a5SLv Zheng  * PARAMETERS:  address                 - Physical address of the table
989ac0f06ebSLv Zheng  *              flags                   - Allocation flags of the table
9905d6e5966SJessica Clarke  *              table                   - Pointer to the table (required for
9915d6e5966SJessica Clarke  *                                        virtual origins, optional for
9925d6e5966SJessica Clarke  *                                        physical)
99342cc87a5SLv Zheng  *              override                - Whether override should be performed
994ac0f06ebSLv Zheng  *              table_index             - Where table index is returned
995ac0f06ebSLv Zheng  *
996ac0f06ebSLv Zheng  * RETURN:      Status
997ac0f06ebSLv Zheng  *
998ac0f06ebSLv Zheng  * DESCRIPTION: Install and load an ACPI table
999ac0f06ebSLv Zheng  *
1000ac0f06ebSLv Zheng  ******************************************************************************/
1001ac0f06ebSLv Zheng 
1002ac0f06ebSLv Zheng acpi_status
acpi_tb_install_and_load_table(acpi_physical_address address,u8 flags,struct acpi_table_header * table,u8 override,u32 * table_index)100342cc87a5SLv Zheng acpi_tb_install_and_load_table(acpi_physical_address address,
10045d6e5966SJessica Clarke 			       u8 flags,
10055d6e5966SJessica Clarke 			       struct acpi_table_header *table,
10065d6e5966SJessica Clarke 			       u8 override, u32 *table_index)
1007ac0f06ebSLv Zheng {
1008ac0f06ebSLv Zheng 	acpi_status status;
1009ac0f06ebSLv Zheng 	u32 i;
1010ac0f06ebSLv Zheng 
101142cc87a5SLv Zheng 	ACPI_FUNCTION_TRACE(tb_install_and_load_table);
1012ac0f06ebSLv Zheng 
1013ac0f06ebSLv Zheng 	/* Install the table and load it into the namespace */
1014ac0f06ebSLv Zheng 
10155d6e5966SJessica Clarke 	status = acpi_tb_install_standard_table(address, flags, table, TRUE,
1016ac0f06ebSLv Zheng 						override, &i);
1017ac0f06ebSLv Zheng 	if (ACPI_FAILURE(status)) {
10187a37052aSLv Zheng 		goto exit;
1019ac0f06ebSLv Zheng 	}
1020ac0f06ebSLv Zheng 
102142cc87a5SLv Zheng 	status = acpi_tb_load_table(i, acpi_gbl_root_node);
1022ac0f06ebSLv Zheng 
10237a37052aSLv Zheng exit:
1024ac0f06ebSLv Zheng 	*table_index = i;
1025ac0f06ebSLv Zheng 	return_ACPI_STATUS(status);
1026ac0f06ebSLv Zheng }
1027170564d9SLv Zheng 
ACPI_EXPORT_SYMBOL(acpi_tb_install_and_load_table)1028772bf1e2SJan Kiszka ACPI_EXPORT_SYMBOL(acpi_tb_install_and_load_table)
1029772bf1e2SJan Kiszka 
1030170564d9SLv Zheng /*******************************************************************************
1031170564d9SLv Zheng  *
1032170564d9SLv Zheng  * FUNCTION:    acpi_tb_unload_table
1033170564d9SLv Zheng  *
1034170564d9SLv Zheng  * PARAMETERS:  table_index             - Table index
1035170564d9SLv Zheng  *
1036170564d9SLv Zheng  * RETURN:      Status
1037170564d9SLv Zheng  *
1038170564d9SLv Zheng  * DESCRIPTION: Unload an ACPI table
1039170564d9SLv Zheng  *
1040170564d9SLv Zheng  ******************************************************************************/
1041170564d9SLv Zheng 
1042170564d9SLv Zheng acpi_status acpi_tb_unload_table(u32 table_index)
1043170564d9SLv Zheng {
1044170564d9SLv Zheng 	acpi_status status = AE_OK;
1045170564d9SLv Zheng 	struct acpi_table_header *table;
1046170564d9SLv Zheng 
1047170564d9SLv Zheng 	ACPI_FUNCTION_TRACE(tb_unload_table);
1048170564d9SLv Zheng 
1049170564d9SLv Zheng 	/* Ensure the table is still loaded */
1050170564d9SLv Zheng 
1051170564d9SLv Zheng 	if (!acpi_tb_is_table_loaded(table_index)) {
1052170564d9SLv Zheng 		return_ACPI_STATUS(AE_NOT_EXIST);
1053170564d9SLv Zheng 	}
1054170564d9SLv Zheng 
10559b019b0fSLv Zheng 	/* Invoke table handler */
1056170564d9SLv Zheng 
1057170564d9SLv Zheng 	status = acpi_get_table_by_index(table_index, &table);
1058170564d9SLv Zheng 	if (ACPI_SUCCESS(status)) {
10599b019b0fSLv Zheng 		acpi_tb_notify_table(ACPI_TABLE_EVENT_UNLOAD, table);
1060170564d9SLv Zheng 	}
1061170564d9SLv Zheng 
1062170564d9SLv Zheng 	/* Delete the portion of the namespace owned by this table */
1063170564d9SLv Zheng 
1064170564d9SLv Zheng 	status = acpi_tb_delete_namespace_by_owner(table_index);
1065170564d9SLv Zheng 	if (ACPI_FAILURE(status)) {
1066170564d9SLv Zheng 		return_ACPI_STATUS(status);
1067170564d9SLv Zheng 	}
1068170564d9SLv Zheng 
1069170564d9SLv Zheng 	(void)acpi_tb_release_owner_id(table_index);
1070170564d9SLv Zheng 	acpi_tb_set_table_loaded_flag(table_index, FALSE);
1071170564d9SLv Zheng 	return_ACPI_STATUS(status);
1072170564d9SLv Zheng }
1073772bf1e2SJan Kiszka 
ACPI_EXPORT_SYMBOL(acpi_tb_unload_table)1074772bf1e2SJan Kiszka ACPI_EXPORT_SYMBOL(acpi_tb_unload_table)
10759b019b0fSLv Zheng 
10769b019b0fSLv Zheng /*******************************************************************************
10779b019b0fSLv Zheng  *
10789b019b0fSLv Zheng  * FUNCTION:    acpi_tb_notify_table
10799b019b0fSLv Zheng  *
10809b019b0fSLv Zheng  * PARAMETERS:  event               - Table event
10819b019b0fSLv Zheng  *              table               - Validated table pointer
10829b019b0fSLv Zheng  *
10839b019b0fSLv Zheng  * RETURN:      None
10849b019b0fSLv Zheng  *
10859b019b0fSLv Zheng  * DESCRIPTION: Notify a table event to the users.
10869b019b0fSLv Zheng  *
10879b019b0fSLv Zheng  ******************************************************************************/
10889b019b0fSLv Zheng 
10899b019b0fSLv Zheng void acpi_tb_notify_table(u32 event, void *table)
10909b019b0fSLv Zheng {
10919b019b0fSLv Zheng 	/* Invoke table handler if present */
10929b019b0fSLv Zheng 
10939b019b0fSLv Zheng 	if (acpi_gbl_table_handler) {
10949b019b0fSLv Zheng 		(void)acpi_gbl_table_handler(event, table,
10959b019b0fSLv Zheng 					     acpi_gbl_table_handler_context);
10969b019b0fSLv Zheng 	}
10979b019b0fSLv Zheng }
1098