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 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
30 #include <acpi_drivers.h>
36 /* Modified for ReactOS and latest ACPICA
37 * Copyright (C)2009 Samuel Serapion
40 #define _COMPONENT ACPI_BUS_COMPONENT
41 ACPI_MODULE_NAME ("acpi_utils")
44 acpi_util_eval_error(ACPI_HANDLE h
, ACPI_STRING p
, ACPI_STATUS s
)
46 #ifdef ACPI_DEBUG_OUTPUT
47 char prefix
[80] = {'\0'};
48 ACPI_BUFFER buffer
= {sizeof(prefix
), prefix
};
49 AcpiGetName(h
, ACPI_FULL_PATHNAME
, &buffer
);
50 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Evaluate [%s.%s]: %s\n",
51 (char *) prefix
, p
, AcpiFormatException(s
)));
58 /* --------------------------------------------------------------------------
59 Object Evaluation Helpers
60 -------------------------------------------------------------------------- */
64 acpi_extract_package (
69 UINT32 size_required
= 0;
70 UINT32 tail_offset
= 0;
71 char *format_string
= NULL
;
72 UINT32 format_count
= 0;
77 if (!package
|| (package
->Type
!= ACPI_TYPE_PACKAGE
) || (package
->Package
.Count
< 1)) {
78 ACPI_DEBUG_PRINT((ACPI_DB_WARN
, "Invalid 'package' argument\n"));
79 return_ACPI_STATUS(AE_BAD_PARAMETER
);
82 if (!format
|| !format
->Pointer
|| (format
->Length
< 1)) {
83 ACPI_DEBUG_PRINT((ACPI_DB_WARN
, "Invalid 'format' argument\n"));
84 return_ACPI_STATUS(AE_BAD_PARAMETER
);
88 ACPI_DEBUG_PRINT((ACPI_DB_WARN
, "Invalid 'buffer' argument\n"));
89 return_ACPI_STATUS(AE_BAD_PARAMETER
);
92 format_count
= (format
->Length
/sizeof(char)) - 1;
93 if (format_count
> package
->Package
.Count
) {
94 ACPI_DEBUG_PRINT((ACPI_DB_WARN
, "Format specifies more objects [%d] than exist in package [%d].", format_count
, package
->package
.count
));
95 return_ACPI_STATUS(AE_BAD_DATA
);
98 format_string
= format
->Pointer
;
101 * Calculate size_required.
103 for (i
=0; i
<format_count
; i
++) {
105 ACPI_OBJECT
*element
= &(package
->Package
.Elements
[i
]);
108 return_ACPI_STATUS(AE_BAD_DATA
);
111 switch (element
->Type
) {
113 case ACPI_TYPE_INTEGER
:
114 switch (format_string
[i
]) {
116 size_required
+= sizeof(ACPI_INTEGER
);
117 tail_offset
+= sizeof(ACPI_INTEGER
);
120 size_required
+= sizeof(char*) + sizeof(ACPI_INTEGER
) + sizeof(char);
121 tail_offset
+= sizeof(char*);
124 ACPI_DEBUG_PRINT((ACPI_DB_WARN
, "Invalid package element [%d]: got number, expecing [%c].\n", i
, format_string
[i
]));
125 return_ACPI_STATUS(AE_BAD_DATA
);
130 case ACPI_TYPE_STRING
:
131 case ACPI_TYPE_BUFFER
:
132 switch (format_string
[i
]) {
134 size_required
+= sizeof(char*) + (element
->String
.Length
* sizeof(char)) + sizeof(char);
135 tail_offset
+= sizeof(char*);
138 size_required
+= sizeof(UINT8
*) + (element
->Buffer
.Length
* sizeof(UINT8
));
139 tail_offset
+= sizeof(UINT8
*);
142 ACPI_DEBUG_PRINT((ACPI_DB_WARN
, "Invalid package element [%d] got string/buffer, expecing [%c].\n", i
, format_string
[i
]));
143 return_ACPI_STATUS(AE_BAD_DATA
);
148 case ACPI_TYPE_PACKAGE
:
150 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Found unsupported element at index=%d\n", i
));
151 /* TBD: handle nested packages... */
152 return_ACPI_STATUS(AE_SUPPORT
);
158 * Validate output buffer.
160 if (buffer
->Length
< size_required
) {
161 buffer
->Length
= size_required
;
162 return_ACPI_STATUS(AE_BUFFER_OVERFLOW
);
164 else if (buffer
->Length
!= size_required
|| !buffer
->Pointer
) {
165 return_ACPI_STATUS(AE_BAD_PARAMETER
);
168 head
= buffer
->Pointer
;
169 tail
= ((PUCHAR
)buffer
->Pointer
) + tail_offset
;
172 * Extract package data.
174 for (i
=0; i
<format_count
; i
++) {
176 UINT8
**pointer
= NULL
;
177 ACPI_OBJECT
*element
= &(package
->Package
.Elements
[i
]);
180 return_ACPI_STATUS(AE_BAD_DATA
);
183 switch (element
->Type
) {
185 case ACPI_TYPE_INTEGER
:
186 switch (format_string
[i
]) {
188 *((ACPI_INTEGER
*)head
) = element
->Integer
.Value
;
189 head
+= sizeof(ACPI_INTEGER
);
192 pointer
= (UINT8
**)head
;
194 *((ACPI_INTEGER
*)tail
) = element
->Integer
.Value
;
195 head
+= sizeof(ACPI_INTEGER
*);
196 tail
+= sizeof(ACPI_INTEGER
);
197 /* NULL terminate string */
199 tail
+= sizeof(char);
202 /* Should never get here */
207 case ACPI_TYPE_STRING
:
208 case ACPI_TYPE_BUFFER
:
209 switch (format_string
[i
]) {
211 pointer
= (UINT8
**)head
;
213 memcpy(tail
, element
->String
.Pointer
, element
->String
.Length
);
214 head
+= sizeof(char*);
215 tail
+= element
->String
.Length
* sizeof(char);
216 /* NULL terminate string */
218 tail
+= sizeof(char);
221 pointer
= (UINT8
**)head
;
223 memcpy(tail
, element
->Buffer
.Pointer
, element
->Buffer
.Length
);
224 head
+= sizeof(UINT8
*);
225 tail
+= element
->Buffer
.Length
* sizeof(UINT8
);
228 /* Should never get here */
233 case ACPI_TYPE_PACKAGE
:
234 /* TBD: handle nested packages... */
236 /* Should never get here */
241 return_ACPI_STATUS(AE_OK
);
246 acpi_evaluate_integer (
248 ACPI_STRING pathname
,
249 ACPI_OBJECT_LIST
*arguments
,
250 unsigned long long *data
)
252 ACPI_STATUS status
= AE_OK
;
254 ACPI_BUFFER buffer
= {sizeof(ACPI_OBJECT
), &element
};
256 ACPI_FUNCTION_TRACE("acpi_evaluate_integer");
259 return_ACPI_STATUS(AE_BAD_PARAMETER
);
261 status
= AcpiEvaluateObject(handle
, pathname
, arguments
, &buffer
);
262 if (ACPI_FAILURE(status
)) {
263 acpi_util_eval_error(handle
, pathname
, status
);
264 return_ACPI_STATUS(status
);
267 if (element
.Type
!= ACPI_TYPE_INTEGER
) {
268 acpi_util_eval_error(handle
, pathname
, AE_BAD_DATA
);
269 return_ACPI_STATUS(AE_BAD_DATA
);
272 *data
= element
.Integer
.Value
;
274 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Return value [%lu]\n", *data
));
276 return_ACPI_STATUS(AE_OK
);
281 acpi_evaluate_reference (
283 ACPI_STRING pathname
,
284 ACPI_OBJECT_LIST
*arguments
,
285 struct acpi_handle_list
*list
)
287 ACPI_STATUS status
= AE_OK
;
288 ACPI_OBJECT
*package
= NULL
;
289 ACPI_OBJECT
*element
= NULL
;
290 ACPI_BUFFER buffer
= {ACPI_ALLOCATE_BUFFER
, NULL
};
293 ACPI_FUNCTION_TRACE("acpi_evaluate_reference");
296 return_ACPI_STATUS(AE_BAD_PARAMETER
);
299 /* Evaluate object. */
301 status
= AcpiEvaluateObject(handle
, pathname
, arguments
, &buffer
);
302 if (ACPI_FAILURE(status
))
305 package
= (ACPI_OBJECT
*) buffer
.Pointer
;
307 if ((buffer
.Length
== 0) || !package
) {
308 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
309 "No return object (len %X ptr %p)\n",
310 buffer
.Length
, package
));
311 status
= AE_BAD_DATA
;
312 acpi_util_eval_error(handle
, pathname
, status
);
315 if (package
->Type
!= ACPI_TYPE_PACKAGE
) {
316 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
317 "Expecting a [Package], found type %X\n",
319 status
= AE_BAD_DATA
;
320 acpi_util_eval_error(handle
, pathname
, status
);
323 if (!package
->Package
.Count
) {
324 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
325 "[Package] has zero elements (%p)\n",
327 status
= AE_BAD_DATA
;
328 acpi_util_eval_error(handle
, pathname
, status
);
332 if (package
->Package
.Count
> ACPI_MAX_HANDLES
) {
335 list
->count
= package
->Package
.Count
;
337 /* Extract package data. */
339 for (i
= 0; i
< list
->count
; i
++) {
341 element
= &(package
->Package
.Elements
[i
]);
343 if (element
->Type
!= ACPI_TYPE_LOCAL_REFERENCE
) {
344 status
= AE_BAD_DATA
;
345 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
346 "Expecting a [Reference] package element, found type %X\n",
348 acpi_util_eval_error(handle
, pathname
, status
);
352 if (!element
->Reference
.Handle
) {
353 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
, "Invalid reference in"
354 " package %s\n", pathname
));
355 status
= AE_NULL_ENTRY
;
358 /* Get the ACPI_HANDLE. */
360 list
->handles
[i
] = element
->Reference
.Handle
;
361 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Found reference [%p]\n",
366 if (ACPI_FAILURE(status
)) {
368 //ExFreePool(list->handles);
372 AcpiOsFree(buffer
.Pointer
);
374 return_ACPI_STATUS(status
);