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