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 <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> 32 33 #define _COMPONENT ACPI_BUS_COMPONENT 34 ACPI_MODULE_NAME("utils"); 35 36 /* -------------------------------------------------------------------------- 37 Object Evaluation Helpers 38 -------------------------------------------------------------------------- */ 39 static void 40 acpi_util_eval_error(acpi_handle h, acpi_string p, acpi_status s) 41 { 42 #ifdef ACPI_DEBUG_OUTPUT 43 char prefix[80] = {'\0'}; 44 struct acpi_buffer buffer = {sizeof(prefix), prefix}; 45 acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer); 46 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n", 47 (char *) prefix, p, acpi_format_exception(s))); 48 #else 49 return; 50 #endif 51 } 52 53 acpi_status 54 acpi_extract_package(union acpi_object *package, 55 struct acpi_buffer *format, struct acpi_buffer *buffer) 56 { 57 u32 size_required = 0; 58 u32 tail_offset = 0; 59 char *format_string = NULL; 60 u32 format_count = 0; 61 u32 i = 0; 62 u8 *head = NULL; 63 u8 *tail = NULL; 64 65 66 if (!package || (package->type != ACPI_TYPE_PACKAGE) 67 || (package->package.count < 1)) { 68 printk(KERN_WARNING PREFIX "Invalid package argument\n"); 69 return AE_BAD_PARAMETER; 70 } 71 72 if (!format || !format->pointer || (format->length < 1)) { 73 printk(KERN_WARNING PREFIX "Invalid format argument\n"); 74 return AE_BAD_PARAMETER; 75 } 76 77 if (!buffer) { 78 printk(KERN_WARNING PREFIX "Invalid buffer argument\n"); 79 return AE_BAD_PARAMETER; 80 } 81 82 format_count = (format->length / sizeof(char)) - 1; 83 if (format_count > package->package.count) { 84 printk(KERN_WARNING PREFIX "Format specifies more objects [%d]" 85 " than exist in package [%d].\n", 86 format_count, package->package.count); 87 return AE_BAD_DATA; 88 } 89 90 format_string = format->pointer; 91 92 /* 93 * Calculate size_required. 94 */ 95 for (i = 0; i < format_count; i++) { 96 97 union acpi_object *element = &(package->package.elements[i]); 98 99 if (!element) { 100 return AE_BAD_DATA; 101 } 102 103 switch (element->type) { 104 105 case ACPI_TYPE_INTEGER: 106 switch (format_string[i]) { 107 case 'N': 108 size_required += sizeof(acpi_integer); 109 tail_offset += sizeof(acpi_integer); 110 break; 111 case 'S': 112 size_required += 113 sizeof(char *) + sizeof(acpi_integer) + 114 sizeof(char); 115 tail_offset += sizeof(char *); 116 break; 117 default: 118 printk(KERN_WARNING PREFIX "Invalid package element" 119 " [%d]: got number, expecing" 120 " [%c]\n", 121 i, format_string[i]); 122 return AE_BAD_DATA; 123 break; 124 } 125 break; 126 127 case ACPI_TYPE_STRING: 128 case ACPI_TYPE_BUFFER: 129 switch (format_string[i]) { 130 case 'S': 131 size_required += 132 sizeof(char *) + 133 (element->string.length * sizeof(char)) + 134 sizeof(char); 135 tail_offset += sizeof(char *); 136 break; 137 case 'B': 138 size_required += 139 sizeof(u8 *) + 140 (element->buffer.length * sizeof(u8)); 141 tail_offset += sizeof(u8 *); 142 break; 143 default: 144 printk(KERN_WARNING PREFIX "Invalid package element" 145 " [%d] got string/buffer," 146 " expecing [%c]\n", 147 i, format_string[i]); 148 return AE_BAD_DATA; 149 break; 150 } 151 break; 152 153 case ACPI_TYPE_PACKAGE: 154 default: 155 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 156 "Found unsupported element at index=%d\n", 157 i)); 158 /* TBD: handle nested packages... */ 159 return AE_SUPPORT; 160 break; 161 } 162 } 163 164 /* 165 * Validate output buffer. 166 */ 167 if (buffer->length < size_required) { 168 buffer->length = size_required; 169 return AE_BUFFER_OVERFLOW; 170 } else if (buffer->length != size_required || !buffer->pointer) { 171 return AE_BAD_PARAMETER; 172 } 173 174 head = buffer->pointer; 175 tail = buffer->pointer + tail_offset; 176 177 /* 178 * Extract package data. 179 */ 180 for (i = 0; i < format_count; i++) { 181 182 u8 **pointer = NULL; 183 union acpi_object *element = &(package->package.elements[i]); 184 185 if (!element) { 186 return AE_BAD_DATA; 187 } 188 189 switch (element->type) { 190 191 case ACPI_TYPE_INTEGER: 192 switch (format_string[i]) { 193 case 'N': 194 *((acpi_integer *) head) = 195 element->integer.value; 196 head += sizeof(acpi_integer); 197 break; 198 case 'S': 199 pointer = (u8 **) head; 200 *pointer = tail; 201 *((acpi_integer *) tail) = 202 element->integer.value; 203 head += sizeof(acpi_integer *); 204 tail += sizeof(acpi_integer); 205 /* NULL terminate string */ 206 *tail = (char)0; 207 tail += sizeof(char); 208 break; 209 default: 210 /* Should never get here */ 211 break; 212 } 213 break; 214 215 case ACPI_TYPE_STRING: 216 case ACPI_TYPE_BUFFER: 217 switch (format_string[i]) { 218 case 'S': 219 pointer = (u8 **) head; 220 *pointer = tail; 221 memcpy(tail, element->string.pointer, 222 element->string.length); 223 head += sizeof(char *); 224 tail += element->string.length * sizeof(char); 225 /* NULL terminate string */ 226 *tail = (char)0; 227 tail += sizeof(char); 228 break; 229 case 'B': 230 pointer = (u8 **) head; 231 *pointer = tail; 232 memcpy(tail, element->buffer.pointer, 233 element->buffer.length); 234 head += sizeof(u8 *); 235 tail += element->buffer.length * sizeof(u8); 236 break; 237 default: 238 /* Should never get here */ 239 break; 240 } 241 break; 242 243 case ACPI_TYPE_PACKAGE: 244 /* TBD: handle nested packages... */ 245 default: 246 /* Should never get here */ 247 break; 248 } 249 } 250 251 return AE_OK; 252 } 253 254 EXPORT_SYMBOL(acpi_extract_package); 255 256 acpi_status 257 acpi_evaluate_integer(acpi_handle handle, 258 acpi_string pathname, 259 struct acpi_object_list *arguments, unsigned long *data) 260 { 261 acpi_status status = AE_OK; 262 union acpi_object *element; 263 struct acpi_buffer buffer = { 0, NULL }; 264 265 266 if (!data) 267 return AE_BAD_PARAMETER; 268 269 element = kzalloc(sizeof(union acpi_object), irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL); 270 if (!element) 271 return AE_NO_MEMORY; 272 273 buffer.length = sizeof(union acpi_object); 274 buffer.pointer = element; 275 status = acpi_evaluate_object(handle, pathname, arguments, &buffer); 276 if (ACPI_FAILURE(status)) { 277 acpi_util_eval_error(handle, pathname, status); 278 kfree(element); 279 return status; 280 } 281 282 if (element->type != ACPI_TYPE_INTEGER) { 283 acpi_util_eval_error(handle, pathname, AE_BAD_DATA); 284 kfree(element); 285 return AE_BAD_DATA; 286 } 287 288 *data = element->integer.value; 289 kfree(element); 290 291 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%lu]\n", *data)); 292 293 return AE_OK; 294 } 295 296 EXPORT_SYMBOL(acpi_evaluate_integer); 297 298 #if 0 299 acpi_status 300 acpi_evaluate_string(acpi_handle handle, 301 acpi_string pathname, 302 acpi_object_list * arguments, acpi_string * data) 303 { 304 acpi_status status = AE_OK; 305 acpi_object *element = NULL; 306 acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 307 308 309 if (!data) 310 return AE_BAD_PARAMETER; 311 312 status = acpi_evaluate_object(handle, pathname, arguments, &buffer); 313 if (ACPI_FAILURE(status)) { 314 acpi_util_eval_error(handle, pathname, status); 315 return status; 316 } 317 318 element = (acpi_object *) buffer.pointer; 319 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 AE_BAD_DATA; 325 } 326 327 *data = kzalloc(element->string.length + 1, GFP_KERNEL); 328 if (!data) { 329 printk(KERN_ERR PREFIX "Memory allocation\n"); 330 return -ENOMEM; 331 } 332 333 memcpy(*data, element->string.pointer, element->string.length); 334 335 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%s]\n", *data)); 336 337 kfree(buffer.pointer); 338 339 return AE_OK; 340 } 341 #endif 342 343 acpi_status 344 acpi_evaluate_reference(acpi_handle handle, 345 acpi_string pathname, 346 struct acpi_object_list *arguments, 347 struct acpi_handle_list *list) 348 { 349 acpi_status status = AE_OK; 350 union acpi_object *package = NULL; 351 union acpi_object *element = NULL; 352 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 353 u32 i = 0; 354 355 356 if (!list) { 357 return AE_BAD_PARAMETER; 358 } 359 360 /* Evaluate object. */ 361 362 status = acpi_evaluate_object(handle, pathname, arguments, &buffer); 363 if (ACPI_FAILURE(status)) 364 goto end; 365 366 package = buffer.pointer; 367 368 if ((buffer.length == 0) || !package) { 369 printk(KERN_ERR PREFIX "No return object (len %X ptr %p)\n", 370 (unsigned)buffer.length, package); 371 status = AE_BAD_DATA; 372 acpi_util_eval_error(handle, pathname, status); 373 goto end; 374 } 375 if (package->type != ACPI_TYPE_PACKAGE) { 376 printk(KERN_ERR PREFIX "Expecting a [Package], found type %X\n", 377 package->type); 378 status = AE_BAD_DATA; 379 acpi_util_eval_error(handle, pathname, status); 380 goto end; 381 } 382 if (!package->package.count) { 383 printk(KERN_ERR PREFIX "[Package] has zero elements (%p)\n", 384 package); 385 status = AE_BAD_DATA; 386 acpi_util_eval_error(handle, pathname, status); 387 goto end; 388 } 389 390 if (package->package.count > ACPI_MAX_HANDLES) { 391 return AE_NO_MEMORY; 392 } 393 list->count = package->package.count; 394 395 /* Extract package data. */ 396 397 for (i = 0; i < list->count; i++) { 398 399 element = &(package->package.elements[i]); 400 401 if (element->type != ACPI_TYPE_LOCAL_REFERENCE) { 402 status = AE_BAD_DATA; 403 printk(KERN_ERR PREFIX 404 "Expecting a [Reference] package element, found type %X\n", 405 element->type); 406 acpi_util_eval_error(handle, pathname, status); 407 break; 408 } 409 410 if (!element->reference.handle) { 411 printk(KERN_WARNING PREFIX "Invalid reference in" 412 " package %s\n", pathname); 413 status = AE_NULL_ENTRY; 414 break; 415 } 416 /* Get the acpi_handle. */ 417 418 list->handles[i] = element->reference.handle; 419 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found reference [%p]\n", 420 list->handles[i])); 421 } 422 423 end: 424 if (ACPI_FAILURE(status)) { 425 list->count = 0; 426 //kfree(list->handles); 427 } 428 429 kfree(buffer.pointer); 430 431 return status; 432 } 433 434 EXPORT_SYMBOL(acpi_evaluate_reference); 435