diff options
Diffstat (limited to 'drivers/acpi/acpica/nspredef.c')
-rw-r--r-- | drivers/acpi/acpica/nspredef.c | 368 |
1 files changed, 368 insertions, 0 deletions
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c new file mode 100644 index 000000000..c0db6690b --- /dev/null +++ b/drivers/acpi/acpica/nspredef.c @@ -0,0 +1,368 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/****************************************************************************** + * + * Module Name: nspredef - Validation of ACPI predefined methods and objects + * + * Copyright (C) 2000 - 2022, Intel Corp. + * + *****************************************************************************/ + +#define ACPI_CREATE_PREDEFINED_TABLE + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acnamesp.h" +#include "acpredef.h" + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nspredef") + +/******************************************************************************* + * + * This module validates predefined ACPI objects that appear in the namespace, + * at the time they are evaluated (via acpi_evaluate_object). The purpose of this + * validation is to detect problems with BIOS-exposed predefined ACPI objects + * before the results are returned to the ACPI-related drivers. + * + * There are several areas that are validated: + * + * 1) The number of input arguments as defined by the method/object in the + * ASL is validated against the ACPI specification. + * 2) The type of the return object (if any) is validated against the ACPI + * specification. + * 3) For returned package objects, the count of package elements is + * validated, as well as the type of each package element. Nested + * packages are supported. + * + * For any problems found, a warning message is issued. + * + ******************************************************************************/ +/* Local prototypes */ +static acpi_status +acpi_ns_check_reference(struct acpi_evaluate_info *info, + union acpi_operand_object *return_object); + +static u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object); + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_return_value + * + * PARAMETERS: node - Namespace node for the method/object + * info - Method execution information block + * user_param_count - Number of parameters actually passed + * return_status - Status from the object evaluation + * return_object_ptr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status + * + * DESCRIPTION: Check the value returned from a predefined name. + * + ******************************************************************************/ + +acpi_status +acpi_ns_check_return_value(struct acpi_namespace_node *node, + struct acpi_evaluate_info *info, + u32 user_param_count, + acpi_status return_status, + union acpi_operand_object **return_object_ptr) +{ + acpi_status status; + const union acpi_predefined_info *predefined; + + ACPI_FUNCTION_TRACE(ns_check_return_value); + + /* If not a predefined name, we cannot validate the return object */ + + predefined = info->predefined; + if (!predefined) { + return_ACPI_STATUS(AE_OK); + } + + /* + * If the method failed or did not actually return an object, we cannot + * validate the return object + */ + if ((return_status != AE_OK) && (return_status != AE_CTRL_RETURN_VALUE)) { + return_ACPI_STATUS(AE_OK); + } + + /* + * Return value validation and possible repair. + * + * 1) Don't perform return value validation/repair if this feature + * has been disabled via a global option. + * + * 2) We have a return value, but if one wasn't expected, just exit, + * this is not a problem. For example, if the "Implicit Return" + * feature is enabled, methods will always return a value. + * + * 3) If the return value can be of any type, then we cannot perform + * any validation, just exit. + */ + if (acpi_gbl_disable_auto_repair || + (!predefined->info.expected_btypes) || + (predefined->info.expected_btypes == ACPI_RTYPE_ALL)) { + return_ACPI_STATUS(AE_OK); + } + + /* + * Check that the type of the main return object is what is expected + * for this predefined name + */ + status = acpi_ns_check_object_type(info, return_object_ptr, + predefined->info.expected_btypes, + ACPI_NOT_PACKAGE_ELEMENT); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* + * + * 4) If there is no return value and it is optional, just return + * AE_OK (_WAK). + */ + if (!(*return_object_ptr)) { + goto exit; + } + + /* + * For returned Package objects, check the type of all sub-objects. + * Note: Package may have been newly created by call above. + */ + if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) { + info->parent_package = *return_object_ptr; + status = acpi_ns_check_package(info, return_object_ptr); + if (ACPI_FAILURE(status)) { + + /* We might be able to fix some errors */ + + if ((status != AE_AML_OPERAND_TYPE) && + (status != AE_AML_OPERAND_VALUE)) { + goto exit; + } + } + } + + /* + * The return object was OK, or it was successfully repaired above. + * Now make some additional checks such as verifying that package + * objects are sorted correctly (if required) or buffer objects have + * the correct data width (bytes vs. dwords). These repairs are + * performed on a per-name basis, i.e., the code is specific to + * particular predefined names. + */ + status = acpi_ns_complex_repairs(info, node, status, return_object_ptr); + +exit: + /* + * If the object validation failed or if we successfully repaired one + * or more objects, mark the parent node to suppress further warning + * messages during the next evaluation of the same method/object. + */ + if (ACPI_FAILURE(status) || (info->return_flags & ACPI_OBJECT_REPAIRED)) { + node->flags |= ANOBJ_EVALUATED; + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_object_type + * + * PARAMETERS: info - Method execution information block + * return_object_ptr - Pointer to the object returned from the + * evaluation of a method or object + * expected_btypes - Bitmap of expected return type(s) + * package_index - Index of object within parent package (if + * applicable - ACPI_NOT_PACKAGE_ELEMENT + * otherwise) + * + * RETURN: Status + * + * DESCRIPTION: Check the type of the return object against the expected object + * type(s). Use of Btype allows multiple expected object types. + * + ******************************************************************************/ + +acpi_status +acpi_ns_check_object_type(struct acpi_evaluate_info *info, + union acpi_operand_object **return_object_ptr, + u32 expected_btypes, u32 package_index) +{ + union acpi_operand_object *return_object = *return_object_ptr; + acpi_status status = AE_OK; + char type_buffer[96]; /* Room for 10 types */ + + /* A Namespace node should not get here, but make sure */ + + if (return_object && + ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) { + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, + "Invalid return type - Found a Namespace node [%4.4s] type %s", + return_object->node.name.ascii, + acpi_ut_get_type_name(return_object->node. + type))); + return (AE_AML_OPERAND_TYPE); + } + + /* + * Convert the object type (ACPI_TYPE_xxx) to a bitmapped object type. + * The bitmapped type allows multiple possible return types. + * + * Note, the cases below must handle all of the possible types returned + * from all of the predefined names (including elements of returned + * packages) + */ + info->return_btype = acpi_ns_get_bitmapped_type(return_object); + if (info->return_btype == ACPI_RTYPE_ANY) { + + /* Not one of the supported objects, must be incorrect */ + goto type_error_exit; + } + + /* For reference objects, check that the reference type is correct */ + + if ((info->return_btype & expected_btypes) == ACPI_RTYPE_REFERENCE) { + status = acpi_ns_check_reference(info, return_object); + return (status); + } + + /* Attempt simple repair of the returned object if necessary */ + + status = acpi_ns_simple_repair(info, expected_btypes, + package_index, return_object_ptr); + if (ACPI_SUCCESS(status)) { + return (AE_OK); /* Successful repair */ + } + +type_error_exit: + + /* Create a string with all expected types for this predefined object */ + + acpi_ut_get_expected_return_types(type_buffer, expected_btypes); + + if (!return_object) { + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, + "Expected return object of type %s", + type_buffer)); + } else if (package_index == ACPI_NOT_PACKAGE_ELEMENT) { + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, + "Return type mismatch - found %s, expected %s", + acpi_ut_get_object_type_name + (return_object), type_buffer)); + } else { + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, + "Return Package type mismatch at index %u - " + "found %s, expected %s", package_index, + acpi_ut_get_object_type_name + (return_object), type_buffer)); + } + + return (AE_AML_OPERAND_TYPE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_reference + * + * PARAMETERS: info - Method execution information block + * return_object - Object returned from the evaluation of a + * method or object + * + * RETURN: Status + * + * DESCRIPTION: Check a returned reference object for the correct reference + * type. The only reference type that can be returned from a + * predefined method is a named reference. All others are invalid. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_check_reference(struct acpi_evaluate_info *info, + union acpi_operand_object *return_object) +{ + + /* + * Check the reference object for the correct reference type (opcode). + * The only type of reference that can be converted to a union acpi_object is + * a reference to a named object (reference class: NAME) + */ + if (return_object->reference.class == ACPI_REFCLASS_NAME) { + return (AE_OK); + } + + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, + "Return type mismatch - unexpected reference object type [%s] %2.2X", + acpi_ut_get_reference_name(return_object), + return_object->reference.class)); + + return (AE_AML_OPERAND_TYPE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_get_bitmapped_type + * + * PARAMETERS: return_object - Object returned from method/obj evaluation + * + * RETURN: Object return type. ACPI_RTYPE_ANY indicates that the object + * type is not supported. ACPI_RTYPE_NONE indicates that no + * object was returned (return_object is NULL). + * + * DESCRIPTION: Convert object type into a bitmapped object return type. + * + ******************************************************************************/ + +static u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object) +{ + u32 return_btype; + + if (!return_object) { + return (ACPI_RTYPE_NONE); + } + + /* Map acpi_object_type to internal bitmapped type */ + + switch (return_object->common.type) { + case ACPI_TYPE_INTEGER: + + return_btype = ACPI_RTYPE_INTEGER; + break; + + case ACPI_TYPE_BUFFER: + + return_btype = ACPI_RTYPE_BUFFER; + break; + + case ACPI_TYPE_STRING: + + return_btype = ACPI_RTYPE_STRING; + break; + + case ACPI_TYPE_PACKAGE: + + return_btype = ACPI_RTYPE_PACKAGE; + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + + return_btype = ACPI_RTYPE_REFERENCE; + break; + + default: + + /* Not one of the supported objects, must be incorrect */ + + return_btype = ACPI_RTYPE_ANY; + break; + } + + return (return_btype); +} |