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

nsconvert.c (13161B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: nsconvert - Object conversions for objects returned by
      5 *                          predefined methods
      6 *
      7 * Copyright (C) 2000 - 2022, Intel Corp.
      8 *
      9 *****************************************************************************/
     10
     11#include <acpi/acpi.h>
     12#include "accommon.h"
     13#include "acnamesp.h"
     14#include "acinterp.h"
     15#include "acpredef.h"
     16#include "amlresrc.h"
     17
     18#define _COMPONENT          ACPI_NAMESPACE
     19ACPI_MODULE_NAME("nsconvert")
     20
     21/*******************************************************************************
     22 *
     23 * FUNCTION:    acpi_ns_convert_to_integer
     24 *
     25 * PARAMETERS:  original_object     - Object to be converted
     26 *              return_object       - Where the new converted object is returned
     27 *
     28 * RETURN:      Status. AE_OK if conversion was successful.
     29 *
     30 * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
     31 *
     32 ******************************************************************************/
     33acpi_status
     34acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
     35			   union acpi_operand_object **return_object)
     36{
     37	union acpi_operand_object *new_object;
     38	acpi_status status;
     39	u64 value = 0;
     40	u32 i;
     41
     42	switch (original_object->common.type) {
     43	case ACPI_TYPE_STRING:
     44
     45		/* String-to-Integer conversion */
     46
     47		status =
     48		    acpi_ut_strtoul64(original_object->string.pointer, &value);
     49		if (ACPI_FAILURE(status)) {
     50			return (status);
     51		}
     52		break;
     53
     54	case ACPI_TYPE_BUFFER:
     55
     56		/* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
     57
     58		if (original_object->buffer.length > 8) {
     59			return (AE_AML_OPERAND_TYPE);
     60		}
     61
     62		/* Extract each buffer byte to create the integer */
     63
     64		for (i = 0; i < original_object->buffer.length; i++) {
     65			value |= ((u64)
     66				  original_object->buffer.pointer[i] << (i *
     67									 8));
     68		}
     69		break;
     70
     71	default:
     72
     73		return (AE_AML_OPERAND_TYPE);
     74	}
     75
     76	new_object = acpi_ut_create_integer_object(value);
     77	if (!new_object) {
     78		return (AE_NO_MEMORY);
     79	}
     80
     81	*return_object = new_object;
     82	return (AE_OK);
     83}
     84
     85/*******************************************************************************
     86 *
     87 * FUNCTION:    acpi_ns_convert_to_string
     88 *
     89 * PARAMETERS:  original_object     - Object to be converted
     90 *              return_object       - Where the new converted object is returned
     91 *
     92 * RETURN:      Status. AE_OK if conversion was successful.
     93 *
     94 * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
     95 *
     96 ******************************************************************************/
     97
     98acpi_status
     99acpi_ns_convert_to_string(union acpi_operand_object *original_object,
    100			  union acpi_operand_object **return_object)
    101{
    102	union acpi_operand_object *new_object;
    103	acpi_size length;
    104	acpi_status status;
    105
    106	switch (original_object->common.type) {
    107	case ACPI_TYPE_INTEGER:
    108		/*
    109		 * Integer-to-String conversion. Commonly, convert
    110		 * an integer of value 0 to a NULL string. The last element of
    111		 * _BIF and _BIX packages occasionally need this fix.
    112		 */
    113		if (original_object->integer.value == 0) {
    114
    115			/* Allocate a new NULL string object */
    116
    117			new_object = acpi_ut_create_string_object(0);
    118			if (!new_object) {
    119				return (AE_NO_MEMORY);
    120			}
    121		} else {
    122			status = acpi_ex_convert_to_string(original_object,
    123							   &new_object,
    124							   ACPI_IMPLICIT_CONVERT_HEX);
    125			if (ACPI_FAILURE(status)) {
    126				return (status);
    127			}
    128		}
    129		break;
    130
    131	case ACPI_TYPE_BUFFER:
    132		/*
    133		 * Buffer-to-String conversion. Use a to_string
    134		 * conversion, no transform performed on the buffer data. The best
    135		 * example of this is the _BIF method, where the string data from
    136		 * the battery is often (incorrectly) returned as buffer object(s).
    137		 */
    138		length = 0;
    139		while ((length < original_object->buffer.length) &&
    140		       (original_object->buffer.pointer[length])) {
    141			length++;
    142		}
    143
    144		/* Allocate a new string object */
    145
    146		new_object = acpi_ut_create_string_object(length);
    147		if (!new_object) {
    148			return (AE_NO_MEMORY);
    149		}
    150
    151		/*
    152		 * Copy the raw buffer data with no transform. String is already NULL
    153		 * terminated at Length+1.
    154		 */
    155		memcpy(new_object->string.pointer,
    156		       original_object->buffer.pointer, length);
    157		break;
    158
    159	default:
    160
    161		return (AE_AML_OPERAND_TYPE);
    162	}
    163
    164	*return_object = new_object;
    165	return (AE_OK);
    166}
    167
    168/*******************************************************************************
    169 *
    170 * FUNCTION:    acpi_ns_convert_to_buffer
    171 *
    172 * PARAMETERS:  original_object     - Object to be converted
    173 *              return_object       - Where the new converted object is returned
    174 *
    175 * RETURN:      Status. AE_OK if conversion was successful.
    176 *
    177 * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
    178 *
    179 ******************************************************************************/
    180
    181acpi_status
    182acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
    183			  union acpi_operand_object **return_object)
    184{
    185	union acpi_operand_object *new_object;
    186	acpi_status status;
    187	union acpi_operand_object **elements;
    188	u32 *dword_buffer;
    189	u32 count;
    190	u32 i;
    191
    192	switch (original_object->common.type) {
    193	case ACPI_TYPE_INTEGER:
    194		/*
    195		 * Integer-to-Buffer conversion.
    196		 * Convert the Integer to a packed-byte buffer. _MAT and other
    197		 * objects need this sometimes, if a read has been performed on a
    198		 * Field object that is less than or equal to the global integer
    199		 * size (32 or 64 bits).
    200		 */
    201		status =
    202		    acpi_ex_convert_to_buffer(original_object, &new_object);
    203		if (ACPI_FAILURE(status)) {
    204			return (status);
    205		}
    206		break;
    207
    208	case ACPI_TYPE_STRING:
    209
    210		/* String-to-Buffer conversion. Simple data copy */
    211
    212		new_object = acpi_ut_create_buffer_object
    213		    (original_object->string.length);
    214		if (!new_object) {
    215			return (AE_NO_MEMORY);
    216		}
    217
    218		memcpy(new_object->buffer.pointer,
    219		       original_object->string.pointer,
    220		       original_object->string.length);
    221		break;
    222
    223	case ACPI_TYPE_PACKAGE:
    224		/*
    225		 * This case is often seen for predefined names that must return a
    226		 * Buffer object with multiple DWORD integers within. For example,
    227		 * _FDE and _GTM. The Package can be converted to a Buffer.
    228		 */
    229
    230		/* All elements of the Package must be integers */
    231
    232		elements = original_object->package.elements;
    233		count = original_object->package.count;
    234
    235		for (i = 0; i < count; i++) {
    236			if ((!*elements) ||
    237			    ((*elements)->common.type != ACPI_TYPE_INTEGER)) {
    238				return (AE_AML_OPERAND_TYPE);
    239			}
    240			elements++;
    241		}
    242
    243		/* Create the new buffer object to replace the Package */
    244
    245		new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
    246		if (!new_object) {
    247			return (AE_NO_MEMORY);
    248		}
    249
    250		/* Copy the package elements (integers) to the buffer as DWORDs */
    251
    252		elements = original_object->package.elements;
    253		dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
    254
    255		for (i = 0; i < count; i++) {
    256			*dword_buffer = (u32)(*elements)->integer.value;
    257			dword_buffer++;
    258			elements++;
    259		}
    260		break;
    261
    262	default:
    263
    264		return (AE_AML_OPERAND_TYPE);
    265	}
    266
    267	*return_object = new_object;
    268	return (AE_OK);
    269}
    270
    271/*******************************************************************************
    272 *
    273 * FUNCTION:    acpi_ns_convert_to_unicode
    274 *
    275 * PARAMETERS:  scope               - Namespace node for the method/object
    276 *              original_object     - ASCII String Object to be converted
    277 *              return_object       - Where the new converted object is returned
    278 *
    279 * RETURN:      Status. AE_OK if conversion was successful.
    280 *
    281 * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer.
    282 *
    283 ******************************************************************************/
    284
    285acpi_status
    286acpi_ns_convert_to_unicode(struct acpi_namespace_node *scope,
    287			   union acpi_operand_object *original_object,
    288			   union acpi_operand_object **return_object)
    289{
    290	union acpi_operand_object *new_object;
    291	char *ascii_string;
    292	u16 *unicode_buffer;
    293	u32 unicode_length;
    294	u32 i;
    295
    296	if (!original_object) {
    297		return (AE_OK);
    298	}
    299
    300	/* If a Buffer was returned, it must be at least two bytes long */
    301
    302	if (original_object->common.type == ACPI_TYPE_BUFFER) {
    303		if (original_object->buffer.length < 2) {
    304			return (AE_AML_OPERAND_VALUE);
    305		}
    306
    307		*return_object = NULL;
    308		return (AE_OK);
    309	}
    310
    311	/*
    312	 * The original object is an ASCII string. Convert this string to
    313	 * a unicode buffer.
    314	 */
    315	ascii_string = original_object->string.pointer;
    316	unicode_length = (original_object->string.length * 2) + 2;
    317
    318	/* Create a new buffer object for the Unicode data */
    319
    320	new_object = acpi_ut_create_buffer_object(unicode_length);
    321	if (!new_object) {
    322		return (AE_NO_MEMORY);
    323	}
    324
    325	unicode_buffer = ACPI_CAST_PTR(u16, new_object->buffer.pointer);
    326
    327	/* Convert ASCII to Unicode */
    328
    329	for (i = 0; i < original_object->string.length; i++) {
    330		unicode_buffer[i] = (u16)ascii_string[i];
    331	}
    332
    333	*return_object = new_object;
    334	return (AE_OK);
    335}
    336
    337/*******************************************************************************
    338 *
    339 * FUNCTION:    acpi_ns_convert_to_resource
    340 *
    341 * PARAMETERS:  scope               - Namespace node for the method/object
    342 *              original_object     - Object to be converted
    343 *              return_object       - Where the new converted object is returned
    344 *
    345 * RETURN:      Status. AE_OK if conversion was successful
    346 *
    347 * DESCRIPTION: Attempt to convert a Integer object to a resource_template
    348 *              Buffer.
    349 *
    350 ******************************************************************************/
    351
    352acpi_status
    353acpi_ns_convert_to_resource(struct acpi_namespace_node *scope,
    354			    union acpi_operand_object *original_object,
    355			    union acpi_operand_object **return_object)
    356{
    357	union acpi_operand_object *new_object;
    358	u8 *buffer;
    359
    360	/*
    361	 * We can fix the following cases for an expected resource template:
    362	 * 1. No return value (interpreter slack mode is disabled)
    363	 * 2. A "Return (Zero)" statement
    364	 * 3. A "Return empty buffer" statement
    365	 *
    366	 * We will return a buffer containing a single end_tag
    367	 * resource descriptor.
    368	 */
    369	if (original_object) {
    370		switch (original_object->common.type) {
    371		case ACPI_TYPE_INTEGER:
    372
    373			/* We can only repair an Integer==0 */
    374
    375			if (original_object->integer.value) {
    376				return (AE_AML_OPERAND_TYPE);
    377			}
    378			break;
    379
    380		case ACPI_TYPE_BUFFER:
    381
    382			if (original_object->buffer.length) {
    383
    384				/* Additional checks can be added in the future */
    385
    386				*return_object = NULL;
    387				return (AE_OK);
    388			}
    389			break;
    390
    391		case ACPI_TYPE_STRING:
    392		default:
    393
    394			return (AE_AML_OPERAND_TYPE);
    395		}
    396	}
    397
    398	/* Create the new buffer object for the resource descriptor */
    399
    400	new_object = acpi_ut_create_buffer_object(2);
    401	if (!new_object) {
    402		return (AE_NO_MEMORY);
    403	}
    404
    405	buffer = ACPI_CAST_PTR(u8, new_object->buffer.pointer);
    406
    407	/* Initialize the Buffer with a single end_tag descriptor */
    408
    409	buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);
    410	buffer[1] = 0x00;
    411
    412	*return_object = new_object;
    413	return (AE_OK);
    414}
    415
    416/*******************************************************************************
    417 *
    418 * FUNCTION:    acpi_ns_convert_to_reference
    419 *
    420 * PARAMETERS:  scope               - Namespace node for the method/object
    421 *              original_object     - Object to be converted
    422 *              return_object       - Where the new converted object is returned
    423 *
    424 * RETURN:      Status. AE_OK if conversion was successful
    425 *
    426 * DESCRIPTION: Attempt to convert a Integer object to a object_reference.
    427 *              Buffer.
    428 *
    429 ******************************************************************************/
    430
    431acpi_status
    432acpi_ns_convert_to_reference(struct acpi_namespace_node *scope,
    433			     union acpi_operand_object *original_object,
    434			     union acpi_operand_object **return_object)
    435{
    436	union acpi_operand_object *new_object = NULL;
    437	acpi_status status;
    438	struct acpi_namespace_node *node;
    439	union acpi_generic_state scope_info;
    440	char *name;
    441
    442	ACPI_FUNCTION_NAME(ns_convert_to_reference);
    443
    444	/* Convert path into internal presentation */
    445
    446	status =
    447	    acpi_ns_internalize_name(original_object->string.pointer, &name);
    448	if (ACPI_FAILURE(status)) {
    449		return_ACPI_STATUS(status);
    450	}
    451
    452	/* Find the namespace node */
    453
    454	scope_info.scope.node =
    455	    ACPI_CAST_PTR(struct acpi_namespace_node, scope);
    456	status =
    457	    acpi_ns_lookup(&scope_info, name, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
    458			   ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
    459			   NULL, &node);
    460	if (ACPI_FAILURE(status)) {
    461
    462		/* Check if we are resolving a named reference within a package */
    463
    464		ACPI_ERROR_NAMESPACE(&scope_info,
    465				     original_object->string.pointer, status);
    466		goto error_exit;
    467	}
    468
    469	/* Create and init a new internal ACPI object */
    470
    471	new_object = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
    472	if (!new_object) {
    473		status = AE_NO_MEMORY;
    474		goto error_exit;
    475	}
    476	new_object->reference.node = node;
    477	new_object->reference.object = node->object;
    478	new_object->reference.class = ACPI_REFCLASS_NAME;
    479
    480	/*
    481	 * Increase reference of the object if needed (the object is likely a
    482	 * null for device nodes).
    483	 */
    484	acpi_ut_add_reference(node->object);
    485
    486error_exit:
    487	ACPI_FREE(name);
    488	*return_object = new_object;
    489	return (status);
    490}