xref: /openbmc/linux/drivers/acpi/acpica/tbinstal.c (revision 2d2f5f1e)
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(&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  *              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(&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(&new_table_desc, NULL, &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(&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, 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, 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(&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(old_table_desc->pointer, &table);
213 	if (ACPI_SUCCESS(status) && table) {
214 		acpi_tb_acquire_temp_table(&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(old_table_desc->pointer,
225 						 &address, &length);
226 	if (ACPI_SUCCESS(status) && address && length) {
227 		acpi_tb_acquire_temp_table(&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(&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(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(old_table_desc, new_table_desc.address,
262 				      new_table_desc.flags,
263 				      new_table_desc.pointer);
264 	acpi_tb_validate_temp_table(old_table_desc);
265 
266 	/* Release the temporary table descriptor */
267 
268 	acpi_tb_release_temp_table(&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