1098 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: tbdata - Table manager data structure functions5 *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_TABLES17ACPI_MODULE_NAME("tbdata")18 19/* Local prototypes */20static acpi_status21acpi_tb_check_duplication(struct acpi_table_desc *table_desc, u32 *table_index);22 23static u824acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index);25 26/*******************************************************************************27 *28 * FUNCTION: acpi_tb_compare_tables29 *30 * PARAMETERS: table_desc - Table 1 descriptor to be compared31 * table_index - Index of table 2 to be compared32 *33 * RETURN: TRUE if both tables are identical.34 *35 * DESCRIPTION: This function compares a table with another table that has36 * already been installed in the root table list.37 *38 ******************************************************************************/39 40static u841acpi_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 70/*******************************************************************************71 *72 * FUNCTION: acpi_tb_init_table_descriptor73 *74 * PARAMETERS: table_desc - Table descriptor75 * address - Physical address of the table76 * flags - Allocation flags of the table77 * table - Pointer to the table78 *79 * RETURN: None80 *81 * DESCRIPTION: Initialize a new table descriptor82 *83 ******************************************************************************/84 85void86acpi_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 external93 * 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_table118 *119 * PARAMETERS: table_desc - Table descriptor120 * table_ptr - Where table is returned121 * table_length - Where table length is returned122 * table_flags - Where table allocation flags are returned123 *124 * RETURN: Status125 *126 * DESCRIPTION: Acquire an ACPI table. It can be used for tables not127 * maintained in the acpi_gbl_root_table_list.128 *129 ******************************************************************************/130 131acpi_status132acpi_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(table_desc->address, 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_table173 *174 * PARAMETERS: table - Pointer for the table175 * table_length - Length for the table176 * table_flags - Allocation flags for the table177 *178 * RETURN: None179 *180 * DESCRIPTION: Release a table. The inverse of acpi_tb_acquire_table().181 *182 ******************************************************************************/183 184void185acpi_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(table, 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_table206 *207 * PARAMETERS: table_desc - Table descriptor to be acquired208 * address - Address of the table209 * flags - Allocation flags of the table210 * table - Pointer to the table (required for virtual211 * origins, optional for physical)212 *213 * RETURN: Status214 *215 * DESCRIPTION: This function validates the table header to obtain the length216 * of a table and fills the table descriptor to make its state as217 * "INSTALLED". Such a table descriptor is only used for verified218 * installation.219 *220 ******************************************************************************/221 222acpi_status223acpi_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(address,237 sizeof(struct238 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(table, sizeof(struct acpi_table_header));267 }268 269 return (AE_OK);270}271 272/*******************************************************************************273 *274 * FUNCTION: acpi_tb_release_temp_table275 *276 * PARAMETERS: table_desc - Table descriptor to be released277 *278 * RETURN: Status279 *280 * DESCRIPTION: The inverse of acpi_tb_acquire_temp_table().281 *282 *****************************************************************************/283 284void acpi_tb_release_temp_table(struct acpi_table_desc *table_desc)285{286 287 /*288 * Note that the .Address is maintained by the callers of289 * 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_table298 *299 * PARAMETERS: table_desc - Table descriptor300 *301 * RETURN: Status302 *303 * DESCRIPTION: This function is called to validate the table, the returned304 * table descriptor is in "VALIDATED" state.305 *306 *****************************************************************************/307 308acpi_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_desc->pointer,318 &table_desc->length,319 &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_table331 *332 * PARAMETERS: table_desc - Table descriptor333 *334 * RETURN: None335 *336 * DESCRIPTION: Invalidate one internal ACPI table, this is the inverse of337 * acpi_tb_validate_table().338 *339 ******************************************************************************/340 341void 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_desc->pointer, table_desc->length,353 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_table374 *375 * PARAMETERS: table_desc - Table descriptor376 *377 * RETURN: Status378 *379 * DESCRIPTION: This function is called to validate the table, the returned380 * table descriptor is in "VALIDATED" state.381 *382 *****************************************************************************/383 384acpi_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 invoking391 * this work around, this value is required by392 * acpi_tb_release_temp_table().393 * We can do this because in acpi_init_table_descriptor(), the Length394 * field of the installed descriptor is filled with the actual395 * 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_duplication406 *407 * PARAMETERS: table_desc - Table descriptor408 * table_index - Where the table index is returned409 *410 * RETURN: Status411 *412 * DESCRIPTION: Avoid installing duplicated tables. However table override and413 * user aided dynamic table load is allowed, thus comparing the414 * address of the table is not sufficient, and checking the entire415 * table content is required.416 *417 ******************************************************************************/418 419static acpi_status420acpi_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, i)) {443 continue;444 }445 446 /*447 * Note: the current mechanism does not unregister a table if it is448 * 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 that452 * will be loaded is actually small, and there is minimal overhead453 * in just keeping the table in case it is needed again.454 *455 * If this assumption changes in the future (perhaps on large456 * machines with many table load/unload operations), tables will457 * need to be unregistered when they are unloaded, and slots in the458 * 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_table480 *481 * PARAMETERS: table_desc - Table descriptor482 * signature - Table signature to verify483 * table_index - Where the table index is returned484 *485 * RETURN: Status486 *487 * DESCRIPTION: This function is called to validate and verify the table, the488 * returned table descriptor is in "VALIDATED" state.489 * Note that 'TableIndex' is required to be set to !NULL to490 * enable duplication check.491 *492 *****************************************************************************/493 494acpi_status495acpi_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_desc->pointer,526 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_nameseg552 (table_desc->signature.553 ascii) ? table_desc->554 signature.555 ascii : "????",556 ACPI_FORMAT_UINT64557 (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 569invalidate_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_list577 *578 * PARAMETERS: None579 *580 * RETURN: Status581 *582 * DESCRIPTION: Expand the size of global table array583 *584 ******************************************************************************/585 586acpi_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_descriptor649 *650 * PARAMETERS: table_index - Where table index is returned651 * table_desc - Where table descriptor is returned652 *653 * RETURN: Status and table index/descriptor.654 *655 * DESCRIPTION: Allocate a new ACPI table entry to the global table list656 *657 ******************************************************************************/658 659acpi_status660acpi_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_terminate692 *693 * PARAMETERS: None694 *695 * RETURN: None696 *697 * DESCRIPTION: Delete all internal ACPI tables698 *699 ******************************************************************************/700 701void 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(&acpi_gbl_root_table_list.tables[i]);713 }714 715 /*716 * Delete the root table array if allocated locally. Array cannot be717 * 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_owner736 *737 * PARAMETERS: table_index - Table index738 *739 * RETURN: Status740 *741 * DESCRIPTION: Delete all namespace objects created when this table was loaded.742 *743 ******************************************************************************/744 745acpi_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 interference772 * with any concurrent namespace walks. The interpreter must be773 * released during the deletion since the acquisition of the deletion774 * lock may block, and also since the execution of a namespace walk775 * must be allowed to use the interpreter.776 */777 status = acpi_ut_acquire_write_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(&acpi_gbl_namespace_rw_lock);784 return_ACPI_STATUS(status);785}786 787/*******************************************************************************788 *789 * FUNCTION: acpi_tb_allocate_owner_id790 *791 * PARAMETERS: table_index - Table index792 *793 * RETURN: Status794 *795 * DESCRIPTION: Allocates owner_id in table_desc796 *797 ******************************************************************************/798 799acpi_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(&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_id820 *821 * PARAMETERS: table_index - Table index822 *823 * RETURN: Status824 *825 * DESCRIPTION: Releases owner_id in table_desc826 *827 ******************************************************************************/828 829acpi_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(&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_id850 *851 * PARAMETERS: table_index - Table index852 * owner_id - Where the table owner_id is returned853 *854 * RETURN: Status855 *856 * DESCRIPTION: returns owner_id for the ACPI table857 *858 ******************************************************************************/859 860acpi_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_loaded880 *881 * PARAMETERS: table_index - Index into the root table882 *883 * RETURN: Table Loaded Flag884 *885 ******************************************************************************/886 887u8 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_flag905 *906 * PARAMETERS: table_index - Table index907 * is_loaded - TRUE if table is loaded, FALSE otherwise908 *909 * RETURN: None910 *911 * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.912 *913 ******************************************************************************/914 915void 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_table935 *936 * PARAMETERS: table_index - Table index937 * parent_node - Where table index is returned938 *939 * RETURN: Status940 *941 * DESCRIPTION: Load an ACPI table942 *943 ******************************************************************************/944 945acpi_status946acpi_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 before956 * using.957 */958 status = acpi_get_table_by_index(table_index, &table);959 if (ACPI_FAILURE(status)) {960 return_ACPI_STATUS(status);961 }962 963 status = acpi_ns_load_table(table_index, 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 is970 * responsible for discovering any new wake GPEs by running _PRW methods971 * that may have been loaded by this table.972 */973 status = acpi_tb_get_owner_id(table_index, &owner_id);974 if (ACPI_SUCCESS(status)) {975 acpi_ev_update_gpes(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_table987 *988 * PARAMETERS: address - Physical address of the table989 * flags - Allocation flags of the table990 * table - Pointer to the table (required for991 * virtual origins, optional for992 * physical)993 * override - Whether override should be performed994 * table_index - Where table index is returned995 *996 * RETURN: Status997 *998 * DESCRIPTION: Install and load an ACPI table999 *1000 ******************************************************************************/1001 1002acpi_status1003acpi_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, &i);1017 if (ACPI_FAILURE(status)) {1018 goto exit;1019 }1020 1021 status = acpi_tb_load_table(i, acpi_gbl_root_node);1022 1023exit:1024 *table_index = i;1025 return_ACPI_STATUS(status);1026}1027 1028ACPI_EXPORT_SYMBOL(acpi_tb_install_and_load_table)1029 1030/*******************************************************************************1031 *1032 * FUNCTION: acpi_tb_unload_table1033 *1034 * PARAMETERS: table_index - Table index1035 *1036 * RETURN: Status1037 *1038 * DESCRIPTION: Unload an ACPI table1039 *1040 ******************************************************************************/1041 1042acpi_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, &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 1074ACPI_EXPORT_SYMBOL(acpi_tb_unload_table)1075 1076/*******************************************************************************1077 *1078 * FUNCTION: acpi_tb_notify_table1079 *1080 * PARAMETERS: event - Table event1081 * table - Validated table pointer1082 *1083 * RETURN: None1084 *1085 * DESCRIPTION: Notify a table event to the users.1086 *1087 ******************************************************************************/1088 1089void 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