cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

uteval.c (8585B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: uteval - Object evaluation
      5 *
      6 * Copyright (C) 2000 - 2022, Intel Corp.
      7 *
      8 *****************************************************************************/
      9
     10#include <acpi/acpi.h>
     11#include "accommon.h"
     12#include "acnamesp.h"
     13
     14#define _COMPONENT          ACPI_UTILITIES
     15ACPI_MODULE_NAME("uteval")
     16
     17/*******************************************************************************
     18 *
     19 * FUNCTION:    acpi_ut_evaluate_object
     20 *
     21 * PARAMETERS:  prefix_node         - Starting node
     22 *              path                - Path to object from starting node
     23 *              expected_return_types - Bitmap of allowed return types
     24 *              return_desc         - Where a return value is stored
     25 *
     26 * RETURN:      Status
     27 *
     28 * DESCRIPTION: Evaluates a namespace object and verifies the type of the
     29 *              return object. Common code that simplifies accessing objects
     30 *              that have required return objects of fixed types.
     31 *
     32 *              NOTE: Internal function, no parameter validation
     33 *
     34 ******************************************************************************/
     35
     36acpi_status
     37acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
     38			const char *path,
     39			u32 expected_return_btypes,
     40			union acpi_operand_object **return_desc)
     41{
     42	struct acpi_evaluate_info *info;
     43	acpi_status status;
     44	u32 return_btype;
     45
     46	ACPI_FUNCTION_TRACE(ut_evaluate_object);
     47
     48	/* Allocate the evaluation information block */
     49
     50	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
     51	if (!info) {
     52		return_ACPI_STATUS(AE_NO_MEMORY);
     53	}
     54
     55	info->prefix_node = prefix_node;
     56	info->relative_pathname = path;
     57
     58	/* Evaluate the object/method */
     59
     60	status = acpi_ns_evaluate(info);
     61	if (ACPI_FAILURE(status)) {
     62		if (status == AE_NOT_FOUND) {
     63			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
     64					  "[%4.4s.%s] was not found\n",
     65					  acpi_ut_get_node_name(prefix_node),
     66					  path));
     67		} else {
     68			ACPI_ERROR_METHOD("Method execution failed",
     69					  prefix_node, path, status);
     70		}
     71
     72		goto cleanup;
     73	}
     74
     75	/* Did we get a return object? */
     76
     77	if (!info->return_object) {
     78		if (expected_return_btypes) {
     79			ACPI_ERROR_METHOD("No object was returned from",
     80					  prefix_node, path, AE_NOT_EXIST);
     81
     82			status = AE_NOT_EXIST;
     83		}
     84
     85		goto cleanup;
     86	}
     87
     88	/* Map the return object type to the bitmapped type */
     89
     90	switch ((info->return_object)->common.type) {
     91	case ACPI_TYPE_INTEGER:
     92
     93		return_btype = ACPI_BTYPE_INTEGER;
     94		break;
     95
     96	case ACPI_TYPE_BUFFER:
     97
     98		return_btype = ACPI_BTYPE_BUFFER;
     99		break;
    100
    101	case ACPI_TYPE_STRING:
    102
    103		return_btype = ACPI_BTYPE_STRING;
    104		break;
    105
    106	case ACPI_TYPE_PACKAGE:
    107
    108		return_btype = ACPI_BTYPE_PACKAGE;
    109		break;
    110
    111	default:
    112
    113		return_btype = 0;
    114		break;
    115	}
    116
    117	if ((acpi_gbl_enable_interpreter_slack) && (!expected_return_btypes)) {
    118		/*
    119		 * We received a return object, but one was not expected. This can
    120		 * happen frequently if the "implicit return" feature is enabled.
    121		 * Just delete the return object and return AE_OK.
    122		 */
    123		acpi_ut_remove_reference(info->return_object);
    124		goto cleanup;
    125	}
    126
    127	/* Is the return object one of the expected types? */
    128
    129	if (!(expected_return_btypes & return_btype)) {
    130		ACPI_ERROR_METHOD("Return object type is incorrect",
    131				  prefix_node, path, AE_TYPE);
    132
    133		ACPI_ERROR((AE_INFO,
    134			    "Type returned from %s was incorrect: %s, expected Btypes: 0x%X",
    135			    path,
    136			    acpi_ut_get_object_type_name(info->return_object),
    137			    expected_return_btypes));
    138
    139		/* On error exit, we must delete the return object */
    140
    141		acpi_ut_remove_reference(info->return_object);
    142		status = AE_TYPE;
    143		goto cleanup;
    144	}
    145
    146	/* Object type is OK, return it */
    147
    148	*return_desc = info->return_object;
    149
    150cleanup:
    151	ACPI_FREE(info);
    152	return_ACPI_STATUS(status);
    153}
    154
    155/*******************************************************************************
    156 *
    157 * FUNCTION:    acpi_ut_evaluate_numeric_object
    158 *
    159 * PARAMETERS:  object_name         - Object name to be evaluated
    160 *              device_node         - Node for the device
    161 *              value               - Where the value is returned
    162 *
    163 * RETURN:      Status
    164 *
    165 * DESCRIPTION: Evaluates a numeric namespace object for a selected device
    166 *              and stores result in *Value.
    167 *
    168 *              NOTE: Internal function, no parameter validation
    169 *
    170 ******************************************************************************/
    171
    172acpi_status
    173acpi_ut_evaluate_numeric_object(const char *object_name,
    174				struct acpi_namespace_node *device_node,
    175				u64 *value)
    176{
    177	union acpi_operand_object *obj_desc;
    178	acpi_status status;
    179
    180	ACPI_FUNCTION_TRACE(ut_evaluate_numeric_object);
    181
    182	status = acpi_ut_evaluate_object(device_node, object_name,
    183					 ACPI_BTYPE_INTEGER, &obj_desc);
    184	if (ACPI_FAILURE(status)) {
    185		return_ACPI_STATUS(status);
    186	}
    187
    188	/* Get the returned Integer */
    189
    190	*value = obj_desc->integer.value;
    191
    192	/* On exit, we must delete the return object */
    193
    194	acpi_ut_remove_reference(obj_desc);
    195	return_ACPI_STATUS(status);
    196}
    197
    198/*******************************************************************************
    199 *
    200 * FUNCTION:    acpi_ut_execute_STA
    201 *
    202 * PARAMETERS:  device_node         - Node for the device
    203 *              flags               - Where the status flags are returned
    204 *
    205 * RETURN:      Status
    206 *
    207 * DESCRIPTION: Executes _STA for selected device and stores results in
    208 *              *Flags. If _STA does not exist, then the device is assumed
    209 *              to be present/functional/enabled (as per the ACPI spec).
    210 *
    211 *              NOTE: Internal function, no parameter validation
    212 *
    213 ******************************************************************************/
    214
    215acpi_status
    216acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags)
    217{
    218	union acpi_operand_object *obj_desc;
    219	acpi_status status;
    220
    221	ACPI_FUNCTION_TRACE(ut_execute_STA);
    222
    223	status = acpi_ut_evaluate_object(device_node, METHOD_NAME__STA,
    224					 ACPI_BTYPE_INTEGER, &obj_desc);
    225	if (ACPI_FAILURE(status)) {
    226		if (AE_NOT_FOUND == status) {
    227			/*
    228			 * if _STA does not exist, then (as per the ACPI specification),
    229			 * the returned flags will indicate that the device is present,
    230			 * functional, and enabled.
    231			 */
    232			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
    233					  "_STA on %4.4s was not found, assuming device is present\n",
    234					  acpi_ut_get_node_name(device_node)));
    235
    236			*flags = ACPI_UINT32_MAX;
    237			status = AE_OK;
    238		}
    239
    240		return_ACPI_STATUS(status);
    241	}
    242
    243	/* Extract the status flags */
    244
    245	*flags = (u32) obj_desc->integer.value;
    246
    247	/* On exit, we must delete the return object */
    248
    249	acpi_ut_remove_reference(obj_desc);
    250	return_ACPI_STATUS(status);
    251}
    252
    253/*******************************************************************************
    254 *
    255 * FUNCTION:    acpi_ut_execute_power_methods
    256 *
    257 * PARAMETERS:  device_node         - Node for the device
    258 *              method_names        - Array of power method names
    259 *              method_count        - Number of methods to execute
    260 *              out_values          - Where the power method values are returned
    261 *
    262 * RETURN:      Status, out_values
    263 *
    264 * DESCRIPTION: Executes the specified power methods for the device and returns
    265 *              the result(s).
    266 *
    267 *              NOTE: Internal function, no parameter validation
    268 *
    269******************************************************************************/
    270
    271acpi_status
    272acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node,
    273			      const char **method_names,
    274			      u8 method_count, u8 *out_values)
    275{
    276	union acpi_operand_object *obj_desc;
    277	acpi_status status;
    278	acpi_status final_status = AE_NOT_FOUND;
    279	u32 i;
    280
    281	ACPI_FUNCTION_TRACE(ut_execute_power_methods);
    282
    283	for (i = 0; i < method_count; i++) {
    284		/*
    285		 * Execute the power method (_sx_d or _sx_w). The only allowable
    286		 * return type is an Integer.
    287		 */
    288		status = acpi_ut_evaluate_object(device_node,
    289						 ACPI_CAST_PTR(char,
    290							       method_names[i]),
    291						 ACPI_BTYPE_INTEGER, &obj_desc);
    292		if (ACPI_SUCCESS(status)) {
    293			out_values[i] = (u8)obj_desc->integer.value;
    294
    295			/* Delete the return object */
    296
    297			acpi_ut_remove_reference(obj_desc);
    298			final_status = AE_OK;	/* At least one value is valid */
    299			continue;
    300		}
    301
    302		out_values[i] = ACPI_UINT8_MAX;
    303		if (status == AE_NOT_FOUND) {
    304			continue;	/* Ignore if not found */
    305		}
    306
    307		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
    308				  "Failed %s on Device %4.4s, %s\n",
    309				  ACPI_CAST_PTR(char, method_names[i]),
    310				  acpi_ut_get_node_name(device_node),
    311				  acpi_format_exception(status)));
    312	}
    313
    314	return_ACPI_STATUS(final_status);
    315}