2 * acpi_utils.c - ACPI Utility Functions ($Revision: 10 $)
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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.
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.
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.
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/init.h>
29 #include <linux/types.h>
30 #include <acpi/acpi_bus.h>
31 #include <acpi/acpi_drivers.h>
33 #define _COMPONENT ACPI_BUS_COMPONENT
34 ACPI_MODULE_NAME("acpi_utils")
36 /* --------------------------------------------------------------------------
37 Object Evaluation Helpers
38 -------------------------------------------------------------------------- */
39 #ifdef ACPI_DEBUG_OUTPUT
40 #define acpi_util_eval_error(h,p,s) {\
41 char prefix[80] = {'\0'};\
42 struct acpi_buffer buffer = {sizeof(prefix), prefix};\
43 acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\
44 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n",\
45 (char *) prefix, p, acpi_format_exception(s))); }
47 #define acpi_util_eval_error(h,p,s)
50 acpi_extract_package(union acpi_object
*package
,
51 struct acpi_buffer
*format
, struct acpi_buffer
*buffer
)
53 u32 size_required
= 0;
55 char *format_string
= NULL
;
62 if (!package
|| (package
->type
!= ACPI_TYPE_PACKAGE
)
63 || (package
->package
.count
< 1)) {
64 printk(KERN_WARNING PREFIX
"Invalid package argument\n");
65 return AE_BAD_PARAMETER
;
68 if (!format
|| !format
->pointer
|| (format
->length
< 1)) {
69 printk(KERN_WARNING PREFIX
"Invalid format argument\n");
70 return AE_BAD_PARAMETER
;
74 printk(KERN_WARNING PREFIX
"Invalid buffer argument\n");
75 return AE_BAD_PARAMETER
;
78 format_count
= (format
->length
/ sizeof(char)) - 1;
79 if (format_count
> package
->package
.count
) {
80 printk(KERN_WARNING PREFIX
"Format specifies more objects [%d]"
81 " than exist in package [%d].\n",
82 format_count
, package
->package
.count
);
86 format_string
= (char *)format
->pointer
;
89 * Calculate size_required.
91 for (i
= 0; i
< format_count
; i
++) {
93 union acpi_object
*element
= &(package
->package
.elements
[i
]);
99 switch (element
->type
) {
101 case ACPI_TYPE_INTEGER
:
102 switch (format_string
[i
]) {
104 size_required
+= sizeof(acpi_integer
);
105 tail_offset
+= sizeof(acpi_integer
);
109 sizeof(char *) + sizeof(acpi_integer
) +
111 tail_offset
+= sizeof(char *);
114 printk(KERN_WARNING PREFIX
"Invalid package element"
115 " [%d]: got number, expecing"
117 i
, format_string
[i
]);
123 case ACPI_TYPE_STRING
:
124 case ACPI_TYPE_BUFFER
:
125 switch (format_string
[i
]) {
129 (element
->string
.length
* sizeof(char)) +
131 tail_offset
+= sizeof(char *);
136 (element
->buffer
.length
* sizeof(u8
));
137 tail_offset
+= sizeof(u8
*);
140 printk(KERN_WARNING PREFIX
"Invalid package element"
141 " [%d] got string/buffer,"
143 i
, format_string
[i
]);
149 case ACPI_TYPE_PACKAGE
:
151 ACPI_DEBUG_PRINT((ACPI_DB_INFO
,
152 "Found unsupported element at index=%d\n",
154 /* TBD: handle nested packages... */
161 * Validate output buffer.
163 if (buffer
->length
< size_required
) {
164 buffer
->length
= size_required
;
165 return AE_BUFFER_OVERFLOW
;
166 } else if (buffer
->length
!= size_required
|| !buffer
->pointer
) {
167 return AE_BAD_PARAMETER
;
170 head
= buffer
->pointer
;
171 tail
= buffer
->pointer
+ tail_offset
;
174 * Extract package data.
176 for (i
= 0; i
< format_count
; i
++) {
179 union acpi_object
*element
= &(package
->package
.elements
[i
]);
185 switch (element
->type
) {
187 case ACPI_TYPE_INTEGER
:
188 switch (format_string
[i
]) {
190 *((acpi_integer
*) head
) =
191 element
->integer
.value
;
192 head
+= sizeof(acpi_integer
);
195 pointer
= (u8
**) head
;
197 *((acpi_integer
*) tail
) =
198 element
->integer
.value
;
199 head
+= sizeof(acpi_integer
*);
200 tail
+= sizeof(acpi_integer
);
201 /* NULL terminate string */
203 tail
+= sizeof(char);
206 /* Should never get here */
211 case ACPI_TYPE_STRING
:
212 case ACPI_TYPE_BUFFER
:
213 switch (format_string
[i
]) {
215 pointer
= (u8
**) head
;
217 memcpy(tail
, element
->string
.pointer
,
218 element
->string
.length
);
219 head
+= sizeof(char *);
220 tail
+= element
->string
.length
* sizeof(char);
221 /* NULL terminate string */
223 tail
+= sizeof(char);
226 pointer
= (u8
**) head
;
228 memcpy(tail
, element
->buffer
.pointer
,
229 element
->buffer
.length
);
230 head
+= sizeof(u8
*);
231 tail
+= element
->buffer
.length
* sizeof(u8
);
234 /* Should never get here */
239 case ACPI_TYPE_PACKAGE
:
240 /* TBD: handle nested packages... */
242 /* Should never get here */
250 EXPORT_SYMBOL(acpi_extract_package
);
253 acpi_evaluate_integer(acpi_handle handle
,
254 acpi_string pathname
,
255 struct acpi_object_list
*arguments
, unsigned long *data
)
257 acpi_status status
= AE_OK
;
258 union acpi_object
*element
;
259 struct acpi_buffer buffer
= { 0, NULL
};
263 return AE_BAD_PARAMETER
;
265 element
= kmalloc(sizeof(union acpi_object
), GFP_KERNEL
);
269 memset(element
, 0, sizeof(union acpi_object
));
270 buffer
.length
= sizeof(union acpi_object
);
271 buffer
.pointer
= element
;
272 status
= acpi_evaluate_object(handle
, pathname
, arguments
, &buffer
);
273 if (ACPI_FAILURE(status
)) {
274 acpi_util_eval_error(handle
, pathname
, status
);
279 if (element
->type
!= ACPI_TYPE_INTEGER
) {
280 acpi_util_eval_error(handle
, pathname
, AE_BAD_DATA
);
285 *data
= element
->integer
.value
;
288 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Return value [%lu]\n", *data
));
293 EXPORT_SYMBOL(acpi_evaluate_integer
);
297 acpi_evaluate_string(acpi_handle handle
,
298 acpi_string pathname
,
299 acpi_object_list
* arguments
, acpi_string
* data
)
301 acpi_status status
= AE_OK
;
302 acpi_object
*element
= NULL
;
303 acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
307 return AE_BAD_PARAMETER
;
309 status
= acpi_evaluate_object(handle
, pathname
, arguments
, &buffer
);
310 if (ACPI_FAILURE(status
)) {
311 acpi_util_eval_error(handle
, pathname
, status
);
315 element
= (acpi_object
*) buffer
.pointer
;
317 if ((element
->type
!= ACPI_TYPE_STRING
)
318 || (element
->type
!= ACPI_TYPE_BUFFER
)
319 || !element
->string
.length
) {
320 acpi_util_eval_error(handle
, pathname
, AE_BAD_DATA
);
324 *data
= kmalloc(element
->string
.length
+ 1, GFP_KERNEL
);
326 printk(KERN_ERR PREFIX
"Memory allocation\n");
329 memset(*data
, 0, element
->string
.length
+ 1);
331 memcpy(*data
, element
->string
.pointer
, element
->string
.length
);
333 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Return value [%s]\n", *data
));
335 kfree(buffer
.pointer
);
342 acpi_evaluate_reference(acpi_handle handle
,
343 acpi_string pathname
,
344 struct acpi_object_list
*arguments
,
345 struct acpi_handle_list
*list
)
347 acpi_status status
= AE_OK
;
348 union acpi_object
*package
= NULL
;
349 union acpi_object
*element
= NULL
;
350 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
355 return AE_BAD_PARAMETER
;
358 /* Evaluate object. */
360 status
= acpi_evaluate_object(handle
, pathname
, arguments
, &buffer
);
361 if (ACPI_FAILURE(status
))
364 package
= (union acpi_object
*)buffer
.pointer
;
366 if ((buffer
.length
== 0) || !package
) {
367 printk(KERN_ERR PREFIX
"No return object (len %X ptr %p)\n",
368 (unsigned)buffer
.length
, package
);
369 status
= AE_BAD_DATA
;
370 acpi_util_eval_error(handle
, pathname
, status
);
373 if (package
->type
!= ACPI_TYPE_PACKAGE
) {
374 printk(KERN_ERR PREFIX
"Expecting a [Package], found type %X\n",
376 status
= AE_BAD_DATA
;
377 acpi_util_eval_error(handle
, pathname
, status
);
380 if (!package
->package
.count
) {
381 printk(KERN_ERR PREFIX
"[Package] has zero elements (%p)\n",
383 status
= AE_BAD_DATA
;
384 acpi_util_eval_error(handle
, pathname
, status
);
388 if (package
->package
.count
> ACPI_MAX_HANDLES
) {
391 list
->count
= package
->package
.count
;
393 /* Extract package data. */
395 for (i
= 0; i
< list
->count
; i
++) {
397 element
= &(package
->package
.elements
[i
]);
399 if (element
->type
!= ACPI_TYPE_ANY
) {
400 status
= AE_BAD_DATA
;
401 printk(KERN_ERR PREFIX
402 "Expecting a [Reference] package element, found type %X\n",
404 acpi_util_eval_error(handle
, pathname
, status
);
408 /* Get the acpi_handle. */
410 list
->handles
[i
] = element
->reference
.handle
;
411 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Found reference [%p]\n",
416 if (ACPI_FAILURE(status
)) {
418 //kfree(list->handles);
421 kfree(buffer
.pointer
);
426 EXPORT_SYMBOL(acpi_evaluate_reference
);