psargs.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:17k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /******************************************************************************
  2.  *
  3.  * Module Name: psargs - Parse AML opcode arguments
  4.  *              $Revision: 52 $
  5.  *
  6.  *****************************************************************************/
  7. /*
  8.  *  Copyright (C) 2000, 2001 R. Byron Moore
  9.  *
  10.  *  This program is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 2 of the License, or
  13.  *  (at your option) any later version.
  14.  *
  15.  *  This program is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with this program; if not, write to the Free Software
  22.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  23.  */
  24. #include "acpi.h"
  25. #include "acparser.h"
  26. #include "amlcode.h"
  27. #include "acnamesp.h"
  28. #define _COMPONENT          ACPI_PARSER
  29.  MODULE_NAME         ("psargs")
  30. /*******************************************************************************
  31.  *
  32.  * FUNCTION:    Acpi_ps_get_next_package_length
  33.  *
  34.  * PARAMETERS:  Parser_state        - Current parser state object
  35.  *
  36.  * RETURN:      Decoded package length.  On completion, the AML pointer points
  37.  *              past the length byte or bytes.
  38.  *
  39.  * DESCRIPTION: Decode and return a package length field
  40.  *
  41.  ******************************************************************************/
  42. u32
  43. acpi_ps_get_next_package_length (
  44. acpi_parse_state        *parser_state)
  45. {
  46. u32                     encoded_length;
  47. u32                     length = 0;
  48. FUNCTION_TRACE ("Ps_get_next_package_length");
  49. encoded_length = (u32) GET8 (parser_state->aml);
  50. parser_state->aml++;
  51. switch (encoded_length >> 6) /* bits 6-7 contain encoding scheme */ {
  52. case 0: /* 1-byte encoding (bits 0-5) */
  53. length = (encoded_length & 0x3F);
  54. break;
  55. case 1: /* 2-byte encoding (next byte + bits 0-3) */
  56. length = ((GET8 (parser_state->aml) << 04) |
  57.  (encoded_length & 0x0F));
  58. parser_state->aml++;
  59. break;
  60. case 2: /* 3-byte encoding (next 2 bytes + bits 0-3) */
  61. length = ((GET8 (parser_state->aml + 1) << 12) |
  62.   (GET8 (parser_state->aml)    << 04) |
  63.   (encoded_length & 0x0F));
  64. parser_state->aml += 2;
  65. break;
  66. case 3: /* 4-byte encoding (next 3 bytes + bits 0-3) */
  67. length = ((GET8 (parser_state->aml + 2) << 20) |
  68.   (GET8 (parser_state->aml + 1) << 12) |
  69.   (GET8 (parser_state->aml)    << 04) |
  70.   (encoded_length & 0x0F));
  71. parser_state->aml += 3;
  72. break;
  73. }
  74. return_VALUE (length);
  75. }
  76. /*******************************************************************************
  77.  *
  78.  * FUNCTION:    Acpi_ps_get_next_package_end
  79.  *
  80.  * PARAMETERS:  Parser_state        - Current parser state object
  81.  *
  82.  * RETURN:      Pointer to end-of-package +1
  83.  *
  84.  * DESCRIPTION: Get next package length and return a pointer past the end of
  85.  *              the package.  Consumes the package length field
  86.  *
  87.  ******************************************************************************/
  88. u8 *
  89. acpi_ps_get_next_package_end (
  90. acpi_parse_state        *parser_state)
  91. {
  92. u8                      *start = parser_state->aml;
  93. NATIVE_UINT             length;
  94. FUNCTION_TRACE ("Ps_get_next_package_end");
  95. length = (NATIVE_UINT) acpi_ps_get_next_package_length (parser_state);
  96. return_PTR (start + length); /* end of package */
  97. }
  98. /*******************************************************************************
  99.  *
  100.  * FUNCTION:    Acpi_ps_get_next_namestring
  101.  *
  102.  * PARAMETERS:  Parser_state        - Current parser state object
  103.  *
  104.  * RETURN:      Pointer to the start of the name string (pointer points into
  105.  *              the AML.
  106.  *
  107.  * DESCRIPTION: Get next raw namestring within the AML stream.  Handles all name
  108.  *              prefix characters.  Set parser state to point past the string.
  109.  *              (Name is consumed from the AML.)
  110.  *
  111.  ******************************************************************************/
  112. NATIVE_CHAR *
  113. acpi_ps_get_next_namestring (
  114. acpi_parse_state        *parser_state)
  115. {
  116. u8                       *start = parser_state->aml;
  117. u8                       *end = parser_state->aml;
  118. u32                     length;
  119. FUNCTION_TRACE ("Ps_get_next_namestring");
  120. /* Handle multiple prefix characters */
  121. while (acpi_ps_is_prefix_char (GET8 (end))) {
  122. /* include prefix '\' or '^' */
  123. end++;
  124. }
  125. /* Decode the path */
  126. switch (GET8 (end)) {
  127. case 0:
  128. /* Null_name */
  129. if (end == start) {
  130. start = NULL;
  131. }
  132. end++;
  133. break;
  134. case AML_DUAL_NAME_PREFIX:
  135. /* two name segments */
  136. end += 9;
  137. break;
  138. case AML_MULTI_NAME_PREFIX_OP:
  139. /* multiple name segments */
  140. length = (u32) GET8 (end + 1) * 4;
  141. end += 2 + length;
  142. break;
  143. default:
  144. /* single name segment */
  145. /* assert (Acpi_ps_is_lead (GET8 (End))); */
  146. end += 4;
  147. break;
  148. }
  149. parser_state->aml = (u8*) end;
  150. return_PTR ((NATIVE_CHAR *) start);
  151. }
  152. /*******************************************************************************
  153.  *
  154.  * FUNCTION:    Acpi_ps_get_next_namepath
  155.  *
  156.  * PARAMETERS:  Parser_state        - Current parser state object
  157.  *              Arg                 - Where the namepath will be stored
  158.  *              Arg_count           - If the namepath points to a control method
  159.  *                                    the method's argument is returned here.
  160.  *              Method_call         - Whether the namepath can be the start
  161.  *                                    of a method call
  162.  *
  163.  * RETURN:      None
  164.  *
  165.  * DESCRIPTION: Get next name (if method call, push appropriate # args).  Names
  166.  *              are looked up in either the parsed or internal namespace to
  167.  *              determine if the name represents a control method.  If a method
  168.  *              is found, the number of arguments to the method is returned.
  169.  *              This information is critical for parsing to continue correctly.
  170.  *
  171.  ******************************************************************************/
  172. #ifdef PARSER_ONLY
  173. void
  174. acpi_ps_get_next_namepath (
  175. acpi_parse_state        *parser_state,
  176. acpi_parse_object       *arg,
  177. u32                     *arg_count,
  178. u8                      method_call)
  179. {
  180. NATIVE_CHAR             *path;
  181. acpi_parse_object       *name_op;
  182. acpi_parse_object       *op;
  183. acpi_parse_object       *count;
  184. FUNCTION_TRACE ("Ps_get_next_namepath");
  185. path = acpi_ps_get_next_namestring (parser_state);
  186. if (!path || !method_call) {
  187. /* Null name case, create a null namepath object */
  188. acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP);
  189. arg->value.name = path;
  190. return_VOID;
  191. }
  192. if (acpi_gbl_parsed_namespace_root) {
  193. /*
  194.  * Lookup the name in the parsed namespace
  195.  */
  196. op = NULL;
  197. if (method_call) {
  198. op = acpi_ps_find (acpi_ps_get_parent_scope (parser_state),
  199.    path, AML_METHOD_OP, 0);
  200. }
  201. if (op) {
  202. if (op->opcode == AML_METHOD_OP) {
  203. /*
  204.  * The name refers to a control method, so this namepath is a
  205.  * method invocation.  We need to 1) Get the number of arguments
  206.  * associated with this method, and 2) Change the NAMEPATH
  207.  * object into a METHODCALL object.
  208.  */
  209. count = acpi_ps_get_arg (op, 0);
  210. if (count && count->opcode == AML_BYTE_OP) {
  211. name_op = acpi_ps_alloc_op (AML_INT_NAMEPATH_OP);
  212. if (name_op) {
  213. /* Change arg into a METHOD CALL and attach the name */
  214. acpi_ps_init_op (arg, AML_INT_METHODCALL_OP);
  215. name_op->value.name = path;
  216. /* Point METHODCALL/NAME to the METHOD Node */
  217. name_op->node = (acpi_namespace_node *) op;
  218. acpi_ps_append_arg (arg, name_op);
  219. *arg_count = (u32) count->value.integer &
  220.  METHOD_FLAGS_ARG_COUNT;
  221. }
  222. }
  223. return_VOID;
  224. }
  225. /*
  226.  * Else this is normal named object reference.
  227.  * Just init the NAMEPATH object with the pathname.
  228.  * (See code below)
  229.  */
  230. }
  231. }
  232. /*
  233.  * Either we didn't find the object in the namespace, or the object is
  234.  * something other than a control method.  Just initialize the Op with the
  235.  * pathname
  236.  */
  237. acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP);
  238. arg->value.name = path;
  239. return_VOID;
  240. }
  241. #else
  242. void
  243. acpi_ps_get_next_namepath (
  244. acpi_parse_state        *parser_state,
  245. acpi_parse_object       *arg,
  246. u32                     *arg_count,
  247. u8                      method_call)
  248. {
  249. NATIVE_CHAR             *path;
  250. acpi_parse_object       *name_op;
  251. acpi_status             status;
  252. acpi_namespace_node     *method_node = NULL;
  253. acpi_namespace_node     *node;
  254. acpi_generic_state      scope_info;
  255. FUNCTION_TRACE ("Ps_get_next_namepath");
  256. path = acpi_ps_get_next_namestring (parser_state);
  257. if (!path || !method_call) {
  258. /* Null name case, create a null namepath object */
  259. acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP);
  260. arg->value.name = path;
  261. return_VOID;
  262. }
  263. if (method_call) {
  264. /*
  265.  * Lookup the name in the internal namespace
  266.  */
  267. scope_info.scope.node = NULL;
  268. node = parser_state->start_node;
  269. if (node) {
  270. scope_info.scope.node = node;
  271. }
  272. /*
  273.  * Lookup object.  We don't want to add anything new to the namespace
  274.  * here, however.  So we use MODE_EXECUTE.  Allow searching of the
  275.  * parent tree, but don't open a new scope -- we just want to lookup the
  276.  * object  (MUST BE mode EXECUTE to perform upsearch)
  277.  */
  278. status = acpi_ns_lookup (&scope_info, path, ACPI_TYPE_ANY, IMODE_EXECUTE,
  279.  NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE, NULL,
  280.  &node);
  281. if (ACPI_SUCCESS (status)) {
  282. if (node->type == ACPI_TYPE_METHOD) {
  283. method_node = node;
  284. ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "method - %p Path=%pn",
  285. method_node, path));
  286. name_op = acpi_ps_alloc_op (AML_INT_NAMEPATH_OP);
  287. if (name_op) {
  288. /* Change arg into a METHOD CALL and attach name to it */
  289. acpi_ps_init_op (arg, AML_INT_METHODCALL_OP);
  290. name_op->value.name = path;
  291. /* Point METHODCALL/NAME to the METHOD Node */
  292. name_op->node = method_node;
  293. acpi_ps_append_arg (arg, name_op);
  294. if (!method_node->object) {
  295. return_VOID;
  296. }
  297. *arg_count = (method_node->object)->method.param_count;
  298. }
  299. return_VOID;
  300. }
  301. /*
  302.  * Else this is normal named object reference.
  303.  * Just init the NAMEPATH object with the pathname.
  304.  * (See code below)
  305.  */
  306. }
  307. }
  308. /*
  309.  * Either we didn't find the object in the namespace, or the object is
  310.  * something other than a control method.  Just initialize the Op with the
  311.  * pathname.
  312.  */
  313. acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP);
  314. arg->value.name = path;
  315. return_VOID;
  316. }
  317. #endif
  318. /*******************************************************************************
  319.  *
  320.  * FUNCTION:    Acpi_ps_get_next_simple_arg
  321.  *
  322.  * PARAMETERS:  Parser_state        - Current parser state object
  323.  *              Arg_type            - The argument type (AML_*_ARG)
  324.  *              Arg                 - Where the argument is returned
  325.  *
  326.  * RETURN:      None
  327.  *
  328.  * DESCRIPTION: Get the next simple argument (constant, string, or namestring)
  329.  *
  330.  ******************************************************************************/
  331. void
  332. acpi_ps_get_next_simple_arg (
  333. acpi_parse_state        *parser_state,
  334. u32                     arg_type,
  335. acpi_parse_object       *arg)
  336. {
  337. FUNCTION_TRACE_U32 ("Ps_get_next_simple_arg", arg_type);
  338. switch (arg_type) {
  339. case ARGP_BYTEDATA:
  340. acpi_ps_init_op (arg, AML_BYTE_OP);
  341. arg->value.integer = (u32) GET8 (parser_state->aml);
  342. parser_state->aml++;
  343. break;
  344. case ARGP_WORDDATA:
  345. acpi_ps_init_op (arg, AML_WORD_OP);
  346. /* Get 2 bytes from the AML stream */
  347. MOVE_UNALIGNED16_TO_32 (&arg->value.integer, parser_state->aml);
  348. parser_state->aml += 2;
  349. break;
  350. case ARGP_DWORDDATA:
  351. acpi_ps_init_op (arg, AML_DWORD_OP);
  352. /* Get 4 bytes from the AML stream */
  353. MOVE_UNALIGNED32_TO_32 (&arg->value.integer, parser_state->aml);
  354. parser_state->aml += 4;
  355. break;
  356. case ARGP_QWORDDATA:
  357. acpi_ps_init_op (arg, AML_QWORD_OP);
  358. /* Get 8 bytes from the AML stream */
  359. MOVE_UNALIGNED64_TO_64 (&arg->value.integer, parser_state->aml);
  360. parser_state->aml += 8;
  361. break;
  362. case ARGP_CHARLIST:
  363. acpi_ps_init_op (arg, AML_STRING_OP);
  364. arg->value.string = (char*) parser_state->aml;
  365. while (GET8 (parser_state->aml) != '') {
  366. parser_state->aml++;
  367. }
  368. parser_state->aml++;
  369. break;
  370. case ARGP_NAME:
  371. case ARGP_NAMESTRING:
  372. acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP);
  373. arg->value.name = acpi_ps_get_next_namestring (parser_state);
  374. break;
  375. }
  376. return_VOID;
  377. }
  378. /*******************************************************************************
  379.  *
  380.  * FUNCTION:    Acpi_ps_get_next_field
  381.  *
  382.  * PARAMETERS:  Parser_state        - Current parser state object
  383.  *
  384.  * RETURN:      A newly allocated FIELD op
  385.  *
  386.  * DESCRIPTION: Get next field (Named_field, Reserved_field, or Access_field)
  387.  *
  388.  ******************************************************************************/
  389. acpi_parse_object *
  390. acpi_ps_get_next_field (
  391. acpi_parse_state        *parser_state)
  392. {
  393. u32                     aml_offset = parser_state->aml -
  394.  parser_state->aml_start;
  395. acpi_parse_object       *field;
  396. u16                     opcode;
  397. u32                     name;
  398. FUNCTION_TRACE ("Ps_get_next_field");
  399. /* determine field type */
  400. switch (GET8 (parser_state->aml)) {
  401. default:
  402. opcode = AML_INT_NAMEDFIELD_OP;
  403. break;
  404. case 0x00:
  405. opcode = AML_INT_RESERVEDFIELD_OP;
  406. parser_state->aml++;
  407. break;
  408. case 0x01:
  409. opcode = AML_INT_ACCESSFIELD_OP;
  410. parser_state->aml++;
  411. break;
  412. }
  413. /* Allocate a new field op */
  414. field = acpi_ps_alloc_op (opcode);
  415. if (field) {
  416. field->aml_offset = aml_offset;
  417. /* Decode the field type */
  418. switch (opcode) {
  419. case AML_INT_NAMEDFIELD_OP:
  420. /* Get the 4-character name */
  421. MOVE_UNALIGNED32_TO_32 (&name, parser_state->aml);
  422. acpi_ps_set_name (field, name);
  423. parser_state->aml += 4;
  424. /* Get the length which is encoded as a package length */
  425. field->value.size = acpi_ps_get_next_package_length (parser_state);
  426. break;
  427. case AML_INT_RESERVEDFIELD_OP:
  428. /* Get the length which is encoded as a package length */
  429. field->value.size = acpi_ps_get_next_package_length (parser_state);
  430. break;
  431. case AML_INT_ACCESSFIELD_OP:
  432. /* Get Access_type and Access_atrib and merge into the field Op */
  433. field->value.integer = ((GET8 (parser_state->aml) << 8) |
  434.   GET8 (parser_state->aml));
  435. parser_state->aml += 2;
  436. break;
  437. }
  438. }
  439. return_PTR (field);
  440. }
  441. /*******************************************************************************
  442.  *
  443.  * FUNCTION:    Acpi_ps_get_next_arg
  444.  *
  445.  * PARAMETERS:  Parser_state        - Current parser state object
  446.  *              Arg_type            - The argument type (AML_*_ARG)
  447.  *              Arg_count           - If the argument points to a control method
  448.  *                                    the method's argument is returned here.
  449.  *
  450.  * RETURN:      An op object containing the next argument.
  451.  *
  452.  * DESCRIPTION: Get next argument (including complex list arguments that require
  453.  *              pushing the parser stack)
  454.  *
  455.  ******************************************************************************/
  456. acpi_parse_object *
  457. acpi_ps_get_next_arg (
  458. acpi_parse_state        *parser_state,
  459. u32                     arg_type,
  460. u32                     *arg_count)
  461. {
  462. acpi_parse_object       *arg = NULL;
  463. acpi_parse_object       *prev = NULL;
  464. acpi_parse_object       *field;
  465. u32                     subop;
  466. FUNCTION_TRACE_PTR ("Ps_get_next_arg", parser_state);
  467. switch (arg_type) {
  468. case ARGP_BYTEDATA:
  469. case ARGP_WORDDATA:
  470. case ARGP_DWORDDATA:
  471. case ARGP_CHARLIST:
  472. case ARGP_NAME:
  473. case ARGP_NAMESTRING:
  474. /* constants, strings, and namestrings are all the same size */
  475. arg = acpi_ps_alloc_op (AML_BYTE_OP);
  476. if (arg) {
  477. acpi_ps_get_next_simple_arg (parser_state, arg_type, arg);
  478. }
  479. break;
  480. case ARGP_PKGLENGTH:
  481. /* package length, nothing returned */
  482. parser_state->pkg_end = acpi_ps_get_next_package_end (parser_state);
  483. break;
  484. case ARGP_FIELDLIST:
  485. if (parser_state->aml < parser_state->pkg_end) {
  486. /* non-empty list */
  487. while (parser_state->aml < parser_state->pkg_end) {
  488. field = acpi_ps_get_next_field (parser_state);
  489. if (!field) {
  490. break;
  491. }
  492. if (prev) {
  493. prev->next = field;
  494. }
  495. else {
  496. arg = field;
  497. }
  498. prev = field;
  499. }
  500. /* skip to End of byte data */
  501. parser_state->aml = parser_state->pkg_end;
  502. }
  503. break;
  504. case ARGP_BYTELIST:
  505. if (parser_state->aml < parser_state->pkg_end) {
  506. /* non-empty list */
  507. arg = acpi_ps_alloc_op (AML_INT_BYTELIST_OP);
  508. if (arg) {
  509. /* fill in bytelist data */
  510. arg->value.size = (parser_state->pkg_end - parser_state->aml);
  511. ((acpi_parse2_object *) arg)->data = parser_state->aml;
  512. }
  513. /* skip to End of byte data */
  514. parser_state->aml = parser_state->pkg_end;
  515. }
  516. break;
  517. case ARGP_TARGET:
  518. case ARGP_SUPERNAME: {
  519. subop = acpi_ps_peek_opcode (parser_state);
  520. if (subop == 0              ||
  521. acpi_ps_is_leading_char (subop) ||
  522. acpi_ps_is_prefix_char (subop)) {
  523. /* Null_name or Name_string */
  524. arg = acpi_ps_alloc_op (AML_INT_NAMEPATH_OP);
  525. if (arg) {
  526. acpi_ps_get_next_namepath (parser_state, arg, arg_count, 0);
  527. }
  528. }
  529. else {
  530. /* single complex argument, nothing returned */
  531. *arg_count = 1;
  532. }
  533. }
  534. break;
  535. case ARGP_DATAOBJ:
  536. case ARGP_TERMARG:
  537. /* single complex argument, nothing returned */
  538. *arg_count = 1;
  539. break;
  540. case ARGP_DATAOBJLIST:
  541. case ARGP_TERMLIST:
  542. case ARGP_OBJLIST:
  543. if (parser_state->aml < parser_state->pkg_end) {
  544. /* non-empty list of variable arguments, nothing returned */
  545. *arg_count = ACPI_VAR_ARGS;
  546. }
  547. break;
  548. }
  549. return_PTR (arg);
  550. }