dsmthdat.c (19736B)
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2/******************************************************************************* 3 * 4 * Module Name: dsmthdat - control method arguments and local variables 5 * 6 ******************************************************************************/ 7 8#include <acpi/acpi.h> 9#include "accommon.h" 10#include "acdispat.h" 11#include "acnamesp.h" 12#include "acinterp.h" 13 14#define _COMPONENT ACPI_DISPATCHER 15ACPI_MODULE_NAME("dsmthdat") 16 17/* Local prototypes */ 18static void 19acpi_ds_method_data_delete_value(u8 type, 20 u32 index, struct acpi_walk_state *walk_state); 21 22static acpi_status 23acpi_ds_method_data_set_value(u8 type, 24 u32 index, 25 union acpi_operand_object *object, 26 struct acpi_walk_state *walk_state); 27 28#ifdef ACPI_OBSOLETE_FUNCTIONS 29acpi_object_type 30acpi_ds_method_data_get_type(u16 opcode, 31 u32 index, struct acpi_walk_state *walk_state); 32#endif 33 34/******************************************************************************* 35 * 36 * FUNCTION: acpi_ds_method_data_init 37 * 38 * PARAMETERS: walk_state - Current walk state object 39 * 40 * RETURN: Status 41 * 42 * DESCRIPTION: Initialize the data structures that hold the method's arguments 43 * and locals. The data struct is an array of namespace nodes for 44 * each - this allows ref_of and de_ref_of to work properly for these 45 * special data types. 46 * 47 * NOTES: walk_state fields are initialized to zero by the 48 * ACPI_ALLOCATE_ZEROED(). 49 * 50 * A pseudo-Namespace Node is assigned to each argument and local 51 * so that ref_of() can return a pointer to the Node. 52 * 53 ******************************************************************************/ 54 55void acpi_ds_method_data_init(struct acpi_walk_state *walk_state) 56{ 57 u32 i; 58 59 ACPI_FUNCTION_TRACE(ds_method_data_init); 60 61 /* Init the method arguments */ 62 63 for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) { 64 ACPI_MOVE_32_TO_32(&walk_state->arguments[i].name, 65 NAMEOF_ARG_NTE); 66 67 walk_state->arguments[i].name.integer |= (i << 24); 68 walk_state->arguments[i].descriptor_type = ACPI_DESC_TYPE_NAMED; 69 walk_state->arguments[i].type = ACPI_TYPE_ANY; 70 walk_state->arguments[i].flags = ANOBJ_METHOD_ARG; 71 } 72 73 /* Init the method locals */ 74 75 for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) { 76 ACPI_MOVE_32_TO_32(&walk_state->local_variables[i].name, 77 NAMEOF_LOCAL_NTE); 78 79 walk_state->local_variables[i].name.integer |= (i << 24); 80 walk_state->local_variables[i].descriptor_type = 81 ACPI_DESC_TYPE_NAMED; 82 walk_state->local_variables[i].type = ACPI_TYPE_ANY; 83 walk_state->local_variables[i].flags = ANOBJ_METHOD_LOCAL; 84 } 85 86 return_VOID; 87} 88 89/******************************************************************************* 90 * 91 * FUNCTION: acpi_ds_method_data_delete_all 92 * 93 * PARAMETERS: walk_state - Current walk state object 94 * 95 * RETURN: None 96 * 97 * DESCRIPTION: Delete method locals and arguments. Arguments are only 98 * deleted if this method was called from another method. 99 * 100 ******************************************************************************/ 101 102void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state) 103{ 104 u32 index; 105 106 ACPI_FUNCTION_TRACE(ds_method_data_delete_all); 107 108 /* Detach the locals */ 109 110 for (index = 0; index < ACPI_METHOD_NUM_LOCALS; index++) { 111 if (walk_state->local_variables[index].object) { 112 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Local%u=%p\n", 113 index, 114 walk_state->local_variables[index]. 115 object)); 116 117 /* Detach object (if present) and remove a reference */ 118 119 acpi_ns_detach_object(&walk_state-> 120 local_variables[index]); 121 } 122 } 123 124 /* Detach the arguments */ 125 126 for (index = 0; index < ACPI_METHOD_NUM_ARGS; index++) { 127 if (walk_state->arguments[index].object) { 128 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Arg%u=%p\n", 129 index, 130 walk_state->arguments[index].object)); 131 132 /* Detach object (if present) and remove a reference */ 133 134 acpi_ns_detach_object(&walk_state->arguments[index]); 135 } 136 } 137 138 return_VOID; 139} 140 141/******************************************************************************* 142 * 143 * FUNCTION: acpi_ds_method_data_init_args 144 * 145 * PARAMETERS: *params - Pointer to a parameter list for the method 146 * max_param_count - The arg count for this method 147 * walk_state - Current walk state object 148 * 149 * RETURN: Status 150 * 151 * DESCRIPTION: Initialize arguments for a method. The parameter list is a list 152 * of ACPI operand objects, either null terminated or whose length 153 * is defined by max_param_count. 154 * 155 ******************************************************************************/ 156 157acpi_status 158acpi_ds_method_data_init_args(union acpi_operand_object **params, 159 u32 max_param_count, 160 struct acpi_walk_state *walk_state) 161{ 162 acpi_status status; 163 u32 index = 0; 164 165 ACPI_FUNCTION_TRACE_PTR(ds_method_data_init_args, params); 166 167 if (!params) { 168 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 169 "No parameter list passed to method\n")); 170 return_ACPI_STATUS(AE_OK); 171 } 172 173 /* Copy passed parameters into the new method stack frame */ 174 175 while ((index < ACPI_METHOD_NUM_ARGS) && 176 (index < max_param_count) && params[index]) { 177 /* 178 * A valid parameter. 179 * Store the argument in the method/walk descriptor. 180 * Do not copy the arg in order to implement call by reference 181 */ 182 status = 183 acpi_ds_method_data_set_value(ACPI_REFCLASS_ARG, index, 184 params[index], walk_state); 185 if (ACPI_FAILURE(status)) { 186 return_ACPI_STATUS(status); 187 } 188 189 index++; 190 } 191 192 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%u args passed to method\n", index)); 193 return_ACPI_STATUS(AE_OK); 194} 195 196/******************************************************************************* 197 * 198 * FUNCTION: acpi_ds_method_data_get_node 199 * 200 * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or 201 * ACPI_REFCLASS_ARG 202 * index - Which Local or Arg whose type to get 203 * walk_state - Current walk state object 204 * node - Where the node is returned. 205 * 206 * RETURN: Status and node 207 * 208 * DESCRIPTION: Get the Node associated with a local or arg. 209 * 210 ******************************************************************************/ 211 212acpi_status 213acpi_ds_method_data_get_node(u8 type, 214 u32 index, 215 struct acpi_walk_state *walk_state, 216 struct acpi_namespace_node **node) 217{ 218 ACPI_FUNCTION_TRACE(ds_method_data_get_node); 219 220 /* 221 * Method Locals and Arguments are supported 222 */ 223 switch (type) { 224 case ACPI_REFCLASS_LOCAL: 225 226 if (index > ACPI_METHOD_MAX_LOCAL) { 227 ACPI_ERROR((AE_INFO, 228 "Local index %u is invalid (max %u)", 229 index, ACPI_METHOD_MAX_LOCAL)); 230 return_ACPI_STATUS(AE_AML_INVALID_INDEX); 231 } 232 233 /* Return a pointer to the pseudo-node */ 234 235 *node = &walk_state->local_variables[index]; 236 break; 237 238 case ACPI_REFCLASS_ARG: 239 240 if (index > ACPI_METHOD_MAX_ARG) { 241 ACPI_ERROR((AE_INFO, 242 "Arg index %u is invalid (max %u)", 243 index, ACPI_METHOD_MAX_ARG)); 244 return_ACPI_STATUS(AE_AML_INVALID_INDEX); 245 } 246 247 /* Return a pointer to the pseudo-node */ 248 249 *node = &walk_state->arguments[index]; 250 break; 251 252 default: 253 254 ACPI_ERROR((AE_INFO, "Type %u is invalid", type)); 255 return_ACPI_STATUS(AE_TYPE); 256 } 257 258 return_ACPI_STATUS(AE_OK); 259} 260 261/******************************************************************************* 262 * 263 * FUNCTION: acpi_ds_method_data_set_value 264 * 265 * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or 266 * ACPI_REFCLASS_ARG 267 * index - Which Local or Arg to get 268 * object - Object to be inserted into the stack entry 269 * walk_state - Current walk state object 270 * 271 * RETURN: Status 272 * 273 * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index. 274 * Note: There is no "implicit conversion" for locals. 275 * 276 ******************************************************************************/ 277 278static acpi_status 279acpi_ds_method_data_set_value(u8 type, 280 u32 index, 281 union acpi_operand_object *object, 282 struct acpi_walk_state *walk_state) 283{ 284 acpi_status status; 285 struct acpi_namespace_node *node; 286 287 ACPI_FUNCTION_TRACE(ds_method_data_set_value); 288 289 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 290 "NewObj %p Type %2.2X, Refs=%u [%s]\n", object, 291 type, object->common.reference_count, 292 acpi_ut_get_type_name(object->common.type))); 293 294 /* Get the namespace node for the arg/local */ 295 296 status = acpi_ds_method_data_get_node(type, index, walk_state, &node); 297 if (ACPI_FAILURE(status)) { 298 return_ACPI_STATUS(status); 299 } 300 301 /* 302 * Increment ref count so object can't be deleted while installed. 303 * NOTE: We do not copy the object in order to preserve the call by 304 * reference semantics of ACPI Control Method invocation. 305 * (See ACPI Specification 2.0C) 306 */ 307 acpi_ut_add_reference(object); 308 309 /* Install the object */ 310 311 node->object = object; 312 return_ACPI_STATUS(status); 313} 314 315/******************************************************************************* 316 * 317 * FUNCTION: acpi_ds_method_data_get_value 318 * 319 * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or 320 * ACPI_REFCLASS_ARG 321 * index - Which localVar or argument to get 322 * walk_state - Current walk state object 323 * dest_desc - Where Arg or Local value is returned 324 * 325 * RETURN: Status 326 * 327 * DESCRIPTION: Retrieve value of selected Arg or Local for this method 328 * Used only in acpi_ex_resolve_to_value(). 329 * 330 ******************************************************************************/ 331 332acpi_status 333acpi_ds_method_data_get_value(u8 type, 334 u32 index, 335 struct acpi_walk_state *walk_state, 336 union acpi_operand_object **dest_desc) 337{ 338 acpi_status status; 339 struct acpi_namespace_node *node; 340 union acpi_operand_object *object; 341 342 ACPI_FUNCTION_TRACE(ds_method_data_get_value); 343 344 /* Validate the object descriptor */ 345 346 if (!dest_desc) { 347 ACPI_ERROR((AE_INFO, "Null object descriptor pointer")); 348 return_ACPI_STATUS(AE_BAD_PARAMETER); 349 } 350 351 /* Get the namespace node for the arg/local */ 352 353 status = acpi_ds_method_data_get_node(type, index, walk_state, &node); 354 if (ACPI_FAILURE(status)) { 355 return_ACPI_STATUS(status); 356 } 357 358 /* Get the object from the node */ 359 360 object = node->object; 361 362 /* Examine the returned object, it must be valid. */ 363 364 if (!object) { 365 /* 366 * Index points to uninitialized object. 367 * This means that either 1) The expected argument was 368 * not passed to the method, or 2) A local variable 369 * was referenced by the method (via the ASL) 370 * before it was initialized. Either case is an error. 371 */ 372 373 /* If slack enabled, init the local_x/arg_x to an Integer of value zero */ 374 375 if (acpi_gbl_enable_interpreter_slack) { 376 object = acpi_ut_create_integer_object((u64) 0); 377 if (!object) { 378 return_ACPI_STATUS(AE_NO_MEMORY); 379 } 380 381 node->object = object; 382 } 383 384 /* Otherwise, return the error */ 385 386 else 387 switch (type) { 388 case ACPI_REFCLASS_ARG: 389 390 ACPI_ERROR((AE_INFO, 391 "Uninitialized Arg[%u] at node %p", 392 index, node)); 393 394 return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG); 395 396 case ACPI_REFCLASS_LOCAL: 397 /* 398 * No error message for this case, will be trapped again later to 399 * detect and ignore cases of Store(local_x,local_x) 400 */ 401 return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL); 402 403 default: 404 405 ACPI_ERROR((AE_INFO, 406 "Not a Arg/Local opcode: 0x%X", 407 type)); 408 return_ACPI_STATUS(AE_AML_INTERNAL); 409 } 410 } 411 412 /* 413 * The Index points to an initialized and valid object. 414 * Return an additional reference to the object 415 */ 416 *dest_desc = object; 417 acpi_ut_add_reference(object); 418 419 return_ACPI_STATUS(AE_OK); 420} 421 422/******************************************************************************* 423 * 424 * FUNCTION: acpi_ds_method_data_delete_value 425 * 426 * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or 427 * ACPI_REFCLASS_ARG 428 * index - Which localVar or argument to delete 429 * walk_state - Current walk state object 430 * 431 * RETURN: None 432 * 433 * DESCRIPTION: Delete the entry at Opcode:Index. Inserts 434 * a null into the stack slot after the object is deleted. 435 * 436 ******************************************************************************/ 437 438static void 439acpi_ds_method_data_delete_value(u8 type, 440 u32 index, struct acpi_walk_state *walk_state) 441{ 442 acpi_status status; 443 struct acpi_namespace_node *node; 444 union acpi_operand_object *object; 445 446 ACPI_FUNCTION_TRACE(ds_method_data_delete_value); 447 448 /* Get the namespace node for the arg/local */ 449 450 status = acpi_ds_method_data_get_node(type, index, walk_state, &node); 451 if (ACPI_FAILURE(status)) { 452 return_VOID; 453 } 454 455 /* Get the associated object */ 456 457 object = acpi_ns_get_attached_object(node); 458 459 /* 460 * Undefine the Arg or Local by setting its descriptor 461 * pointer to NULL. Locals/Args can contain both 462 * ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs 463 */ 464 node->object = NULL; 465 466 if ((object) && 467 (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_OPERAND)) { 468 /* 469 * There is a valid object. 470 * Decrement the reference count by one to balance the 471 * increment when the object was stored. 472 */ 473 acpi_ut_remove_reference(object); 474 } 475 476 return_VOID; 477} 478 479/******************************************************************************* 480 * 481 * FUNCTION: acpi_ds_store_object_to_local 482 * 483 * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or 484 * ACPI_REFCLASS_ARG 485 * index - Which Local or Arg to set 486 * obj_desc - Value to be stored 487 * walk_state - Current walk state 488 * 489 * RETURN: Status 490 * 491 * DESCRIPTION: Store a value in an Arg or Local. The obj_desc is installed 492 * as the new value for the Arg or Local and the reference count 493 * for obj_desc is incremented. 494 * 495 ******************************************************************************/ 496 497acpi_status 498acpi_ds_store_object_to_local(u8 type, 499 u32 index, 500 union acpi_operand_object *obj_desc, 501 struct acpi_walk_state *walk_state) 502{ 503 acpi_status status; 504 struct acpi_namespace_node *node; 505 union acpi_operand_object *current_obj_desc; 506 union acpi_operand_object *new_obj_desc; 507 508 ACPI_FUNCTION_TRACE(ds_store_object_to_local); 509 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Type=%2.2X Index=%u Obj=%p\n", 510 type, index, obj_desc)); 511 512 /* Parameter validation */ 513 514 if (!obj_desc) { 515 return_ACPI_STATUS(AE_BAD_PARAMETER); 516 } 517 518 /* Get the namespace node for the arg/local */ 519 520 status = acpi_ds_method_data_get_node(type, index, walk_state, &node); 521 if (ACPI_FAILURE(status)) { 522 return_ACPI_STATUS(status); 523 } 524 525 current_obj_desc = acpi_ns_get_attached_object(node); 526 if (current_obj_desc == obj_desc) { 527 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p already installed!\n", 528 obj_desc)); 529 return_ACPI_STATUS(status); 530 } 531 532 /* 533 * If the reference count on the object is more than one, we must 534 * take a copy of the object before we store. A reference count 535 * of exactly 1 means that the object was just created during the 536 * evaluation of an expression, and we can safely use it since it 537 * is not used anywhere else. 538 */ 539 new_obj_desc = obj_desc; 540 if (obj_desc->common.reference_count > 1) { 541 status = 542 acpi_ut_copy_iobject_to_iobject(obj_desc, &new_obj_desc, 543 walk_state); 544 if (ACPI_FAILURE(status)) { 545 return_ACPI_STATUS(status); 546 } 547 } 548 549 /* 550 * If there is an object already in this slot, we either 551 * have to delete it, or if this is an argument and there 552 * is an object reference stored there, we have to do 553 * an indirect store! 554 */ 555 if (current_obj_desc) { 556 /* 557 * Check for an indirect store if an argument 558 * contains an object reference (stored as an Node). 559 * We don't allow this automatic dereferencing for 560 * locals, since a store to a local should overwrite 561 * anything there, including an object reference. 562 * 563 * If both Arg0 and Local0 contain ref_of (Local4): 564 * 565 * Store (1, Arg0) - Causes indirect store to local4 566 * Store (1, Local0) - Stores 1 in local0, overwriting 567 * the reference to local4 568 * Store (1, de_refof (Local0)) - Causes indirect store to local4 569 * 570 * Weird, but true. 571 */ 572 if (type == ACPI_REFCLASS_ARG) { 573 /* 574 * If we have a valid reference object that came from ref_of(), 575 * do the indirect store 576 */ 577 if ((ACPI_GET_DESCRIPTOR_TYPE(current_obj_desc) == 578 ACPI_DESC_TYPE_OPERAND) && 579 (current_obj_desc->common.type == 580 ACPI_TYPE_LOCAL_REFERENCE) && 581 (current_obj_desc->reference.class == 582 ACPI_REFCLASS_REFOF)) { 583 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 584 "Arg (%p) is an ObjRef(Node), storing in node %p\n", 585 new_obj_desc, 586 current_obj_desc)); 587 588 /* 589 * Store this object to the Node (perform the indirect store) 590 * NOTE: No implicit conversion is performed, as per the ACPI 591 * specification rules on storing to Locals/Args. 592 */ 593 status = 594 acpi_ex_store_object_to_node(new_obj_desc, 595 current_obj_desc-> 596 reference. 597 object, 598 walk_state, 599 ACPI_NO_IMPLICIT_CONVERSION); 600 601 /* Remove local reference if we copied the object above */ 602 603 if (new_obj_desc != obj_desc) { 604 acpi_ut_remove_reference(new_obj_desc); 605 } 606 607 return_ACPI_STATUS(status); 608 } 609 } 610 611 /* Delete the existing object before storing the new one */ 612 613 acpi_ds_method_data_delete_value(type, index, walk_state); 614 } 615 616 /* 617 * Install the Obj descriptor (*new_obj_desc) into 618 * the descriptor for the Arg or Local. 619 * (increments the object reference count by one) 620 */ 621 status = 622 acpi_ds_method_data_set_value(type, index, new_obj_desc, 623 walk_state); 624 625 /* Remove local reference if we copied the object above */ 626 627 if (new_obj_desc != obj_desc) { 628 acpi_ut_remove_reference(new_obj_desc); 629 } 630 631 return_ACPI_STATUS(status); 632} 633 634#ifdef ACPI_OBSOLETE_FUNCTIONS 635/******************************************************************************* 636 * 637 * FUNCTION: acpi_ds_method_data_get_type 638 * 639 * PARAMETERS: opcode - Either AML_FIRST LOCAL_OP or 640 * AML_FIRST_ARG_OP 641 * index - Which Local or Arg whose type to get 642 * walk_state - Current walk state object 643 * 644 * RETURN: Data type of current value of the selected Arg or Local 645 * 646 * DESCRIPTION: Get the type of the object stored in the Local or Arg 647 * 648 ******************************************************************************/ 649 650acpi_object_type 651acpi_ds_method_data_get_type(u16 opcode, 652 u32 index, struct acpi_walk_state *walk_state) 653{ 654 acpi_status status; 655 struct acpi_namespace_node *node; 656 union acpi_operand_object *object; 657 658 ACPI_FUNCTION_TRACE(ds_method_data_get_type); 659 660 /* Get the namespace node for the arg/local */ 661 662 status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node); 663 if (ACPI_FAILURE(status)) { 664 return_VALUE((ACPI_TYPE_NOT_FOUND)); 665 } 666 667 /* Get the object */ 668 669 object = acpi_ns_get_attached_object(node); 670 if (!object) { 671 672 /* Uninitialized local/arg, return TYPE_ANY */ 673 674 return_VALUE(ACPI_TYPE_ANY); 675 } 676 677 /* Get the object type */ 678 679 return_VALUE(object->type); 680} 681#endif