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
31 #define _COMPONENT ACPI_BUS_MANAGER
32 MODULE_NAME ("bmutils")
36 #define DEBUG_EVAL_ERROR(l,h,p,s) bm_print_eval_error(l,h,p,s)
38 #define DEBUG_EVAL_ERROR(l,h,p,s)
42 /****************************************************************************
44 ****************************************************************************/
46 /****************************************************************************
48 * FUNCTION: bm_print_eval_error
56 ****************************************************************************/
61 ACPI_HANDLE acpi_handle
,
66 ACPI_STRING status_string
= NULL
;
69 buffer
.pointer
= acpi_os_callocate(buffer
.length
);
70 if (!buffer
.pointer
) {
74 status_string
= acpi_cm_format_exception(status
);
76 status
= acpi_get_name(acpi_handle
, ACPI_FULL_PATHNAME
, &buffer
);
77 if (ACPI_FAILURE(status
)) {
78 DEBUG_PRINT(debug_level
, ("Evaluate object [0x%08x], %s\n", acpi_handle
, status_string
));
83 DEBUG_PRINT(ACPI_INFO
, ("Evaluate object [%s.%s], %s\n", buffer
.pointer
, pathname
, status_string
));
86 DEBUG_PRINT(ACPI_INFO
, ("Evaluate object [%s], %s\n", buffer
.pointer
, status_string
));
89 acpi_os_free(buffer
.pointer
);
93 /****************************************************************************
95 * FUNCTION: bm_copy_to_buffer
103 ****************************************************************************/
111 FUNCTION_TRACE("bm_copy_to_buffer");
113 if (!buffer
|| (!buffer
->pointer
) || !data
|| (length
== 0)) {
114 return_ACPI_STATUS(AE_BAD_PARAMETER
);
117 if (length
> buffer
->length
) {
118 buffer
->length
= length
;
119 return_ACPI_STATUS(AE_BUFFER_OVERFLOW
);
122 buffer
->length
= length
;
123 MEMCPY(buffer
->pointer
, data
, length
);
125 return_ACPI_STATUS(AE_OK
);
129 /****************************************************************************
131 * FUNCTION: bm_cast_buffer
139 ****************************************************************************/
147 FUNCTION_TRACE("bm_cast_buffer");
149 if (!buffer
|| !buffer
->pointer
|| !pointer
|| length
== 0) {
150 return_ACPI_STATUS(AE_BAD_PARAMETER
);
153 if (length
> buffer
->length
) {
154 return_ACPI_STATUS(AE_BAD_DATA
);
157 *pointer
= buffer
->pointer
;
159 return_ACPI_STATUS(AE_OK
);
163 /****************************************************************************
165 * FUNCTION: bm_extract_package_data
173 ****************************************************************************/
176 TODO: Don't assume numbers (in ASL) are 32-bit values!!!! (IA64)
177 TODO: Issue with 'assumed' types coming out of interpreter...
182 bm_extract_package_data (
183 ACPI_OBJECT
*package
,
184 ACPI_BUFFER
*package_format
,
187 ACPI_STATUS status
= AE_OK
;
192 ACPI_OBJECT
*element
= NULL
;
193 u32 size_required
= 0;
195 u32 format_count
= 0;
198 FUNCTION_TRACE("bm_extract_package_data");
200 if (!package
|| (package
->type
!= ACPI_TYPE_PACKAGE
) ||
201 (package
->package
.count
== 0) || !package_format
||
202 (package_format
->length
< 1) ||
203 (!package_format
->pointer
) || !buffer
) {
204 return_ACPI_STATUS(AE_BAD_PARAMETER
);
207 format_count
= package_format
->length
- 1;
209 if (format_count
> package
->package
.count
) {
210 DEBUG_PRINT(ACPI_WARN
, ("Format specifies more objects [%d] than exist in package [%d].", format_count
, package
->package
.count
));
211 return_ACPI_STATUS(AE_BAD_DATA
);
214 format
= (char*)package_format
->pointer
;
217 * Calculate size_required.
219 for (i
=0; i
<format_count
; i
++) {
220 element
= &(package
->package
.elements
[i
]);
222 switch (element
->type
) {
224 case ACPI_TYPE_INTEGER
:
227 size_required
+= sizeof(ACPI_INTEGER
);
228 tail_offset
+= sizeof(ACPI_INTEGER
);
231 size_required
+= sizeof(u8
*) +
232 sizeof(ACPI_INTEGER
) + 1;
233 tail_offset
+= sizeof(ACPI_INTEGER
);
236 DEBUG_PRINT(ACPI_WARN
, ("Invalid package element [%d]: got number, expecing [%c].\n", i
, format
[i
]));
237 return_ACPI_STATUS(AE_BAD_DATA
);
242 case ACPI_TYPE_STRING
:
243 case ACPI_TYPE_BUFFER
:
246 size_required
+= sizeof(u8
*) +
247 element
->string
.length
+ 1;
248 tail_offset
+= sizeof(u8
*);
251 size_required
+= sizeof(u8
*) +
252 element
->buffer
.length
;
253 tail_offset
+= sizeof(u8
*);
256 DEBUG_PRINT(ACPI_WARN
, ("Invalid package element [%d] got string/buffer, expecing [%c].\n", i
, format
[i
]));
257 return_ACPI_STATUS(AE_BAD_DATA
);
262 case ACPI_TYPE_PACKAGE
:
264 /* TODO: handle nested packages... */
265 return_ACPI_STATUS(AE_SUPPORT
);
270 if (size_required
> buffer
->length
) {
271 buffer
->length
= size_required
;
272 return_ACPI_STATUS(AE_BUFFER_OVERFLOW
);
275 buffer
->length
= size_required
;
277 if (!buffer
->pointer
) {
278 return_ACPI_STATUS(AE_BAD_PARAMETER
);
281 head
= buffer
->pointer
;
282 tail
= buffer
->pointer
+ tail_offset
;
285 * Extract package data:
287 for (i
=0; i
<format_count
; i
++) {
289 element
= &(package
->package
.elements
[i
]);
291 switch (element
->type
) {
293 case ACPI_TYPE_INTEGER
:
296 *((ACPI_INTEGER
*)head
) =
297 element
->integer
.value
;
298 head
+= sizeof(ACPI_INTEGER
);
301 pointer
= (u8
**)head
;
303 *((ACPI_INTEGER
*)tail
) =
304 element
->integer
.value
;
305 head
+= sizeof(ACPI_INTEGER
*);
306 tail
+= sizeof(ACPI_INTEGER
);
307 /* NULL terminate string */
312 /* Should never get here */
317 case ACPI_TYPE_STRING
:
318 case ACPI_TYPE_BUFFER
:
321 pointer
= (u8
**)head
;
323 memcpy(tail
, element
->string
.pointer
,
324 element
->string
.length
);
326 tail
+= element
->string
.length
;
327 /* NULL terminate string */
332 pointer
= (u8
**)head
;
334 memcpy(tail
, element
->buffer
.pointer
,
335 element
->buffer
.length
);
337 tail
+= element
->buffer
.length
;
340 /* Should never get here */
345 case ACPI_TYPE_PACKAGE
:
346 /* TODO: handle nested packages... */
348 /* Should never get here */
353 return_ACPI_STATUS(status
);
357 /****************************************************************************
359 * FUNCTION: bm_evaluate_object
364 * AE_BUFFER_OVERFLOW Evaluated object returned data, but
365 * caller did not provide buffer.
367 * DESCRIPTION: Helper for acpi_evaluate_object that handles buffer
368 * allocation. Note that the caller is responsible for
369 * freeing buffer->pointer!
371 ****************************************************************************/
375 ACPI_HANDLE acpi_handle
,
376 ACPI_STRING pathname
,
377 ACPI_OBJECT_LIST
*arguments
,
380 ACPI_STATUS status
= AE_OK
;
382 FUNCTION_TRACE("bm_evaluate_object");
384 /* If caller provided a buffer it must be unallocated/zero'd. */
385 if ((buffer
) && (buffer
->length
!= 0 || buffer
->pointer
)) {
386 return_ACPI_STATUS(AE_BAD_PARAMETER
);
392 * The first attempt is just to get the size of the object data
393 * (that is unless there's no return data, e.g. _INI); the second
396 status
= acpi_evaluate_object(acpi_handle
, pathname
, arguments
, buffer
);
397 if (ACPI_SUCCESS(status
)) {
398 return_ACPI_STATUS(status
);
401 else if ((buffer
) && (status
== AE_BUFFER_OVERFLOW
)) {
403 /* Gotta allocate -- CALLER MUST FREE! */
404 buffer
->pointer
= acpi_os_callocate(buffer
->length
);
405 if (!buffer
->pointer
) {
406 return_ACPI_STATUS(AE_NO_MEMORY
);
409 /* Re-evaluate -- this time it should work */
410 status
= acpi_evaluate_object(acpi_handle
, pathname
,
414 if (ACPI_FAILURE(status
)) {
415 DEBUG_EVAL_ERROR(ACPI_WARN
, acpi_handle
, pathname
, status
);
416 if (buffer
&& buffer
->pointer
) {
417 acpi_os_free(buffer
->pointer
);
418 buffer
->pointer
= NULL
;
423 return_ACPI_STATUS(status
);
427 /****************************************************************************
429 * FUNCTION: bm_evaluate_simple_integer
437 ****************************************************************************/
440 bm_evaluate_simple_integer (
441 ACPI_HANDLE acpi_handle
,
442 ACPI_STRING pathname
,
445 ACPI_STATUS status
= AE_OK
;
446 ACPI_OBJECT
*element
= NULL
;
449 FUNCTION_TRACE("bm_evaluate_simple_integer");
452 return_ACPI_STATUS(AE_BAD_PARAMETER
);
455 MEMSET(&buffer
, 0, sizeof(ACPI_BUFFER
));
461 status
= bm_evaluate_object(acpi_handle
, pathname
, NULL
, &buffer
);
462 if (ACPI_FAILURE(status
)) {
470 status
= bm_cast_buffer(&buffer
, (void**)&element
,
471 sizeof(ACPI_OBJECT
));
472 if (ACPI_FAILURE(status
)) {
473 DEBUG_EVAL_ERROR(ACPI_WARN
, acpi_handle
, pathname
, status
);
477 if (element
->type
!= ACPI_TYPE_INTEGER
) {
478 status
= AE_BAD_DATA
;
479 DEBUG_EVAL_ERROR(ACPI_WARN
, acpi_handle
, pathname
, status
);
483 *data
= element
->integer
.value
;
486 acpi_os_free(buffer
.pointer
);
488 return_ACPI_STATUS(status
);
492 /****************************************************************************
494 * FUNCTION: bm_evaluate_reference_list
502 ****************************************************************************/
505 bm_evaluate_reference_list (
506 ACPI_HANDLE acpi_handle
,
507 ACPI_STRING pathname
,
508 BM_HANDLE_LIST
*reference_list
)
510 ACPI_STATUS status
= AE_OK
;
511 ACPI_OBJECT
*package
= NULL
;
512 ACPI_OBJECT
*element
= NULL
;
513 ACPI_HANDLE reference_handle
= NULL
;
517 FUNCTION_TRACE("bm_evaluate_reference_list");
519 if (!reference_list
) {
520 return_ACPI_STATUS(AE_BAD_PARAMETER
);
523 MEMSET(&buffer
, 0, sizeof(ACPI_BUFFER
));
529 status
= bm_evaluate_object(acpi_handle
, pathname
, NULL
, &buffer
);
530 if (ACPI_FAILURE(status
)) {
538 status
= bm_cast_buffer(&buffer
, (void**)&package
,
539 sizeof(ACPI_OBJECT
));
540 if (ACPI_FAILURE(status
)) {
541 DEBUG_EVAL_ERROR(ACPI_WARN
, acpi_handle
, pathname
, status
);
545 if (package
->type
!= ACPI_TYPE_PACKAGE
) {
546 status
= AE_BAD_DATA
;
547 DEBUG_EVAL_ERROR(ACPI_WARN
, acpi_handle
, pathname
, status
);
551 if (package
->package
.count
> BM_HANDLES_MAX
) {
552 package
->package
.count
= BM_HANDLES_MAX
;
556 * Parse Package Data:
557 * -------------------
559 for (i
= 0; i
< package
->package
.count
; i
++) {
561 element
= &(package
->package
.elements
[i
]);
563 if (!element
|| (element
->type
!= ACPI_TYPE_STRING
)) {
564 status
= AE_BAD_DATA
;
565 DEBUG_PRINT(ACPI_WARN
, ("Invalid element in package (not a device reference).\n"));
566 DEBUG_EVAL_ERROR(ACPI_WARN
, acpi_handle
, pathname
, status
);
571 * Resolve reference string (e.g. "\_PR_.CPU_") to an
574 status
= acpi_get_handle(acpi_handle
,
575 element
->string
.pointer
, &reference_handle
);
576 if (ACPI_FAILURE(status
)) {
577 status
= AE_BAD_DATA
;
578 DEBUG_PRINT(ACPI_WARN
, ("Unable to resolve device reference [%s].\n", element
->string
.pointer
));
579 DEBUG_EVAL_ERROR(ACPI_WARN
, acpi_handle
, pathname
, status
);
584 * Resolve ACPI_HANDLE to BM_HANDLE.
586 status
= bm_get_handle(reference_handle
,
587 &(reference_list
->handles
[i
]));
588 if (ACPI_FAILURE(status
)) {
589 status
= AE_BAD_DATA
;
590 DEBUG_PRINT(ACPI_WARN
, ("Unable to resolve device reference for [0x%08x].\n", reference_handle
));
591 DEBUG_EVAL_ERROR(ACPI_WARN
, acpi_handle
, pathname
, status
);
595 DEBUG_PRINT(ACPI_INFO
, ("Resolved reference [%s]->[0x%08x]->[0x%02x]\n", element
->string
.pointer
, reference_handle
, reference_list
->handles
[i
]));
597 (reference_list
->count
)++;
601 acpi_os_free(buffer
.pointer
);
603 return_ACPI_STATUS(status
);