Pull Kconfig into release branch
[linux-2.6] / drivers / acpi / dispatcher / dsopcode.c
1 /******************************************************************************
2  *
3  * Module Name: dsopcode - Dispatcher Op Region support and handling of
4  *                         "control" opcodes
5  *
6  *****************************************************************************/
7
8 /*
9  * Copyright (C) 2000 - 2006, R. Byron Moore
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
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/acinterp.h>
50 #include <acpi/acnamesp.h>
51 #include <acpi/acevents.h>
52
53 #define _COMPONENT          ACPI_DISPATCHER
54 ACPI_MODULE_NAME("dsopcode")
55
56 /* Local prototypes */
57 static acpi_status
58 acpi_ds_execute_arguments(struct acpi_namespace_node *node,
59                           struct acpi_namespace_node *scope_node,
60                           u32 aml_length, u8 * aml_start);
61
62 static acpi_status
63 acpi_ds_init_buffer_field(u16 aml_opcode,
64                           union acpi_operand_object *obj_desc,
65                           union acpi_operand_object *buffer_desc,
66                           union acpi_operand_object *offset_desc,
67                           union acpi_operand_object *length_desc,
68                           union acpi_operand_object *result_desc);
69
70 /*******************************************************************************
71  *
72  * FUNCTION:    acpi_ds_execute_arguments
73  *
74  * PARAMETERS:  Node                - Object NS node
75  *              scope_node          - Parent NS node
76  *              aml_length          - Length of executable AML
77  *              aml_start           - Pointer to the AML
78  *
79  * RETURN:      Status.
80  *
81  * DESCRIPTION: Late (deferred) execution of region or field arguments
82  *
83  ******************************************************************************/
84
85 static acpi_status
86 acpi_ds_execute_arguments(struct acpi_namespace_node *node,
87                           struct acpi_namespace_node *scope_node,
88                           u32 aml_length, u8 * aml_start)
89 {
90         acpi_status status;
91         union acpi_parse_object *op;
92         struct acpi_walk_state *walk_state;
93
94         ACPI_FUNCTION_TRACE(ds_execute_arguments);
95
96         /*
97          * Allocate a new parser op to be the root of the parsed tree
98          */
99         op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP);
100         if (!op) {
101                 return_ACPI_STATUS(AE_NO_MEMORY);
102         }
103
104         /* Save the Node for use in acpi_ps_parse_aml */
105
106         op->common.node = scope_node;
107
108         /* Create and initialize a new parser state */
109
110         walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
111         if (!walk_state) {
112                 status = AE_NO_MEMORY;
113                 goto cleanup;
114         }
115
116         status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
117                                        aml_length, NULL, 1);
118         if (ACPI_FAILURE(status)) {
119                 acpi_ds_delete_walk_state(walk_state);
120                 goto cleanup;
121         }
122
123         /* Mark this parse as a deferred opcode */
124
125         walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP;
126         walk_state->deferred_node = node;
127
128         /* Pass1: Parse the entire declaration */
129
130         status = acpi_ps_parse_aml(walk_state);
131         if (ACPI_FAILURE(status)) {
132                 goto cleanup;
133         }
134
135         /* Get and init the Op created above */
136
137         op->common.node = node;
138         acpi_ps_delete_parse_tree(op);
139
140         /* Evaluate the deferred arguments */
141
142         op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP);
143         if (!op) {
144                 return_ACPI_STATUS(AE_NO_MEMORY);
145         }
146
147         op->common.node = scope_node;
148
149         /* Create and initialize a new parser state */
150
151         walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
152         if (!walk_state) {
153                 status = AE_NO_MEMORY;
154                 goto cleanup;
155         }
156
157         /* Execute the opcode and arguments */
158
159         status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
160                                        aml_length, NULL, 3);
161         if (ACPI_FAILURE(status)) {
162                 acpi_ds_delete_walk_state(walk_state);
163                 goto cleanup;
164         }
165
166         /* Mark this execution as a deferred opcode */
167
168         walk_state->deferred_node = node;
169         status = acpi_ps_parse_aml(walk_state);
170
171       cleanup:
172         acpi_ps_delete_parse_tree(op);
173         return_ACPI_STATUS(status);
174 }
175
176 /*******************************************************************************
177  *
178  * FUNCTION:    acpi_ds_get_buffer_field_arguments
179  *
180  * PARAMETERS:  obj_desc        - A valid buffer_field object
181  *
182  * RETURN:      Status.
183  *
184  * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late
185  *              evaluation of these field attributes.
186  *
187  ******************************************************************************/
188
189 acpi_status
190 acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc)
191 {
192         union acpi_operand_object *extra_desc;
193         struct acpi_namespace_node *node;
194         acpi_status status;
195
196         ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc);
197
198         if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
199                 return_ACPI_STATUS(AE_OK);
200         }
201
202         /* Get the AML pointer (method object) and buffer_field node */
203
204         extra_desc = acpi_ns_get_secondary_object(obj_desc);
205         node = obj_desc->buffer_field.node;
206
207         ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
208                         (ACPI_TYPE_BUFFER_FIELD, node, NULL));
209         ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n",
210                           acpi_ut_get_node_name(node)));
211
212         /* Execute the AML code for the term_arg arguments */
213
214         status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
215                                            extra_desc->extra.aml_length,
216                                            extra_desc->extra.aml_start);
217         return_ACPI_STATUS(status);
218 }
219
220 /*******************************************************************************
221  *
222  * FUNCTION:    acpi_ds_get_buffer_arguments
223  *
224  * PARAMETERS:  obj_desc        - A valid Buffer object
225  *
226  * RETURN:      Status.
227  *
228  * DESCRIPTION: Get Buffer length and initializer byte list.  This implements
229  *              the late evaluation of these attributes.
230  *
231  ******************************************************************************/
232
233 acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc)
234 {
235         struct acpi_namespace_node *node;
236         acpi_status status;
237
238         ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc);
239
240         if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
241                 return_ACPI_STATUS(AE_OK);
242         }
243
244         /* Get the Buffer node */
245
246         node = obj_desc->buffer.node;
247         if (!node) {
248                 ACPI_ERROR((AE_INFO,
249                             "No pointer back to NS node in buffer obj %p",
250                             obj_desc));
251                 return_ACPI_STATUS(AE_AML_INTERNAL);
252         }
253
254         ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n"));
255
256         /* Execute the AML code for the term_arg arguments */
257
258         status = acpi_ds_execute_arguments(node, node,
259                                            obj_desc->buffer.aml_length,
260                                            obj_desc->buffer.aml_start);
261         return_ACPI_STATUS(status);
262 }
263
264 /*******************************************************************************
265  *
266  * FUNCTION:    acpi_ds_get_package_arguments
267  *
268  * PARAMETERS:  obj_desc        - A valid Package object
269  *
270  * RETURN:      Status.
271  *
272  * DESCRIPTION: Get Package length and initializer byte list.  This implements
273  *              the late evaluation of these attributes.
274  *
275  ******************************************************************************/
276
277 acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc)
278 {
279         struct acpi_namespace_node *node;
280         acpi_status status;
281
282         ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc);
283
284         if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
285                 return_ACPI_STATUS(AE_OK);
286         }
287
288         /* Get the Package node */
289
290         node = obj_desc->package.node;
291         if (!node) {
292                 ACPI_ERROR((AE_INFO,
293                             "No pointer back to NS node in package %p",
294                             obj_desc));
295                 return_ACPI_STATUS(AE_AML_INTERNAL);
296         }
297
298         ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n"));
299
300         /* Execute the AML code for the term_arg arguments */
301
302         status = acpi_ds_execute_arguments(node, node,
303                                            obj_desc->package.aml_length,
304                                            obj_desc->package.aml_start);
305         return_ACPI_STATUS(status);
306 }
307
308 /*****************************************************************************
309  *
310  * FUNCTION:    acpi_ds_get_region_arguments
311  *
312  * PARAMETERS:  obj_desc        - A valid region object
313  *
314  * RETURN:      Status.
315  *
316  * DESCRIPTION: Get region address and length.  This implements the late
317  *              evaluation of these region attributes.
318  *
319  ****************************************************************************/
320
321 acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
322 {
323         struct acpi_namespace_node *node;
324         acpi_status status;
325         union acpi_operand_object *extra_desc;
326
327         ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc);
328
329         if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
330                 return_ACPI_STATUS(AE_OK);
331         }
332
333         extra_desc = acpi_ns_get_secondary_object(obj_desc);
334         if (!extra_desc) {
335                 return_ACPI_STATUS(AE_NOT_EXIST);
336         }
337
338         /* Get the Region node */
339
340         node = obj_desc->region.node;
341
342         ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
343                         (ACPI_TYPE_REGION, node, NULL));
344
345         ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n",
346                           acpi_ut_get_node_name(node),
347                           extra_desc->extra.aml_start));
348
349         /* Execute the argument AML */
350
351         status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
352                                            extra_desc->extra.aml_length,
353                                            extra_desc->extra.aml_start);
354         if (ACPI_FAILURE(status)) {
355                 return_ACPI_STATUS(status);
356         }
357
358         /* Validate the region address/length via the host OS */
359
360         status = acpi_os_validate_address(obj_desc->region.space_id,
361                                           obj_desc->region.address,
362                                           (acpi_size) obj_desc->region.length);
363         if (ACPI_FAILURE(status)) {
364                 /*
365                  * Invalid address/length. We will emit an error message and mark
366                  * the region as invalid, so that it will cause an additional error if
367                  * it is ever used. Then return AE_OK.
368                  */
369                 ACPI_EXCEPTION((AE_INFO, status,
370                                 "During address validation of OpRegion [%4.4s]",
371                                 node->name.ascii));
372                 obj_desc->common.flags |= AOPOBJ_INVALID;
373                 status = AE_OK;
374         }
375
376         return_ACPI_STATUS(status);
377 }
378
379 /*******************************************************************************
380  *
381  * FUNCTION:    acpi_ds_initialize_region
382  *
383  * PARAMETERS:  obj_handle      - Region namespace node
384  *
385  * RETURN:      Status
386  *
387  * DESCRIPTION: Front end to ev_initialize_region
388  *
389  ******************************************************************************/
390
391 acpi_status acpi_ds_initialize_region(acpi_handle obj_handle)
392 {
393         union acpi_operand_object *obj_desc;
394         acpi_status status;
395
396         obj_desc = acpi_ns_get_attached_object(obj_handle);
397
398         /* Namespace is NOT locked */
399
400         status = acpi_ev_initialize_region(obj_desc, FALSE);
401         return (status);
402 }
403
404 /*******************************************************************************
405  *
406  * FUNCTION:    acpi_ds_init_buffer_field
407  *
408  * PARAMETERS:  aml_opcode      - create_xxx_field
409  *              obj_desc        - buffer_field object
410  *              buffer_desc     - Host Buffer
411  *              offset_desc     - Offset into buffer
412  *              length_desc     - Length of field (CREATE_FIELD_OP only)
413  *              result_desc     - Where to store the result
414  *
415  * RETURN:      Status
416  *
417  * DESCRIPTION: Perform actual initialization of a buffer field
418  *
419  ******************************************************************************/
420
421 static acpi_status
422 acpi_ds_init_buffer_field(u16 aml_opcode,
423                           union acpi_operand_object *obj_desc,
424                           union acpi_operand_object *buffer_desc,
425                           union acpi_operand_object *offset_desc,
426                           union acpi_operand_object *length_desc,
427                           union acpi_operand_object *result_desc)
428 {
429         u32 offset;
430         u32 bit_offset;
431         u32 bit_count;
432         u8 field_flags;
433         acpi_status status;
434
435         ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc);
436
437         /* Host object must be a Buffer */
438
439         if (ACPI_GET_OBJECT_TYPE(buffer_desc) != ACPI_TYPE_BUFFER) {
440                 ACPI_ERROR((AE_INFO,
441                             "Target of Create Field is not a Buffer object - %s",
442                             acpi_ut_get_object_type_name(buffer_desc)));
443
444                 status = AE_AML_OPERAND_TYPE;
445                 goto cleanup;
446         }
447
448         /*
449          * The last parameter to all of these opcodes (result_desc) started
450          * out as a name_string, and should therefore now be a NS node
451          * after resolution in acpi_ex_resolve_operands().
452          */
453         if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) {
454                 ACPI_ERROR((AE_INFO,
455                             "(%s) destination not a NS Node [%s]",
456                             acpi_ps_get_opcode_name(aml_opcode),
457                             acpi_ut_get_descriptor_name(result_desc)));
458
459                 status = AE_AML_OPERAND_TYPE;
460                 goto cleanup;
461         }
462
463         offset = (u32) offset_desc->integer.value;
464
465         /*
466          * Setup the Bit offsets and counts, according to the opcode
467          */
468         switch (aml_opcode) {
469         case AML_CREATE_FIELD_OP:
470
471                 /* Offset is in bits, count is in bits */
472
473                 field_flags = AML_FIELD_ACCESS_BYTE;
474                 bit_offset = offset;
475                 bit_count = (u32) length_desc->integer.value;
476
477                 /* Must have a valid (>0) bit count */
478
479                 if (bit_count == 0) {
480                         ACPI_ERROR((AE_INFO,
481                                     "Attempt to CreateField of length zero"));
482                         status = AE_AML_OPERAND_VALUE;
483                         goto cleanup;
484                 }
485                 break;
486
487         case AML_CREATE_BIT_FIELD_OP:
488
489                 /* Offset is in bits, Field is one bit */
490
491                 bit_offset = offset;
492                 bit_count = 1;
493                 field_flags = AML_FIELD_ACCESS_BYTE;
494                 break;
495
496         case AML_CREATE_BYTE_FIELD_OP:
497
498                 /* Offset is in bytes, field is one byte */
499
500                 bit_offset = 8 * offset;
501                 bit_count = 8;
502                 field_flags = AML_FIELD_ACCESS_BYTE;
503                 break;
504
505         case AML_CREATE_WORD_FIELD_OP:
506
507                 /* Offset is in bytes, field is one word */
508
509                 bit_offset = 8 * offset;
510                 bit_count = 16;
511                 field_flags = AML_FIELD_ACCESS_WORD;
512                 break;
513
514         case AML_CREATE_DWORD_FIELD_OP:
515
516                 /* Offset is in bytes, field is one dword */
517
518                 bit_offset = 8 * offset;
519                 bit_count = 32;
520                 field_flags = AML_FIELD_ACCESS_DWORD;
521                 break;
522
523         case AML_CREATE_QWORD_FIELD_OP:
524
525                 /* Offset is in bytes, field is one qword */
526
527                 bit_offset = 8 * offset;
528                 bit_count = 64;
529                 field_flags = AML_FIELD_ACCESS_QWORD;
530                 break;
531
532         default:
533
534                 ACPI_ERROR((AE_INFO,
535                             "Unknown field creation opcode %02x", aml_opcode));
536                 status = AE_AML_BAD_OPCODE;
537                 goto cleanup;
538         }
539
540         /* Entire field must fit within the current length of the buffer */
541
542         if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) {
543                 ACPI_ERROR((AE_INFO,
544                             "Field [%4.4s] at %d exceeds Buffer [%4.4s] size %d (bits)",
545                             acpi_ut_get_node_name(result_desc),
546                             bit_offset + bit_count,
547                             acpi_ut_get_node_name(buffer_desc->buffer.node),
548                             8 * (u32) buffer_desc->buffer.length));
549                 status = AE_AML_BUFFER_LIMIT;
550                 goto cleanup;
551         }
552
553         /*
554          * Initialize areas of the field object that are common to all fields
555          * For field_flags, use LOCK_RULE = 0 (NO_LOCK),
556          * UPDATE_RULE = 0 (UPDATE_PRESERVE)
557          */
558         status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0,
559                                                   bit_offset, bit_count);
560         if (ACPI_FAILURE(status)) {
561                 goto cleanup;
562         }
563
564         obj_desc->buffer_field.buffer_obj = buffer_desc;
565
566         /* Reference count for buffer_desc inherits obj_desc count */
567
568         buffer_desc->common.reference_count = (u16)
569             (buffer_desc->common.reference_count +
570              obj_desc->common.reference_count);
571
572       cleanup:
573
574         /* Always delete the operands */
575
576         acpi_ut_remove_reference(offset_desc);
577         acpi_ut_remove_reference(buffer_desc);
578
579         if (aml_opcode == AML_CREATE_FIELD_OP) {
580                 acpi_ut_remove_reference(length_desc);
581         }
582
583         /* On failure, delete the result descriptor */
584
585         if (ACPI_FAILURE(status)) {
586                 acpi_ut_remove_reference(result_desc);  /* Result descriptor */
587         } else {
588                 /* Now the address and length are valid for this buffer_field */
589
590                 obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID;
591         }
592
593         return_ACPI_STATUS(status);
594 }
595
596 /*******************************************************************************
597  *
598  * FUNCTION:    acpi_ds_eval_buffer_field_operands
599  *
600  * PARAMETERS:  walk_state      - Current walk
601  *              Op              - A valid buffer_field Op object
602  *
603  * RETURN:      Status
604  *
605  * DESCRIPTION: Get buffer_field Buffer and Index
606  *              Called from acpi_ds_exec_end_op during buffer_field parse tree walk
607  *
608  ******************************************************************************/
609
610 acpi_status
611 acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
612                                    union acpi_parse_object *op)
613 {
614         acpi_status status;
615         union acpi_operand_object *obj_desc;
616         struct acpi_namespace_node *node;
617         union acpi_parse_object *next_op;
618
619         ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op);
620
621         /*
622          * This is where we evaluate the address and length fields of the
623          * create_xxx_field declaration
624          */
625         node = op->common.node;
626
627         /* next_op points to the op that holds the Buffer */
628
629         next_op = op->common.value.arg;
630
631         /* Evaluate/create the address and length operands */
632
633         status = acpi_ds_create_operands(walk_state, next_op);
634         if (ACPI_FAILURE(status)) {
635                 return_ACPI_STATUS(status);
636         }
637
638         obj_desc = acpi_ns_get_attached_object(node);
639         if (!obj_desc) {
640                 return_ACPI_STATUS(AE_NOT_EXIST);
641         }
642
643         /* Resolve the operands */
644
645         status = acpi_ex_resolve_operands(op->common.aml_opcode,
646                                           ACPI_WALK_OPERANDS, walk_state);
647
648         ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
649                            acpi_ps_get_opcode_name(op->common.aml_opcode),
650                            walk_state->num_operands,
651                            "after AcpiExResolveOperands");
652
653         if (ACPI_FAILURE(status)) {
654                 ACPI_ERROR((AE_INFO, "(%s) bad operand(s) (%X)",
655                             acpi_ps_get_opcode_name(op->common.aml_opcode),
656                             status));
657
658                 return_ACPI_STATUS(status);
659         }
660
661         /* Initialize the Buffer Field */
662
663         if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
664
665                 /* NOTE: Slightly different operands for this opcode */
666
667                 status =
668                     acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
669                                               walk_state->operands[0],
670                                               walk_state->operands[1],
671                                               walk_state->operands[2],
672                                               walk_state->operands[3]);
673         } else {
674                 /* All other, create_xxx_field opcodes */
675
676                 status =
677                     acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
678                                               walk_state->operands[0],
679                                               walk_state->operands[1], NULL,
680                                               walk_state->operands[2]);
681         }
682
683         return_ACPI_STATUS(status);
684 }
685
686 /*******************************************************************************
687  *
688  * FUNCTION:    acpi_ds_eval_region_operands
689  *
690  * PARAMETERS:  walk_state      - Current walk
691  *              Op              - A valid region Op object
692  *
693  * RETURN:      Status
694  *
695  * DESCRIPTION: Get region address and length
696  *              Called from acpi_ds_exec_end_op during op_region parse tree walk
697  *
698  ******************************************************************************/
699
700 acpi_status
701 acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
702                              union acpi_parse_object *op)
703 {
704         acpi_status status;
705         union acpi_operand_object *obj_desc;
706         union acpi_operand_object *operand_desc;
707         struct acpi_namespace_node *node;
708         union acpi_parse_object *next_op;
709
710         ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op);
711
712         /*
713          * This is where we evaluate the address and length fields of the
714          * op_region declaration
715          */
716         node = op->common.node;
717
718         /* next_op points to the op that holds the space_iD */
719
720         next_op = op->common.value.arg;
721
722         /* next_op points to address op */
723
724         next_op = next_op->common.next;
725
726         /* Evaluate/create the address and length operands */
727
728         status = acpi_ds_create_operands(walk_state, next_op);
729         if (ACPI_FAILURE(status)) {
730                 return_ACPI_STATUS(status);
731         }
732
733         /* Resolve the length and address operands to numbers */
734
735         status = acpi_ex_resolve_operands(op->common.aml_opcode,
736                                           ACPI_WALK_OPERANDS, walk_state);
737         if (ACPI_FAILURE(status)) {
738                 return_ACPI_STATUS(status);
739         }
740
741         ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
742                            acpi_ps_get_opcode_name(op->common.aml_opcode),
743                            1, "after AcpiExResolveOperands");
744
745         obj_desc = acpi_ns_get_attached_object(node);
746         if (!obj_desc) {
747                 return_ACPI_STATUS(AE_NOT_EXIST);
748         }
749
750         /*
751          * Get the length operand and save it
752          * (at Top of stack)
753          */
754         operand_desc = walk_state->operands[walk_state->num_operands - 1];
755
756         obj_desc->region.length = (u32) operand_desc->integer.value;
757         acpi_ut_remove_reference(operand_desc);
758
759         /*
760          * Get the address and save it
761          * (at top of stack - 1)
762          */
763         operand_desc = walk_state->operands[walk_state->num_operands - 2];
764
765         obj_desc->region.address = (acpi_physical_address)
766             operand_desc->integer.value;
767         acpi_ut_remove_reference(operand_desc);
768
769         ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
770                           obj_desc,
771                           ACPI_FORMAT_UINT64(obj_desc->region.address),
772                           obj_desc->region.length));
773
774         /* Now the address and length are valid for this opregion */
775
776         obj_desc->region.flags |= AOPOBJ_DATA_VALID;
777
778         return_ACPI_STATUS(status);
779 }
780
781 /*******************************************************************************
782  *
783  * FUNCTION:    acpi_ds_eval_data_object_operands
784  *
785  * PARAMETERS:  walk_state      - Current walk
786  *              Op              - A valid data_object Op object
787  *              obj_desc        - data_object
788  *
789  * RETURN:      Status
790  *
791  * DESCRIPTION: Get the operands and complete the following data object types:
792  *              Buffer, Package.
793  *
794  ******************************************************************************/
795
796 acpi_status
797 acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
798                                   union acpi_parse_object *op,
799                                   union acpi_operand_object *obj_desc)
800 {
801         acpi_status status;
802         union acpi_operand_object *arg_desc;
803         u32 length;
804
805         ACPI_FUNCTION_TRACE(ds_eval_data_object_operands);
806
807         /* The first operand (for all of these data objects) is the length */
808
809         status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1);
810         if (ACPI_FAILURE(status)) {
811                 return_ACPI_STATUS(status);
812         }
813
814         status = acpi_ex_resolve_operands(walk_state->opcode,
815                                           &(walk_state->
816                                             operands[walk_state->num_operands -
817                                                      1]), walk_state);
818         if (ACPI_FAILURE(status)) {
819                 return_ACPI_STATUS(status);
820         }
821
822         /* Extract length operand */
823
824         arg_desc = walk_state->operands[walk_state->num_operands - 1];
825         length = (u32) arg_desc->integer.value;
826
827         /* Cleanup for length operand */
828
829         status = acpi_ds_obj_stack_pop(1, walk_state);
830         if (ACPI_FAILURE(status)) {
831                 return_ACPI_STATUS(status);
832         }
833
834         acpi_ut_remove_reference(arg_desc);
835
836         /*
837          * Create the actual data object
838          */
839         switch (op->common.aml_opcode) {
840         case AML_BUFFER_OP:
841
842                 status =
843                     acpi_ds_build_internal_buffer_obj(walk_state, op, length,
844                                                       &obj_desc);
845                 break;
846
847         case AML_PACKAGE_OP:
848         case AML_VAR_PACKAGE_OP:
849
850                 status =
851                     acpi_ds_build_internal_package_obj(walk_state, op, length,
852                                                        &obj_desc);
853                 break;
854
855         default:
856                 return_ACPI_STATUS(AE_AML_BAD_OPCODE);
857         }
858
859         if (ACPI_SUCCESS(status)) {
860                 /*
861                  * Return the object in the walk_state, unless the parent is a package -
862                  * in this case, the return object will be stored in the parse tree
863                  * for the package.
864                  */
865                 if ((!op->common.parent) ||
866                     ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
867                      (op->common.parent->common.aml_opcode !=
868                       AML_VAR_PACKAGE_OP)
869                      && (op->common.parent->common.aml_opcode !=
870                          AML_NAME_OP))) {
871                         walk_state->result_obj = obj_desc;
872                 }
873         }
874
875         return_ACPI_STATUS(status);
876 }
877
878 /*******************************************************************************
879  *
880  * FUNCTION:    acpi_ds_exec_begin_control_op
881  *
882  * PARAMETERS:  walk_list       - The list that owns the walk stack
883  *              Op              - The control Op
884  *
885  * RETURN:      Status
886  *
887  * DESCRIPTION: Handles all control ops encountered during control method
888  *              execution.
889  *
890  ******************************************************************************/
891
892 acpi_status
893 acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
894                               union acpi_parse_object *op)
895 {
896         acpi_status status = AE_OK;
897         union acpi_generic_state *control_state;
898
899         ACPI_FUNCTION_NAME(ds_exec_begin_control_op);
900
901         ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op,
902                           op->common.aml_opcode, walk_state));
903
904         switch (op->common.aml_opcode) {
905         case AML_IF_OP:
906         case AML_WHILE_OP:
907
908                 /*
909                  * IF/WHILE: Create a new control state to manage these
910                  * constructs. We need to manage these as a stack, in order
911                  * to handle nesting.
912                  */
913                 control_state = acpi_ut_create_control_state();
914                 if (!control_state) {
915                         status = AE_NO_MEMORY;
916                         break;
917                 }
918                 /*
919                  * Save a pointer to the predicate for multiple executions
920                  * of a loop
921                  */
922                 control_state->control.aml_predicate_start =
923                     walk_state->parser_state.aml - 1;
924                 control_state->control.package_end =
925                     walk_state->parser_state.pkg_end;
926                 control_state->control.opcode = op->common.aml_opcode;
927
928                 /* Push the control state on this walk's control stack */
929
930                 acpi_ut_push_generic_state(&walk_state->control_state,
931                                            control_state);
932                 break;
933
934         case AML_ELSE_OP:
935
936                 /* Predicate is in the state object */
937                 /* If predicate is true, the IF was executed, ignore ELSE part */
938
939                 if (walk_state->last_predicate) {
940                         status = AE_CTRL_TRUE;
941                 }
942
943                 break;
944
945         case AML_RETURN_OP:
946
947                 break;
948
949         default:
950                 break;
951         }
952
953         return (status);
954 }
955
956 /*******************************************************************************
957  *
958  * FUNCTION:    acpi_ds_exec_end_control_op
959  *
960  * PARAMETERS:  walk_list       - The list that owns the walk stack
961  *              Op              - The control Op
962  *
963  * RETURN:      Status
964  *
965  * DESCRIPTION: Handles all control ops encountered during control method
966  *              execution.
967  *
968  ******************************************************************************/
969
970 acpi_status
971 acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
972                             union acpi_parse_object * op)
973 {
974         acpi_status status = AE_OK;
975         union acpi_generic_state *control_state;
976
977         ACPI_FUNCTION_NAME(ds_exec_end_control_op);
978
979         switch (op->common.aml_opcode) {
980         case AML_IF_OP:
981
982                 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op));
983
984                 /*
985                  * Save the result of the predicate in case there is an
986                  * ELSE to come
987                  */
988                 walk_state->last_predicate =
989                     (u8) walk_state->control_state->common.value;
990
991                 /*
992                  * Pop the control state that was created at the start
993                  * of the IF and free it
994                  */
995                 control_state =
996                     acpi_ut_pop_generic_state(&walk_state->control_state);
997                 acpi_ut_delete_generic_state(control_state);
998                 break;
999
1000         case AML_ELSE_OP:
1001
1002                 break;
1003
1004         case AML_WHILE_OP:
1005
1006                 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op));
1007
1008                 if (walk_state->control_state->common.value) {
1009
1010                         /* Predicate was true, go back and evaluate it again! */
1011
1012                         status = AE_CTRL_PENDING;
1013                 }
1014
1015                 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
1016                                   "[WHILE_OP] termination! Op=%p\n", op));
1017
1018                 /* Pop this control state and free it */
1019
1020                 control_state =
1021                     acpi_ut_pop_generic_state(&walk_state->control_state);
1022
1023                 walk_state->aml_last_while =
1024                     control_state->control.aml_predicate_start;
1025                 acpi_ut_delete_generic_state(control_state);
1026                 break;
1027
1028         case AML_RETURN_OP:
1029
1030                 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
1031                                   "[RETURN_OP] Op=%p Arg=%p\n", op,
1032                                   op->common.value.arg));
1033
1034                 /*
1035                  * One optional operand -- the return value
1036                  * It can be either an immediate operand or a result that
1037                  * has been bubbled up the tree
1038                  */
1039                 if (op->common.value.arg) {
1040
1041                         /* Since we have a real Return(), delete any implicit return */
1042
1043                         acpi_ds_clear_implicit_return(walk_state);
1044
1045                         /* Return statement has an immediate operand */
1046
1047                         status =
1048                             acpi_ds_create_operands(walk_state,
1049                                                     op->common.value.arg);
1050                         if (ACPI_FAILURE(status)) {
1051                                 return (status);
1052                         }
1053
1054                         /*
1055                          * If value being returned is a Reference (such as
1056                          * an arg or local), resolve it now because it may
1057                          * cease to exist at the end of the method.
1058                          */
1059                         status =
1060                             acpi_ex_resolve_to_value(&walk_state->operands[0],
1061                                                      walk_state);
1062                         if (ACPI_FAILURE(status)) {
1063                                 return (status);
1064                         }
1065
1066                         /*
1067                          * Get the return value and save as the last result
1068                          * value.  This is the only place where walk_state->return_desc
1069                          * is set to anything other than zero!
1070                          */
1071                         walk_state->return_desc = walk_state->operands[0];
1072                 } else if ((walk_state->results) &&
1073                            (walk_state->results->results.num_results > 0)) {
1074
1075                         /* Since we have a real Return(), delete any implicit return */
1076
1077                         acpi_ds_clear_implicit_return(walk_state);
1078
1079                         /*
1080                          * The return value has come from a previous calculation.
1081                          *
1082                          * If value being returned is a Reference (such as
1083                          * an arg or local), resolve it now because it may
1084                          * cease to exist at the end of the method.
1085                          *
1086                          * Allow references created by the Index operator to return unchanged.
1087                          */
1088                         if ((ACPI_GET_DESCRIPTOR_TYPE
1089                              (walk_state->results->results.obj_desc[0]) ==
1090                              ACPI_DESC_TYPE_OPERAND)
1091                             &&
1092                             (ACPI_GET_OBJECT_TYPE
1093                              (walk_state->results->results.obj_desc[0]) ==
1094                              ACPI_TYPE_LOCAL_REFERENCE)
1095                             && ((walk_state->results->results.obj_desc[0])->
1096                                 reference.opcode != AML_INDEX_OP)) {
1097                                 status =
1098                                     acpi_ex_resolve_to_value(&walk_state->
1099                                                              results->results.
1100                                                              obj_desc[0],
1101                                                              walk_state);
1102                                 if (ACPI_FAILURE(status)) {
1103                                         return (status);
1104                                 }
1105                         }
1106
1107                         walk_state->return_desc =
1108                             walk_state->results->results.obj_desc[0];
1109                 } else {
1110                         /* No return operand */
1111
1112                         if (walk_state->num_operands) {
1113                                 acpi_ut_remove_reference(walk_state->
1114                                                          operands[0]);
1115                         }
1116
1117                         walk_state->operands[0] = NULL;
1118                         walk_state->num_operands = 0;
1119                         walk_state->return_desc = NULL;
1120                 }
1121
1122                 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
1123                                   "Completed RETURN_OP State=%p, RetVal=%p\n",
1124                                   walk_state, walk_state->return_desc));
1125
1126                 /* End the control method execution right now */
1127
1128                 status = AE_CTRL_TERMINATE;
1129                 break;
1130
1131         case AML_NOOP_OP:
1132
1133                 /* Just do nothing! */
1134                 break;
1135
1136         case AML_BREAK_POINT_OP:
1137
1138                 /* Call up to the OS service layer to handle this */
1139
1140                 status =
1141                     acpi_os_signal(ACPI_SIGNAL_BREAKPOINT,
1142                                    "Executed AML Breakpoint opcode");
1143
1144                 /* If and when it returns, all done. */
1145
1146                 break;
1147
1148         case AML_BREAK_OP:
1149         case AML_CONTINUE_OP:   /* ACPI 2.0 */
1150
1151                 /* Pop and delete control states until we find a while */
1152
1153                 while (walk_state->control_state &&
1154                        (walk_state->control_state->control.opcode !=
1155                         AML_WHILE_OP)) {
1156                         control_state =
1157                             acpi_ut_pop_generic_state(&walk_state->
1158                                                       control_state);
1159                         acpi_ut_delete_generic_state(control_state);
1160                 }
1161
1162                 /* No while found? */
1163
1164                 if (!walk_state->control_state) {
1165                         return (AE_AML_NO_WHILE);
1166                 }
1167
1168                 /* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */
1169
1170                 walk_state->aml_last_while =
1171                     walk_state->control_state->control.package_end;
1172
1173                 /* Return status depending on opcode */
1174
1175                 if (op->common.aml_opcode == AML_BREAK_OP) {
1176                         status = AE_CTRL_BREAK;
1177                 } else {
1178                         status = AE_CTRL_CONTINUE;
1179                 }
1180                 break;
1181
1182         default:
1183
1184                 ACPI_ERROR((AE_INFO, "Unknown control opcode=%X Op=%p",
1185                             op->common.aml_opcode, op));
1186
1187                 status = AE_AML_BAD_OPCODE;
1188                 break;
1189         }
1190
1191         return (status);
1192 }