1 /* 2 * acpi_utils.c - ACPI Utility Functions ($Revision: 10 $) 3 * 4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 6 * 7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8 * 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. 13 * 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. 18 * 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. 22 * 23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 24 */ 25 26 #include <ntddk.h> 27 28 #include <acpi.h> 29 #include <acpi_bus.h> 30 #include <acpi_drivers.h> 31 #include <glue.h> 32 33 #define NDEBUG 34 #include <debug.h> 35 36 /* Modified for ReactOS and latest ACPICA 37 * Copyright (C)2009 Samuel Serapion 38 */ 39 40 #define _COMPONENT ACPI_BUS_COMPONENT 41 ACPI_MODULE_NAME ("acpi_utils") 42 43 static void 44 acpi_util_eval_error(ACPI_HANDLE h, ACPI_STRING p, ACPI_STATUS s) 45 { 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))); 52 #else 53 return; 54 #endif 55 } 56 57 58 /* -------------------------------------------------------------------------- 59 Object Evaluation Helpers 60 -------------------------------------------------------------------------- */ 61 62 63 ACPI_STATUS 64 acpi_extract_package ( 65 ACPI_OBJECT *package, 66 ACPI_BUFFER *format, 67 ACPI_BUFFER *buffer) 68 { 69 UINT32 size_required = 0; 70 UINT32 tail_offset = 0; 71 char *format_string = NULL; 72 UINT32 format_count = 0; 73 UINT32 i = 0; 74 UINT8 *head = NULL; 75 UINT8 *tail = NULL; 76 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); 80 } 81 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); 85 } 86 87 if (!buffer) { 88 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid 'buffer' argument\n")); 89 return_ACPI_STATUS(AE_BAD_PARAMETER); 90 } 91 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); 96 } 97 98 format_string = format->Pointer; 99 100 /* 101 * Calculate size_required. 102 */ 103 for (i=0; i<format_count; i++) { 104 105 ACPI_OBJECT *element = &(package->Package.Elements[i]); 106 107 if (!element) { 108 return_ACPI_STATUS(AE_BAD_DATA); 109 } 110 111 switch (element->Type) { 112 113 case ACPI_TYPE_INTEGER: 114 switch (format_string[i]) { 115 case 'N': 116 size_required += sizeof(ACPI_INTEGER); 117 tail_offset += sizeof(ACPI_INTEGER); 118 break; 119 case 'S': 120 size_required += sizeof(char*) + sizeof(ACPI_INTEGER) + sizeof(char); 121 tail_offset += sizeof(char*); 122 break; 123 default: 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); 126 break; 127 } 128 break; 129 130 case ACPI_TYPE_STRING: 131 case ACPI_TYPE_BUFFER: 132 switch (format_string[i]) { 133 case 'S': 134 size_required += sizeof(char*) + (element->String.Length * sizeof(char)) + sizeof(char); 135 tail_offset += sizeof(char*); 136 break; 137 case 'B': 138 size_required += sizeof(UINT8*) + (element->Buffer.Length * sizeof(UINT8)); 139 tail_offset += sizeof(UINT8*); 140 break; 141 default: 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); 144 break; 145 } 146 break; 147 148 case ACPI_TYPE_PACKAGE: 149 default: 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); 153 break; 154 } 155 } 156 157 /* 158 * Validate output buffer. 159 */ 160 if (buffer->Length < size_required) { 161 buffer->Length = size_required; 162 return_ACPI_STATUS(AE_BUFFER_OVERFLOW); 163 } 164 else if (buffer->Length != size_required || !buffer->Pointer) { 165 return_ACPI_STATUS(AE_BAD_PARAMETER); 166 } 167 168 head = buffer->Pointer; 169 tail = ((PUCHAR)buffer->Pointer) + tail_offset; 170 171 /* 172 * Extract package data. 173 */ 174 for (i=0; i<format_count; i++) { 175 176 UINT8 **pointer = NULL; 177 ACPI_OBJECT *element = &(package->Package.Elements[i]); 178 179 if (!element) { 180 return_ACPI_STATUS(AE_BAD_DATA); 181 } 182 183 switch (element->Type) { 184 185 case ACPI_TYPE_INTEGER: 186 switch (format_string[i]) { 187 case 'N': 188 *((ACPI_INTEGER*)head) = element->Integer.Value; 189 head += sizeof(ACPI_INTEGER); 190 break; 191 case 'S': 192 pointer = (UINT8**)head; 193 *pointer = tail; 194 *((ACPI_INTEGER*)tail) = element->Integer.Value; 195 head += sizeof(ACPI_INTEGER*); 196 tail += sizeof(ACPI_INTEGER); 197 /* NULL terminate string */ 198 *tail = (char)0; 199 tail += sizeof(char); 200 break; 201 default: 202 /* Should never get here */ 203 break; 204 } 205 break; 206 207 case ACPI_TYPE_STRING: 208 case ACPI_TYPE_BUFFER: 209 switch (format_string[i]) { 210 case 'S': 211 pointer = (UINT8**)head; 212 *pointer = tail; 213 memcpy(tail, element->String.Pointer, element->String.Length); 214 head += sizeof(char*); 215 tail += element->String.Length * sizeof(char); 216 /* NULL terminate string */ 217 *tail = (char)0; 218 tail += sizeof(char); 219 break; 220 case 'B': 221 pointer = (UINT8**)head; 222 *pointer = tail; 223 memcpy(tail, element->Buffer.Pointer, element->Buffer.Length); 224 head += sizeof(UINT8*); 225 tail += element->Buffer.Length * sizeof(UINT8); 226 break; 227 default: 228 /* Should never get here */ 229 break; 230 } 231 break; 232 233 case ACPI_TYPE_PACKAGE: 234 /* TBD: handle nested packages... */ 235 default: 236 /* Should never get here */ 237 break; 238 } 239 } 240 241 return_ACPI_STATUS(AE_OK); 242 } 243 244 245 ACPI_STATUS 246 acpi_evaluate_integer ( 247 ACPI_HANDLE handle, 248 ACPI_STRING pathname, 249 ACPI_OBJECT_LIST *arguments, 250 unsigned long long *data) 251 { 252 ACPI_STATUS status = AE_OK; 253 ACPI_OBJECT element; 254 ACPI_BUFFER buffer = {sizeof(ACPI_OBJECT), &element}; 255 256 ACPI_FUNCTION_TRACE("acpi_evaluate_integer"); 257 258 if (!data) 259 return_ACPI_STATUS(AE_BAD_PARAMETER); 260 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); 265 } 266 267 if (element.Type != ACPI_TYPE_INTEGER) { 268 acpi_util_eval_error(handle, pathname, AE_BAD_DATA); 269 return_ACPI_STATUS(AE_BAD_DATA); 270 } 271 272 *data = element.Integer.Value; 273 274 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%lu]\n", *data)); 275 276 return_ACPI_STATUS(AE_OK); 277 } 278 279 280 ACPI_STATUS 281 acpi_evaluate_reference ( 282 ACPI_HANDLE handle, 283 ACPI_STRING pathname, 284 ACPI_OBJECT_LIST *arguments, 285 struct acpi_handle_list *list) 286 { 287 ACPI_STATUS status = AE_OK; 288 ACPI_OBJECT *package = NULL; 289 ACPI_OBJECT *element = NULL; 290 ACPI_BUFFER buffer = {ACPI_ALLOCATE_BUFFER, NULL}; 291 UINT32 i = 0; 292 293 ACPI_FUNCTION_TRACE("acpi_evaluate_reference"); 294 295 if (!list) { 296 return_ACPI_STATUS(AE_BAD_PARAMETER); 297 } 298 299 /* Evaluate object. */ 300 301 status = AcpiEvaluateObject(handle, pathname, arguments, &buffer); 302 if (ACPI_FAILURE(status)) 303 goto end; 304 305 package = (ACPI_OBJECT *) buffer.Pointer; 306 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); 313 goto end; 314 } 315 if (package->Type != ACPI_TYPE_PACKAGE) { 316 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 317 "Expecting a [Package], found type %X\n", 318 package->Type)); 319 status = AE_BAD_DATA; 320 acpi_util_eval_error(handle, pathname, status); 321 goto end; 322 } 323 if (!package->Package.Count) { 324 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 325 "[Package] has zero elements (%p)\n", 326 package)); 327 status = AE_BAD_DATA; 328 acpi_util_eval_error(handle, pathname, status); 329 goto end; 330 } 331 332 if (package->Package.Count > ACPI_MAX_HANDLES) { 333 return AE_NO_MEMORY; 334 } 335 list->count = package->Package.Count; 336 337 /* Extract package data. */ 338 339 for (i = 0; i < list->count; i++) { 340 341 element = &(package->Package.Elements[i]); 342 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", 347 element->type)); 348 acpi_util_eval_error(handle, pathname, status); 349 break; 350 } 351 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; 356 break; 357 } 358 /* Get the ACPI_HANDLE. */ 359 360 list->handles[i] = element->Reference.Handle; 361 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found reference [%p]\n", 362 list->handles[i])); 363 } 364 365 end: 366 if (ACPI_FAILURE(status)) { 367 list->count = 0; 368 //ExFreePool(list->handles); 369 } 370 371 if (buffer.Pointer) 372 AcpiOsFree(buffer.Pointer); 373 374 return_ACPI_STATUS(status); 375 } 376 377 378