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

nsxfname.c (16400B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: nsxfname - Public interfaces to the ACPI subsystem
      5 *                         ACPI Namespace oriented interfaces
      6 *
      7 * Copyright (C) 2000 - 2022, Intel Corp.
      8 *
      9 *****************************************************************************/
     10
     11#define EXPORT_ACPI_INTERFACES
     12
     13#include <acpi/acpi.h>
     14#include "accommon.h"
     15#include "acnamesp.h"
     16#include "acparser.h"
     17#include "amlcode.h"
     18
     19#define _COMPONENT          ACPI_NAMESPACE
     20ACPI_MODULE_NAME("nsxfname")
     21
     22/* Local prototypes */
     23static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
     24				    struct acpi_pnp_device_id *source,
     25				    char *string_area);
     26
     27/******************************************************************************
     28 *
     29 * FUNCTION:    acpi_get_handle
     30 *
     31 * PARAMETERS:  parent          - Object to search under (search scope).
     32 *              pathname        - Pointer to an asciiz string containing the
     33 *                                name
     34 *              ret_handle      - Where the return handle is returned
     35 *
     36 * RETURN:      Status
     37 *
     38 * DESCRIPTION: This routine will search for a caller specified name in the
     39 *              name space. The caller can restrict the search region by
     40 *              specifying a non NULL parent. The parent value is itself a
     41 *              namespace handle.
     42 *
     43 ******************************************************************************/
     44
     45acpi_status
     46acpi_get_handle(acpi_handle parent,
     47		acpi_string pathname, acpi_handle *ret_handle)
     48{
     49	acpi_status status;
     50	struct acpi_namespace_node *node = NULL;
     51	struct acpi_namespace_node *prefix_node = NULL;
     52
     53	ACPI_FUNCTION_ENTRY();
     54
     55	/* Parameter Validation */
     56
     57	if (!ret_handle || !pathname) {
     58		return (AE_BAD_PARAMETER);
     59	}
     60
     61	/* Convert a parent handle to a prefix node */
     62
     63	if (parent) {
     64		prefix_node = acpi_ns_validate_handle(parent);
     65		if (!prefix_node) {
     66			return (AE_BAD_PARAMETER);
     67		}
     68	}
     69
     70	/*
     71	 * Valid cases are:
     72	 * 1) Fully qualified pathname
     73	 * 2) Parent + Relative pathname
     74	 *
     75	 * Error for <null Parent + relative path>
     76	 */
     77	if (ACPI_IS_ROOT_PREFIX(pathname[0])) {
     78
     79		/* Pathname is fully qualified (starts with '\') */
     80
     81		/* Special case for root-only, since we can't search for it */
     82
     83		if (!strcmp(pathname, ACPI_NS_ROOT_PATH)) {
     84			*ret_handle =
     85			    ACPI_CAST_PTR(acpi_handle, acpi_gbl_root_node);
     86			return (AE_OK);
     87		}
     88	} else if (!prefix_node) {
     89
     90		/* Relative path with null prefix is disallowed */
     91
     92		return (AE_BAD_PARAMETER);
     93	}
     94
     95	/* Find the Node and convert to a handle */
     96
     97	status =
     98	    acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH, &node);
     99	if (ACPI_SUCCESS(status)) {
    100		*ret_handle = ACPI_CAST_PTR(acpi_handle, node);
    101	}
    102
    103	return (status);
    104}
    105
    106ACPI_EXPORT_SYMBOL(acpi_get_handle)
    107
    108/******************************************************************************
    109 *
    110 * FUNCTION:    acpi_get_name
    111 *
    112 * PARAMETERS:  handle          - Handle to be converted to a pathname
    113 *              name_type       - Full pathname or single segment
    114 *              buffer          - Buffer for returned path
    115 *
    116 * RETURN:      Pointer to a string containing the fully qualified Name.
    117 *
    118 * DESCRIPTION: This routine returns the fully qualified name associated with
    119 *              the Handle parameter. This and the acpi_pathname_to_handle are
    120 *              complementary functions.
    121 *
    122 ******************************************************************************/
    123acpi_status
    124acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer *buffer)
    125{
    126	acpi_status status;
    127
    128	/* Parameter validation */
    129
    130	if (name_type > ACPI_NAME_TYPE_MAX) {
    131		return (AE_BAD_PARAMETER);
    132	}
    133
    134	status = acpi_ut_validate_buffer(buffer);
    135	if (ACPI_FAILURE(status)) {
    136		return (status);
    137	}
    138
    139	/*
    140	 * Wants the single segment ACPI name.
    141	 * Validate handle and convert to a namespace Node
    142	 */
    143	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
    144	if (ACPI_FAILURE(status)) {
    145		return (status);
    146	}
    147
    148	if (name_type == ACPI_FULL_PATHNAME ||
    149	    name_type == ACPI_FULL_PATHNAME_NO_TRAILING) {
    150
    151		/* Get the full pathname (From the namespace root) */
    152
    153		status = acpi_ns_handle_to_pathname(handle, buffer,
    154						    name_type ==
    155						    ACPI_FULL_PATHNAME ? FALSE :
    156						    TRUE);
    157	} else {
    158		/* Get the single name */
    159
    160		status = acpi_ns_handle_to_name(handle, buffer);
    161	}
    162
    163	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
    164	return (status);
    165}
    166
    167ACPI_EXPORT_SYMBOL(acpi_get_name)
    168
    169/******************************************************************************
    170 *
    171 * FUNCTION:    acpi_ns_copy_device_id
    172 *
    173 * PARAMETERS:  dest                - Pointer to the destination PNP_DEVICE_ID
    174 *              source              - Pointer to the source PNP_DEVICE_ID
    175 *              string_area         - Pointer to where to copy the dest string
    176 *
    177 * RETURN:      Pointer to the next string area
    178 *
    179 * DESCRIPTION: Copy a single PNP_DEVICE_ID, including the string data.
    180 *
    181 ******************************************************************************/
    182static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
    183				    struct acpi_pnp_device_id *source,
    184				    char *string_area)
    185{
    186	/* Create the destination PNP_DEVICE_ID */
    187
    188	dest->string = string_area;
    189	dest->length = source->length;
    190
    191	/* Copy actual string and return a pointer to the next string area */
    192
    193	memcpy(string_area, source->string, source->length);
    194	return (string_area + source->length);
    195}
    196
    197/******************************************************************************
    198 *
    199 * FUNCTION:    acpi_get_object_info
    200 *
    201 * PARAMETERS:  handle              - Object Handle
    202 *              return_buffer       - Where the info is returned
    203 *
    204 * RETURN:      Status
    205 *
    206 * DESCRIPTION: Returns information about an object as gleaned from the
    207 *              namespace node and possibly by running several standard
    208 *              control methods (Such as in the case of a device.)
    209 *
    210 * For Device and Processor objects, run the Device _HID, _UID, _CID,
    211 * _CLS, _ADR, _sx_w, and _sx_d methods.
    212 *
    213 * Note: Allocates the return buffer, must be freed by the caller.
    214 *
    215 * Note: This interface is intended to be used during the initial device
    216 * discovery namespace traversal. Therefore, no complex methods can be
    217 * executed, especially those that access operation regions. Therefore, do
    218 * not add any additional methods that could cause problems in this area.
    219 * Because of this reason support for the following methods has been removed:
    220 * 1) _SUB method was removed (11/2015)
    221 * 2) _STA method was removed (02/2018)
    222 *
    223 ******************************************************************************/
    224
    225acpi_status
    226acpi_get_object_info(acpi_handle handle,
    227		     struct acpi_device_info **return_buffer)
    228{
    229	struct acpi_namespace_node *node;
    230	struct acpi_device_info *info;
    231	struct acpi_pnp_device_id_list *cid_list = NULL;
    232	struct acpi_pnp_device_id *hid = NULL;
    233	struct acpi_pnp_device_id *uid = NULL;
    234	struct acpi_pnp_device_id *cls = NULL;
    235	char *next_id_string;
    236	acpi_object_type type;
    237	acpi_name name;
    238	u8 param_count = 0;
    239	u16 valid = 0;
    240	u32 info_size;
    241	u32 i;
    242	acpi_status status;
    243
    244	/* Parameter validation */
    245
    246	if (!handle || !return_buffer) {
    247		return (AE_BAD_PARAMETER);
    248	}
    249
    250	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
    251	if (ACPI_FAILURE(status)) {
    252		return (status);
    253	}
    254
    255	node = acpi_ns_validate_handle(handle);
    256	if (!node) {
    257		(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
    258		return (AE_BAD_PARAMETER);
    259	}
    260
    261	/* Get the namespace node data while the namespace is locked */
    262
    263	info_size = sizeof(struct acpi_device_info);
    264	type = node->type;
    265	name = node->name.integer;
    266
    267	if (node->type == ACPI_TYPE_METHOD) {
    268		param_count = node->object->method.param_count;
    269	}
    270
    271	status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
    272	if (ACPI_FAILURE(status)) {
    273		return (status);
    274	}
    275
    276	if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) {
    277		/*
    278		 * Get extra info for ACPI Device/Processor objects only:
    279		 * Run the Device _HID, _UID, _CLS, and _CID methods.
    280		 *
    281		 * Note: none of these methods are required, so they may or may
    282		 * not be present for this device. The Info->Valid bitfield is used
    283		 * to indicate which methods were found and run successfully.
    284		 */
    285
    286		/* Execute the Device._HID method */
    287
    288		status = acpi_ut_execute_HID(node, &hid);
    289		if (ACPI_SUCCESS(status)) {
    290			info_size += hid->length;
    291			valid |= ACPI_VALID_HID;
    292		}
    293
    294		/* Execute the Device._UID method */
    295
    296		status = acpi_ut_execute_UID(node, &uid);
    297		if (ACPI_SUCCESS(status)) {
    298			info_size += uid->length;
    299			valid |= ACPI_VALID_UID;
    300		}
    301
    302		/* Execute the Device._CID method */
    303
    304		status = acpi_ut_execute_CID(node, &cid_list);
    305		if (ACPI_SUCCESS(status)) {
    306
    307			/* Add size of CID strings and CID pointer array */
    308
    309			info_size +=
    310			    (cid_list->list_size -
    311			     sizeof(struct acpi_pnp_device_id_list));
    312			valid |= ACPI_VALID_CID;
    313		}
    314
    315		/* Execute the Device._CLS method */
    316
    317		status = acpi_ut_execute_CLS(node, &cls);
    318		if (ACPI_SUCCESS(status)) {
    319			info_size += cls->length;
    320			valid |= ACPI_VALID_CLS;
    321		}
    322	}
    323
    324	/*
    325	 * Now that we have the variable-length data, we can allocate the
    326	 * return buffer
    327	 */
    328	info = ACPI_ALLOCATE_ZEROED(info_size);
    329	if (!info) {
    330		status = AE_NO_MEMORY;
    331		goto cleanup;
    332	}
    333
    334	/* Get the fixed-length data */
    335
    336	if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) {
    337		/*
    338		 * Get extra info for ACPI Device/Processor objects only:
    339		 * Run the _ADR and, sx_w, and _sx_d methods.
    340		 *
    341		 * Notes: none of these methods are required, so they may or may
    342		 * not be present for this device. The Info->Valid bitfield is used
    343		 * to indicate which methods were found and run successfully.
    344		 */
    345
    346		/* Execute the Device._ADR method */
    347
    348		status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node,
    349							 &info->address);
    350		if (ACPI_SUCCESS(status)) {
    351			valid |= ACPI_VALID_ADR;
    352		}
    353
    354		/* Execute the Device._sx_w methods */
    355
    356		status = acpi_ut_execute_power_methods(node,
    357						       acpi_gbl_lowest_dstate_names,
    358						       ACPI_NUM_sx_w_METHODS,
    359						       info->lowest_dstates);
    360		if (ACPI_SUCCESS(status)) {
    361			valid |= ACPI_VALID_SXWS;
    362		}
    363
    364		/* Execute the Device._sx_d methods */
    365
    366		status = acpi_ut_execute_power_methods(node,
    367						       acpi_gbl_highest_dstate_names,
    368						       ACPI_NUM_sx_d_METHODS,
    369						       info->highest_dstates);
    370		if (ACPI_SUCCESS(status)) {
    371			valid |= ACPI_VALID_SXDS;
    372		}
    373	}
    374
    375	/*
    376	 * Create a pointer to the string area of the return buffer.
    377	 * Point to the end of the base struct acpi_device_info structure.
    378	 */
    379	next_id_string = ACPI_CAST_PTR(char, info->compatible_id_list.ids);
    380	if (cid_list) {
    381
    382		/* Point past the CID PNP_DEVICE_ID array */
    383
    384		next_id_string +=
    385		    ((acpi_size)cid_list->count *
    386		     sizeof(struct acpi_pnp_device_id));
    387	}
    388
    389	/*
    390	 * Copy the HID, UID, and CIDs to the return buffer. The variable-length
    391	 * strings are copied to the reserved area at the end of the buffer.
    392	 *
    393	 * For HID and CID, check if the ID is a PCI Root Bridge.
    394	 */
    395	if (hid) {
    396		next_id_string = acpi_ns_copy_device_id(&info->hardware_id,
    397							hid, next_id_string);
    398
    399		if (acpi_ut_is_pci_root_bridge(hid->string)) {
    400			info->flags |= ACPI_PCI_ROOT_BRIDGE;
    401		}
    402	}
    403
    404	if (uid) {
    405		next_id_string = acpi_ns_copy_device_id(&info->unique_id,
    406							uid, next_id_string);
    407	}
    408
    409	if (cid_list) {
    410		info->compatible_id_list.count = cid_list->count;
    411		info->compatible_id_list.list_size = cid_list->list_size;
    412
    413		/* Copy each CID */
    414
    415		for (i = 0; i < cid_list->count; i++) {
    416			next_id_string =
    417			    acpi_ns_copy_device_id(&info->compatible_id_list.
    418						   ids[i], &cid_list->ids[i],
    419						   next_id_string);
    420
    421			if (acpi_ut_is_pci_root_bridge(cid_list->ids[i].string)) {
    422				info->flags |= ACPI_PCI_ROOT_BRIDGE;
    423			}
    424		}
    425	}
    426
    427	if (cls) {
    428		(void)acpi_ns_copy_device_id(&info->class_code,
    429					     cls, next_id_string);
    430	}
    431
    432	/* Copy the fixed-length data */
    433
    434	info->info_size = info_size;
    435	info->type = type;
    436	info->name = name;
    437	info->param_count = param_count;
    438	info->valid = valid;
    439
    440	*return_buffer = info;
    441	status = AE_OK;
    442
    443cleanup:
    444	if (hid) {
    445		ACPI_FREE(hid);
    446	}
    447	if (uid) {
    448		ACPI_FREE(uid);
    449	}
    450	if (cid_list) {
    451		ACPI_FREE(cid_list);
    452	}
    453	if (cls) {
    454		ACPI_FREE(cls);
    455	}
    456	return (status);
    457}
    458
    459ACPI_EXPORT_SYMBOL(acpi_get_object_info)
    460
    461/******************************************************************************
    462 *
    463 * FUNCTION:    acpi_install_method
    464 *
    465 * PARAMETERS:  buffer         - An ACPI table containing one control method
    466 *
    467 * RETURN:      Status
    468 *
    469 * DESCRIPTION: Install a control method into the namespace. If the method
    470 *              name already exists in the namespace, it is overwritten. The
    471 *              input buffer must contain a valid DSDT or SSDT containing a
    472 *              single control method.
    473 *
    474 ******************************************************************************/
    475acpi_status acpi_install_method(u8 *buffer)
    476{
    477	struct acpi_table_header *table =
    478	    ACPI_CAST_PTR(struct acpi_table_header, buffer);
    479	u8 *aml_buffer;
    480	u8 *aml_start;
    481	char *path;
    482	struct acpi_namespace_node *node;
    483	union acpi_operand_object *method_obj;
    484	struct acpi_parse_state parser_state;
    485	u32 aml_length;
    486	u16 opcode;
    487	u8 method_flags;
    488	acpi_status status;
    489
    490	/* Parameter validation */
    491
    492	if (!buffer) {
    493		return (AE_BAD_PARAMETER);
    494	}
    495
    496	/* Table must be a DSDT or SSDT */
    497
    498	if (!ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_DSDT) &&
    499	    !ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_SSDT)) {
    500		return (AE_BAD_HEADER);
    501	}
    502
    503	/* First AML opcode in the table must be a control method */
    504
    505	parser_state.aml = buffer + sizeof(struct acpi_table_header);
    506	opcode = acpi_ps_peek_opcode(&parser_state);
    507	if (opcode != AML_METHOD_OP) {
    508		return (AE_BAD_PARAMETER);
    509	}
    510
    511	/* Extract method information from the raw AML */
    512
    513	parser_state.aml += acpi_ps_get_opcode_size(opcode);
    514	parser_state.pkg_end = acpi_ps_get_next_package_end(&parser_state);
    515	path = acpi_ps_get_next_namestring(&parser_state);
    516
    517	method_flags = *parser_state.aml++;
    518	aml_start = parser_state.aml;
    519	aml_length = (u32)ACPI_PTR_DIFF(parser_state.pkg_end, aml_start);
    520
    521	/*
    522	 * Allocate resources up-front. We don't want to have to delete a new
    523	 * node from the namespace if we cannot allocate memory.
    524	 */
    525	aml_buffer = ACPI_ALLOCATE(aml_length);
    526	if (!aml_buffer) {
    527		return (AE_NO_MEMORY);
    528	}
    529
    530	method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
    531	if (!method_obj) {
    532		ACPI_FREE(aml_buffer);
    533		return (AE_NO_MEMORY);
    534	}
    535
    536	/* Lock namespace for acpi_ns_lookup, we may be creating a new node */
    537
    538	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
    539	if (ACPI_FAILURE(status)) {
    540		goto error_exit;
    541	}
    542
    543	/* The lookup either returns an existing node or creates a new one */
    544
    545	status =
    546	    acpi_ns_lookup(NULL, path, ACPI_TYPE_METHOD, ACPI_IMODE_LOAD_PASS1,
    547			   ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND,
    548			   NULL, &node);
    549
    550	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
    551
    552	if (ACPI_FAILURE(status)) {	/* ns_lookup */
    553		if (status != AE_ALREADY_EXISTS) {
    554			goto error_exit;
    555		}
    556
    557		/* Node existed previously, make sure it is a method node */
    558
    559		if (node->type != ACPI_TYPE_METHOD) {
    560			status = AE_TYPE;
    561			goto error_exit;
    562		}
    563	}
    564
    565	/* Copy the method AML to the local buffer */
    566
    567	memcpy(aml_buffer, aml_start, aml_length);
    568
    569	/* Initialize the method object with the new method's information */
    570
    571	method_obj->method.aml_start = aml_buffer;
    572	method_obj->method.aml_length = aml_length;
    573
    574	method_obj->method.param_count = (u8)
    575	    (method_flags & AML_METHOD_ARG_COUNT);
    576
    577	if (method_flags & AML_METHOD_SERIALIZED) {
    578		method_obj->method.info_flags = ACPI_METHOD_SERIALIZED;
    579
    580		method_obj->method.sync_level = (u8)
    581		    ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4);
    582	}
    583
    584	/*
    585	 * Now that it is complete, we can attach the new method object to
    586	 * the method Node (detaches/deletes any existing object)
    587	 */
    588	status = acpi_ns_attach_object(node, method_obj, ACPI_TYPE_METHOD);
    589
    590	/*
    591	 * Flag indicates AML buffer is dynamic, must be deleted later.
    592	 * Must be set only after attach above.
    593	 */
    594	node->flags |= ANOBJ_ALLOCATED_BUFFER;
    595
    596	/* Remove local reference to the method object */
    597
    598	acpi_ut_remove_reference(method_obj);
    599	return (status);
    600
    601error_exit:
    602
    603	ACPI_FREE(aml_buffer);
    604	ACPI_FREE(method_obj);
    605	return (status);
    606}
    607ACPI_EXPORT_SYMBOL(acpi_install_method)