File: /usr/src/linux/drivers/acpi/parser/psargs.c
1 /******************************************************************************
2 *
3 * Module Name: psargs - Parse AML opcode arguments
4 * $Revision: 51 $
5 *
6 *****************************************************************************/
7
8 /*
9 * Copyright (C) 2000, 2001 R. Byron Moore
10 *
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.
15 *
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.
20 *
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
24 */
25
26
27 #include "acpi.h"
28 #include "acparser.h"
29 #include "amlcode.h"
30 #include "acnamesp.h"
31
32 #define _COMPONENT ACPI_PARSER
33 MODULE_NAME ("psargs")
34
35
36 /*******************************************************************************
37 *
38 * FUNCTION: Acpi_ps_get_next_package_length
39 *
40 * PARAMETERS: Parser_state - Current parser state object
41 *
42 * RETURN: Decoded package length. On completion, the AML pointer points
43 * past the length byte or bytes.
44 *
45 * DESCRIPTION: Decode and return a package length field
46 *
47 ******************************************************************************/
48
49 u32
50 acpi_ps_get_next_package_length (
51 acpi_parse_state *parser_state)
52 {
53 u32 encoded_length;
54 u32 length = 0;
55
56
57 FUNCTION_TRACE ("Ps_get_next_package_length");
58
59
60 encoded_length = (u32) GET8 (parser_state->aml);
61 parser_state->aml++;
62
63
64 switch (encoded_length >> 6) /* bits 6-7 contain encoding scheme */ {
65 case 0: /* 1-byte encoding (bits 0-5) */
66
67 length = (encoded_length & 0x3F);
68 break;
69
70
71 case 1: /* 2-byte encoding (next byte + bits 0-3) */
72
73 length = ((GET8 (parser_state->aml) << 04) |
74 (encoded_length & 0x0F));
75 parser_state->aml++;
76 break;
77
78
79 case 2: /* 3-byte encoding (next 2 bytes + bits 0-3) */
80
81 length = ((GET8 (parser_state->aml + 1) << 12) |
82 (GET8 (parser_state->aml) << 04) |
83 (encoded_length & 0x0F));
84 parser_state->aml += 2;
85 break;
86
87
88 case 3: /* 4-byte encoding (next 3 bytes + bits 0-3) */
89
90 length = ((GET8 (parser_state->aml + 2) << 20) |
91 (GET8 (parser_state->aml + 1) << 12) |
92 (GET8 (parser_state->aml) << 04) |
93 (encoded_length & 0x0F));
94 parser_state->aml += 3;
95 break;
96 }
97
98 return_VALUE (length);
99 }
100
101
102 /*******************************************************************************
103 *
104 * FUNCTION: Acpi_ps_get_next_package_end
105 *
106 * PARAMETERS: Parser_state - Current parser state object
107 *
108 * RETURN: Pointer to end-of-package +1
109 *
110 * DESCRIPTION: Get next package length and return a pointer past the end of
111 * the package. Consumes the package length field
112 *
113 ******************************************************************************/
114
115 u8 *
116 acpi_ps_get_next_package_end (
117 acpi_parse_state *parser_state)
118 {
119 u8 *start = parser_state->aml;
120 NATIVE_UINT length;
121
122
123 FUNCTION_TRACE ("Ps_get_next_package_end");
124
125
126 length = (NATIVE_UINT) acpi_ps_get_next_package_length (parser_state);
127
128 return_PTR (start + length); /* end of package */
129 }
130
131
132 /*******************************************************************************
133 *
134 * FUNCTION: Acpi_ps_get_next_namestring
135 *
136 * PARAMETERS: Parser_state - Current parser state object
137 *
138 * RETURN: Pointer to the start of the name string (pointer points into
139 * the AML.
140 *
141 * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name
142 * prefix characters. Set parser state to point past the string.
143 * (Name is consumed from the AML.)
144 *
145 ******************************************************************************/
146
147 NATIVE_CHAR *
148 acpi_ps_get_next_namestring (
149 acpi_parse_state *parser_state)
150 {
151 u8 *start = parser_state->aml;
152 u8 *end = parser_state->aml;
153 u32 length;
154
155
156 FUNCTION_TRACE ("Ps_get_next_namestring");
157
158
159 /* Handle multiple prefix characters */
160
161 while (acpi_ps_is_prefix_char (GET8 (end))) {
162 /* include prefix '\\' or '^' */
163
164 end++;
165 }
166
167 /* Decode the path */
168
169 switch (GET8 (end)) {
170 case 0:
171
172 /* Null_name */
173
174 if (end == start) {
175 start = NULL;
176 }
177 end++;
178 break;
179
180
181 case AML_DUAL_NAME_PREFIX:
182
183 /* two name segments */
184
185 end += 9;
186 break;
187
188
189 case AML_MULTI_NAME_PREFIX_OP:
190
191 /* multiple name segments */
192
193 length = (u32) GET8 (end + 1) * 4;
194 end += 2 + length;
195 break;
196
197
198 default:
199
200 /* single name segment */
201 /* assert (Acpi_ps_is_lead (GET8 (End))); */
202
203 end += 4;
204 break;
205 }
206
207 parser_state->aml = (u8*) end;
208
209 return_PTR ((NATIVE_CHAR *) start);
210 }
211
212
213 /*******************************************************************************
214 *
215 * FUNCTION: Acpi_ps_get_next_namepath
216 *
217 * PARAMETERS: Parser_state - Current parser state object
218 * Arg - Where the namepath will be stored
219 * Arg_count - If the namepath points to a control method
220 * the method's argument is returned here.
221 * Method_call - Whether the namepath can be the start
222 * of a method call
223 *
224 * RETURN: None
225 *
226 * DESCRIPTION: Get next name (if method call, push appropriate # args). Names
227 * are looked up in either the parsed or internal namespace to
228 * determine if the name represents a control method. If a method
229 * is found, the number of arguments to the method is returned.
230 * This information is critical for parsing to continue correctly.
231 *
232 ******************************************************************************/
233
234
235 #ifdef PARSER_ONLY
236
237 void
238 acpi_ps_get_next_namepath (
239 acpi_parse_state *parser_state,
240 acpi_parse_object *arg,
241 u32 *arg_count,
242 u8 method_call)
243 {
244 NATIVE_CHAR *path;
245 acpi_parse_object *name_op;
246 acpi_parse_object *op;
247 acpi_parse_object *count;
248
249
250 FUNCTION_TRACE ("Ps_get_next_namepath");
251
252
253 path = acpi_ps_get_next_namestring (parser_state);
254 if (!path || !method_call) {
255 /* Null name case, create a null namepath object */
256
257 acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP);
258 arg->value.name = path;
259 return_VOID;
260 }
261
262
263 if (acpi_gbl_parsed_namespace_root) {
264 /*
265 * Lookup the name in the parsed namespace
266 */
267 op = NULL;
268 if (method_call) {
269 op = acpi_ps_find (acpi_ps_get_parent_scope (parser_state),
270 path, AML_METHOD_OP, 0);
271 }
272
273 if (op) {
274 if (op->opcode == AML_METHOD_OP) {
275 /*
276 * The name refers to a control method, so this namepath is a
277 * method invocation. We need to 1) Get the number of arguments
278 * associated with this method, and 2) Change the NAMEPATH
279 * object into a METHODCALL object.
280 */
281 count = acpi_ps_get_arg (op, 0);
282 if (count && count->opcode == AML_BYTE_OP) {
283 name_op = acpi_ps_alloc_op (AML_INT_NAMEPATH_OP);
284 if (name_op) {
285 /* Change arg into a METHOD CALL and attach the name */
286
287 acpi_ps_init_op (arg, AML_INT_METHODCALL_OP);
288
289 name_op->value.name = path;
290
291 /* Point METHODCALL/NAME to the METHOD Node */
292
293 name_op->node = (acpi_namespace_node *) op;
294 acpi_ps_append_arg (arg, name_op);
295
296 *arg_count = (u32) count->value.integer &
297 METHOD_FLAGS_ARG_COUNT;
298 }
299 }
300
301 return_VOID;
302 }
303
304 /*
305 * Else this is normal named object reference.
306 * Just init the NAMEPATH object with the pathname.
307 * (See code below)
308 */
309 }
310 }
311
312 /*
313 * Either we didn't find the object in the namespace, or the object is
314 * something other than a control method. Just initialize the Op with the
315 * pathname
316 */
317 acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP);
318 arg->value.name = path;
319
320
321 return_VOID;
322 }
323
324
325 #else
326
327
328 void
329 acpi_ps_get_next_namepath (
330 acpi_parse_state *parser_state,
331 acpi_parse_object *arg,
332 u32 *arg_count,
333 u8 method_call)
334 {
335 NATIVE_CHAR *path;
336 acpi_parse_object *name_op;
337 acpi_status status;
338 acpi_namespace_node *method_node = NULL;
339 acpi_namespace_node *node;
340 acpi_generic_state scope_info;
341
342
343 FUNCTION_TRACE ("Ps_get_next_namepath");
344
345
346 path = acpi_ps_get_next_namestring (parser_state);
347 if (!path || !method_call) {
348 /* Null name case, create a null namepath object */
349
350 acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP);
351 arg->value.name = path;
352 return_VOID;
353 }
354
355
356 if (method_call) {
357 /*
358 * Lookup the name in the internal namespace
359 */
360 scope_info.scope.node = NULL;
361 node = parser_state->start_node;
362 if (node) {
363 scope_info.scope.node = node;
364 }
365
366 /*
367 * Lookup object. We don't want to add anything new to the namespace
368 * here, however. So we use MODE_EXECUTE. Allow searching of the
369 * parent tree, but don't open a new scope -- we just want to lookup the
370 * object (MUST BE mode EXECUTE to perform upsearch)
371 */
372 status = acpi_ns_lookup (&scope_info, path, ACPI_TYPE_ANY, IMODE_EXECUTE,
373 NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE, NULL,
374 &node);
375 if (ACPI_SUCCESS (status)) {
376 if (node->type == ACPI_TYPE_METHOD) {
377 method_node = node;
378 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "method - %p Path=%p\n",
379 method_node, path));
380
381 name_op = acpi_ps_alloc_op (AML_INT_NAMEPATH_OP);
382 if (name_op) {
383 /* Change arg into a METHOD CALL and attach name to it */
384
385 acpi_ps_init_op (arg, AML_INT_METHODCALL_OP);
386
387 name_op->value.name = path;
388
389 /* Point METHODCALL/NAME to the METHOD Node */
390
391 name_op->node = method_node;
392 acpi_ps_append_arg (arg, name_op);
393
394 if (!(acpi_operand_object *) method_node->object) {
395 return_VOID;
396 }
397
398 *arg_count = ((acpi_operand_object *) method_node->object)->method.param_count;
399 }
400
401 return_VOID;
402 }
403
404 /*
405 * Else this is normal named object reference.
406 * Just init the NAMEPATH object with the pathname.
407 * (See code below)
408 */
409 }
410 }
411
412 /*
413 * Either we didn't find the object in the namespace, or the object is
414 * something other than a control method. Just initialize the Op with the
415 * pathname.
416 */
417 acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP);
418 arg->value.name = path;
419
420
421 return_VOID;
422 }
423
424 #endif
425
426 /*******************************************************************************
427 *
428 * FUNCTION: Acpi_ps_get_next_simple_arg
429 *
430 * PARAMETERS: Parser_state - Current parser state object
431 * Arg_type - The argument type (AML_*_ARG)
432 * Arg - Where the argument is returned
433 *
434 * RETURN: None
435 *
436 * DESCRIPTION: Get the next simple argument (constant, string, or namestring)
437 *
438 ******************************************************************************/
439
440 void
441 acpi_ps_get_next_simple_arg (
442 acpi_parse_state *parser_state,
443 u32 arg_type,
444 acpi_parse_object *arg)
445 {
446
447 FUNCTION_TRACE_U32 ("Ps_get_next_simple_arg", arg_type);
448
449
450 switch (arg_type) {
451
452 case ARGP_BYTEDATA:
453
454 acpi_ps_init_op (arg, AML_BYTE_OP);
455 arg->value.integer = (u32) GET8 (parser_state->aml);
456 parser_state->aml++;
457 break;
458
459
460 case ARGP_WORDDATA:
461
462 acpi_ps_init_op (arg, AML_WORD_OP);
463
464 /* Get 2 bytes from the AML stream */
465
466 MOVE_UNALIGNED16_TO_32 (&arg->value.integer, parser_state->aml);
467 parser_state->aml += 2;
468 break;
469
470
471 case ARGP_DWORDDATA:
472
473 acpi_ps_init_op (arg, AML_DWORD_OP);
474
475 /* Get 4 bytes from the AML stream */
476
477 MOVE_UNALIGNED32_TO_32 (&arg->value.integer, parser_state->aml);
478 parser_state->aml += 4;
479 break;
480
481
482 case ARGP_QWORDDATA:
483
484 acpi_ps_init_op (arg, AML_QWORD_OP);
485
486 /* Get 8 bytes from the AML stream */
487
488 MOVE_UNALIGNED64_TO_64 (&arg->value.integer, parser_state->aml);
489 parser_state->aml += 8;
490 break;
491
492
493 case ARGP_CHARLIST:
494
495 acpi_ps_init_op (arg, AML_STRING_OP);
496 arg->value.string = (char*) parser_state->aml;
497
498 while (GET8 (parser_state->aml) != '\0') {
499 parser_state->aml++;
500 }
501 parser_state->aml++;
502 break;
503
504
505 case ARGP_NAME:
506 case ARGP_NAMESTRING:
507
508 acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP);
509 arg->value.name = acpi_ps_get_next_namestring (parser_state);
510 break;
511 }
512
513 return_VOID;
514 }
515
516
517 /*******************************************************************************
518 *
519 * FUNCTION: Acpi_ps_get_next_field
520 *
521 * PARAMETERS: Parser_state - Current parser state object
522 *
523 * RETURN: A newly allocated FIELD op
524 *
525 * DESCRIPTION: Get next field (Named_field, Reserved_field, or Access_field)
526 *
527 ******************************************************************************/
528
529 acpi_parse_object *
530 acpi_ps_get_next_field (
531 acpi_parse_state *parser_state)
532 {
533 u32 aml_offset = parser_state->aml -
534 parser_state->aml_start;
535 acpi_parse_object *field;
536 u16 opcode;
537 u32 name;
538
539
540 FUNCTION_TRACE ("Ps_get_next_field");
541
542
543 /* determine field type */
544
545 switch (GET8 (parser_state->aml)) {
546
547 default:
548
549 opcode = AML_INT_NAMEDFIELD_OP;
550 break;
551
552
553 case 0x00:
554
555 opcode = AML_INT_RESERVEDFIELD_OP;
556 parser_state->aml++;
557 break;
558
559
560 case 0x01:
561
562 opcode = AML_INT_ACCESSFIELD_OP;
563 parser_state->aml++;
564 break;
565 }
566
567
568 /* Allocate a new field op */
569
570 field = acpi_ps_alloc_op (opcode);
571 if (field) {
572 field->aml_offset = aml_offset;
573
574 /* Decode the field type */
575
576 switch (opcode) {
577 case AML_INT_NAMEDFIELD_OP:
578
579 /* Get the 4-character name */
580
581 MOVE_UNALIGNED32_TO_32 (&name, parser_state->aml);
582 acpi_ps_set_name (field, name);
583 parser_state->aml += 4;
584
585 /* Get the length which is encoded as a package length */
586
587 field->value.size = acpi_ps_get_next_package_length (parser_state);
588 break;
589
590
591 case AML_INT_RESERVEDFIELD_OP:
592
593 /* Get the length which is encoded as a package length */
594
595 field->value.size = acpi_ps_get_next_package_length (parser_state);
596 break;
597
598
599 case AML_INT_ACCESSFIELD_OP:
600
601 /* Get Access_type and Access_atrib and merge into the field Op */
602
603 field->value.integer = ((GET8 (parser_state->aml) << 8) |
604 GET8 (parser_state->aml));
605 parser_state->aml += 2;
606 break;
607 }
608 }
609
610 return_PTR (field);
611 }
612
613
614 /*******************************************************************************
615 *
616 * FUNCTION: Acpi_ps_get_next_arg
617 *
618 * PARAMETERS: Parser_state - Current parser state object
619 * Arg_type - The argument type (AML_*_ARG)
620 * Arg_count - If the argument points to a control method
621 * the method's argument is returned here.
622 *
623 * RETURN: An op object containing the next argument.
624 *
625 * DESCRIPTION: Get next argument (including complex list arguments that require
626 * pushing the parser stack)
627 *
628 ******************************************************************************/
629
630 acpi_parse_object *
631 acpi_ps_get_next_arg (
632 acpi_parse_state *parser_state,
633 u32 arg_type,
634 u32 *arg_count)
635 {
636 acpi_parse_object *arg = NULL;
637 acpi_parse_object *prev = NULL;
638 acpi_parse_object *field;
639 u32 subop;
640
641
642 FUNCTION_TRACE_PTR ("Ps_get_next_arg", parser_state);
643
644
645 switch (arg_type) {
646 case ARGP_BYTEDATA:
647 case ARGP_WORDDATA:
648 case ARGP_DWORDDATA:
649 case ARGP_CHARLIST:
650 case ARGP_NAME:
651 case ARGP_NAMESTRING:
652
653 /* constants, strings, and namestrings are all the same size */
654
655 arg = acpi_ps_alloc_op (AML_BYTE_OP);
656 if (arg) {
657 acpi_ps_get_next_simple_arg (parser_state, arg_type, arg);
658 }
659 break;
660
661
662 case ARGP_PKGLENGTH:
663
664 /* package length, nothing returned */
665
666 parser_state->pkg_end = acpi_ps_get_next_package_end (parser_state);
667 break;
668
669
670 case ARGP_FIELDLIST:
671
672 if (parser_state->aml < parser_state->pkg_end) {
673 /* non-empty list */
674
675 while (parser_state->aml < parser_state->pkg_end) {
676 field = acpi_ps_get_next_field (parser_state);
677 if (!field) {
678 break;
679 }
680
681 if (prev) {
682 prev->next = field;
683 }
684
685 else {
686 arg = field;
687 }
688
689 prev = field;
690 }
691
692 /* skip to End of byte data */
693
694 parser_state->aml = parser_state->pkg_end;
695 }
696 break;
697
698
699 case ARGP_BYTELIST:
700
701 if (parser_state->aml < parser_state->pkg_end) {
702 /* non-empty list */
703
704 arg = acpi_ps_alloc_op (AML_INT_BYTELIST_OP);
705 if (arg) {
706 /* fill in bytelist data */
707
708 arg->value.size = (parser_state->pkg_end - parser_state->aml);
709 ((acpi_parse2_object *) arg)->data = parser_state->aml;
710 }
711
712 /* skip to End of byte data */
713
714 parser_state->aml = parser_state->pkg_end;
715 }
716 break;
717
718
719 case ARGP_TARGET:
720 case ARGP_SUPERNAME: {
721 subop = acpi_ps_peek_opcode (parser_state);
722 if (subop == 0 ||
723 acpi_ps_is_leading_char (subop) ||
724 acpi_ps_is_prefix_char (subop)) {
725 /* Null_name or Name_string */
726
727 arg = acpi_ps_alloc_op (AML_INT_NAMEPATH_OP);
728 if (arg) {
729 acpi_ps_get_next_namepath (parser_state, arg, arg_count, 0);
730 }
731 }
732
733 else {
734 /* single complex argument, nothing returned */
735
736 *arg_count = 1;
737 }
738 }
739 break;
740
741
742 case ARGP_DATAOBJ:
743 case ARGP_TERMARG:
744
745 /* single complex argument, nothing returned */
746
747 *arg_count = 1;
748 break;
749
750
751 case ARGP_DATAOBJLIST:
752 case ARGP_TERMLIST:
753 case ARGP_OBJLIST:
754
755 if (parser_state->aml < parser_state->pkg_end) {
756 /* non-empty list of variable arguments, nothing returned */
757
758 *arg_count = ACPI_VAR_ARGS;
759 }
760 break;
761 }
762
763 return_PTR (arg);
764 }
765