Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /*******************************************************************************
0003  *
0004  * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
0005  *                         ACPI Object evaluation interfaces
0006  *
0007  ******************************************************************************/
0008 
0009 #define EXPORT_ACPI_INTERFACES
0010 
0011 #include <acpi/acpi.h>
0012 #include "accommon.h"
0013 #include "acnamesp.h"
0014 #include "acinterp.h"
0015 
0016 #define _COMPONENT          ACPI_NAMESPACE
0017 ACPI_MODULE_NAME("nsxfeval")
0018 
0019 /* Local prototypes */
0020 static void acpi_ns_resolve_references(struct acpi_evaluate_info *info);
0021 
0022 /*******************************************************************************
0023  *
0024  * FUNCTION:    acpi_evaluate_object_typed
0025  *
0026  * PARAMETERS:  handle              - Object handle (optional)
0027  *              pathname            - Object pathname (optional)
0028  *              external_params     - List of parameters to pass to a method,
0029  *                                    terminated by NULL. May be NULL
0030  *                                    if no parameters are being passed.
0031  *              return_buffer       - Where to put the object's return value (if
0032  *                                    any). If NULL, no value is returned.
0033  *              return_type         - Expected type of return object
0034  *
0035  * RETURN:      Status
0036  *
0037  * DESCRIPTION: Find and evaluate the given object, passing the given
0038  *              parameters if necessary. One of "Handle" or "Pathname" must
0039  *              be valid (non-null)
0040  *
0041  ******************************************************************************/
0042 
0043 acpi_status
0044 acpi_evaluate_object_typed(acpi_handle handle,
0045                acpi_string pathname,
0046                struct acpi_object_list *external_params,
0047                struct acpi_buffer *return_buffer,
0048                acpi_object_type return_type)
0049 {
0050     acpi_status status;
0051     u8 free_buffer_on_error = FALSE;
0052     acpi_handle target_handle;
0053     char *full_pathname;
0054 
0055     ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed);
0056 
0057     /* Return buffer must be valid */
0058 
0059     if (!return_buffer) {
0060         return_ACPI_STATUS(AE_BAD_PARAMETER);
0061     }
0062 
0063     if (return_buffer->length == ACPI_ALLOCATE_BUFFER) {
0064         free_buffer_on_error = TRUE;
0065     }
0066 
0067     /* Get a handle here, in order to build an error message if needed */
0068 
0069     target_handle = handle;
0070     if (pathname) {
0071         status = acpi_get_handle(handle, pathname, &target_handle);
0072         if (ACPI_FAILURE(status)) {
0073             return_ACPI_STATUS(status);
0074         }
0075     }
0076 
0077     full_pathname = acpi_ns_get_external_pathname(target_handle);
0078     if (!full_pathname) {
0079         return_ACPI_STATUS(AE_NO_MEMORY);
0080     }
0081 
0082     /* Evaluate the object */
0083 
0084     status = acpi_evaluate_object(target_handle, NULL, external_params,
0085                       return_buffer);
0086     if (ACPI_FAILURE(status)) {
0087         goto exit;
0088     }
0089 
0090     /* Type ANY means "don't care about return value type" */
0091 
0092     if (return_type == ACPI_TYPE_ANY) {
0093         goto exit;
0094     }
0095 
0096     if (return_buffer->length == 0) {
0097 
0098         /* Error because caller specifically asked for a return value */
0099 
0100         ACPI_ERROR((AE_INFO, "%s did not return any object",
0101                 full_pathname));
0102         status = AE_NULL_OBJECT;
0103         goto exit;
0104     }
0105 
0106     /* Examine the object type returned from evaluate_object */
0107 
0108     if (((union acpi_object *)return_buffer->pointer)->type == return_type) {
0109         goto exit;
0110     }
0111 
0112     /* Return object type does not match requested type */
0113 
0114     ACPI_ERROR((AE_INFO,
0115             "Incorrect return type from %s - received [%s], requested [%s]",
0116             full_pathname,
0117             acpi_ut_get_type_name(((union acpi_object *)return_buffer->
0118                        pointer)->type),
0119             acpi_ut_get_type_name(return_type)));
0120 
0121     if (free_buffer_on_error) {
0122         /*
0123          * Free a buffer created via ACPI_ALLOCATE_BUFFER.
0124          * Note: We use acpi_os_free here because acpi_os_allocate was used
0125          * to allocate the buffer. This purposefully bypasses the
0126          * (optionally enabled) allocation tracking mechanism since we
0127          * only want to track internal allocations.
0128          */
0129         acpi_os_free(return_buffer->pointer);
0130         return_buffer->pointer = NULL;
0131     }
0132 
0133     return_buffer->length = 0;
0134     status = AE_TYPE;
0135 
0136 exit:
0137     ACPI_FREE(full_pathname);
0138     return_ACPI_STATUS(status);
0139 }
0140 
0141 ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed)
0142 
0143 /*******************************************************************************
0144  *
0145  * FUNCTION:    acpi_evaluate_object
0146  *
0147  * PARAMETERS:  handle              - Object handle (optional)
0148  *              pathname            - Object pathname (optional)
0149  *              external_params     - List of parameters to pass to method,
0150  *                                    terminated by NULL. May be NULL
0151  *                                    if no parameters are being passed.
0152  *              return_buffer       - Where to put method's return value (if
0153  *                                    any). If NULL, no value is returned.
0154  *
0155  * RETURN:      Status
0156  *
0157  * DESCRIPTION: Find and evaluate the given object, passing the given
0158  *              parameters if necessary. One of "Handle" or "Pathname" must
0159  *              be valid (non-null)
0160  *
0161  ******************************************************************************/
0162 acpi_status
0163 acpi_evaluate_object(acpi_handle handle,
0164              acpi_string pathname,
0165              struct acpi_object_list *external_params,
0166              struct acpi_buffer *return_buffer)
0167 {
0168     acpi_status status;
0169     struct acpi_evaluate_info *info;
0170     acpi_size buffer_space_needed;
0171     u32 i;
0172 
0173     ACPI_FUNCTION_TRACE(acpi_evaluate_object);
0174 
0175     /* Allocate and initialize the evaluation information block */
0176 
0177     info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
0178     if (!info) {
0179         return_ACPI_STATUS(AE_NO_MEMORY);
0180     }
0181 
0182     /* Convert and validate the device handle */
0183 
0184     info->prefix_node = acpi_ns_validate_handle(handle);
0185     if (!info->prefix_node) {
0186         status = AE_BAD_PARAMETER;
0187         goto cleanup;
0188     }
0189 
0190     /*
0191      * Get the actual namespace node for the target object.
0192      * Handles these cases:
0193      *
0194      * 1) Null node, valid pathname from root (absolute path)
0195      * 2) Node and valid pathname (path relative to Node)
0196      * 3) Node, Null pathname
0197      */
0198     if ((pathname) && (ACPI_IS_ROOT_PREFIX(pathname[0]))) {
0199 
0200         /* The path is fully qualified, just evaluate by name */
0201 
0202         info->prefix_node = NULL;
0203     } else if (!handle) {
0204         /*
0205          * A handle is optional iff a fully qualified pathname is specified.
0206          * Since we've already handled fully qualified names above, this is
0207          * an error.
0208          */
0209         if (!pathname) {
0210             ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0211                       "Both Handle and Pathname are NULL"));
0212         } else {
0213             ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0214                       "Null Handle with relative pathname [%s]",
0215                       pathname));
0216         }
0217 
0218         status = AE_BAD_PARAMETER;
0219         goto cleanup;
0220     }
0221 
0222     info->relative_pathname = pathname;
0223 
0224     /*
0225      * Convert all external objects passed as arguments to the
0226      * internal version(s).
0227      */
0228     if (external_params && external_params->count) {
0229         info->param_count = (u16)external_params->count;
0230 
0231         /* Warn on impossible argument count */
0232 
0233         if (info->param_count > ACPI_METHOD_NUM_ARGS) {
0234             ACPI_WARN_PREDEFINED((AE_INFO, pathname,
0235                           ACPI_WARN_ALWAYS,
0236                           "Excess arguments (%u) - using only %u",
0237                           info->param_count,
0238                           ACPI_METHOD_NUM_ARGS));
0239 
0240             info->param_count = ACPI_METHOD_NUM_ARGS;
0241         }
0242 
0243         /*
0244          * Allocate a new parameter block for the internal objects
0245          * Add 1 to count to allow for null terminated internal list
0246          */
0247         info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)info->
0248                              param_count +
0249                              1) * sizeof(void *));
0250         if (!info->parameters) {
0251             status = AE_NO_MEMORY;
0252             goto cleanup;
0253         }
0254 
0255         /* Convert each external object in the list to an internal object */
0256 
0257         for (i = 0; i < info->param_count; i++) {
0258             status =
0259                 acpi_ut_copy_eobject_to_iobject(&external_params->
0260                                 pointer[i],
0261                                 &info->
0262                                 parameters[i]);
0263             if (ACPI_FAILURE(status)) {
0264                 goto cleanup;
0265             }
0266         }
0267 
0268         info->parameters[info->param_count] = NULL;
0269     }
0270 
0271 #ifdef _FUTURE_FEATURE
0272 
0273     /*
0274      * Begin incoming argument count analysis. Check for too few args
0275      * and too many args.
0276      */
0277     switch (acpi_ns_get_type(info->node)) {
0278     case ACPI_TYPE_METHOD:
0279 
0280         /* Check incoming argument count against the method definition */
0281 
0282         if (info->obj_desc->method.param_count > info->param_count) {
0283             ACPI_ERROR((AE_INFO,
0284                     "Insufficient arguments (%u) - %u are required",
0285                     info->param_count,
0286                     info->obj_desc->method.param_count));
0287 
0288             status = AE_MISSING_ARGUMENTS;
0289             goto cleanup;
0290         }
0291 
0292         else if (info->obj_desc->method.param_count < info->param_count) {
0293             ACPI_WARNING((AE_INFO,
0294                       "Excess arguments (%u) - only %u are required",
0295                       info->param_count,
0296                       info->obj_desc->method.param_count));
0297 
0298             /* Just pass the required number of arguments */
0299 
0300             info->param_count = info->obj_desc->method.param_count;
0301         }
0302 
0303         /*
0304          * Any incoming external objects to be passed as arguments to the
0305          * method must be converted to internal objects
0306          */
0307         if (info->param_count) {
0308             /*
0309              * Allocate a new parameter block for the internal objects
0310              * Add 1 to count to allow for null terminated internal list
0311              */
0312             info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)
0313                                  info->
0314                                  param_count +
0315                                  1) *
0316                                 sizeof(void *));
0317             if (!info->parameters) {
0318                 status = AE_NO_MEMORY;
0319                 goto cleanup;
0320             }
0321 
0322             /* Convert each external object in the list to an internal object */
0323 
0324             for (i = 0; i < info->param_count; i++) {
0325                 status =
0326                     acpi_ut_copy_eobject_to_iobject
0327                     (&external_params->pointer[i],
0328                      &info->parameters[i]);
0329                 if (ACPI_FAILURE(status)) {
0330                     goto cleanup;
0331                 }
0332             }
0333 
0334             info->parameters[info->param_count] = NULL;
0335         }
0336         break;
0337 
0338     default:
0339 
0340         /* Warn if arguments passed to an object that is not a method */
0341 
0342         if (info->param_count) {
0343             ACPI_WARNING((AE_INFO,
0344                       "%u arguments were passed to a non-method ACPI object",
0345                       info->param_count));
0346         }
0347         break;
0348     }
0349 
0350 #endif
0351 
0352     /* Now we can evaluate the object */
0353 
0354     status = acpi_ns_evaluate(info);
0355 
0356     /*
0357      * If we are expecting a return value, and all went well above,
0358      * copy the return value to an external object.
0359      */
0360     if (!return_buffer) {
0361         goto cleanup_return_object;
0362     }
0363 
0364     if (!info->return_object) {
0365         return_buffer->length = 0;
0366         goto cleanup;
0367     }
0368 
0369     if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) ==
0370         ACPI_DESC_TYPE_NAMED) {
0371         /*
0372          * If we received a NS Node as a return object, this means that
0373          * the object we are evaluating has nothing interesting to
0374          * return (such as a mutex, etc.)  We return an error because
0375          * these types are essentially unsupported by this interface.
0376          * We don't check up front because this makes it easier to add
0377          * support for various types at a later date if necessary.
0378          */
0379         status = AE_TYPE;
0380         info->return_object = NULL; /* No need to delete a NS Node */
0381         return_buffer->length = 0;
0382     }
0383 
0384     if (ACPI_FAILURE(status)) {
0385         goto cleanup_return_object;
0386     }
0387 
0388     /* Dereference Index and ref_of references */
0389 
0390     acpi_ns_resolve_references(info);
0391 
0392     /* Get the size of the returned object */
0393 
0394     status = acpi_ut_get_object_size(info->return_object,
0395                      &buffer_space_needed);
0396     if (ACPI_SUCCESS(status)) {
0397 
0398         /* Validate/Allocate/Clear caller buffer */
0399 
0400         status = acpi_ut_initialize_buffer(return_buffer,
0401                            buffer_space_needed);
0402         if (ACPI_FAILURE(status)) {
0403             /*
0404              * Caller's buffer is too small or a new one can't
0405              * be allocated
0406              */
0407             ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0408                       "Needed buffer size %X, %s\n",
0409                       (u32)buffer_space_needed,
0410                       acpi_format_exception(status)));
0411         } else {
0412             /* We have enough space for the object, build it */
0413 
0414             status =
0415                 acpi_ut_copy_iobject_to_eobject(info->return_object,
0416                                 return_buffer);
0417         }
0418     }
0419 
0420 cleanup_return_object:
0421 
0422     if (info->return_object) {
0423         /*
0424          * Delete the internal return object. NOTE: Interpreter must be
0425          * locked to avoid race condition.
0426          */
0427         acpi_ex_enter_interpreter();
0428 
0429         /* Remove one reference on the return object (should delete it) */
0430 
0431         acpi_ut_remove_reference(info->return_object);
0432         acpi_ex_exit_interpreter();
0433     }
0434 
0435 cleanup:
0436 
0437     /* Free the input parameter list (if we created one) */
0438 
0439     if (info->parameters) {
0440 
0441         /* Free the allocated parameter block */
0442 
0443         acpi_ut_delete_internal_object_list(info->parameters);
0444     }
0445 
0446     ACPI_FREE(info);
0447     return_ACPI_STATUS(status);
0448 }
0449 
0450 ACPI_EXPORT_SYMBOL(acpi_evaluate_object)
0451 
0452 /*******************************************************************************
0453  *
0454  * FUNCTION:    acpi_ns_resolve_references
0455  *
0456  * PARAMETERS:  info                    - Evaluation info block
0457  *
0458  * RETURN:      Info->return_object is replaced with the dereferenced object
0459  *
0460  * DESCRIPTION: Dereference certain reference objects. Called before an
0461  *              internal return object is converted to an external union acpi_object.
0462  *
0463  * Performs an automatic dereference of Index and ref_of reference objects.
0464  * These reference objects are not supported by the union acpi_object, so this is a
0465  * last resort effort to return something useful. Also, provides compatibility
0466  * with other ACPI implementations.
0467  *
0468  * NOTE: does not handle references within returned package objects or nested
0469  * references, but this support could be added later if found to be necessary.
0470  *
0471  ******************************************************************************/
0472 static void acpi_ns_resolve_references(struct acpi_evaluate_info *info)
0473 {
0474     union acpi_operand_object *obj_desc = NULL;
0475     struct acpi_namespace_node *node;
0476 
0477     /* We are interested in reference objects only */
0478 
0479     if ((info->return_object)->common.type != ACPI_TYPE_LOCAL_REFERENCE) {
0480         return;
0481     }
0482 
0483     /*
0484      * Two types of references are supported - those created by Index and
0485      * ref_of operators. A name reference (AML_NAMEPATH_OP) can be converted
0486      * to a union acpi_object, so it is not dereferenced here. A ddb_handle
0487      * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
0488      * a union acpi_object.
0489      */
0490     switch (info->return_object->reference.class) {
0491     case ACPI_REFCLASS_INDEX:
0492 
0493         obj_desc = *(info->return_object->reference.where);
0494         break;
0495 
0496     case ACPI_REFCLASS_REFOF:
0497 
0498         node = info->return_object->reference.object;
0499         if (node) {
0500             obj_desc = node->object;
0501         }
0502         break;
0503 
0504     default:
0505 
0506         return;
0507     }
0508 
0509     /* Replace the existing reference object */
0510 
0511     if (obj_desc) {
0512         acpi_ut_add_reference(obj_desc);
0513         acpi_ut_remove_reference(info->return_object);
0514         info->return_object = obj_desc;
0515     }
0516 
0517     return;
0518 }
0519 
0520 /*******************************************************************************
0521  *
0522  * FUNCTION:    acpi_walk_namespace
0523  *
0524  * PARAMETERS:  type                - acpi_object_type to search for
0525  *              start_object        - Handle in namespace where search begins
0526  *              max_depth           - Depth to which search is to reach
0527  *              descending_callback - Called during tree descent
0528  *                                    when an object of "Type" is found
0529  *              ascending_callback  - Called during tree ascent
0530  *                                    when an object of "Type" is found
0531  *              context             - Passed to user function(s) above
0532  *              return_value        - Location where return value of
0533  *                                    user_function is put if terminated early
0534  *
0535  * RETURNS      Return value from the user_function if terminated early.
0536  *              Otherwise, returns NULL.
0537  *
0538  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
0539  *              starting (and ending) at the object specified by start_handle.
0540  *              The callback function is called whenever an object that matches
0541  *              the type parameter is found. If the callback function returns
0542  *              a non-zero value, the search is terminated immediately and this
0543  *              value is returned to the caller.
0544  *
0545  *              The point of this procedure is to provide a generic namespace
0546  *              walk routine that can be called from multiple places to
0547  *              provide multiple services; the callback function(s) can be
0548  *              tailored to each task, whether it is a print function,
0549  *              a compare function, etc.
0550  *
0551  ******************************************************************************/
0552 
0553 acpi_status
0554 acpi_walk_namespace(acpi_object_type type,
0555             acpi_handle start_object,
0556             u32 max_depth,
0557             acpi_walk_callback descending_callback,
0558             acpi_walk_callback ascending_callback,
0559             void *context, void **return_value)
0560 {
0561     acpi_status status;
0562 
0563     ACPI_FUNCTION_TRACE(acpi_walk_namespace);
0564 
0565     /* Parameter validation */
0566 
0567     if ((type > ACPI_TYPE_LOCAL_MAX) ||
0568         (!max_depth) || (!descending_callback && !ascending_callback)) {
0569         return_ACPI_STATUS(AE_BAD_PARAMETER);
0570     }
0571 
0572     /*
0573      * Need to acquire the namespace reader lock to prevent interference
0574      * with any concurrent table unloads (which causes the deletion of
0575      * namespace objects). We cannot allow the deletion of a namespace node
0576      * while the user function is using it. The exception to this are the
0577      * nodes created and deleted during control method execution -- these
0578      * nodes are marked as temporary nodes and are ignored by the namespace
0579      * walk. Thus, control methods can be executed while holding the
0580      * namespace deletion lock (and the user function can execute control
0581      * methods.)
0582      */
0583     status = acpi_ut_acquire_read_lock(&acpi_gbl_namespace_rw_lock);
0584     if (ACPI_FAILURE(status)) {
0585         return_ACPI_STATUS(status);
0586     }
0587 
0588     /*
0589      * Lock the namespace around the walk. The namespace will be
0590      * unlocked/locked around each call to the user function - since the user
0591      * function must be allowed to make ACPICA calls itself (for example, it
0592      * will typically execute control methods during device enumeration.)
0593      */
0594     status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0595     if (ACPI_FAILURE(status)) {
0596         goto unlock_and_exit;
0597     }
0598 
0599     /* Now we can validate the starting node */
0600 
0601     if (!acpi_ns_validate_handle(start_object)) {
0602         status = AE_BAD_PARAMETER;
0603         goto unlock_and_exit2;
0604     }
0605 
0606     status = acpi_ns_walk_namespace(type, start_object, max_depth,
0607                     ACPI_NS_WALK_UNLOCK,
0608                     descending_callback, ascending_callback,
0609                     context, return_value);
0610 
0611 unlock_and_exit2:
0612     (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0613 
0614 unlock_and_exit:
0615     (void)acpi_ut_release_read_lock(&acpi_gbl_namespace_rw_lock);
0616     return_ACPI_STATUS(status);
0617 }
0618 
0619 ACPI_EXPORT_SYMBOL(acpi_walk_namespace)
0620 
0621 /*******************************************************************************
0622  *
0623  * FUNCTION:    acpi_ns_get_device_callback
0624  *
0625  * PARAMETERS:  Callback from acpi_get_device
0626  *
0627  * RETURN:      Status
0628  *
0629  * DESCRIPTION: Takes callbacks from walk_namespace and filters out all non-
0630  *              present devices, or if they specified a HID, it filters based
0631  *              on that.
0632  *
0633  ******************************************************************************/
0634 static acpi_status
0635 acpi_ns_get_device_callback(acpi_handle obj_handle,
0636                 u32 nesting_level,
0637                 void *context, void **return_value)
0638 {
0639     struct acpi_get_devices_info *info = context;
0640     acpi_status status;
0641     struct acpi_namespace_node *node;
0642     u32 flags;
0643     struct acpi_pnp_device_id *hid;
0644     struct acpi_pnp_device_id_list *cid;
0645     u32 i;
0646     u8 found;
0647     int no_match;
0648 
0649     status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0650     if (ACPI_FAILURE(status)) {
0651         return (status);
0652     }
0653 
0654     node = acpi_ns_validate_handle(obj_handle);
0655     status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0656     if (ACPI_FAILURE(status)) {
0657         return (status);
0658     }
0659 
0660     if (!node) {
0661         return (AE_BAD_PARAMETER);
0662     }
0663 
0664     /*
0665      * First, filter based on the device HID and CID.
0666      *
0667      * 01/2010: For this case where a specific HID is requested, we don't
0668      * want to run _STA until we have an actual HID match. Thus, we will
0669      * not unnecessarily execute _STA on devices for which the caller
0670      * doesn't care about. Previously, _STA was executed unconditionally
0671      * on all devices found here.
0672      *
0673      * A side-effect of this change is that now we will continue to search
0674      * for a matching HID even under device trees where the parent device
0675      * would have returned a _STA that indicates it is not present or
0676      * not functioning (thus aborting the search on that branch).
0677      */
0678     if (info->hid != NULL) {
0679         status = acpi_ut_execute_HID(node, &hid);
0680         if (status == AE_NOT_FOUND) {
0681             return (AE_OK);
0682         } else if (ACPI_FAILURE(status)) {
0683             return (AE_CTRL_DEPTH);
0684         }
0685 
0686         no_match = strcmp(hid->string, info->hid);
0687         ACPI_FREE(hid);
0688 
0689         if (no_match) {
0690             /*
0691              * HID does not match, attempt match within the
0692              * list of Compatible IDs (CIDs)
0693              */
0694             status = acpi_ut_execute_CID(node, &cid);
0695             if (status == AE_NOT_FOUND) {
0696                 return (AE_OK);
0697             } else if (ACPI_FAILURE(status)) {
0698                 return (AE_CTRL_DEPTH);
0699             }
0700 
0701             /* Walk the CID list */
0702 
0703             found = FALSE;
0704             for (i = 0; i < cid->count; i++) {
0705                 if (strcmp(cid->ids[i].string, info->hid) == 0) {
0706 
0707                     /* Found a matching CID */
0708 
0709                     found = TRUE;
0710                     break;
0711                 }
0712             }
0713 
0714             ACPI_FREE(cid);
0715             if (!found) {
0716                 return (AE_OK);
0717             }
0718         }
0719     }
0720 
0721     /* Run _STA to determine if device is present */
0722 
0723     status = acpi_ut_execute_STA(node, &flags);
0724     if (ACPI_FAILURE(status)) {
0725         return (AE_CTRL_DEPTH);
0726     }
0727 
0728     if (!(flags & ACPI_STA_DEVICE_PRESENT) &&
0729         !(flags & ACPI_STA_DEVICE_FUNCTIONING)) {
0730         /*
0731          * Don't examine the children of the device only when the
0732          * device is neither present nor functional. See ACPI spec,
0733          * description of _STA for more information.
0734          */
0735         return (AE_CTRL_DEPTH);
0736     }
0737 
0738     /* We have a valid device, invoke the user function */
0739 
0740     status = info->user_function(obj_handle, nesting_level,
0741                      info->context, return_value);
0742     return (status);
0743 }
0744 
0745 /*******************************************************************************
0746  *
0747  * FUNCTION:    acpi_get_devices
0748  *
0749  * PARAMETERS:  HID                 - HID to search for. Can be NULL.
0750  *              user_function       - Called when a matching object is found
0751  *              context             - Passed to user function
0752  *              return_value        - Location where return value of
0753  *                                    user_function is put if terminated early
0754  *
0755  * RETURNS      Return value from the user_function if terminated early.
0756  *              Otherwise, returns NULL.
0757  *
0758  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
0759  *              starting (and ending) at the object specified by start_handle.
0760  *              The user_function is called whenever an object of type
0761  *              Device is found. If the user function returns
0762  *              a non-zero value, the search is terminated immediately and this
0763  *              value is returned to the caller.
0764  *
0765  *              This is a wrapper for walk_namespace, but the callback performs
0766  *              additional filtering. Please see acpi_ns_get_device_callback.
0767  *
0768  ******************************************************************************/
0769 
0770 acpi_status
0771 acpi_get_devices(const char *HID,
0772          acpi_walk_callback user_function,
0773          void *context, void **return_value)
0774 {
0775     acpi_status status;
0776     struct acpi_get_devices_info info;
0777 
0778     ACPI_FUNCTION_TRACE(acpi_get_devices);
0779 
0780     /* Parameter validation */
0781 
0782     if (!user_function) {
0783         return_ACPI_STATUS(AE_BAD_PARAMETER);
0784     }
0785 
0786     /*
0787      * We're going to call their callback from OUR callback, so we need
0788      * to know what it is, and their context parameter.
0789      */
0790     info.hid = HID;
0791     info.context = context;
0792     info.user_function = user_function;
0793 
0794     /*
0795      * Lock the namespace around the walk.
0796      * The namespace will be unlocked/locked around each call
0797      * to the user function - since this function
0798      * must be allowed to make Acpi calls itself.
0799      */
0800     status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0801     if (ACPI_FAILURE(status)) {
0802         return_ACPI_STATUS(status);
0803     }
0804 
0805     status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
0806                     ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
0807                     acpi_ns_get_device_callback, NULL,
0808                     &info, return_value);
0809 
0810     (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0811     return_ACPI_STATUS(status);
0812 }
0813 
0814 ACPI_EXPORT_SYMBOL(acpi_get_devices)
0815 
0816 /*******************************************************************************
0817  *
0818  * FUNCTION:    acpi_attach_data
0819  *
0820  * PARAMETERS:  obj_handle          - Namespace node
0821  *              handler             - Handler for this attachment
0822  *              data                - Pointer to data to be attached
0823  *
0824  * RETURN:      Status
0825  *
0826  * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
0827  *
0828  ******************************************************************************/
0829 acpi_status
0830 acpi_attach_data(acpi_handle obj_handle,
0831          acpi_object_handler handler, void *data)
0832 {
0833     struct acpi_namespace_node *node;
0834     acpi_status status;
0835 
0836     /* Parameter validation */
0837 
0838     if (!obj_handle || !handler || !data) {
0839         return (AE_BAD_PARAMETER);
0840     }
0841 
0842     status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0843     if (ACPI_FAILURE(status)) {
0844         return (status);
0845     }
0846 
0847     /* Convert and validate the handle */
0848 
0849     node = acpi_ns_validate_handle(obj_handle);
0850     if (!node) {
0851         status = AE_BAD_PARAMETER;
0852         goto unlock_and_exit;
0853     }
0854 
0855     status = acpi_ns_attach_data(node, handler, data);
0856 
0857 unlock_and_exit:
0858     (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0859     return (status);
0860 }
0861 
0862 ACPI_EXPORT_SYMBOL(acpi_attach_data)
0863 
0864 /*******************************************************************************
0865  *
0866  * FUNCTION:    acpi_detach_data
0867  *
0868  * PARAMETERS:  obj_handle          - Namespace node handle
0869  *              handler             - Handler used in call to acpi_attach_data
0870  *
0871  * RETURN:      Status
0872  *
0873  * DESCRIPTION: Remove data that was previously attached to a node.
0874  *
0875  ******************************************************************************/
0876 acpi_status
0877 acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler)
0878 {
0879     struct acpi_namespace_node *node;
0880     acpi_status status;
0881 
0882     /* Parameter validation */
0883 
0884     if (!obj_handle || !handler) {
0885         return (AE_BAD_PARAMETER);
0886     }
0887 
0888     status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0889     if (ACPI_FAILURE(status)) {
0890         return (status);
0891     }
0892 
0893     /* Convert and validate the handle */
0894 
0895     node = acpi_ns_validate_handle(obj_handle);
0896     if (!node) {
0897         status = AE_BAD_PARAMETER;
0898         goto unlock_and_exit;
0899     }
0900 
0901     status = acpi_ns_detach_data(node, handler);
0902 
0903 unlock_and_exit:
0904     (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0905     return (status);
0906 }
0907 
0908 ACPI_EXPORT_SYMBOL(acpi_detach_data)
0909 
0910 /*******************************************************************************
0911  *
0912  * FUNCTION:    acpi_get_data_full
0913  *
0914  * PARAMETERS:  obj_handle          - Namespace node
0915  *              handler             - Handler used in call to attach_data
0916  *              data                - Where the data is returned
0917  *              callback            - function to execute before returning
0918  *
0919  * RETURN:      Status
0920  *
0921  * DESCRIPTION: Retrieve data that was previously attached to a namespace node
0922  *              and execute a callback before returning.
0923  *
0924  ******************************************************************************/
0925 acpi_status
0926 acpi_get_data_full(acpi_handle obj_handle, acpi_object_handler handler,
0927            void **data, void (*callback)(void *))
0928 {
0929     struct acpi_namespace_node *node;
0930     acpi_status status;
0931 
0932     /* Parameter validation */
0933 
0934     if (!obj_handle || !handler || !data) {
0935         return (AE_BAD_PARAMETER);
0936     }
0937 
0938     status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0939     if (ACPI_FAILURE(status)) {
0940         return (status);
0941     }
0942 
0943     /* Convert and validate the handle */
0944 
0945     node = acpi_ns_validate_handle(obj_handle);
0946     if (!node) {
0947         status = AE_BAD_PARAMETER;
0948         goto unlock_and_exit;
0949     }
0950 
0951     status = acpi_ns_get_attached_data(node, handler, data);
0952     if (ACPI_SUCCESS(status) && callback) {
0953         callback(*data);
0954     }
0955 
0956 unlock_and_exit:
0957     (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0958     return (status);
0959 }
0960 
0961 ACPI_EXPORT_SYMBOL(acpi_get_data_full)
0962 
0963 /*******************************************************************************
0964  *
0965  * FUNCTION:    acpi_get_data
0966  *
0967  * PARAMETERS:  obj_handle          - Namespace node
0968  *              handler             - Handler used in call to attach_data
0969  *              data                - Where the data is returned
0970  *
0971  * RETURN:      Status
0972  *
0973  * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
0974  *
0975  ******************************************************************************/
0976 acpi_status
0977 acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
0978 {
0979     return acpi_get_data_full(obj_handle, handler, data, NULL);
0980 }
0981 
0982 ACPI_EXPORT_SYMBOL(acpi_get_data)