exoparg2.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /******************************************************************************
  3. *
  4. * Module Name: exoparg2 - AML execution - opcodes with 2 arguments
  5. *
  6. * Copyright (C) 2000 - 2022, Intel Corp.
  7. *
  8. *****************************************************************************/
  9. #include <acpi/acpi.h>
  10. #include "accommon.h"
  11. #include "acparser.h"
  12. #include "acinterp.h"
  13. #include "acevents.h"
  14. #include "amlcode.h"
  15. #define _COMPONENT ACPI_EXECUTER
  16. ACPI_MODULE_NAME("exoparg2")
  17. /*!
  18. * Naming convention for AML interpreter execution routines.
  19. *
  20. * The routines that begin execution of AML opcodes are named with a common
  21. * convention based upon the number of arguments, the number of target operands,
  22. * and whether or not a value is returned:
  23. *
  24. * AcpiExOpcode_xA_yT_zR
  25. *
  26. * Where:
  27. *
  28. * xA - ARGUMENTS: The number of arguments (input operands) that are
  29. * required for this opcode type (1 through 6 args).
  30. * yT - TARGETS: The number of targets (output operands) that are required
  31. * for this opcode type (0, 1, or 2 targets).
  32. * zR - RETURN VALUE: Indicates whether this opcode type returns a value
  33. * as the function return (0 or 1).
  34. *
  35. * The AcpiExOpcode* functions are called via the Dispatcher component with
  36. * fully resolved operands.
  37. !*/
  38. /*******************************************************************************
  39. *
  40. * FUNCTION: acpi_ex_opcode_2A_0T_0R
  41. *
  42. * PARAMETERS: walk_state - Current walk state
  43. *
  44. * RETURN: Status
  45. *
  46. * DESCRIPTION: Execute opcode with two arguments, no target, and no return
  47. * value.
  48. *
  49. * ALLOCATION: Deletes both operands
  50. *
  51. ******************************************************************************/
  52. acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
  53. {
  54. union acpi_operand_object **operand = &walk_state->operands[0];
  55. struct acpi_namespace_node *node;
  56. u32 value;
  57. acpi_status status = AE_OK;
  58. ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_0R,
  59. acpi_ps_get_opcode_name(walk_state->opcode));
  60. /* Examine the opcode */
  61. switch (walk_state->opcode) {
  62. case AML_NOTIFY_OP: /* Notify (notify_object, notify_value) */
  63. /* The first operand is a namespace node */
  64. node = (struct acpi_namespace_node *)operand[0];
  65. /* Second value is the notify value */
  66. value = (u32) operand[1]->integer.value;
  67. /* Are notifies allowed on this object? */
  68. if (!acpi_ev_is_notify_object(node)) {
  69. ACPI_ERROR((AE_INFO,
  70. "Unexpected notify object type [%s]",
  71. acpi_ut_get_type_name(node->type)));
  72. status = AE_AML_OPERAND_TYPE;
  73. break;
  74. }
  75. /*
  76. * Dispatch the notify to the appropriate handler
  77. * NOTE: the request is queued for execution after this method
  78. * completes. The notify handlers are NOT invoked synchronously
  79. * from this thread -- because handlers may in turn run other
  80. * control methods.
  81. */
  82. status = acpi_ev_queue_notify_request(node, value);
  83. break;
  84. default:
  85. ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
  86. walk_state->opcode));
  87. status = AE_AML_BAD_OPCODE;
  88. }
  89. return_ACPI_STATUS(status);
  90. }
  91. /*******************************************************************************
  92. *
  93. * FUNCTION: acpi_ex_opcode_2A_2T_1R
  94. *
  95. * PARAMETERS: walk_state - Current walk state
  96. *
  97. * RETURN: Status
  98. *
  99. * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets
  100. * and one implicit return value.
  101. *
  102. ******************************************************************************/
  103. acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state)
  104. {
  105. union acpi_operand_object **operand = &walk_state->operands[0];
  106. union acpi_operand_object *return_desc1 = NULL;
  107. union acpi_operand_object *return_desc2 = NULL;
  108. acpi_status status;
  109. ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_2T_1R,
  110. acpi_ps_get_opcode_name(walk_state->opcode));
  111. /* Execute the opcode */
  112. switch (walk_state->opcode) {
  113. case AML_DIVIDE_OP:
  114. /* Divide (Dividend, Divisor, remainder_result quotient_result) */
  115. return_desc1 =
  116. acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
  117. if (!return_desc1) {
  118. status = AE_NO_MEMORY;
  119. goto cleanup;
  120. }
  121. return_desc2 =
  122. acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
  123. if (!return_desc2) {
  124. status = AE_NO_MEMORY;
  125. goto cleanup;
  126. }
  127. /* Quotient to return_desc1, remainder to return_desc2 */
  128. status = acpi_ut_divide(operand[0]->integer.value,
  129. operand[1]->integer.value,
  130. &return_desc1->integer.value,
  131. &return_desc2->integer.value);
  132. if (ACPI_FAILURE(status)) {
  133. goto cleanup;
  134. }
  135. break;
  136. default:
  137. ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
  138. walk_state->opcode));
  139. status = AE_AML_BAD_OPCODE;
  140. goto cleanup;
  141. }
  142. /* Store the results to the target reference operands */
  143. status = acpi_ex_store(return_desc2, operand[2], walk_state);
  144. if (ACPI_FAILURE(status)) {
  145. goto cleanup;
  146. }
  147. status = acpi_ex_store(return_desc1, operand[3], walk_state);
  148. if (ACPI_FAILURE(status)) {
  149. goto cleanup;
  150. }
  151. cleanup:
  152. /*
  153. * Since the remainder is not returned indirectly, remove a reference to
  154. * it. Only the quotient is returned indirectly.
  155. */
  156. acpi_ut_remove_reference(return_desc2);
  157. if (ACPI_FAILURE(status)) {
  158. /* Delete the return object */
  159. acpi_ut_remove_reference(return_desc1);
  160. }
  161. /* Save return object (the remainder) on success */
  162. else {
  163. walk_state->result_obj = return_desc1;
  164. }
  165. return_ACPI_STATUS(status);
  166. }
  167. /*******************************************************************************
  168. *
  169. * FUNCTION: acpi_ex_opcode_2A_1T_1R
  170. *
  171. * PARAMETERS: walk_state - Current walk state
  172. *
  173. * RETURN: Status
  174. *
  175. * DESCRIPTION: Execute opcode with two arguments, one target, and a return
  176. * value.
  177. *
  178. ******************************************************************************/
  179. acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
  180. {
  181. union acpi_operand_object **operand = &walk_state->operands[0];
  182. union acpi_operand_object *return_desc = NULL;
  183. u64 index;
  184. acpi_status status = AE_OK;
  185. acpi_size length = 0;
  186. ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_1T_1R,
  187. acpi_ps_get_opcode_name(walk_state->opcode));
  188. /* Execute the opcode */
  189. if (walk_state->op_info->flags & AML_MATH) {
  190. /* All simple math opcodes (add, etc.) */
  191. return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
  192. if (!return_desc) {
  193. status = AE_NO_MEMORY;
  194. goto cleanup;
  195. }
  196. return_desc->integer.value =
  197. acpi_ex_do_math_op(walk_state->opcode,
  198. operand[0]->integer.value,
  199. operand[1]->integer.value);
  200. goto store_result_to_target;
  201. }
  202. switch (walk_state->opcode) {
  203. case AML_MOD_OP: /* Mod (Dividend, Divisor, remainder_result (ACPI 2.0) */
  204. return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
  205. if (!return_desc) {
  206. status = AE_NO_MEMORY;
  207. goto cleanup;
  208. }
  209. /* return_desc will contain the remainder */
  210. status = acpi_ut_divide(operand[0]->integer.value,
  211. operand[1]->integer.value,
  212. NULL, &return_desc->integer.value);
  213. break;
  214. case AML_CONCATENATE_OP: /* Concatenate (Data1, Data2, Result) */
  215. status =
  216. acpi_ex_do_concatenate(operand[0], operand[1], &return_desc,
  217. walk_state);
  218. break;
  219. case AML_TO_STRING_OP: /* to_string (Buffer, Length, Result) (ACPI 2.0) */
  220. /*
  221. * Input object is guaranteed to be a buffer at this point (it may have
  222. * been converted.) Copy the raw buffer data to a new object of
  223. * type String.
  224. */
  225. /*
  226. * Get the length of the new string. It is the smallest of:
  227. * 1) Length of the input buffer
  228. * 2) Max length as specified in the to_string operator
  229. * 3) Length of input buffer up to a zero byte (null terminator)
  230. *
  231. * NOTE: A length of zero is ok, and will create a zero-length, null
  232. * terminated string.
  233. */
  234. while ((length < operand[0]->buffer.length) && /* Length of input buffer */
  235. (length < operand[1]->integer.value) && /* Length operand */
  236. (operand[0]->buffer.pointer[length])) { /* Null terminator */
  237. length++;
  238. }
  239. /* Allocate a new string object */
  240. return_desc = acpi_ut_create_string_object(length);
  241. if (!return_desc) {
  242. status = AE_NO_MEMORY;
  243. goto cleanup;
  244. }
  245. /*
  246. * Copy the raw buffer data with no transform.
  247. * (NULL terminated already)
  248. */
  249. memcpy(return_desc->string.pointer,
  250. operand[0]->buffer.pointer, length);
  251. break;
  252. case AML_CONCATENATE_TEMPLATE_OP:
  253. /* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */
  254. status =
  255. acpi_ex_concat_template(operand[0], operand[1],
  256. &return_desc, walk_state);
  257. break;
  258. case AML_INDEX_OP: /* Index (Source Index Result) */
  259. /* Create the internal return object */
  260. return_desc =
  261. acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
  262. if (!return_desc) {
  263. status = AE_NO_MEMORY;
  264. goto cleanup;
  265. }
  266. /* Initialize the Index reference object */
  267. index = operand[1]->integer.value;
  268. return_desc->reference.value = (u32) index;
  269. return_desc->reference.class = ACPI_REFCLASS_INDEX;
  270. /*
  271. * At this point, the Source operand is a String, Buffer, or Package.
  272. * Verify that the index is within range.
  273. */
  274. switch ((operand[0])->common.type) {
  275. case ACPI_TYPE_STRING:
  276. if (index >= operand[0]->string.length) {
  277. length = operand[0]->string.length;
  278. status = AE_AML_STRING_LIMIT;
  279. }
  280. return_desc->reference.target_type =
  281. ACPI_TYPE_BUFFER_FIELD;
  282. return_desc->reference.index_pointer =
  283. &(operand[0]->buffer.pointer[index]);
  284. break;
  285. case ACPI_TYPE_BUFFER:
  286. if (index >= operand[0]->buffer.length) {
  287. length = operand[0]->buffer.length;
  288. status = AE_AML_BUFFER_LIMIT;
  289. }
  290. return_desc->reference.target_type =
  291. ACPI_TYPE_BUFFER_FIELD;
  292. return_desc->reference.index_pointer =
  293. &(operand[0]->buffer.pointer[index]);
  294. break;
  295. case ACPI_TYPE_PACKAGE:
  296. if (index >= operand[0]->package.count) {
  297. length = operand[0]->package.count;
  298. status = AE_AML_PACKAGE_LIMIT;
  299. }
  300. return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
  301. return_desc->reference.where =
  302. &operand[0]->package.elements[index];
  303. break;
  304. default:
  305. ACPI_ERROR((AE_INFO,
  306. "Invalid object type: %X",
  307. (operand[0])->common.type));
  308. status = AE_AML_INTERNAL;
  309. goto cleanup;
  310. }
  311. /* Failure means that the Index was beyond the end of the object */
  312. if (ACPI_FAILURE(status)) {
  313. ACPI_BIOS_EXCEPTION((AE_INFO, status,
  314. "Index (0x%X%8.8X) is beyond end of object (length 0x%X)",
  315. ACPI_FORMAT_UINT64(index),
  316. (u32)length));
  317. goto cleanup;
  318. }
  319. /*
  320. * Save the target object and add a reference to it for the life
  321. * of the index
  322. */
  323. return_desc->reference.object = operand[0];
  324. acpi_ut_add_reference(operand[0]);
  325. /* Store the reference to the Target */
  326. status = acpi_ex_store(return_desc, operand[2], walk_state);
  327. /* Return the reference */
  328. walk_state->result_obj = return_desc;
  329. goto cleanup;
  330. default:
  331. ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
  332. walk_state->opcode));
  333. status = AE_AML_BAD_OPCODE;
  334. break;
  335. }
  336. store_result_to_target:
  337. if (ACPI_SUCCESS(status)) {
  338. /*
  339. * Store the result of the operation (which is now in return_desc) into
  340. * the Target descriptor.
  341. */
  342. status = acpi_ex_store(return_desc, operand[2], walk_state);
  343. if (ACPI_FAILURE(status)) {
  344. goto cleanup;
  345. }
  346. if (!walk_state->result_obj) {
  347. walk_state->result_obj = return_desc;
  348. }
  349. }
  350. cleanup:
  351. /* Delete return object on error */
  352. if (ACPI_FAILURE(status)) {
  353. acpi_ut_remove_reference(return_desc);
  354. walk_state->result_obj = NULL;
  355. }
  356. return_ACPI_STATUS(status);
  357. }
  358. /*******************************************************************************
  359. *
  360. * FUNCTION: acpi_ex_opcode_2A_0T_1R
  361. *
  362. * PARAMETERS: walk_state - Current walk state
  363. *
  364. * RETURN: Status
  365. *
  366. * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value
  367. *
  368. ******************************************************************************/
  369. acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
  370. {
  371. union acpi_operand_object **operand = &walk_state->operands[0];
  372. union acpi_operand_object *return_desc = NULL;
  373. acpi_status status = AE_OK;
  374. u8 logical_result = FALSE;
  375. ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_1R,
  376. acpi_ps_get_opcode_name(walk_state->opcode));
  377. /* Create the internal return object */
  378. return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
  379. if (!return_desc) {
  380. status = AE_NO_MEMORY;
  381. goto cleanup;
  382. }
  383. /* Execute the Opcode */
  384. if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) {
  385. /* logical_op (Operand0, Operand1) */
  386. status = acpi_ex_do_logical_numeric_op(walk_state->opcode,
  387. operand[0]->integer.
  388. value,
  389. operand[1]->integer.
  390. value, &logical_result);
  391. goto store_logical_result;
  392. } else if (walk_state->op_info->flags & AML_LOGICAL) {
  393. /* logical_op (Operand0, Operand1) */
  394. status = acpi_ex_do_logical_op(walk_state->opcode, operand[0],
  395. operand[1], &logical_result);
  396. goto store_logical_result;
  397. }
  398. switch (walk_state->opcode) {
  399. case AML_ACQUIRE_OP: /* Acquire (mutex_object, Timeout) */
  400. status =
  401. acpi_ex_acquire_mutex(operand[1], operand[0], walk_state);
  402. if (status == AE_TIME) {
  403. logical_result = TRUE; /* TRUE = Acquire timed out */
  404. status = AE_OK;
  405. }
  406. break;
  407. case AML_WAIT_OP: /* Wait (event_object, Timeout) */
  408. status = acpi_ex_system_wait_event(operand[1], operand[0]);
  409. if (status == AE_TIME) {
  410. logical_result = TRUE; /* TRUE, Wait timed out */
  411. status = AE_OK;
  412. }
  413. break;
  414. default:
  415. ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
  416. walk_state->opcode));
  417. status = AE_AML_BAD_OPCODE;
  418. goto cleanup;
  419. }
  420. store_logical_result:
  421. /*
  422. * Set return value to according to logical_result. logical TRUE (all ones)
  423. * Default is FALSE (zero)
  424. */
  425. if (logical_result) {
  426. return_desc->integer.value = ACPI_UINT64_MAX;
  427. }
  428. cleanup:
  429. /* Delete return object on error */
  430. if (ACPI_FAILURE(status)) {
  431. acpi_ut_remove_reference(return_desc);
  432. }
  433. /* Save return object on success */
  434. else {
  435. walk_state->result_obj = return_desc;
  436. }
  437. return_ACPI_STATUS(status);
  438. }