Merge branch 'master' of /home/tglx/work/mtd/git/linux-2.6.git/
[linux-2.6] / drivers / acpi / dispatcher / dsobject.c
1 /******************************************************************************
2  *
3  * Module Name: dsobject - Dispatcher object management routines
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2005, R. Byron Moore
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43
44 #include <acpi/acpi.h>
45 #include <acpi/acparser.h>
46 #include <acpi/amlcode.h>
47 #include <acpi/acdispat.h>
48 #include <acpi/acnamesp.h>
49 #include <acpi/acinterp.h>
50
51 #define _COMPONENT          ACPI_DISPATCHER
52 ACPI_MODULE_NAME("dsobject")
53
54 static acpi_status
55 acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
56                               union acpi_parse_object *op,
57                               union acpi_operand_object **obj_desc_ptr);
58
59 #ifndef ACPI_NO_METHOD_EXECUTION
60 /*******************************************************************************
61  *
62  * FUNCTION:    acpi_ds_build_internal_object
63  *
64  * PARAMETERS:  walk_state      - Current walk state
65  *              Op              - Parser object to be translated
66  *              obj_desc_ptr    - Where the ACPI internal object is returned
67  *
68  * RETURN:      Status
69  *
70  * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
71  *              Simple objects are any objects other than a package object!
72  *
73  ******************************************************************************/
74
75 static acpi_status
76 acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
77                               union acpi_parse_object *op,
78                               union acpi_operand_object **obj_desc_ptr)
79 {
80         union acpi_operand_object *obj_desc;
81         acpi_status status;
82
83         ACPI_FUNCTION_TRACE("ds_build_internal_object");
84
85         *obj_desc_ptr = NULL;
86         if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
87                 /*
88                  * This is an named object reference.  If this name was
89                  * previously looked up in the namespace, it was stored in this op.
90                  * Otherwise, go ahead and look it up now
91                  */
92                 if (!op->common.node) {
93                         status = acpi_ns_lookup(walk_state->scope_info,
94                                                 op->common.value.string,
95                                                 ACPI_TYPE_ANY,
96                                                 ACPI_IMODE_EXECUTE,
97                                                 ACPI_NS_SEARCH_PARENT |
98                                                 ACPI_NS_DONT_OPEN_SCOPE, NULL,
99                                                 (struct acpi_namespace_node **)
100                                                 &(op->common.node));
101
102                         if (ACPI_FAILURE(status)) {
103                                 ACPI_REPORT_NSERROR(op->common.value.string,
104                                                     status);
105                                 return_ACPI_STATUS(status);
106                         }
107                 }
108         }
109
110         /* Create and init the internal ACPI object */
111
112         obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info
113                                                    (op->common.aml_opcode))->
114                                                   object_type);
115         if (!obj_desc) {
116                 return_ACPI_STATUS(AE_NO_MEMORY);
117         }
118
119         status =
120             acpi_ds_init_object_from_op(walk_state, op, op->common.aml_opcode,
121                                         &obj_desc);
122         if (ACPI_FAILURE(status)) {
123                 acpi_ut_remove_reference(obj_desc);
124                 return_ACPI_STATUS(status);
125         }
126
127         *obj_desc_ptr = obj_desc;
128         return_ACPI_STATUS(AE_OK);
129 }
130
131 /*******************************************************************************
132  *
133  * FUNCTION:    acpi_ds_build_internal_buffer_obj
134  *
135  * PARAMETERS:  walk_state      - Current walk state
136  *              Op              - Parser object to be translated
137  *              buffer_length   - Length of the buffer
138  *              obj_desc_ptr    - Where the ACPI internal object is returned
139  *
140  * RETURN:      Status
141  *
142  * DESCRIPTION: Translate a parser Op package object to the equivalent
143  *              namespace object
144  *
145  ******************************************************************************/
146
147 acpi_status
148 acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
149                                   union acpi_parse_object *op,
150                                   u32 buffer_length,
151                                   union acpi_operand_object **obj_desc_ptr)
152 {
153         union acpi_parse_object *arg;
154         union acpi_operand_object *obj_desc;
155         union acpi_parse_object *byte_list;
156         u32 byte_list_length = 0;
157
158         ACPI_FUNCTION_TRACE("ds_build_internal_buffer_obj");
159
160         obj_desc = *obj_desc_ptr;
161         if (obj_desc) {
162                 /*
163                  * We are evaluating a Named buffer object "Name (xxxx, Buffer)".
164                  * The buffer object already exists (from the NS node)
165                  */
166         } else {
167                 /* Create a new buffer object */
168
169                 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
170                 *obj_desc_ptr = obj_desc;
171                 if (!obj_desc) {
172                         return_ACPI_STATUS(AE_NO_MEMORY);
173                 }
174         }
175
176         /*
177          * Second arg is the buffer data (optional) byte_list can be either
178          * individual bytes or a string initializer.  In either case, a
179          * byte_list appears in the AML.
180          */
181         arg = op->common.value.arg;     /* skip first arg */
182
183         byte_list = arg->named.next;
184         if (byte_list) {
185                 if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) {
186                         ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
187                                           "Expecting bytelist, got AML opcode %X in op %p\n",
188                                           byte_list->common.aml_opcode,
189                                           byte_list));
190
191                         acpi_ut_remove_reference(obj_desc);
192                         return (AE_TYPE);
193                 }
194
195                 byte_list_length = (u32) byte_list->common.value.integer;
196         }
197
198         /*
199          * The buffer length (number of bytes) will be the larger of:
200          * 1) The specified buffer length and
201          * 2) The length of the initializer byte list
202          */
203         obj_desc->buffer.length = buffer_length;
204         if (byte_list_length > buffer_length) {
205                 obj_desc->buffer.length = byte_list_length;
206         }
207
208         /* Allocate the buffer */
209
210         if (obj_desc->buffer.length == 0) {
211                 obj_desc->buffer.pointer = NULL;
212                 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
213                                   "Buffer defined with zero length in AML, creating\n"));
214         } else {
215                 obj_desc->buffer.pointer =
216                     ACPI_MEM_CALLOCATE(obj_desc->buffer.length);
217                 if (!obj_desc->buffer.pointer) {
218                         acpi_ut_delete_object_desc(obj_desc);
219                         return_ACPI_STATUS(AE_NO_MEMORY);
220                 }
221
222                 /* Initialize buffer from the byte_list (if present) */
223
224                 if (byte_list) {
225                         ACPI_MEMCPY(obj_desc->buffer.pointer,
226                                     byte_list->named.data, byte_list_length);
227                 }
228         }
229
230         obj_desc->buffer.flags |= AOPOBJ_DATA_VALID;
231         op->common.node = (struct acpi_namespace_node *)obj_desc;
232         return_ACPI_STATUS(AE_OK);
233 }
234
235 /*******************************************************************************
236  *
237  * FUNCTION:    acpi_ds_build_internal_package_obj
238  *
239  * PARAMETERS:  walk_state      - Current walk state
240  *              Op              - Parser object to be translated
241  *              package_length  - Number of elements in the package
242  *              obj_desc_ptr    - Where the ACPI internal object is returned
243  *
244  * RETURN:      Status
245  *
246  * DESCRIPTION: Translate a parser Op package object to the equivalent
247  *              namespace object
248  *
249  ******************************************************************************/
250
251 acpi_status
252 acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
253                                    union acpi_parse_object *op,
254                                    u32 package_length,
255                                    union acpi_operand_object **obj_desc_ptr)
256 {
257         union acpi_parse_object *arg;
258         union acpi_parse_object *parent;
259         union acpi_operand_object *obj_desc = NULL;
260         u32 package_list_length;
261         acpi_status status = AE_OK;
262         u32 i;
263
264         ACPI_FUNCTION_TRACE("ds_build_internal_package_obj");
265
266         /* Find the parent of a possibly nested package */
267
268         parent = op->common.parent;
269         while ((parent->common.aml_opcode == AML_PACKAGE_OP) ||
270                (parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
271                 parent = parent->common.parent;
272         }
273
274         obj_desc = *obj_desc_ptr;
275         if (obj_desc) {
276                 /*
277                  * We are evaluating a Named package object "Name (xxxx, Package)".
278                  * Get the existing package object from the NS node
279                  */
280         } else {
281                 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
282                 *obj_desc_ptr = obj_desc;
283                 if (!obj_desc) {
284                         return_ACPI_STATUS(AE_NO_MEMORY);
285                 }
286
287                 obj_desc->package.node = parent->common.node;
288         }
289
290         obj_desc->package.count = package_length;
291
292         /* Count the number of items in the package list */
293
294         package_list_length = 0;
295         arg = op->common.value.arg;
296         arg = arg->common.next;
297         while (arg) {
298                 package_list_length++;
299                 arg = arg->common.next;
300         }
301
302         /*
303          * The package length (number of elements) will be the greater
304          * of the specified length and the length of the initializer list
305          */
306         if (package_list_length > package_length) {
307                 obj_desc->package.count = package_list_length;
308         }
309
310         /*
311          * Allocate the pointer array (array of pointers to the
312          * individual objects). Add an extra pointer slot so
313          * that the list is always null terminated.
314          */
315         obj_desc->package.elements = ACPI_MEM_CALLOCATE(((acpi_size) obj_desc->
316                                                          package.count +
317                                                          1) * sizeof(void *));
318
319         if (!obj_desc->package.elements) {
320                 acpi_ut_delete_object_desc(obj_desc);
321                 return_ACPI_STATUS(AE_NO_MEMORY);
322         }
323
324         /*
325          * Now init the elements of the package
326          */
327         i = 0;
328         arg = op->common.value.arg;
329         arg = arg->common.next;
330         while (arg) {
331                 if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
332                         /* Object (package or buffer) is already built */
333
334                         obj_desc->package.elements[i] =
335                             ACPI_CAST_PTR(union acpi_operand_object,
336                                           arg->common.node);
337                 } else {
338                         status = acpi_ds_build_internal_object(walk_state, arg,
339                                                                &obj_desc->
340                                                                package.
341                                                                elements[i]);
342                 }
343
344                 i++;
345                 arg = arg->common.next;
346         }
347
348         obj_desc->package.flags |= AOPOBJ_DATA_VALID;
349         op->common.node = (struct acpi_namespace_node *)obj_desc;
350         return_ACPI_STATUS(status);
351 }
352
353 /*******************************************************************************
354  *
355  * FUNCTION:    acpi_ds_create_node
356  *
357  * PARAMETERS:  walk_state      - Current walk state
358  *              Node            - NS Node to be initialized
359  *              Op              - Parser object to be translated
360  *
361  * RETURN:      Status
362  *
363  * DESCRIPTION: Create the object to be associated with a namespace node
364  *
365  ******************************************************************************/
366
367 acpi_status
368 acpi_ds_create_node(struct acpi_walk_state *walk_state,
369                     struct acpi_namespace_node *node,
370                     union acpi_parse_object *op)
371 {
372         acpi_status status;
373         union acpi_operand_object *obj_desc;
374
375         ACPI_FUNCTION_TRACE_PTR("ds_create_node", op);
376
377         /*
378          * Because of the execution pass through the non-control-method
379          * parts of the table, we can arrive here twice.  Only init
380          * the named object node the first time through
381          */
382         if (acpi_ns_get_attached_object(node)) {
383                 return_ACPI_STATUS(AE_OK);
384         }
385
386         if (!op->common.value.arg) {
387                 /* No arguments, there is nothing to do */
388
389                 return_ACPI_STATUS(AE_OK);
390         }
391
392         /* Build an internal object for the argument(s) */
393
394         status = acpi_ds_build_internal_object(walk_state, op->common.value.arg,
395                                                &obj_desc);
396         if (ACPI_FAILURE(status)) {
397                 return_ACPI_STATUS(status);
398         }
399
400         /* Re-type the object according to its argument */
401
402         node->type = ACPI_GET_OBJECT_TYPE(obj_desc);
403
404         /* Attach obj to node */
405
406         status = acpi_ns_attach_object(node, obj_desc, node->type);
407
408         /* Remove local reference to the object */
409
410         acpi_ut_remove_reference(obj_desc);
411         return_ACPI_STATUS(status);
412 }
413
414 #endif                          /* ACPI_NO_METHOD_EXECUTION */
415
416 /*******************************************************************************
417  *
418  * FUNCTION:    acpi_ds_init_object_from_op
419  *
420  * PARAMETERS:  walk_state      - Current walk state
421  *              Op              - Parser op used to init the internal object
422  *              Opcode          - AML opcode associated with the object
423  *              ret_obj_desc    - Namespace object to be initialized
424  *
425  * RETURN:      Status
426  *
427  * DESCRIPTION: Initialize a namespace object from a parser Op and its
428  *              associated arguments.  The namespace object is a more compact
429  *              representation of the Op and its arguments.
430  *
431  ******************************************************************************/
432
433 acpi_status
434 acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
435                             union acpi_parse_object *op,
436                             u16 opcode,
437                             union acpi_operand_object **ret_obj_desc)
438 {
439         const struct acpi_opcode_info *op_info;
440         union acpi_operand_object *obj_desc;
441         acpi_status status = AE_OK;
442
443         ACPI_FUNCTION_TRACE("ds_init_object_from_op");
444
445         obj_desc = *ret_obj_desc;
446         op_info = acpi_ps_get_opcode_info(opcode);
447         if (op_info->class == AML_CLASS_UNKNOWN) {
448                 /* Unknown opcode */
449
450                 return_ACPI_STATUS(AE_TYPE);
451         }
452
453         /* Perform per-object initialization */
454
455         switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
456         case ACPI_TYPE_BUFFER:
457
458                 /*
459                  * Defer evaluation of Buffer term_arg operand
460                  */
461                 obj_desc->buffer.node = (struct acpi_namespace_node *)
462                     walk_state->operands[0];
463                 obj_desc->buffer.aml_start = op->named.data;
464                 obj_desc->buffer.aml_length = op->named.length;
465                 break;
466
467         case ACPI_TYPE_PACKAGE:
468
469                 /*
470                  * Defer evaluation of Package term_arg operand
471                  */
472                 obj_desc->package.node = (struct acpi_namespace_node *)
473                     walk_state->operands[0];
474                 obj_desc->package.aml_start = op->named.data;
475                 obj_desc->package.aml_length = op->named.length;
476                 break;
477
478         case ACPI_TYPE_INTEGER:
479
480                 switch (op_info->type) {
481                 case AML_TYPE_CONSTANT:
482                         /*
483                          * Resolve AML Constants here - AND ONLY HERE!
484                          * All constants are integers.
485                          * We mark the integer with a flag that indicates that it started
486                          * life as a constant -- so that stores to constants will perform
487                          * as expected (noop). zero_op is used as a placeholder for optional
488                          * target operands.
489                          */
490                         obj_desc->common.flags = AOPOBJ_AML_CONSTANT;
491
492                         switch (opcode) {
493                         case AML_ZERO_OP:
494
495                                 obj_desc->integer.value = 0;
496                                 break;
497
498                         case AML_ONE_OP:
499
500                                 obj_desc->integer.value = 1;
501                                 break;
502
503                         case AML_ONES_OP:
504
505                                 obj_desc->integer.value = ACPI_INTEGER_MAX;
506
507                                 /* Truncate value if we are executing from a 32-bit ACPI table */
508
509 #ifndef ACPI_NO_METHOD_EXECUTION
510                                 acpi_ex_truncate_for32bit_table(obj_desc);
511 #endif
512                                 break;
513
514                         case AML_REVISION_OP:
515
516                                 obj_desc->integer.value = ACPI_CA_VERSION;
517                                 break;
518
519                         default:
520
521                                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
522                                                   "Unknown constant opcode %X\n",
523                                                   opcode));
524                                 status = AE_AML_OPERAND_TYPE;
525                                 break;
526                         }
527                         break;
528
529                 case AML_TYPE_LITERAL:
530
531                         obj_desc->integer.value = op->common.value.integer;
532 #ifndef ACPI_NO_METHOD_EXECUTION
533                         acpi_ex_truncate_for32bit_table(obj_desc);
534 #endif
535                         break;
536
537                 default:
538                         ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
539                                           "Unknown Integer type %X\n",
540                                           op_info->type));
541                         status = AE_AML_OPERAND_TYPE;
542                         break;
543                 }
544                 break;
545
546         case ACPI_TYPE_STRING:
547
548                 obj_desc->string.pointer = op->common.value.string;
549                 obj_desc->string.length =
550                     (u32) ACPI_STRLEN(op->common.value.string);
551
552                 /*
553                  * The string is contained in the ACPI table, don't ever try
554                  * to delete it
555                  */
556                 obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
557                 break;
558
559         case ACPI_TYPE_METHOD:
560                 break;
561
562         case ACPI_TYPE_LOCAL_REFERENCE:
563
564                 switch (op_info->type) {
565                 case AML_TYPE_LOCAL_VARIABLE:
566
567                         /* Split the opcode into a base opcode + offset */
568
569                         obj_desc->reference.opcode = AML_LOCAL_OP;
570                         obj_desc->reference.offset = opcode - AML_LOCAL_OP;
571
572 #ifndef ACPI_NO_METHOD_EXECUTION
573                         status = acpi_ds_method_data_get_node(AML_LOCAL_OP,
574                                                               obj_desc->
575                                                               reference.offset,
576                                                               walk_state,
577                                                               (struct
578                                                                acpi_namespace_node
579                                                                **)&obj_desc->
580                                                               reference.object);
581 #endif
582                         break;
583
584                 case AML_TYPE_METHOD_ARGUMENT:
585
586                         /* Split the opcode into a base opcode + offset */
587
588                         obj_desc->reference.opcode = AML_ARG_OP;
589                         obj_desc->reference.offset = opcode - AML_ARG_OP;
590
591 #ifndef ACPI_NO_METHOD_EXECUTION
592                         status = acpi_ds_method_data_get_node(AML_ARG_OP,
593                                                               obj_desc->
594                                                               reference.offset,
595                                                               walk_state,
596                                                               (struct
597                                                                acpi_namespace_node
598                                                                **)&obj_desc->
599                                                               reference.object);
600 #endif
601                         break;
602
603                 default:        /* Other literals, etc.. */
604
605                         if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
606                                 /* Node was saved in Op */
607
608                                 obj_desc->reference.node = op->common.node;
609                         }
610
611                         obj_desc->reference.opcode = opcode;
612                         break;
613                 }
614                 break;
615
616         default:
617
618                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
619                                   "Unimplemented data type: %X\n",
620                                   ACPI_GET_OBJECT_TYPE(obj_desc)));
621
622                 status = AE_AML_OPERAND_TYPE;
623                 break;
624         }
625
626         return_ACPI_STATUS(status);
627 }