]>
git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - drivers/acpi/utils.c
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_WARNING((AE_INFO
, "Invalid package argument"));
66 return_ACPI_STATUS(AE_BAD_PARAMETER
);
69 if (!format
|| !format
->pointer
|| (format
->length
< 1)) {
70 ACPI_WARNING((AE_INFO
, "Invalid format argument"));
71 return_ACPI_STATUS(AE_BAD_PARAMETER
);
75 ACPI_WARNING((AE_INFO
, "Invalid buffer argument"));
76 return_ACPI_STATUS(AE_BAD_PARAMETER
);
79 format_count
= (format
->length
/ sizeof(char)) - 1;
80 if (format_count
> package
->package
.count
) {
81 ACPI_WARNING((AE_INFO
, "Format specifies more objects [%d]"
82 " than exist in package [%d].",
83 format_count
, package
->package
.count
));
84 return_ACPI_STATUS(AE_BAD_DATA
);
87 format_string
= (char *)format
->pointer
;
90 * Calculate size_required.
92 for (i
= 0; i
< format_count
; i
++) {
94 union acpi_object
*element
= &(package
->package
.elements
[i
]);
97 return_ACPI_STATUS(AE_BAD_DATA
);
100 switch (element
->type
) {
102 case ACPI_TYPE_INTEGER
:
103 switch (format_string
[i
]) {
105 size_required
+= sizeof(acpi_integer
);
106 tail_offset
+= sizeof(acpi_integer
);
110 sizeof(char *) + sizeof(acpi_integer
) +
112 tail_offset
+= sizeof(char *);
115 ACPI_WARNING((AE_INFO
, "Invalid package element"
116 " [%d]: got number, expecing"
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_WARNING((AE_INFO
, "Invalid package element"
142 " [%d] got string/buffer,"
144 i
, format_string
[i
]));
145 return_ACPI_STATUS(AE_BAD_DATA
);
150 case ACPI_TYPE_PACKAGE
:
152 ACPI_DEBUG_PRINT((ACPI_DB_INFO
,
153 "Found unsupported element at index=%d\n",
155 /* TBD: handle nested packages... */
156 return_ACPI_STATUS(AE_SUPPORT
);
162 * Validate output buffer.
164 if (buffer
->length
< size_required
) {
165 buffer
->length
= size_required
;
166 return_ACPI_STATUS(AE_BUFFER_OVERFLOW
);
167 } else if (buffer
->length
!= size_required
|| !buffer
->pointer
) {
168 return_ACPI_STATUS(AE_BAD_PARAMETER
);
171 head
= buffer
->pointer
;
172 tail
= buffer
->pointer
+ tail_offset
;
175 * Extract package data.
177 for (i
= 0; i
< format_count
; i
++) {
180 union acpi_object
*element
= &(package
->package
.elements
[i
]);
183 return_ACPI_STATUS(AE_BAD_DATA
);
186 switch (element
->type
) {
188 case ACPI_TYPE_INTEGER
:
189 switch (format_string
[i
]) {
191 *((acpi_integer
*) head
) =
192 element
->integer
.value
;
193 head
+= sizeof(acpi_integer
);
196 pointer
= (u8
**) head
;
198 *((acpi_integer
*) tail
) =
199 element
->integer
.value
;
200 head
+= sizeof(acpi_integer
*);
201 tail
+= sizeof(acpi_integer
);
202 /* NULL terminate string */
204 tail
+= sizeof(char);
207 /* Should never get here */
212 case ACPI_TYPE_STRING
:
213 case ACPI_TYPE_BUFFER
:
214 switch (format_string
[i
]) {
216 pointer
= (u8
**) head
;
218 memcpy(tail
, element
->string
.pointer
,
219 element
->string
.length
);
220 head
+= sizeof(char *);
221 tail
+= element
->string
.length
* sizeof(char);
222 /* NULL terminate string */
224 tail
+= sizeof(char);
227 pointer
= (u8
**) head
;
229 memcpy(tail
, element
->buffer
.pointer
,
230 element
->buffer
.length
);
231 head
+= sizeof(u8
*);
232 tail
+= element
->buffer
.length
* sizeof(u8
);
235 /* Should never get here */
240 case ACPI_TYPE_PACKAGE
:
241 /* TBD: handle nested packages... */
243 /* Should never get here */
248 return_ACPI_STATUS(AE_OK
);
251 EXPORT_SYMBOL(acpi_extract_package
);
254 acpi_evaluate_integer(acpi_handle handle
,
255 acpi_string pathname
,
256 struct acpi_object_list
*arguments
, unsigned long *data
)
258 acpi_status status
= AE_OK
;
259 union acpi_object
*element
;
260 struct acpi_buffer buffer
= { 0, NULL
};
262 ACPI_FUNCTION_TRACE("acpi_evaluate_integer");
265 return_ACPI_STATUS(AE_BAD_PARAMETER
);
267 element
= kmalloc(sizeof(union acpi_object
), GFP_KERNEL
);
269 return_ACPI_STATUS(AE_NO_MEMORY
);
271 memset(element
, 0, sizeof(union acpi_object
));
272 buffer
.length
= sizeof(union acpi_object
);
273 buffer
.pointer
= element
;
274 status
= acpi_evaluate_object(handle
, pathname
, arguments
, &buffer
);
275 if (ACPI_FAILURE(status
)) {
276 acpi_util_eval_error(handle
, pathname
, status
);
278 return_ACPI_STATUS(status
);
281 if (element
->type
!= ACPI_TYPE_INTEGER
) {
282 acpi_util_eval_error(handle
, pathname
, AE_BAD_DATA
);
284 return_ACPI_STATUS(AE_BAD_DATA
);
287 *data
= element
->integer
.value
;
290 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Return value [%lu]\n", *data
));
292 return_ACPI_STATUS(AE_OK
);
295 EXPORT_SYMBOL(acpi_evaluate_integer
);
299 acpi_evaluate_string(acpi_handle handle
,
300 acpi_string pathname
,
301 acpi_object_list
* arguments
, acpi_string
* data
)
303 acpi_status status
= AE_OK
;
304 acpi_object
*element
= NULL
;
305 acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
307 ACPI_FUNCTION_TRACE("acpi_evaluate_string");
310 return_ACPI_STATUS(AE_BAD_PARAMETER
);
312 status
= acpi_evaluate_object(handle
, pathname
, arguments
, &buffer
);
313 if (ACPI_FAILURE(status
)) {
314 acpi_util_eval_error(handle
, pathname
, status
);
315 return_ACPI_STATUS(status
);
318 element
= (acpi_object
*) buffer
.pointer
;
320 if ((element
->type
!= ACPI_TYPE_STRING
)
321 || (element
->type
!= ACPI_TYPE_BUFFER
)
322 || !element
->string
.length
) {
323 acpi_util_eval_error(handle
, pathname
, AE_BAD_DATA
);
324 return_ACPI_STATUS(AE_BAD_DATA
);
327 *data
= kmalloc(element
->string
.length
+ 1, GFP_KERNEL
);
329 ACPI_ERROR((AE_INFO
, "Memory allocation"));
330 return_VALUE(-ENOMEM
);
332 memset(*data
, 0, element
->string
.length
+ 1);
334 memcpy(*data
, element
->string
.pointer
, element
->string
.length
);
336 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Return value [%s]\n", *data
));
338 acpi_os_free(buffer
.pointer
);
340 return_ACPI_STATUS(AE_OK
);
345 acpi_evaluate_reference(acpi_handle handle
,
346 acpi_string pathname
,
347 struct acpi_object_list
*arguments
,
348 struct acpi_handle_list
*list
)
350 acpi_status status
= AE_OK
;
351 union acpi_object
*package
= NULL
;
352 union acpi_object
*element
= NULL
;
353 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
356 ACPI_FUNCTION_TRACE("acpi_evaluate_reference");
359 return_ACPI_STATUS(AE_BAD_PARAMETER
);
362 /* Evaluate object. */
364 status
= acpi_evaluate_object(handle
, pathname
, arguments
, &buffer
);
365 if (ACPI_FAILURE(status
))
368 package
= (union acpi_object
*)buffer
.pointer
;
370 if ((buffer
.length
== 0) || !package
) {
371 ACPI_ERROR((AE_INFO
, "No return object (len %X ptr %p)",
372 (unsigned)buffer
.length
, package
));
373 status
= AE_BAD_DATA
;
374 acpi_util_eval_error(handle
, pathname
, status
);
377 if (package
->type
!= ACPI_TYPE_PACKAGE
) {
378 ACPI_ERROR((AE_INFO
, "Expecting a [Package], found type %X",
380 status
= AE_BAD_DATA
;
381 acpi_util_eval_error(handle
, pathname
, status
);
384 if (!package
->package
.count
) {
385 ACPI_ERROR((AE_INFO
, "[Package] has zero elements (%p)",
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
;
406 "Expecting a [Reference] package element, found type %X",
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
);