Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dsmthdat.c
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * Module Name: dsmthdat - control method arguments and local variables
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2012, Intel Corp.
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 "accommon.h"
46 #include "acdispat.h"
47 #include "acnamesp.h"
48 #include "acinterp.h"
49 
50 #define _COMPONENT ACPI_DISPATCHER
51 ACPI_MODULE_NAME("dsmthdat")
52 
53 /* Local prototypes */
54 static void
55 acpi_ds_method_data_delete_value(u8 type,
56  u32 index, struct acpi_walk_state *walk_state);
57 
58 static acpi_status
59 acpi_ds_method_data_set_value(u8 type,
60  u32 index,
61  union acpi_operand_object *object,
62  struct acpi_walk_state *walk_state);
63 
64 #ifdef ACPI_OBSOLETE_FUNCTIONS
66 acpi_ds_method_data_get_type(u16 opcode,
67  u32 index, struct acpi_walk_state *walk_state);
68 #endif
69 
70 /*******************************************************************************
71  *
72  * FUNCTION: acpi_ds_method_data_init
73  *
74  * PARAMETERS: walk_state - Current walk state object
75  *
76  * RETURN: Status
77  *
78  * DESCRIPTION: Initialize the data structures that hold the method's arguments
79  * and locals. The data struct is an array of namespace nodes for
80  * each - this allows ref_of and de_ref_of to work properly for these
81  * special data types.
82  *
83  * NOTES: walk_state fields are initialized to zero by the
84  * ACPI_ALLOCATE_ZEROED().
85  *
86  * A pseudo-Namespace Node is assigned to each argument and local
87  * so that ref_of() can return a pointer to the Node.
88  *
89  ******************************************************************************/
90 
91 void acpi_ds_method_data_init(struct acpi_walk_state *walk_state)
92 {
93  u32 i;
94 
95  ACPI_FUNCTION_TRACE(ds_method_data_init);
96 
97  /* Init the method arguments */
98 
99  for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) {
100  ACPI_MOVE_32_TO_32(&walk_state->arguments[i].name,
102  walk_state->arguments[i].name.integer |= (i << 24);
103  walk_state->arguments[i].descriptor_type = ACPI_DESC_TYPE_NAMED;
104  walk_state->arguments[i].type = ACPI_TYPE_ANY;
105  walk_state->arguments[i].flags = ANOBJ_METHOD_ARG;
106  }
107 
108  /* Init the method locals */
109 
110  for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) {
111  ACPI_MOVE_32_TO_32(&walk_state->local_variables[i].name,
113 
114  walk_state->local_variables[i].name.integer |= (i << 24);
115  walk_state->local_variables[i].descriptor_type =
117  walk_state->local_variables[i].type = ACPI_TYPE_ANY;
118  walk_state->local_variables[i].flags = ANOBJ_METHOD_LOCAL;
119  }
120 
121  return_VOID;
122 }
123 
124 /*******************************************************************************
125  *
126  * FUNCTION: acpi_ds_method_data_delete_all
127  *
128  * PARAMETERS: walk_state - Current walk state object
129  *
130  * RETURN: None
131  *
132  * DESCRIPTION: Delete method locals and arguments. Arguments are only
133  * deleted if this method was called from another method.
134  *
135  ******************************************************************************/
136 
138 {
139  u32 index;
140 
141  ACPI_FUNCTION_TRACE(ds_method_data_delete_all);
142 
143  /* Detach the locals */
144 
145  for (index = 0; index < ACPI_METHOD_NUM_LOCALS; index++) {
146  if (walk_state->local_variables[index].object) {
147  ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Local%u=%p\n",
148  index,
149  walk_state->local_variables[index].
150  object));
151 
152  /* Detach object (if present) and remove a reference */
153 
154  acpi_ns_detach_object(&walk_state->
155  local_variables[index]);
156  }
157  }
158 
159  /* Detach the arguments */
160 
161  for (index = 0; index < ACPI_METHOD_NUM_ARGS; index++) {
162  if (walk_state->arguments[index].object) {
163  ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Arg%u=%p\n",
164  index,
165  walk_state->arguments[index].object));
166 
167  /* Detach object (if present) and remove a reference */
168 
169  acpi_ns_detach_object(&walk_state->arguments[index]);
170  }
171  }
172 
173  return_VOID;
174 }
175 
176 /*******************************************************************************
177  *
178  * FUNCTION: acpi_ds_method_data_init_args
179  *
180  * PARAMETERS: *params - Pointer to a parameter list for the method
181  * max_param_count - The arg count for this method
182  * walk_state - Current walk state object
183  *
184  * RETURN: Status
185  *
186  * DESCRIPTION: Initialize arguments for a method. The parameter list is a list
187  * of ACPI operand objects, either null terminated or whose length
188  * is defined by max_param_count.
189  *
190  ******************************************************************************/
191 
194  u32 max_param_count,
195  struct acpi_walk_state *walk_state)
196 {
198  u32 index = 0;
199 
200  ACPI_FUNCTION_TRACE_PTR(ds_method_data_init_args, params);
201 
202  if (!params) {
204  "No param list passed to method\n"));
206  }
207 
208  /* Copy passed parameters into the new method stack frame */
209 
210  while ((index < ACPI_METHOD_NUM_ARGS) &&
211  (index < max_param_count) && params[index]) {
212  /*
213  * A valid parameter.
214  * Store the argument in the method/walk descriptor.
215  * Do not copy the arg in order to implement call by reference
216  */
217  status = acpi_ds_method_data_set_value(ACPI_REFCLASS_ARG, index,
218  params[index],
219  walk_state);
220  if (ACPI_FAILURE(status)) {
221  return_ACPI_STATUS(status);
222  }
223 
224  index++;
225  }
226 
227  ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%u args passed to method\n", index));
229 }
230 
231 /*******************************************************************************
232  *
233  * FUNCTION: acpi_ds_method_data_get_node
234  *
235  * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or
236  * ACPI_REFCLASS_ARG
237  * index - Which Local or Arg whose type to get
238  * walk_state - Current walk state object
239  * node - Where the node is returned.
240  *
241  * RETURN: Status and node
242  *
243  * DESCRIPTION: Get the Node associated with a local or arg.
244  *
245  ******************************************************************************/
246 
249  u32 index,
250  struct acpi_walk_state *walk_state,
251  struct acpi_namespace_node **node)
252 {
253  ACPI_FUNCTION_TRACE(ds_method_data_get_node);
254 
255  /*
256  * Method Locals and Arguments are supported
257  */
258  switch (type) {
259  case ACPI_REFCLASS_LOCAL:
260 
261  if (index > ACPI_METHOD_MAX_LOCAL) {
263  "Local index %u is invalid (max %u)",
264  index, ACPI_METHOD_MAX_LOCAL));
266  }
267 
268  /* Return a pointer to the pseudo-node */
269 
270  *node = &walk_state->local_variables[index];
271  break;
272 
273  case ACPI_REFCLASS_ARG:
274 
275  if (index > ACPI_METHOD_MAX_ARG) {
277  "Arg index %u is invalid (max %u)",
278  index, ACPI_METHOD_MAX_ARG));
280  }
281 
282  /* Return a pointer to the pseudo-node */
283 
284  *node = &walk_state->arguments[index];
285  break;
286 
287  default:
288  ACPI_ERROR((AE_INFO, "Type %u is invalid", type));
290  }
291 
293 }
294 
295 /*******************************************************************************
296  *
297  * FUNCTION: acpi_ds_method_data_set_value
298  *
299  * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or
300  * ACPI_REFCLASS_ARG
301  * index - Which Local or Arg to get
302  * object - Object to be inserted into the stack entry
303  * walk_state - Current walk state object
304  *
305  * RETURN: Status
306  *
307  * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index.
308  * Note: There is no "implicit conversion" for locals.
309  *
310  ******************************************************************************/
311 
312 static acpi_status
313 acpi_ds_method_data_set_value(u8 type,
314  u32 index,
315  union acpi_operand_object *object,
316  struct acpi_walk_state *walk_state)
317 {
319  struct acpi_namespace_node *node;
320 
321  ACPI_FUNCTION_TRACE(ds_method_data_set_value);
322 
324  "NewObj %p Type %2.2X, Refs=%u [%s]\n", object,
325  type, object->common.reference_count,
326  acpi_ut_get_type_name(object->common.type)));
327 
328  /* Get the namespace node for the arg/local */
329 
330  status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
331  if (ACPI_FAILURE(status)) {
332  return_ACPI_STATUS(status);
333  }
334 
335  /*
336  * Increment ref count so object can't be deleted while installed.
337  * NOTE: We do not copy the object in order to preserve the call by
338  * reference semantics of ACPI Control Method invocation.
339  * (See ACPI Specification 2.0C)
340  */
341  acpi_ut_add_reference(object);
342 
343  /* Install the object */
344 
345  node->object = object;
346  return_ACPI_STATUS(status);
347 }
348 
349 /*******************************************************************************
350  *
351  * FUNCTION: acpi_ds_method_data_get_value
352  *
353  * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or
354  * ACPI_REFCLASS_ARG
355  * index - Which localVar or argument to get
356  * walk_state - Current walk state object
357  * dest_desc - Where Arg or Local value is returned
358  *
359  * RETURN: Status
360  *
361  * DESCRIPTION: Retrieve value of selected Arg or Local for this method
362  * Used only in acpi_ex_resolve_to_value().
363  *
364  ******************************************************************************/
365 
368  u32 index,
369  struct acpi_walk_state *walk_state,
370  union acpi_operand_object **dest_desc)
371 {
373  struct acpi_namespace_node *node;
374  union acpi_operand_object *object;
375 
376  ACPI_FUNCTION_TRACE(ds_method_data_get_value);
377 
378  /* Validate the object descriptor */
379 
380  if (!dest_desc) {
381  ACPI_ERROR((AE_INFO, "Null object descriptor pointer"));
383  }
384 
385  /* Get the namespace node for the arg/local */
386 
387  status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
388  if (ACPI_FAILURE(status)) {
389  return_ACPI_STATUS(status);
390  }
391 
392  /* Get the object from the node */
393 
394  object = node->object;
395 
396  /* Examine the returned object, it must be valid. */
397 
398  if (!object) {
399  /*
400  * Index points to uninitialized object.
401  * This means that either 1) The expected argument was
402  * not passed to the method, or 2) A local variable
403  * was referenced by the method (via the ASL)
404  * before it was initialized. Either case is an error.
405  */
406 
407  /* If slack enabled, init the local_x/arg_x to an Integer of value zero */
408 
410  object = acpi_ut_create_integer_object((u64) 0);
411  if (!object) {
413  }
414 
415  node->object = object;
416  }
417 
418  /* Otherwise, return the error */
419 
420  else
421  switch (type) {
422  case ACPI_REFCLASS_ARG:
423 
425  "Uninitialized Arg[%u] at node %p",
426  index, node));
427 
429 
430  case ACPI_REFCLASS_LOCAL:
431 
432  /*
433  * No error message for this case, will be trapped again later to
434  * detect and ignore cases of Store(local_x,local_x)
435  */
437 
438  default:
439 
441  "Not a Arg/Local opcode: 0x%X",
442  type));
444  }
445  }
446 
447  /*
448  * The Index points to an initialized and valid object.
449  * Return an additional reference to the object
450  */
451  *dest_desc = object;
452  acpi_ut_add_reference(object);
453 
455 }
456 
457 /*******************************************************************************
458  *
459  * FUNCTION: acpi_ds_method_data_delete_value
460  *
461  * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or
462  * ACPI_REFCLASS_ARG
463  * index - Which localVar or argument to delete
464  * walk_state - Current walk state object
465  *
466  * RETURN: None
467  *
468  * DESCRIPTION: Delete the entry at Opcode:Index. Inserts
469  * a null into the stack slot after the object is deleted.
470  *
471  ******************************************************************************/
472 
473 static void
474 acpi_ds_method_data_delete_value(u8 type,
475  u32 index, struct acpi_walk_state *walk_state)
476 {
478  struct acpi_namespace_node *node;
479  union acpi_operand_object *object;
480 
481  ACPI_FUNCTION_TRACE(ds_method_data_delete_value);
482 
483  /* Get the namespace node for the arg/local */
484 
485  status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
486  if (ACPI_FAILURE(status)) {
487  return_VOID;
488  }
489 
490  /* Get the associated object */
491 
492  object = acpi_ns_get_attached_object(node);
493 
494  /*
495  * Undefine the Arg or Local by setting its descriptor
496  * pointer to NULL. Locals/Args can contain both
497  * ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs
498  */
499  node->object = NULL;
500 
501  if ((object) &&
503  /*
504  * There is a valid object.
505  * Decrement the reference count by one to balance the
506  * increment when the object was stored.
507  */
508  acpi_ut_remove_reference(object);
509  }
510 
511  return_VOID;
512 }
513 
514 /*******************************************************************************
515  *
516  * FUNCTION: acpi_ds_store_object_to_local
517  *
518  * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or
519  * ACPI_REFCLASS_ARG
520  * index - Which Local or Arg to set
521  * obj_desc - Value to be stored
522  * walk_state - Current walk state
523  *
524  * RETURN: Status
525  *
526  * DESCRIPTION: Store a value in an Arg or Local. The obj_desc is installed
527  * as the new value for the Arg or Local and the reference count
528  * for obj_desc is incremented.
529  *
530  ******************************************************************************/
531 
534  u32 index,
535  union acpi_operand_object *obj_desc,
536  struct acpi_walk_state *walk_state)
537 {
539  struct acpi_namespace_node *node;
540  union acpi_operand_object *current_obj_desc;
541  union acpi_operand_object *new_obj_desc;
542 
543  ACPI_FUNCTION_TRACE(ds_store_object_to_local);
544  ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Type=%2.2X Index=%u Obj=%p\n",
545  type, index, obj_desc));
546 
547  /* Parameter validation */
548 
549  if (!obj_desc) {
551  }
552 
553  /* Get the namespace node for the arg/local */
554 
555  status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
556  if (ACPI_FAILURE(status)) {
557  return_ACPI_STATUS(status);
558  }
559 
560  current_obj_desc = acpi_ns_get_attached_object(node);
561  if (current_obj_desc == obj_desc) {
562  ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p already installed!\n",
563  obj_desc));
564  return_ACPI_STATUS(status);
565  }
566 
567  /*
568  * If the reference count on the object is more than one, we must
569  * take a copy of the object before we store. A reference count
570  * of exactly 1 means that the object was just created during the
571  * evaluation of an expression, and we can safely use it since it
572  * is not used anywhere else.
573  */
574  new_obj_desc = obj_desc;
575  if (obj_desc->common.reference_count > 1) {
576  status =
577  acpi_ut_copy_iobject_to_iobject(obj_desc, &new_obj_desc,
578  walk_state);
579  if (ACPI_FAILURE(status)) {
580  return_ACPI_STATUS(status);
581  }
582  }
583 
584  /*
585  * If there is an object already in this slot, we either
586  * have to delete it, or if this is an argument and there
587  * is an object reference stored there, we have to do
588  * an indirect store!
589  */
590  if (current_obj_desc) {
591  /*
592  * Check for an indirect store if an argument
593  * contains an object reference (stored as an Node).
594  * We don't allow this automatic dereferencing for
595  * locals, since a store to a local should overwrite
596  * anything there, including an object reference.
597  *
598  * If both Arg0 and Local0 contain ref_of (Local4):
599  *
600  * Store (1, Arg0) - Causes indirect store to local4
601  * Store (1, Local0) - Stores 1 in local0, overwriting
602  * the reference to local4
603  * Store (1, de_refof (Local0)) - Causes indirect store to local4
604  *
605  * Weird, but true.
606  */
607  if (type == ACPI_REFCLASS_ARG) {
608  /*
609  * If we have a valid reference object that came from ref_of(),
610  * do the indirect store
611  */
612  if ((ACPI_GET_DESCRIPTOR_TYPE(current_obj_desc) ==
614  && (current_obj_desc->common.type ==
616  && (current_obj_desc->reference.class ==
619  "Arg (%p) is an ObjRef(Node), storing in node %p\n",
620  new_obj_desc,
621  current_obj_desc));
622 
623  /*
624  * Store this object to the Node (perform the indirect store)
625  * NOTE: No implicit conversion is performed, as per the ACPI
626  * specification rules on storing to Locals/Args.
627  */
628  status =
629  acpi_ex_store_object_to_node(new_obj_desc,
630  current_obj_desc->
631  reference.
632  object,
633  walk_state,
635 
636  /* Remove local reference if we copied the object above */
637 
638  if (new_obj_desc != obj_desc) {
639  acpi_ut_remove_reference(new_obj_desc);
640  }
641  return_ACPI_STATUS(status);
642  }
643  }
644 
645  /* Delete the existing object before storing the new one */
646 
647  acpi_ds_method_data_delete_value(type, index, walk_state);
648  }
649 
650  /*
651  * Install the Obj descriptor (*new_obj_desc) into
652  * the descriptor for the Arg or Local.
653  * (increments the object reference count by one)
654  */
655  status =
656  acpi_ds_method_data_set_value(type, index, new_obj_desc,
657  walk_state);
658 
659  /* Remove local reference if we copied the object above */
660 
661  if (new_obj_desc != obj_desc) {
662  acpi_ut_remove_reference(new_obj_desc);
663  }
664 
665  return_ACPI_STATUS(status);
666 }
667 
668 #ifdef ACPI_OBSOLETE_FUNCTIONS
669 /*******************************************************************************
670  *
671  * FUNCTION: acpi_ds_method_data_get_type
672  *
673  * PARAMETERS: opcode - Either AML_LOCAL_OP or AML_ARG_OP
674  * index - Which Local or Arg whose type to get
675  * walk_state - Current walk state object
676  *
677  * RETURN: Data type of current value of the selected Arg or Local
678  *
679  * DESCRIPTION: Get the type of the object stored in the Local or Arg
680  *
681  ******************************************************************************/
682 
684 acpi_ds_method_data_get_type(u16 opcode,
685  u32 index, struct acpi_walk_state *walk_state)
686 {
688  struct acpi_namespace_node *node;
689  union acpi_operand_object *object;
690 
691  ACPI_FUNCTION_TRACE(ds_method_data_get_type);
692 
693  /* Get the namespace node for the arg/local */
694 
695  status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
696  if (ACPI_FAILURE(status)) {
698  }
699 
700  /* Get the object */
701 
702  object = acpi_ns_get_attached_object(node);
703  if (!object) {
704 
705  /* Uninitialized local/arg, return TYPE_ANY */
706 
708  }
709 
710  /* Get the object type */
711 
712  return_VALUE(object->type);
713 }
714 #endif