psparse.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. /******************************************************************************
  2. *
  3. * Module Name: psparse - Parser top level AML parse routines
  4. *
  5. *****************************************************************************/
  6. /*
  7. * Copyright (C) 2000 - 2005, R. Byron Moore
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions, and the following disclaimer,
  15. * without modification.
  16. * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  17. * substantially similar to the "NO WARRANTY" disclaimer below
  18. * ("Disclaimer") and any redistribution must be conditioned upon
  19. * including a substantially similar Disclaimer requirement for further
  20. * binary redistribution.
  21. * 3. Neither the names of the above-listed copyright holders nor the names
  22. * of any contributors may be used to endorse or promote products derived
  23. * from this software without specific prior written permission.
  24. *
  25. * Alternatively, this software may be distributed under the terms of the
  26. * GNU General Public License ("GPL") version 2 as published by the Free
  27. * Software Foundation.
  28. *
  29. * NO WARRANTY
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  31. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  32. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  33. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  34. * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  35. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  36. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  37. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  38. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  39. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  40. * POSSIBILITY OF SUCH DAMAGES.
  41. */
  42. /*
  43. * Parse the AML and build an operation tree as most interpreters,
  44. * like Perl, do. Parsing is done by hand rather than with a YACC
  45. * generated parser to tightly constrain stack and dynamic memory
  46. * usage. At the same time, parsing is kept flexible and the code
  47. * fairly compact by parsing based on a list of AML opcode
  48. * templates in aml_op_info[]
  49. */
  50. #include <acpi/acpi.h>
  51. #include <acpi/acparser.h>
  52. #include <acpi/acdispat.h>
  53. #include <acpi/amlcode.h>
  54. #include <acpi/acnamesp.h>
  55. #include <acpi/acinterp.h>
  56. #define _COMPONENT ACPI_PARSER
  57. ACPI_MODULE_NAME ("psparse")
  58. /*******************************************************************************
  59. *
  60. * FUNCTION: acpi_ps_get_opcode_size
  61. *
  62. * PARAMETERS: Opcode - An AML opcode
  63. *
  64. * RETURN: Size of the opcode, in bytes (1 or 2)
  65. *
  66. * DESCRIPTION: Get the size of the current opcode.
  67. *
  68. ******************************************************************************/
  69. u32
  70. acpi_ps_get_opcode_size (
  71. u32 opcode)
  72. {
  73. /* Extended (2-byte) opcode if > 255 */
  74. if (opcode > 0x00FF) {
  75. return (2);
  76. }
  77. /* Otherwise, just a single byte opcode */
  78. return (1);
  79. }
  80. /*******************************************************************************
  81. *
  82. * FUNCTION: acpi_ps_peek_opcode
  83. *
  84. * PARAMETERS: parser_state - A parser state object
  85. *
  86. * RETURN: Next AML opcode
  87. *
  88. * DESCRIPTION: Get next AML opcode (without incrementing AML pointer)
  89. *
  90. ******************************************************************************/
  91. u16
  92. acpi_ps_peek_opcode (
  93. struct acpi_parse_state *parser_state)
  94. {
  95. u8 *aml;
  96. u16 opcode;
  97. aml = parser_state->aml;
  98. opcode = (u16) ACPI_GET8 (aml);
  99. if (opcode == AML_EXTENDED_OP_PREFIX) {
  100. /* Extended opcode, get the second opcode byte */
  101. aml++;
  102. opcode = (u16) ((opcode << 8) | ACPI_GET8 (aml));
  103. }
  104. return (opcode);
  105. }
  106. /*******************************************************************************
  107. *
  108. * FUNCTION: acpi_ps_complete_this_op
  109. *
  110. * PARAMETERS: walk_state - Current State
  111. * Op - Op to complete
  112. *
  113. * RETURN: Status
  114. *
  115. * DESCRIPTION: Perform any cleanup at the completion of an Op.
  116. *
  117. ******************************************************************************/
  118. acpi_status
  119. acpi_ps_complete_this_op (
  120. struct acpi_walk_state *walk_state,
  121. union acpi_parse_object *op)
  122. {
  123. union acpi_parse_object *prev;
  124. union acpi_parse_object *next;
  125. const struct acpi_opcode_info *parent_info;
  126. union acpi_parse_object *replacement_op = NULL;
  127. ACPI_FUNCTION_TRACE_PTR ("ps_complete_this_op", op);
  128. /* Check for null Op, can happen if AML code is corrupt */
  129. if (!op) {
  130. return_ACPI_STATUS (AE_OK); /* OK for now */
  131. }
  132. /* Delete this op and the subtree below it if asked to */
  133. if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) ||
  134. (walk_state->op_info->class == AML_CLASS_ARGUMENT)) {
  135. return_ACPI_STATUS (AE_OK);
  136. }
  137. /* Make sure that we only delete this subtree */
  138. if (op->common.parent) {
  139. prev = op->common.parent->common.value.arg;
  140. if (!prev) {
  141. /* Nothing more to do */
  142. goto cleanup;
  143. }
  144. /*
  145. * Check if we need to replace the operator and its subtree
  146. * with a return value op (placeholder op)
  147. */
  148. parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode);
  149. switch (parent_info->class) {
  150. case AML_CLASS_CONTROL:
  151. break;
  152. case AML_CLASS_CREATE:
  153. /*
  154. * These opcodes contain term_arg operands. The current
  155. * op must be replaced by a placeholder return op
  156. */
  157. replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
  158. if (!replacement_op) {
  159. goto allocate_error;
  160. }
  161. break;
  162. case AML_CLASS_NAMED_OBJECT:
  163. /*
  164. * These opcodes contain term_arg operands. The current
  165. * op must be replaced by a placeholder return op
  166. */
  167. if ((op->common.parent->common.aml_opcode == AML_REGION_OP) ||
  168. (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) ||
  169. (op->common.parent->common.aml_opcode == AML_BUFFER_OP) ||
  170. (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
  171. (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
  172. replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
  173. if (!replacement_op) {
  174. goto allocate_error;
  175. }
  176. }
  177. else if ((op->common.parent->common.aml_opcode == AML_NAME_OP) &&
  178. (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2)) {
  179. if ((op->common.aml_opcode == AML_BUFFER_OP) ||
  180. (op->common.aml_opcode == AML_PACKAGE_OP) ||
  181. (op->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
  182. replacement_op = acpi_ps_alloc_op (op->common.aml_opcode);
  183. if (!replacement_op) {
  184. goto allocate_error;
  185. }
  186. replacement_op->named.data = op->named.data;
  187. replacement_op->named.length = op->named.length;
  188. }
  189. }
  190. break;
  191. default:
  192. replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
  193. if (!replacement_op) {
  194. goto allocate_error;
  195. }
  196. }
  197. /* We must unlink this op from the parent tree */
  198. if (prev == op) {
  199. /* This op is the first in the list */
  200. if (replacement_op) {
  201. replacement_op->common.parent = op->common.parent;
  202. replacement_op->common.value.arg = NULL;
  203. replacement_op->common.node = op->common.node;
  204. op->common.parent->common.value.arg = replacement_op;
  205. replacement_op->common.next = op->common.next;
  206. }
  207. else {
  208. op->common.parent->common.value.arg = op->common.next;
  209. }
  210. }
  211. /* Search the parent list */
  212. else while (prev) {
  213. /* Traverse all siblings in the parent's argument list */
  214. next = prev->common.next;
  215. if (next == op) {
  216. if (replacement_op) {
  217. replacement_op->common.parent = op->common.parent;
  218. replacement_op->common.value.arg = NULL;
  219. replacement_op->common.node = op->common.node;
  220. prev->common.next = replacement_op;
  221. replacement_op->common.next = op->common.next;
  222. next = NULL;
  223. }
  224. else {
  225. prev->common.next = op->common.next;
  226. next = NULL;
  227. }
  228. }
  229. prev = next;
  230. }
  231. }
  232. cleanup:
  233. /* Now we can actually delete the subtree rooted at Op */
  234. acpi_ps_delete_parse_tree (op);
  235. return_ACPI_STATUS (AE_OK);
  236. allocate_error:
  237. /* Always delete the subtree, even on error */
  238. acpi_ps_delete_parse_tree (op);
  239. return_ACPI_STATUS (AE_NO_MEMORY);
  240. }
  241. /*******************************************************************************
  242. *
  243. * FUNCTION: acpi_ps_next_parse_state
  244. *
  245. * PARAMETERS: walk_state - Current state
  246. * Op - Current parse op
  247. * callback_status - Status from previous operation
  248. *
  249. * RETURN: Status
  250. *
  251. * DESCRIPTION: Update the parser state based upon the return exception from
  252. * the parser callback.
  253. *
  254. ******************************************************************************/
  255. acpi_status
  256. acpi_ps_next_parse_state (
  257. struct acpi_walk_state *walk_state,
  258. union acpi_parse_object *op,
  259. acpi_status callback_status)
  260. {
  261. struct acpi_parse_state *parser_state = &walk_state->parser_state;
  262. acpi_status status = AE_CTRL_PENDING;
  263. ACPI_FUNCTION_TRACE_PTR ("ps_next_parse_state", op);
  264. switch (callback_status) {
  265. case AE_CTRL_TERMINATE:
  266. /*
  267. * A control method was terminated via a RETURN statement.
  268. * The walk of this method is complete.
  269. */
  270. parser_state->aml = parser_state->aml_end;
  271. status = AE_CTRL_TERMINATE;
  272. break;
  273. case AE_CTRL_BREAK:
  274. parser_state->aml = walk_state->aml_last_while;
  275. walk_state->control_state->common.value = FALSE;
  276. status = AE_CTRL_BREAK;
  277. break;
  278. case AE_CTRL_CONTINUE:
  279. parser_state->aml = walk_state->aml_last_while;
  280. status = AE_CTRL_CONTINUE;
  281. break;
  282. case AE_CTRL_PENDING:
  283. parser_state->aml = walk_state->aml_last_while;
  284. break;
  285. #if 0
  286. case AE_CTRL_SKIP:
  287. parser_state->aml = parser_state->scope->parse_scope.pkg_end;
  288. status = AE_OK;
  289. break;
  290. #endif
  291. case AE_CTRL_TRUE:
  292. /*
  293. * Predicate of an IF was true, and we are at the matching ELSE.
  294. * Just close out this package
  295. */
  296. parser_state->aml = acpi_ps_get_next_package_end (parser_state);
  297. break;
  298. case AE_CTRL_FALSE:
  299. /*
  300. * Either an IF/WHILE Predicate was false or we encountered a BREAK
  301. * opcode. In both cases, we do not execute the rest of the
  302. * package; We simply close out the parent (finishing the walk of
  303. * this branch of the tree) and continue execution at the parent
  304. * level.
  305. */
  306. parser_state->aml = parser_state->scope->parse_scope.pkg_end;
  307. /* In the case of a BREAK, just force a predicate (if any) to FALSE */
  308. walk_state->control_state->common.value = FALSE;
  309. status = AE_CTRL_END;
  310. break;
  311. case AE_CTRL_TRANSFER:
  312. /* A method call (invocation) -- transfer control */
  313. status = AE_CTRL_TRANSFER;
  314. walk_state->prev_op = op;
  315. walk_state->method_call_op = op;
  316. walk_state->method_call_node = (op->common.value.arg)->common.node;
  317. /* Will return value (if any) be used by the caller? */
  318. walk_state->return_used = acpi_ds_is_result_used (op, walk_state);
  319. break;
  320. default:
  321. status = callback_status;
  322. if ((callback_status & AE_CODE_MASK) == AE_CODE_CONTROL) {
  323. status = AE_OK;
  324. }
  325. break;
  326. }
  327. return_ACPI_STATUS (status);
  328. }
  329. /*******************************************************************************
  330. *
  331. * FUNCTION: acpi_ps_parse_aml
  332. *
  333. * PARAMETERS: walk_state - Current state
  334. *
  335. *
  336. * RETURN: Status
  337. *
  338. * DESCRIPTION: Parse raw AML and return a tree of ops
  339. *
  340. ******************************************************************************/
  341. acpi_status
  342. acpi_ps_parse_aml (
  343. struct acpi_walk_state *walk_state)
  344. {
  345. acpi_status status;
  346. acpi_status terminate_status;
  347. struct acpi_thread_state *thread;
  348. struct acpi_thread_state *prev_walk_list = acpi_gbl_current_walk_list;
  349. struct acpi_walk_state *previous_walk_state;
  350. ACPI_FUNCTION_TRACE ("ps_parse_aml");
  351. ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
  352. "Entered with walk_state=%p Aml=%p size=%X\n",
  353. walk_state, walk_state->parser_state.aml,
  354. walk_state->parser_state.aml_size));
  355. /* Create and initialize a new thread state */
  356. thread = acpi_ut_create_thread_state ();
  357. if (!thread) {
  358. return_ACPI_STATUS (AE_NO_MEMORY);
  359. }
  360. walk_state->thread = thread;
  361. acpi_ds_push_walk_state (walk_state, thread);
  362. /*
  363. * This global allows the AML debugger to get a handle to the currently
  364. * executing control method.
  365. */
  366. acpi_gbl_current_walk_list = thread;
  367. /*
  368. * Execute the walk loop as long as there is a valid Walk State. This
  369. * handles nested control method invocations without recursion.
  370. */
  371. ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "State=%p\n", walk_state));
  372. status = AE_OK;
  373. while (walk_state) {
  374. if (ACPI_SUCCESS (status)) {
  375. /*
  376. * The parse_loop executes AML until the method terminates
  377. * or calls another method.
  378. */
  379. status = acpi_ps_parse_loop (walk_state);
  380. }
  381. ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
  382. "Completed one call to walk loop, %s State=%p\n",
  383. acpi_format_exception (status), walk_state));
  384. if (status == AE_CTRL_TRANSFER) {
  385. /*
  386. * A method call was detected.
  387. * Transfer control to the called control method
  388. */
  389. status = acpi_ds_call_control_method (thread, walk_state, NULL);
  390. /*
  391. * If the transfer to the new method method call worked, a new walk
  392. * state was created -- get it
  393. */
  394. walk_state = acpi_ds_get_current_walk_state (thread);
  395. continue;
  396. }
  397. else if (status == AE_CTRL_TERMINATE) {
  398. status = AE_OK;
  399. }
  400. else if ((status != AE_OK) && (walk_state->method_desc)) {
  401. ACPI_REPORT_METHOD_ERROR ("Method execution failed",
  402. walk_state->method_node, NULL, status);
  403. /* Check for possible multi-thread reentrancy problem */
  404. if ((status == AE_ALREADY_EXISTS) &&
  405. (!walk_state->method_desc->method.semaphore)) {
  406. /*
  407. * This method is marked not_serialized, but it tried to create
  408. * a named object, causing the second thread entrance to fail.
  409. * We will workaround this by marking the method permanently
  410. * as Serialized.
  411. */
  412. walk_state->method_desc->method.method_flags |= AML_METHOD_SERIALIZED;
  413. walk_state->method_desc->method.concurrency = 1;
  414. }
  415. }
  416. if (walk_state->method_desc) {
  417. /* Decrement the thread count on the method parse tree */
  418. if (walk_state->method_desc->method.thread_count) {
  419. walk_state->method_desc->method.thread_count--;
  420. }
  421. }
  422. /* We are done with this walk, move on to the parent if any */
  423. walk_state = acpi_ds_pop_walk_state (thread);
  424. /* Reset the current scope to the beginning of scope stack */
  425. acpi_ds_scope_stack_clear (walk_state);
  426. /*
  427. * If we just returned from the execution of a control method,
  428. * there's lots of cleanup to do
  429. */
  430. if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) {
  431. terminate_status = acpi_ds_terminate_control_method (walk_state);
  432. if (ACPI_FAILURE (terminate_status)) {
  433. ACPI_REPORT_ERROR ((
  434. "Could not terminate control method properly\n"));
  435. /* Ignore error and continue */
  436. }
  437. }
  438. /* Delete this walk state and all linked control states */
  439. acpi_ps_cleanup_scope (&walk_state->parser_state);
  440. previous_walk_state = walk_state;
  441. ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
  442. "return_value=%p, implicit_value=%p State=%p\n",
  443. walk_state->return_desc, walk_state->implicit_return_obj, walk_state));
  444. /* Check if we have restarted a preempted walk */
  445. walk_state = acpi_ds_get_current_walk_state (thread);
  446. if (walk_state) {
  447. if (ACPI_SUCCESS (status)) {
  448. /*
  449. * There is another walk state, restart it.
  450. * If the method return value is not used by the parent,
  451. * The object is deleted
  452. */
  453. if (!previous_walk_state->return_desc) {
  454. status = acpi_ds_restart_control_method (walk_state,
  455. previous_walk_state->implicit_return_obj);
  456. }
  457. else {
  458. /*
  459. * We have a valid return value, delete any implicit
  460. * return value.
  461. */
  462. acpi_ds_clear_implicit_return (previous_walk_state);
  463. status = acpi_ds_restart_control_method (walk_state,
  464. previous_walk_state->return_desc);
  465. }
  466. if (ACPI_SUCCESS (status)) {
  467. walk_state->walk_type |= ACPI_WALK_METHOD_RESTART;
  468. }
  469. }
  470. else {
  471. /* On error, delete any return object */
  472. acpi_ut_remove_reference (previous_walk_state->return_desc);
  473. }
  474. }
  475. /*
  476. * Just completed a 1st-level method, save the final internal return
  477. * value (if any)
  478. */
  479. else if (previous_walk_state->caller_return_desc) {
  480. if (previous_walk_state->implicit_return_obj) {
  481. *(previous_walk_state->caller_return_desc) =
  482. previous_walk_state->implicit_return_obj;
  483. }
  484. else {
  485. /* NULL if no return value */
  486. *(previous_walk_state->caller_return_desc) =
  487. previous_walk_state->return_desc;
  488. }
  489. }
  490. else {
  491. if (previous_walk_state->return_desc) {
  492. /* Caller doesn't want it, must delete it */
  493. acpi_ut_remove_reference (previous_walk_state->return_desc);
  494. }
  495. if (previous_walk_state->implicit_return_obj) {
  496. /* Caller doesn't want it, must delete it */
  497. acpi_ut_remove_reference (previous_walk_state->implicit_return_obj);
  498. }
  499. }
  500. acpi_ds_delete_walk_state (previous_walk_state);
  501. }
  502. /* Normal exit */
  503. acpi_ex_release_all_mutexes (thread);
  504. acpi_ut_delete_generic_state (ACPI_CAST_PTR (union acpi_generic_state, thread));
  505. acpi_gbl_current_walk_list = prev_walk_list;
  506. return_ACPI_STATUS (status);
  507. }