xref: /openbmc/linux/drivers/acpi/acpica/tbinstal.c (revision 75020f2d)
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
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
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 
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 
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