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 - 2023, 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 |
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(table_index: &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(old_table_desc: new_table_desc); |
54 | } |
55 | |
56 | acpi_tb_init_table_descriptor(table_desc: &acpi_gbl_root_table_list.tables[i], |
57 | address: new_table_desc->address, |
58 | flags: new_table_desc->flags, |
59 | table: new_table_desc->pointer); |
60 | |
61 | acpi_tb_print_table_header(address: new_table_desc->address, |
62 | header: 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(revision: 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 | * table - Pointer to the table (required for virtual |
83 | * origins, optional for physical) |
84 | * reload - Whether reload should be performed |
85 | * override - Whether override should be performed |
86 | * table_index - Where the table index is returned |
87 | * |
88 | * RETURN: Status |
89 | * |
90 | * DESCRIPTION: This function is called to verify and install an ACPI table. |
91 | * When this function is called by "Load" or "LoadTable" opcodes, |
92 | * or by acpi_load_table() API, the "Reload" parameter is set. |
93 | * After successfully returning from this function, table is |
94 | * "INSTALLED" but not "VALIDATED". |
95 | * |
96 | ******************************************************************************/ |
97 | |
98 | acpi_status |
99 | acpi_tb_install_standard_table(acpi_physical_address address, |
100 | u8 flags, |
101 | struct acpi_table_header *table, |
102 | u8 reload, u8 override, u32 *table_index) |
103 | { |
104 | u32 i; |
105 | acpi_status status = AE_OK; |
106 | struct acpi_table_desc new_table_desc; |
107 | |
108 | ACPI_FUNCTION_TRACE(tb_install_standard_table); |
109 | |
110 | /* Acquire a temporary table descriptor for validation */ |
111 | |
112 | status = |
113 | acpi_tb_acquire_temp_table(table_desc: &new_table_desc, address, flags, table); |
114 | if (ACPI_FAILURE(status)) { |
115 | ACPI_ERROR((AE_INFO, |
116 | "Could not acquire table length at %8.8X%8.8X" , |
117 | ACPI_FORMAT_UINT64(address))); |
118 | return_ACPI_STATUS(status); |
119 | } |
120 | |
121 | /* |
122 | * Optionally do not load any SSDTs from the RSDT/XSDT. This can |
123 | * be useful for debugging ACPI problems on some machines. |
124 | */ |
125 | if (!reload && |
126 | acpi_gbl_disable_ssdt_table_install && |
127 | ACPI_COMPARE_NAMESEG(&new_table_desc.signature, ACPI_SIG_SSDT)) { |
128 | ACPI_INFO(("Ignoring installation of %4.4s at %8.8X%8.8X" , |
129 | new_table_desc.signature.ascii, |
130 | ACPI_FORMAT_UINT64(address))); |
131 | goto release_and_exit; |
132 | } |
133 | |
134 | /* Acquire the table lock */ |
135 | |
136 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
137 | |
138 | /* Validate and verify a table before installation */ |
139 | |
140 | status = acpi_tb_verify_temp_table(table_desc: &new_table_desc, NULL, table_index: &i); |
141 | if (ACPI_FAILURE(status)) { |
142 | if (status == AE_CTRL_TERMINATE) { |
143 | /* |
144 | * Table was unloaded, allow it to be reloaded. |
145 | * As we are going to return AE_OK to the caller, we should |
146 | * take the responsibility of freeing the input descriptor. |
147 | * Refill the input descriptor to ensure |
148 | * acpi_tb_install_table_with_override() can be called again to |
149 | * indicate the re-installation. |
150 | */ |
151 | acpi_tb_uninstall_table(table_desc: &new_table_desc); |
152 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
153 | *table_index = i; |
154 | return_ACPI_STATUS(AE_OK); |
155 | } |
156 | goto unlock_and_exit; |
157 | } |
158 | |
159 | /* Add the table to the global root table list */ |
160 | |
161 | acpi_tb_install_table_with_override(new_table_desc: &new_table_desc, override, |
162 | table_index); |
163 | |
164 | /* Invoke table handler */ |
165 | |
166 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
167 | acpi_tb_notify_table(ACPI_TABLE_EVENT_INSTALL, table: new_table_desc.pointer); |
168 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
169 | |
170 | unlock_and_exit: |
171 | |
172 | /* Release the table lock */ |
173 | |
174 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
175 | |
176 | release_and_exit: |
177 | |
178 | /* Release the temporary table descriptor */ |
179 | |
180 | acpi_tb_release_temp_table(table_desc: &new_table_desc); |
181 | return_ACPI_STATUS(status); |
182 | } |
183 | |
184 | /******************************************************************************* |
185 | * |
186 | * FUNCTION: acpi_tb_override_table |
187 | * |
188 | * PARAMETERS: old_table_desc - Validated table descriptor to be |
189 | * overridden |
190 | * |
191 | * RETURN: None |
192 | * |
193 | * DESCRIPTION: Attempt table override by calling the OSL override functions. |
194 | * Note: If the table is overridden, then the entire new table |
195 | * is acquired and returned by this function. |
196 | * Before/after invocation, the table descriptor is in a state |
197 | * that is "VALIDATED". |
198 | * |
199 | ******************************************************************************/ |
200 | |
201 | void acpi_tb_override_table(struct acpi_table_desc *old_table_desc) |
202 | { |
203 | acpi_status status; |
204 | struct acpi_table_desc new_table_desc; |
205 | struct acpi_table_header *table; |
206 | acpi_physical_address address; |
207 | u32 length; |
208 | ACPI_ERROR_ONLY(char *override_type); |
209 | |
210 | /* (1) Attempt logical override (returns a logical address) */ |
211 | |
212 | status = acpi_os_table_override(existing_table: old_table_desc->pointer, new_table: &table); |
213 | if (ACPI_SUCCESS(status) && table) { |
214 | acpi_tb_acquire_temp_table(table_desc: &new_table_desc, |
215 | ACPI_PTR_TO_PHYSADDR(table), |
216 | ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, |
217 | table); |
218 | ACPI_ERROR_ONLY(override_type = "Logical" ); |
219 | goto finish_override; |
220 | } |
221 | |
222 | /* (2) Attempt physical override (returns a physical address) */ |
223 | |
224 | status = acpi_os_physical_table_override(existing_table: old_table_desc->pointer, |
225 | new_address: &address, new_table_length: &length); |
226 | if (ACPI_SUCCESS(status) && address && length) { |
227 | acpi_tb_acquire_temp_table(table_desc: &new_table_desc, address, |
228 | ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, |
229 | NULL); |
230 | ACPI_ERROR_ONLY(override_type = "Physical" ); |
231 | goto finish_override; |
232 | } |
233 | |
234 | return; /* There was no override */ |
235 | |
236 | finish_override: |
237 | |
238 | /* |
239 | * Validate and verify a table before overriding, no nested table |
240 | * duplication check as it's too complicated and unnecessary. |
241 | */ |
242 | status = acpi_tb_verify_temp_table(table_desc: &new_table_desc, NULL, NULL); |
243 | if (ACPI_FAILURE(status)) { |
244 | return; |
245 | } |
246 | |
247 | ACPI_INFO(("%4.4s 0x%8.8X%8.8X" |
248 | " %s table override, new table: 0x%8.8X%8.8X" , |
249 | old_table_desc->signature.ascii, |
250 | ACPI_FORMAT_UINT64(old_table_desc->address), |
251 | override_type, ACPI_FORMAT_UINT64(new_table_desc.address))); |
252 | |
253 | /* We can now uninstall the original table */ |
254 | |
255 | acpi_tb_uninstall_table(table_desc: old_table_desc); |
256 | |
257 | /* |
258 | * Replace the original table descriptor and keep its state as |
259 | * "VALIDATED". |
260 | */ |
261 | acpi_tb_init_table_descriptor(table_desc: old_table_desc, address: new_table_desc.address, |
262 | flags: new_table_desc.flags, |
263 | table: new_table_desc.pointer); |
264 | acpi_tb_validate_temp_table(table_desc: old_table_desc); |
265 | |
266 | /* Release the temporary table descriptor */ |
267 | |
268 | acpi_tb_release_temp_table(table_desc: &new_table_desc); |
269 | } |
270 | |
271 | /******************************************************************************* |
272 | * |
273 | * FUNCTION: acpi_tb_uninstall_table |
274 | * |
275 | * PARAMETERS: table_desc - Table descriptor |
276 | * |
277 | * RETURN: None |
278 | * |
279 | * DESCRIPTION: Delete one internal ACPI table |
280 | * |
281 | ******************************************************************************/ |
282 | |
283 | void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc) |
284 | { |
285 | |
286 | ACPI_FUNCTION_TRACE(tb_uninstall_table); |
287 | |
288 | /* Table must be installed */ |
289 | |
290 | if (!table_desc->address) { |
291 | return_VOID; |
292 | } |
293 | |
294 | acpi_tb_invalidate_table(table_desc); |
295 | |
296 | if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == |
297 | ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) { |
298 | ACPI_FREE(table_desc->pointer); |
299 | table_desc->pointer = NULL; |
300 | } |
301 | |
302 | table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL); |
303 | return_VOID; |
304 | } |
305 | |