1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3 *
4 * Module Name: tbinstal - ACPI table installation and removal
5 *
6 * Copyright (C) 2000 - 2021, Intel Corp.
7 *
8 *****************************************************************************/
9
10 #include <acpi/acpi.h>
11 #include "accommon.h"
12 #include "actables.h"
13
14 #define _COMPONENT ACPI_TABLES
15 ACPI_MODULE_NAME("tbinstal")
16
17 /*******************************************************************************
18 *
19 * FUNCTION: acpi_tb_install_table_with_override
20 *
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
24 *
25 * RETURN: None
26 *
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
30 * table array.
31 *
32 ******************************************************************************/
33 void
acpi_tb_install_table_with_override(struct acpi_table_desc * new_table_desc,u8 override,u32 * table_index)34 acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc,
35 u8 override, u32 *table_index)
36 {
37 u32 i;
38 acpi_status status;
39
40 status = acpi_tb_get_next_table_descriptor(&i, NULL);
41 if (ACPI_FAILURE(status)) {
42 return;
43 }
44
45 /*
46 * ACPI Table Override:
47 *
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.
51 */
52 if (override) {
53 acpi_tb_override_table(new_table_desc);
54 }
55
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);
60
61 acpi_tb_print_table_header(new_table_desc->address,
62 new_table_desc->pointer);
63
64 /* This synchronizes acpi_gbl_dsdt_index */
65
66 *table_index = i;
67
68 /* Set the global integer width (based upon revision of the DSDT) */
69
70 if (i == acpi_gbl_dsdt_index) {
71 acpi_ut_set_integer_width(new_table_desc->pointer->revision);
72 }
73 }
74
75 /*******************************************************************************
76 *
77 * FUNCTION: acpi_tb_install_standard_table
78 *
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
85 *
86 * RETURN: Status
87 *
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".
93 *
94 ******************************************************************************/
95
96 acpi_status
acpi_tb_install_standard_table(acpi_physical_address address,u8 flags,u8 reload,u8 override,u32 * table_index)97 acpi_tb_install_standard_table(acpi_physical_address address,
98 u8 flags,
99 u8 reload, u8 override, u32 *table_index)
100 {
101 u32 i;
102 acpi_status status = AE_OK;
103 struct acpi_table_desc new_table_desc;
104
105 ACPI_FUNCTION_TRACE(tb_install_standard_table);
106
107 /* Acquire a temporary table descriptor for validation */
108
109 status = acpi_tb_acquire_temp_table(&new_table_desc, address, flags);
110 if (ACPI_FAILURE(status)) {
111 ACPI_ERROR((AE_INFO,
112 "Could not acquire table length at %8.8X%8.8X",
113 ACPI_FORMAT_UINT64(address)));
114 return_ACPI_STATUS(status);
115 }
116
117 /*
118 * Optionally do not load any SSDTs from the RSDT/XSDT. This can
119 * be useful for debugging ACPI problems on some machines.
120 */
121 if (!reload &&
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;
128 }
129
130 /* Acquire the table lock */
131
132 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
133
134 /* Validate and verify a table before installation */
135
136 status = acpi_tb_verify_temp_table(&new_table_desc, NULL, &i);
137 if (ACPI_FAILURE(status)) {
138 if (status == AE_CTRL_TERMINATE) {
139 /*
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.
146 */
147 acpi_tb_uninstall_table(&new_table_desc);
148 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
149 *table_index = i;
150 return_ACPI_STATUS(AE_OK);
151 }
152 goto unlock_and_exit;
153 }
154
155 /* Add the table to the global root table list */
156
157 acpi_tb_install_table_with_override(&new_table_desc, override,
158 table_index);
159
160 /* Invoke table handler */
161
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);
165
166 unlock_and_exit:
167
168 /* Release the table lock */
169
170 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
171
172 release_and_exit:
173
174 /* Release the temporary table descriptor */
175
176 acpi_tb_release_temp_table(&new_table_desc);
177 return_ACPI_STATUS(status);
178 }
179
180 /*******************************************************************************
181 *
182 * FUNCTION: acpi_tb_override_table
183 *
184 * PARAMETERS: old_table_desc - Validated table descriptor to be
185 * overridden
186 *
187 * RETURN: None
188 *
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".
194 *
195 ******************************************************************************/
196
acpi_tb_override_table(struct acpi_table_desc * old_table_desc)197 void acpi_tb_override_table(struct acpi_table_desc *old_table_desc)
198 {
199 acpi_status status;
200 struct acpi_table_desc new_table_desc;
201 struct acpi_table_header *table;
202 acpi_physical_address address;
203 u32 length;
204 ACPI_ERROR_ONLY(char *override_type);
205
206 /* (1) Attempt logical override (returns a logical address) */
207
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;
215 }
216
217 /* (2) Attempt physical override (returns a physical address) */
218
219 status = acpi_os_physical_table_override(old_table_desc->pointer,
220 &address, &length);
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;
226 }
227
228 return; /* There was no override */
229
230 finish_override:
231
232 /*
233 * Validate and verify a table before overriding, no nested table
234 * duplication check as it's too complicated and unnecessary.
235 */
236 status = acpi_tb_verify_temp_table(&new_table_desc, NULL, NULL);
237 if (ACPI_FAILURE(status)) {
238 return;
239 }
240
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)));
246
247 /* We can now uninstall the original table */
248
249 acpi_tb_uninstall_table(old_table_desc);
250
251 /*
252 * Replace the original table descriptor and keep its state as
253 * "VALIDATED".
254 */
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);
259
260 /* Release the temporary table descriptor */
261
262 acpi_tb_release_temp_table(&new_table_desc);
263 }
264
265 /*******************************************************************************
266 *
267 * FUNCTION: acpi_tb_uninstall_table
268 *
269 * PARAMETERS: table_desc - Table descriptor
270 *
271 * RETURN: None
272 *
273 * DESCRIPTION: Delete one internal ACPI table
274 *
275 ******************************************************************************/
276
acpi_tb_uninstall_table(struct acpi_table_desc * table_desc)277 void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc)
278 {
279
280 ACPI_FUNCTION_TRACE(tb_uninstall_table);
281
282 /* Table must be installed */
283
284 if (!table_desc->address) {
285 return_VOID;
286 }
287
288 acpi_tb_invalidate_table(table_desc);
289
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));
293 }
294
295 table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL);
296 return_VOID;
297 }
298