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