162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: nspredef - Validation of ACPI predefined methods and objects 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2000 - 2023, Intel Corp. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci *****************************************************************************/ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#define ACPI_CREATE_PREDEFINED_TABLE 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <acpi/acpi.h> 1362306a36Sopenharmony_ci#include "accommon.h" 1462306a36Sopenharmony_ci#include "acnamesp.h" 1562306a36Sopenharmony_ci#include "acpredef.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define _COMPONENT ACPI_NAMESPACE 1862306a36Sopenharmony_ciACPI_MODULE_NAME("nspredef") 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci/******************************************************************************* 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * This module validates predefined ACPI objects that appear in the namespace, 2362306a36Sopenharmony_ci * at the time they are evaluated (via acpi_evaluate_object). The purpose of this 2462306a36Sopenharmony_ci * validation is to detect problems with BIOS-exposed predefined ACPI objects 2562306a36Sopenharmony_ci * before the results are returned to the ACPI-related drivers. 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * There are several areas that are validated: 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * 1) The number of input arguments as defined by the method/object in the 3062306a36Sopenharmony_ci * ASL is validated against the ACPI specification. 3162306a36Sopenharmony_ci * 2) The type of the return object (if any) is validated against the ACPI 3262306a36Sopenharmony_ci * specification. 3362306a36Sopenharmony_ci * 3) For returned package objects, the count of package elements is 3462306a36Sopenharmony_ci * validated, as well as the type of each package element. Nested 3562306a36Sopenharmony_ci * packages are supported. 3662306a36Sopenharmony_ci * 3762306a36Sopenharmony_ci * For any problems found, a warning message is issued. 3862306a36Sopenharmony_ci * 3962306a36Sopenharmony_ci ******************************************************************************/ 4062306a36Sopenharmony_ci/* Local prototypes */ 4162306a36Sopenharmony_cistatic acpi_status 4262306a36Sopenharmony_ciacpi_ns_check_reference(struct acpi_evaluate_info *info, 4362306a36Sopenharmony_ci union acpi_operand_object *return_object); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/******************************************************************************* 4862306a36Sopenharmony_ci * 4962306a36Sopenharmony_ci * FUNCTION: acpi_ns_check_return_value 5062306a36Sopenharmony_ci * 5162306a36Sopenharmony_ci * PARAMETERS: node - Namespace node for the method/object 5262306a36Sopenharmony_ci * info - Method execution information block 5362306a36Sopenharmony_ci * user_param_count - Number of parameters actually passed 5462306a36Sopenharmony_ci * return_status - Status from the object evaluation 5562306a36Sopenharmony_ci * return_object_ptr - Pointer to the object returned from the 5662306a36Sopenharmony_ci * evaluation of a method or object 5762306a36Sopenharmony_ci * 5862306a36Sopenharmony_ci * RETURN: Status 5962306a36Sopenharmony_ci * 6062306a36Sopenharmony_ci * DESCRIPTION: Check the value returned from a predefined name. 6162306a36Sopenharmony_ci * 6262306a36Sopenharmony_ci ******************************************************************************/ 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ciacpi_status 6562306a36Sopenharmony_ciacpi_ns_check_return_value(struct acpi_namespace_node *node, 6662306a36Sopenharmony_ci struct acpi_evaluate_info *info, 6762306a36Sopenharmony_ci u32 user_param_count, 6862306a36Sopenharmony_ci acpi_status return_status, 6962306a36Sopenharmony_ci union acpi_operand_object **return_object_ptr) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci acpi_status status; 7262306a36Sopenharmony_ci const union acpi_predefined_info *predefined; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ns_check_return_value); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci /* If not a predefined name, we cannot validate the return object */ 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci predefined = info->predefined; 7962306a36Sopenharmony_ci if (!predefined) { 8062306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci /* 8462306a36Sopenharmony_ci * If the method failed or did not actually return an object, we cannot 8562306a36Sopenharmony_ci * validate the return object 8662306a36Sopenharmony_ci */ 8762306a36Sopenharmony_ci if ((return_status != AE_OK) && (return_status != AE_CTRL_RETURN_VALUE)) { 8862306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci /* 9262306a36Sopenharmony_ci * Return value validation and possible repair. 9362306a36Sopenharmony_ci * 9462306a36Sopenharmony_ci * 1) Don't perform return value validation/repair if this feature 9562306a36Sopenharmony_ci * has been disabled via a global option. 9662306a36Sopenharmony_ci * 9762306a36Sopenharmony_ci * 2) We have a return value, but if one wasn't expected, just exit, 9862306a36Sopenharmony_ci * this is not a problem. For example, if the "Implicit Return" 9962306a36Sopenharmony_ci * feature is enabled, methods will always return a value. 10062306a36Sopenharmony_ci * 10162306a36Sopenharmony_ci * 3) If the return value can be of any type, then we cannot perform 10262306a36Sopenharmony_ci * any validation, just exit. 10362306a36Sopenharmony_ci */ 10462306a36Sopenharmony_ci if (acpi_gbl_disable_auto_repair || 10562306a36Sopenharmony_ci (!predefined->info.expected_btypes) || 10662306a36Sopenharmony_ci (predefined->info.expected_btypes == ACPI_RTYPE_ALL)) { 10762306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci /* 11162306a36Sopenharmony_ci * Check that the type of the main return object is what is expected 11262306a36Sopenharmony_ci * for this predefined name 11362306a36Sopenharmony_ci */ 11462306a36Sopenharmony_ci status = acpi_ns_check_object_type(info, return_object_ptr, 11562306a36Sopenharmony_ci predefined->info.expected_btypes, 11662306a36Sopenharmony_ci ACPI_NOT_PACKAGE_ELEMENT); 11762306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 11862306a36Sopenharmony_ci goto exit; 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci /* 12262306a36Sopenharmony_ci * 12362306a36Sopenharmony_ci * 4) If there is no return value and it is optional, just return 12462306a36Sopenharmony_ci * AE_OK (_WAK). 12562306a36Sopenharmony_ci */ 12662306a36Sopenharmony_ci if (!(*return_object_ptr)) { 12762306a36Sopenharmony_ci goto exit; 12862306a36Sopenharmony_ci } 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci /* 13162306a36Sopenharmony_ci * For returned Package objects, check the type of all sub-objects. 13262306a36Sopenharmony_ci * Note: Package may have been newly created by call above. 13362306a36Sopenharmony_ci */ 13462306a36Sopenharmony_ci if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) { 13562306a36Sopenharmony_ci info->parent_package = *return_object_ptr; 13662306a36Sopenharmony_ci status = acpi_ns_check_package(info, return_object_ptr); 13762306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci /* We might be able to fix some errors */ 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci if ((status != AE_AML_OPERAND_TYPE) && 14262306a36Sopenharmony_ci (status != AE_AML_OPERAND_VALUE)) { 14362306a36Sopenharmony_ci goto exit; 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci /* 14962306a36Sopenharmony_ci * The return object was OK, or it was successfully repaired above. 15062306a36Sopenharmony_ci * Now make some additional checks such as verifying that package 15162306a36Sopenharmony_ci * objects are sorted correctly (if required) or buffer objects have 15262306a36Sopenharmony_ci * the correct data width (bytes vs. dwords). These repairs are 15362306a36Sopenharmony_ci * performed on a per-name basis, i.e., the code is specific to 15462306a36Sopenharmony_ci * particular predefined names. 15562306a36Sopenharmony_ci */ 15662306a36Sopenharmony_ci status = acpi_ns_complex_repairs(info, node, status, return_object_ptr); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ciexit: 15962306a36Sopenharmony_ci /* 16062306a36Sopenharmony_ci * If the object validation failed or if we successfully repaired one 16162306a36Sopenharmony_ci * or more objects, mark the parent node to suppress further warning 16262306a36Sopenharmony_ci * messages during the next evaluation of the same method/object. 16362306a36Sopenharmony_ci */ 16462306a36Sopenharmony_ci if (ACPI_FAILURE(status) || (info->return_flags & ACPI_OBJECT_REPAIRED)) { 16562306a36Sopenharmony_ci node->flags |= ANOBJ_EVALUATED; 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci return_ACPI_STATUS(status); 16962306a36Sopenharmony_ci} 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci/******************************************************************************* 17262306a36Sopenharmony_ci * 17362306a36Sopenharmony_ci * FUNCTION: acpi_ns_check_object_type 17462306a36Sopenharmony_ci * 17562306a36Sopenharmony_ci * PARAMETERS: info - Method execution information block 17662306a36Sopenharmony_ci * return_object_ptr - Pointer to the object returned from the 17762306a36Sopenharmony_ci * evaluation of a method or object 17862306a36Sopenharmony_ci * expected_btypes - Bitmap of expected return type(s) 17962306a36Sopenharmony_ci * package_index - Index of object within parent package (if 18062306a36Sopenharmony_ci * applicable - ACPI_NOT_PACKAGE_ELEMENT 18162306a36Sopenharmony_ci * otherwise) 18262306a36Sopenharmony_ci * 18362306a36Sopenharmony_ci * RETURN: Status 18462306a36Sopenharmony_ci * 18562306a36Sopenharmony_ci * DESCRIPTION: Check the type of the return object against the expected object 18662306a36Sopenharmony_ci * type(s). Use of Btype allows multiple expected object types. 18762306a36Sopenharmony_ci * 18862306a36Sopenharmony_ci ******************************************************************************/ 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ciacpi_status 19162306a36Sopenharmony_ciacpi_ns_check_object_type(struct acpi_evaluate_info *info, 19262306a36Sopenharmony_ci union acpi_operand_object **return_object_ptr, 19362306a36Sopenharmony_ci u32 expected_btypes, u32 package_index) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci union acpi_operand_object *return_object = *return_object_ptr; 19662306a36Sopenharmony_ci acpi_status status = AE_OK; 19762306a36Sopenharmony_ci char type_buffer[96]; /* Room for 10 types */ 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci /* A Namespace node should not get here, but make sure */ 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci if (return_object && 20262306a36Sopenharmony_ci ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) { 20362306a36Sopenharmony_ci ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, 20462306a36Sopenharmony_ci info->node_flags, 20562306a36Sopenharmony_ci "Invalid return type - Found a Namespace node [%4.4s] type %s", 20662306a36Sopenharmony_ci return_object->node.name.ascii, 20762306a36Sopenharmony_ci acpi_ut_get_type_name(return_object->node. 20862306a36Sopenharmony_ci type))); 20962306a36Sopenharmony_ci return (AE_AML_OPERAND_TYPE); 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci /* 21362306a36Sopenharmony_ci * Convert the object type (ACPI_TYPE_xxx) to a bitmapped object type. 21462306a36Sopenharmony_ci * The bitmapped type allows multiple possible return types. 21562306a36Sopenharmony_ci * 21662306a36Sopenharmony_ci * Note, the cases below must handle all of the possible types returned 21762306a36Sopenharmony_ci * from all of the predefined names (including elements of returned 21862306a36Sopenharmony_ci * packages) 21962306a36Sopenharmony_ci */ 22062306a36Sopenharmony_ci info->return_btype = acpi_ns_get_bitmapped_type(return_object); 22162306a36Sopenharmony_ci if (info->return_btype == ACPI_RTYPE_ANY) { 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci /* Not one of the supported objects, must be incorrect */ 22462306a36Sopenharmony_ci goto type_error_exit; 22562306a36Sopenharmony_ci } 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci /* For reference objects, check that the reference type is correct */ 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci if ((info->return_btype & expected_btypes) == ACPI_RTYPE_REFERENCE) { 23062306a36Sopenharmony_ci status = acpi_ns_check_reference(info, return_object); 23162306a36Sopenharmony_ci return (status); 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci /* Attempt simple repair of the returned object if necessary */ 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci status = acpi_ns_simple_repair(info, expected_btypes, 23762306a36Sopenharmony_ci package_index, return_object_ptr); 23862306a36Sopenharmony_ci if (ACPI_SUCCESS(status)) { 23962306a36Sopenharmony_ci return (AE_OK); /* Successful repair */ 24062306a36Sopenharmony_ci } 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_citype_error_exit: 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci /* Create a string with all expected types for this predefined object */ 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci acpi_ut_get_expected_return_types(type_buffer, expected_btypes); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci if (!return_object) { 24962306a36Sopenharmony_ci ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, 25062306a36Sopenharmony_ci info->node_flags, 25162306a36Sopenharmony_ci "Expected return object of type %s", 25262306a36Sopenharmony_ci type_buffer)); 25362306a36Sopenharmony_ci } else if (package_index == ACPI_NOT_PACKAGE_ELEMENT) { 25462306a36Sopenharmony_ci ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, 25562306a36Sopenharmony_ci info->node_flags, 25662306a36Sopenharmony_ci "Return type mismatch - found %s, expected %s", 25762306a36Sopenharmony_ci acpi_ut_get_object_type_name 25862306a36Sopenharmony_ci (return_object), type_buffer)); 25962306a36Sopenharmony_ci } else { 26062306a36Sopenharmony_ci ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, 26162306a36Sopenharmony_ci info->node_flags, 26262306a36Sopenharmony_ci "Return Package type mismatch at index %u - " 26362306a36Sopenharmony_ci "found %s, expected %s", package_index, 26462306a36Sopenharmony_ci acpi_ut_get_object_type_name 26562306a36Sopenharmony_ci (return_object), type_buffer)); 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci return (AE_AML_OPERAND_TYPE); 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci/******************************************************************************* 27262306a36Sopenharmony_ci * 27362306a36Sopenharmony_ci * FUNCTION: acpi_ns_check_reference 27462306a36Sopenharmony_ci * 27562306a36Sopenharmony_ci * PARAMETERS: info - Method execution information block 27662306a36Sopenharmony_ci * return_object - Object returned from the evaluation of a 27762306a36Sopenharmony_ci * method or object 27862306a36Sopenharmony_ci * 27962306a36Sopenharmony_ci * RETURN: Status 28062306a36Sopenharmony_ci * 28162306a36Sopenharmony_ci * DESCRIPTION: Check a returned reference object for the correct reference 28262306a36Sopenharmony_ci * type. The only reference type that can be returned from a 28362306a36Sopenharmony_ci * predefined method is a named reference. All others are invalid. 28462306a36Sopenharmony_ci * 28562306a36Sopenharmony_ci ******************************************************************************/ 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_cistatic acpi_status 28862306a36Sopenharmony_ciacpi_ns_check_reference(struct acpi_evaluate_info *info, 28962306a36Sopenharmony_ci union acpi_operand_object *return_object) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci /* 29362306a36Sopenharmony_ci * Check the reference object for the correct reference type (opcode). 29462306a36Sopenharmony_ci * The only type of reference that can be converted to a union acpi_object is 29562306a36Sopenharmony_ci * a reference to a named object (reference class: NAME) 29662306a36Sopenharmony_ci */ 29762306a36Sopenharmony_ci if (return_object->reference.class == ACPI_REFCLASS_NAME) { 29862306a36Sopenharmony_ci return (AE_OK); 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, 30262306a36Sopenharmony_ci "Return type mismatch - unexpected reference object type [%s] %2.2X", 30362306a36Sopenharmony_ci acpi_ut_get_reference_name(return_object), 30462306a36Sopenharmony_ci return_object->reference.class)); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci return (AE_AML_OPERAND_TYPE); 30762306a36Sopenharmony_ci} 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci/******************************************************************************* 31062306a36Sopenharmony_ci * 31162306a36Sopenharmony_ci * FUNCTION: acpi_ns_get_bitmapped_type 31262306a36Sopenharmony_ci * 31362306a36Sopenharmony_ci * PARAMETERS: return_object - Object returned from method/obj evaluation 31462306a36Sopenharmony_ci * 31562306a36Sopenharmony_ci * RETURN: Object return type. ACPI_RTYPE_ANY indicates that the object 31662306a36Sopenharmony_ci * type is not supported. ACPI_RTYPE_NONE indicates that no 31762306a36Sopenharmony_ci * object was returned (return_object is NULL). 31862306a36Sopenharmony_ci * 31962306a36Sopenharmony_ci * DESCRIPTION: Convert object type into a bitmapped object return type. 32062306a36Sopenharmony_ci * 32162306a36Sopenharmony_ci ******************************************************************************/ 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_cistatic u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci u32 return_btype; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci if (!return_object) { 32862306a36Sopenharmony_ci return (ACPI_RTYPE_NONE); 32962306a36Sopenharmony_ci } 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci /* Map acpi_object_type to internal bitmapped type */ 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci switch (return_object->common.type) { 33462306a36Sopenharmony_ci case ACPI_TYPE_INTEGER: 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci return_btype = ACPI_RTYPE_INTEGER; 33762306a36Sopenharmony_ci break; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci case ACPI_TYPE_BUFFER: 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci return_btype = ACPI_RTYPE_BUFFER; 34262306a36Sopenharmony_ci break; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci case ACPI_TYPE_STRING: 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci return_btype = ACPI_RTYPE_STRING; 34762306a36Sopenharmony_ci break; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci case ACPI_TYPE_PACKAGE: 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci return_btype = ACPI_RTYPE_PACKAGE; 35262306a36Sopenharmony_ci break; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci case ACPI_TYPE_LOCAL_REFERENCE: 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci return_btype = ACPI_RTYPE_REFERENCE; 35762306a36Sopenharmony_ci break; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci default: 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci /* Not one of the supported objects, must be incorrect */ 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci return_btype = ACPI_RTYPE_ANY; 36462306a36Sopenharmony_ci break; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci return (return_btype); 36862306a36Sopenharmony_ci} 369