1/******************************************************************************* 2 * 3 * Module Name: nsxfobj - Public interfaces to the ACPI subsystem 4 * ACPI Object oriented interfaces 5 * $Revision: 1.1.1.1 $ 6 * 7 ******************************************************************************/ 8 9/* 10 * Copyright (C) 2000, 2001 R. Byron Moore 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 */ 26 27 28#include "acpi.h" 29#include "acinterp.h" 30#include "acnamesp.h" 31#include "acdispat.h" 32 33 34#define _COMPONENT ACPI_NAMESPACE 35 MODULE_NAME ("nsxfobj") 36 37 38/******************************************************************************* 39 * 40 * FUNCTION: Acpi_evaluate_object 41 * 42 * PARAMETERS: Handle - Object handle (optional) 43 * *Pathname - Object pathname (optional) 44 * **External_params - List of parameters to pass to method, 45 * terminated by NULL. May be NULL 46 * if no parameters are being passed. 47 * *Return_buffer - Where to put method's return value (if 48 * any). If NULL, no value is returned. 49 * 50 * RETURN: Status 51 * 52 * DESCRIPTION: Find and evaluate the given object, passing the given 53 * parameters if necessary. One of "Handle" or "Pathname" must 54 * be valid (non-null) 55 * 56 ******************************************************************************/ 57 58acpi_status 59acpi_evaluate_object ( 60 acpi_handle handle, 61 acpi_string pathname, 62 acpi_object_list *external_params, 63 acpi_buffer *return_buffer) 64{ 65 acpi_status status; 66 acpi_operand_object **internal_params = NULL; 67 acpi_operand_object *internal_return_obj = NULL; 68 u32 buffer_space_needed; 69 u32 user_buffer_length; 70 u32 i; 71 72 73 FUNCTION_TRACE ("Acpi_evaluate_object"); 74 75 76 /* 77 * If there are parameters to be passed to the object 78 * (which must be a control method), the external objects 79 * must be converted to internal objects 80 */ 81 if (external_params && external_params->count) { 82 /* 83 * Allocate a new parameter block for the internal objects 84 * Add 1 to count to allow for null terminated internal list 85 */ 86 internal_params = ACPI_MEM_CALLOCATE ((external_params->count + 1) * sizeof (void *)); 87 if (!internal_params) { 88 return_ACPI_STATUS (AE_NO_MEMORY); 89 } 90 91 92 /* 93 * Convert each external object in the list to an 94 * internal object 95 */ 96 for (i = 0; i < external_params->count; i++) { 97 status = acpi_ut_copy_eobject_to_iobject (&external_params->pointer[i], 98 &internal_params[i]); 99 100 if (ACPI_FAILURE (status)) { 101 acpi_ut_delete_internal_object_list (internal_params); 102 return_ACPI_STATUS (status); 103 } 104 } 105 internal_params[external_params->count] = NULL; 106 } 107 108 109 /* 110 * Three major cases: 111 * 1) Fully qualified pathname 112 * 2) No handle, not fully qualified pathname (error) 113 * 3) Valid handle 114 */ 115 if ((pathname) && 116 (acpi_ns_valid_root_prefix (pathname[0]))) { 117 /* 118 * The path is fully qualified, just evaluate by name 119 */ 120 status = acpi_ns_evaluate_by_name (pathname, internal_params, &internal_return_obj); 121 } 122 123 else if (!handle) { 124 /* 125 * A handle is optional iff a fully qualified pathname 126 * is specified. Since we've already handled fully 127 * qualified names above, this is an error 128 */ 129 if (!pathname) { 130 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Both Handle and Pathname are NULL\n")); 131 } 132 133 else { 134 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Handle is NULL and Pathname is relative\n")); 135 } 136 137 status = AE_BAD_PARAMETER; 138 } 139 140 else { 141 /* 142 * We get here if we have a handle -- and if we have a 143 * pathname it is relative. The handle will be validated 144 * in the lower procedures 145 */ 146 if (!pathname) { 147 /* 148 * The null pathname case means the handle is for 149 * the actual object to be evaluated 150 */ 151 status = acpi_ns_evaluate_by_handle (handle, internal_params, &internal_return_obj); 152 } 153 154 else { 155 /* 156 * Both a Handle and a relative Pathname 157 */ 158 status = acpi_ns_evaluate_relative (handle, pathname, internal_params, 159 &internal_return_obj); 160 } 161 } 162 163 164 /* 165 * If we are expecting a return value, and all went well above, 166 * copy the return value to an external object. 167 */ 168 169 if (return_buffer) { 170 user_buffer_length = return_buffer->length; 171 return_buffer->length = 0; 172 173 if (internal_return_obj) { 174 if (VALID_DESCRIPTOR_TYPE (internal_return_obj, ACPI_DESC_TYPE_NAMED)) { 175 /* 176 * If we got an Node as a return object, 177 * this means the object we are evaluating 178 * has nothing interesting to return (such 179 * as a mutex, etc.) We return an error 180 * because these types are essentially 181 * unsupported by this interface. We 182 * don't check up front because this makes 183 * it easier to add support for various 184 * types at a later date if necessary. 185 */ 186 status = AE_TYPE; 187 internal_return_obj = NULL; /* No need to delete an Node */ 188 } 189 190 if (ACPI_SUCCESS (status)) { 191 /* 192 * Find out how large a buffer is needed 193 * to contain the returned object 194 */ 195 status = acpi_ut_get_object_size (internal_return_obj, 196 &buffer_space_needed); 197 if (ACPI_SUCCESS (status)) { 198 /* 199 * Check if there is enough room in the 200 * caller's buffer 201 */ 202 if (user_buffer_length < buffer_space_needed) { 203 /* 204 * Caller's buffer is too small, can't 205 * give him partial results fail the call 206 * but return the buffer size needed 207 */ 208 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 209 "Needed buffer size %X, received %X\n", 210 buffer_space_needed, user_buffer_length)); 211 212 return_buffer->length = buffer_space_needed; 213 status = AE_BUFFER_OVERFLOW; 214 } 215 216 else { 217 /* 218 * We have enough space for the object, build it 219 */ 220 status = acpi_ut_copy_iobject_to_eobject (internal_return_obj, 221 return_buffer); 222 return_buffer->length = buffer_space_needed; 223 } 224 } 225 } 226 } 227 } 228 229 230 /* Delete the return and parameter objects */ 231 232 if (internal_return_obj) { 233 /* 234 * Delete the internal return object. (Or at least 235 * decrement the reference count by one) 236 */ 237 acpi_ut_remove_reference (internal_return_obj); 238 } 239 240 /* 241 * Free the input parameter list (if we created one), 242 */ 243 if (internal_params) { 244 /* Free the allocated parameter block */ 245 246 acpi_ut_delete_internal_object_list (internal_params); 247 } 248 249 return_ACPI_STATUS (status); 250} 251 252 253/******************************************************************************* 254 * 255 * FUNCTION: Acpi_get_next_object 256 * 257 * PARAMETERS: Type - Type of object to be searched for 258 * Parent - Parent object whose children we are getting 259 * Last_child - Previous child that was found. 260 * The NEXT child will be returned 261 * Ret_handle - Where handle to the next object is placed 262 * 263 * RETURN: Status 264 * 265 * DESCRIPTION: Return the next peer object within the namespace. If Handle is 266 * valid, Scope is ignored. Otherwise, the first object within 267 * Scope is returned. 268 * 269 ******************************************************************************/ 270 271acpi_status 272acpi_get_next_object ( 273 acpi_object_type type, 274 acpi_handle parent, 275 acpi_handle child, 276 acpi_handle *ret_handle) 277{ 278 acpi_status status = AE_OK; 279 acpi_namespace_node *node; 280 acpi_namespace_node *parent_node = NULL; 281 acpi_namespace_node *child_node = NULL; 282 283 284 /* Parameter validation */ 285 286 if (type > ACPI_TYPE_MAX) { 287 return (AE_BAD_PARAMETER); 288 } 289 290 acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); 291 292 /* If null handle, use the parent */ 293 294 if (!child) { 295 /* Start search at the beginning of the specified scope */ 296 297 parent_node = acpi_ns_map_handle_to_node (parent); 298 if (!parent_node) { 299 status = AE_BAD_PARAMETER; 300 goto unlock_and_exit; 301 } 302 } 303 304 /* Non-null handle, ignore the parent */ 305 306 else { 307 /* Convert and validate the handle */ 308 309 child_node = acpi_ns_map_handle_to_node (child); 310 if (!child_node) { 311 status = AE_BAD_PARAMETER; 312 goto unlock_and_exit; 313 } 314 } 315 316 317 /* Internal function does the real work */ 318 319 node = acpi_ns_get_next_node ((acpi_object_type8) type, 320 parent_node, child_node); 321 if (!node) { 322 status = AE_NOT_FOUND; 323 goto unlock_and_exit; 324 } 325 326 if (ret_handle) { 327 *ret_handle = acpi_ns_convert_entry_to_handle (node); 328 } 329 330 331unlock_and_exit: 332 333 acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); 334 return (status); 335} 336 337 338/******************************************************************************* 339 * 340 * FUNCTION: Acpi_get_type 341 * 342 * PARAMETERS: Handle - Handle of object whose type is desired 343 * *Ret_type - Where the type will be placed 344 * 345 * RETURN: Status 346 * 347 * DESCRIPTION: This routine returns the type associatd with a particular handle 348 * 349 ******************************************************************************/ 350 351acpi_status 352acpi_get_type ( 353 acpi_handle handle, 354 acpi_object_type *ret_type) 355{ 356 acpi_namespace_node *node; 357 358 359 /* Parameter Validation */ 360 361 if (!ret_type) { 362 return (AE_BAD_PARAMETER); 363 } 364 365 /* 366 * Special case for the predefined Root Node 367 * (return type ANY) 368 */ 369 if (handle == ACPI_ROOT_OBJECT) { 370 *ret_type = ACPI_TYPE_ANY; 371 return (AE_OK); 372 } 373 374 acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); 375 376 /* Convert and validate the handle */ 377 378 node = acpi_ns_map_handle_to_node (handle); 379 if (!node) { 380 acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); 381 return (AE_BAD_PARAMETER); 382 } 383 384 *ret_type = node->type; 385 386 387 acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); 388 return (AE_OK); 389} 390 391 392/******************************************************************************* 393 * 394 * FUNCTION: Acpi_get_parent 395 * 396 * PARAMETERS: Handle - Handle of object whose parent is desired 397 * Ret_handle - Where the parent handle will be placed 398 * 399 * RETURN: Status 400 * 401 * DESCRIPTION: Returns a handle to the parent of the object represented by 402 * Handle. 403 * 404 ******************************************************************************/ 405 406acpi_status 407acpi_get_parent ( 408 acpi_handle handle, 409 acpi_handle *ret_handle) 410{ 411 acpi_namespace_node *node; 412 acpi_status status = AE_OK; 413 414 415 if (!ret_handle) { 416 return (AE_BAD_PARAMETER); 417 } 418 419 /* Special case for the predefined Root Node (no parent) */ 420 421 if (handle == ACPI_ROOT_OBJECT) { 422 return (AE_NULL_ENTRY); 423 } 424 425 426 acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); 427 428 /* Convert and validate the handle */ 429 430 node = acpi_ns_map_handle_to_node (handle); 431 if (!node) { 432 status = AE_BAD_PARAMETER; 433 goto unlock_and_exit; 434 } 435 436 437 /* Get the parent entry */ 438 439 *ret_handle = 440 acpi_ns_convert_entry_to_handle (acpi_ns_get_parent_object (node)); 441 442 /* Return exeption if parent is null */ 443 444 if (!acpi_ns_get_parent_object (node)) { 445 status = AE_NULL_ENTRY; 446 } 447 448 449unlock_and_exit: 450 451 acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); 452 return (status); 453} 454 455 456/******************************************************************************* 457 * 458 * FUNCTION: Acpi_walk_namespace 459 * 460 * PARAMETERS: Type - acpi_object_type to search for 461 * Start_object - Handle in namespace where search begins 462 * Max_depth - Depth to which search is to reach 463 * User_function - Called when an object of "Type" is found 464 * Context - Passed to user function 465 * Return_value - Location where return value of 466 * User_function is put if terminated early 467 * 468 * RETURNS Return value from the User_function if terminated early. 469 * Otherwise, returns NULL. 470 * 471 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, 472 * starting (and ending) at the object specified by Start_handle. 473 * The User_function is called whenever an object that matches 474 * the type parameter is found. If the user function returns 475 * a non-zero value, the search is terminated immediately and this 476 * value is returned to the caller. 477 * 478 * The point of this procedure is to provide a generic namespace 479 * walk routine that can be called from multiple places to 480 * provide multiple services; the User Function can be tailored 481 * to each task, whether it is a print function, a compare 482 * function, etc. 483 * 484 ******************************************************************************/ 485 486acpi_status 487acpi_walk_namespace ( 488 acpi_object_type type, 489 acpi_handle start_object, 490 u32 max_depth, 491 acpi_walk_callback user_function, 492 void *context, 493 void **return_value) 494{ 495 acpi_status status; 496 497 498 FUNCTION_TRACE ("Acpi_walk_namespace"); 499 500 501 /* Parameter validation */ 502 503 if ((type > ACPI_TYPE_MAX) || 504 (!max_depth) || 505 (!user_function)) { 506 return_ACPI_STATUS (AE_BAD_PARAMETER); 507 } 508 509 /* 510 * Lock the namespace around the walk. 511 * The namespace will be unlocked/locked around each call 512 * to the user function - since this function 513 * must be allowed to make Acpi calls itself. 514 */ 515 acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); 516 status = acpi_ns_walk_namespace ((acpi_object_type8) type, start_object, 517 max_depth, NS_WALK_UNLOCK, user_function, context, 518 return_value); 519 520 acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); 521 522 return_ACPI_STATUS (status); 523} 524 525 526/******************************************************************************* 527 * 528 * FUNCTION: Acpi_ns_get_device_callback 529 * 530 * PARAMETERS: Callback from Acpi_get_device 531 * 532 * RETURN: Status 533 * 534 * DESCRIPTION: Takes callbacks from Walk_namespace and filters out all non- 535 * present devices, or if they specified a HID, it filters based 536 * on that. 537 * 538 ******************************************************************************/ 539 540static acpi_status 541acpi_ns_get_device_callback ( 542 acpi_handle obj_handle, 543 u32 nesting_level, 544 void *context, 545 void **return_value) 546{ 547 acpi_status status; 548 acpi_namespace_node *node; 549 u32 flags; 550 acpi_device_id device_id; 551 acpi_get_devices_info *info; 552 553 554 info = context; 555 556 acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); 557 node = acpi_ns_map_handle_to_node (obj_handle); 558 acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); 559 560 if (!node) { 561 return (AE_BAD_PARAMETER); 562 } 563 564 /* 565 * Run _STA to determine if device is present 566 */ 567 status = acpi_ut_execute_STA (node, &flags); 568 if (ACPI_FAILURE (status)) { 569 return (AE_CTRL_DEPTH); 570 } 571 572 if (!(flags & 0x01)) { 573 /* don't return at the device or children of the device if not there */ 574 return (AE_CTRL_DEPTH); 575 } 576 577 /* 578 * Filter based on device HID 579 */ 580 if (info->hid != NULL) { 581 status = acpi_ut_execute_HID (node, &device_id); 582 if (status == AE_NOT_FOUND) { 583 return (AE_OK); 584 } 585 586 else if (ACPI_FAILURE (status)) { 587 return (AE_CTRL_DEPTH); 588 } 589 590 if (STRNCMP (device_id.buffer, info->hid, sizeof (device_id.buffer)) != 0) { 591 return (AE_OK); 592 } 593 } 594 595 info->user_function (obj_handle, nesting_level, info->context, return_value); 596 return (AE_OK); 597} 598 599 600/******************************************************************************* 601 * 602 * FUNCTION: Acpi_get_devices 603 * 604 * PARAMETERS: HID - HID to search for. Can be NULL. 605 * User_function - Called when a matching object is found 606 * Context - Passed to user function 607 * Return_value - Location where return value of 608 * User_function is put if terminated early 609 * 610 * RETURNS Return value from the User_function if terminated early. 611 * Otherwise, returns NULL. 612 * 613 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, 614 * starting (and ending) at the object specified by Start_handle. 615 * The User_function is called whenever an object that matches 616 * the type parameter is found. If the user function returns 617 * a non-zero value, the search is terminated immediately and this 618 * value is returned to the caller. 619 * 620 * This is a wrapper for Walk_namespace, but the callback performs 621 * additional filtering. Please see Acpi_get_device_callback. 622 * 623 ******************************************************************************/ 624 625acpi_status 626acpi_get_devices ( 627 NATIVE_CHAR *HID, 628 acpi_walk_callback user_function, 629 void *context, 630 void **return_value) 631{ 632 acpi_status status; 633 acpi_get_devices_info info; 634 635 636 FUNCTION_TRACE ("Acpi_get_devices"); 637 638 639 /* Parameter validation */ 640 641 if (!user_function) { 642 return_ACPI_STATUS (AE_BAD_PARAMETER); 643 } 644 645 /* 646 * We're going to call their callback from OUR callback, so we need 647 * to know what it is, and their context parameter. 648 */ 649 info.context = context; 650 info.user_function = user_function; 651 info.hid = HID; 652 653 /* 654 * Lock the namespace around the walk. 655 * The namespace will be unlocked/locked around each call 656 * to the user function - since this function 657 * must be allowed to make Acpi calls itself. 658 */ 659 acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); 660 status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, 661 ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 662 NS_WALK_UNLOCK, 663 acpi_ns_get_device_callback, &info, 664 return_value); 665 666 acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); 667 668 return_ACPI_STATUS (status); 669} 670