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 15 ACPI_MODULE_NAME("dsmthdat") 16 17 /* Local prototypes */ 18 static void 19 acpi_ds_method_data_delete_value(u8 type, 20 u32 index, struct acpi_walk_state *walk_state); 21 22 static acpi_status 23 acpi_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 29 acpi_object_type 30 acpi_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 55 void 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 102 void 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 157 acpi_status 158 acpi_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 acpi_ex_trace_args(params, index); 192 193 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%u args passed to method\n", index)); 194 return_ACPI_STATUS(AE_OK); 195 } 196 197 /******************************************************************************* 198 * 199 * FUNCTION: acpi_ds_method_data_get_node 200 * 201 * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or 202 * ACPI_REFCLASS_ARG 203 * index - Which Local or Arg whose type to get 204 * walk_state - Current walk state object 205 * node - Where the node is returned. 206 * 207 * RETURN: Status and node 208 * 209 * DESCRIPTION: Get the Node associated with a local or arg. 210 * 211 ******************************************************************************/ 212 213 acpi_status 214 acpi_ds_method_data_get_node(u8 type, 215 u32 index, 216 struct acpi_walk_state *walk_state, 217 struct acpi_namespace_node **node) 218 { 219 ACPI_FUNCTION_TRACE(ds_method_data_get_node); 220 221 /* 222 * Method Locals and Arguments are supported 223 */ 224 switch (type) { 225 case ACPI_REFCLASS_LOCAL: 226 227 if (index > ACPI_METHOD_MAX_LOCAL) { 228 ACPI_ERROR((AE_INFO, 229 "Local index %u is invalid (max %u)", 230 index, ACPI_METHOD_MAX_LOCAL)); 231 return_ACPI_STATUS(AE_AML_INVALID_INDEX); 232 } 233 234 /* Return a pointer to the pseudo-node */ 235 236 *node = &walk_state->local_variables[index]; 237 break; 238 239 case ACPI_REFCLASS_ARG: 240 241 if (index > ACPI_METHOD_MAX_ARG) { 242 ACPI_ERROR((AE_INFO, 243 "Arg index %u is invalid (max %u)", 244 index, ACPI_METHOD_MAX_ARG)); 245 return_ACPI_STATUS(AE_AML_INVALID_INDEX); 246 } 247 248 /* Return a pointer to the pseudo-node */ 249 250 *node = &walk_state->arguments[index]; 251 break; 252 253 default: 254 255 ACPI_ERROR((AE_INFO, "Type %u is invalid", type)); 256 return_ACPI_STATUS(AE_TYPE); 257 } 258 259 return_ACPI_STATUS(AE_OK); 260 } 261 262 /******************************************************************************* 263 * 264 * FUNCTION: acpi_ds_method_data_set_value 265 * 266 * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or 267 * ACPI_REFCLASS_ARG 268 * index - Which Local or Arg to get 269 * object - Object to be inserted into the stack entry 270 * walk_state - Current walk state object 271 * 272 * RETURN: Status 273 * 274 * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index. 275 * Note: There is no "implicit conversion" for locals. 276 * 277 ******************************************************************************/ 278 279 static acpi_status 280 acpi_ds_method_data_set_value(u8 type, 281 u32 index, 282 union acpi_operand_object *object, 283 struct acpi_walk_state *walk_state) 284 { 285 acpi_status status; 286 struct acpi_namespace_node *node; 287 288 ACPI_FUNCTION_TRACE(ds_method_data_set_value); 289 290 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 291 "NewObj %p Type %2.2X, Refs=%u [%s]\n", object, 292 type, object->common.reference_count, 293 acpi_ut_get_type_name(object->common.type))); 294 295 /* Get the namespace node for the arg/local */ 296 297 status = acpi_ds_method_data_get_node(type, index, walk_state, &node); 298 if (ACPI_FAILURE(status)) { 299 return_ACPI_STATUS(status); 300 } 301 302 /* 303 * Increment ref count so object can't be deleted while installed. 304 * NOTE: We do not copy the object in order to preserve the call by 305 * reference semantics of ACPI Control Method invocation. 306 * (See ACPI Specification 2.0C) 307 */ 308 acpi_ut_add_reference(object); 309 310 /* Install the object */ 311 312 node->object = object; 313 return_ACPI_STATUS(status); 314 } 315 316 /******************************************************************************* 317 * 318 * FUNCTION: acpi_ds_method_data_get_value 319 * 320 * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or 321 * ACPI_REFCLASS_ARG 322 * index - Which localVar or argument to get 323 * walk_state - Current walk state object 324 * dest_desc - Where Arg or Local value is returned 325 * 326 * RETURN: Status 327 * 328 * DESCRIPTION: Retrieve value of selected Arg or Local for this method 329 * Used only in acpi_ex_resolve_to_value(). 330 * 331 ******************************************************************************/ 332 333 acpi_status 334 acpi_ds_method_data_get_value(u8 type, 335 u32 index, 336 struct acpi_walk_state *walk_state, 337 union acpi_operand_object **dest_desc) 338 { 339 acpi_status status; 340 struct acpi_namespace_node *node; 341 union acpi_operand_object *object; 342 343 ACPI_FUNCTION_TRACE(ds_method_data_get_value); 344 345 /* Validate the object descriptor */ 346 347 if (!dest_desc) { 348 ACPI_ERROR((AE_INFO, "Null object descriptor pointer")); 349 return_ACPI_STATUS(AE_BAD_PARAMETER); 350 } 351 352 /* Get the namespace node for the arg/local */ 353 354 status = acpi_ds_method_data_get_node(type, index, walk_state, &node); 355 if (ACPI_FAILURE(status)) { 356 return_ACPI_STATUS(status); 357 } 358 359 /* Get the object from the node */ 360 361 object = node->object; 362 363 /* Examine the returned object, it must be valid. */ 364 365 if (!object) { 366 /* 367 * Index points to uninitialized object. 368 * This means that either 1) The expected argument was 369 * not passed to the method, or 2) A local variable 370 * was referenced by the method (via the ASL) 371 * before it was initialized. Either case is an error. 372 */ 373 374 /* If slack enabled, init the local_x/arg_x to an Integer of value zero */ 375 376 if (acpi_gbl_enable_interpreter_slack) { 377 object = acpi_ut_create_integer_object((u64) 0); 378 if (!object) { 379 return_ACPI_STATUS(AE_NO_MEMORY); 380 } 381 382 node->object = object; 383 } 384 385 /* Otherwise, return the error */ 386 387 else 388 switch (type) { 389 case ACPI_REFCLASS_ARG: 390 391 ACPI_ERROR((AE_INFO, 392 "Uninitialized Arg[%u] at node %p", 393 index, node)); 394 395 return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG); 396 397 case ACPI_REFCLASS_LOCAL: 398 /* 399 * No error message for this case, will be trapped again later to 400 * detect and ignore cases of Store(local_x,local_x) 401 */ 402 return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL); 403 404 default: 405 406 ACPI_ERROR((AE_INFO, 407 "Not a Arg/Local opcode: 0x%X", 408 type)); 409 return_ACPI_STATUS(AE_AML_INTERNAL); 410 } 411 } 412 413 /* 414 * The Index points to an initialized and valid object. 415 * Return an additional reference to the object 416 */ 417 *dest_desc = object; 418 acpi_ut_add_reference(object); 419 420 return_ACPI_STATUS(AE_OK); 421 } 422 423 /******************************************************************************* 424 * 425 * FUNCTION: acpi_ds_method_data_delete_value 426 * 427 * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or 428 * ACPI_REFCLASS_ARG 429 * index - Which localVar or argument to delete 430 * walk_state - Current walk state object 431 * 432 * RETURN: None 433 * 434 * DESCRIPTION: Delete the entry at Opcode:Index. Inserts 435 * a null into the stack slot after the object is deleted. 436 * 437 ******************************************************************************/ 438 439 static void 440 acpi_ds_method_data_delete_value(u8 type, 441 u32 index, struct acpi_walk_state *walk_state) 442 { 443 acpi_status status; 444 struct acpi_namespace_node *node; 445 union acpi_operand_object *object; 446 447 ACPI_FUNCTION_TRACE(ds_method_data_delete_value); 448 449 /* Get the namespace node for the arg/local */ 450 451 status = acpi_ds_method_data_get_node(type, index, walk_state, &node); 452 if (ACPI_FAILURE(status)) { 453 return_VOID; 454 } 455 456 /* Get the associated object */ 457 458 object = acpi_ns_get_attached_object(node); 459 460 /* 461 * Undefine the Arg or Local by setting its descriptor 462 * pointer to NULL. Locals/Args can contain both 463 * ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs 464 */ 465 node->object = NULL; 466 467 if ((object) && 468 (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_OPERAND)) { 469 /* 470 * There is a valid object. 471 * Decrement the reference count by one to balance the 472 * increment when the object was stored. 473 */ 474 acpi_ut_remove_reference(object); 475 } 476 477 return_VOID; 478 } 479 480 /******************************************************************************* 481 * 482 * FUNCTION: acpi_ds_store_object_to_local 483 * 484 * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or 485 * ACPI_REFCLASS_ARG 486 * index - Which Local or Arg to set 487 * obj_desc - Value to be stored 488 * walk_state - Current walk state 489 * 490 * RETURN: Status 491 * 492 * DESCRIPTION: Store a value in an Arg or Local. The obj_desc is installed 493 * as the new value for the Arg or Local and the reference count 494 * for obj_desc is incremented. 495 * 496 ******************************************************************************/ 497 498 acpi_status 499 acpi_ds_store_object_to_local(u8 type, 500 u32 index, 501 union acpi_operand_object *obj_desc, 502 struct acpi_walk_state *walk_state) 503 { 504 acpi_status status; 505 struct acpi_namespace_node *node; 506 union acpi_operand_object *current_obj_desc; 507 union acpi_operand_object *new_obj_desc; 508 509 ACPI_FUNCTION_TRACE(ds_store_object_to_local); 510 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Type=%2.2X Index=%u Obj=%p\n", 511 type, index, obj_desc)); 512 513 /* Parameter validation */ 514 515 if (!obj_desc) { 516 return_ACPI_STATUS(AE_BAD_PARAMETER); 517 } 518 519 /* Get the namespace node for the arg/local */ 520 521 status = acpi_ds_method_data_get_node(type, index, walk_state, &node); 522 if (ACPI_FAILURE(status)) { 523 return_ACPI_STATUS(status); 524 } 525 526 current_obj_desc = acpi_ns_get_attached_object(node); 527 if (current_obj_desc == obj_desc) { 528 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p already installed!\n", 529 obj_desc)); 530 return_ACPI_STATUS(status); 531 } 532 533 /* 534 * If the reference count on the object is more than one, we must 535 * take a copy of the object before we store. A reference count 536 * of exactly 1 means that the object was just created during the 537 * evaluation of an expression, and we can safely use it since it 538 * is not used anywhere else. 539 */ 540 new_obj_desc = obj_desc; 541 if (obj_desc->common.reference_count > 1) { 542 status = 543 acpi_ut_copy_iobject_to_iobject(obj_desc, &new_obj_desc, 544 walk_state); 545 if (ACPI_FAILURE(status)) { 546 return_ACPI_STATUS(status); 547 } 548 } 549 550 /* 551 * If there is an object already in this slot, we either 552 * have to delete it, or if this is an argument and there 553 * is an object reference stored there, we have to do 554 * an indirect store! 555 */ 556 if (current_obj_desc) { 557 /* 558 * Check for an indirect store if an argument 559 * contains an object reference (stored as an Node). 560 * We don't allow this automatic dereferencing for 561 * locals, since a store to a local should overwrite 562 * anything there, including an object reference. 563 * 564 * If both Arg0 and Local0 contain ref_of (Local4): 565 * 566 * Store (1, Arg0) - Causes indirect store to local4 567 * Store (1, Local0) - Stores 1 in local0, overwriting 568 * the reference to local4 569 * Store (1, de_refof (Local0)) - Causes indirect store to local4 570 * 571 * Weird, but true. 572 */ 573 if (type == ACPI_REFCLASS_ARG) { 574 /* 575 * If we have a valid reference object that came from ref_of(), 576 * do the indirect store 577 */ 578 if ((ACPI_GET_DESCRIPTOR_TYPE(current_obj_desc) == 579 ACPI_DESC_TYPE_OPERAND) && 580 (current_obj_desc->common.type == 581 ACPI_TYPE_LOCAL_REFERENCE) && 582 (current_obj_desc->reference.class == 583 ACPI_REFCLASS_REFOF)) { 584 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 585 "Arg (%p) is an ObjRef(Node), storing in node %p\n", 586 new_obj_desc, 587 current_obj_desc)); 588 589 /* 590 * Store this object to the Node (perform the indirect store) 591 * NOTE: No implicit conversion is performed, as per the ACPI 592 * specification rules on storing to Locals/Args. 593 */ 594 status = 595 acpi_ex_store_object_to_node(new_obj_desc, 596 current_obj_desc-> 597 reference. 598 object, 599 walk_state, 600 ACPI_NO_IMPLICIT_CONVERSION); 601 602 /* Remove local reference if we copied the object above */ 603 604 if (new_obj_desc != obj_desc) { 605 acpi_ut_remove_reference(new_obj_desc); 606 } 607 608 return_ACPI_STATUS(status); 609 } 610 } 611 612 /* Delete the existing object before storing the new one */ 613 614 acpi_ds_method_data_delete_value(type, index, walk_state); 615 } 616 617 /* 618 * Install the Obj descriptor (*new_obj_desc) into 619 * the descriptor for the Arg or Local. 620 * (increments the object reference count by one) 621 */ 622 status = 623 acpi_ds_method_data_set_value(type, index, new_obj_desc, 624 walk_state); 625 626 /* Remove local reference if we copied the object above */ 627 628 if (new_obj_desc != obj_desc) { 629 acpi_ut_remove_reference(new_obj_desc); 630 } 631 632 return_ACPI_STATUS(status); 633 } 634 635 #ifdef ACPI_OBSOLETE_FUNCTIONS 636 /******************************************************************************* 637 * 638 * FUNCTION: acpi_ds_method_data_get_type 639 * 640 * PARAMETERS: opcode - Either AML_FIRST LOCAL_OP or 641 * AML_FIRST_ARG_OP 642 * index - Which Local or Arg whose type to get 643 * walk_state - Current walk state object 644 * 645 * RETURN: Data type of current value of the selected Arg or Local 646 * 647 * DESCRIPTION: Get the type of the object stored in the Local or Arg 648 * 649 ******************************************************************************/ 650 651 acpi_object_type 652 acpi_ds_method_data_get_type(u16 opcode, 653 u32 index, struct acpi_walk_state *walk_state) 654 { 655 acpi_status status; 656 struct acpi_namespace_node *node; 657 union acpi_operand_object *object; 658 659 ACPI_FUNCTION_TRACE(ds_method_data_get_type); 660 661 /* Get the namespace node for the arg/local */ 662 663 status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node); 664 if (ACPI_FAILURE(status)) { 665 return_VALUE((ACPI_TYPE_NOT_FOUND)); 666 } 667 668 /* Get the object */ 669 670 object = acpi_ns_get_attached_object(node); 671 if (!object) { 672 673 /* Uninitialized local/arg, return TYPE_ANY */ 674 675 return_VALUE(ACPI_TYPE_ANY); 676 } 677 678 /* Get the object type */ 679 680 return_VALUE(object->type); 681 } 682 #endif 683