dsmthdat.c 19 KB

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