1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
4 * Module Name: tbinstal - ACPI table installation and removal
6 * Copyright (C) 2000 - 2020, Intel Corp.
8 *****************************************************************************/
10 #include <acpi/acpi.h>
14 #define _COMPONENT ACPI_TABLES
15 ACPI_MODULE_NAME("tbinstal")
17 /*******************************************************************************
19 * FUNCTION: acpi_tb_install_table_with_override
21 * PARAMETERS: new_table_desc - New table descriptor to install
22 * override - Whether override should be performed
23 * table_index - Where the table index is returned
27 * DESCRIPTION: Install an ACPI table into the global data structure. The
28 * table override mechanism is called to allow the host
29 * OS to replace any table before it is installed in the root
32 ******************************************************************************/
34 acpi_tb_install_table_with_override(struct acpi_table_desc
*new_table_desc
,
35 u8 override
, u32
*table_index
)
40 status
= acpi_tb_get_next_table_descriptor(&i
, NULL
);
41 if (ACPI_FAILURE(status
)) {
46 * ACPI Table Override:
48 * Before we install the table, let the host OS override it with a new
49 * one if desired. Any table within the RSDT/XSDT can be replaced,
50 * including the DSDT which is pointed to by the FADT.
53 acpi_tb_override_table(new_table_desc
);
56 acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list
.tables
[i
],
57 new_table_desc
->address
,
58 new_table_desc
->flags
,
59 new_table_desc
->pointer
);
61 acpi_tb_print_table_header(new_table_desc
->address
,
62 new_table_desc
->pointer
);
64 /* This synchronizes acpi_gbl_dsdt_index */
68 /* Set the global integer width (based upon revision of the DSDT) */
70 if (i
== acpi_gbl_dsdt_index
) {
71 acpi_ut_set_integer_width(new_table_desc
->pointer
->revision
);
75 /*******************************************************************************
77 * FUNCTION: acpi_tb_install_standard_table
79 * PARAMETERS: address - Address of the table (might be a virtual
80 * address depending on the table_flags)
81 * flags - Flags for the table
82 * reload - Whether reload should be performed
83 * override - Whether override should be performed
84 * table_index - Where the table index is returned
88 * DESCRIPTION: This function is called to verify and install an ACPI table.
89 * When this function is called by "Load" or "LoadTable" opcodes,
90 * or by acpi_load_table() API, the "Reload" parameter is set.
91 * After successfully returning from this function, table is
92 * "INSTALLED" but not "VALIDATED".
94 ******************************************************************************/
97 acpi_tb_install_standard_table(acpi_physical_address address
,
99 u8 reload
, u8 override
, u32
*table_index
)
102 acpi_status status
= AE_OK
;
103 struct acpi_table_desc new_table_desc
;
105 ACPI_FUNCTION_TRACE(tb_install_standard_table
);
107 /* Acquire a temporary table descriptor for validation */
109 status
= acpi_tb_acquire_temp_table(&new_table_desc
, address
, flags
);
110 if (ACPI_FAILURE(status
)) {
112 "Could not acquire table length at %8.8X%8.8X",
113 ACPI_FORMAT_UINT64(address
)));
114 return_ACPI_STATUS(status
);
118 * Optionally do not load any SSDTs from the RSDT/XSDT. This can
119 * be useful for debugging ACPI problems on some machines.
122 acpi_gbl_disable_ssdt_table_install
&&
123 ACPI_COMPARE_NAMESEG(&new_table_desc
.signature
, ACPI_SIG_SSDT
)) {
124 ACPI_INFO(("Ignoring installation of %4.4s at %8.8X%8.8X",
125 new_table_desc
.signature
.ascii
,
126 ACPI_FORMAT_UINT64(address
)));
127 goto release_and_exit
;
130 /* Acquire the table lock */
132 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES
);
134 /* Validate and verify a table before installation */
136 status
= acpi_tb_verify_temp_table(&new_table_desc
, NULL
, &i
);
137 if (ACPI_FAILURE(status
)) {
138 if (status
== AE_CTRL_TERMINATE
) {
140 * Table was unloaded, allow it to be reloaded.
141 * As we are going to return AE_OK to the caller, we should
142 * take the responsibility of freeing the input descriptor.
143 * Refill the input descriptor to ensure
144 * acpi_tb_install_table_with_override() can be called again to
145 * indicate the re-installation.
147 acpi_tb_uninstall_table(&new_table_desc
);
148 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES
);
150 return_ACPI_STATUS(AE_OK
);
152 goto unlock_and_exit
;
155 /* Add the table to the global root table list */
157 acpi_tb_install_table_with_override(&new_table_desc
, override
,
160 /* Invoke table handler */
162 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES
);
163 acpi_tb_notify_table(ACPI_TABLE_EVENT_INSTALL
, new_table_desc
.pointer
);
164 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES
);
168 /* Release the table lock */
170 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES
);
174 /* Release the temporary table descriptor */
176 acpi_tb_release_temp_table(&new_table_desc
);
177 return_ACPI_STATUS(status
);
180 /*******************************************************************************
182 * FUNCTION: acpi_tb_override_table
184 * PARAMETERS: old_table_desc - Validated table descriptor to be
189 * DESCRIPTION: Attempt table override by calling the OSL override functions.
190 * Note: If the table is overridden, then the entire new table
191 * is acquired and returned by this function.
192 * Before/after invocation, the table descriptor is in a state
193 * that is "VALIDATED".
195 ******************************************************************************/
197 void acpi_tb_override_table(struct acpi_table_desc
*old_table_desc
)
200 struct acpi_table_desc new_table_desc
;
201 struct acpi_table_header
*table
;
202 acpi_physical_address address
;
204 ACPI_ERROR_ONLY(char *override_type
);
206 /* (1) Attempt logical override (returns a logical address) */
208 status
= acpi_os_table_override(old_table_desc
->pointer
, &table
);
209 if (ACPI_SUCCESS(status
) && table
) {
210 acpi_tb_acquire_temp_table(&new_table_desc
,
211 ACPI_PTR_TO_PHYSADDR(table
),
212 ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL
);
213 ACPI_ERROR_ONLY(override_type
= "Logical");
214 goto finish_override
;
217 /* (2) Attempt physical override (returns a physical address) */
219 status
= acpi_os_physical_table_override(old_table_desc
->pointer
,
221 if (ACPI_SUCCESS(status
) && address
&& length
) {
222 acpi_tb_acquire_temp_table(&new_table_desc
, address
,
223 ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL
);
224 ACPI_ERROR_ONLY(override_type
= "Physical");
225 goto finish_override
;
228 return; /* There was no override */
233 * Validate and verify a table before overriding, no nested table
234 * duplication check as it's too complicated and unnecessary.
236 status
= acpi_tb_verify_temp_table(&new_table_desc
, NULL
, NULL
);
237 if (ACPI_FAILURE(status
)) {
241 ACPI_INFO(("%4.4s 0x%8.8X%8.8X"
242 " %s table override, new table: 0x%8.8X%8.8X",
243 old_table_desc
->signature
.ascii
,
244 ACPI_FORMAT_UINT64(old_table_desc
->address
),
245 override_type
, ACPI_FORMAT_UINT64(new_table_desc
.address
)));
247 /* We can now uninstall the original table */
249 acpi_tb_uninstall_table(old_table_desc
);
252 * Replace the original table descriptor and keep its state as
255 acpi_tb_init_table_descriptor(old_table_desc
, new_table_desc
.address
,
256 new_table_desc
.flags
,
257 new_table_desc
.pointer
);
258 acpi_tb_validate_temp_table(old_table_desc
);
260 /* Release the temporary table descriptor */
262 acpi_tb_release_temp_table(&new_table_desc
);
265 /*******************************************************************************
267 * FUNCTION: acpi_tb_uninstall_table
269 * PARAMETERS: table_desc - Table descriptor
273 * DESCRIPTION: Delete one internal ACPI table
275 ******************************************************************************/
277 void acpi_tb_uninstall_table(struct acpi_table_desc
*table_desc
)
280 ACPI_FUNCTION_TRACE(tb_uninstall_table
);
282 /* Table must be installed */
284 if (!table_desc
->address
) {
288 acpi_tb_invalidate_table(table_desc
);
290 if ((table_desc
->flags
& ACPI_TABLE_ORIGIN_MASK
) ==
291 ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL
) {
292 ACPI_FREE(ACPI_PHYSADDR_TO_PTR(table_desc
->address
));
295 table_desc
->address
= ACPI_PTR_TO_PHYSADDR(NULL
);