dsargs.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /******************************************************************************
  3. *
  4. * Module Name: dsargs - Support for execution of dynamic arguments for static
  5. * objects (regions, fields, buffer fields, etc.)
  6. *
  7. * Copyright (C) 2000 - 2018, Intel Corp.
  8. *
  9. *****************************************************************************/
  10. #include <acpi/acpi.h>
  11. #include "accommon.h"
  12. #include "acparser.h"
  13. #include "amlcode.h"
  14. #include "acdispat.h"
  15. #include "acnamesp.h"
  16. #define _COMPONENT ACPI_DISPATCHER
  17. ACPI_MODULE_NAME("dsargs")
  18. /* Local prototypes */
  19. static acpi_status
  20. acpi_ds_execute_arguments(struct acpi_namespace_node *node,
  21. struct acpi_namespace_node *scope_node,
  22. u32 aml_length, u8 *aml_start);
  23. /*******************************************************************************
  24. *
  25. * FUNCTION: acpi_ds_execute_arguments
  26. *
  27. * PARAMETERS: node - Object NS node
  28. * scope_node - Parent NS node
  29. * aml_length - Length of executable AML
  30. * aml_start - Pointer to the AML
  31. *
  32. * RETURN: Status.
  33. *
  34. * DESCRIPTION: Late (deferred) execution of region or field arguments
  35. *
  36. ******************************************************************************/
  37. static acpi_status
  38. acpi_ds_execute_arguments(struct acpi_namespace_node *node,
  39. struct acpi_namespace_node *scope_node,
  40. u32 aml_length, u8 *aml_start)
  41. {
  42. acpi_status status;
  43. union acpi_parse_object *op;
  44. struct acpi_walk_state *walk_state;
  45. ACPI_FUNCTION_TRACE_PTR(ds_execute_arguments, aml_start);
  46. /* Allocate a new parser op to be the root of the parsed tree */
  47. op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP, aml_start);
  48. if (!op) {
  49. return_ACPI_STATUS(AE_NO_MEMORY);
  50. }
  51. /* Save the Node for use in acpi_ps_parse_aml */
  52. op->common.node = scope_node;
  53. /* Create and initialize a new parser state */
  54. walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
  55. if (!walk_state) {
  56. status = AE_NO_MEMORY;
  57. goto cleanup;
  58. }
  59. status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
  60. aml_length, NULL, ACPI_IMODE_LOAD_PASS1);
  61. if (ACPI_FAILURE(status)) {
  62. acpi_ds_delete_walk_state(walk_state);
  63. goto cleanup;
  64. }
  65. /* Mark this parse as a deferred opcode */
  66. walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP;
  67. walk_state->deferred_node = node;
  68. /* Pass1: Parse the entire declaration */
  69. status = acpi_ps_parse_aml(walk_state);
  70. if (ACPI_FAILURE(status)) {
  71. goto cleanup;
  72. }
  73. /* Get and init the Op created above */
  74. op->common.node = node;
  75. acpi_ps_delete_parse_tree(op);
  76. /* Evaluate the deferred arguments */
  77. op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP, aml_start);
  78. if (!op) {
  79. return_ACPI_STATUS(AE_NO_MEMORY);
  80. }
  81. op->common.node = scope_node;
  82. /* Create and initialize a new parser state */
  83. walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
  84. if (!walk_state) {
  85. status = AE_NO_MEMORY;
  86. goto cleanup;
  87. }
  88. /* Execute the opcode and arguments */
  89. status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
  90. aml_length, NULL, ACPI_IMODE_EXECUTE);
  91. if (ACPI_FAILURE(status)) {
  92. acpi_ds_delete_walk_state(walk_state);
  93. goto cleanup;
  94. }
  95. /* Mark this execution as a deferred opcode */
  96. walk_state->deferred_node = node;
  97. status = acpi_ps_parse_aml(walk_state);
  98. cleanup:
  99. acpi_ps_delete_parse_tree(op);
  100. return_ACPI_STATUS(status);
  101. }
  102. /*******************************************************************************
  103. *
  104. * FUNCTION: acpi_ds_get_buffer_field_arguments
  105. *
  106. * PARAMETERS: obj_desc - A valid buffer_field object
  107. *
  108. * RETURN: Status.
  109. *
  110. * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late
  111. * evaluation of these field attributes.
  112. *
  113. ******************************************************************************/
  114. acpi_status
  115. acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc)
  116. {
  117. union acpi_operand_object *extra_desc;
  118. struct acpi_namespace_node *node;
  119. acpi_status status;
  120. ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc);
  121. if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
  122. return_ACPI_STATUS(AE_OK);
  123. }
  124. /* Get the AML pointer (method object) and buffer_field node */
  125. extra_desc = acpi_ns_get_secondary_object(obj_desc);
  126. node = obj_desc->buffer_field.node;
  127. ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
  128. (ACPI_TYPE_BUFFER_FIELD, node, NULL));
  129. ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n",
  130. acpi_ut_get_node_name(node)));
  131. /* Execute the AML code for the term_arg arguments */
  132. status = acpi_ds_execute_arguments(node, node->parent,
  133. extra_desc->extra.aml_length,
  134. extra_desc->extra.aml_start);
  135. return_ACPI_STATUS(status);
  136. }
  137. /*******************************************************************************
  138. *
  139. * FUNCTION: acpi_ds_get_bank_field_arguments
  140. *
  141. * PARAMETERS: obj_desc - A valid bank_field object
  142. *
  143. * RETURN: Status.
  144. *
  145. * DESCRIPTION: Get bank_field bank_value. This implements the late
  146. * evaluation of these field attributes.
  147. *
  148. ******************************************************************************/
  149. acpi_status
  150. acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc)
  151. {
  152. union acpi_operand_object *extra_desc;
  153. struct acpi_namespace_node *node;
  154. acpi_status status;
  155. ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc);
  156. if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
  157. return_ACPI_STATUS(AE_OK);
  158. }
  159. /* Get the AML pointer (method object) and bank_field node */
  160. extra_desc = acpi_ns_get_secondary_object(obj_desc);
  161. node = obj_desc->bank_field.node;
  162. ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
  163. (ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL));
  164. ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n",
  165. acpi_ut_get_node_name(node)));
  166. /* Execute the AML code for the term_arg arguments */
  167. status = acpi_ds_execute_arguments(node, node->parent,
  168. extra_desc->extra.aml_length,
  169. extra_desc->extra.aml_start);
  170. if (ACPI_FAILURE(status)) {
  171. return_ACPI_STATUS(status);
  172. }
  173. status = acpi_ut_add_address_range(obj_desc->region.space_id,
  174. obj_desc->region.address,
  175. obj_desc->region.length, node);
  176. return_ACPI_STATUS(status);
  177. }
  178. /*******************************************************************************
  179. *
  180. * FUNCTION: acpi_ds_get_buffer_arguments
  181. *
  182. * PARAMETERS: obj_desc - A valid Buffer object
  183. *
  184. * RETURN: Status.
  185. *
  186. * DESCRIPTION: Get Buffer length and initializer byte list. This implements
  187. * the late evaluation of these attributes.
  188. *
  189. ******************************************************************************/
  190. acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc)
  191. {
  192. struct acpi_namespace_node *node;
  193. acpi_status status;
  194. ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc);
  195. if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
  196. return_ACPI_STATUS(AE_OK);
  197. }
  198. /* Get the Buffer node */
  199. node = obj_desc->buffer.node;
  200. if (!node) {
  201. ACPI_ERROR((AE_INFO,
  202. "No pointer back to namespace node in buffer object %p",
  203. obj_desc));
  204. return_ACPI_STATUS(AE_AML_INTERNAL);
  205. }
  206. ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n"));
  207. /* Execute the AML code for the term_arg arguments */
  208. status = acpi_ds_execute_arguments(node, node,
  209. obj_desc->buffer.aml_length,
  210. obj_desc->buffer.aml_start);
  211. return_ACPI_STATUS(status);
  212. }
  213. /*******************************************************************************
  214. *
  215. * FUNCTION: acpi_ds_get_package_arguments
  216. *
  217. * PARAMETERS: obj_desc - A valid Package object
  218. *
  219. * RETURN: Status.
  220. *
  221. * DESCRIPTION: Get Package length and initializer byte list. This implements
  222. * the late evaluation of these attributes.
  223. *
  224. ******************************************************************************/
  225. acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc)
  226. {
  227. struct acpi_namespace_node *node;
  228. acpi_status status;
  229. ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc);
  230. if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
  231. return_ACPI_STATUS(AE_OK);
  232. }
  233. /* Get the Package node */
  234. node = obj_desc->package.node;
  235. if (!node) {
  236. ACPI_ERROR((AE_INFO,
  237. "No pointer back to namespace node in package %p",
  238. obj_desc));
  239. return_ACPI_STATUS(AE_AML_INTERNAL);
  240. }
  241. ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Argument Init, AML Ptr: %p\n",
  242. obj_desc->package.aml_start));
  243. /* Execute the AML code for the term_arg arguments */
  244. status = acpi_ds_execute_arguments(node, node,
  245. obj_desc->package.aml_length,
  246. obj_desc->package.aml_start);
  247. return_ACPI_STATUS(status);
  248. }
  249. /*******************************************************************************
  250. *
  251. * FUNCTION: acpi_ds_get_region_arguments
  252. *
  253. * PARAMETERS: obj_desc - A valid region object
  254. *
  255. * RETURN: Status.
  256. *
  257. * DESCRIPTION: Get region address and length. This implements the late
  258. * evaluation of these region attributes.
  259. *
  260. ******************************************************************************/
  261. acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
  262. {
  263. struct acpi_namespace_node *node;
  264. acpi_status status;
  265. union acpi_operand_object *extra_desc;
  266. ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc);
  267. if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
  268. return_ACPI_STATUS(AE_OK);
  269. }
  270. extra_desc = acpi_ns_get_secondary_object(obj_desc);
  271. if (!extra_desc) {
  272. return_ACPI_STATUS(AE_NOT_EXIST);
  273. }
  274. /* Get the Region node */
  275. node = obj_desc->region.node;
  276. ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
  277. (ACPI_TYPE_REGION, node, NULL));
  278. ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
  279. "[%4.4s] OpRegion Arg Init at AML %p\n",
  280. acpi_ut_get_node_name(node),
  281. extra_desc->extra.aml_start));
  282. /* Execute the argument AML */
  283. status = acpi_ds_execute_arguments(node, extra_desc->extra.scope_node,
  284. extra_desc->extra.aml_length,
  285. extra_desc->extra.aml_start);
  286. if (ACPI_FAILURE(status)) {
  287. return_ACPI_STATUS(status);
  288. }
  289. status = acpi_ut_add_address_range(obj_desc->region.space_id,
  290. obj_desc->region.address,
  291. obj_desc->region.length, node);
  292. return_ACPI_STATUS(status);
  293. }