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 ¶meter_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