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