Branch data Line data Source code
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 - 2020, 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 : 390 : acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc,
35 : : u8 override, u32 *table_index)
36 : : {
37 : 390 : u32 i;
38 : 390 : acpi_status status;
39 : :
40 : 390 : status = acpi_tb_get_next_table_descriptor(&i, NULL);
41 [ - + ]: 390 : if (ACPI_FAILURE(status)) {
42 : 0 : 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 [ + - ]: 390 : if (override) {
53 : 390 : acpi_tb_override_table(new_table_desc);
54 : : }
55 : :
56 : 390 : acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.tables[i],
57 : : new_table_desc->address,
58 : 390 : new_table_desc->flags,
59 : : new_table_desc->pointer);
60 : :
61 : 390 : acpi_tb_print_table_header(new_table_desc->address,
62 : : new_table_desc->pointer);
63 : :
64 : : /* This synchronizes acpi_gbl_dsdt_index */
65 : :
66 : 390 : *table_index = i;
67 : :
68 : : /* Set the global integer width (based upon revision of the DSDT) */
69 : :
70 [ + + ]: 390 : if (i == acpi_gbl_dsdt_index) {
71 : 78 : 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
97 : 390 : acpi_tb_install_standard_table(acpi_physical_address address,
98 : : u8 flags,
99 : : u8 reload, u8 override, u32 *table_index)
100 : : {
101 : 390 : u32 i;
102 : 390 : acpi_status status = AE_OK;
103 : 390 : struct acpi_table_desc new_table_desc;
104 : :
105 : 390 : ACPI_FUNCTION_TRACE(tb_install_standard_table);
106 : :
107 : : /* Acquire a temporary table descriptor for validation */
108 : :
109 : 390 : status = acpi_tb_acquire_temp_table(&new_table_desc, address, flags);
110 [ - + ]: 390 : if (ACPI_FAILURE(status)) {
111 : 0 : ACPI_ERROR((AE_INFO,
112 : : "Could not acquire table length at %8.8X%8.8X",
113 : : ACPI_FORMAT_UINT64(address)));
114 : 0 : 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 [ + - - + ]: 390 : if (!reload &&
122 : 0 : acpi_gbl_disable_ssdt_table_install &&
123 [ # # ]: 0 : ACPI_COMPARE_NAMESEG(&new_table_desc.signature, ACPI_SIG_SSDT)) {
124 : 0 : ACPI_INFO(("Ignoring installation of %4.4s at %8.8X%8.8X",
125 : : new_table_desc.signature.ascii,
126 : : ACPI_FORMAT_UINT64(address)));
127 : 0 : goto release_and_exit;
128 : : }
129 : :
130 : : /* Acquire the table lock */
131 : :
132 : 390 : (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
133 : :
134 : : /* Validate and verify a table before installation */
135 : :
136 : 390 : status = acpi_tb_verify_temp_table(&new_table_desc, NULL, &i);
137 [ - + ]: 390 : if (ACPI_FAILURE(status)) {
138 [ # # ]: 0 : 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 : 0 : acpi_tb_uninstall_table(&new_table_desc);
148 : 0 : (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
149 : 0 : *table_index = i;
150 : 0 : return_ACPI_STATUS(AE_OK);
151 : : }
152 : 0 : goto unlock_and_exit;
153 : : }
154 : :
155 : : /* Add the table to the global root table list */
156 : :
157 : 390 : acpi_tb_install_table_with_override(&new_table_desc, override,
158 : : table_index);
159 : :
160 : : /* Invoke table handler */
161 : :
162 : 390 : (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
163 : 390 : acpi_tb_notify_table(ACPI_TABLE_EVENT_INSTALL, new_table_desc.pointer);
164 : 390 : (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
165 : :
166 : 390 : unlock_and_exit:
167 : :
168 : : /* Release the table lock */
169 : :
170 : 390 : (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
171 : :
172 : 390 : release_and_exit:
173 : :
174 : : /* Release the temporary table descriptor */
175 : :
176 : 390 : acpi_tb_release_temp_table(&new_table_desc);
177 : 390 : 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 : :
197 : 390 : void acpi_tb_override_table(struct acpi_table_desc *old_table_desc)
198 : : {
199 : 390 : acpi_status status;
200 : 390 : struct acpi_table_desc new_table_desc;
201 : 390 : struct acpi_table_header *table;
202 : 390 : acpi_physical_address address;
203 : 390 : u32 length;
204 : 390 : ACPI_ERROR_ONLY(char *override_type);
205 : :
206 : : /* (1) Attempt logical override (returns a logical address) */
207 : :
208 : 390 : status = acpi_os_table_override(old_table_desc->pointer, &table);
209 [ + - - + ]: 390 : if (ACPI_SUCCESS(status) && table) {
210 : 0 : acpi_tb_acquire_temp_table(&new_table_desc,
211 : : ACPI_PTR_TO_PHYSADDR(table),
212 : : ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL);
213 : 0 : ACPI_ERROR_ONLY(override_type = "Logical");
214 : 0 : goto finish_override;
215 : : }
216 : :
217 : : /* (2) Attempt physical override (returns a physical address) */
218 : :
219 : 390 : status = acpi_os_physical_table_override(old_table_desc->pointer,
220 : : &address, &length);
221 [ + - - + : 390 : if (ACPI_SUCCESS(status) && address && length) {
- - ]
222 : 0 : acpi_tb_acquire_temp_table(&new_table_desc, address,
223 : : ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL);
224 : 0 : ACPI_ERROR_ONLY(override_type = "Physical");
225 : 0 : goto finish_override;
226 : : }
227 : :
228 : 390 : return; /* There was no override */
229 : :
230 : 0 : 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 : 0 : status = acpi_tb_verify_temp_table(&new_table_desc, NULL, NULL);
237 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
238 : : return;
239 : : }
240 : :
241 : 0 : 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 : 0 : acpi_tb_uninstall_table(old_table_desc);
250 : :
251 : : /*
252 : : * Replace the original table descriptor and keep its state as
253 : : * "VALIDATED".
254 : : */
255 : 0 : acpi_tb_init_table_descriptor(old_table_desc, new_table_desc.address,
256 : 0 : new_table_desc.flags,
257 : : new_table_desc.pointer);
258 : 0 : acpi_tb_validate_temp_table(old_table_desc);
259 : :
260 : : /* Release the temporary table descriptor */
261 : :
262 : 0 : 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 : :
277 : 0 : void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc)
278 : : {
279 : :
280 : 0 : ACPI_FUNCTION_TRACE(tb_uninstall_table);
281 : :
282 : : /* Table must be installed */
283 : :
284 [ # # ]: 0 : if (!table_desc->address) {
285 : : return_VOID;
286 : : }
287 : :
288 : 0 : acpi_tb_invalidate_table(table_desc);
289 : :
290 [ # # ]: 0 : if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) ==
291 : : ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) {
292 : 0 : ACPI_FREE(ACPI_PHYSADDR_TO_PTR(table_desc->address));
293 : : }
294 : :
295 : 0 : table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL);
296 : 0 : return_VOID;
297 : : }
|