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

rscreate.c (13493B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/*******************************************************************************
      3 *
      4 * Module Name: rscreate - Create resource lists/tables
      5 *
      6 ******************************************************************************/
      7
      8#include <acpi/acpi.h>
      9#include "accommon.h"
     10#include "acresrc.h"
     11#include "acnamesp.h"
     12
     13#define _COMPONENT          ACPI_RESOURCES
     14ACPI_MODULE_NAME("rscreate")
     15
     16/*******************************************************************************
     17 *
     18 * FUNCTION:    acpi_buffer_to_resource
     19 *
     20 * PARAMETERS:  aml_buffer          - Pointer to the resource byte stream
     21 *              aml_buffer_length   - Length of the aml_buffer
     22 *              resource_ptr        - Where the converted resource is returned
     23 *
     24 * RETURN:      Status
     25 *
     26 * DESCRIPTION: Convert a raw AML buffer to a resource list
     27 *
     28 ******************************************************************************/
     29acpi_status
     30acpi_buffer_to_resource(u8 *aml_buffer,
     31			u16 aml_buffer_length,
     32			struct acpi_resource **resource_ptr)
     33{
     34	acpi_status status;
     35	acpi_size list_size_needed;
     36	void *resource;
     37	void *current_resource_ptr;
     38
     39	ACPI_FUNCTION_TRACE(acpi_buffer_to_resource);
     40
     41	/*
     42	 * Note: we allow AE_AML_NO_RESOURCE_END_TAG, since an end tag
     43	 * is not required here.
     44	 */
     45
     46	/* Get the required length for the converted resource */
     47
     48	status =
     49	    acpi_rs_get_list_length(aml_buffer, aml_buffer_length,
     50				    &list_size_needed);
     51	if (status == AE_AML_NO_RESOURCE_END_TAG) {
     52		status = AE_OK;
     53	}
     54	if (ACPI_FAILURE(status)) {
     55		return_ACPI_STATUS(status);
     56	}
     57
     58	/* Allocate a buffer for the converted resource */
     59
     60	resource = ACPI_ALLOCATE_ZEROED(list_size_needed);
     61	current_resource_ptr = resource;
     62	if (!resource) {
     63		return_ACPI_STATUS(AE_NO_MEMORY);
     64	}
     65
     66	/* Perform the AML-to-Resource conversion */
     67
     68	status = acpi_ut_walk_aml_resources(NULL, aml_buffer, aml_buffer_length,
     69					    acpi_rs_convert_aml_to_resources,
     70					    &current_resource_ptr);
     71	if (status == AE_AML_NO_RESOURCE_END_TAG) {
     72		status = AE_OK;
     73	}
     74	if (ACPI_FAILURE(status)) {
     75		ACPI_FREE(resource);
     76	} else {
     77		*resource_ptr = resource;
     78	}
     79
     80	return_ACPI_STATUS(status);
     81}
     82
     83ACPI_EXPORT_SYMBOL(acpi_buffer_to_resource)
     84
     85/*******************************************************************************
     86 *
     87 * FUNCTION:    acpi_rs_create_resource_list
     88 *
     89 * PARAMETERS:  aml_buffer          - Pointer to the resource byte stream
     90 *              output_buffer       - Pointer to the user's buffer
     91 *
     92 * RETURN:      Status: AE_OK if okay, else a valid acpi_status code
     93 *              If output_buffer is not large enough, output_buffer_length
     94 *              indicates how large output_buffer should be, else it
     95 *              indicates how may u8 elements of output_buffer are valid.
     96 *
     97 * DESCRIPTION: Takes the byte stream returned from a _CRS, _PRS control method
     98 *              execution and parses the stream to create a linked list
     99 *              of device resources.
    100 *
    101 ******************************************************************************/
    102acpi_status
    103acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer,
    104			     struct acpi_buffer *output_buffer)
    105{
    106
    107	acpi_status status;
    108	u8 *aml_start;
    109	acpi_size list_size_needed = 0;
    110	u32 aml_buffer_length;
    111	void *resource;
    112
    113	ACPI_FUNCTION_TRACE(rs_create_resource_list);
    114
    115	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlBuffer = %p\n", aml_buffer));
    116
    117	/* Params already validated, so we don't re-validate here */
    118
    119	aml_buffer_length = aml_buffer->buffer.length;
    120	aml_start = aml_buffer->buffer.pointer;
    121
    122	/*
    123	 * Pass the aml_buffer into a module that can calculate
    124	 * the buffer size needed for the linked list
    125	 */
    126	status = acpi_rs_get_list_length(aml_start, aml_buffer_length,
    127					 &list_size_needed);
    128
    129	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Status=%X ListSizeNeeded=%X\n",
    130			  status, (u32) list_size_needed));
    131	if (ACPI_FAILURE(status)) {
    132		return_ACPI_STATUS(status);
    133	}
    134
    135	/* Validate/Allocate/Clear caller buffer */
    136
    137	status = acpi_ut_initialize_buffer(output_buffer, list_size_needed);
    138	if (ACPI_FAILURE(status)) {
    139		return_ACPI_STATUS(status);
    140	}
    141
    142	/* Do the conversion */
    143
    144	resource = output_buffer->pointer;
    145	status = acpi_ut_walk_aml_resources(NULL, aml_start, aml_buffer_length,
    146					    acpi_rs_convert_aml_to_resources,
    147					    &resource);
    148	if (ACPI_FAILURE(status)) {
    149		return_ACPI_STATUS(status);
    150	}
    151
    152	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n",
    153			  output_buffer->pointer, (u32) output_buffer->length));
    154	return_ACPI_STATUS(AE_OK);
    155}
    156
    157/*******************************************************************************
    158 *
    159 * FUNCTION:    acpi_rs_create_pci_routing_table
    160 *
    161 * PARAMETERS:  package_object          - Pointer to a package containing one
    162 *                                        of more ACPI_OPERAND_OBJECTs
    163 *              output_buffer           - Pointer to the user's buffer
    164 *
    165 * RETURN:      Status  AE_OK if okay, else a valid acpi_status code.
    166 *              If the output_buffer is too small, the error will be
    167 *              AE_BUFFER_OVERFLOW and output_buffer->Length will point
    168 *              to the size buffer needed.
    169 *
    170 * DESCRIPTION: Takes the union acpi_operand_object package and creates a
    171 *              linked list of PCI interrupt descriptions
    172 *
    173 * NOTE: It is the caller's responsibility to ensure that the start of the
    174 * output buffer is aligned properly (if necessary).
    175 *
    176 ******************************************************************************/
    177
    178acpi_status
    179acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
    180				 struct acpi_buffer *output_buffer)
    181{
    182	u8 *buffer;
    183	union acpi_operand_object **top_object_list;
    184	union acpi_operand_object **sub_object_list;
    185	union acpi_operand_object *obj_desc;
    186	acpi_size buffer_size_needed = 0;
    187	u32 number_of_elements;
    188	u32 index;
    189	struct acpi_pci_routing_table *user_prt;
    190	struct acpi_namespace_node *node;
    191	acpi_status status;
    192	struct acpi_buffer path_buffer;
    193
    194	ACPI_FUNCTION_TRACE(rs_create_pci_routing_table);
    195
    196	/* Params already validated, so we don't re-validate here */
    197
    198	/* Get the required buffer length */
    199
    200	status =
    201	    acpi_rs_get_pci_routing_table_length(package_object,
    202						 &buffer_size_needed);
    203	if (ACPI_FAILURE(status)) {
    204		return_ACPI_STATUS(status);
    205	}
    206
    207	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "BufferSizeNeeded = %X\n",
    208			  (u32) buffer_size_needed));
    209
    210	/* Validate/Allocate/Clear caller buffer */
    211
    212	status = acpi_ut_initialize_buffer(output_buffer, buffer_size_needed);
    213	if (ACPI_FAILURE(status)) {
    214		return_ACPI_STATUS(status);
    215	}
    216
    217	/*
    218	 * Loop through the ACPI_INTERNAL_OBJECTS - Each object should be a
    219	 * package that in turn contains an u64 Address, a u8 Pin,
    220	 * a Name, and a u8 source_index.
    221	 */
    222	top_object_list = package_object->package.elements;
    223	number_of_elements = package_object->package.count;
    224	buffer = output_buffer->pointer;
    225	user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
    226
    227	for (index = 0; index < number_of_elements; index++) {
    228
    229		/*
    230		 * Point user_prt past this current structure
    231		 *
    232		 * NOTE: On the first iteration, user_prt->Length will
    233		 * be zero because we cleared the return buffer earlier
    234		 */
    235		buffer += user_prt->length;
    236		user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
    237
    238		/*
    239		 * Fill in the Length field with the information we have at this
    240		 * point. The minus four is to subtract the size of the u8
    241		 * Source[4] member because it is added below.
    242		 */
    243		user_prt->length = (sizeof(struct acpi_pci_routing_table) - 4);
    244
    245		/* Each subpackage must be of length 4 */
    246
    247		if ((*top_object_list)->package.count != 4) {
    248			ACPI_ERROR((AE_INFO,
    249				    "(PRT[%u]) Need package of length 4, found length %u",
    250				    index, (*top_object_list)->package.count));
    251			return_ACPI_STATUS(AE_AML_PACKAGE_LIMIT);
    252		}
    253
    254		/*
    255		 * Dereference the subpackage.
    256		 * The sub_object_list will now point to an array of the four IRQ
    257		 * elements: [Address, Pin, Source, source_index]
    258		 */
    259		sub_object_list = (*top_object_list)->package.elements;
    260
    261		/* 1) First subobject: Dereference the PRT.Address */
    262
    263		obj_desc = sub_object_list[0];
    264		if (!obj_desc || obj_desc->common.type != ACPI_TYPE_INTEGER) {
    265			ACPI_ERROR((AE_INFO,
    266				    "(PRT[%u].Address) Need Integer, found %s",
    267				    index,
    268				    acpi_ut_get_object_type_name(obj_desc)));
    269			return_ACPI_STATUS(AE_BAD_DATA);
    270		}
    271
    272		user_prt->address = obj_desc->integer.value;
    273
    274		/* 2) Second subobject: Dereference the PRT.Pin */
    275
    276		obj_desc = sub_object_list[1];
    277		if (!obj_desc || obj_desc->common.type != ACPI_TYPE_INTEGER) {
    278			ACPI_ERROR((AE_INFO,
    279				    "(PRT[%u].Pin) Need Integer, found %s",
    280				    index,
    281				    acpi_ut_get_object_type_name(obj_desc)));
    282			return_ACPI_STATUS(AE_BAD_DATA);
    283		}
    284
    285		user_prt->pin = (u32) obj_desc->integer.value;
    286
    287		/*
    288		 * 3) Third subobject: Dereference the PRT.source_name
    289		 * The name may be unresolved (slack mode), so allow a null object
    290		 */
    291		obj_desc = sub_object_list[2];
    292		if (obj_desc) {
    293			switch (obj_desc->common.type) {
    294			case ACPI_TYPE_LOCAL_REFERENCE:
    295
    296				if (obj_desc->reference.class !=
    297				    ACPI_REFCLASS_NAME) {
    298					ACPI_ERROR((AE_INFO,
    299						    "(PRT[%u].Source) Need name, found Reference Class 0x%X",
    300						    index,
    301						    obj_desc->reference.class));
    302					return_ACPI_STATUS(AE_BAD_DATA);
    303				}
    304
    305				node = obj_desc->reference.node;
    306
    307				/* Use *remaining* length of the buffer as max for pathname */
    308
    309				path_buffer.length = output_buffer->length -
    310				    (u32) ((u8 *) user_prt->source -
    311					   (u8 *) output_buffer->pointer);
    312				path_buffer.pointer = user_prt->source;
    313
    314				status = acpi_ns_handle_to_pathname((acpi_handle)node, &path_buffer, FALSE);
    315				if (ACPI_FAILURE(status)) {
    316					return_ACPI_STATUS(status);
    317				}
    318
    319				/* +1 to include null terminator */
    320
    321				user_prt->length +=
    322				    (u32)strlen(user_prt->source) + 1;
    323				break;
    324
    325			case ACPI_TYPE_STRING:
    326
    327				strcpy(user_prt->source,
    328				       obj_desc->string.pointer);
    329
    330				/*
    331				 * Add to the Length field the length of the string
    332				 * (add 1 for terminator)
    333				 */
    334				user_prt->length += obj_desc->string.length + 1;
    335				break;
    336
    337			case ACPI_TYPE_INTEGER:
    338				/*
    339				 * If this is a number, then the Source Name is NULL, since
    340				 * the entire buffer was zeroed out, we can leave this alone.
    341				 *
    342				 * Add to the Length field the length of the u32 NULL
    343				 */
    344				user_prt->length += sizeof(u32);
    345				break;
    346
    347			default:
    348
    349				ACPI_ERROR((AE_INFO,
    350					    "(PRT[%u].Source) Need Ref/String/Integer, found %s",
    351					    index,
    352					    acpi_ut_get_object_type_name
    353					    (obj_desc)));
    354				return_ACPI_STATUS(AE_BAD_DATA);
    355			}
    356		}
    357
    358		/* Now align the current length */
    359
    360		user_prt->length =
    361		    (u32) ACPI_ROUND_UP_TO_64BIT(user_prt->length);
    362
    363		/* 4) Fourth subobject: Dereference the PRT.source_index */
    364
    365		obj_desc = sub_object_list[3];
    366		if (!obj_desc || obj_desc->common.type != ACPI_TYPE_INTEGER) {
    367			ACPI_ERROR((AE_INFO,
    368				    "(PRT[%u].SourceIndex) Need Integer, found %s",
    369				    index,
    370				    acpi_ut_get_object_type_name(obj_desc)));
    371			return_ACPI_STATUS(AE_BAD_DATA);
    372		}
    373
    374		user_prt->source_index = (u32) obj_desc->integer.value;
    375
    376		/* Point to the next union acpi_operand_object in the top level package */
    377
    378		top_object_list++;
    379	}
    380
    381	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n",
    382			  output_buffer->pointer, (u32) output_buffer->length));
    383	return_ACPI_STATUS(AE_OK);
    384}
    385
    386/*******************************************************************************
    387 *
    388 * FUNCTION:    acpi_rs_create_aml_resources
    389 *
    390 * PARAMETERS:  resource_list           - Pointer to the resource list buffer
    391 *              output_buffer           - Where the AML buffer is returned
    392 *
    393 * RETURN:      Status  AE_OK if okay, else a valid acpi_status code.
    394 *              If the output_buffer is too small, the error will be
    395 *              AE_BUFFER_OVERFLOW and output_buffer->Length will point
    396 *              to the size buffer needed.
    397 *
    398 * DESCRIPTION: Converts a list of device resources to an AML bytestream
    399 *              to be used as input for the _SRS control method.
    400 *
    401 ******************************************************************************/
    402
    403acpi_status
    404acpi_rs_create_aml_resources(struct acpi_buffer *resource_list,
    405			     struct acpi_buffer *output_buffer)
    406{
    407	acpi_status status;
    408	acpi_size aml_size_needed = 0;
    409
    410	ACPI_FUNCTION_TRACE(rs_create_aml_resources);
    411
    412	/* Params already validated, no need to re-validate here */
    413
    414	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ResourceList Buffer = %p\n",
    415			  resource_list->pointer));
    416
    417	/* Get the buffer size needed for the AML byte stream */
    418
    419	status =
    420	    acpi_rs_get_aml_length(resource_list->pointer,
    421				   resource_list->length, &aml_size_needed);
    422
    423	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlSizeNeeded=%X, %s\n",
    424			  (u32)aml_size_needed, acpi_format_exception(status)));
    425	if (ACPI_FAILURE(status)) {
    426		return_ACPI_STATUS(status);
    427	}
    428
    429	/* Validate/Allocate/Clear caller buffer */
    430
    431	status = acpi_ut_initialize_buffer(output_buffer, aml_size_needed);
    432	if (ACPI_FAILURE(status)) {
    433		return_ACPI_STATUS(status);
    434	}
    435
    436	/* Do the conversion */
    437
    438	status = acpi_rs_convert_resources_to_aml(resource_list->pointer,
    439						  aml_size_needed,
    440						  output_buffer->pointer);
    441	if (ACPI_FAILURE(status)) {
    442		return_ACPI_STATUS(status);
    443	}
    444
    445	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n",
    446			  output_buffer->pointer, (u32) output_buffer->length));
    447	return_ACPI_STATUS(AE_OK);
    448}