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