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