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