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

exconcat.c (10765B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: exconcat - Concatenate-type AML operators
      5 *
      6 * Copyright (C) 2000 - 2022, Intel Corp.
      7 *
      8 *****************************************************************************/
      9
     10#include <acpi/acpi.h>
     11#include "accommon.h"
     12#include "acinterp.h"
     13#include "amlresrc.h"
     14
     15#define _COMPONENT          ACPI_EXECUTER
     16ACPI_MODULE_NAME("exconcat")
     17
     18/* Local Prototypes */
     19static acpi_status
     20acpi_ex_convert_to_object_type_string(union acpi_operand_object *obj_desc,
     21				      union acpi_operand_object **result_desc);
     22
     23/*******************************************************************************
     24 *
     25 * FUNCTION:    acpi_ex_do_concatenate
     26 *
     27 * PARAMETERS:  operand0            - First source object
     28 *              operand1            - Second source object
     29 *              actual_return_desc  - Where to place the return object
     30 *              walk_state          - Current walk state
     31 *
     32 * RETURN:      Status
     33 *
     34 * DESCRIPTION: Concatenate two objects with the ACPI-defined conversion
     35 *              rules as necessary.
     36 * NOTE:
     37 * Per the ACPI spec (up to 6.1), Concatenate only supports Integer,
     38 * String, and Buffer objects. However, we support all objects here
     39 * as an extension. This improves the usefulness of both Concatenate
     40 * and the Printf/Fprintf macros. The extension returns a string
     41 * describing the object type for the other objects.
     42 * 02/2016.
     43 *
     44 ******************************************************************************/
     45
     46acpi_status
     47acpi_ex_do_concatenate(union acpi_operand_object *operand0,
     48		       union acpi_operand_object *operand1,
     49		       union acpi_operand_object **actual_return_desc,
     50		       struct acpi_walk_state *walk_state)
     51{
     52	union acpi_operand_object *local_operand0 = operand0;
     53	union acpi_operand_object *local_operand1 = operand1;
     54	union acpi_operand_object *temp_operand1 = NULL;
     55	union acpi_operand_object *return_desc;
     56	char *buffer;
     57	acpi_object_type operand0_type;
     58	acpi_object_type operand1_type;
     59	acpi_status status;
     60
     61	ACPI_FUNCTION_TRACE(ex_do_concatenate);
     62
     63	/* Operand 0 preprocessing */
     64
     65	switch (operand0->common.type) {
     66	case ACPI_TYPE_INTEGER:
     67	case ACPI_TYPE_STRING:
     68	case ACPI_TYPE_BUFFER:
     69
     70		operand0_type = operand0->common.type;
     71		break;
     72
     73	default:
     74
     75		/* For all other types, get the "object type" string */
     76
     77		status =
     78		    acpi_ex_convert_to_object_type_string(operand0,
     79							  &local_operand0);
     80		if (ACPI_FAILURE(status)) {
     81			goto cleanup;
     82		}
     83
     84		operand0_type = ACPI_TYPE_STRING;
     85		break;
     86	}
     87
     88	/* Operand 1 preprocessing */
     89
     90	switch (operand1->common.type) {
     91	case ACPI_TYPE_INTEGER:
     92	case ACPI_TYPE_STRING:
     93	case ACPI_TYPE_BUFFER:
     94
     95		operand1_type = operand1->common.type;
     96		break;
     97
     98	default:
     99
    100		/* For all other types, get the "object type" string */
    101
    102		status =
    103		    acpi_ex_convert_to_object_type_string(operand1,
    104							  &local_operand1);
    105		if (ACPI_FAILURE(status)) {
    106			goto cleanup;
    107		}
    108
    109		operand1_type = ACPI_TYPE_STRING;
    110		break;
    111	}
    112
    113	/*
    114	 * Convert the second operand if necessary. The first operand (0)
    115	 * determines the type of the second operand (1) (See the Data Types
    116	 * section of the ACPI specification). Both object types are
    117	 * guaranteed to be either Integer/String/Buffer by the operand
    118	 * resolution mechanism.
    119	 */
    120	switch (operand0_type) {
    121	case ACPI_TYPE_INTEGER:
    122
    123		status =
    124		    acpi_ex_convert_to_integer(local_operand1, &temp_operand1,
    125					       ACPI_IMPLICIT_CONVERSION);
    126		break;
    127
    128	case ACPI_TYPE_BUFFER:
    129
    130		status =
    131		    acpi_ex_convert_to_buffer(local_operand1, &temp_operand1);
    132		break;
    133
    134	case ACPI_TYPE_STRING:
    135
    136		switch (operand1_type) {
    137		case ACPI_TYPE_INTEGER:
    138		case ACPI_TYPE_STRING:
    139		case ACPI_TYPE_BUFFER:
    140
    141			/* Other types have already been converted to string */
    142
    143			status =
    144			    acpi_ex_convert_to_string(local_operand1,
    145						      &temp_operand1,
    146						      ACPI_IMPLICIT_CONVERT_HEX);
    147			break;
    148
    149		default:
    150
    151			status = AE_OK;
    152			break;
    153		}
    154		break;
    155
    156	default:
    157
    158		ACPI_ERROR((AE_INFO, "Invalid object type: 0x%X",
    159			    operand0->common.type));
    160		status = AE_AML_INTERNAL;
    161	}
    162
    163	if (ACPI_FAILURE(status)) {
    164		goto cleanup;
    165	}
    166
    167	/* Take care with any newly created operand objects */
    168
    169	if ((local_operand1 != operand1) && (local_operand1 != temp_operand1)) {
    170		acpi_ut_remove_reference(local_operand1);
    171	}
    172
    173	local_operand1 = temp_operand1;
    174
    175	/*
    176	 * Both operands are now known to be the same object type
    177	 * (Both are Integer, String, or Buffer), and we can now perform
    178	 * the concatenation.
    179	 *
    180	 * There are three cases to handle, as per the ACPI spec:
    181	 *
    182	 * 1) Two Integers concatenated to produce a new Buffer
    183	 * 2) Two Strings concatenated to produce a new String
    184	 * 3) Two Buffers concatenated to produce a new Buffer
    185	 */
    186	switch (operand0_type) {
    187	case ACPI_TYPE_INTEGER:
    188
    189		/* Result of two Integers is a Buffer */
    190		/* Need enough buffer space for two integers */
    191
    192		return_desc = acpi_ut_create_buffer_object((acpi_size)
    193							   ACPI_MUL_2
    194							   (acpi_gbl_integer_byte_width));
    195		if (!return_desc) {
    196			status = AE_NO_MEMORY;
    197			goto cleanup;
    198		}
    199
    200		buffer = (char *)return_desc->buffer.pointer;
    201
    202		/* Copy the first integer, LSB first */
    203
    204		memcpy(buffer, &operand0->integer.value,
    205		       acpi_gbl_integer_byte_width);
    206
    207		/* Copy the second integer (LSB first) after the first */
    208
    209		memcpy(buffer + acpi_gbl_integer_byte_width,
    210		       &local_operand1->integer.value,
    211		       acpi_gbl_integer_byte_width);
    212		break;
    213
    214	case ACPI_TYPE_STRING:
    215
    216		/* Result of two Strings is a String */
    217
    218		return_desc = acpi_ut_create_string_object(((acpi_size)
    219							    local_operand0->
    220							    string.length +
    221							    local_operand1->
    222							    string.length));
    223		if (!return_desc) {
    224			status = AE_NO_MEMORY;
    225			goto cleanup;
    226		}
    227
    228		buffer = return_desc->string.pointer;
    229
    230		/* Concatenate the strings */
    231
    232		strcpy(buffer, local_operand0->string.pointer);
    233		strcat(buffer, local_operand1->string.pointer);
    234		break;
    235
    236	case ACPI_TYPE_BUFFER:
    237
    238		/* Result of two Buffers is a Buffer */
    239
    240		return_desc = acpi_ut_create_buffer_object(((acpi_size)
    241							    operand0->buffer.
    242							    length +
    243							    local_operand1->
    244							    buffer.length));
    245		if (!return_desc) {
    246			status = AE_NO_MEMORY;
    247			goto cleanup;
    248		}
    249
    250		buffer = (char *)return_desc->buffer.pointer;
    251
    252		/* Concatenate the buffers */
    253
    254		memcpy(buffer, operand0->buffer.pointer,
    255		       operand0->buffer.length);
    256		memcpy(buffer + operand0->buffer.length,
    257		       local_operand1->buffer.pointer,
    258		       local_operand1->buffer.length);
    259		break;
    260
    261	default:
    262
    263		/* Invalid object type, should not happen here */
    264
    265		ACPI_ERROR((AE_INFO, "Invalid object type: 0x%X",
    266			    operand0->common.type));
    267		status = AE_AML_INTERNAL;
    268		goto cleanup;
    269	}
    270
    271	*actual_return_desc = return_desc;
    272
    273cleanup:
    274	if (local_operand0 != operand0) {
    275		acpi_ut_remove_reference(local_operand0);
    276	}
    277
    278	if (local_operand1 != operand1) {
    279		acpi_ut_remove_reference(local_operand1);
    280	}
    281
    282	return_ACPI_STATUS(status);
    283}
    284
    285/*******************************************************************************
    286 *
    287 * FUNCTION:    acpi_ex_convert_to_object_type_string
    288 *
    289 * PARAMETERS:  obj_desc            - Object to be converted
    290 *              return_desc         - Where to place the return object
    291 *
    292 * RETURN:      Status
    293 *
    294 * DESCRIPTION: Convert an object of arbitrary type to a string object that
    295 *              contains the namestring for the object. Used for the
    296 *              concatenate operator.
    297 *
    298 ******************************************************************************/
    299
    300static acpi_status
    301acpi_ex_convert_to_object_type_string(union acpi_operand_object *obj_desc,
    302				      union acpi_operand_object **result_desc)
    303{
    304	union acpi_operand_object *return_desc;
    305	const char *type_string;
    306
    307	type_string = acpi_ut_get_type_name(obj_desc->common.type);
    308
    309	return_desc = acpi_ut_create_string_object(((acpi_size)strlen(type_string) + 9));	/* 9 For "[ Object]" */
    310	if (!return_desc) {
    311		return (AE_NO_MEMORY);
    312	}
    313
    314	strcpy(return_desc->string.pointer, "[");
    315	strcat(return_desc->string.pointer, type_string);
    316	strcat(return_desc->string.pointer, " Object]");
    317
    318	*result_desc = return_desc;
    319	return (AE_OK);
    320}
    321
    322/*******************************************************************************
    323 *
    324 * FUNCTION:    acpi_ex_concat_template
    325 *
    326 * PARAMETERS:  operand0            - First source object
    327 *              operand1            - Second source object
    328 *              actual_return_desc  - Where to place the return object
    329 *              walk_state          - Current walk state
    330 *
    331 * RETURN:      Status
    332 *
    333 * DESCRIPTION: Concatenate two resource templates
    334 *
    335 ******************************************************************************/
    336
    337acpi_status
    338acpi_ex_concat_template(union acpi_operand_object *operand0,
    339			union acpi_operand_object *operand1,
    340			union acpi_operand_object **actual_return_desc,
    341			struct acpi_walk_state *walk_state)
    342{
    343	acpi_status status;
    344	union acpi_operand_object *return_desc;
    345	u8 *new_buf;
    346	u8 *end_tag;
    347	acpi_size length0;
    348	acpi_size length1;
    349	acpi_size new_length;
    350
    351	ACPI_FUNCTION_TRACE(ex_concat_template);
    352
    353	/*
    354	 * Find the end_tag descriptor in each resource template.
    355	 * Note1: returned pointers point TO the end_tag, not past it.
    356	 * Note2: zero-length buffers are allowed; treated like one end_tag
    357	 */
    358
    359	/* Get the length of the first resource template */
    360
    361	status = acpi_ut_get_resource_end_tag(operand0, &end_tag);
    362	if (ACPI_FAILURE(status)) {
    363		return_ACPI_STATUS(status);
    364	}
    365
    366	length0 = ACPI_PTR_DIFF(end_tag, operand0->buffer.pointer);
    367
    368	/* Get the length of the second resource template */
    369
    370	status = acpi_ut_get_resource_end_tag(operand1, &end_tag);
    371	if (ACPI_FAILURE(status)) {
    372		return_ACPI_STATUS(status);
    373	}
    374
    375	length1 = ACPI_PTR_DIFF(end_tag, operand1->buffer.pointer);
    376
    377	/* Combine both lengths, minimum size will be 2 for end_tag */
    378
    379	new_length = length0 + length1 + sizeof(struct aml_resource_end_tag);
    380
    381	/* Create a new buffer object for the result (with one end_tag) */
    382
    383	return_desc = acpi_ut_create_buffer_object(new_length);
    384	if (!return_desc) {
    385		return_ACPI_STATUS(AE_NO_MEMORY);
    386	}
    387
    388	/*
    389	 * Copy the templates to the new buffer, 0 first, then 1 follows. One
    390	 * end_tag descriptor is copied from Operand1.
    391	 */
    392	new_buf = return_desc->buffer.pointer;
    393	memcpy(new_buf, operand0->buffer.pointer, length0);
    394	memcpy(new_buf + length0, operand1->buffer.pointer, length1);
    395
    396	/* Insert end_tag and set the checksum to zero, means "ignore checksum" */
    397
    398	new_buf[new_length - 1] = 0;
    399	new_buf[new_length - 2] = ACPI_RESOURCE_NAME_END_TAG | 1;
    400
    401	/* Return the completed resource template */
    402
    403	*actual_return_desc = return_desc;
    404	return_ACPI_STATUS(AE_OK);
    405}