1 /******************************************************************************
3 * Module Name: psargs - Parse AML opcode arguments
6 *****************************************************************************/
9 * Copyright (C) 2000, 2001 R. Byron Moore
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #define _COMPONENT ACPI_PARSER
33 MODULE_NAME ("psargs")
36 /*******************************************************************************
38 * FUNCTION: Acpi_ps_get_next_package_length
40 * PARAMETERS: Parser_state - Current parser state object
42 * RETURN: Decoded package length. On completion, the AML pointer points
43 * past the length byte or bytes.
45 * DESCRIPTION: Decode and return a package length field
47 ******************************************************************************/
50 acpi_ps_get_next_package_length (
51 ACPI_PARSE_STATE
*parser_state
)
57 encoded_length
= (u32
) GET8 (parser_state
->aml
);
61 switch (encoded_length
>> 6) /* bits 6-7 contain encoding scheme */ {
62 case 0: /* 1-byte encoding (bits 0-5) */
64 length
= (encoded_length
& 0x3F);
68 case 1: /* 2-byte encoding (next byte + bits 0-3) */
70 length
= ((GET8 (parser_state
->aml
) << 04) |
71 (encoded_length
& 0x0F));
76 case 2: /* 3-byte encoding (next 2 bytes + bits 0-3) */
78 length
= ((GET8 (parser_state
->aml
+ 1) << 12) |
79 (GET8 (parser_state
->aml
) << 04) |
80 (encoded_length
& 0x0F));
81 parser_state
->aml
+= 2;
85 case 3: /* 4-byte encoding (next 3 bytes + bits 0-3) */
87 length
= ((GET8 (parser_state
->aml
+ 2) << 20) |
88 (GET8 (parser_state
->aml
+ 1) << 12) |
89 (GET8 (parser_state
->aml
) << 04) |
90 (encoded_length
& 0x0F));
91 parser_state
->aml
+= 3;
99 /*******************************************************************************
101 * FUNCTION: Acpi_ps_get_next_package_end
103 * PARAMETERS: Parser_state - Current parser state object
105 * RETURN: Pointer to end-of-package +1
107 * DESCRIPTION: Get next package length and return a pointer past the end of
108 * the package. Consumes the package length field
110 ******************************************************************************/
113 acpi_ps_get_next_package_end (
114 ACPI_PARSE_STATE
*parser_state
)
116 u8
*start
= parser_state
->aml
;
120 length
= (NATIVE_UINT
) acpi_ps_get_next_package_length (parser_state
);
122 return (start
+ length
); /* end of package */
126 /*******************************************************************************
128 * FUNCTION: Acpi_ps_get_next_namestring
130 * PARAMETERS: Parser_state - Current parser state object
132 * RETURN: Pointer to the start of the name string (pointer points into
135 * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name
136 * prefix characters. Set parser state to point past the string.
137 * (Name is consumed from the AML.)
139 ******************************************************************************/
142 acpi_ps_get_next_namestring (
143 ACPI_PARSE_STATE
*parser_state
)
145 u8
*start
= parser_state
->aml
;
146 u8
*end
= parser_state
->aml
;
150 /* Handle multiple prefix characters */
152 while (acpi_ps_is_prefix_char (GET8 (end
))) {
153 /* include prefix '\\' or '^' */
158 /* Decode the path */
160 switch (GET8 (end
)) {
172 case AML_DUAL_NAME_PREFIX
:
174 /* two name segments */
180 case AML_MULTI_NAME_PREFIX_OP
:
182 /* multiple name segments */
184 length
= (u32
) GET8 (end
+ 1) * 4;
191 /* single name segment */
192 /* assert (Acpi_ps_is_lead (GET8 (End))); */
198 parser_state
->aml
= (u8
*) end
;
200 return ((NATIVE_CHAR
*) start
);
204 /*******************************************************************************
206 * FUNCTION: Acpi_ps_get_next_namepath
208 * PARAMETERS: Parser_state - Current parser state object
209 * Arg - Where the namepath will be stored
210 * Arg_count - If the namepath points to a control method
211 * the method's argument is returned here.
212 * Method_call - Whether the namepath can be the start
217 * DESCRIPTION: Get next name (if method call, push appropriate # args). Names
218 * are looked up in either the parsed or internal namespace to
219 * determine if the name represents a control method. If a method
220 * is found, the number of arguments to the method is returned.
221 * This information is critical for parsing to continue correctly.
223 ******************************************************************************/
229 acpi_ps_get_next_namepath (
230 ACPI_PARSE_STATE
*parser_state
,
231 ACPI_PARSE_OBJECT
*arg
,
236 ACPI_PARSE_OBJECT
*name_op
;
237 ACPI_PARSE_OBJECT
*op
;
238 ACPI_PARSE_OBJECT
*count
;
241 path
= acpi_ps_get_next_namestring (parser_state
);
242 if (!path
|| !method_call
) {
243 /* Null name case, create a null namepath object */
245 acpi_ps_init_op (arg
, AML_NAMEPATH_OP
);
246 arg
->value
.name
= path
;
251 if (acpi_gbl_parsed_namespace_root
) {
253 * Lookup the name in the parsed namespace
258 op
= acpi_ps_find (acpi_ps_get_parent_scope (parser_state
),
259 path
, AML_METHOD_OP
, 0);
263 if (op
->opcode
== AML_METHOD_OP
) {
265 * The name refers to a control method, so this namepath is a
266 * method invocation. We need to 1) Get the number of arguments
267 * associated with this method, and 2) Change the NAMEPATH
268 * object into a METHODCALL object.
271 count
= acpi_ps_get_arg (op
, 0);
272 if (count
&& count
->opcode
== AML_BYTE_OP
) {
273 name_op
= acpi_ps_alloc_op (AML_NAMEPATH_OP
);
275 /* Change arg into a METHOD CALL and attach the name */
277 acpi_ps_init_op (arg
, AML_METHODCALL_OP
);
279 name_op
->value
.name
= path
;
281 /* Point METHODCALL/NAME to the METHOD Node */
283 name_op
->node
= (ACPI_NAMESPACE_NODE
*) op
;
284 acpi_ps_append_arg (arg
, name_op
);
286 *arg_count
= count
->value
.integer
&
287 METHOD_FLAGS_ARG_COUNT
;
295 * Else this is normal named object reference.
296 * Just init the NAMEPATH object with the pathname.
304 * Either we didn't find the object in the namespace, or the object is
305 * something other than a control method. Just initialize the Op with the
309 acpi_ps_init_op (arg
, AML_NAMEPATH_OP
);
310 arg
->value
.name
= path
;
321 acpi_ps_get_next_namepath (
322 ACPI_PARSE_STATE
*parser_state
,
323 ACPI_PARSE_OBJECT
*arg
,
328 ACPI_PARSE_OBJECT
*name_op
;
330 ACPI_NAMESPACE_NODE
*method_node
= NULL
;
331 ACPI_NAMESPACE_NODE
*node
;
332 ACPI_GENERIC_STATE scope_info
;
335 path
= acpi_ps_get_next_namestring (parser_state
);
336 if (!path
|| !method_call
) {
337 /* Null name case, create a null namepath object */
339 acpi_ps_init_op (arg
, AML_NAMEPATH_OP
);
340 arg
->value
.name
= path
;
347 * Lookup the name in the internal namespace
349 scope_info
.scope
.node
= NULL
;
350 node
= parser_state
->start_node
;
352 scope_info
.scope
.node
= node
;
356 * Lookup object. We don't want to add anything new to the namespace
357 * here, however. So we use MODE_EXECUTE. Allow searching of the
358 * parent tree, but don't open a new scope -- we just want to lookup the
359 * object (MUST BE mode EXECUTE to perform upsearch)
362 status
= acpi_ns_lookup (&scope_info
, path
, ACPI_TYPE_ANY
, IMODE_EXECUTE
,
363 NS_SEARCH_PARENT
| NS_DONT_OPEN_SCOPE
, NULL
,
365 if (ACPI_SUCCESS (status
)) {
366 if (node
->type
== ACPI_TYPE_METHOD
) {
368 name_op
= acpi_ps_alloc_op (AML_NAMEPATH_OP
);
370 /* Change arg into a METHOD CALL and attach name to it */
372 acpi_ps_init_op (arg
, AML_METHODCALL_OP
);
374 name_op
->value
.name
= path
;
376 /* Point METHODCALL/NAME to the METHOD Node */
378 name_op
->node
= method_node
;
379 acpi_ps_append_arg (arg
, name_op
);
381 if (!(ACPI_OPERAND_OBJECT
*) method_node
->object
) {
385 *arg_count
= ((ACPI_OPERAND_OBJECT
*) method_node
->object
)->method
.param_count
;
392 * Else this is normal named object reference.
393 * Just init the NAMEPATH object with the pathname.
400 * Either we didn't find the object in the namespace, or the object is
401 * something other than a control method. Just initialize the Op with the
405 acpi_ps_init_op (arg
, AML_NAMEPATH_OP
);
406 arg
->value
.name
= path
;
414 /*******************************************************************************
416 * FUNCTION: Acpi_ps_get_next_simple_arg
418 * PARAMETERS: Parser_state - Current parser state object
419 * Arg_type - The argument type (AML_*_ARG)
420 * Arg - Where the argument is returned
424 * DESCRIPTION: Get the next simple argument (constant, string, or namestring)
426 ******************************************************************************/
429 acpi_ps_get_next_simple_arg (
430 ACPI_PARSE_STATE
*parser_state
,
432 ACPI_PARSE_OBJECT
*arg
)
440 acpi_ps_init_op (arg
, AML_BYTE_OP
);
441 arg
->value
.integer
= (u32
) GET8 (parser_state
->aml
);
448 acpi_ps_init_op (arg
, AML_WORD_OP
);
450 /* Get 2 bytes from the AML stream */
452 MOVE_UNALIGNED16_TO_32 (&arg
->value
.integer
, parser_state
->aml
);
453 parser_state
->aml
+= 2;
459 acpi_ps_init_op (arg
, AML_DWORD_OP
);
461 /* Get 4 bytes from the AML stream */
463 MOVE_UNALIGNED32_TO_32 (&arg
->value
.integer
, parser_state
->aml
);
464 parser_state
->aml
+= 4;
470 acpi_ps_init_op (arg
, AML_STRING_OP
);
471 arg
->value
.string
= (char*) parser_state
->aml
;
473 while (GET8 (parser_state
->aml
) != '\0') {
481 case ARGP_NAMESTRING
:
483 acpi_ps_init_op (arg
, AML_NAMEPATH_OP
);
484 arg
->value
.name
= acpi_ps_get_next_namestring (parser_state
);
492 /*******************************************************************************
494 * FUNCTION: Acpi_ps_get_next_field
496 * PARAMETERS: Parser_state - Current parser state object
498 * RETURN: A newly allocated FIELD op
500 * DESCRIPTION: Get next field (Named_field, Reserved_field, or Access_field)
502 ******************************************************************************/
505 acpi_ps_get_next_field (
506 ACPI_PARSE_STATE
*parser_state
)
508 ACPI_PTRDIFF aml_offset
= parser_state
->aml
-
509 parser_state
->aml_start
;
510 ACPI_PARSE_OBJECT
*field
;
515 /* determine field type */
517 switch (GET8 (parser_state
->aml
)) {
521 opcode
= AML_NAMEDFIELD_OP
;
527 opcode
= AML_RESERVEDFIELD_OP
;
534 opcode
= AML_ACCESSFIELD_OP
;
540 /* Allocate a new field op */
542 field
= acpi_ps_alloc_op (opcode
);
544 field
->aml_offset
= aml_offset
;
546 /* Decode the field type */
549 case AML_NAMEDFIELD_OP
:
551 /* Get the 4-character name */
553 MOVE_UNALIGNED32_TO_32 (&name
, parser_state
->aml
);
554 acpi_ps_set_name (field
, name
);
555 parser_state
->aml
+= 4;
557 /* Get the length which is encoded as a package length */
559 field
->value
.size
= acpi_ps_get_next_package_length (parser_state
);
563 case AML_RESERVEDFIELD_OP
:
565 /* Get the length which is encoded as a package length */
567 field
->value
.size
= acpi_ps_get_next_package_length (parser_state
);
571 case AML_ACCESSFIELD_OP
:
573 /* Get Access_type and Access_atrib and merge into the field Op */
575 field
->value
.integer
= ((GET8 (parser_state
->aml
) << 8) |
576 GET8 (parser_state
->aml
));
577 parser_state
->aml
+= 2;
586 /*******************************************************************************
588 * FUNCTION: Acpi_ps_get_next_arg
590 * PARAMETERS: Parser_state - Current parser state object
591 * Arg_type - The argument type (AML_*_ARG)
592 * Arg_count - If the argument points to a control method
593 * the method's argument is returned here.
595 * RETURN: An op object containing the next argument.
597 * DESCRIPTION: Get next argument (including complex list arguments that require
598 * pushing the parser stack)
600 ******************************************************************************/
603 acpi_ps_get_next_arg (
604 ACPI_PARSE_STATE
*parser_state
,
608 ACPI_PARSE_OBJECT
*arg
= NULL
;
609 ACPI_PARSE_OBJECT
*prev
= NULL
;
610 ACPI_PARSE_OBJECT
*field
;
620 case ARGP_NAMESTRING
:
622 /* constants, strings, and namestrings are all the same size */
624 arg
= acpi_ps_alloc_op (AML_BYTE_OP
);
626 acpi_ps_get_next_simple_arg (parser_state
, arg_type
, arg
);
633 /* package length, nothing returned */
635 parser_state
->pkg_end
= acpi_ps_get_next_package_end (parser_state
);
641 if (parser_state
->aml
< parser_state
->pkg_end
) {
644 while (parser_state
->aml
< parser_state
->pkg_end
) {
645 field
= acpi_ps_get_next_field (parser_state
);
661 /* skip to End of byte data */
663 parser_state
->aml
= parser_state
->pkg_end
;
670 if (parser_state
->aml
< parser_state
->pkg_end
) {
673 arg
= acpi_ps_alloc_op (AML_BYTELIST_OP
);
675 /* fill in bytelist data */
677 arg
->value
.size
= (parser_state
->pkg_end
- parser_state
->aml
);
678 ((ACPI_PARSE2_OBJECT
*) arg
)->data
= parser_state
->aml
;
681 /* skip to End of byte data */
683 parser_state
->aml
= parser_state
->pkg_end
;
689 case ARGP_SUPERNAME
: {
690 subop
= acpi_ps_peek_opcode (parser_state
);
692 acpi_ps_is_leading_char (subop
) ||
693 acpi_ps_is_prefix_char (subop
)) {
694 /* Null_name or Name_string */
696 arg
= acpi_ps_alloc_op (AML_NAMEPATH_OP
);
698 acpi_ps_get_next_namepath (parser_state
, arg
, arg_count
, 0);
703 /* single complex argument, nothing returned */
714 /* single complex argument, nothing returned */
720 case ARGP_DATAOBJLIST
:
724 if (parser_state
->aml
< parser_state
->pkg_end
) {
725 /* non-empty list of variable arguments, nothing returned */
727 *arg_count
= ACPI_VAR_ARGS
;