dsmthdat.c 19 KB

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