1/******************************************************************************* 2 * 3 * Module Name: nsxfeval - Public interfaces to the ACPI subsystem 4 * ACPI Object evaluation interfaces 5 * 6 ******************************************************************************/ 7 8/* 9 * Copyright (C) 2000 - 2007, R. Byron Moore 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45#include <acpi/acpi.h> 46#include <acpi/acnamesp.h> 47#include <acpi/acinterp.h> 48 49#define _COMPONENT ACPI_NAMESPACE 50ACPI_MODULE_NAME("nsxfeval") 51#ifdef ACPI_FUTURE_USAGE 52/******************************************************************************* 53 * 54 * FUNCTION: acpi_evaluate_object_typed 55 * 56 * PARAMETERS: Handle - Object handle (optional) 57 * Pathname - Object pathname (optional) 58 * external_params - List of parameters to pass to method, 59 * terminated by NULL. May be NULL 60 * if no parameters are being passed. 61 * return_buffer - Where to put method's return value (if 62 * any). If NULL, no value is returned. 63 * return_type - Expected type of return object 64 * 65 * RETURN: Status 66 * 67 * DESCRIPTION: Find and evaluate the given object, passing the given 68 * parameters if necessary. One of "Handle" or "Pathname" must 69 * be valid (non-null) 70 * 71 ******************************************************************************/ 72acpi_status 73acpi_evaluate_object_typed(acpi_handle handle, 74 acpi_string pathname, 75 struct acpi_object_list *external_params, 76 struct acpi_buffer *return_buffer, 77 acpi_object_type return_type) 78{ 79 acpi_status status; 80 u8 must_free = FALSE; 81 82 ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed); 83 84 /* Return buffer must be valid */ 85 86 if (!return_buffer) { 87 return_ACPI_STATUS(AE_BAD_PARAMETER); 88 } 89 90 if (return_buffer->length == ACPI_ALLOCATE_BUFFER) { 91 must_free = TRUE; 92 } 93 94 /* Evaluate the object */ 95 96 status = 97 acpi_evaluate_object(handle, pathname, external_params, 98 return_buffer); 99 if (ACPI_FAILURE(status)) { 100 return_ACPI_STATUS(status); 101 } 102 103 /* Type ANY means "don't care" */ 104 105 if (return_type == ACPI_TYPE_ANY) { 106 return_ACPI_STATUS(AE_OK); 107 } 108 109 if (return_buffer->length == 0) { 110 111 /* Error because caller specifically asked for a return value */ 112 113 ACPI_ERROR((AE_INFO, "No return value")); 114 return_ACPI_STATUS(AE_NULL_OBJECT); 115 } 116 117 /* Examine the object type returned from evaluate_object */ 118 119 if (((union acpi_object *)return_buffer->pointer)->type == return_type) { 120 return_ACPI_STATUS(AE_OK); 121 } 122 123 /* Return object type does not match requested type */ 124 125 ACPI_ERROR((AE_INFO, 126 "Incorrect return type [%s] requested [%s]", 127 acpi_ut_get_type_name(((union acpi_object *)return_buffer-> 128 pointer)->type), 129 acpi_ut_get_type_name(return_type))); 130 131 if (must_free) { 132 133 /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */ 134 135 ACPI_FREE(return_buffer->pointer); 136 return_buffer->pointer = NULL; 137 } 138 139 return_buffer->length = 0; 140 return_ACPI_STATUS(AE_TYPE); 141} 142 143ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed) 144#endif /* ACPI_FUTURE_USAGE */ 145/******************************************************************************* 146 * 147 * FUNCTION: acpi_evaluate_object 148 * 149 * PARAMETERS: Handle - Object handle (optional) 150 * Pathname - Object pathname (optional) 151 * external_params - List of parameters to pass to method, 152 * terminated by NULL. May be NULL 153 * if no parameters are being passed. 154 * return_buffer - Where to put method's return value (if 155 * any). If NULL, no value is returned. 156 * 157 * RETURN: Status 158 * 159 * DESCRIPTION: Find and evaluate the given object, passing the given 160 * parameters if necessary. One of "Handle" or "Pathname" must 161 * be valid (non-null) 162 * 163 ******************************************************************************/ 164acpi_status 165acpi_evaluate_object(acpi_handle handle, 166 acpi_string pathname, 167 struct acpi_object_list *external_params, 168 struct acpi_buffer *return_buffer) 169{ 170 acpi_status status; 171 struct acpi_evaluate_info *info; 172 acpi_size buffer_space_needed; 173 u32 i; 174 175 ACPI_FUNCTION_TRACE(acpi_evaluate_object); 176 177 /* Allocate and initialize the evaluation information block */ 178 179 info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); 180 if (!info) { 181 return_ACPI_STATUS(AE_NO_MEMORY); 182 } 183 184 info->pathname = pathname; 185 info->parameter_type = ACPI_PARAM_ARGS; 186 187 /* Convert and validate the device handle */ 188 189 info->prefix_node = acpi_ns_map_handle_to_node(handle); 190 if (!info->prefix_node) { 191 status = AE_BAD_PARAMETER; 192 goto cleanup; 193 } 194 195 /* 196 * If there are parameters to be passed to a control method, the external 197 * objects must all be converted to internal objects 198 */ 199 if (external_params && external_params->count) { 200 /* 201 * Allocate a new parameter block for the internal objects 202 * Add 1 to count to allow for null terminated internal list 203 */ 204 info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) 205 external_params-> 206 count + 207 1) * sizeof(void *)); 208 if (!info->parameters) { 209 status = AE_NO_MEMORY; 210 goto cleanup; 211 } 212 213 /* Convert each external object in the list to an internal object */ 214 215 for (i = 0; i < external_params->count; i++) { 216 status = 217 acpi_ut_copy_eobject_to_iobject(&external_params-> 218 pointer[i], 219 &info-> 220 parameters[i]); 221 if (ACPI_FAILURE(status)) { 222 goto cleanup; 223 } 224 } 225 info->parameters[external_params->count] = NULL; 226 } 227 228 /* 229 * Three major cases: 230 * 1) Fully qualified pathname 231 * 2) No handle, not fully qualified pathname (error) 232 * 3) Valid handle 233 */ 234 if ((pathname) && (acpi_ns_valid_root_prefix(pathname[0]))) { 235 236 /* The path is fully qualified, just evaluate by name */ 237 238 info->prefix_node = NULL; 239 status = acpi_ns_evaluate(info); 240 } else if (!handle) { 241 /* 242 * A handle is optional iff a fully qualified pathname is specified. 243 * Since we've already handled fully qualified names above, this is 244 * an error 245 */ 246 if (!pathname) { 247 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 248 "Both Handle and Pathname are NULL")); 249 } else { 250 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 251 "Null Handle with relative pathname [%s]", 252 pathname)); 253 } 254 255 status = AE_BAD_PARAMETER; 256 } else { 257 /* We have a namespace a node and a possible relative path */ 258 259 status = acpi_ns_evaluate(info); 260 } 261 262 /* 263 * If we are expecting a return value, and all went well above, 264 * copy the return value to an external object. 265 */ 266 if (return_buffer) { 267 if (!info->return_object) { 268 return_buffer->length = 0; 269 } else { 270 if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) == 271 ACPI_DESC_TYPE_NAMED) { 272 /* 273 * If we received a NS Node as a return object, this means that 274 * the object we are evaluating has nothing interesting to 275 * return (such as a mutex, etc.) We return an error because 276 * these types are essentially unsupported by this interface. 277 * We don't check up front because this makes it easier to add 278 * support for various types at a later date if necessary. 279 */ 280 status = AE_TYPE; 281 info->return_object = NULL; /* No need to delete a NS Node */ 282 return_buffer->length = 0; 283 } 284 285 if (ACPI_SUCCESS(status)) { 286 287 /* Get the size of the returned object */ 288 289 status = 290 acpi_ut_get_object_size(info->return_object, 291 &buffer_space_needed); 292 if (ACPI_SUCCESS(status)) { 293 294 /* Validate/Allocate/Clear caller buffer */ 295 296 status = 297 acpi_ut_initialize_buffer 298 (return_buffer, 299 buffer_space_needed); 300 if (ACPI_FAILURE(status)) { 301 /* 302 * Caller's buffer is too small or a new one can't 303 * be allocated 304 */ 305 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 306 "Needed buffer size %X, %s\n", 307 (u32) 308 buffer_space_needed, 309 acpi_format_exception 310 (status))); 311 } else { 312 /* We have enough space for the object, build it */ 313 314 status = 315 acpi_ut_copy_iobject_to_eobject 316 (info->return_object, 317 return_buffer); 318 } 319 } 320 } 321 } 322 } 323 324 if (info->return_object) { 325 /* 326 * Delete the internal return object. NOTE: Interpreter must be 327 * locked to avoid race condition. 328 */ 329 acpi_ex_enter_interpreter(); 330 331 /* Remove one reference on the return object (should delete it) */ 332 333 acpi_ut_remove_reference(info->return_object); 334 acpi_ex_exit_interpreter(); 335 } 336 337 cleanup: 338 339 /* Free the input parameter list (if we created one) */ 340 341 if (info->parameters) { 342 343 /* Free the allocated parameter block */ 344 345 acpi_ut_delete_internal_object_list(info->parameters); 346 } 347 348 ACPI_FREE(info); 349 return_ACPI_STATUS(status); 350} 351 352ACPI_EXPORT_SYMBOL(acpi_evaluate_object) 353 354/******************************************************************************* 355 * 356 * FUNCTION: acpi_walk_namespace 357 * 358 * PARAMETERS: Type - acpi_object_type to search for 359 * start_object - Handle in namespace where search begins 360 * max_depth - Depth to which search is to reach 361 * user_function - Called when an object of "Type" is found 362 * Context - Passed to user function 363 * return_value - Location where return value of 364 * user_function is put if terminated early 365 * 366 * RETURNS Return value from the user_function if terminated early. 367 * Otherwise, returns NULL. 368 * 369 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, 370 * starting (and ending) at the object specified by start_handle. 371 * The user_function is called whenever an object that matches 372 * the type parameter is found. If the user function returns 373 * a non-zero value, the search is terminated immediately and this 374 * value is returned to the caller. 375 * 376 * The point of this procedure is to provide a generic namespace 377 * walk routine that can be called from multiple places to 378 * provide multiple services; the User Function can be tailored 379 * to each task, whether it is a print function, a compare 380 * function, etc. 381 * 382 ******************************************************************************/ 383acpi_status 384acpi_walk_namespace(acpi_object_type type, 385 acpi_handle start_object, 386 u32 max_depth, 387 acpi_walk_callback user_function, 388 void *context, void **return_value) 389{ 390 acpi_status status; 391 392 ACPI_FUNCTION_TRACE(acpi_walk_namespace); 393 394 /* Parameter validation */ 395 396 if ((type > ACPI_TYPE_LOCAL_MAX) || (!max_depth) || (!user_function)) { 397 return_ACPI_STATUS(AE_BAD_PARAMETER); 398 } 399 400 /* 401 * Lock the namespace around the walk. 402 * The namespace will be unlocked/locked around each call 403 * to the user function - since this function 404 * must be allowed to make Acpi calls itself. 405 */ 406 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 407 if (ACPI_FAILURE(status)) { 408 return_ACPI_STATUS(status); 409 } 410 411 status = acpi_ns_walk_namespace(type, start_object, max_depth, 412 ACPI_NS_WALK_UNLOCK, 413 user_function, context, return_value); 414 415 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 416 return_ACPI_STATUS(status); 417} 418 419ACPI_EXPORT_SYMBOL(acpi_walk_namespace) 420 421/******************************************************************************* 422 * 423 * FUNCTION: acpi_ns_get_device_callback 424 * 425 * PARAMETERS: Callback from acpi_get_device 426 * 427 * RETURN: Status 428 * 429 * DESCRIPTION: Takes callbacks from walk_namespace and filters out all non- 430 * present devices, or if they specified a HID, it filters based 431 * on that. 432 * 433 ******************************************************************************/ 434static acpi_status 435acpi_ns_get_device_callback(acpi_handle obj_handle, 436 u32 nesting_level, 437 void *context, void **return_value) 438{ 439 struct acpi_get_devices_info *info = context; 440 acpi_status status; 441 struct acpi_namespace_node *node; 442 u32 flags; 443 struct acpi_device_id hid; 444 struct acpi_compatible_id_list *cid; 445 acpi_native_uint i; 446 447 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 448 if (ACPI_FAILURE(status)) { 449 return (status); 450 } 451 452 node = acpi_ns_map_handle_to_node(obj_handle); 453 status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 454 if (ACPI_FAILURE(status)) { 455 return (status); 456 } 457 458 if (!node) { 459 return (AE_BAD_PARAMETER); 460 } 461 462 /* Run _STA to determine if device is present */ 463 464 status = acpi_ut_execute_STA(node, &flags); 465 if (ACPI_FAILURE(status)) { 466 return (AE_CTRL_DEPTH); 467 } 468 469 if (!(flags & ACPI_STA_DEVICE_PRESENT)) { 470 471 /* Don't examine children of the device if not present */ 472 473 return (AE_CTRL_DEPTH); 474 } 475 476 /* Filter based on device HID & CID */ 477 478 if (info->hid != NULL) { 479 status = acpi_ut_execute_HID(node, &hid); 480 if (status == AE_NOT_FOUND) { 481 return (AE_OK); 482 } else if (ACPI_FAILURE(status)) { 483 return (AE_CTRL_DEPTH); 484 } 485 486 if (ACPI_STRNCMP(hid.value, info->hid, sizeof(hid.value)) != 0) { 487 488 /* Get the list of Compatible IDs */ 489 490 status = acpi_ut_execute_CID(node, &cid); 491 if (status == AE_NOT_FOUND) { 492 return (AE_OK); 493 } else if (ACPI_FAILURE(status)) { 494 return (AE_CTRL_DEPTH); 495 } 496 497 /* Walk the CID list */ 498 499 for (i = 0; i < cid->count; i++) { 500 if (ACPI_STRNCMP(cid->id[i].value, info->hid, 501 sizeof(struct 502 acpi_compatible_id)) != 503 0) { 504 ACPI_FREE(cid); 505 return (AE_OK); 506 } 507 } 508 ACPI_FREE(cid); 509 } 510 } 511 512 status = info->user_function(obj_handle, nesting_level, info->context, 513 return_value); 514 return (status); 515} 516 517/******************************************************************************* 518 * 519 * FUNCTION: acpi_get_devices 520 * 521 * PARAMETERS: HID - HID to search for. Can be NULL. 522 * user_function - Called when a matching object is found 523 * Context - Passed to user function 524 * return_value - Location where return value of 525 * user_function is put if terminated early 526 * 527 * RETURNS Return value from the user_function if terminated early. 528 * Otherwise, returns NULL. 529 * 530 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, 531 * starting (and ending) at the object specified by start_handle. 532 * The user_function is called whenever an object of type 533 * Device is found. If the user function returns 534 * a non-zero value, the search is terminated immediately and this 535 * value is returned to the caller. 536 * 537 * This is a wrapper for walk_namespace, but the callback performs 538 * additional filtering. Please see acpi_get_device_callback. 539 * 540 ******************************************************************************/ 541 542acpi_status 543acpi_get_devices(char *HID, 544 acpi_walk_callback user_function, 545 void *context, void **return_value) 546{ 547 acpi_status status; 548 struct acpi_get_devices_info info; 549 550 ACPI_FUNCTION_TRACE(acpi_get_devices); 551 552 /* Parameter validation */ 553 554 if (!user_function) { 555 return_ACPI_STATUS(AE_BAD_PARAMETER); 556 } 557 558 /* 559 * We're going to call their callback from OUR callback, so we need 560 * to know what it is, and their context parameter. 561 */ 562 info.hid = HID; 563 info.context = context; 564 info.user_function = user_function; 565 566 /* 567 * Lock the namespace around the walk. 568 * The namespace will be unlocked/locked around each call 569 * to the user function - since this function 570 * must be allowed to make Acpi calls itself. 571 */ 572 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 573 if (ACPI_FAILURE(status)) { 574 return_ACPI_STATUS(status); 575 } 576 577 status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 578 ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, 579 acpi_ns_get_device_callback, &info, 580 return_value); 581 582 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 583 return_ACPI_STATUS(status); 584} 585 586ACPI_EXPORT_SYMBOL(acpi_get_devices) 587 588/******************************************************************************* 589 * 590 * FUNCTION: acpi_attach_data 591 * 592 * PARAMETERS: obj_handle - Namespace node 593 * Handler - Handler for this attachment 594 * Data - Pointer to data to be attached 595 * 596 * RETURN: Status 597 * 598 * DESCRIPTION: Attach arbitrary data and handler to a namespace node. 599 * 600 ******************************************************************************/ 601acpi_status 602acpi_attach_data(acpi_handle obj_handle, 603 acpi_object_handler handler, void *data) 604{ 605 struct acpi_namespace_node *node; 606 acpi_status status; 607 608 /* Parameter validation */ 609 610 if (!obj_handle || !handler || !data) { 611 return (AE_BAD_PARAMETER); 612 } 613 614 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 615 if (ACPI_FAILURE(status)) { 616 return (status); 617 } 618 619 /* Convert and validate the handle */ 620 621 node = acpi_ns_map_handle_to_node(obj_handle); 622 if (!node) { 623 status = AE_BAD_PARAMETER; 624 goto unlock_and_exit; 625 } 626 627 status = acpi_ns_attach_data(node, handler, data); 628 629 unlock_and_exit: 630 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 631 return (status); 632} 633 634ACPI_EXPORT_SYMBOL(acpi_attach_data) 635 636/******************************************************************************* 637 * 638 * FUNCTION: acpi_detach_data 639 * 640 * PARAMETERS: obj_handle - Namespace node handle 641 * Handler - Handler used in call to acpi_attach_data 642 * 643 * RETURN: Status 644 * 645 * DESCRIPTION: Remove data that was previously attached to a node. 646 * 647 ******************************************************************************/ 648acpi_status 649acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler) 650{ 651 struct acpi_namespace_node *node; 652 acpi_status status; 653 654 /* Parameter validation */ 655 656 if (!obj_handle || !handler) { 657 return (AE_BAD_PARAMETER); 658 } 659 660 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 661 if (ACPI_FAILURE(status)) { 662 return (status); 663 } 664 665 /* Convert and validate the handle */ 666 667 node = acpi_ns_map_handle_to_node(obj_handle); 668 if (!node) { 669 status = AE_BAD_PARAMETER; 670 goto unlock_and_exit; 671 } 672 673 status = acpi_ns_detach_data(node, handler); 674 675 unlock_and_exit: 676 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 677 return (status); 678} 679 680ACPI_EXPORT_SYMBOL(acpi_detach_data) 681 682/******************************************************************************* 683 * 684 * FUNCTION: acpi_get_data 685 * 686 * PARAMETERS: obj_handle - Namespace node 687 * Handler - Handler used in call to attach_data 688 * Data - Where the data is returned 689 * 690 * RETURN: Status 691 * 692 * DESCRIPTION: Retrieve data that was previously attached to a namespace node. 693 * 694 ******************************************************************************/ 695acpi_status 696acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) 697{ 698 struct acpi_namespace_node *node; 699 acpi_status status; 700 701 /* Parameter validation */ 702 703 if (!obj_handle || !handler || !data) { 704 return (AE_BAD_PARAMETER); 705 } 706 707 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 708 if (ACPI_FAILURE(status)) { 709 return (status); 710 } 711 712 /* Convert and validate the handle */ 713 714 node = acpi_ns_map_handle_to_node(obj_handle); 715 if (!node) { 716 status = AE_BAD_PARAMETER; 717 goto unlock_and_exit; 718 } 719 720 status = acpi_ns_get_attached_data(node, handler, data); 721 722 unlock_and_exit: 723 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 724 return (status); 725} 726 727ACPI_EXPORT_SYMBOL(acpi_get_data) 728