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
;
61 ACPI_FUNCTION_TRACE("acpi_extract_package");
63 if (!package
|| (package
->type
!= ACPI_TYPE_PACKAGE
)
64 || (package
->package
.count
< 1)) {
65 ACPI_DEBUG_PRINT((ACPI_DB_WARN
,
66 "Invalid 'package' argument\n"));
67 return_ACPI_STATUS(AE_BAD_PARAMETER
);
70 if (!format
|| !format
->pointer
|| (format
->length
< 1)) {
71 ACPI_DEBUG_PRINT((ACPI_DB_WARN
, "Invalid 'format' argument\n"));
72 return_ACPI_STATUS(AE_BAD_PARAMETER
);
76 ACPI_DEBUG_PRINT((ACPI_DB_WARN
, "Invalid 'buffer' argument\n"));
77 return_ACPI_STATUS(AE_BAD_PARAMETER
);
80 format_count
= (format
->length
/ sizeof(char)) - 1;
81 if (format_count
> package
->package
.count
) {
82 ACPI_DEBUG_PRINT((ACPI_DB_WARN
,
83 "Format specifies more objects [%d] than exist in package [%d].",
84 format_count
, package
->package
.count
));
85 return_ACPI_STATUS(AE_BAD_DATA
);
88 format_string
= (char *)format
->pointer
;
91 * Calculate size_required.
93 for (i
= 0; i
< format_count
; i
++) {
95 union acpi_object
*element
= &(package
->package
.elements
[i
]);
98 return_ACPI_STATUS(AE_BAD_DATA
);
101 switch (element
->type
) {
103 case ACPI_TYPE_INTEGER
:
104 switch (format_string
[i
]) {
106 size_required
+= sizeof(acpi_integer
);
107 tail_offset
+= sizeof(acpi_integer
);
111 sizeof(char *) + sizeof(acpi_integer
) +
113 tail_offset
+= sizeof(char *);
116 ACPI_DEBUG_PRINT((ACPI_DB_WARN
,
117 "Invalid package element [%d]: got number, expecing [%c].\n",
118 i
, format_string
[i
]));
119 return_ACPI_STATUS(AE_BAD_DATA
);
124 case ACPI_TYPE_STRING
:
125 case ACPI_TYPE_BUFFER
:
126 switch (format_string
[i
]) {
130 (element
->string
.length
* sizeof(char)) +
132 tail_offset
+= sizeof(char *);
137 (element
->buffer
.length
* sizeof(u8
));
138 tail_offset
+= sizeof(u8
*);
141 ACPI_DEBUG_PRINT((ACPI_DB_WARN
,
142 "Invalid package element [%d] got string/buffer, expecing [%c].\n",
143 i
, format_string
[i
]));
144 return_ACPI_STATUS(AE_BAD_DATA
);
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... */
155 return_ACPI_STATUS(AE_SUPPORT
);
161 * Validate output buffer.
163 if (buffer
->length
< size_required
) {
164 buffer
->length
= size_required
;
165 return_ACPI_STATUS(AE_BUFFER_OVERFLOW
);
166 } else if (buffer
->length
!= size_required
|| !buffer
->pointer
) {
167 return_ACPI_STATUS(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
]);
182 return_ACPI_STATUS(AE_BAD_DATA
);
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 */
247 return_ACPI_STATUS(AE_OK
);
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
};
261 ACPI_FUNCTION_TRACE("acpi_evaluate_integer");
264 return_ACPI_STATUS(AE_BAD_PARAMETER
);
266 element
= kmalloc(sizeof(union acpi_object
), GFP_KERNEL
);
268 return_ACPI_STATUS(AE_NO_MEMORY
);
270 memset(element
, 0, sizeof(union acpi_object
));
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_ACPI_STATUS(status
);
279 if (element
->type
!= ACPI_TYPE_INTEGER
) {
280 acpi_util_eval_error(handle
, pathname
, AE_BAD_DATA
);
281 return_ACPI_STATUS(AE_BAD_DATA
);
284 *data
= element
->integer
.value
;
287 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Return value [%lu]\n", *data
));
289 return_ACPI_STATUS(AE_OK
);
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
};
304 ACPI_FUNCTION_TRACE("acpi_evaluate_string");
307 return_ACPI_STATUS(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
);
312 return_ACPI_STATUS(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
);
321 return_ACPI_STATUS(AE_BAD_DATA
);
324 *data
= kmalloc(element
->string
.length
+ 1, GFP_KERNEL
);
326 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
, "Memory allocation error\n"));
327 return_VALUE(-ENOMEM
);
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 acpi_os_free(buffer
.pointer
);
337 return_ACPI_STATUS(AE_OK
);
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
};
353 ACPI_FUNCTION_TRACE("acpi_evaluate_reference");
356 return_ACPI_STATUS(AE_BAD_PARAMETER
);
359 /* Evaluate object. */
361 status
= acpi_evaluate_object(handle
, pathname
, arguments
, &buffer
);
362 if (ACPI_FAILURE(status
))
365 package
= (union acpi_object
*)buffer
.pointer
;
367 if ((buffer
.length
== 0) || !package
) {
368 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
369 "No return object (len %X ptr %p)\n",
370 (unsigned)buffer
.length
, package
));
371 status
= AE_BAD_DATA
;
372 acpi_util_eval_error(handle
, pathname
, status
);
375 if (package
->type
!= ACPI_TYPE_PACKAGE
) {
376 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
377 "Expecting a [Package], found type %X\n",
379 status
= AE_BAD_DATA
;
380 acpi_util_eval_error(handle
, pathname
, status
);
383 if (!package
->package
.count
) {
384 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
385 "[Package] has zero elements (%p)\n",
387 status
= AE_BAD_DATA
;
388 acpi_util_eval_error(handle
, pathname
, status
);
392 if (package
->package
.count
> ACPI_MAX_HANDLES
) {
393 return_ACPI_STATUS(AE_NO_MEMORY
);
395 list
->count
= package
->package
.count
;
397 /* Extract package data. */
399 for (i
= 0; i
< list
->count
; i
++) {
401 element
= &(package
->package
.elements
[i
]);
403 if (element
->type
!= ACPI_TYPE_ANY
) {
404 status
= AE_BAD_DATA
;
405 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
406 "Expecting a [Reference] package element, found type %X\n",
408 acpi_util_eval_error(handle
, pathname
, status
);
412 /* Get the acpi_handle. */
414 list
->handles
[i
] = element
->reference
.handle
;
415 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Found reference [%p]\n",
420 if (ACPI_FAILURE(status
)) {
422 //kfree(list->handles);
425 acpi_os_free(buffer
.pointer
);
427 return_ACPI_STATUS(status
);
430 EXPORT_SYMBOL(acpi_evaluate_reference
);