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 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
31 /* Modified for ReactOS and latest ACPICA
32 * Copyright (C)2009 Samuel Serapion
35 #define _COMPONENT ACPI_BUS_COMPONENT
36 ACPI_MODULE_NAME ("acpi_utils")
39 acpi_util_eval_error(ACPI_HANDLE h
, ACPI_STRING p
, ACPI_STATUS s
)
41 #ifdef ACPI_DEBUG_OUTPUT
42 char prefix
[80] = {'\0'};
43 ACPI_BUFFER buffer
= {sizeof(prefix
), prefix
};
44 AcpiGetName(h
, ACPI_FULL_PATHNAME
, &buffer
);
45 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Evaluate [%s.%s]: %s\n",
46 (char *) prefix
, p
, AcpiFormatException(s
)));
53 /* --------------------------------------------------------------------------
54 Object Evaluation Helpers
55 -------------------------------------------------------------------------- */
59 acpi_extract_package (
64 UINT32 size_required
= 0;
65 UINT32 tail_offset
= 0;
66 char *format_string
= NULL
;
67 UINT32 format_count
= 0;
72 if (!package
|| (package
->Type
!= ACPI_TYPE_PACKAGE
) || (package
->Package
.Count
< 1)) {
73 ACPI_DEBUG_PRINT((ACPI_DB_WARN
, "Invalid 'package' argument\n"));
74 return_ACPI_STATUS(AE_BAD_PARAMETER
);
77 if (!format
|| !format
->Pointer
|| (format
->Length
< 1)) {
78 ACPI_DEBUG_PRINT((ACPI_DB_WARN
, "Invalid 'format' argument\n"));
79 return_ACPI_STATUS(AE_BAD_PARAMETER
);
83 ACPI_DEBUG_PRINT((ACPI_DB_WARN
, "Invalid 'buffer' argument\n"));
84 return_ACPI_STATUS(AE_BAD_PARAMETER
);
87 format_count
= (format
->Length
/sizeof(char)) - 1;
88 if (format_count
> package
->Package
.Count
) {
89 ACPI_DEBUG_PRINT((ACPI_DB_WARN
, "Format specifies more objects [%d] than exist in package [%d].", format_count
, package
->package
.count
));
90 return_ACPI_STATUS(AE_BAD_DATA
);
93 format_string
= format
->Pointer
;
96 * Calculate size_required.
98 for (i
=0; i
<format_count
; i
++) {
100 ACPI_OBJECT
*element
= &(package
->Package
.Elements
[i
]);
103 return_ACPI_STATUS(AE_BAD_DATA
);
106 switch (element
->Type
) {
108 case ACPI_TYPE_INTEGER
:
109 switch (format_string
[i
]) {
111 size_required
+= sizeof(ACPI_INTEGER
);
112 tail_offset
+= sizeof(ACPI_INTEGER
);
115 size_required
+= sizeof(char*) + sizeof(ACPI_INTEGER
) + sizeof(char);
116 tail_offset
+= sizeof(char*);
119 ACPI_DEBUG_PRINT((ACPI_DB_WARN
, "Invalid package element [%d]: got number, expecing [%c].\n", i
, format_string
[i
]));
120 return_ACPI_STATUS(AE_BAD_DATA
);
125 case ACPI_TYPE_STRING
:
126 case ACPI_TYPE_BUFFER
:
127 switch (format_string
[i
]) {
129 size_required
+= sizeof(char*) + (element
->String
.Length
* sizeof(char)) + sizeof(char);
130 tail_offset
+= sizeof(char*);
133 size_required
+= sizeof(UINT8
*) + (element
->Buffer
.Length
* sizeof(UINT8
));
134 tail_offset
+= sizeof(UINT8
*);
137 ACPI_DEBUG_PRINT((ACPI_DB_WARN
, "Invalid package element [%d] got string/buffer, expecing [%c].\n", i
, format_string
[i
]));
138 return_ACPI_STATUS(AE_BAD_DATA
);
143 case ACPI_TYPE_PACKAGE
:
145 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Found unsupported element at index=%d\n", i
));
146 /* TBD: handle nested packages... */
147 return_ACPI_STATUS(AE_SUPPORT
);
153 * Validate output buffer.
155 if (buffer
->Length
< size_required
) {
156 buffer
->Length
= size_required
;
157 return_ACPI_STATUS(AE_BUFFER_OVERFLOW
);
159 else if (buffer
->Length
!= size_required
|| !buffer
->Pointer
) {
160 return_ACPI_STATUS(AE_BAD_PARAMETER
);
163 head
= buffer
->Pointer
;
164 tail
= ((PUCHAR
)buffer
->Pointer
) + tail_offset
;
167 * Extract package data.
169 for (i
=0; i
<format_count
; i
++) {
171 UINT8
**pointer
= NULL
;
172 ACPI_OBJECT
*element
= &(package
->Package
.Elements
[i
]);
175 return_ACPI_STATUS(AE_BAD_DATA
);
178 switch (element
->Type
) {
180 case ACPI_TYPE_INTEGER
:
181 switch (format_string
[i
]) {
183 *((ACPI_INTEGER
*)head
) = element
->Integer
.Value
;
184 head
+= sizeof(ACPI_INTEGER
);
187 pointer
= (UINT8
**)head
;
189 *((ACPI_INTEGER
*)tail
) = element
->Integer
.Value
;
190 head
+= sizeof(ACPI_INTEGER
*);
191 tail
+= sizeof(ACPI_INTEGER
);
192 /* NULL terminate string */
194 tail
+= sizeof(char);
197 /* Should never get here */
202 case ACPI_TYPE_STRING
:
203 case ACPI_TYPE_BUFFER
:
204 switch (format_string
[i
]) {
206 pointer
= (UINT8
**)head
;
208 memcpy(tail
, element
->String
.Pointer
, element
->String
.Length
);
209 head
+= sizeof(char*);
210 tail
+= element
->String
.Length
* sizeof(char);
211 /* NULL terminate string */
213 tail
+= sizeof(char);
216 pointer
= (UINT8
**)head
;
218 memcpy(tail
, element
->Buffer
.Pointer
, element
->Buffer
.Length
);
219 head
+= sizeof(UINT8
*);
220 tail
+= element
->Buffer
.Length
* sizeof(UINT8
);
223 /* Should never get here */
228 case ACPI_TYPE_PACKAGE
:
229 /* TBD: handle nested packages... */
231 /* Should never get here */
236 return_ACPI_STATUS(AE_OK
);
241 acpi_evaluate_integer (
243 ACPI_STRING pathname
,
244 ACPI_OBJECT_LIST
*arguments
,
245 unsigned long long *data
)
247 ACPI_STATUS status
= AE_OK
;
249 ACPI_BUFFER buffer
= {sizeof(ACPI_OBJECT
), &element
};
251 ACPI_FUNCTION_TRACE("acpi_evaluate_integer");
254 return_ACPI_STATUS(AE_BAD_PARAMETER
);
256 status
= AcpiEvaluateObject(handle
, pathname
, arguments
, &buffer
);
257 if (ACPI_FAILURE(status
)) {
258 acpi_util_eval_error(handle
, pathname
, status
);
259 return_ACPI_STATUS(status
);
262 if (element
.Type
!= ACPI_TYPE_INTEGER
) {
263 acpi_util_eval_error(handle
, pathname
, AE_BAD_DATA
);
264 return_ACPI_STATUS(AE_BAD_DATA
);
267 *data
= element
.Integer
.Value
;
269 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Return value [%lu]\n", *data
));
271 return_ACPI_STATUS(AE_OK
);
276 acpi_evaluate_reference (
278 ACPI_STRING pathname
,
279 ACPI_OBJECT_LIST
*arguments
,
280 struct acpi_handle_list
*list
)
282 ACPI_STATUS status
= AE_OK
;
283 ACPI_OBJECT
*package
= NULL
;
284 ACPI_OBJECT
*element
= NULL
;
285 ACPI_BUFFER buffer
= {ACPI_ALLOCATE_BUFFER
, NULL
};
288 ACPI_FUNCTION_TRACE("acpi_evaluate_reference");
291 return_ACPI_STATUS(AE_BAD_PARAMETER
);
294 /* Evaluate object. */
296 status
= AcpiEvaluateObject(handle
, pathname
, arguments
, &buffer
);
297 if (ACPI_FAILURE(status
))
300 package
= (ACPI_OBJECT
*) buffer
.Pointer
;
302 if ((buffer
.Length
== 0) || !package
) {
303 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
304 "No return object (len %X ptr %p)\n",
305 buffer
.Length
, package
));
306 status
= AE_BAD_DATA
;
307 acpi_util_eval_error(handle
, pathname
, status
);
310 if (package
->Type
!= ACPI_TYPE_PACKAGE
) {
311 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
312 "Expecting a [Package], found type %X\n",
314 status
= AE_BAD_DATA
;
315 acpi_util_eval_error(handle
, pathname
, status
);
318 if (!package
->Package
.Count
) {
319 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
320 "[Package] has zero elements (%p)\n",
322 status
= AE_BAD_DATA
;
323 acpi_util_eval_error(handle
, pathname
, status
);
327 if (package
->Package
.Count
> ACPI_MAX_HANDLES
) {
330 list
->count
= package
->Package
.Count
;
332 /* Extract package data. */
334 for (i
= 0; i
< list
->count
; i
++) {
336 element
= &(package
->Package
.Elements
[i
]);
338 if (element
->Type
!= ACPI_TYPE_LOCAL_REFERENCE
) {
339 status
= AE_BAD_DATA
;
340 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
341 "Expecting a [Reference] package element, found type %X\n",
343 acpi_util_eval_error(handle
, pathname
, status
);
347 if (!element
->Reference
.Handle
) {
348 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
, "Invalid reference in"
349 " package %s\n", pathname
));
350 status
= AE_NULL_ENTRY
;
353 /* Get the ACPI_HANDLE. */
355 list
->handles
[i
] = element
->Reference
.Handle
;
356 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Found reference [%p]\n",
361 if (ACPI_FAILURE(status
)) {
363 //ExFreePool(list->handles);
367 AcpiOsFree(buffer
.Pointer
);
369 return_ACPI_STATUS(status
);