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

dspkginit.c (16258B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: dspkginit - Completion of deferred package initialization
      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#include "amlcode.h"
     14#include "acdispat.h"
     15#include "acinterp.h"
     16#include "acparser.h"
     17
     18#define _COMPONENT          ACPI_NAMESPACE
     19ACPI_MODULE_NAME("dspkginit")
     20
     21/* Local prototypes */
     22static void
     23acpi_ds_resolve_package_element(union acpi_operand_object **element);
     24
     25/*******************************************************************************
     26 *
     27 * FUNCTION:    acpi_ds_build_internal_package_obj
     28 *
     29 * PARAMETERS:  walk_state      - Current walk state
     30 *              op              - Parser object to be translated
     31 *              element_count   - Number of elements in the package - this is
     32 *                                the num_elements argument to Package()
     33 *              obj_desc_ptr    - Where the ACPI internal object is returned
     34 *
     35 * RETURN:      Status
     36 *
     37 * DESCRIPTION: Translate a parser Op package object to the equivalent
     38 *              namespace object
     39 *
     40 * NOTE: The number of elements in the package will be always be the num_elements
     41 * count, regardless of the number of elements in the package list. If
     42 * num_elements is smaller, only that many package list elements are used.
     43 * if num_elements is larger, the Package object is padded out with
     44 * objects of type Uninitialized (as per ACPI spec.)
     45 *
     46 * Even though the ASL compilers do not allow num_elements to be smaller
     47 * than the Package list length (for the fixed length package opcode), some
     48 * BIOS code modifies the AML on the fly to adjust the num_elements, and
     49 * this code compensates for that. This also provides compatibility with
     50 * other AML interpreters.
     51 *
     52 ******************************************************************************/
     53
     54acpi_status
     55acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
     56				   union acpi_parse_object *op,
     57				   u32 element_count,
     58				   union acpi_operand_object **obj_desc_ptr)
     59{
     60	union acpi_parse_object *arg;
     61	union acpi_parse_object *parent;
     62	union acpi_operand_object *obj_desc = NULL;
     63	acpi_status status = AE_OK;
     64	u8 module_level_code = FALSE;
     65	u16 reference_count;
     66	u32 index;
     67	u32 i;
     68
     69	ACPI_FUNCTION_TRACE(ds_build_internal_package_obj);
     70
     71	/* Check if we are executing module level code */
     72
     73	if (walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL) {
     74		module_level_code = TRUE;
     75	}
     76
     77	/* Find the parent of a possibly nested package */
     78
     79	parent = op->common.parent;
     80	while ((parent->common.aml_opcode == AML_PACKAGE_OP) ||
     81	       (parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP)) {
     82		parent = parent->common.parent;
     83	}
     84
     85	/*
     86	 * If we are evaluating a Named package object of the form:
     87	 *      Name (xxxx, Package)
     88	 * the package object already exists, otherwise it must be created.
     89	 */
     90	obj_desc = *obj_desc_ptr;
     91	if (!obj_desc) {
     92		obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
     93		*obj_desc_ptr = obj_desc;
     94		if (!obj_desc) {
     95			return_ACPI_STATUS(AE_NO_MEMORY);
     96		}
     97
     98		obj_desc->package.node = parent->common.node;
     99	}
    100
    101	if (obj_desc->package.flags & AOPOBJ_DATA_VALID) {	/* Just in case */
    102		return_ACPI_STATUS(AE_OK);
    103	}
    104
    105	/*
    106	 * Allocate the element array (array of pointers to the individual
    107	 * objects) if necessary. the count is based on the num_elements
    108	 * parameter. Add an extra pointer slot so that the list is always
    109	 * null terminated.
    110	 */
    111	if (!obj_desc->package.elements) {
    112		obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size)
    113								   element_count
    114								   +
    115								   1) *
    116								  sizeof(void
    117									 *));
    118
    119		if (!obj_desc->package.elements) {
    120			acpi_ut_delete_object_desc(obj_desc);
    121			return_ACPI_STATUS(AE_NO_MEMORY);
    122		}
    123
    124		obj_desc->package.count = element_count;
    125	}
    126
    127	/* First arg is element count. Second arg begins the initializer list */
    128
    129	arg = op->common.value.arg;
    130	arg = arg->common.next;
    131
    132	/*
    133	 * If we are executing module-level code, we will defer the
    134	 * full resolution of the package elements in order to support
    135	 * forward references from the elements. This provides
    136	 * compatibility with other ACPI implementations.
    137	 */
    138	if (module_level_code) {
    139		obj_desc->package.aml_start = walk_state->aml;
    140		obj_desc->package.aml_length = 0;
    141
    142		ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
    143				      "%s: Deferring resolution of Package elements\n",
    144				      ACPI_GET_FUNCTION_NAME));
    145	}
    146
    147	/*
    148	 * Initialize the elements of the package, up to the num_elements count.
    149	 * Package is automatically padded with uninitialized (NULL) elements
    150	 * if num_elements is greater than the package list length. Likewise,
    151	 * Package is truncated if num_elements is less than the list length.
    152	 */
    153	for (i = 0; arg && (i < element_count); i++) {
    154		if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
    155			if (!arg->common.node) {
    156				/*
    157				 * This is the case where an expression has returned a value.
    158				 * The use of expressions (term_args) within individual
    159				 * package elements is not supported by the AML interpreter,
    160				 * even though the ASL grammar supports it. Example:
    161				 *
    162				 *      Name (INT1, 0x1234)
    163				 *
    164				 *      Name (PKG3, Package () {
    165				 *          Add (INT1, 0xAAAA0000)
    166				 *      })
    167				 *
    168				 *  1) No known AML interpreter supports this type of construct
    169				 *  2) This fixes a fault if the construct is encountered
    170				 */
    171				ACPI_EXCEPTION((AE_INFO, AE_SUPPORT,
    172						"Expressions within package elements are not supported"));
    173
    174				/* Cleanup the return object, it is not needed */
    175
    176				acpi_ut_remove_reference(walk_state->results->
    177							 results.obj_desc[0]);
    178				return_ACPI_STATUS(AE_SUPPORT);
    179			}
    180
    181			if (arg->common.node->type == ACPI_TYPE_METHOD) {
    182				/*
    183				 * A method reference "looks" to the parser to be a method
    184				 * invocation, so we special case it here
    185				 */
    186				arg->common.aml_opcode = AML_INT_NAMEPATH_OP;
    187				status =
    188				    acpi_ds_build_internal_object(walk_state,
    189								  arg,
    190								  &obj_desc->
    191								  package.
    192								  elements[i]);
    193			} else {
    194				/* This package element is already built, just get it */
    195
    196				obj_desc->package.elements[i] =
    197				    ACPI_CAST_PTR(union acpi_operand_object,
    198						  arg->common.node);
    199			}
    200		} else {
    201			status =
    202			    acpi_ds_build_internal_object(walk_state, arg,
    203							  &obj_desc->package.
    204							  elements[i]);
    205			if (status == AE_NOT_FOUND) {
    206				ACPI_ERROR((AE_INFO, "%-48s",
    207					    "****DS namepath not found"));
    208			}
    209
    210			if (!module_level_code) {
    211				/*
    212				 * Initialize this package element. This function handles the
    213				 * resolution of named references within the package.
    214				 * Forward references from module-level code are deferred
    215				 * until all ACPI tables are loaded.
    216				 */
    217				acpi_ds_init_package_element(0,
    218							     obj_desc->package.
    219							     elements[i], NULL,
    220							     &obj_desc->package.
    221							     elements[i]);
    222			}
    223		}
    224
    225		if (*obj_desc_ptr) {
    226
    227			/* Existing package, get existing reference count */
    228
    229			reference_count =
    230			    (*obj_desc_ptr)->common.reference_count;
    231			if (reference_count > 1) {
    232
    233				/* Make new element ref count match original ref count */
    234				/* TBD: Probably need an acpi_ut_add_references function */
    235
    236				for (index = 0;
    237				     index < ((u32)reference_count - 1);
    238				     index++) {
    239					acpi_ut_add_reference((obj_desc->
    240							       package.
    241							       elements[i]));
    242				}
    243			}
    244		}
    245
    246		arg = arg->common.next;
    247	}
    248
    249	/* Check for match between num_elements and actual length of package_list */
    250
    251	if (arg) {
    252		/*
    253		 * num_elements was exhausted, but there are remaining elements in
    254		 * the package_list. Truncate the package to num_elements.
    255		 *
    256		 * Note: technically, this is an error, from ACPI spec: "It is an
    257		 * error for NumElements to be less than the number of elements in
    258		 * the PackageList". However, we just print a message and no
    259		 * exception is returned. This provides compatibility with other
    260		 * ACPI implementations. Some firmware implementations will alter
    261		 * the num_elements on the fly, possibly creating this type of
    262		 * ill-formed package object.
    263		 */
    264		while (arg) {
    265			/*
    266			 * We must delete any package elements that were created earlier
    267			 * and are not going to be used because of the package truncation.
    268			 */
    269			if (arg->common.node) {
    270				acpi_ut_remove_reference(ACPI_CAST_PTR
    271							 (union
    272							  acpi_operand_object,
    273							  arg->common.node));
    274				arg->common.node = NULL;
    275			}
    276
    277			/* Find out how many elements there really are */
    278
    279			i++;
    280			arg = arg->common.next;
    281		}
    282
    283		ACPI_INFO(("Actual Package length (%u) is larger than "
    284			   "NumElements field (%u), truncated",
    285			   i, element_count));
    286	} else if (i < element_count) {
    287		/*
    288		 * Arg list (elements) was exhausted, but we did not reach
    289		 * num_elements count.
    290		 *
    291		 * Note: this is not an error, the package is padded out
    292		 * with NULLs as per the ACPI specification.
    293		 */
    294		ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO,
    295				      "%s: Package List length (%u) smaller than NumElements "
    296				      "count (%u), padded with null elements\n",
    297				      ACPI_GET_FUNCTION_NAME, i,
    298				      element_count));
    299	}
    300
    301	/* Module-level packages will be resolved later */
    302
    303	if (!module_level_code) {
    304		obj_desc->package.flags |= AOPOBJ_DATA_VALID;
    305	}
    306
    307	op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc);
    308	return_ACPI_STATUS(status);
    309}
    310
    311/*******************************************************************************
    312 *
    313 * FUNCTION:    acpi_ds_init_package_element
    314 *
    315 * PARAMETERS:  acpi_pkg_callback
    316 *
    317 * RETURN:      Status
    318 *
    319 * DESCRIPTION: Resolve a named reference element within a package object
    320 *
    321 ******************************************************************************/
    322
    323acpi_status
    324acpi_ds_init_package_element(u8 object_type,
    325			     union acpi_operand_object *source_object,
    326			     union acpi_generic_state *state, void *context)
    327{
    328	union acpi_operand_object **element_ptr;
    329
    330	ACPI_FUNCTION_TRACE(ds_init_package_element);
    331
    332	if (!source_object) {
    333		return_ACPI_STATUS(AE_OK);
    334	}
    335
    336	/*
    337	 * The following code is a bit of a hack to workaround a (current)
    338	 * limitation of the acpi_pkg_callback interface. We need a pointer
    339	 * to the location within the element array because a new object
    340	 * may be created and stored there.
    341	 */
    342	if (context) {
    343
    344		/* A direct call was made to this function */
    345
    346		element_ptr = (union acpi_operand_object **)context;
    347	} else {
    348		/* Call came from acpi_ut_walk_package_tree */
    349
    350		element_ptr = state->pkg.this_target_obj;
    351	}
    352
    353	/* We are only interested in reference objects/elements */
    354
    355	if (source_object->common.type == ACPI_TYPE_LOCAL_REFERENCE) {
    356
    357		/* Attempt to resolve the (named) reference to a namespace node */
    358
    359		acpi_ds_resolve_package_element(element_ptr);
    360	} else if (source_object->common.type == ACPI_TYPE_PACKAGE) {
    361		source_object->package.flags |= AOPOBJ_DATA_VALID;
    362	}
    363
    364	return_ACPI_STATUS(AE_OK);
    365}
    366
    367/*******************************************************************************
    368 *
    369 * FUNCTION:    acpi_ds_resolve_package_element
    370 *
    371 * PARAMETERS:  element_ptr         - Pointer to a reference object
    372 *
    373 * RETURN:      Possible new element is stored to the indirect element_ptr
    374 *
    375 * DESCRIPTION: Resolve a package element that is a reference to a named
    376 *              object.
    377 *
    378 ******************************************************************************/
    379
    380static void
    381acpi_ds_resolve_package_element(union acpi_operand_object **element_ptr)
    382{
    383	acpi_status status;
    384	acpi_status status2;
    385	union acpi_generic_state scope_info;
    386	union acpi_operand_object *element = *element_ptr;
    387	struct acpi_namespace_node *resolved_node;
    388	struct acpi_namespace_node *original_node;
    389	char *external_path = "";
    390	acpi_object_type type;
    391
    392	ACPI_FUNCTION_TRACE(ds_resolve_package_element);
    393
    394	/* Check if reference element is already resolved */
    395
    396	if (element->reference.resolved) {
    397		ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
    398				      "%s: Package element is already resolved\n",
    399				      ACPI_GET_FUNCTION_NAME));
    400
    401		return_VOID;
    402	}
    403
    404	/* Element must be a reference object of correct type */
    405
    406	scope_info.scope.node = element->reference.node;	/* Prefix node */
    407
    408	status = acpi_ns_lookup(&scope_info, (char *)element->reference.aml,
    409				ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
    410				ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
    411				NULL, &resolved_node);
    412	if (ACPI_FAILURE(status)) {
    413		if ((status == AE_NOT_FOUND)
    414		    && acpi_gbl_ignore_package_resolution_errors) {
    415			/*
    416			 * Optionally be silent about the NOT_FOUND case for the referenced
    417			 * name. Although this is potentially a serious problem,
    418			 * it can generate a lot of noise/errors on platforms whose
    419			 * firmware carries around a bunch of unused Package objects.
    420			 * To disable these errors, set this global to TRUE:
    421			 *     acpi_gbl_ignore_package_resolution_errors
    422			 *
    423			 * If the AML actually tries to use such a package, the unresolved
    424			 * element(s) will be replaced with NULL elements.
    425			 */
    426
    427			/* Referenced name not found, set the element to NULL */
    428
    429			acpi_ut_remove_reference(*element_ptr);
    430			*element_ptr = NULL;
    431			return_VOID;
    432		}
    433
    434		status2 = acpi_ns_externalize_name(ACPI_UINT32_MAX,
    435						   (char *)element->reference.
    436						   aml, NULL, &external_path);
    437
    438		ACPI_EXCEPTION((AE_INFO, status,
    439				"While resolving a named reference package element - %s",
    440				external_path));
    441		if (ACPI_SUCCESS(status2)) {
    442			ACPI_FREE(external_path);
    443		}
    444
    445		/* Could not resolve name, set the element to NULL */
    446
    447		acpi_ut_remove_reference(*element_ptr);
    448		*element_ptr = NULL;
    449		return_VOID;
    450	} else if (resolved_node->type == ACPI_TYPE_ANY) {
    451
    452		/* Named reference not resolved, return a NULL package element */
    453
    454		ACPI_ERROR((AE_INFO,
    455			    "Could not resolve named package element [%4.4s] in [%4.4s]",
    456			    resolved_node->name.ascii,
    457			    scope_info.scope.node->name.ascii));
    458		*element_ptr = NULL;
    459		return_VOID;
    460	}
    461
    462	/*
    463	 * Special handling for Alias objects. We need resolved_node to point
    464	 * to the Alias target. This effectively "resolves" the alias.
    465	 */
    466	if (resolved_node->type == ACPI_TYPE_LOCAL_ALIAS) {
    467		resolved_node = ACPI_CAST_PTR(struct acpi_namespace_node,
    468					      resolved_node->object);
    469	}
    470
    471	/* Update the reference object */
    472
    473	element->reference.resolved = TRUE;
    474	element->reference.node = resolved_node;
    475	type = element->reference.node->type;
    476
    477	/*
    478	 * Attempt to resolve the node to a value before we insert it into
    479	 * the package. If this is a reference to a common data type,
    480	 * resolve it immediately. According to the ACPI spec, package
    481	 * elements can only be "data objects" or method references.
    482	 * Attempt to resolve to an Integer, Buffer, String or Package.
    483	 * If cannot, return the named reference (for things like Devices,
    484	 * Methods, etc.) Buffer Fields and Fields will resolve to simple
    485	 * objects (int/buf/str/pkg).
    486	 *
    487	 * NOTE: References to things like Devices, Methods, Mutexes, etc.
    488	 * will remain as named references. This behavior is not described
    489	 * in the ACPI spec, but it appears to be an oversight.
    490	 */
    491	original_node = resolved_node;
    492	status = acpi_ex_resolve_node_to_value(&resolved_node, NULL);
    493	if (ACPI_FAILURE(status)) {
    494		return_VOID;
    495	}
    496
    497	switch (type) {
    498		/*
    499		 * These object types are a result of named references, so we will
    500		 * leave them as reference objects. In other words, these types
    501		 * have no intrinsic "value".
    502		 */
    503	case ACPI_TYPE_DEVICE:
    504	case ACPI_TYPE_THERMAL:
    505	case ACPI_TYPE_METHOD:
    506		break;
    507
    508	case ACPI_TYPE_MUTEX:
    509	case ACPI_TYPE_POWER:
    510	case ACPI_TYPE_PROCESSOR:
    511	case ACPI_TYPE_EVENT:
    512	case ACPI_TYPE_REGION:
    513
    514		/* acpi_ex_resolve_node_to_value gave these an extra reference */
    515
    516		acpi_ut_remove_reference(original_node->object);
    517		break;
    518
    519	default:
    520		/*
    521		 * For all other types - the node was resolved to an actual
    522		 * operand object with a value, return the object. Remove
    523		 * a reference on the existing object.
    524		 */
    525		acpi_ut_remove_reference(element);
    526		*element_ptr = (union acpi_operand_object *)resolved_node;
    527		break;
    528	}
    529
    530	return_VOID;
    531}