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