brintos

brintos / linux-shallow public Read only

0
0
Text · 29.7 KiB · a1f10e4 Raw
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