File: /usr/src/linux/drivers/acpi/ospm/busmgr/bmutils.c
1 /*****************************************************************************
2 *
3 * Module Name: bmutils.c
4 * $Revision: 38 $
5 *
6 *****************************************************************************/
7
8 /*
9 * Copyright (C) 2000, 2001 Andrew Grover
10 *
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.
15 *
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.
20 *
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
24 */
25
26
27 #include <acpi.h>
28 #include "bm.h"
29
30
31 #define _COMPONENT ACPI_BUS
32 MODULE_NAME ("bmutils")
33
34
35 #ifdef ACPI_DEBUG
36 #define DEBUG_EVAL_ERROR(l,h,p,s) bm_print_eval_error(l,h,p,s)
37 #else
38 #define DEBUG_EVAL_ERROR(l,h,p,s)
39 #endif
40
41
42 /****************************************************************************
43 * External Functions
44 ****************************************************************************/
45
46 /****************************************************************************
47 *
48 * FUNCTION: bm_print_eval_error
49 *
50 * PARAMETERS:
51 *
52 * RETURN:
53 *
54 * DESCRIPTION:
55 *
56 ****************************************************************************/
57
58 void
59 bm_print_eval_error (
60 u32 debug_level,
61 acpi_handle handle,
62 acpi_string pathname,
63 acpi_status status)
64 {
65 acpi_buffer buffer;
66 acpi_status local_status;
67
68 PROC_NAME("bm_print_eval_error");
69
70 buffer.length = 256;
71 buffer.pointer = acpi_os_callocate(buffer.length);
72 if (!buffer.pointer) {
73 return;
74 }
75
76 local_status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
77 if (ACPI_FAILURE(local_status)) {
78 ACPI_DEBUG_PRINT((ACPI_DEBUG_LEVEL(debug_level), "Evaluate object [%p], %s\n", handle,
79 acpi_format_exception(status)));
80 return;
81 }
82
83 if (pathname) {
84 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Evaluate object [%s.%s], %s\n", buffer.pointer, pathname,
85 acpi_format_exception(status)));
86 }
87 else {
88 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Evaluate object [%s], %s\n", buffer.pointer,
89 acpi_format_exception(status)));
90 }
91
92 acpi_os_free(buffer.pointer);
93 }
94
95
96 /****************************************************************************
97 *
98 * FUNCTION: bm_copy_to_buffer
99 *
100 * PARAMETERS:
101 *
102 * RETURN:
103 *
104 * DESCRIPTION:
105 *
106 ****************************************************************************/
107
108 acpi_status
109 bm_copy_to_buffer (
110 acpi_buffer *buffer,
111 void *data,
112 u32 length)
113 {
114 FUNCTION_TRACE("bm_copy_to_buffer");
115
116 if (!buffer || (!buffer->pointer) || !data || (length == 0)) {
117 return_ACPI_STATUS(AE_BAD_PARAMETER);
118 }
119
120 if (length > buffer->length) {
121 buffer->length = length;
122 return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
123 }
124
125 buffer->length = length;
126 MEMCPY(buffer->pointer, data, length);
127
128 return_ACPI_STATUS(AE_OK);
129 }
130
131
132 /****************************************************************************
133 *
134 * FUNCTION: bm_cast_buffer
135 *
136 * PARAMETERS:
137 *
138 * RETURN:
139 *
140 * DESCRIPTION:
141 *
142 ****************************************************************************/
143
144 acpi_status
145 bm_cast_buffer (
146 acpi_buffer *buffer,
147 void **pointer,
148 u32 length)
149 {
150 FUNCTION_TRACE("bm_cast_buffer");
151
152 if (!buffer || !buffer->pointer || !pointer || length == 0) {
153 return_ACPI_STATUS(AE_BAD_PARAMETER);
154 }
155
156 if (length > buffer->length) {
157 return_ACPI_STATUS(AE_BAD_DATA);
158 }
159
160 *pointer = buffer->pointer;
161
162 return_ACPI_STATUS(AE_OK);
163 }
164
165
166 /****************************************************************************
167 *
168 * FUNCTION: bm_extract_package_data
169 *
170 * PARAMETERS:
171 *
172 * RETURN:
173 *
174 * DESCRIPTION:
175 *
176 ****************************************************************************/
177
178 /*
179 * TBD: Don't assume numbers (in ASL) are 32-bit values!!!! (IA64)
180 * TBD: Issue with 'assumed' types coming out of interpreter...
181 * (e.g. toshiba _BIF)
182 */
183
184 acpi_status
185 bm_extract_package_data (
186 acpi_object *package,
187 acpi_buffer *package_format,
188 acpi_buffer *buffer)
189 {
190 acpi_status status = AE_OK;
191 u8 *head = NULL;
192 u8 *tail = NULL;
193 u8 **pointer = NULL;
194 u32 tail_offset = 0;
195 acpi_object *element = NULL;
196 u32 size_required = 0;
197 char* format = NULL;
198 u32 format_count = 0;
199 u32 i = 0;
200
201 FUNCTION_TRACE("bm_extract_package_data");
202
203 if (!package || (package->type != ACPI_TYPE_PACKAGE) ||
204 (package->package.count == 0) || !package_format ||
205 (package_format->length < 1) ||
206 (!package_format->pointer) || !buffer) {
207 return_ACPI_STATUS(AE_BAD_PARAMETER);
208 }
209
210 format_count = package_format->length - 1;
211
212 if (format_count > package->package.count) {
213 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Format specifies more objects [%d] than exist in package [%d].", format_count, package->package.count));
214 return_ACPI_STATUS(AE_BAD_DATA);
215 }
216
217 format = (char*)package_format->pointer;
218
219 /*
220 * Calculate size_required.
221 */
222 for (i=0; i<format_count; i++) {
223 element = &(package->package.elements[i]);
224
225 switch (element->type) {
226
227 case ACPI_TYPE_INTEGER:
228 switch (format[i]) {
229 case 'N':
230 size_required += sizeof(acpi_integer);
231 tail_offset += sizeof(acpi_integer);
232 break;
233 case 'S':
234 size_required += sizeof(u8*) +
235 sizeof(acpi_integer) + 1;
236 tail_offset += sizeof(acpi_integer);
237 break;
238 default:
239 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Invalid package element [%d]: got number, expecing [%c].\n", i, format[i]));
240 return_ACPI_STATUS(AE_BAD_DATA);
241 break;
242 }
243 break;
244
245 case ACPI_TYPE_STRING:
246 case ACPI_TYPE_BUFFER:
247 switch (format[i]) {
248 case 'S':
249 size_required += sizeof(u8*) +
250 element->string.length + 1;
251 tail_offset += sizeof(u8*);
252 break;
253 case 'B':
254 size_required += sizeof(u8*) +
255 element->buffer.length;
256 tail_offset += sizeof(u8*);
257 break;
258 default:
259 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Invalid package element [%d] got string/buffer, expecing [%c].\n", i, format[i]));
260 return_ACPI_STATUS(AE_BAD_DATA);
261 break;
262 }
263 break;
264
265 case ACPI_TYPE_PACKAGE:
266 default:
267 /* TBD: handle nested packages... */
268 return_ACPI_STATUS(AE_SUPPORT);
269 break;
270 }
271 }
272
273 if (size_required > buffer->length) {
274 buffer->length = size_required;
275 return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
276 }
277
278 buffer->length = size_required;
279
280 if (!buffer->pointer) {
281 return_ACPI_STATUS(AE_BAD_PARAMETER);
282 }
283
284 head = buffer->pointer;
285 tail = buffer->pointer + tail_offset;
286
287 /*
288 * Extract package data:
289 */
290 for (i=0; i<format_count; i++) {
291
292 element = &(package->package.elements[i]);
293
294 switch (element->type) {
295
296 case ACPI_TYPE_INTEGER:
297 switch (format[i]) {
298 case 'N':
299 *((acpi_integer*)head) =
300 element->integer.value;
301 head += sizeof(acpi_integer);
302 break;
303 case 'S':
304 pointer = (u8**)head;
305 *pointer = tail;
306 *((acpi_integer*)tail) =
307 element->integer.value;
308 head += sizeof(acpi_integer*);
309 tail += sizeof(acpi_integer);
310 /* NULL terminate string */
311 *tail = 0;
312 tail++;
313 break;
314 default:
315 /* Should never get here */
316 break;
317 }
318 break;
319
320 case ACPI_TYPE_STRING:
321 case ACPI_TYPE_BUFFER:
322 switch (format[i]) {
323 case 'S':
324 pointer = (u8**)head;
325 *pointer = tail;
326 memcpy(tail, element->string.pointer,
327 element->string.length);
328 head += sizeof(u8*);
329 tail += element->string.length;
330 /* NULL terminate string */
331 *tail = 0;
332 tail++;
333 break;
334 case 'B':
335 pointer = (u8**)head;
336 *pointer = tail;
337 memcpy(tail, element->buffer.pointer,
338 element->buffer.length);
339 head += sizeof(u8*);
340 tail += element->buffer.length;
341 break;
342 default:
343 /* Should never get here */
344 break;
345 }
346 break;
347
348 case ACPI_TYPE_PACKAGE:
349 /* TBD: handle nested packages... */
350 default:
351 /* Should never get here */
352 break;
353 }
354 }
355
356 return_ACPI_STATUS(status);
357 }
358
359
360 /****************************************************************************
361 *
362 * FUNCTION: bm_evaluate_object
363 *
364 * PARAMETERS:
365 *
366 * RETURN: AE_OK
367 * AE_BUFFER_OVERFLOW Evaluated object returned data, but
368 * caller did not provide buffer.
369 *
370 * DESCRIPTION: Helper for acpi_evaluate_object that handles buffer
371 * allocation. Note that the caller is responsible for
372 * freeing buffer->pointer!
373 *
374 ****************************************************************************/
375
376 acpi_status
377 bm_evaluate_object (
378 acpi_handle handle,
379 acpi_string pathname,
380 acpi_object_list *arguments,
381 acpi_buffer *buffer)
382 {
383 acpi_status status = AE_OK;
384
385 FUNCTION_TRACE("bm_evaluate_object");
386
387 /* If caller provided a buffer it must be unallocated/zero'd. */
388 if ((buffer) && (buffer->length != 0 || buffer->pointer)) {
389 return_ACPI_STATUS(AE_BAD_PARAMETER);
390 }
391
392 /*
393 * Evalute Object:
394 * ---------------
395 * The first attempt is just to get the size of the object data
396 * (that is unless there's no return data, e.g. _INI); the second
397 * gets the data.
398 */
399 status = acpi_evaluate_object(handle, pathname, arguments, buffer);
400 if (ACPI_SUCCESS(status)) {
401 return_ACPI_STATUS(status);
402 }
403 else if ((buffer) && (status == AE_BUFFER_OVERFLOW)) {
404
405 /* Gotta allocate -- CALLER MUST FREE! */
406 buffer->pointer = acpi_os_callocate(buffer->length);
407 if (!buffer->pointer) {
408 return_ACPI_STATUS(AE_NO_MEMORY);
409 }
410
411 /* Re-evaluate -- this time it should work */
412 status = acpi_evaluate_object(handle, pathname,
413 arguments, buffer);
414 }
415
416 if (ACPI_FAILURE(status)) {
417 if (status != AE_NOT_FOUND) {
418 DEBUG_EVAL_ERROR(ACPI_LV_WARN, handle, pathname,
419 status);
420 }
421 if (buffer && buffer->pointer) {
422 acpi_os_free(buffer->pointer);
423 buffer->pointer = NULL;
424 buffer->length = 0;
425 }
426 }
427
428 return_ACPI_STATUS(status);
429 }
430
431
432 /****************************************************************************
433 *
434 * FUNCTION: bm_evaluate_simple_integer
435 *
436 * PARAMETERS:
437 *
438 * RETURN:
439 *
440 * DESCRIPTION:
441 *
442 ****************************************************************************/
443
444 acpi_status
445 bm_evaluate_simple_integer (
446 acpi_handle handle,
447 acpi_string pathname,
448 u32 *data)
449 {
450 acpi_status status = AE_OK;
451 acpi_object *element = NULL;
452 acpi_buffer buffer;
453
454 FUNCTION_TRACE("bm_evaluate_simple_integer");
455
456 if (!data) {
457 return_ACPI_STATUS(AE_BAD_PARAMETER);
458 }
459
460 MEMSET(&buffer, 0, sizeof(acpi_buffer));
461
462 /*
463 * Evaluate Object:
464 * ----------------
465 */
466 status = bm_evaluate_object(handle, pathname, NULL, &buffer);
467 if (ACPI_FAILURE(status)) {
468 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "failed to evaluate object (%s)\n",
469 acpi_format_exception(status)));
470 goto end;
471 }
472
473 /*
474 * Validate Data:
475 * --------------
476 */
477 status = bm_cast_buffer(&buffer, (void**)&element,
478 sizeof(acpi_object));
479 if (ACPI_FAILURE(status)) {
480 DEBUG_EVAL_ERROR(ACPI_LV_WARN, handle, pathname, status);
481 goto end;
482 }
483
484 if (element->type != ACPI_TYPE_INTEGER) {
485 status = AE_BAD_DATA;
486 DEBUG_EVAL_ERROR(ACPI_LV_WARN, handle, pathname, status);
487 goto end;
488 }
489
490 *data = element->integer.value;
491
492 end:
493 acpi_os_free(buffer.pointer);
494
495 return_ACPI_STATUS(status);
496 }
497
498
499 /****************************************************************************
500 *
501 * FUNCTION: bm_evaluate_reference_list
502 *
503 * PARAMETERS:
504 *
505 * RETURN:
506 *
507 * DESCRIPTION:
508 *
509 ****************************************************************************/
510
511 acpi_status
512 bm_evaluate_reference_list (
513 acpi_handle handle,
514 acpi_string pathname,
515 BM_HANDLE_LIST *reference_list)
516 {
517 acpi_status status = AE_OK;
518 acpi_object *package = NULL;
519 acpi_object *element = NULL;
520 acpi_handle reference_handle = NULL;
521 acpi_buffer buffer;
522 u32 i = 0;
523
524 FUNCTION_TRACE("bm_evaluate_reference_list");
525
526 if (!reference_list) {
527 return_ACPI_STATUS(AE_BAD_PARAMETER);
528 }
529
530 MEMSET(&buffer, 0, sizeof(acpi_buffer));
531
532 /*
533 * Evaluate Object:
534 * ----------------
535 */
536 status = bm_evaluate_object(handle, pathname, NULL, &buffer);
537 if (ACPI_FAILURE(status)) {
538 goto end;
539 }
540
541 /*
542 * Validate Package:
543 * -----------------
544 */
545 status = bm_cast_buffer(&buffer, (void**)&package,
546 sizeof(acpi_object));
547 if (ACPI_FAILURE(status)) {
548 DEBUG_EVAL_ERROR(ACPI_LV_WARN, handle, pathname, status);
549 goto end;
550 }
551
552 if (package->type != ACPI_TYPE_PACKAGE) {
553 status = AE_BAD_DATA;
554 DEBUG_EVAL_ERROR(ACPI_LV_WARN, handle, pathname, status);
555 goto end;
556 }
557
558 if (package->package.count > BM_HANDLES_MAX) {
559 package->package.count = BM_HANDLES_MAX;
560 }
561
562 /*
563 * Parse Package Data:
564 * -------------------
565 */
566 for (i = 0; i < package->package.count; i++) {
567
568 element = &(package->package.elements[i]);
569
570 if (!element || (element->type != ACPI_TYPE_STRING)) {
571 status = AE_BAD_DATA;
572 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Invalid element in package (not a device reference).\n"));
573 DEBUG_EVAL_ERROR (ACPI_LV_WARN, handle, pathname, status);
574 break;
575 }
576
577 /*
578 * Resolve reference string (e.g. "\_PR_.CPU_") to an
579 * acpi_handle.
580 */
581 status = acpi_get_handle(handle,
582 element->string.pointer, &reference_handle);
583 if (ACPI_FAILURE(status)) {
584 status = AE_BAD_DATA;
585 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to resolve device reference [%s].\n", element->string.pointer));
586 DEBUG_EVAL_ERROR (ACPI_LV_WARN, handle, pathname, status);
587 break;
588 }
589
590 /*
591 * Resolve acpi_handle to BM_HANDLE.
592 */
593 status = bm_get_handle(reference_handle,
594 &(reference_list->handles[i]));
595 if (ACPI_FAILURE(status)) {
596 status = AE_BAD_DATA;
597 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to resolve device reference for [%p].\n", reference_handle));
598 DEBUG_EVAL_ERROR (ACPI_LV_WARN, handle, pathname, status);
599 break;
600 }
601
602 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Resolved reference [%s]->[%p]->[%02x]\n", element->string.pointer, reference_handle, reference_list->handles[i]));
603
604 (reference_list->count)++;
605 }
606
607 end:
608 acpi_os_free(buffer.pointer);
609
610 return_ACPI_STATUS(status);
611 }
612
613
614