diff options
Diffstat (limited to 'drivers/acpi/acpica/nsxfeval.c')
| -rw-r--r-- | drivers/acpi/acpica/nsxfeval.c | 301 |
1 files changed, 163 insertions, 138 deletions
diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index f553cfdb71dd..f9d059647cc5 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 /******************************************************************************* * * Module Name: nsxfeval - Public interfaces to the ACPI subsystem @@ -5,44 +6,8 @@ * ******************************************************************************/ -/* - * Copyright (C) 2000 - 2013, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include <linux/export.h> +#define EXPORT_ACPI_INTERFACES + #include <acpi/acpi.h> #include "accommon.h" #include "acnamesp.h" @@ -60,10 +25,10 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info); * * PARAMETERS: handle - Object handle (optional) * pathname - Object pathname (optional) - * external_params - List of parameters to pass to method, + * external_params - List of parameters to pass to a method, * terminated by NULL. May be NULL * if no parameters are being passed. - * return_buffer - Where to put method's return value (if + * return_buffer - Where to put the object's return value (if * any). If NULL, no value is returned. * return_type - Expected type of return object * @@ -83,7 +48,9 @@ acpi_evaluate_object_typed(acpi_handle handle, acpi_object_type return_type) { acpi_status status; - u8 must_free = FALSE; + u8 free_buffer_on_error = FALSE; + acpi_handle target_handle; + char *full_pathname; ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed); @@ -94,56 +61,81 @@ acpi_evaluate_object_typed(acpi_handle handle, } if (return_buffer->length == ACPI_ALLOCATE_BUFFER) { - must_free = TRUE; + free_buffer_on_error = TRUE; + } + + /* Get a handle here, in order to build an error message if needed */ + + target_handle = handle; + if (pathname) { + status = acpi_get_handle(handle, pathname, &target_handle); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + full_pathname = acpi_ns_get_external_pathname(target_handle); + if (!full_pathname) { + return_ACPI_STATUS(AE_NO_MEMORY); } /* Evaluate the object */ - status = - acpi_evaluate_object(handle, pathname, external_params, - return_buffer); + status = acpi_evaluate_object(target_handle, NULL, external_params, + return_buffer); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto exit; } - /* Type ANY means "don't care" */ + /* Type ANY means "don't care about return value type" */ if (return_type == ACPI_TYPE_ANY) { - return_ACPI_STATUS(AE_OK); + goto exit; } if (return_buffer->length == 0) { /* Error because caller specifically asked for a return value */ - ACPI_ERROR((AE_INFO, "No return value")); - return_ACPI_STATUS(AE_NULL_OBJECT); + ACPI_ERROR((AE_INFO, "%s did not return any object", + full_pathname)); + status = AE_NULL_OBJECT; + goto exit; } /* Examine the object type returned from evaluate_object */ if (((union acpi_object *)return_buffer->pointer)->type == return_type) { - return_ACPI_STATUS(AE_OK); + goto exit; } /* Return object type does not match requested type */ ACPI_ERROR((AE_INFO, - "Incorrect return type [%s] requested [%s]", + "Incorrect return type from %s - received [%s], requested [%s]", + full_pathname, acpi_ut_get_type_name(((union acpi_object *)return_buffer-> pointer)->type), acpi_ut_get_type_name(return_type))); - if (must_free) { - - /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */ - - ACPI_FREE(return_buffer->pointer); + if (free_buffer_on_error) { + /* + * Free a buffer created via ACPI_ALLOCATE_BUFFER. + * Note: We use acpi_os_free here because acpi_os_allocate was used + * to allocate the buffer. This purposefully bypasses the + * (optionally enabled) allocation tracking mechanism since we + * only want to track internal allocations. + */ + acpi_os_free(return_buffer->pointer); return_buffer->pointer = NULL; } return_buffer->length = 0; - return_ACPI_STATUS(AE_TYPE); + status = AE_TYPE; + +exit: + ACPI_FREE(full_pathname); + return_ACPI_STATUS(status); } ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed) @@ -252,7 +244,7 @@ acpi_evaluate_object(acpi_handle handle, * Allocate a new parameter block for the internal objects * Add 1 to count to allow for null terminated internal list */ - info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) info-> + info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)info-> param_count + 1) * sizeof(void *)); if (!info->parameters) { @@ -276,13 +268,12 @@ acpi_evaluate_object(acpi_handle handle, info->parameters[info->param_count] = NULL; } -#if 0 +#ifdef _FUTURE_FEATURE /* * Begin incoming argument count analysis. Check for too few args * and too many args. */ - switch (acpi_ns_get_type(info->node)) { case ACPI_TYPE_METHOD: @@ -366,68 +357,68 @@ acpi_evaluate_object(acpi_handle handle, * If we are expecting a return value, and all went well above, * copy the return value to an external object. */ - if (return_buffer) { - if (!info->return_object) { - return_buffer->length = 0; - } else { - if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) == - ACPI_DESC_TYPE_NAMED) { - /* - * If we received a NS Node as a return object, this means that - * the object we are evaluating has nothing interesting to - * return (such as a mutex, etc.) We return an error because - * these types are essentially unsupported by this interface. - * We don't check up front because this makes it easier to add - * support for various types at a later date if necessary. - */ - status = AE_TYPE; - info->return_object = NULL; /* No need to delete a NS Node */ - return_buffer->length = 0; - } + if (!return_buffer) { + goto cleanup_return_object; + } - if (ACPI_SUCCESS(status)) { + if (!info->return_object) { + return_buffer->length = 0; + goto cleanup; + } - /* Dereference Index and ref_of references */ + if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) == + ACPI_DESC_TYPE_NAMED) { + /* + * If we received a NS Node as a return object, this means that + * the object we are evaluating has nothing interesting to + * return (such as a mutex, etc.) We return an error because + * these types are essentially unsupported by this interface. + * We don't check up front because this makes it easier to add + * support for various types at a later date if necessary. + */ + status = AE_TYPE; + info->return_object = NULL; /* No need to delete a NS Node */ + return_buffer->length = 0; + } - acpi_ns_resolve_references(info); + if (ACPI_FAILURE(status)) { + goto cleanup_return_object; + } - /* Get the size of the returned object */ + /* Dereference Index and ref_of references */ - status = - acpi_ut_get_object_size(info->return_object, - &buffer_space_needed); - if (ACPI_SUCCESS(status)) { - - /* Validate/Allocate/Clear caller buffer */ - - status = - acpi_ut_initialize_buffer - (return_buffer, - buffer_space_needed); - if (ACPI_FAILURE(status)) { - /* - * Caller's buffer is too small or a new one can't - * be allocated - */ - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Needed buffer size %X, %s\n", - (u32) - buffer_space_needed, - acpi_format_exception - (status))); - } else { - /* We have enough space for the object, build it */ - - status = - acpi_ut_copy_iobject_to_eobject - (info->return_object, - return_buffer); - } - } - } + acpi_ns_resolve_references(info); + + /* Get the size of the returned object */ + + status = acpi_ut_get_object_size(info->return_object, + &buffer_space_needed); + if (ACPI_SUCCESS(status)) { + + /* Validate/Allocate/Clear caller buffer */ + + status = acpi_ut_initialize_buffer(return_buffer, + buffer_space_needed); + if (ACPI_FAILURE(status)) { + /* + * Caller's buffer is too small or a new one can't + * be allocated + */ + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Needed buffer size %X, %s\n", + (u32)buffer_space_needed, + acpi_format_exception(status))); + } else { + /* We have enough space for the object, build it */ + + status = + acpi_ut_copy_iobject_to_eobject(info->return_object, + return_buffer); } } +cleanup_return_object: + if (info->return_object) { /* * Delete the internal return object. NOTE: Interpreter must be @@ -441,7 +432,7 @@ acpi_evaluate_object(acpi_handle handle, acpi_ex_exit_interpreter(); } - cleanup: +cleanup: /* Free the input parameter list (if we created one) */ @@ -492,9 +483,9 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info) /* * Two types of references are supported - those created by Index and * ref_of operators. A name reference (AML_NAMEPATH_OP) can be converted - * to an union acpi_object, so it is not dereferenced here. A ddb_handle + * to a union acpi_object, so it is not dereferenced here. A ddb_handle * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to - * an union acpi_object. + * a union acpi_object. */ switch (info->return_object->reference.class) { case ACPI_REFCLASS_INDEX: @@ -533,9 +524,9 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info) * PARAMETERS: type - acpi_object_type to search for * start_object - Handle in namespace where search begins * max_depth - Depth to which search is to reach - * pre_order_visit - Called during tree pre-order visit + * descending_callback - Called during tree descent * when an object of "Type" is found - * post_order_visit - Called during tree post-order visit + * ascending_callback - Called during tree ascent * when an object of "Type" is found * context - Passed to user function(s) above * return_value - Location where return value of @@ -563,8 +554,8 @@ acpi_status acpi_walk_namespace(acpi_object_type type, acpi_handle start_object, u32 max_depth, - acpi_walk_callback pre_order_visit, - acpi_walk_callback post_order_visit, + acpi_walk_callback descending_callback, + acpi_walk_callback ascending_callback, void *context, void **return_value) { acpi_status status; @@ -574,7 +565,7 @@ acpi_walk_namespace(acpi_object_type type, /* Parameter validation */ if ((type > ACPI_TYPE_LOCAL_MAX) || - (!max_depth) || (!pre_order_visit && !post_order_visit)) { + (!max_depth) || (!descending_callback && !ascending_callback)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -605,14 +596,22 @@ acpi_walk_namespace(acpi_object_type type, goto unlock_and_exit; } + /* Now we can validate the starting node */ + + if (!acpi_ns_validate_handle(start_object)) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit2; + } + status = acpi_ns_walk_namespace(type, start_object, max_depth, - ACPI_NS_WALK_UNLOCK, pre_order_visit, - post_order_visit, context, - return_value); + ACPI_NS_WALK_UNLOCK, + descending_callback, ascending_callback, + context, return_value); +unlock_and_exit2: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_read_lock(&acpi_gbl_namespace_rw_lock); return_ACPI_STATUS(status); } @@ -684,7 +683,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, return (AE_CTRL_DEPTH); } - no_match = ACPI_STRCMP(hid->string, info->hid); + no_match = strcmp(hid->string, info->hid); ACPI_FREE(hid); if (no_match) { @@ -703,8 +702,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, found = FALSE; for (i = 0; i < cid->count; i++) { - if (ACPI_STRCMP(cid->ids[i].string, info->hid) - == 0) { + if (strcmp(cid->ids[i].string, info->hid) == 0) { /* Found a matching CID */ @@ -739,8 +737,8 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, /* We have a valid device, invoke the user function */ - status = info->user_function(obj_handle, nesting_level, info->context, - return_value); + status = info->user_function(obj_handle, nesting_level, + info->context, return_value); return (status); } @@ -856,7 +854,7 @@ acpi_attach_data(acpi_handle obj_handle, status = acpi_ns_attach_data(node, handler, data); - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); } @@ -902,7 +900,7 @@ acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler) status = acpi_ns_detach_data(node, handler); - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); } @@ -911,19 +909,22 @@ ACPI_EXPORT_SYMBOL(acpi_detach_data) /******************************************************************************* * - * FUNCTION: acpi_get_data + * FUNCTION: acpi_get_data_full * * PARAMETERS: obj_handle - Namespace node * handler - Handler used in call to attach_data * data - Where the data is returned + * callback - function to execute before returning * * RETURN: Status * - * DESCRIPTION: Retrieve data that was previously attached to a namespace node. + * DESCRIPTION: Retrieve data that was previously attached to a namespace node + * and execute a callback before returning. * ******************************************************************************/ acpi_status -acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) +acpi_get_data_full(acpi_handle obj_handle, acpi_object_handler handler, + void **data, void (*callback)(void *)) { struct acpi_namespace_node *node; acpi_status status; @@ -948,10 +949,34 @@ acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) } status = acpi_ns_get_attached_data(node, handler, data); + if (ACPI_SUCCESS(status) && callback) { + callback(*data); + } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); } +ACPI_EXPORT_SYMBOL(acpi_get_data_full) + +/******************************************************************************* + * + * FUNCTION: acpi_get_data + * + * PARAMETERS: obj_handle - Namespace node + * handler - Handler used in call to attach_data + * data - Where the data is returned + * + * RETURN: Status + * + * DESCRIPTION: Retrieve data that was previously attached to a namespace node. + * + ******************************************************************************/ +acpi_status +acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) +{ + return acpi_get_data_full(obj_handle, handler, data, NULL); +} + ACPI_EXPORT_SYMBOL(acpi_get_data) |
