import of ftp.dlink.com/GPL/DSMG-600_reB/ppclinux.tar.gz
[linux-2.4.21-pre4.git] / drivers / acpi / parser / psargs.c
1 /******************************************************************************
2  *
3  * Module Name: psargs - Parse AML opcode arguments
4  *              $Revision: 1.1.1.1 $
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 (!method_node->object) {
395                                                 return_VOID;
396                                         }
397
398                                         *arg_count = (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 }