Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
utils.c
Go to the documentation of this file.
1 /*
2  * acpi_utils.c - ACPI Utility Functions ($Revision: 10 $)
3  *
4  * Copyright (C) 2001, 2002 Andy Grover <[email protected]>
5  * Copyright (C) 2001, 2002 Paul Diefenbaugh <[email protected]>
6  *
7  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or (at
12  * your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22  *
23  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24  */
25 
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/slab.h>
29 #include <linux/init.h>
30 #include <linux/types.h>
31 #include <acpi/acpi_bus.h>
32 #include <acpi/acpi_drivers.h>
33 
34 #include "internal.h"
35 
36 #define _COMPONENT ACPI_BUS_COMPONENT
37 ACPI_MODULE_NAME("utils");
38 
39 /* --------------------------------------------------------------------------
40  Object Evaluation Helpers
41  -------------------------------------------------------------------------- */
42 static void
43 acpi_util_eval_error(acpi_handle h, acpi_string p, acpi_status s)
44 {
45 #ifdef ACPI_DEBUG_OUTPUT
46  char prefix[80] = {'\0'};
47  struct acpi_buffer buffer = {sizeof(prefix), prefix};
48  acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);
49  ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n",
50  (char *) prefix, p, acpi_format_exception(s)));
51 #else
52  return;
53 #endif
54 }
55 
58  struct acpi_buffer *format, struct acpi_buffer *buffer)
59 {
60  u32 size_required = 0;
61  u32 tail_offset = 0;
62  char *format_string = NULL;
63  u32 format_count = 0;
64  u32 i = 0;
65  u8 *head = NULL;
66  u8 *tail = NULL;
67 
68 
69  if (!package || (package->type != ACPI_TYPE_PACKAGE)
70  || (package->package.count < 1)) {
71  printk(KERN_WARNING PREFIX "Invalid package argument\n");
72  return AE_BAD_PARAMETER;
73  }
74 
75  if (!format || !format->pointer || (format->length < 1)) {
76  printk(KERN_WARNING PREFIX "Invalid format argument\n");
77  return AE_BAD_PARAMETER;
78  }
79 
80  if (!buffer) {
81  printk(KERN_WARNING PREFIX "Invalid buffer argument\n");
82  return AE_BAD_PARAMETER;
83  }
84 
85  format_count = (format->length / sizeof(char)) - 1;
86  if (format_count > package->package.count) {
87  printk(KERN_WARNING PREFIX "Format specifies more objects [%d]"
88  " than exist in package [%d].\n",
89  format_count, package->package.count);
90  return AE_BAD_DATA;
91  }
92 
93  format_string = format->pointer;
94 
95  /*
96  * Calculate size_required.
97  */
98  for (i = 0; i < format_count; i++) {
99 
100  union acpi_object *element = &(package->package.elements[i]);
101 
102  if (!element) {
103  return AE_BAD_DATA;
104  }
105 
106  switch (element->type) {
107 
108  case ACPI_TYPE_INTEGER:
109  switch (format_string[i]) {
110  case 'N':
111  size_required += sizeof(u64);
112  tail_offset += sizeof(u64);
113  break;
114  case 'S':
115  size_required +=
116  sizeof(char *) + sizeof(u64) +
117  sizeof(char);
118  tail_offset += sizeof(char *);
119  break;
120  default:
121  printk(KERN_WARNING PREFIX "Invalid package element"
122  " [%d]: got number, expecing"
123  " [%c]\n",
124  i, format_string[i]);
125  return AE_BAD_DATA;
126  break;
127  }
128  break;
129 
130  case ACPI_TYPE_STRING:
131  case ACPI_TYPE_BUFFER:
132  switch (format_string[i]) {
133  case 'S':
134  size_required +=
135  sizeof(char *) +
136  (element->string.length * sizeof(char)) +
137  sizeof(char);
138  tail_offset += sizeof(char *);
139  break;
140  case 'B':
141  size_required +=
142  sizeof(u8 *) +
143  (element->buffer.length * sizeof(u8));
144  tail_offset += sizeof(u8 *);
145  break;
146  default:
147  printk(KERN_WARNING PREFIX "Invalid package element"
148  " [%d] got string/buffer,"
149  " expecing [%c]\n",
150  i, format_string[i]);
151  return AE_BAD_DATA;
152  break;
153  }
154  break;
155 
156  case ACPI_TYPE_PACKAGE:
157  default:
159  "Found unsupported element at index=%d\n",
160  i));
161  /* TBD: handle nested packages... */
162  return AE_SUPPORT;
163  break;
164  }
165  }
166 
167  /*
168  * Validate output buffer.
169  */
170  if (buffer->length < size_required) {
171  buffer->length = size_required;
172  return AE_BUFFER_OVERFLOW;
173  } else if (buffer->length != size_required || !buffer->pointer) {
174  return AE_BAD_PARAMETER;
175  }
176 
177  head = buffer->pointer;
178  tail = buffer->pointer + tail_offset;
179 
180  /*
181  * Extract package data.
182  */
183  for (i = 0; i < format_count; i++) {
184 
185  u8 **pointer = NULL;
186  union acpi_object *element = &(package->package.elements[i]);
187 
188  if (!element) {
189  return AE_BAD_DATA;
190  }
191 
192  switch (element->type) {
193 
194  case ACPI_TYPE_INTEGER:
195  switch (format_string[i]) {
196  case 'N':
197  *((u64 *) head) =
198  element->integer.value;
199  head += sizeof(u64);
200  break;
201  case 'S':
202  pointer = (u8 **) head;
203  *pointer = tail;
204  *((u64 *) tail) =
205  element->integer.value;
206  head += sizeof(u64 *);
207  tail += sizeof(u64);
208  /* NULL terminate string */
209  *tail = (char)0;
210  tail += sizeof(char);
211  break;
212  default:
213  /* Should never get here */
214  break;
215  }
216  break;
217 
218  case ACPI_TYPE_STRING:
219  case ACPI_TYPE_BUFFER:
220  switch (format_string[i]) {
221  case 'S':
222  pointer = (u8 **) head;
223  *pointer = tail;
224  memcpy(tail, element->string.pointer,
225  element->string.length);
226  head += sizeof(char *);
227  tail += element->string.length * sizeof(char);
228  /* NULL terminate string */
229  *tail = (char)0;
230  tail += sizeof(char);
231  break;
232  case 'B':
233  pointer = (u8 **) head;
234  *pointer = tail;
235  memcpy(tail, element->buffer.pointer,
236  element->buffer.length);
237  head += sizeof(u8 *);
238  tail += element->buffer.length * sizeof(u8);
239  break;
240  default:
241  /* Should never get here */
242  break;
243  }
244  break;
245 
246  case ACPI_TYPE_PACKAGE:
247  /* TBD: handle nested packages... */
248  default:
249  /* Should never get here */
250  break;
251  }
252  }
253 
254  return AE_OK;
255 }
256 
258 
262  struct acpi_object_list *arguments, unsigned long long *data)
263 {
265  union acpi_object element;
266  struct acpi_buffer buffer = { 0, NULL };
267 
268  if (!data)
269  return AE_BAD_PARAMETER;
270 
271  buffer.length = sizeof(union acpi_object);
272  buffer.pointer = &element;
273  status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
274  if (ACPI_FAILURE(status)) {
275  acpi_util_eval_error(handle, pathname, status);
276  return status;
277  }
278 
279  if (element.type != ACPI_TYPE_INTEGER) {
280  acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
281  return AE_BAD_DATA;
282  }
283 
284  *data = element.integer.value;
285 
286  ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data));
287 
288  return AE_OK;
289 }
290 
292 
296  struct acpi_object_list *arguments,
297  struct acpi_handle_list *list)
298 {
300  union acpi_object *package = NULL;
301  union acpi_object *element = NULL;
302  struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
303  u32 i = 0;
304 
305 
306  if (!list) {
307  return AE_BAD_PARAMETER;
308  }
309 
310  /* Evaluate object. */
311 
312  status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
313  if (ACPI_FAILURE(status))
314  goto end;
315 
316  package = buffer.pointer;
317 
318  if ((buffer.length == 0) || !package) {
319  printk(KERN_ERR PREFIX "No return object (len %X ptr %p)\n",
320  (unsigned)buffer.length, package);
321  status = AE_BAD_DATA;
322  acpi_util_eval_error(handle, pathname, status);
323  goto end;
324  }
325  if (package->type != ACPI_TYPE_PACKAGE) {
326  printk(KERN_ERR PREFIX "Expecting a [Package], found type %X\n",
327  package->type);
328  status = AE_BAD_DATA;
329  acpi_util_eval_error(handle, pathname, status);
330  goto end;
331  }
332  if (!package->package.count) {
333  printk(KERN_ERR PREFIX "[Package] has zero elements (%p)\n",
334  package);
335  status = AE_BAD_DATA;
336  acpi_util_eval_error(handle, pathname, status);
337  goto end;
338  }
339 
340  if (package->package.count > ACPI_MAX_HANDLES) {
341  return AE_NO_MEMORY;
342  }
343  list->count = package->package.count;
344 
345  /* Extract package data. */
346 
347  for (i = 0; i < list->count; i++) {
348 
349  element = &(package->package.elements[i]);
350 
352  status = AE_BAD_DATA;
354  "Expecting a [Reference] package element, found type %X\n",
355  element->type);
356  acpi_util_eval_error(handle, pathname, status);
357  break;
358  }
359 
360  if (!element->reference.handle) {
361  printk(KERN_WARNING PREFIX "Invalid reference in"
362  " package %s\n", pathname);
363  status = AE_NULL_ENTRY;
364  break;
365  }
366  /* Get the acpi_handle. */
367 
368  list->handles[i] = element->reference.handle;
369  ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found reference [%p]\n",
370  list->handles[i]));
371  }
372 
373  end:
374  if (ACPI_FAILURE(status)) {
375  list->count = 0;
376  //kfree(list->handles);
377  }
378 
379  kfree(buffer.pointer);
380 
381  return status;
382 }
383 
385 
388 {
390  struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
391  union acpi_object *output;
392 
393  status = acpi_evaluate_object(handle, "_PLD", NULL, &buffer);
394 
395  if (ACPI_FAILURE(status))
396  return status;
397 
398  output = buffer.pointer;
399 
400  if (!output || output->type != ACPI_TYPE_PACKAGE
401  || !output->package.count
402  || output->package.elements[0].type != ACPI_TYPE_BUFFER
403  || output->package.elements[0].buffer.length < ACPI_PLD_REV1_BUFFER_SIZE) {
404  status = AE_TYPE;
405  goto out;
406  }
407 
408  status = acpi_decode_pld_buffer(
409  output->package.elements[0].buffer.pointer,
410  output->package.elements[0].buffer.length,
411  pld);
412 
413 out:
414  kfree(buffer.pointer);
415  return status;
416 }
418 
432  u32 status_code, struct acpi_buffer *status_buf)
433 {
434 #ifdef ACPI_HOTPLUG_OST
435  union acpi_object params[3] = {
436  {.type = ACPI_TYPE_INTEGER,},
437  {.type = ACPI_TYPE_INTEGER,},
438  {.type = ACPI_TYPE_BUFFER,}
439  };
440  struct acpi_object_list arg_list = {3, params};
442 
443  params[0].integer.value = source_event;
444  params[1].integer.value = status_code;
445  if (status_buf != NULL) {
446  params[2].buffer.pointer = status_buf->pointer;
447  params[2].buffer.length = status_buf->length;
448  } else {
449  params[2].buffer.pointer = NULL;
450  params[2].buffer.length = 0;
451  }
452 
453  status = acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
454  return status;
455 #else
456  return AE_OK;
457 #endif
458 }