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
= 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
= kzalloc(sizeof(union acpi_object
), irqs_disabled() ? GFP_ATOMIC
: GFP_KERNEL
);
269 buffer
.length
= sizeof(union acpi_object
);
270 buffer
.pointer
= element
;
271 status
= acpi_evaluate_object(handle
, pathname
, arguments
, &buffer
);
272 if (ACPI_FAILURE(status
)) {
273 acpi_util_eval_error(handle
, pathname
, status
);
278 if (element
->type
!= ACPI_TYPE_INTEGER
) {
279 acpi_util_eval_error(handle
, pathname
, AE_BAD_DATA
);
284 *data
= element
->integer
.value
;
287 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Return value [%lu]\n", *data
));
292 EXPORT_SYMBOL(acpi_evaluate_integer
);
296 acpi_evaluate_string(acpi_handle handle
,
297 acpi_string pathname
,
298 acpi_object_list
* arguments
, acpi_string
* data
)
300 acpi_status status
= AE_OK
;
301 acpi_object
*element
= NULL
;
302 acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
306 return AE_BAD_PARAMETER
;
308 status
= acpi_evaluate_object(handle
, pathname
, arguments
, &buffer
);
309 if (ACPI_FAILURE(status
)) {
310 acpi_util_eval_error(handle
, pathname
, status
);
314 element
= (acpi_object
*) buffer
.pointer
;
316 if ((element
->type
!= ACPI_TYPE_STRING
)
317 || (element
->type
!= ACPI_TYPE_BUFFER
)
318 || !element
->string
.length
) {
319 acpi_util_eval_error(handle
, pathname
, AE_BAD_DATA
);
323 *data
= kzalloc(element
->string
.length
+ 1, GFP_KERNEL
);
325 printk(KERN_ERR PREFIX
"Memory allocation\n");
329 memcpy(*data
, element
->string
.pointer
, element
->string
.length
);
331 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Return value [%s]\n", *data
));
333 kfree(buffer
.pointer
);
340 acpi_evaluate_reference(acpi_handle handle
,
341 acpi_string pathname
,
342 struct acpi_object_list
*arguments
,
343 struct acpi_handle_list
*list
)
345 acpi_status status
= AE_OK
;
346 union acpi_object
*package
= NULL
;
347 union acpi_object
*element
= NULL
;
348 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
353 return AE_BAD_PARAMETER
;
356 /* Evaluate object. */
358 status
= acpi_evaluate_object(handle
, pathname
, arguments
, &buffer
);
359 if (ACPI_FAILURE(status
))
362 package
= buffer
.pointer
;
364 if ((buffer
.length
== 0) || !package
) {
365 printk(KERN_ERR PREFIX
"No return object (len %X ptr %p)\n",
366 (unsigned)buffer
.length
, package
);
367 status
= AE_BAD_DATA
;
368 acpi_util_eval_error(handle
, pathname
, status
);
371 if (package
->type
!= ACPI_TYPE_PACKAGE
) {
372 printk(KERN_ERR PREFIX
"Expecting a [Package], found type %X\n",
374 status
= AE_BAD_DATA
;
375 acpi_util_eval_error(handle
, pathname
, status
);
378 if (!package
->package
.count
) {
379 printk(KERN_ERR PREFIX
"[Package] has zero elements (%p)\n",
381 status
= AE_BAD_DATA
;
382 acpi_util_eval_error(handle
, pathname
, status
);
386 if (package
->package
.count
> ACPI_MAX_HANDLES
) {
389 list
->count
= package
->package
.count
;
391 /* Extract package data. */
393 for (i
= 0; i
< list
->count
; i
++) {
395 element
= &(package
->package
.elements
[i
]);
397 if (element
->type
!= ACPI_TYPE_ANY
) {
398 status
= AE_BAD_DATA
;
399 printk(KERN_ERR PREFIX
400 "Expecting a [Reference] package element, found type %X\n",
402 acpi_util_eval_error(handle
, pathname
, status
);
406 /* Get the acpi_handle. */
408 list
->handles
[i
] = element
->reference
.handle
;
409 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Found reference [%p]\n",
414 if (ACPI_FAILURE(status
)) {
416 //kfree(list->handles);
419 kfree(buffer
.pointer
);
424 EXPORT_SYMBOL(acpi_evaluate_reference
);