Linux-2.6.12-rc2
[linux-flexiantxendom0-natty.git] / 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
45 #include <acpi/acpi.h>
46 #include <acpi/acparser.h>
47 #include <acpi/amlcode.h>
48 #include <acpi/acdispat.h>
49 #include <acpi/acnamesp.h>
50 #include <acpi/acinterp.h>
51
52 #define _COMPONENT          ACPI_DISPATCHER
53          ACPI_MODULE_NAME    ("dsobject")
54
55
56 #ifndef ACPI_NO_METHOD_EXECUTION
57 /*****************************************************************************
58  *
59  * FUNCTION:    acpi_ds_build_internal_object
60  *
61  * PARAMETERS:  walk_state      - Current walk state
62  *              Op              - Parser object to be translated
63  *              obj_desc_ptr    - Where the ACPI internal object is returned
64  *
65  * RETURN:      Status
66  *
67  * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
68  *              Simple objects are any objects other than a package object!
69  *
70  ****************************************************************************/
71
72 acpi_status
73 acpi_ds_build_internal_object (
74         struct acpi_walk_state          *walk_state,
75         union acpi_parse_object         *op,
76         union acpi_operand_object       **obj_desc_ptr)
77 {
78         union acpi_operand_object       *obj_desc;
79         acpi_status                     status;
80
81
82         ACPI_FUNCTION_TRACE ("ds_build_internal_object");
83
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, op->common.value.string,
94                                           ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
95                                           ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL,
96                                           (struct acpi_namespace_node **) &(op->common.node));
97
98                         if (ACPI_FAILURE (status)) {
99                                 ACPI_REPORT_NSERROR (op->common.value.string, status);
100                                 return_ACPI_STATUS (status);
101                         }
102                 }
103         }
104
105         /* Create and init the internal ACPI object */
106
107         obj_desc = acpi_ut_create_internal_object ((acpi_ps_get_opcode_info (op->common.aml_opcode))->object_type);
108         if (!obj_desc) {
109                 return_ACPI_STATUS (AE_NO_MEMORY);
110         }
111
112         status = acpi_ds_init_object_from_op (walk_state, op, op->common.aml_opcode, &obj_desc);
113         if (ACPI_FAILURE (status)) {
114                 acpi_ut_remove_reference (obj_desc);
115                 return_ACPI_STATUS (status);
116         }
117
118         *obj_desc_ptr = obj_desc;
119         return_ACPI_STATUS (AE_OK);
120 }
121
122
123 /*****************************************************************************
124  *
125  * FUNCTION:    acpi_ds_build_internal_buffer_obj
126  *
127  * PARAMETERS:  walk_state      - Current walk state
128  *              Op              - Parser object to be translated
129  *              buffer_length   - Length of the buffer
130  *              obj_desc_ptr    - Where the ACPI internal object is returned
131  *
132  * RETURN:      Status
133  *
134  * DESCRIPTION: Translate a parser Op package object to the equivalent
135  *              namespace object
136  *
137  ****************************************************************************/
138
139 acpi_status
140 acpi_ds_build_internal_buffer_obj (
141         struct acpi_walk_state          *walk_state,
142         union acpi_parse_object         *op,
143         u32                             buffer_length,
144         union acpi_operand_object       **obj_desc_ptr)
145 {
146         union acpi_parse_object         *arg;
147         union acpi_operand_object       *obj_desc;
148         union acpi_parse_object         *byte_list;
149         u32                             byte_list_length = 0;
150
151
152         ACPI_FUNCTION_TRACE ("ds_build_internal_buffer_obj");
153
154
155         obj_desc = *obj_desc_ptr;
156         if (obj_desc) {
157                 /*
158                  * We are evaluating a Named buffer object "Name (xxxx, Buffer)".
159                  * The buffer object already exists (from the NS node)
160                  */
161         }
162         else {
163                 /* Create a new buffer object */
164
165                 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
166                 *obj_desc_ptr = obj_desc;
167                 if (!obj_desc) {
168                         return_ACPI_STATUS (AE_NO_MEMORY);
169                 }
170         }
171
172         /*
173          * Second arg is the buffer data (optional) byte_list can be either
174          * individual bytes or a string initializer.  In either case, a
175          * byte_list appears in the AML.
176          */
177         arg = op->common.value.arg;         /* skip first arg */
178
179         byte_list = arg->named.next;
180         if (byte_list) {
181                 if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) {
182                         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
183                                 "Expecting bytelist, got AML opcode %X in op %p\n",
184                                 byte_list->common.aml_opcode, byte_list));
185
186                         acpi_ut_remove_reference (obj_desc);
187                         return (AE_TYPE);
188                 }
189
190                 byte_list_length = (u32) byte_list->common.value.integer;
191         }
192
193         /*
194          * The buffer length (number of bytes) will be the larger of:
195          * 1) The specified buffer length and
196          * 2) The length of the initializer byte list
197          */
198         obj_desc->buffer.length = buffer_length;
199         if (byte_list_length > buffer_length) {
200                 obj_desc->buffer.length = byte_list_length;
201         }
202
203         /* Allocate the buffer */
204
205         if (obj_desc->buffer.length == 0) {
206                 obj_desc->buffer.pointer = NULL;
207                 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
208                         "Buffer defined with zero length in AML, creating\n"));
209         }
210         else {
211                 obj_desc->buffer.pointer = ACPI_MEM_CALLOCATE (
212                                    obj_desc->buffer.length);
213                 if (!obj_desc->buffer.pointer) {
214                         acpi_ut_delete_object_desc (obj_desc);
215                         return_ACPI_STATUS (AE_NO_MEMORY);
216                 }
217
218                 /* Initialize buffer from the byte_list (if present) */
219
220                 if (byte_list) {
221                         ACPI_MEMCPY (obj_desc->buffer.pointer, byte_list->named.data,
222                                           byte_list_length);
223                 }
224         }
225
226         obj_desc->buffer.flags |= AOPOBJ_DATA_VALID;
227         op->common.node = (struct acpi_namespace_node *) obj_desc;
228         return_ACPI_STATUS (AE_OK);
229 }
230
231
232 /*****************************************************************************
233  *
234  * FUNCTION:    acpi_ds_build_internal_package_obj
235  *
236  * PARAMETERS:  walk_state      - Current walk state
237  *              Op              - Parser object to be translated
238  *              package_length  - Number of elements in the package
239  *              obj_desc_ptr    - Where the ACPI internal object is returned
240  *
241  * RETURN:      Status
242  *
243  * DESCRIPTION: Translate a parser Op package object to the equivalent
244  *              namespace object
245  *
246  ****************************************************************************/
247
248 acpi_status
249 acpi_ds_build_internal_package_obj (
250         struct acpi_walk_state          *walk_state,
251         union acpi_parse_object         *op,
252         u32                             package_length,
253         union acpi_operand_object       **obj_desc_ptr)
254 {
255         union acpi_parse_object         *arg;
256         union acpi_parse_object         *parent;
257         union acpi_operand_object       *obj_desc = NULL;
258         u32                             package_list_length;
259         acpi_status                     status = AE_OK;
260         u32                             i;
261
262
263         ACPI_FUNCTION_TRACE ("ds_build_internal_package_obj");
264
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         }
281         else {
282                 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE);
283                 *obj_desc_ptr = obj_desc;
284                 if (!obj_desc) {
285                         return_ACPI_STATUS (AE_NO_MEMORY);
286                 }
287
288                 obj_desc->package.node = parent->common.node;
289         }
290
291         obj_desc->package.count = package_length;
292
293         /* Count the number of items in the package list */
294
295         package_list_length = 0;
296         arg = op->common.value.arg;
297         arg = arg->common.next;
298         while (arg) {
299                 package_list_length++;
300                 arg = arg->common.next;
301         }
302
303         /*
304          * The package length (number of elements) will be the greater
305          * of the specified length and the length of the initializer list
306          */
307         if (package_list_length > package_length) {
308                 obj_desc->package.count = package_list_length;
309         }
310
311         /*
312          * Allocate the pointer array (array of pointers to the
313          * individual objects). Add an extra pointer slot so
314          * that the list is always null terminated.
315          */
316         obj_desc->package.elements = ACPI_MEM_CALLOCATE (
317                          ((acpi_size) obj_desc->package.count + 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] = ACPI_CAST_PTR (union acpi_operand_object, arg->common.node);
335                 }
336                 else {
337                         status = acpi_ds_build_internal_object (walk_state, arg,
338                                           &obj_desc->package.elements[i]);
339                 }
340
341                 i++;
342                 arg = arg->common.next;
343         }
344
345         obj_desc->package.flags |= AOPOBJ_DATA_VALID;
346         op->common.node = (struct acpi_namespace_node *) obj_desc;
347         return_ACPI_STATUS (status);
348 }
349
350
351 /*****************************************************************************
352  *
353  * FUNCTION:    acpi_ds_create_node
354  *
355  * PARAMETERS:  walk_state      - Current walk state
356  *              Node            - NS Node to be initialized
357  *              Op              - Parser object to be translated
358  *
359  * RETURN:      Status
360  *
361  * DESCRIPTION: Create the object to be associated with a namespace node
362  *
363  ****************************************************************************/
364
365 acpi_status
366 acpi_ds_create_node (
367         struct acpi_walk_state          *walk_state,
368         struct acpi_namespace_node      *node,
369         union acpi_parse_object         *op)
370 {
371         acpi_status                     status;
372         union acpi_operand_object       *obj_desc;
373
374
375         ACPI_FUNCTION_TRACE_PTR ("ds_create_node", op);
376
377
378         /*
379          * Because of the execution pass through the non-control-method
380          * parts of the table, we can arrive here twice.  Only init
381          * the named object node the first time through
382          */
383         if (acpi_ns_get_attached_object (node)) {
384                 return_ACPI_STATUS (AE_OK);
385         }
386
387         if (!op->common.value.arg) {
388                 /* No arguments, there is nothing to do */
389
390                 return_ACPI_STATUS (AE_OK);
391         }
392
393         /* Build an internal object for the argument(s) */
394
395         status = acpi_ds_build_internal_object (walk_state, op->common.value.arg, &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  *
419  * FUNCTION:    acpi_ds_init_object_from_op
420  *
421  * PARAMETERS:  walk_state      - Current walk state
422  *              Op              - Parser op used to init the internal object
423  *              Opcode          - AML opcode associated with the object
424  *              ret_obj_desc    - Namespace object to be initialized
425  *
426  * RETURN:      Status
427  *
428  * DESCRIPTION: Initialize a namespace object from a parser Op and its
429  *              associated arguments.  The namespace object is a more compact
430  *              representation of the Op and its arguments.
431  *
432  ****************************************************************************/
433
434 acpi_status
435 acpi_ds_init_object_from_op (
436         struct acpi_walk_state          *walk_state,
437         union acpi_parse_object         *op,
438         u16                             opcode,
439         union acpi_operand_object       **ret_obj_desc)
440 {
441         const struct acpi_opcode_info   *op_info;
442         union acpi_operand_object       *obj_desc;
443         acpi_status                     status = AE_OK;
444
445
446         ACPI_FUNCTION_TRACE ("ds_init_object_from_op");
447
448
449         obj_desc = *ret_obj_desc;
450         op_info = acpi_ps_get_opcode_info (opcode);
451         if (op_info->class == AML_CLASS_UNKNOWN) {
452                 /* Unknown opcode */
453
454                 return_ACPI_STATUS (AE_TYPE);
455         }
456
457         /* Perform per-object initialization */
458
459         switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
460         case ACPI_TYPE_BUFFER:
461
462                 /*
463                  * Defer evaluation of Buffer term_arg operand
464                  */
465                 obj_desc->buffer.node     = (struct acpi_namespace_node *) walk_state->operands[0];
466                 obj_desc->buffer.aml_start = op->named.data;
467                 obj_desc->buffer.aml_length = op->named.length;
468                 break;
469
470
471         case ACPI_TYPE_PACKAGE:
472
473                 /*
474                  * Defer evaluation of Package term_arg operand
475                  */
476                 obj_desc->package.node     = (struct acpi_namespace_node *) walk_state->operands[0];
477                 obj_desc->package.aml_start = op->named.data;
478                 obj_desc->package.aml_length = op->named.length;
479                 break;
480
481
482         case ACPI_TYPE_INTEGER:
483
484                 switch (op_info->type) {
485                 case AML_TYPE_CONSTANT:
486                         /*
487                          * Resolve AML Constants here - AND ONLY HERE!
488                          * All constants are integers.
489                          * We mark the integer with a flag that indicates that it started life
490                          * as a constant -- so that stores to constants will perform as expected (noop).
491                          * (zero_op is used as a placeholder for optional target operands.)
492                          */
493                         obj_desc->common.flags = AOPOBJ_AML_CONSTANT;
494
495                         switch (opcode) {
496                         case AML_ZERO_OP:
497
498                                 obj_desc->integer.value = 0;
499                                 break;
500
501                         case AML_ONE_OP:
502
503                                 obj_desc->integer.value = 1;
504                                 break;
505
506                         case AML_ONES_OP:
507
508                                 obj_desc->integer.value = ACPI_INTEGER_MAX;
509
510                                 /* Truncate value if we are executing from a 32-bit ACPI table */
511
512 #ifndef ACPI_NO_METHOD_EXECUTION
513                                 acpi_ex_truncate_for32bit_table (obj_desc);
514 #endif
515                                 break;
516
517                         case AML_REVISION_OP:
518
519                                 obj_desc->integer.value = ACPI_CA_VERSION;
520                                 break;
521
522                         default:
523
524                                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown constant opcode %X\n", opcode));
525                                 status = AE_AML_OPERAND_TYPE;
526                                 break;
527                         }
528                         break;
529
530
531                 case AML_TYPE_LITERAL:
532
533                         obj_desc->integer.value = op->common.value.integer;
534                         break;
535
536
537                 default:
538                         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Integer type %X\n", op_info->type));
539                         status = AE_AML_OPERAND_TYPE;
540                         break;
541                 }
542                 break;
543
544
545         case ACPI_TYPE_STRING:
546
547                 obj_desc->string.pointer = op->common.value.string;
548                 obj_desc->string.length = (u32) ACPI_STRLEN (op->common.value.string);
549
550                 /*
551                  * The string is contained in the ACPI table, don't ever try
552                  * to delete it
553                  */
554                 obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
555                 break;
556
557
558         case ACPI_TYPE_METHOD:
559                 break;
560
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, obj_desc->reference.offset,
574                                          walk_state, (struct acpi_namespace_node **) &obj_desc->reference.object);
575 #endif
576                         break;
577
578
579                 case AML_TYPE_METHOD_ARGUMENT:
580
581                         /* Split the opcode into a base opcode + offset */
582
583                         obj_desc->reference.opcode = AML_ARG_OP;
584                         obj_desc->reference.offset = opcode - AML_ARG_OP;
585
586 #ifndef ACPI_NO_METHOD_EXECUTION
587                         status = acpi_ds_method_data_get_node (AML_ARG_OP, obj_desc->reference.offset,
588                                          walk_state, (struct acpi_namespace_node **) &obj_desc->reference.object);
589 #endif
590                         break;
591
592                 default: /* Other literals, etc.. */
593
594                         if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
595                                 /* Node was saved in Op */
596
597                                 obj_desc->reference.node = op->common.node;
598                         }
599
600                         obj_desc->reference.opcode = opcode;
601                         break;
602                 }
603                 break;
604
605
606         default:
607
608                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented data type: %X\n",
609                         ACPI_GET_OBJECT_TYPE (obj_desc)));
610
611                 status = AE_AML_OPERAND_TYPE;
612                 break;
613         }
614
615         return_ACPI_STATUS (status);
616 }
617
618