xref: /linux/drivers/acpi/acpica/exconfig.c (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3  *
4  * Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes)
5  *
6  * Copyright (C) 2000 - 2026, Intel Corp.
7  *
8  *****************************************************************************/
9 
10 #include <acpi/acpi.h>
11 #include "accommon.h"
12 #include "acinterp.h"
13 #include "acnamesp.h"
14 #include "actables.h"
15 #include "acdispat.h"
16 #include "acevents.h"
17 #include "amlcode.h"
18 
19 #define _COMPONENT          ACPI_EXECUTER
20 ACPI_MODULE_NAME("exconfig")
21 
22 /* Local prototypes */
23 static acpi_status
24 acpi_ex_add_table(u32 table_index, union acpi_operand_object **ddb_handle);
25 
26 static acpi_status
27 acpi_ex_region_read(union acpi_operand_object *obj_desc,
28 		    u32 length, u8 *buffer);
29 
30 /*******************************************************************************
31  *
32  * FUNCTION:    acpi_ex_add_table
33  *
34  * PARAMETERS:  table               - Pointer to raw table
35  *              parent_node         - Where to load the table (scope)
36  *              ddb_handle          - Where to return the table handle.
37  *
38  * RETURN:      Status
39  *
40  * DESCRIPTION: Common function to Install and Load an ACPI table with a
41  *              returned table handle.
42  *
43  ******************************************************************************/
44 
45 static acpi_status
46 acpi_ex_add_table(u32 table_index, union acpi_operand_object **ddb_handle)
47 {
48 	union acpi_operand_object *obj_desc;
49 
50 	ACPI_FUNCTION_TRACE(ex_add_table);
51 
52 	/* Create an object to be the table handle */
53 
54 	obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
55 	if (!obj_desc) {
56 		return_ACPI_STATUS(AE_NO_MEMORY);
57 	}
58 
59 	/* Init the table handle */
60 
61 	obj_desc->common.flags |= AOPOBJ_DATA_VALID;
62 	obj_desc->reference.class = ACPI_REFCLASS_TABLE;
63 	obj_desc->reference.value = table_index;
64 	*ddb_handle = obj_desc;
65 	return_ACPI_STATUS(AE_OK);
66 }
67 
68 /*******************************************************************************
69  *
70  * FUNCTION:    acpi_ex_load_table_op
71  *
72  * PARAMETERS:  walk_state          - Current state with operands
73  *              return_desc         - Where to store the return object
74  *
75  * RETURN:      Status
76  *
77  * DESCRIPTION: Load an ACPI table from the RSDT/XSDT
78  *
79  ******************************************************************************/
80 
81 acpi_status
82 acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
83 		      union acpi_operand_object **return_desc)
84 {
85 	acpi_status status;
86 	union acpi_operand_object **operand = &walk_state->operands[0];
87 	struct acpi_namespace_node *parent_node;
88 	struct acpi_namespace_node *start_node;
89 	struct acpi_namespace_node *parameter_node = NULL;
90 	union acpi_operand_object *return_obj;
91 	union acpi_operand_object *ddb_handle;
92 	u32 table_index;
93 	char oem_id[ACPI_OEM_ID_SIZE + 1];
94 	char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
95 
96 	ACPI_FUNCTION_TRACE(ex_load_table_op);
97 
98 	/* Create the return object */
99 
100 	return_obj = acpi_ut_create_integer_object((u64)0);
101 	if (!return_obj) {
102 		return_ACPI_STATUS(AE_NO_MEMORY);
103 	}
104 
105 	*return_desc = return_obj;
106 
107 	/*
108 	 * Validate OEM ID and OEM Table ID string lengths.
109 	 * acpi_tb_find_table expects strings that can safely read
110 	 * ACPI_OEM_ID_SIZE and ACPI_OEM_TABLE_ID_SIZE bytes.
111 	 */
112 	if ((operand[1]->string.length > ACPI_OEM_ID_SIZE) ||
113 	    (operand[2]->string.length > ACPI_OEM_TABLE_ID_SIZE)) {
114 		return_ACPI_STATUS(AE_AML_STRING_LIMIT);
115 	}
116 
117 	/*
118 	 * Copy OEM strings to local buffers with guaranteed null-termination.
119 	 * This prevents heap-buffer-overflow when acpi_tb_find_table reads
120 	 * ACPI_OEM_ID_SIZE/ACPI_OEM_TABLE_ID_SIZE bytes.
121 	 */
122 	memcpy(oem_id, operand[1]->string.pointer, operand[1]->string.length);
123 	oem_id[operand[1]->string.length] = 0;
124 	memcpy(oem_table_id, operand[2]->string.pointer,
125 	       operand[2]->string.length);
126 	oem_table_id[operand[2]->string.length] = 0;
127 
128 	/* Find the ACPI table in the RSDT/XSDT */
129 
130 	acpi_ex_exit_interpreter();
131 	status = acpi_tb_find_table(operand[0]->string.pointer,
132 				    oem_id, oem_table_id, &table_index);
133 	acpi_ex_enter_interpreter();
134 	if (ACPI_FAILURE(status)) {
135 		if (status != AE_NOT_FOUND) {
136 			return_ACPI_STATUS(status);
137 		}
138 
139 		/* Table not found, return an Integer=0 and AE_OK */
140 
141 		return_ACPI_STATUS(AE_OK);
142 	}
143 
144 	/* Default nodes */
145 
146 	start_node = walk_state->scope_info->scope.node;
147 	parent_node = acpi_gbl_root_node;
148 
149 	/* root_path (optional parameter) */
150 
151 	if (operand[3]->string.length > 0) {
152 		/*
153 		 * Find the node referenced by the root_path_string. This is the
154 		 * location within the namespace where the table will be loaded.
155 		 */
156 		status = acpi_ns_get_node_unlocked(start_node,
157 						   operand[3]->string.pointer,
158 						   ACPI_NS_SEARCH_PARENT,
159 						   &parent_node);
160 		if (ACPI_FAILURE(status)) {
161 			return_ACPI_STATUS(status);
162 		}
163 	}
164 
165 	/* parameter_path (optional parameter) */
166 
167 	if (operand[4]->string.length > 0) {
168 		if ((operand[4]->string.pointer[0] != AML_ROOT_PREFIX) &&
169 		    (operand[4]->string.pointer[0] != AML_PARENT_PREFIX)) {
170 			/*
171 			 * Path is not absolute, so it will be relative to the node
172 			 * referenced by the root_path_string (or the NS root if omitted)
173 			 */
174 			start_node = parent_node;
175 		}
176 
177 		/* Find the node referenced by the parameter_path_string */
178 
179 		status = acpi_ns_get_node_unlocked(start_node,
180 						   operand[4]->string.pointer,
181 						   ACPI_NS_SEARCH_PARENT,
182 						   &parameter_node);
183 		if (ACPI_FAILURE(status)) {
184 			return_ACPI_STATUS(status);
185 		}
186 	}
187 
188 	/* Load the table into the namespace */
189 
190 	ACPI_INFO(("Dynamic OEM Table Load:"));
191 	acpi_ex_exit_interpreter();
192 	status = acpi_tb_load_table(table_index, parent_node);
193 	acpi_ex_enter_interpreter();
194 	if (ACPI_FAILURE(status)) {
195 		return_ACPI_STATUS(status);
196 	}
197 
198 	status = acpi_ex_add_table(table_index, &ddb_handle);
199 	if (ACPI_FAILURE(status)) {
200 		return_ACPI_STATUS(status);
201 	}
202 
203 	/* Complete the initialization/resolution of new objects */
204 
205 	acpi_ex_exit_interpreter();
206 	acpi_ns_initialize_objects();
207 	acpi_ex_enter_interpreter();
208 
209 	/* Parameter Data (optional) */
210 
211 	if (parameter_node) {
212 
213 		/* Store the parameter data into the optional parameter object */
214 
215 		status = acpi_ex_store(operand[5],
216 				       ACPI_CAST_PTR(union acpi_operand_object,
217 						     parameter_node),
218 				       walk_state);
219 		if (ACPI_FAILURE(status)) {
220 			(void)acpi_ex_unload_table(ddb_handle);
221 
222 			acpi_ut_remove_reference(ddb_handle);
223 			return_ACPI_STATUS(status);
224 		}
225 	}
226 
227 	/* Remove the reference to ddb_handle created by acpi_ex_add_table above */
228 
229 	acpi_ut_remove_reference(ddb_handle);
230 
231 	/* Return -1 (non-zero) indicates success */
232 
233 	return_obj->integer.value = 0xFFFFFFFFFFFFFFFF;
234 	return_ACPI_STATUS(status);
235 }
236 
237 /*******************************************************************************
238  *
239  * FUNCTION:    acpi_ex_region_read
240  *
241  * PARAMETERS:  obj_desc        - Region descriptor
242  *              length          - Number of bytes to read
243  *              buffer          - Pointer to where to put the data
244  *
245  * RETURN:      Status
246  *
247  * DESCRIPTION: Read data from an operation region. The read starts from the
248  *              beginning of the region.
249  *
250  ******************************************************************************/
251 
252 static acpi_status
253 acpi_ex_region_read(union acpi_operand_object *obj_desc, u32 length, u8 *buffer)
254 {
255 	acpi_status status;
256 	u64 value;
257 	u32 region_offset = 0;
258 	u32 i;
259 
260 	/* Bytewise reads */
261 
262 	for (i = 0; i < length; i++) {
263 		status =
264 		    acpi_ev_address_space_dispatch(obj_desc, NULL, ACPI_READ,
265 						   region_offset, 8, &value);
266 		if (ACPI_FAILURE(status)) {
267 			return (status);
268 		}
269 
270 		*buffer = (u8)value;
271 		buffer++;
272 		region_offset++;
273 	}
274 
275 	return (AE_OK);
276 }
277 
278 /*******************************************************************************
279  *
280  * FUNCTION:    acpi_ex_load_op
281  *
282  * PARAMETERS:  obj_desc        - Region or Buffer/Field where the table will be
283  *                                obtained
284  *              target          - Where the status of the load will be stored
285  *              walk_state      - Current state
286  *
287  * RETURN:      Status
288  *
289  * DESCRIPTION: Load an ACPI table from a field or operation region
290  *
291  * NOTE: Region Fields (Field, bank_field, index_fields) are resolved to buffer
292  *       objects before this code is reached.
293  *
294  *       If source is an operation region, it must refer to system_memory, as
295  *       per the ACPI specification.
296  *
297  ******************************************************************************/
298 
299 acpi_status
300 acpi_ex_load_op(union acpi_operand_object *obj_desc,
301 		union acpi_operand_object *target,
302 		struct acpi_walk_state *walk_state)
303 {
304 	union acpi_operand_object *ddb_handle;
305 	struct acpi_table_header *table_header;
306 	struct acpi_table_header *table;
307 	u32 table_index;
308 	acpi_status status;
309 	u32 length;
310 
311 	ACPI_FUNCTION_TRACE(ex_load_op);
312 
313 	if (target->common.descriptor_type == ACPI_DESC_TYPE_NAMED) {
314 		target =
315 		    acpi_ns_get_attached_object(ACPI_CAST_PTR
316 						(struct acpi_namespace_node,
317 						 target));
318 	}
319 	if (target->common.type != ACPI_TYPE_INTEGER) {
320 		ACPI_ERROR((AE_INFO, "Type not integer: %X",
321 			    target->common.type));
322 		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
323 	}
324 
325 	target->integer.value = 0;
326 
327 	/* Source Object can be either an op_region or a Buffer/Field */
328 
329 	switch (obj_desc->common.type) {
330 	case ACPI_TYPE_REGION:
331 
332 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
333 				  "Load table from Region %p\n", obj_desc));
334 
335 		/* Region must be system_memory (from ACPI spec) */
336 
337 		if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) {
338 			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
339 		}
340 
341 		/*
342 		 * If the Region Address and Length have not been previously
343 		 * evaluated, evaluate them now and save the results.
344 		 */
345 		if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
346 			status = acpi_ds_get_region_arguments(obj_desc);
347 			if (ACPI_FAILURE(status)) {
348 				return_ACPI_STATUS(status);
349 			}
350 		}
351 
352 		/* Get the table header first so we can get the table length */
353 
354 		table_header = ACPI_ALLOCATE(sizeof(struct acpi_table_header));
355 		if (!table_header) {
356 			return_ACPI_STATUS(AE_NO_MEMORY);
357 		}
358 
359 		status =
360 		    acpi_ex_region_read(obj_desc,
361 					sizeof(struct acpi_table_header),
362 					ACPI_CAST_PTR(u8, table_header));
363 		length = table_header->length;
364 		ACPI_FREE(table_header);
365 
366 		if (ACPI_FAILURE(status)) {
367 			return_ACPI_STATUS(status);
368 		}
369 
370 		/* Must have at least an ACPI table header */
371 
372 		if (length < sizeof(struct acpi_table_header)) {
373 			return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
374 		}
375 
376 		/*
377 		 * The original implementation simply mapped the table, with no copy.
378 		 * However, the memory region is not guaranteed to remain stable and
379 		 * we must copy the table to a local buffer. For example, the memory
380 		 * region is corrupted after suspend on some machines. Dynamically
381 		 * loaded tables are usually small, so this overhead is minimal.
382 		 *
383 		 * The latest implementation (5/2009) does not use a mapping at all.
384 		 * We use the low-level operation region interface to read the table
385 		 * instead of the obvious optimization of using a direct mapping.
386 		 * This maintains a consistent use of operation regions across the
387 		 * entire subsystem. This is important if additional processing must
388 		 * be performed in the (possibly user-installed) operation region
389 		 * handler. For example, acpi_exec and ASLTS depend on this.
390 		 */
391 
392 		/* Allocate a buffer for the table */
393 
394 		table = ACPI_ALLOCATE(length);
395 		if (!table) {
396 			return_ACPI_STATUS(AE_NO_MEMORY);
397 		}
398 
399 		/* Read the entire table */
400 
401 		status = acpi_ex_region_read(obj_desc, length,
402 					     ACPI_CAST_PTR(u8, table));
403 		if (ACPI_FAILURE(status)) {
404 			ACPI_FREE(table);
405 			return_ACPI_STATUS(status);
406 		}
407 		break;
408 
409 	case ACPI_TYPE_BUFFER:	/* Buffer or resolved region_field */
410 
411 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
412 				  "Load table from Buffer or Field %p\n",
413 				  obj_desc));
414 
415 		/* Must have at least an ACPI table header */
416 
417 		if (obj_desc->buffer.length < sizeof(struct acpi_table_header)) {
418 			return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
419 		}
420 
421 		/* Get the actual table length from the table header */
422 
423 		table_header =
424 		    ACPI_CAST_PTR(struct acpi_table_header,
425 				  obj_desc->buffer.pointer);
426 		length = table_header->length;
427 
428 		/* Table cannot extend beyond the buffer */
429 
430 		if (length > obj_desc->buffer.length) {
431 			return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
432 		}
433 		if (length < sizeof(struct acpi_table_header)) {
434 			return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
435 		}
436 
437 		/*
438 		 * Copy the table from the buffer because the buffer could be
439 		 * modified or even deleted in the future
440 		 */
441 		table = ACPI_ALLOCATE(length);
442 		if (!table) {
443 			return_ACPI_STATUS(AE_NO_MEMORY);
444 		}
445 
446 		memcpy(table, table_header, length);
447 		break;
448 
449 	default:
450 
451 		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
452 	}
453 
454 	/* Install the new table into the local data structures */
455 
456 	ACPI_INFO(("Dynamic OEM Table Load:"));
457 	acpi_ex_exit_interpreter();
458 	status = acpi_tb_install_and_load_table(ACPI_PTR_TO_PHYSADDR(table),
459 						ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL,
460 						table, TRUE, &table_index);
461 	acpi_ex_enter_interpreter();
462 	if (ACPI_FAILURE(status)) {
463 
464 		/* Delete allocated table buffer */
465 
466 		ACPI_FREE(table);
467 		return_ACPI_STATUS(status);
468 	}
469 
470 	/*
471 	 * Add the table to the namespace.
472 	 *
473 	 * Note: Load the table objects relative to the root of the namespace.
474 	 * This appears to go against the ACPI specification, but we do it for
475 	 * compatibility with other ACPI implementations.
476 	 */
477 	status = acpi_ex_add_table(table_index, &ddb_handle);
478 	if (ACPI_FAILURE(status)) {
479 		return_ACPI_STATUS(status);
480 	}
481 
482 	/* Complete the initialization/resolution of new objects */
483 
484 	acpi_ex_exit_interpreter();
485 	acpi_ns_initialize_objects();
486 	acpi_ex_enter_interpreter();
487 
488 	/* Remove the reference to ddb_handle created by acpi_ex_add_table above */
489 
490 	acpi_ut_remove_reference(ddb_handle);
491 
492 	/* Return -1 (non-zero) indicates success */
493 
494 	target->integer.value = 0xFFFFFFFFFFFFFFFF;
495 	return_ACPI_STATUS(status);
496 }
497 
498 /*******************************************************************************
499  *
500  * FUNCTION:    acpi_ex_unload_table
501  *
502  * PARAMETERS:  ddb_handle          - Handle to a previously loaded table
503  *
504  * RETURN:      Status
505  *
506  * DESCRIPTION: Unload an ACPI table
507  *
508  ******************************************************************************/
509 
510 acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
511 {
512 	acpi_status status = AE_OK;
513 	union acpi_operand_object *table_desc = ddb_handle;
514 	u32 table_index;
515 
516 	ACPI_FUNCTION_TRACE(ex_unload_table);
517 
518 	/*
519 	 * Temporarily emit a warning so that the ASL for the machine can be
520 	 * hopefully obtained. This is to say that the Unload() operator is
521 	 * extremely rare if not completely unused.
522 	 */
523 	ACPI_WARNING((AE_INFO, "Received request to unload an ACPI table"));
524 
525 	/*
526 	 * May 2018: Unload is no longer supported for the following reasons:
527 	 * 1) A correct implementation on some hosts may not be possible.
528 	 * 2) Other ACPI implementations do not correctly/fully support it.
529 	 * 3) It requires host device driver support which does not exist.
530 	 *    (To properly support namespace unload out from underneath.)
531 	 * 4) This AML operator has never been seen in the field.
532 	 */
533 	ACPI_EXCEPTION((AE_INFO, AE_NOT_IMPLEMENTED,
534 			"AML Unload operator is not supported"));
535 
536 	/*
537 	 * Validate the handle
538 	 * Although the handle is partially validated in acpi_ex_reconfiguration()
539 	 * when it calls acpi_ex_resolve_operands(), the handle is more completely
540 	 * validated here.
541 	 *
542 	 * Handle must be a valid operand object of type reference. Also, the
543 	 * ddb_handle must still be marked valid (table has not been previously
544 	 * unloaded)
545 	 */
546 	if ((!ddb_handle) ||
547 	    (ACPI_GET_DESCRIPTOR_TYPE(ddb_handle) != ACPI_DESC_TYPE_OPERAND) ||
548 	    (ddb_handle->common.type != ACPI_TYPE_LOCAL_REFERENCE) ||
549 	    (!(ddb_handle->common.flags & AOPOBJ_DATA_VALID))) {
550 		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
551 	}
552 
553 	/* Get the table index from the ddb_handle */
554 
555 	table_index = table_desc->reference.value;
556 
557 	/*
558 	 * Release the interpreter lock so that the table lock won't have
559 	 * strict order requirement against it.
560 	 */
561 	acpi_ex_exit_interpreter();
562 	status = acpi_tb_unload_table(table_index);
563 	acpi_ex_enter_interpreter();
564 
565 	/*
566 	 * Invalidate the handle. We do this because the handle may be stored
567 	 * in a named object and may not be actually deleted until much later.
568 	 */
569 	if (ACPI_SUCCESS(status)) {
570 		ddb_handle->common.flags &= ~AOPOBJ_DATA_VALID;
571 	}
572 	return_ACPI_STATUS(status);
573 }
574