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/slab.h> 29 #include <linux/init.h> 30 #include <linux/types.h> 31 #include <linux/hardirq.h> 32 #include <linux/acpi.h> 33 #include <acpi/acpi_bus.h> 34 #include <acpi/acpi_drivers.h> 35 36 #include "internal.h" 37 38 #define _COMPONENT ACPI_BUS_COMPONENT 39 ACPI_MODULE_NAME("utils"); 40 41 /* -------------------------------------------------------------------------- 42 Object Evaluation Helpers 43 -------------------------------------------------------------------------- */ 44 static void 45 acpi_util_eval_error(acpi_handle h, acpi_string p, acpi_status s) 46 { 47 #ifdef ACPI_DEBUG_OUTPUT 48 char prefix[80] = {'\0'}; 49 struct acpi_buffer buffer = {sizeof(prefix), prefix}; 50 acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer); 51 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n", 52 (char *) prefix, p, acpi_format_exception(s))); 53 #else 54 return; 55 #endif 56 } 57 58 acpi_status 59 acpi_extract_package(union acpi_object *package, 60 struct acpi_buffer *format, struct acpi_buffer *buffer) 61 { 62 u32 size_required = 0; 63 u32 tail_offset = 0; 64 char *format_string = NULL; 65 u32 format_count = 0; 66 u32 i = 0; 67 u8 *head = NULL; 68 u8 *tail = NULL; 69 70 71 if (!package || (package->type != ACPI_TYPE_PACKAGE) 72 || (package->package.count < 1)) { 73 printk(KERN_WARNING PREFIX "Invalid package argument\n"); 74 return AE_BAD_PARAMETER; 75 } 76 77 if (!format || !format->pointer || (format->length < 1)) { 78 printk(KERN_WARNING PREFIX "Invalid format argument\n"); 79 return AE_BAD_PARAMETER; 80 } 81 82 if (!buffer) { 83 printk(KERN_WARNING PREFIX "Invalid buffer argument\n"); 84 return AE_BAD_PARAMETER; 85 } 86 87 format_count = (format->length / sizeof(char)) - 1; 88 if (format_count > package->package.count) { 89 printk(KERN_WARNING PREFIX "Format specifies more objects [%d]" 90 " than exist in package [%d].\n", 91 format_count, package->package.count); 92 return AE_BAD_DATA; 93 } 94 95 format_string = format->pointer; 96 97 /* 98 * Calculate size_required. 99 */ 100 for (i = 0; i < format_count; i++) { 101 102 union acpi_object *element = &(package->package.elements[i]); 103 104 if (!element) { 105 return AE_BAD_DATA; 106 } 107 108 switch (element->type) { 109 110 case ACPI_TYPE_INTEGER: 111 switch (format_string[i]) { 112 case 'N': 113 size_required += sizeof(u64); 114 tail_offset += sizeof(u64); 115 break; 116 case 'S': 117 size_required += 118 sizeof(char *) + sizeof(u64) + 119 sizeof(char); 120 tail_offset += sizeof(char *); 121 break; 122 default: 123 printk(KERN_WARNING PREFIX "Invalid package element" 124 " [%d]: got number, expecing" 125 " [%c]\n", 126 i, format_string[i]); 127 return AE_BAD_DATA; 128 break; 129 } 130 break; 131 132 case ACPI_TYPE_STRING: 133 case ACPI_TYPE_BUFFER: 134 switch (format_string[i]) { 135 case 'S': 136 size_required += 137 sizeof(char *) + 138 (element->string.length * sizeof(char)) + 139 sizeof(char); 140 tail_offset += sizeof(char *); 141 break; 142 case 'B': 143 size_required += 144 sizeof(u8 *) + 145 (element->buffer.length * sizeof(u8)); 146 tail_offset += sizeof(u8 *); 147 break; 148 default: 149 printk(KERN_WARNING PREFIX "Invalid package element" 150 " [%d] got string/buffer," 151 " expecing [%c]\n", 152 i, format_string[i]); 153 return AE_BAD_DATA; 154 break; 155 } 156 break; 157 158 case ACPI_TYPE_PACKAGE: 159 default: 160 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 161 "Found unsupported element at index=%d\n", 162 i)); 163 /* TBD: handle nested packages... */ 164 return AE_SUPPORT; 165 break; 166 } 167 } 168 169 /* 170 * Validate output buffer. 171 */ 172 if (buffer->length < size_required) { 173 buffer->length = size_required; 174 return AE_BUFFER_OVERFLOW; 175 } else if (buffer->length != size_required || !buffer->pointer) { 176 return AE_BAD_PARAMETER; 177 } 178 179 head = buffer->pointer; 180 tail = buffer->pointer + tail_offset; 181 182 /* 183 * Extract package data. 184 */ 185 for (i = 0; i < format_count; i++) { 186 187 u8 **pointer = NULL; 188 union acpi_object *element = &(package->package.elements[i]); 189 190 if (!element) { 191 return AE_BAD_DATA; 192 } 193 194 switch (element->type) { 195 196 case ACPI_TYPE_INTEGER: 197 switch (format_string[i]) { 198 case 'N': 199 *((u64 *) head) = 200 element->integer.value; 201 head += sizeof(u64); 202 break; 203 case 'S': 204 pointer = (u8 **) head; 205 *pointer = tail; 206 *((u64 *) tail) = 207 element->integer.value; 208 head += sizeof(u64 *); 209 tail += sizeof(u64); 210 /* NULL terminate string */ 211 *tail = (char)0; 212 tail += sizeof(char); 213 break; 214 default: 215 /* Should never get here */ 216 break; 217 } 218 break; 219 220 case ACPI_TYPE_STRING: 221 case ACPI_TYPE_BUFFER: 222 switch (format_string[i]) { 223 case 'S': 224 pointer = (u8 **) head; 225 *pointer = tail; 226 memcpy(tail, element->string.pointer, 227 element->string.length); 228 head += sizeof(char *); 229 tail += element->string.length * sizeof(char); 230 /* NULL terminate string */ 231 *tail = (char)0; 232 tail += sizeof(char); 233 break; 234 case 'B': 235 pointer = (u8 **) head; 236 *pointer = tail; 237 memcpy(tail, element->buffer.pointer, 238 element->buffer.length); 239 head += sizeof(u8 *); 240 tail += element->buffer.length * sizeof(u8); 241 break; 242 default: 243 /* Should never get here */ 244 break; 245 } 246 break; 247 248 case ACPI_TYPE_PACKAGE: 249 /* TBD: handle nested packages... */ 250 default: 251 /* Should never get here */ 252 break; 253 } 254 } 255 256 return AE_OK; 257 } 258 259 EXPORT_SYMBOL(acpi_extract_package); 260 261 acpi_status 262 acpi_evaluate_integer(acpi_handle handle, 263 acpi_string pathname, 264 struct acpi_object_list *arguments, unsigned long long *data) 265 { 266 acpi_status status = AE_OK; 267 union acpi_object element; 268 struct acpi_buffer buffer = { 0, NULL }; 269 270 if (!data) 271 return AE_BAD_PARAMETER; 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 return status; 279 } 280 281 if (element.type != ACPI_TYPE_INTEGER) { 282 acpi_util_eval_error(handle, pathname, AE_BAD_DATA); 283 return AE_BAD_DATA; 284 } 285 286 *data = element.integer.value; 287 288 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data)); 289 290 return AE_OK; 291 } 292 293 EXPORT_SYMBOL(acpi_evaluate_integer); 294 295 acpi_status 296 acpi_evaluate_reference(acpi_handle handle, 297 acpi_string pathname, 298 struct acpi_object_list *arguments, 299 struct acpi_handle_list *list) 300 { 301 acpi_status status = AE_OK; 302 union acpi_object *package = NULL; 303 union acpi_object *element = NULL; 304 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 305 u32 i = 0; 306 307 308 if (!list) { 309 return AE_BAD_PARAMETER; 310 } 311 312 /* Evaluate object. */ 313 314 status = acpi_evaluate_object(handle, pathname, arguments, &buffer); 315 if (ACPI_FAILURE(status)) 316 goto end; 317 318 package = buffer.pointer; 319 320 if ((buffer.length == 0) || !package) { 321 printk(KERN_ERR PREFIX "No return object (len %X ptr %p)\n", 322 (unsigned)buffer.length, package); 323 status = AE_BAD_DATA; 324 acpi_util_eval_error(handle, pathname, status); 325 goto end; 326 } 327 if (package->type != ACPI_TYPE_PACKAGE) { 328 printk(KERN_ERR PREFIX "Expecting a [Package], found type %X\n", 329 package->type); 330 status = AE_BAD_DATA; 331 acpi_util_eval_error(handle, pathname, status); 332 goto end; 333 } 334 if (!package->package.count) { 335 printk(KERN_ERR PREFIX "[Package] has zero elements (%p)\n", 336 package); 337 status = AE_BAD_DATA; 338 acpi_util_eval_error(handle, pathname, status); 339 goto end; 340 } 341 342 if (package->package.count > ACPI_MAX_HANDLES) { 343 return AE_NO_MEMORY; 344 } 345 list->count = package->package.count; 346 347 /* Extract package data. */ 348 349 for (i = 0; i < list->count; i++) { 350 351 element = &(package->package.elements[i]); 352 353 if (element->type != ACPI_TYPE_LOCAL_REFERENCE) { 354 status = AE_BAD_DATA; 355 printk(KERN_ERR PREFIX 356 "Expecting a [Reference] package element, found type %X\n", 357 element->type); 358 acpi_util_eval_error(handle, pathname, status); 359 break; 360 } 361 362 if (!element->reference.handle) { 363 printk(KERN_WARNING PREFIX "Invalid reference in" 364 " package %s\n", pathname); 365 status = AE_NULL_ENTRY; 366 break; 367 } 368 /* Get the acpi_handle. */ 369 370 list->handles[i] = element->reference.handle; 371 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found reference [%p]\n", 372 list->handles[i])); 373 } 374 375 end: 376 if (ACPI_FAILURE(status)) { 377 list->count = 0; 378 //kfree(list->handles); 379 } 380 381 kfree(buffer.pointer); 382 383 return status; 384 } 385 386 EXPORT_SYMBOL(acpi_evaluate_reference); 387 388 acpi_status 389 acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld) 390 { 391 acpi_status status; 392 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 393 union acpi_object *output; 394 395 status = acpi_evaluate_object(handle, "_PLD", NULL, &buffer); 396 397 if (ACPI_FAILURE(status)) 398 return status; 399 400 output = buffer.pointer; 401 402 if (!output || output->type != ACPI_TYPE_PACKAGE 403 || !output->package.count 404 || output->package.elements[0].type != ACPI_TYPE_BUFFER 405 || output->package.elements[0].buffer.length < ACPI_PLD_REV1_BUFFER_SIZE) { 406 status = AE_TYPE; 407 goto out; 408 } 409 410 status = acpi_decode_pld_buffer( 411 output->package.elements[0].buffer.pointer, 412 output->package.elements[0].buffer.length, 413 pld); 414 415 out: 416 kfree(buffer.pointer); 417 return status; 418 } 419 EXPORT_SYMBOL(acpi_get_physical_device_location); 420 421 /** 422 * acpi_evaluate_hotplug_ost: Evaluate _OST for hotplug operations 423 * @handle: ACPI device handle 424 * @source_event: source event code 425 * @status_code: status code 426 * @status_buf: optional detailed information (NULL if none) 427 * 428 * Evaluate _OST for hotplug operations. All ACPI hotplug handlers 429 * must call this function when evaluating _OST for hotplug operations. 430 * When the platform does not support _OST, this function has no effect. 431 */ 432 acpi_status 433 acpi_evaluate_hotplug_ost(acpi_handle handle, u32 source_event, 434 u32 status_code, struct acpi_buffer *status_buf) 435 { 436 #ifdef ACPI_HOTPLUG_OST 437 union acpi_object params[3] = { 438 {.type = ACPI_TYPE_INTEGER,}, 439 {.type = ACPI_TYPE_INTEGER,}, 440 {.type = ACPI_TYPE_BUFFER,} 441 }; 442 struct acpi_object_list arg_list = {3, params}; 443 acpi_status status; 444 445 params[0].integer.value = source_event; 446 params[1].integer.value = status_code; 447 if (status_buf != NULL) { 448 params[2].buffer.pointer = status_buf->pointer; 449 params[2].buffer.length = status_buf->length; 450 } else { 451 params[2].buffer.pointer = NULL; 452 params[2].buffer.length = 0; 453 } 454 455 status = acpi_evaluate_object(handle, "_OST", &arg_list, NULL); 456 return status; 457 #else 458 return AE_OK; 459 #endif 460 } 461 EXPORT_SYMBOL(acpi_evaluate_hotplug_ost); 462 463 /** 464 * acpi_handle_printk: Print message with ACPI prefix and object path 465 * 466 * This function is called through acpi_handle_<level> macros and prints 467 * a message with ACPI prefix and object path. This function acquires 468 * the global namespace mutex to obtain an object path. In interrupt 469 * context, it shows the object path as <n/a>. 470 */ 471 void 472 acpi_handle_printk(const char *level, acpi_handle handle, const char *fmt, ...) 473 { 474 struct va_format vaf; 475 va_list args; 476 struct acpi_buffer buffer = { 477 .length = ACPI_ALLOCATE_BUFFER, 478 .pointer = NULL 479 }; 480 const char *path; 481 482 va_start(args, fmt); 483 vaf.fmt = fmt; 484 vaf.va = &args; 485 486 if (in_interrupt() || 487 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer) != AE_OK) 488 path = "<n/a>"; 489 else 490 path = buffer.pointer; 491 492 printk("%sACPI: %s: %pV", level, path, &vaf); 493 494 va_end(args); 495 kfree(buffer.pointer); 496 } 497 EXPORT_SYMBOL(acpi_handle_printk); 498