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