Branch data Line data Source code
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 - 2020, 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 : 110 : acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index)
42 : : {
43 : 110 : acpi_status status = AE_OK;
44 : 110 : u8 is_identical;
45 : 110 : struct acpi_table_header *table;
46 : 110 : u32 table_length;
47 : 110 : u8 table_flags;
48 : :
49 : 110 : status =
50 : 110 : acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index],
51 : : &table, &table_length, &table_flags);
52 [ + - ]: 110 : 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 [ - + ]: 110 : is_identical = (u8)((table_desc->length != table_length ||
61 [ # # ]: 0 : memcmp(table_desc->pointer, table, table_length)) ?
62 : : FALSE : TRUE);
63 : :
64 : : /* Release the acquired table */
65 : :
66 : 110 : acpi_tb_release_table(table, table_length, table_flags);
67 : 110 : 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 : 110 : 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 : : */
95 : 110 : memset(table_desc, 0, sizeof(struct acpi_table_desc));
96 : 110 : table_desc->address = address;
97 : 110 : table_desc->length = table->length;
98 : 110 : table_desc->flags = flags;
99 : 110 : ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature);
100 : 110 : }
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 : 363 : 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 : 363 : struct acpi_table_header *table = NULL;
124 : :
125 [ + - - ]: 363 : switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
126 : 363 : case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
127 : :
128 : 363 : table =
129 : 363 : acpi_os_map_memory(table_desc->address, table_desc->length);
130 : 363 : break;
131 : :
132 : 0 : case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
133 : : case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
134 : :
135 : 0 : table = ACPI_CAST_PTR(struct acpi_table_header,
136 : : ACPI_PHYSADDR_TO_PTR(table_desc->
137 : : address));
138 : 0 : break;
139 : :
140 : : default:
141 : :
142 : : break;
143 : : }
144 : :
145 : : /* Table is not valid yet */
146 : :
147 [ - + ]: 363 : if (!table) {
148 : 0 : return (AE_NO_MEMORY);
149 : : }
150 : :
151 : : /* Fill the return values */
152 : :
153 : 363 : *table_ptr = table;
154 : 363 : *table_length = table_desc->length;
155 : 363 : *table_flags = table_desc->flags;
156 : 363 : 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 : 308 : acpi_tb_release_table(struct acpi_table_header *table,
175 : : u32 table_length, u8 table_flags)
176 : : {
177 : :
178 [ + - ]: 308 : switch (table_flags & ACPI_TABLE_ORIGIN_MASK) {
179 : 308 : case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
180 : :
181 : 308 : acpi_os_unmap_memory(table, table_length);
182 : 308 : break;
183 : :
184 : : case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
185 : : case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
186 : : default:
187 : :
188 : : break;
189 : : }
190 : 308 : }
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 : 55 : acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc,
211 : : acpi_physical_address address, u8 flags)
212 : : {
213 : 55 : struct acpi_table_header *table_header;
214 : :
215 [ + - - ]: 55 : switch (flags & ACPI_TABLE_ORIGIN_MASK) {
216 : 55 : case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
217 : :
218 : : /* Get the length of the full table from the header */
219 : :
220 : 55 : table_header =
221 : 55 : acpi_os_map_memory(address,
222 : : sizeof(struct acpi_table_header));
223 [ + - ]: 55 : if (!table_header) {
224 : : return (AE_NO_MEMORY);
225 : : }
226 : :
227 : 55 : acpi_tb_init_table_descriptor(table_desc, address, flags,
228 : : table_header);
229 : 55 : acpi_os_unmap_memory(table_header,
230 : : sizeof(struct acpi_table_header));
231 : 55 : return (AE_OK);
232 : :
233 : 0 : case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
234 : : case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
235 : :
236 : 0 : table_header = ACPI_CAST_PTR(struct acpi_table_header,
237 : : ACPI_PHYSADDR_TO_PTR(address));
238 [ # # ]: 0 : if (!table_header) {
239 : : return (AE_NO_MEMORY);
240 : : }
241 : :
242 : 0 : acpi_tb_init_table_descriptor(table_desc, address, flags,
243 : : table_header);
244 : 0 : 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 : 55 : 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 : 55 : acpi_tb_invalidate_table(table_desc);
277 : 55 : }
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 : 319 : acpi_status acpi_tb_validate_table(struct acpi_table_desc *table_desc)
293 : : {
294 : 319 : acpi_status status = AE_OK;
295 : :
296 : 319 : ACPI_FUNCTION_TRACE(tb_validate_table);
297 : :
298 : : /* Validate the table if necessary */
299 : :
300 [ + + ]: 319 : if (!table_desc->pointer) {
301 : 253 : status = acpi_tb_acquire_table(table_desc, &table_desc->pointer,
302 : : &table_desc->length,
303 : : &table_desc->flags);
304 [ - + ]: 253 : if (!table_desc->pointer) {
305 : 0 : status = AE_NO_MEMORY;
306 : : }
307 : : }
308 : :
309 : 319 : 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 : 198 : void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc)
326 : : {
327 : :
328 : 198 : ACPI_FUNCTION_TRACE(tb_invalidate_table);
329 : :
330 : : /* Table must be validated */
331 : :
332 [ + - ]: 198 : if (!table_desc->pointer) {
333 : : return_VOID;
334 : : }
335 : :
336 : 198 : acpi_tb_release_table(table_desc->pointer, table_desc->length,
337 : 198 : table_desc->flags);
338 : 198 : table_desc->pointer = NULL;
339 : :
340 : 198 : return_VOID;
341 : : }
342 : :
343 : : /******************************************************************************
344 : : *
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 : 110 : acpi_status acpi_tb_validate_temp_table(struct acpi_table_desc *table_desc)
357 : : {
358 : :
359 [ + - + + ]: 110 : if (!table_desc->pointer && !acpi_gbl_enable_table_validation) {
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 : 55 : table_desc->length = sizeof(struct acpi_table_header);
370 : : }
371 : :
372 : 110 : return (acpi_tb_validate_table(table_desc));
373 : : }
374 : :
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 : 55 : acpi_tb_check_duplication(struct acpi_table_desc *table_desc, u32 *table_index)
393 : : {
394 : 55 : u32 i;
395 : :
396 : 55 : ACPI_FUNCTION_TRACE(tb_check_duplication);
397 : :
398 : : /* Check if table is already registered */
399 : :
400 [ + + ]: 330 : for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
401 : :
402 : : /* Do not compare with unverified tables */
403 : :
404 : 275 : if (!
405 [ + + ]: 275 : (acpi_gbl_root_table_list.tables[i].
406 : : flags & ACPI_TABLE_IS_VERIFIED)) {
407 : 165 : continue;
408 : : }
409 : :
410 : : /*
411 : : * Check for a table match on the entire table length,
412 : : * not just the header.
413 : : */
414 [ + - ]: 110 : if (!acpi_tb_compare_tables(table_desc, i)) {
415 : 110 : 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 [ # # ]: 0 : 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 : 0 : *table_index = i;
440 : 0 : 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 : :
449 : : /******************************************************************************
450 : : *
451 : : * FUNCTION: acpi_tb_verify_temp_table
452 : : *
453 : : * PARAMETERS: table_desc - Table descriptor
454 : : * signature - Table signature to verify
455 : : * table_index - Where the table index is returned
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.
461 : : * Note that 'TableIndex' is required to be set to !NULL to
462 : : * enable duplication check.
463 : : *
464 : : *****************************************************************************/
465 : :
466 : : acpi_status
467 : 110 : acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc,
468 : : char *signature, u32 *table_index)
469 : : {
470 : 110 : acpi_status status = AE_OK;
471 : :
472 : 110 : ACPI_FUNCTION_TRACE(tb_verify_temp_table);
473 : :
474 : : /* Validate the table */
475 : :
476 : 110 : status = acpi_tb_validate_temp_table(table_desc);
477 [ + - ]: 110 : 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 : :
483 [ - + ]: 110 : if (signature &&
484 [ # # ]: 0 : !ACPI_COMPARE_NAMESEG(&table_desc->signature, signature)) {
485 : 0 : ACPI_BIOS_ERROR((AE_INFO,
486 : : "Invalid signature 0x%X for ACPI table, expected [%s]",
487 : : table_desc->signature.integer, signature));
488 : 0 : status = AE_BAD_SIGNATURE;
489 : 0 : goto invalidate_and_exit;
490 : : }
491 : :
492 [ + + ]: 110 : if (acpi_gbl_enable_table_validation) {
493 : :
494 : : /* Verify the checksum */
495 : :
496 : 55 : status =
497 : 55 : acpi_tb_verify_checksum(table_desc->pointer,
498 : : table_desc->length);
499 [ - + ]: 55 : if (ACPI_FAILURE(status)) {
500 [ # # ]: 0 : ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
501 : : "%4.4s 0x%8.8X%8.8X"
502 : : " Attempted table install failed",
503 : : acpi_ut_valid_nameseg(table_desc->
504 : : signature.
505 : : ascii) ?
506 : : table_desc->signature.ascii : "????",
507 : : ACPI_FORMAT_UINT64(table_desc->
508 : : address)));
509 : :
510 : 0 : goto invalidate_and_exit;
511 : : }
512 : :
513 : : /* Avoid duplications */
514 : :
515 [ + - ]: 55 : if (table_index) {
516 : 55 : status =
517 : 55 : acpi_tb_check_duplication(table_desc, table_index);
518 [ - + ]: 55 : if (ACPI_FAILURE(status)) {
519 [ # # ]: 0 : if (status != AE_CTRL_TERMINATE) {
520 [ # # ]: 0 : ACPI_EXCEPTION((AE_INFO, status,
521 : : "%4.4s 0x%8.8X%8.8X"
522 : : " Table is already loaded",
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 : 0 : goto invalidate_and_exit;
533 : : }
534 : : }
535 : :
536 : 55 : table_desc->flags |= ACPI_TABLE_IS_VERIFIED;
537 : : }
538 : :
539 : : return_ACPI_STATUS(status);
540 : :
541 : 0 : invalidate_and_exit:
542 : 0 : acpi_tb_invalidate_table(table_desc);
543 : 0 : 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 : 11 : acpi_status acpi_tb_resize_root_table_list(void)
559 : : {
560 : 11 : struct acpi_table_desc *tables;
561 : 11 : u32 table_count;
562 : 11 : u32 current_table_count, max_table_count;
563 : 11 : u32 i;
564 : :
565 : 11 : ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
566 : :
567 : : /* allow_resize flag is a parameter to acpi_initialize_tables */
568 : :
569 [ - + ]: 11 : if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) {
570 : 0 : ACPI_ERROR((AE_INFO,
571 : : "Resize of Root Table Array is not allowed"));
572 : 0 : return_ACPI_STATUS(AE_SUPPORT);
573 : : }
574 : :
575 : : /* Increase the Table Array size */
576 : :
577 [ - + ]: 11 : if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
578 : 0 : table_count = acpi_gbl_root_table_list.max_table_count;
579 : : } else {
580 : 11 : table_count = acpi_gbl_root_table_list.current_table_count;
581 : : }
582 : :
583 : 11 : max_table_count = table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT;
584 : 11 : tables = ACPI_ALLOCATE_ZEROED(((acpi_size)max_table_count) *
585 : : sizeof(struct acpi_table_desc));
586 [ - + ]: 11 : if (!tables) {
587 : 0 : ACPI_ERROR((AE_INFO,
588 : : "Could not allocate new root table array"));
589 : 0 : return_ACPI_STATUS(AE_NO_MEMORY);
590 : : }
591 : :
592 : : /* Copy and free the previous table array */
593 : :
594 : 11 : current_table_count = 0;
595 [ + - ]: 11 : if (acpi_gbl_root_table_list.tables) {
596 [ + + ]: 66 : for (i = 0; i < table_count; i++) {
597 [ + - ]: 55 : if (acpi_gbl_root_table_list.tables[i].address) {
598 : 55 : memcpy(tables + current_table_count,
599 : : acpi_gbl_root_table_list.tables + i,
600 : : sizeof(struct acpi_table_desc));
601 : 55 : current_table_count++;
602 : : }
603 : : }
604 : :
605 [ - + ]: 11 : if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
606 : 0 : ACPI_FREE(acpi_gbl_root_table_list.tables);
607 : : }
608 : : }
609 : :
610 : 11 : acpi_gbl_root_table_list.tables = tables;
611 : 11 : acpi_gbl_root_table_list.max_table_count = max_table_count;
612 : 11 : acpi_gbl_root_table_list.current_table_count = current_table_count;
613 : 11 : acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
614 : :
615 : 11 : return_ACPI_STATUS(AE_OK);
616 : : }
617 : :
618 : : /*******************************************************************************
619 : : *
620 : : * FUNCTION: acpi_tb_get_next_table_descriptor
621 : : *
622 : : * PARAMETERS: table_index - Where table index is returned
623 : : * table_desc - Where table descriptor is returned
624 : : *
625 : : * RETURN: Status and table index/descriptor.
626 : : *
627 : : * DESCRIPTION: Allocate a new ACPI table entry to the global table list
628 : : *
629 : : ******************************************************************************/
630 : :
631 : : acpi_status
632 : 55 : acpi_tb_get_next_table_descriptor(u32 *table_index,
633 : : struct acpi_table_desc **table_desc)
634 : : {
635 : 55 : acpi_status status;
636 : 55 : u32 i;
637 : :
638 : : /* Ensure that there is room for the table in the Root Table List */
639 : :
640 : 55 : if (acpi_gbl_root_table_list.current_table_count >=
641 [ - + ]: 55 : acpi_gbl_root_table_list.max_table_count) {
642 : 0 : status = acpi_tb_resize_root_table_list();
643 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
644 : : return (status);
645 : : }
646 : : }
647 : :
648 : 55 : i = acpi_gbl_root_table_list.current_table_count;
649 : 55 : acpi_gbl_root_table_list.current_table_count++;
650 : :
651 [ + - ]: 55 : if (table_index) {
652 : 55 : *table_index = i;
653 : : }
654 [ - + ]: 55 : if (table_desc) {
655 : 0 : *table_desc = &acpi_gbl_root_table_list.tables[i];
656 : : }
657 : :
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 : 0 : void acpi_tb_terminate(void)
674 : : {
675 : 0 : u32 i;
676 : :
677 : 0 : ACPI_FUNCTION_TRACE(tb_terminate);
678 : :
679 : 0 : (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
680 : :
681 : : /* Delete the individual tables */
682 : :
683 [ # # ]: 0 : for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
684 : 0 : 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 [ # # ]: 0 : if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
692 : 0 : ACPI_FREE(acpi_gbl_root_table_list.tables);
693 : : }
694 : :
695 : 0 : acpi_gbl_root_table_list.tables = NULL;
696 : 0 : acpi_gbl_root_table_list.flags = 0;
697 : 0 : acpi_gbl_root_table_list.current_table_count = 0;
698 : :
699 : 0 : ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
700 : :
701 : 0 : (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
702 : 0 : 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 : 0 : acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index)
718 : : {
719 : 0 : acpi_owner_id owner_id;
720 : 0 : acpi_status status;
721 : :
722 : 0 : ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner);
723 : :
724 : 0 : status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
725 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
726 : : return_ACPI_STATUS(status);
727 : : }
728 : :
729 [ # # ]: 0 : if (table_index >= acpi_gbl_root_table_list.current_table_count) {
730 : :
731 : : /* The table index does not exist */
732 : :
733 : 0 : (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
734 : 0 : return_ACPI_STATUS(AE_NOT_EXIST);
735 : : }
736 : :
737 : : /* Get the owner ID for this table, used to delete namespace nodes */
738 : :
739 : 0 : owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id;
740 : 0 : (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 : : */
749 : 0 : status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock);
750 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
751 : : return_ACPI_STATUS(status);
752 : : }
753 : :
754 : 0 : acpi_ns_delete_namespace_by_owner(owner_id);
755 : 0 : acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock);
756 : 0 : 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 : 11 : acpi_status acpi_tb_allocate_owner_id(u32 table_index)
772 : : {
773 : 11 : acpi_status status = AE_BAD_PARAMETER;
774 : :
775 : 11 : ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
776 : :
777 : 11 : (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
778 [ + - ]: 11 : if (table_index < acpi_gbl_root_table_list.current_table_count) {
779 : 11 : status =
780 : 11 : acpi_ut_allocate_owner_id(&
781 : 11 : (acpi_gbl_root_table_list.
782 : 11 : tables[table_index].owner_id));
783 : : }
784 : :
785 : 11 : (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
786 : 11 : 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 : 0 : acpi_status acpi_tb_release_owner_id(u32 table_index)
802 : : {
803 : 0 : acpi_status status = AE_BAD_PARAMETER;
804 : :
805 : 0 : ACPI_FUNCTION_TRACE(tb_release_owner_id);
806 : :
807 : 0 : (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
808 [ # # ]: 0 : if (table_index < acpi_gbl_root_table_list.current_table_count) {
809 : 0 : acpi_ut_release_owner_id(&
810 : 0 : (acpi_gbl_root_table_list.
811 : 0 : tables[table_index].owner_id));
812 : 0 : status = AE_OK;
813 : : }
814 : :
815 : 0 : (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
816 : 0 : 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 : :
832 : 22 : acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id)
833 : : {
834 : 22 : acpi_status status = AE_BAD_PARAMETER;
835 : :
836 : 22 : ACPI_FUNCTION_TRACE(tb_get_owner_id);
837 : :
838 : 22 : (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
839 [ + - ]: 22 : if (table_index < acpi_gbl_root_table_list.current_table_count) {
840 : 22 : *owner_id =
841 : 22 : acpi_gbl_root_table_list.tables[table_index].owner_id;
842 : 22 : status = AE_OK;
843 : : }
844 : :
845 : 22 : (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
846 : 22 : 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 : 11 : u8 acpi_tb_is_table_loaded(u32 table_index)
860 : : {
861 : 11 : u8 is_loaded = FALSE;
862 : :
863 : 11 : (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
864 [ + - ]: 11 : if (table_index < acpi_gbl_root_table_list.current_table_count) {
865 : 11 : is_loaded = (u8)
866 : 11 : (acpi_gbl_root_table_list.tables[table_index].flags &
867 : : ACPI_TABLE_IS_LOADED);
868 : : }
869 : :
870 : 11 : (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
871 : 11 : 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 : 11 : void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded)
888 : : {
889 : :
890 : 11 : (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
891 [ + - ]: 11 : if (table_index < acpi_gbl_root_table_list.current_table_count) {
892 [ + - ]: 11 : if (is_loaded) {
893 : 11 : acpi_gbl_root_table_list.tables[table_index].flags |=
894 : : ACPI_TABLE_IS_LOADED;
895 : : } else {
896 : 0 : acpi_gbl_root_table_list.tables[table_index].flags &=
897 : : ~ACPI_TABLE_IS_LOADED;
898 : : }
899 : : }
900 : :
901 : 11 : (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
902 : 11 : }
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 : 0 : acpi_tb_load_table(u32 table_index, struct acpi_namespace_node *parent_node)
919 : : {
920 : 0 : struct acpi_table_header *table;
921 : 0 : acpi_status status;
922 : 0 : acpi_owner_id owner_id;
923 : :
924 : 0 : ACPI_FUNCTION_TRACE(tb_load_table);
925 : :
926 : : /*
927 : : * Note: Now table is "INSTALLED", it must be validated before
928 : : * using.
929 : : */
930 : 0 : status = acpi_get_table_by_index(table_index, &table);
931 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
932 : : return_ACPI_STATUS(status);
933 : : }
934 : :
935 : 0 : status = acpi_ns_load_table(table_index, parent_node);
936 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
937 : : return_ACPI_STATUS(status);
938 : : }
939 : :
940 : : /*
941 : : * Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is
942 : : * responsible for discovering any new wake GPEs by running _PRW methods
943 : : * that may have been loaded by this table.
944 : : */
945 : 0 : status = acpi_tb_get_owner_id(table_index, &owner_id);
946 [ # # ]: 0 : if (ACPI_SUCCESS(status)) {
947 : 0 : acpi_ev_update_gpes(owner_id);
948 : : }
949 : :
950 : : /* Invoke table handler */
951 : :
952 : 0 : acpi_tb_notify_table(ACPI_TABLE_EVENT_LOAD, table);
953 : 0 : return_ACPI_STATUS(status);
954 : : }
955 : :
956 : : /*******************************************************************************
957 : : *
958 : : * FUNCTION: acpi_tb_install_and_load_table
959 : : *
960 : : * PARAMETERS: address - Physical address of the table
961 : : * flags - Allocation flags of the table
962 : : * override - Whether override should be performed
963 : : * table_index - Where table index is returned
964 : : *
965 : : * RETURN: Status
966 : : *
967 : : * DESCRIPTION: Install and load an ACPI table
968 : : *
969 : : ******************************************************************************/
970 : :
971 : : acpi_status
972 : 0 : acpi_tb_install_and_load_table(acpi_physical_address address,
973 : : u8 flags, u8 override, u32 *table_index)
974 : : {
975 : 0 : acpi_status status;
976 : 0 : u32 i;
977 : :
978 : 0 : ACPI_FUNCTION_TRACE(tb_install_and_load_table);
979 : :
980 : : /* Install the table and load it into the namespace */
981 : :
982 : 0 : status = acpi_tb_install_standard_table(address, flags, TRUE,
983 : : override, &i);
984 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
985 : 0 : goto exit;
986 : : }
987 : :
988 : 0 : status = acpi_tb_load_table(i, acpi_gbl_root_node);
989 : :
990 : 0 : exit:
991 : 0 : *table_index = i;
992 : 0 : return_ACPI_STATUS(status);
993 : : }
994 : :
995 : : ACPI_EXPORT_SYMBOL(acpi_tb_install_and_load_table)
996 : :
997 : : /*******************************************************************************
998 : : *
999 : : * FUNCTION: acpi_tb_unload_table
1000 : : *
1001 : : * PARAMETERS: table_index - Table index
1002 : : *
1003 : : * RETURN: Status
1004 : : *
1005 : : * DESCRIPTION: Unload an ACPI table
1006 : : *
1007 : : ******************************************************************************/
1008 : :
1009 : 0 : acpi_status acpi_tb_unload_table(u32 table_index)
1010 : : {
1011 : 0 : acpi_status status = AE_OK;
1012 : 0 : struct acpi_table_header *table;
1013 : :
1014 : 0 : ACPI_FUNCTION_TRACE(tb_unload_table);
1015 : :
1016 : : /* Ensure the table is still loaded */
1017 : :
1018 [ # # ]: 0 : if (!acpi_tb_is_table_loaded(table_index)) {
1019 : : return_ACPI_STATUS(AE_NOT_EXIST);
1020 : : }
1021 : :
1022 : : /* Invoke table handler */
1023 : :
1024 : 0 : status = acpi_get_table_by_index(table_index, &table);
1025 [ # # ]: 0 : if (ACPI_SUCCESS(status)) {
1026 : 0 : acpi_tb_notify_table(ACPI_TABLE_EVENT_UNLOAD, table);
1027 : : }
1028 : :
1029 : : /* Delete the portion of the namespace owned by this table */
1030 : :
1031 : 0 : status = acpi_tb_delete_namespace_by_owner(table_index);
1032 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
1033 : : return_ACPI_STATUS(status);
1034 : : }
1035 : :
1036 : 0 : (void)acpi_tb_release_owner_id(table_index);
1037 : 0 : acpi_tb_set_table_loaded_flag(table_index, FALSE);
1038 : 0 : return_ACPI_STATUS(status);
1039 : : }
1040 : :
1041 : : ACPI_EXPORT_SYMBOL(acpi_tb_unload_table)
1042 : :
1043 : : /*******************************************************************************
1044 : : *
1045 : : * FUNCTION: acpi_tb_notify_table
1046 : : *
1047 : : * PARAMETERS: event - Table event
1048 : : * table - Validated table pointer
1049 : : *
1050 : : * RETURN: None
1051 : : *
1052 : : * DESCRIPTION: Notify a table event to the users.
1053 : : *
1054 : : ******************************************************************************/
1055 : :
1056 : 55 : void acpi_tb_notify_table(u32 event, void *table)
1057 : : {
1058 : : /* Invoke table handler if present */
1059 : :
1060 [ - + ]: 55 : if (acpi_gbl_table_handler) {
1061 : 0 : (void)acpi_gbl_table_handler(event, table,
1062 : : acpi_gbl_table_handler_context);
1063 : : }
1064 : 55 : }
|