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