1 /*****************************************************************************
3 * Module Name: bmutils.c
6 *****************************************************************************/
9 * Copyright (C) 2000, 2001 Andrew Grover
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #define _COMPONENT ACPI_BUS_MANAGER
30 MODULE_NAME ("bmutils")
34 #define DEBUG_EVAL_ERROR(l,h,p,s) bm_print_eval_error(l,h,p,s)
36 #define DEBUG_EVAL_ERROR(l,h,p,s)
40 /****************************************************************************
42 ****************************************************************************/
44 /****************************************************************************
46 * FUNCTION: bm_print_eval_error
54 ****************************************************************************/
59 ACPI_HANDLE acpi_handle
,
64 ACPI_STRING status_string
= NULL
;
67 buffer
.pointer
= acpi_os_callocate(buffer
.length
);
68 if (!buffer
.pointer
) {
72 status_string
= acpi_cm_format_exception(status
);
74 status
= acpi_get_name(acpi_handle
, ACPI_FULL_PATHNAME
, &buffer
);
75 if (ACPI_FAILURE(status
)) {
76 DEBUG_PRINT(debug_level
, ("Evaluate object [0x%08x], %s\n", acpi_handle
, status_string
));
81 DEBUG_PRINT(ACPI_INFO
, ("Evaluate object [%s.%s], %s\n", buffer
.pointer
, pathname
, status_string
));
84 DEBUG_PRINT(ACPI_INFO
, ("Evaluate object [%s], %s\n", buffer
.pointer
, status_string
));
87 acpi_os_free(buffer
.pointer
);
91 /****************************************************************************
93 * FUNCTION: bm_copy_to_buffer
101 ****************************************************************************/
109 FUNCTION_TRACE("bm_copy_to_buffer");
111 if (!buffer
|| (!buffer
->pointer
) || !data
|| (length
== 0)) {
112 return_ACPI_STATUS(AE_BAD_PARAMETER
);
115 if (length
> buffer
->length
) {
116 buffer
->length
= length
;
117 return_ACPI_STATUS(AE_BUFFER_OVERFLOW
);
120 buffer
->length
= length
;
121 MEMCPY(buffer
->pointer
, data
, length
);
123 return_ACPI_STATUS(AE_OK
);
127 /****************************************************************************
129 * FUNCTION: bm_cast_buffer
137 ****************************************************************************/
145 FUNCTION_TRACE("bm_cast_buffer");
147 if (!buffer
|| !buffer
->pointer
|| !pointer
|| length
== 0) {
148 return_ACPI_STATUS(AE_BAD_PARAMETER
);
151 if (length
> buffer
->length
) {
152 return_ACPI_STATUS(AE_BAD_DATA
);
155 *pointer
= buffer
->pointer
;
157 return_ACPI_STATUS(AE_OK
);
161 /****************************************************************************
163 * FUNCTION: bm_extract_package_data
171 ****************************************************************************/
174 TODO: Don't assume numbers (in ASL) are 32-bit values!!!! (IA64)
175 TODO: Issue with 'assumed' types coming out of interpreter...
180 bm_extract_package_data (
181 ACPI_OBJECT
*package
,
182 ACPI_BUFFER
*package_format
,
185 ACPI_STATUS status
= AE_OK
;
190 ACPI_OBJECT
*element
= NULL
;
191 u32 size_required
= 0;
193 u32 format_count
= 0;
196 FUNCTION_TRACE("bm_extract_package_data");
198 if (!package
|| (package
->type
!= ACPI_TYPE_PACKAGE
) ||
199 (package
->package
.count
== 0) || !package_format
||
200 (package_format
->length
< 1) ||
201 (!package_format
->pointer
) || !buffer
) {
202 return_ACPI_STATUS(AE_BAD_PARAMETER
);
205 format_count
= package_format
->length
- 1;
207 if (format_count
> package
->package
.count
) {
208 DEBUG_PRINT(ACPI_WARN
, ("Format specifies more objects [%d] than exist in package [%d].", format_count
, package
->package
.count
));
209 return_ACPI_STATUS(AE_BAD_DATA
);
212 format
= (char*)package_format
->pointer
;
215 * Calculate size_required.
217 for (i
=0; i
<format_count
; i
++) {
218 element
= &(package
->package
.elements
[i
]);
220 switch (element
->type
) {
222 case ACPI_TYPE_INTEGER
:
225 size_required
+= sizeof(ACPI_INTEGER
);
226 tail_offset
+= sizeof(ACPI_INTEGER
);
229 size_required
+= sizeof(u8
*) +
230 sizeof(ACPI_INTEGER
) + 1;
231 tail_offset
+= sizeof(ACPI_INTEGER
);
234 DEBUG_PRINT(ACPI_WARN
, ("Invalid package element [%d]: got number, expecing [%c].\n", i
, format
[i
]));
235 return_ACPI_STATUS(AE_BAD_DATA
);
240 case ACPI_TYPE_STRING
:
241 case ACPI_TYPE_BUFFER
:
244 size_required
+= sizeof(u8
*) +
245 element
->string
.length
+ 1;
246 tail_offset
+= sizeof(u8
*);
249 size_required
+= sizeof(u8
*) +
250 element
->buffer
.length
;
251 tail_offset
+= sizeof(u8
*);
254 DEBUG_PRINT(ACPI_WARN
, ("Invalid package element [%d] got string/buffer, expecing [%c].\n", i
, format
[i
]));
255 return_ACPI_STATUS(AE_BAD_DATA
);
260 case ACPI_TYPE_PACKAGE
:
262 /* TODO: handle nested packages... */
263 return_ACPI_STATUS(AE_SUPPORT
);
268 if (size_required
> buffer
->length
) {
269 buffer
->length
= size_required
;
270 return_ACPI_STATUS(AE_BUFFER_OVERFLOW
);
273 buffer
->length
= size_required
;
275 if (!buffer
->pointer
) {
276 return_ACPI_STATUS(AE_BAD_PARAMETER
);
279 head
= buffer
->pointer
;
280 tail
= head
+ tail_offset
;
283 * Extract package data:
285 for (i
=0; i
<format_count
; i
++) {
287 element
= &(package
->package
.elements
[i
]);
289 switch (element
->type
) {
291 case ACPI_TYPE_INTEGER
:
294 *((ACPI_INTEGER
*)head
) =
295 element
->integer
.value
;
296 head
+= sizeof(ACPI_INTEGER
);
299 pointer
= (u8
**)head
;
301 *((ACPI_INTEGER
*)tail
) =
302 element
->integer
.value
;
303 head
+= sizeof(ACPI_INTEGER
*);
304 tail
+= sizeof(ACPI_INTEGER
);
305 /* NULL terminate string */
310 /* Should never get here */
315 case ACPI_TYPE_STRING
:
316 case ACPI_TYPE_BUFFER
:
319 pointer
= (u8
**)head
;
321 memcpy(tail
, element
->string
.pointer
,
322 element
->string
.length
);
324 tail
+= element
->string
.length
;
325 /* NULL terminate string */
330 pointer
= (u8
**)head
;
332 memcpy(tail
, element
->buffer
.pointer
,
333 element
->buffer
.length
);
335 tail
+= element
->buffer
.length
;
338 /* Should never get here */
343 case ACPI_TYPE_PACKAGE
:
344 /* TODO: handle nested packages... */
346 /* Should never get here */
351 return_ACPI_STATUS(status
);
355 /****************************************************************************
357 * FUNCTION: bm_evaluate_object
362 * AE_BUFFER_OVERFLOW Evaluated object returned data, but
363 * caller did not provide buffer.
365 * DESCRIPTION: Helper for acpi_evaluate_object that handles buffer
366 * allocation. Note that the caller is responsible for
367 * freeing buffer->pointer!
369 ****************************************************************************/
373 ACPI_HANDLE acpi_handle
,
374 ACPI_STRING pathname
,
375 ACPI_OBJECT_LIST
*arguments
,
378 ACPI_STATUS status
= AE_OK
;
380 FUNCTION_TRACE("bm_evaluate_object");
382 /* If caller provided a buffer it must be unallocated/zero'd. */
383 if ((buffer
) && (buffer
->length
!= 0 || buffer
->pointer
)) {
384 return_ACPI_STATUS(AE_BAD_PARAMETER
);
390 * The first attempt is just to get the size of the object data
391 * (that is unless there's no return data, e.g. _INI); the second
394 status
= acpi_evaluate_object(acpi_handle
, pathname
, arguments
, buffer
);
395 if (ACPI_SUCCESS(status
)) {
396 return_ACPI_STATUS(status
);
399 else if ((buffer
) && (status
== AE_BUFFER_OVERFLOW
)) {
401 /* Gotta allocate -- CALLER MUST FREE! */
402 buffer
->pointer
= acpi_os_callocate(buffer
->length
);
403 if (!buffer
->pointer
) {
404 return_ACPI_STATUS(AE_NO_MEMORY
);
407 /* Re-evaluate -- this time it should work */
408 status
= acpi_evaluate_object(acpi_handle
, pathname
,
412 if (ACPI_FAILURE(status
)) {
413 DEBUG_EVAL_ERROR(ACPI_WARN
, acpi_handle
, pathname
, status
);
414 if (buffer
&& buffer
->pointer
) {
415 acpi_os_free(buffer
->pointer
);
416 buffer
->pointer
= NULL
;
421 return_ACPI_STATUS(status
);
425 /****************************************************************************
427 * FUNCTION: bm_evaluate_simple_integer
435 ****************************************************************************/
438 bm_evaluate_simple_integer (
439 ACPI_HANDLE acpi_handle
,
440 ACPI_STRING pathname
,
443 ACPI_STATUS status
= AE_OK
;
444 ACPI_OBJECT
*element
= NULL
;
447 FUNCTION_TRACE("bm_evaluate_simple_integer");
450 return_ACPI_STATUS(AE_BAD_PARAMETER
);
453 MEMSET(&buffer
, 0, sizeof(ACPI_BUFFER
));
459 status
= bm_evaluate_object(acpi_handle
, pathname
, NULL
, &buffer
);
460 if (ACPI_FAILURE(status
)) {
468 status
= bm_cast_buffer(&buffer
, (void**)&element
,
469 sizeof(ACPI_OBJECT
));
470 if (ACPI_FAILURE(status
)) {
471 DEBUG_EVAL_ERROR(ACPI_WARN
, acpi_handle
, pathname
, status
);
475 if (element
->type
!= ACPI_TYPE_INTEGER
) {
476 status
= AE_BAD_DATA
;
477 DEBUG_EVAL_ERROR(ACPI_WARN
, acpi_handle
, pathname
, status
);
481 *data
= element
->integer
.value
;
484 acpi_os_free(buffer
.pointer
);
486 return_ACPI_STATUS(status
);
490 /****************************************************************************
492 * FUNCTION: bm_evaluate_reference_list
500 ****************************************************************************/
503 bm_evaluate_reference_list (
504 ACPI_HANDLE acpi_handle
,
505 ACPI_STRING pathname
,
506 BM_HANDLE_LIST
*reference_list
)
508 ACPI_STATUS status
= AE_OK
;
509 ACPI_OBJECT
*package
= NULL
;
510 ACPI_OBJECT
*element
= NULL
;
511 ACPI_HANDLE reference_handle
= NULL
;
515 FUNCTION_TRACE("bm_evaluate_reference_list");
517 if (!reference_list
) {
518 return_ACPI_STATUS(AE_BAD_PARAMETER
);
521 MEMSET(&buffer
, 0, sizeof(ACPI_BUFFER
));
527 status
= bm_evaluate_object(acpi_handle
, pathname
, NULL
, &buffer
);
528 if (ACPI_FAILURE(status
)) {
536 status
= bm_cast_buffer(&buffer
, (void**)&package
,
537 sizeof(ACPI_OBJECT
));
538 if (ACPI_FAILURE(status
)) {
539 DEBUG_EVAL_ERROR(ACPI_WARN
, acpi_handle
, pathname
, status
);
543 if (package
->type
!= ACPI_TYPE_PACKAGE
) {
544 status
= AE_BAD_DATA
;
545 DEBUG_EVAL_ERROR(ACPI_WARN
, acpi_handle
, pathname
, status
);
549 if (package
->package
.count
> BM_HANDLES_MAX
) {
550 package
->package
.count
= BM_HANDLES_MAX
;
554 * Parse Package Data:
555 * -------------------
557 for (i
= 0; i
< package
->package
.count
; i
++) {
559 element
= &(package
->package
.elements
[i
]);
561 if (!element
|| (element
->type
!= ACPI_TYPE_STRING
)) {
562 status
= AE_BAD_DATA
;
563 DEBUG_PRINT(ACPI_WARN
, ("Invalid element in package (not a device reference).\n"));
564 DEBUG_EVAL_ERROR(ACPI_WARN
, acpi_handle
, pathname
, status
);
569 * Resolve reference string (e.g. "\_PR_.CPU_") to an
572 status
= acpi_get_handle(acpi_handle
,
573 element
->string
.pointer
, &reference_handle
);
574 if (ACPI_FAILURE(status
)) {
575 status
= AE_BAD_DATA
;
576 DEBUG_PRINT(ACPI_WARN
, ("Unable to resolve device reference [%s].\n", element
->string
.pointer
));
577 DEBUG_EVAL_ERROR(ACPI_WARN
, acpi_handle
, pathname
, status
);
582 * Resolve ACPI_HANDLE to BM_HANDLE.
584 status
= bm_get_handle(reference_handle
,
585 &(reference_list
->handles
[i
]));
586 if (ACPI_FAILURE(status
)) {
587 status
= AE_BAD_DATA
;
588 DEBUG_PRINT(ACPI_WARN
, ("Unable to resolve device reference for [0x%08x].\n", reference_handle
));
589 DEBUG_EVAL_ERROR(ACPI_WARN
, acpi_handle
, pathname
, status
);
593 DEBUG_PRINT(ACPI_INFO
, ("Resolved reference [%s]->[0x%08x]->[0x%02x]\n", element
->string
.pointer
, reference_handle
, reference_list
->handles
[i
]));
595 (reference_list
->count
)++;
599 acpi_os_free(buffer
.pointer
);
601 return_ACPI_STATUS(status
);