LCOV - code coverage report
Current view: top level - drivers/acpi/acpica - nsxfeval.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 157 215 73.0 %
Date: 2022-04-01 14:58:12 Functions: 7 9 77.8 %
Branches: 67 124 54.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
       2                 :            : /*******************************************************************************
       3                 :            :  *
       4                 :            :  * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
       5                 :            :  *                         ACPI Object evaluation interfaces
       6                 :            :  *
       7                 :            :  ******************************************************************************/
       8                 :            : 
       9                 :            : #define EXPORT_ACPI_INTERFACES
      10                 :            : 
      11                 :            : #include <acpi/acpi.h>
      12                 :            : #include "accommon.h"
      13                 :            : #include "acnamesp.h"
      14                 :            : #include "acinterp.h"
      15                 :            : 
      16                 :            : #define _COMPONENT          ACPI_NAMESPACE
      17                 :            : ACPI_MODULE_NAME("nsxfeval")
      18                 :            : 
      19                 :            : /* Local prototypes */
      20                 :            : static void acpi_ns_resolve_references(struct acpi_evaluate_info *info);
      21                 :            : 
      22                 :            : /*******************************************************************************
      23                 :            :  *
      24                 :            :  * FUNCTION:    acpi_evaluate_object_typed
      25                 :            :  *
      26                 :            :  * PARAMETERS:  handle              - Object handle (optional)
      27                 :            :  *              pathname            - Object pathname (optional)
      28                 :            :  *              external_params     - List of parameters to pass to a method,
      29                 :            :  *                                    terminated by NULL. May be NULL
      30                 :            :  *                                    if no parameters are being passed.
      31                 :            :  *              return_buffer       - Where to put the object's return value (if
      32                 :            :  *                                    any). If NULL, no value is returned.
      33                 :            :  *              return_type         - Expected type of return object
      34                 :            :  *
      35                 :            :  * RETURN:      Status
      36                 :            :  *
      37                 :            :  * DESCRIPTION: Find and evaluate the given object, passing the given
      38                 :            :  *              parameters if necessary. One of "Handle" or "Pathname" must
      39                 :            :  *              be valid (non-null)
      40                 :            :  *
      41                 :            :  ******************************************************************************/
      42                 :            : 
      43                 :            : acpi_status
      44                 :        174 : acpi_evaluate_object_typed(acpi_handle handle,
      45                 :            :                            acpi_string pathname,
      46                 :            :                            struct acpi_object_list *external_params,
      47                 :            :                            struct acpi_buffer *return_buffer,
      48                 :            :                            acpi_object_type return_type)
      49                 :            : {
      50                 :        174 :         acpi_status status;
      51                 :        174 :         u8 free_buffer_on_error = FALSE;
      52                 :        174 :         acpi_handle target_handle;
      53                 :        174 :         char *full_pathname;
      54                 :            : 
      55                 :        174 :         ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed);
      56                 :            : 
      57                 :            :         /* Return buffer must be valid */
      58                 :            : 
      59         [ +  - ]:        174 :         if (!return_buffer) {
      60                 :            :                 return_ACPI_STATUS(AE_BAD_PARAMETER);
      61                 :            :         }
      62                 :            : 
      63         [ +  - ]:        174 :         if (return_buffer->length == ACPI_ALLOCATE_BUFFER) {
      64                 :        174 :                 free_buffer_on_error = TRUE;
      65                 :            :         }
      66                 :            : 
      67                 :            :         /* Get a handle here, in order to build an error message if needed */
      68                 :            : 
      69                 :        174 :         target_handle = handle;
      70         [ +  - ]:        174 :         if (pathname) {
      71                 :        174 :                 status = acpi_get_handle(handle, pathname, &target_handle);
      72         [ -  + ]:        174 :                 if (ACPI_FAILURE(status)) {
      73                 :            :                         return_ACPI_STATUS(status);
      74                 :            :                 }
      75                 :            :         }
      76                 :            : 
      77                 :          0 :         full_pathname = acpi_ns_get_external_pathname(target_handle);
      78         [ #  # ]:          0 :         if (!full_pathname) {
      79                 :            :                 return_ACPI_STATUS(AE_NO_MEMORY);
      80                 :            :         }
      81                 :            : 
      82                 :            :         /* Evaluate the object */
      83                 :            : 
      84                 :          0 :         status = acpi_evaluate_object(target_handle, NULL, external_params,
      85                 :            :                                       return_buffer);
      86         [ #  # ]:          0 :         if (ACPI_FAILURE(status)) {
      87                 :          0 :                 goto exit;
      88                 :            :         }
      89                 :            : 
      90                 :            :         /* Type ANY means "don't care about return value type" */
      91                 :            : 
      92         [ #  # ]:          0 :         if (return_type == ACPI_TYPE_ANY) {
      93                 :          0 :                 goto exit;
      94                 :            :         }
      95                 :            : 
      96         [ #  # ]:          0 :         if (return_buffer->length == 0) {
      97                 :            : 
      98                 :            :                 /* Error because caller specifically asked for a return value */
      99                 :            : 
     100                 :          0 :                 ACPI_ERROR((AE_INFO, "%s did not return any object",
     101                 :            :                             full_pathname));
     102                 :          0 :                 status = AE_NULL_OBJECT;
     103                 :          0 :                 goto exit;
     104                 :            :         }
     105                 :            : 
     106                 :            :         /* Examine the object type returned from evaluate_object */
     107                 :            : 
     108         [ #  # ]:          0 :         if (((union acpi_object *)return_buffer->pointer)->type == return_type) {
     109                 :          0 :                 goto exit;
     110                 :            :         }
     111                 :            : 
     112                 :            :         /* Return object type does not match requested type */
     113                 :            : 
     114                 :          0 :         ACPI_ERROR((AE_INFO,
     115                 :            :                     "Incorrect return type from %s - received [%s], requested [%s]",
     116                 :            :                     full_pathname,
     117                 :            :                     acpi_ut_get_type_name(((union acpi_object *)return_buffer->
     118                 :            :                                            pointer)->type),
     119                 :            :                     acpi_ut_get_type_name(return_type)));
     120                 :            : 
     121         [ #  # ]:          0 :         if (free_buffer_on_error) {
     122                 :            :                 /*
     123                 :            :                  * Free a buffer created via ACPI_ALLOCATE_BUFFER.
     124                 :            :                  * Note: We use acpi_os_free here because acpi_os_allocate was used
     125                 :            :                  * to allocate the buffer. This purposefully bypasses the
     126                 :            :                  * (optionally enabled) allocation tracking mechanism since we
     127                 :            :                  * only want to track internal allocations.
     128                 :            :                  */
     129                 :          0 :                 acpi_os_free(return_buffer->pointer);
     130                 :          0 :                 return_buffer->pointer = NULL;
     131                 :            :         }
     132                 :            : 
     133                 :          0 :         return_buffer->length = 0;
     134                 :          0 :         status = AE_TYPE;
     135                 :            : 
     136                 :          0 : exit:
     137                 :          0 :         ACPI_FREE(full_pathname);
     138                 :          0 :         return_ACPI_STATUS(status);
     139                 :            : }
     140                 :            : 
     141                 :            : ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed)
     142                 :            : 
     143                 :            : /*******************************************************************************
     144                 :            :  *
     145                 :            :  * FUNCTION:    acpi_evaluate_object
     146                 :            :  *
     147                 :            :  * PARAMETERS:  handle              - Object handle (optional)
     148                 :            :  *              pathname            - Object pathname (optional)
     149                 :            :  *              external_params     - List of parameters to pass to method,
     150                 :            :  *                                    terminated by NULL. May be NULL
     151                 :            :  *                                    if no parameters are being passed.
     152                 :            :  *              return_buffer       - Where to put method's return value (if
     153                 :            :  *                                    any). If NULL, no value is returned.
     154                 :            :  *
     155                 :            :  * RETURN:      Status
     156                 :            :  *
     157                 :            :  * DESCRIPTION: Find and evaluate the given object, passing the given
     158                 :            :  *              parameters if necessary. One of "Handle" or "Pathname" must
     159                 :            :  *              be valid (non-null)
     160                 :            :  *
     161                 :            :  ******************************************************************************/
     162                 :            : acpi_status
     163                 :       1848 : acpi_evaluate_object(acpi_handle handle,
     164                 :            :                      acpi_string pathname,
     165                 :            :                      struct acpi_object_list *external_params,
     166                 :            :                      struct acpi_buffer *return_buffer)
     167                 :            : {
     168                 :       1848 :         acpi_status status;
     169                 :       1848 :         struct acpi_evaluate_info *info;
     170                 :       1848 :         acpi_size buffer_space_needed;
     171                 :       1848 :         u32 i;
     172                 :            : 
     173                 :       1848 :         ACPI_FUNCTION_TRACE(acpi_evaluate_object);
     174                 :            : 
     175                 :            :         /* Allocate and initialize the evaluation information block */
     176                 :            : 
     177                 :       1848 :         info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
     178         [ +  - ]:       1848 :         if (!info) {
     179                 :            :                 return_ACPI_STATUS(AE_NO_MEMORY);
     180                 :            :         }
     181                 :            : 
     182                 :            :         /* Convert and validate the device handle */
     183                 :            : 
     184                 :       1848 :         info->prefix_node = acpi_ns_validate_handle(handle);
     185         [ -  + ]:       1848 :         if (!info->prefix_node) {
     186                 :          0 :                 status = AE_BAD_PARAMETER;
     187                 :          0 :                 goto cleanup;
     188                 :            :         }
     189                 :            : 
     190                 :            :         /*
     191                 :            :          * Get the actual namespace node for the target object.
     192                 :            :          * Handles these cases:
     193                 :            :          *
     194                 :            :          * 1) Null node, valid pathname from root (absolute path)
     195                 :            :          * 2) Node and valid pathname (path relative to Node)
     196                 :            :          * 3) Node, Null pathname
     197                 :            :          */
     198   [ +  +  +  + ]:       1848 :         if ((pathname) && (ACPI_IS_ROOT_PREFIX(pathname[0]))) {
     199                 :            : 
     200                 :            :                 /* The path is fully qualified, just evaluate by name */
     201                 :            : 
     202                 :          3 :                 info->prefix_node = NULL;
     203         [ +  + ]:       1845 :         } else if (!handle) {
     204                 :            :                 /*
     205                 :            :                  * A handle is optional iff a fully qualified pathname is specified.
     206                 :            :                  * Since we've already handled fully qualified names above, this is
     207                 :            :                  * an error.
     208                 :            :                  */
     209                 :          3 :                 if (!pathname) {
     210                 :            :                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
     211                 :            :                                           "Both Handle and Pathname are NULL"));
     212                 :            :                 } else {
     213                 :            :                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
     214                 :            :                                           "Null Handle with relative pathname [%s]",
     215                 :          3 :                                           pathname));
     216                 :            :                 }
     217                 :            : 
     218                 :          3 :                 status = AE_BAD_PARAMETER;
     219                 :          3 :                 goto cleanup;
     220                 :            :         }
     221                 :            : 
     222                 :       1845 :         info->relative_pathname = pathname;
     223                 :            : 
     224                 :            :         /*
     225                 :            :          * Convert all external objects passed as arguments to the
     226                 :            :          * internal version(s).
     227                 :            :          */
     228   [ +  +  +  - ]:       1845 :         if (external_params && external_params->count) {
     229                 :         51 :                 info->param_count = (u16)external_params->count;
     230                 :            : 
     231                 :            :                 /* Warn on impossible argument count */
     232                 :            : 
     233         [ -  + ]:         51 :                 if (info->param_count > ACPI_METHOD_NUM_ARGS) {
     234                 :          0 :                         ACPI_WARN_PREDEFINED((AE_INFO, pathname,
     235                 :            :                                               ACPI_WARN_ALWAYS,
     236                 :            :                                               "Excess arguments (%u) - using only %u",
     237                 :            :                                               info->param_count,
     238                 :            :                                               ACPI_METHOD_NUM_ARGS));
     239                 :            : 
     240                 :          0 :                         info->param_count = ACPI_METHOD_NUM_ARGS;
     241                 :            :                 }
     242                 :            : 
     243                 :            :                 /*
     244                 :            :                  * Allocate a new parameter block for the internal objects
     245                 :            :                  * Add 1 to count to allow for null terminated internal list
     246                 :            :                  */
     247                 :         51 :                 info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)info->
     248                 :            :                                                          param_count +
     249                 :            :                                                          1) * sizeof(void *));
     250         [ -  + ]:         51 :                 if (!info->parameters) {
     251                 :          0 :                         status = AE_NO_MEMORY;
     252                 :          0 :                         goto cleanup;
     253                 :            :                 }
     254                 :            : 
     255                 :            :                 /* Convert each external object in the list to an internal object */
     256                 :            : 
     257         [ +  + ]:        246 :                 for (i = 0; i < info->param_count; i++) {
     258                 :        195 :                         status =
     259                 :        195 :                             acpi_ut_copy_eobject_to_iobject(&external_params->
     260                 :        195 :                                                             pointer[i],
     261                 :        195 :                                                             &info->
     262                 :        195 :                                                             parameters[i]);
     263         [ -  + ]:        195 :                         if (ACPI_FAILURE(status)) {
     264                 :          0 :                                 goto cleanup;
     265                 :            :                         }
     266                 :            :                 }
     267                 :            : 
     268                 :         51 :                 info->parameters[info->param_count] = NULL;
     269                 :            :         }
     270                 :            : 
     271                 :            : #ifdef _FUTURE_FEATURE
     272                 :            : 
     273                 :            :         /*
     274                 :            :          * Begin incoming argument count analysis. Check for too few args
     275                 :            :          * and too many args.
     276                 :            :          */
     277                 :            :         switch (acpi_ns_get_type(info->node)) {
     278                 :            :         case ACPI_TYPE_METHOD:
     279                 :            : 
     280                 :            :                 /* Check incoming argument count against the method definition */
     281                 :            : 
     282                 :            :                 if (info->obj_desc->method.param_count > info->param_count) {
     283                 :            :                         ACPI_ERROR((AE_INFO,
     284                 :            :                                     "Insufficient arguments (%u) - %u are required",
     285                 :            :                                     info->param_count,
     286                 :            :                                     info->obj_desc->method.param_count));
     287                 :            : 
     288                 :            :                         status = AE_MISSING_ARGUMENTS;
     289                 :            :                         goto cleanup;
     290                 :            :                 }
     291                 :            : 
     292                 :            :                 else if (info->obj_desc->method.param_count < info->param_count) {
     293                 :            :                         ACPI_WARNING((AE_INFO,
     294                 :            :                                       "Excess arguments (%u) - only %u are required",
     295                 :            :                                       info->param_count,
     296                 :            :                                       info->obj_desc->method.param_count));
     297                 :            : 
     298                 :            :                         /* Just pass the required number of arguments */
     299                 :            : 
     300                 :            :                         info->param_count = info->obj_desc->method.param_count;
     301                 :            :                 }
     302                 :            : 
     303                 :            :                 /*
     304                 :            :                  * Any incoming external objects to be passed as arguments to the
     305                 :            :                  * method must be converted to internal objects
     306                 :            :                  */
     307                 :            :                 if (info->param_count) {
     308                 :            :                         /*
     309                 :            :                          * Allocate a new parameter block for the internal objects
     310                 :            :                          * Add 1 to count to allow for null terminated internal list
     311                 :            :                          */
     312                 :            :                         info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)
     313                 :            :                                                                  info->
     314                 :            :                                                                  param_count +
     315                 :            :                                                                  1) *
     316                 :            :                                                                 sizeof(void *));
     317                 :            :                         if (!info->parameters) {
     318                 :            :                                 status = AE_NO_MEMORY;
     319                 :            :                                 goto cleanup;
     320                 :            :                         }
     321                 :            : 
     322                 :            :                         /* Convert each external object in the list to an internal object */
     323                 :            : 
     324                 :            :                         for (i = 0; i < info->param_count; i++) {
     325                 :            :                                 status =
     326                 :            :                                     acpi_ut_copy_eobject_to_iobject
     327                 :            :                                     (&external_params->pointer[i],
     328                 :            :                                      &info->parameters[i]);
     329                 :            :                                 if (ACPI_FAILURE(status)) {
     330                 :            :                                         goto cleanup;
     331                 :            :                                 }
     332                 :            :                         }
     333                 :            : 
     334                 :            :                         info->parameters[info->param_count] = NULL;
     335                 :            :                 }
     336                 :            :                 break;
     337                 :            : 
     338                 :            :         default:
     339                 :            : 
     340                 :            :                 /* Warn if arguments passed to an object that is not a method */
     341                 :            : 
     342                 :            :                 if (info->param_count) {
     343                 :            :                         ACPI_WARNING((AE_INFO,
     344                 :            :                                       "%u arguments were passed to a non-method ACPI object",
     345                 :            :                                       info->param_count));
     346                 :            :                 }
     347                 :            :                 break;
     348                 :            :         }
     349                 :            : 
     350                 :            : #endif
     351                 :            : 
     352                 :            :         /* Now we can evaluate the object */
     353                 :            : 
     354                 :       1845 :         status = acpi_ns_evaluate(info);
     355                 :            : 
     356                 :            :         /*
     357                 :            :          * If we are expecting a return value, and all went well above,
     358                 :            :          * copy the return value to an external object.
     359                 :            :          */
     360         [ +  + ]:       1845 :         if (!return_buffer) {
     361                 :         18 :                 goto cleanup_return_object;
     362                 :            :         }
     363                 :            : 
     364         [ +  + ]:       1827 :         if (!info->return_object) {
     365                 :        798 :                 return_buffer->length = 0;
     366                 :        798 :                 goto cleanup;
     367                 :            :         }
     368                 :            : 
     369         [ -  + ]:       1029 :         if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) ==
     370                 :            :             ACPI_DESC_TYPE_NAMED) {
     371                 :            :                 /*
     372                 :            :                  * If we received a NS Node as a return object, this means that
     373                 :            :                  * the object we are evaluating has nothing interesting to
     374                 :            :                  * return (such as a mutex, etc.)  We return an error because
     375                 :            :                  * these types are essentially unsupported by this interface.
     376                 :            :                  * We don't check up front because this makes it easier to add
     377                 :            :                  * support for various types at a later date if necessary.
     378                 :            :                  */
     379                 :          0 :                 status = AE_TYPE;
     380                 :          0 :                 info->return_object = NULL;  /* No need to delete a NS Node */
     381                 :          0 :                 return_buffer->length = 0;
     382                 :            :         }
     383                 :            : 
     384         [ -  + ]:       1029 :         if (ACPI_FAILURE(status)) {
     385                 :          0 :                 goto cleanup_return_object;
     386                 :            :         }
     387                 :            : 
     388                 :            :         /* Dereference Index and ref_of references */
     389                 :            : 
     390                 :       1029 :         acpi_ns_resolve_references(info);
     391                 :            : 
     392                 :            :         /* Get the size of the returned object */
     393                 :            : 
     394                 :       1029 :         status = acpi_ut_get_object_size(info->return_object,
     395                 :            :                                          &buffer_space_needed);
     396         [ -  + ]:       1029 :         if (ACPI_SUCCESS(status)) {
     397                 :            : 
     398                 :            :                 /* Validate/Allocate/Clear caller buffer */
     399                 :            : 
     400                 :       1029 :                 status = acpi_ut_initialize_buffer(return_buffer,
     401                 :            :                                                    buffer_space_needed);
     402         [ +  - ]:       1029 :                 if (ACPI_FAILURE(status)) {
     403                 :            :                         /*
     404                 :            :                          * Caller's buffer is too small or a new one can't
     405                 :            :                          * be allocated
     406                 :            :                          */
     407                 :            :                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
     408                 :            :                                           "Needed buffer size %X, %s\n",
     409                 :            :                                           (u32)buffer_space_needed,
     410                 :            :                                           acpi_format_exception(status)));
     411                 :            :                 } else {
     412                 :            :                         /* We have enough space for the object, build it */
     413                 :            : 
     414                 :       1029 :                         status =
     415                 :       1029 :                             acpi_ut_copy_iobject_to_eobject(info->return_object,
     416                 :            :                                                             return_buffer);
     417                 :            :                 }
     418                 :            :         }
     419                 :            : 
     420                 :          0 : cleanup_return_object:
     421                 :            : 
     422         [ +  + ]:       1047 :         if (info->return_object) {
     423                 :            :                 /*
     424                 :            :                  * Delete the internal return object. NOTE: Interpreter must be
     425                 :            :                  * locked to avoid race condition.
     426                 :            :                  */
     427                 :       1044 :                 acpi_ex_enter_interpreter();
     428                 :            : 
     429                 :            :                 /* Remove one reference on the return object (should delete it) */
     430                 :            : 
     431                 :       1044 :                 acpi_ut_remove_reference(info->return_object);
     432                 :       1044 :                 acpi_ex_exit_interpreter();
     433                 :            :         }
     434                 :            : 
     435                 :          3 : cleanup:
     436                 :            : 
     437                 :            :         /* Free the input parameter list (if we created one) */
     438                 :            : 
     439         [ +  + ]:       1848 :         if (info->parameters) {
     440                 :            : 
     441                 :            :                 /* Free the allocated parameter block */
     442                 :            : 
     443                 :         51 :                 acpi_ut_delete_internal_object_list(info->parameters);
     444                 :            :         }
     445                 :            : 
     446                 :       1848 :         ACPI_FREE(info);
     447                 :       1848 :         return_ACPI_STATUS(status);
     448                 :            : }
     449                 :            : 
     450                 :            : ACPI_EXPORT_SYMBOL(acpi_evaluate_object)
     451                 :            : 
     452                 :            : /*******************************************************************************
     453                 :            :  *
     454                 :            :  * FUNCTION:    acpi_ns_resolve_references
     455                 :            :  *
     456                 :            :  * PARAMETERS:  info                    - Evaluation info block
     457                 :            :  *
     458                 :            :  * RETURN:      Info->return_object is replaced with the dereferenced object
     459                 :            :  *
     460                 :            :  * DESCRIPTION: Dereference certain reference objects. Called before an
     461                 :            :  *              internal return object is converted to an external union acpi_object.
     462                 :            :  *
     463                 :            :  * Performs an automatic dereference of Index and ref_of reference objects.
     464                 :            :  * These reference objects are not supported by the union acpi_object, so this is a
     465                 :            :  * last resort effort to return something useful. Also, provides compatibility
     466                 :            :  * with other ACPI implementations.
     467                 :            :  *
     468                 :            :  * NOTE: does not handle references within returned package objects or nested
     469                 :            :  * references, but this support could be added later if found to be necessary.
     470                 :            :  *
     471                 :            :  ******************************************************************************/
     472                 :            : static void acpi_ns_resolve_references(struct acpi_evaluate_info *info)
     473                 :            : {
     474                 :            :         union acpi_operand_object *obj_desc = NULL;
     475                 :            :         struct acpi_namespace_node *node;
     476                 :            : 
     477                 :            :         /* We are interested in reference objects only */
     478                 :            : 
     479                 :            :         if ((info->return_object)->common.type != ACPI_TYPE_LOCAL_REFERENCE) {
     480                 :            :                 return;
     481                 :            :         }
     482                 :            : 
     483                 :            :         /*
     484                 :            :          * Two types of references are supported - those created by Index and
     485                 :            :          * ref_of operators. A name reference (AML_NAMEPATH_OP) can be converted
     486                 :            :          * to a union acpi_object, so it is not dereferenced here. A ddb_handle
     487                 :            :          * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
     488                 :            :          * a union acpi_object.
     489                 :            :          */
     490                 :            :         switch (info->return_object->reference.class) {
     491                 :            :         case ACPI_REFCLASS_INDEX:
     492                 :            : 
     493                 :            :                 obj_desc = *(info->return_object->reference.where);
     494                 :            :                 break;
     495                 :            : 
     496                 :            :         case ACPI_REFCLASS_REFOF:
     497                 :            : 
     498                 :            :                 node = info->return_object->reference.object;
     499                 :            :                 if (node) {
     500                 :            :                         obj_desc = node->object;
     501                 :            :                 }
     502                 :            :                 break;
     503                 :            : 
     504                 :            :         default:
     505                 :            : 
     506                 :            :                 return;
     507                 :            :         }
     508                 :            : 
     509                 :            :         /* Replace the existing reference object */
     510                 :            : 
     511                 :            :         if (obj_desc) {
     512                 :            :                 acpi_ut_add_reference(obj_desc);
     513                 :            :                 acpi_ut_remove_reference(info->return_object);
     514                 :            :                 info->return_object = obj_desc;
     515                 :            :         }
     516                 :            : 
     517                 :            :         return;
     518                 :            : }
     519                 :            : 
     520                 :            : /*******************************************************************************
     521                 :            :  *
     522                 :            :  * FUNCTION:    acpi_walk_namespace
     523                 :            :  *
     524                 :            :  * PARAMETERS:  type                - acpi_object_type to search for
     525                 :            :  *              start_object        - Handle in namespace where search begins
     526                 :            :  *              max_depth           - Depth to which search is to reach
     527                 :            :  *              descending_callback - Called during tree descent
     528                 :            :  *                                    when an object of "Type" is found
     529                 :            :  *              ascending_callback  - Called during tree ascent
     530                 :            :  *                                    when an object of "Type" is found
     531                 :            :  *              context             - Passed to user function(s) above
     532                 :            :  *              return_value        - Location where return value of
     533                 :            :  *                                    user_function is put if terminated early
     534                 :            :  *
     535                 :            :  * RETURNS      Return value from the user_function if terminated early.
     536                 :            :  *              Otherwise, returns NULL.
     537                 :            :  *
     538                 :            :  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
     539                 :            :  *              starting (and ending) at the object specified by start_handle.
     540                 :            :  *              The callback function is called whenever an object that matches
     541                 :            :  *              the type parameter is found. If the callback function returns
     542                 :            :  *              a non-zero value, the search is terminated immediately and this
     543                 :            :  *              value is returned to the caller.
     544                 :            :  *
     545                 :            :  *              The point of this procedure is to provide a generic namespace
     546                 :            :  *              walk routine that can be called from multiple places to
     547                 :            :  *              provide multiple services; the callback function(s) can be
     548                 :            :  *              tailored to each task, whether it is a print function,
     549                 :            :  *              a compare function, etc.
     550                 :            :  *
     551                 :            :  ******************************************************************************/
     552                 :            : 
     553                 :            : acpi_status
     554                 :         21 : acpi_walk_namespace(acpi_object_type type,
     555                 :            :                     acpi_handle start_object,
     556                 :            :                     u32 max_depth,
     557                 :            :                     acpi_walk_callback descending_callback,
     558                 :            :                     acpi_walk_callback ascending_callback,
     559                 :            :                     void *context, void **return_value)
     560                 :            : {
     561                 :         21 :         acpi_status status;
     562                 :            : 
     563                 :         21 :         ACPI_FUNCTION_TRACE(acpi_walk_namespace);
     564                 :            : 
     565                 :            :         /* Parameter validation */
     566                 :            : 
     567                 :         21 :         if ((type > ACPI_TYPE_LOCAL_MAX) ||
     568   [ +  -  +  - ]:         21 :             (!max_depth) || (!descending_callback && !ascending_callback)) {
     569                 :            :                 return_ACPI_STATUS(AE_BAD_PARAMETER);
     570                 :            :         }
     571                 :            : 
     572                 :            :         /*
     573                 :            :          * Need to acquire the namespace reader lock to prevent interference
     574                 :            :          * with any concurrent table unloads (which causes the deletion of
     575                 :            :          * namespace objects). We cannot allow the deletion of a namespace node
     576                 :            :          * while the user function is using it. The exception to this are the
     577                 :            :          * nodes created and deleted during control method execution -- these
     578                 :            :          * nodes are marked as temporary nodes and are ignored by the namespace
     579                 :            :          * walk. Thus, control methods can be executed while holding the
     580                 :            :          * namespace deletion lock (and the user function can execute control
     581                 :            :          * methods.)
     582                 :            :          */
     583                 :         21 :         status = acpi_ut_acquire_read_lock(&acpi_gbl_namespace_rw_lock);
     584         [ +  - ]:         21 :         if (ACPI_FAILURE(status)) {
     585                 :            :                 return_ACPI_STATUS(status);
     586                 :            :         }
     587                 :            : 
     588                 :            :         /*
     589                 :            :          * Lock the namespace around the walk. The namespace will be
     590                 :            :          * unlocked/locked around each call to the user function - since the user
     591                 :            :          * function must be allowed to make ACPICA calls itself (for example, it
     592                 :            :          * will typically execute control methods during device enumeration.)
     593                 :            :          */
     594                 :         21 :         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
     595         [ -  + ]:         21 :         if (ACPI_FAILURE(status)) {
     596                 :          0 :                 goto unlock_and_exit;
     597                 :            :         }
     598                 :            : 
     599                 :            :         /* Now we can validate the starting node */
     600                 :            : 
     601         [ -  + ]:         21 :         if (!acpi_ns_validate_handle(start_object)) {
     602                 :          0 :                 status = AE_BAD_PARAMETER;
     603                 :          0 :                 goto unlock_and_exit2;
     604                 :            :         }
     605                 :            : 
     606                 :         21 :         status = acpi_ns_walk_namespace(type, start_object, max_depth,
     607                 :            :                                         ACPI_NS_WALK_UNLOCK,
     608                 :            :                                         descending_callback, ascending_callback,
     609                 :            :                                         context, return_value);
     610                 :            : 
     611                 :         21 : unlock_and_exit2:
     612                 :         21 :         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
     613                 :            : 
     614                 :         21 : unlock_and_exit:
     615                 :         21 :         (void)acpi_ut_release_read_lock(&acpi_gbl_namespace_rw_lock);
     616                 :         21 :         return_ACPI_STATUS(status);
     617                 :            : }
     618                 :            : 
     619                 :            : ACPI_EXPORT_SYMBOL(acpi_walk_namespace)
     620                 :            : 
     621                 :            : /*******************************************************************************
     622                 :            :  *
     623                 :            :  * FUNCTION:    acpi_ns_get_device_callback
     624                 :            :  *
     625                 :            :  * PARAMETERS:  Callback from acpi_get_device
     626                 :            :  *
     627                 :            :  * RETURN:      Status
     628                 :            :  *
     629                 :            :  * DESCRIPTION: Takes callbacks from walk_namespace and filters out all non-
     630                 :            :  *              present devices, or if they specified a HID, it filters based
     631                 :            :  *              on that.
     632                 :            :  *
     633                 :            :  ******************************************************************************/
     634                 :            : static acpi_status
     635                 :        660 : acpi_ns_get_device_callback(acpi_handle obj_handle,
     636                 :            :                             u32 nesting_level,
     637                 :            :                             void *context, void **return_value)
     638                 :            : {
     639                 :        660 :         struct acpi_get_devices_info *info = context;
     640                 :        660 :         acpi_status status;
     641                 :        660 :         struct acpi_namespace_node *node;
     642                 :        660 :         u32 flags;
     643                 :        660 :         struct acpi_pnp_device_id *hid;
     644                 :        660 :         struct acpi_pnp_device_id_list *cid;
     645                 :        660 :         u32 i;
     646                 :        660 :         u8 found;
     647                 :        660 :         int no_match;
     648                 :            : 
     649                 :        660 :         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
     650         [ +  - ]:        660 :         if (ACPI_FAILURE(status)) {
     651                 :            :                 return (status);
     652                 :            :         }
     653                 :            : 
     654                 :        660 :         node = acpi_ns_validate_handle(obj_handle);
     655                 :        660 :         status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
     656         [ +  - ]:        660 :         if (ACPI_FAILURE(status)) {
     657                 :            :                 return (status);
     658                 :            :         }
     659                 :            : 
     660         [ +  - ]:        660 :         if (!node) {
     661                 :            :                 return (AE_BAD_PARAMETER);
     662                 :            :         }
     663                 :            : 
     664                 :            :         /*
     665                 :            :          * First, filter based on the device HID and CID.
     666                 :            :          *
     667                 :            :          * 01/2010: For this case where a specific HID is requested, we don't
     668                 :            :          * want to run _STA until we have an actual HID match. Thus, we will
     669                 :            :          * not unnecessarily execute _STA on devices for which the caller
     670                 :            :          * doesn't care about. Previously, _STA was executed unconditionally
     671                 :            :          * on all devices found here.
     672                 :            :          *
     673                 :            :          * A side-effect of this change is that now we will continue to search
     674                 :            :          * for a matching HID even under device trees where the parent device
     675                 :            :          * would have returned a _STA that indicates it is not present or
     676                 :            :          * not functioning (thus aborting the search on that branch).
     677                 :            :          */
     678         [ +  + ]:        660 :         if (info->hid != NULL) {
     679                 :        495 :                 status = acpi_ut_execute_HID(node, &hid);
     680         [ +  + ]:        495 :                 if (status == AE_NOT_FOUND) {
     681                 :            :                         return (AE_OK);
     682         [ +  - ]:        171 :                 } else if (ACPI_FAILURE(status)) {
     683                 :            :                         return (AE_CTRL_DEPTH);
     684                 :            :                 }
     685                 :            : 
     686                 :        171 :                 no_match = strcmp(hid->string, info->hid);
     687                 :        171 :                 ACPI_FREE(hid);
     688                 :            : 
     689         [ +  - ]:        171 :                 if (no_match) {
     690                 :            :                         /*
     691                 :            :                          * HID does not match, attempt match within the
     692                 :            :                          * list of Compatible IDs (CIDs)
     693                 :            :                          */
     694                 :        171 :                         status = acpi_ut_execute_CID(node, &cid);
     695         [ +  + ]:        171 :                         if (status == AE_NOT_FOUND) {
     696                 :            :                                 return (AE_OK);
     697         [ +  - ]:          9 :                         } else if (ACPI_FAILURE(status)) {
     698                 :            :                                 return (AE_CTRL_DEPTH);
     699                 :            :                         }
     700                 :            : 
     701                 :            :                         /* Walk the CID list */
     702                 :            : 
     703                 :            :                         found = FALSE;
     704         [ +  + ]:         18 :                         for (i = 0; i < cid->count; i++) {
     705         [ +  - ]:          9 :                                 if (strcmp(cid->ids[i].string, info->hid) == 0) {
     706                 :            : 
     707                 :            :                                         /* Found a matching CID */
     708                 :            : 
     709                 :            :                                         found = TRUE;
     710                 :            :                                         break;
     711                 :            :                                 }
     712                 :            :                         }
     713                 :            : 
     714                 :          9 :                         ACPI_FREE(cid);
     715         [ -  + ]:          9 :                         if (!found) {
     716                 :            :                                 return (AE_OK);
     717                 :            :                         }
     718                 :            :                 }
     719                 :            :         }
     720                 :            : 
     721                 :            :         /* Run _STA to determine if device is present */
     722                 :            : 
     723                 :        165 :         status = acpi_ut_execute_STA(node, &flags);
     724         [ +  - ]:        165 :         if (ACPI_FAILURE(status)) {
     725                 :            :                 return (AE_CTRL_DEPTH);
     726                 :            :         }
     727                 :            : 
     728         [ +  + ]:        165 :         if (!(flags & ACPI_STA_DEVICE_PRESENT) &&
     729                 :            :             !(flags & ACPI_STA_DEVICE_FUNCTIONING)) {
     730                 :            :                 /*
     731                 :            :                  * Don't examine the children of the device only when the
     732                 :            :                  * device is neither present nor functional. See ACPI spec,
     733                 :            :                  * description of _STA for more information.
     734                 :            :                  */
     735                 :            :                 return (AE_CTRL_DEPTH);
     736                 :            :         }
     737                 :            : 
     738                 :            :         /* We have a valid device, invoke the user function */
     739                 :            : 
     740                 :        162 :         status = info->user_function(obj_handle, nesting_level,
     741                 :            :                                      info->context, return_value);
     742                 :        162 :         return (status);
     743                 :            : }
     744                 :            : 
     745                 :            : /*******************************************************************************
     746                 :            :  *
     747                 :            :  * FUNCTION:    acpi_get_devices
     748                 :            :  *
     749                 :            :  * PARAMETERS:  HID                 - HID to search for. Can be NULL.
     750                 :            :  *              user_function       - Called when a matching object is found
     751                 :            :  *              context             - Passed to user function
     752                 :            :  *              return_value        - Location where return value of
     753                 :            :  *                                    user_function is put if terminated early
     754                 :            :  *
     755                 :            :  * RETURNS      Return value from the user_function if terminated early.
     756                 :            :  *              Otherwise, returns NULL.
     757                 :            :  *
     758                 :            :  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
     759                 :            :  *              starting (and ending) at the object specified by start_handle.
     760                 :            :  *              The user_function is called whenever an object of type
     761                 :            :  *              Device is found. If the user function returns
     762                 :            :  *              a non-zero value, the search is terminated immediately and this
     763                 :            :  *              value is returned to the caller.
     764                 :            :  *
     765                 :            :  *              This is a wrapper for walk_namespace, but the callback performs
     766                 :            :  *              additional filtering. Please see acpi_ns_get_device_callback.
     767                 :            :  *
     768                 :            :  ******************************************************************************/
     769                 :            : 
     770                 :            : acpi_status
     771                 :         12 : acpi_get_devices(const char *HID,
     772                 :            :                  acpi_walk_callback user_function,
     773                 :            :                  void *context, void **return_value)
     774                 :            : {
     775                 :         12 :         acpi_status status;
     776                 :         12 :         struct acpi_get_devices_info info;
     777                 :            : 
     778                 :         12 :         ACPI_FUNCTION_TRACE(acpi_get_devices);
     779                 :            : 
     780                 :            :         /* Parameter validation */
     781                 :            : 
     782         [ +  - ]:         12 :         if (!user_function) {
     783                 :            :                 return_ACPI_STATUS(AE_BAD_PARAMETER);
     784                 :            :         }
     785                 :            : 
     786                 :            :         /*
     787                 :            :          * We're going to call their callback from OUR callback, so we need
     788                 :            :          * to know what it is, and their context parameter.
     789                 :            :          */
     790                 :         12 :         info.hid = HID;
     791                 :         12 :         info.context = context;
     792                 :         12 :         info.user_function = user_function;
     793                 :            : 
     794                 :            :         /*
     795                 :            :          * Lock the namespace around the walk.
     796                 :            :          * The namespace will be unlocked/locked around each call
     797                 :            :          * to the user function - since this function
     798                 :            :          * must be allowed to make Acpi calls itself.
     799                 :            :          */
     800                 :         12 :         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
     801         [ +  - ]:         12 :         if (ACPI_FAILURE(status)) {
     802                 :            :                 return_ACPI_STATUS(status);
     803                 :            :         }
     804                 :            : 
     805                 :         12 :         status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
     806                 :            :                                         ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
     807                 :            :                                         acpi_ns_get_device_callback, NULL,
     808                 :            :                                         &info, return_value);
     809                 :            : 
     810                 :         12 :         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
     811                 :         12 :         return_ACPI_STATUS(status);
     812                 :            : }
     813                 :            : 
     814                 :            : ACPI_EXPORT_SYMBOL(acpi_get_devices)
     815                 :            : 
     816                 :            : /*******************************************************************************
     817                 :            :  *
     818                 :            :  * FUNCTION:    acpi_attach_data
     819                 :            :  *
     820                 :            :  * PARAMETERS:  obj_handle          - Namespace node
     821                 :            :  *              handler             - Handler for this attachment
     822                 :            :  *              data                - Pointer to data to be attached
     823                 :            :  *
     824                 :            :  * RETURN:      Status
     825                 :            :  *
     826                 :            :  * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
     827                 :            :  *
     828                 :            :  ******************************************************************************/
     829                 :            : acpi_status
     830                 :        171 : acpi_attach_data(acpi_handle obj_handle,
     831                 :            :                  acpi_object_handler handler, void *data)
     832                 :            : {
     833                 :        171 :         struct acpi_namespace_node *node;
     834                 :        171 :         acpi_status status;
     835                 :            : 
     836                 :            :         /* Parameter validation */
     837                 :            : 
     838   [ +  -  +  - ]:        171 :         if (!obj_handle || !handler || !data) {
     839                 :            :                 return (AE_BAD_PARAMETER);
     840                 :            :         }
     841                 :            : 
     842                 :        171 :         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
     843         [ +  - ]:        171 :         if (ACPI_FAILURE(status)) {
     844                 :            :                 return (status);
     845                 :            :         }
     846                 :            : 
     847                 :            :         /* Convert and validate the handle */
     848                 :            : 
     849                 :        171 :         node = acpi_ns_validate_handle(obj_handle);
     850         [ -  + ]:        171 :         if (!node) {
     851                 :          0 :                 status = AE_BAD_PARAMETER;
     852                 :          0 :                 goto unlock_and_exit;
     853                 :            :         }
     854                 :            : 
     855                 :        171 :         status = acpi_ns_attach_data(node, handler, data);
     856                 :            : 
     857                 :        171 : unlock_and_exit:
     858                 :        171 :         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
     859                 :        171 :         return (status);
     860                 :            : }
     861                 :            : 
     862                 :            : ACPI_EXPORT_SYMBOL(acpi_attach_data)
     863                 :            : 
     864                 :            : /*******************************************************************************
     865                 :            :  *
     866                 :            :  * FUNCTION:    acpi_detach_data
     867                 :            :  *
     868                 :            :  * PARAMETERS:  obj_handle          - Namespace node handle
     869                 :            :  *              handler             - Handler used in call to acpi_attach_data
     870                 :            :  *
     871                 :            :  * RETURN:      Status
     872                 :            :  *
     873                 :            :  * DESCRIPTION: Remove data that was previously attached to a node.
     874                 :            :  *
     875                 :            :  ******************************************************************************/
     876                 :            : acpi_status
     877                 :          0 : acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler)
     878                 :            : {
     879                 :          0 :         struct acpi_namespace_node *node;
     880                 :          0 :         acpi_status status;
     881                 :            : 
     882                 :            :         /* Parameter validation */
     883                 :            : 
     884         [ #  # ]:          0 :         if (!obj_handle || !handler) {
     885                 :            :                 return (AE_BAD_PARAMETER);
     886                 :            :         }
     887                 :            : 
     888                 :          0 :         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
     889         [ #  # ]:          0 :         if (ACPI_FAILURE(status)) {
     890                 :            :                 return (status);
     891                 :            :         }
     892                 :            : 
     893                 :            :         /* Convert and validate the handle */
     894                 :            : 
     895                 :          0 :         node = acpi_ns_validate_handle(obj_handle);
     896         [ #  # ]:          0 :         if (!node) {
     897                 :          0 :                 status = AE_BAD_PARAMETER;
     898                 :          0 :                 goto unlock_and_exit;
     899                 :            :         }
     900                 :            : 
     901                 :          0 :         status = acpi_ns_detach_data(node, handler);
     902                 :            : 
     903                 :          0 : unlock_and_exit:
     904                 :          0 :         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
     905                 :          0 :         return (status);
     906                 :            : }
     907                 :            : 
     908                 :            : ACPI_EXPORT_SYMBOL(acpi_detach_data)
     909                 :            : 
     910                 :            : /*******************************************************************************
     911                 :            :  *
     912                 :            :  * FUNCTION:    acpi_get_data_full
     913                 :            :  *
     914                 :            :  * PARAMETERS:  obj_handle          - Namespace node
     915                 :            :  *              handler             - Handler used in call to attach_data
     916                 :            :  *              data                - Where the data is returned
     917                 :            :  *              callback            - function to execute before returning
     918                 :            :  *
     919                 :            :  * RETURN:      Status
     920                 :            :  *
     921                 :            :  * DESCRIPTION: Retrieve data that was previously attached to a namespace node
     922                 :            :  *              and execute a callback before returning.
     923                 :            :  *
     924                 :            :  ******************************************************************************/
     925                 :            : acpi_status
     926                 :       1362 : acpi_get_data_full(acpi_handle obj_handle, acpi_object_handler handler,
     927                 :            :                    void **data, void (*callback)(void *))
     928                 :            : {
     929                 :       1362 :         struct acpi_namespace_node *node;
     930                 :       1362 :         acpi_status status;
     931                 :            : 
     932                 :            :         /* Parameter validation */
     933                 :            : 
     934   [ +  -  +  - ]:       1362 :         if (!obj_handle || !handler || !data) {
     935                 :            :                 return (AE_BAD_PARAMETER);
     936                 :            :         }
     937                 :            : 
     938                 :       1362 :         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
     939         [ +  - ]:       1362 :         if (ACPI_FAILURE(status)) {
     940                 :            :                 return (status);
     941                 :            :         }
     942                 :            : 
     943                 :            :         /* Convert and validate the handle */
     944                 :            : 
     945                 :       1362 :         node = acpi_ns_validate_handle(obj_handle);
     946         [ -  + ]:       1362 :         if (!node) {
     947                 :          0 :                 status = AE_BAD_PARAMETER;
     948                 :          0 :                 goto unlock_and_exit;
     949                 :            :         }
     950                 :            : 
     951                 :       1362 :         status = acpi_ns_get_attached_data(node, handler, data);
     952         [ +  - ]:       1362 :         if (ACPI_SUCCESS(status) && callback) {
     953                 :          0 :                 callback(*data);
     954                 :            :         }
     955                 :            : 
     956                 :       1362 : unlock_and_exit:
     957                 :       1362 :         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
     958                 :       1362 :         return (status);
     959                 :            : }
     960                 :            : 
     961                 :            : ACPI_EXPORT_SYMBOL(acpi_get_data_full)
     962                 :            : 
     963                 :            : /*******************************************************************************
     964                 :            :  *
     965                 :            :  * FUNCTION:    acpi_get_data
     966                 :            :  *
     967                 :            :  * PARAMETERS:  obj_handle          - Namespace node
     968                 :            :  *              handler             - Handler used in call to attach_data
     969                 :            :  *              data                - Where the data is returned
     970                 :            :  *
     971                 :            :  * RETURN:      Status
     972                 :            :  *
     973                 :            :  * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
     974                 :            :  *
     975                 :            :  ******************************************************************************/
     976                 :            : acpi_status
     977                 :          0 : acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
     978                 :            : {
     979                 :          0 :         return acpi_get_data_full(obj_handle, handler, data, NULL);
     980                 :            : }
     981                 :            : 
     982                 :            : ACPI_EXPORT_SYMBOL(acpi_get_data)

Generated by: LCOV version 1.14