162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
262306a36Sopenharmony_ci/*******************************************************************************
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Module Name: utmisc - common utility procedures
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci ******************************************************************************/
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <acpi/acpi.h>
962306a36Sopenharmony_ci#include "accommon.h"
1062306a36Sopenharmony_ci#include "acnamesp.h"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#define _COMPONENT          ACPI_UTILITIES
1362306a36Sopenharmony_ciACPI_MODULE_NAME("utmisc")
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci/*******************************************************************************
1662306a36Sopenharmony_ci *
1762306a36Sopenharmony_ci * FUNCTION:    acpi_ut_is_pci_root_bridge
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * PARAMETERS:  id              - The HID/CID in string format
2062306a36Sopenharmony_ci *
2162306a36Sopenharmony_ci * RETURN:      TRUE if the Id is a match for a PCI/PCI-Express Root Bridge
2262306a36Sopenharmony_ci *
2362306a36Sopenharmony_ci * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID.
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci ******************************************************************************/
2662306a36Sopenharmony_ciu8 acpi_ut_is_pci_root_bridge(char *id)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	/*
3062306a36Sopenharmony_ci	 * Check if this is a PCI root bridge.
3162306a36Sopenharmony_ci	 * ACPI 3.0+: check for a PCI Express root also.
3262306a36Sopenharmony_ci	 */
3362306a36Sopenharmony_ci	if (!(strcmp(id,
3462306a36Sopenharmony_ci		     PCI_ROOT_HID_STRING)) ||
3562306a36Sopenharmony_ci	    !(strcmp(id, PCI_EXPRESS_ROOT_HID_STRING))) {
3662306a36Sopenharmony_ci		return (TRUE);
3762306a36Sopenharmony_ci	}
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	return (FALSE);
4062306a36Sopenharmony_ci}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP || defined ACPI_NAMES_APP)
4362306a36Sopenharmony_ci/*******************************************************************************
4462306a36Sopenharmony_ci *
4562306a36Sopenharmony_ci * FUNCTION:    acpi_ut_is_aml_table
4662306a36Sopenharmony_ci *
4762306a36Sopenharmony_ci * PARAMETERS:  table               - An ACPI table
4862306a36Sopenharmony_ci *
4962306a36Sopenharmony_ci * RETURN:      TRUE if table contains executable AML; FALSE otherwise
5062306a36Sopenharmony_ci *
5162306a36Sopenharmony_ci * DESCRIPTION: Check ACPI Signature for a table that contains AML code.
5262306a36Sopenharmony_ci *              Currently, these are DSDT,SSDT,PSDT. All other table types are
5362306a36Sopenharmony_ci *              data tables that do not contain AML code.
5462306a36Sopenharmony_ci *
5562306a36Sopenharmony_ci ******************************************************************************/
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ciu8 acpi_ut_is_aml_table(struct acpi_table_header *table)
5862306a36Sopenharmony_ci{
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	/* These are the only tables that contain executable AML */
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	if (ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_DSDT) ||
6362306a36Sopenharmony_ci	    ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_PSDT) ||
6462306a36Sopenharmony_ci	    ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_SSDT) ||
6562306a36Sopenharmony_ci	    ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_OSDT) ||
6662306a36Sopenharmony_ci	    ACPI_IS_OEM_SIG(table->signature)) {
6762306a36Sopenharmony_ci		return (TRUE);
6862306a36Sopenharmony_ci	}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	return (FALSE);
7162306a36Sopenharmony_ci}
7262306a36Sopenharmony_ci#endif
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci/*******************************************************************************
7562306a36Sopenharmony_ci *
7662306a36Sopenharmony_ci * FUNCTION:    acpi_ut_dword_byte_swap
7762306a36Sopenharmony_ci *
7862306a36Sopenharmony_ci * PARAMETERS:  value           - Value to be converted
7962306a36Sopenharmony_ci *
8062306a36Sopenharmony_ci * RETURN:      u32 integer with bytes swapped
8162306a36Sopenharmony_ci *
8262306a36Sopenharmony_ci * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes)
8362306a36Sopenharmony_ci *
8462306a36Sopenharmony_ci ******************************************************************************/
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ciu32 acpi_ut_dword_byte_swap(u32 value)
8762306a36Sopenharmony_ci{
8862306a36Sopenharmony_ci	union {
8962306a36Sopenharmony_ci		u32 value;
9062306a36Sopenharmony_ci		u8 bytes[4];
9162306a36Sopenharmony_ci	} out;
9262306a36Sopenharmony_ci	union {
9362306a36Sopenharmony_ci		u32 value;
9462306a36Sopenharmony_ci		u8 bytes[4];
9562306a36Sopenharmony_ci	} in;
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	ACPI_FUNCTION_ENTRY();
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	in.value = value;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	out.bytes[0] = in.bytes[3];
10262306a36Sopenharmony_ci	out.bytes[1] = in.bytes[2];
10362306a36Sopenharmony_ci	out.bytes[2] = in.bytes[1];
10462306a36Sopenharmony_ci	out.bytes[3] = in.bytes[0];
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	return (out.value);
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci/*******************************************************************************
11062306a36Sopenharmony_ci *
11162306a36Sopenharmony_ci * FUNCTION:    acpi_ut_set_integer_width
11262306a36Sopenharmony_ci *
11362306a36Sopenharmony_ci * PARAMETERS:  Revision            From DSDT header
11462306a36Sopenharmony_ci *
11562306a36Sopenharmony_ci * RETURN:      None
11662306a36Sopenharmony_ci *
11762306a36Sopenharmony_ci * DESCRIPTION: Set the global integer bit width based upon the revision
11862306a36Sopenharmony_ci *              of the DSDT. For Revision 1 and 0, Integers are 32 bits.
11962306a36Sopenharmony_ci *              For Revision 2 and above, Integers are 64 bits. Yes, this
12062306a36Sopenharmony_ci *              makes a difference.
12162306a36Sopenharmony_ci *
12262306a36Sopenharmony_ci ******************************************************************************/
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_civoid acpi_ut_set_integer_width(u8 revision)
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	if (revision < 2) {
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci		/* 32-bit case */
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci		acpi_gbl_integer_bit_width = 32;
13262306a36Sopenharmony_ci		acpi_gbl_integer_nybble_width = 8;
13362306a36Sopenharmony_ci		acpi_gbl_integer_byte_width = 4;
13462306a36Sopenharmony_ci	} else {
13562306a36Sopenharmony_ci		/* 64-bit case (ACPI 2.0+) */
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci		acpi_gbl_integer_bit_width = 64;
13862306a36Sopenharmony_ci		acpi_gbl_integer_nybble_width = 16;
13962306a36Sopenharmony_ci		acpi_gbl_integer_byte_width = 8;
14062306a36Sopenharmony_ci	}
14162306a36Sopenharmony_ci}
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci/*******************************************************************************
14462306a36Sopenharmony_ci *
14562306a36Sopenharmony_ci * FUNCTION:    acpi_ut_create_update_state_and_push
14662306a36Sopenharmony_ci *
14762306a36Sopenharmony_ci * PARAMETERS:  object          - Object to be added to the new state
14862306a36Sopenharmony_ci *              action          - Increment/Decrement
14962306a36Sopenharmony_ci *              state_list      - List the state will be added to
15062306a36Sopenharmony_ci *
15162306a36Sopenharmony_ci * RETURN:      Status
15262306a36Sopenharmony_ci *
15362306a36Sopenharmony_ci * DESCRIPTION: Create a new state and push it
15462306a36Sopenharmony_ci *
15562306a36Sopenharmony_ci ******************************************************************************/
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ciacpi_status
15862306a36Sopenharmony_ciacpi_ut_create_update_state_and_push(union acpi_operand_object *object,
15962306a36Sopenharmony_ci				     u16 action,
16062306a36Sopenharmony_ci				     union acpi_generic_state **state_list)
16162306a36Sopenharmony_ci{
16262306a36Sopenharmony_ci	union acpi_generic_state *state;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	ACPI_FUNCTION_ENTRY();
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	/* Ignore null objects; these are expected */
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	if (!object) {
16962306a36Sopenharmony_ci		return (AE_OK);
17062306a36Sopenharmony_ci	}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	state = acpi_ut_create_update_state(object, action);
17362306a36Sopenharmony_ci	if (!state) {
17462306a36Sopenharmony_ci		return (AE_NO_MEMORY);
17562306a36Sopenharmony_ci	}
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	acpi_ut_push_generic_state(state_list, state);
17862306a36Sopenharmony_ci	return (AE_OK);
17962306a36Sopenharmony_ci}
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci/*******************************************************************************
18262306a36Sopenharmony_ci *
18362306a36Sopenharmony_ci * FUNCTION:    acpi_ut_walk_package_tree
18462306a36Sopenharmony_ci *
18562306a36Sopenharmony_ci * PARAMETERS:  source_object       - The package to walk
18662306a36Sopenharmony_ci *              target_object       - Target object (if package is being copied)
18762306a36Sopenharmony_ci *              walk_callback       - Called once for each package element
18862306a36Sopenharmony_ci *              context             - Passed to the callback function
18962306a36Sopenharmony_ci *
19062306a36Sopenharmony_ci * RETURN:      Status
19162306a36Sopenharmony_ci *
19262306a36Sopenharmony_ci * DESCRIPTION: Walk through a package, including subpackages
19362306a36Sopenharmony_ci *
19462306a36Sopenharmony_ci ******************************************************************************/
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ciacpi_status
19762306a36Sopenharmony_ciacpi_ut_walk_package_tree(union acpi_operand_object *source_object,
19862306a36Sopenharmony_ci			  void *target_object,
19962306a36Sopenharmony_ci			  acpi_pkg_callback walk_callback, void *context)
20062306a36Sopenharmony_ci{
20162306a36Sopenharmony_ci	acpi_status status = AE_OK;
20262306a36Sopenharmony_ci	union acpi_generic_state *state_list = NULL;
20362306a36Sopenharmony_ci	union acpi_generic_state *state;
20462306a36Sopenharmony_ci	union acpi_operand_object *this_source_obj;
20562306a36Sopenharmony_ci	u32 this_index;
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ut_walk_package_tree);
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	state = acpi_ut_create_pkg_state(source_object, target_object, 0);
21062306a36Sopenharmony_ci	if (!state) {
21162306a36Sopenharmony_ci		return_ACPI_STATUS(AE_NO_MEMORY);
21262306a36Sopenharmony_ci	}
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	while (state) {
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci		/* Get one element of the package */
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci		this_index = state->pkg.index;
21962306a36Sopenharmony_ci		this_source_obj =
22062306a36Sopenharmony_ci		    state->pkg.source_object->package.elements[this_index];
22162306a36Sopenharmony_ci		state->pkg.this_target_obj =
22262306a36Sopenharmony_ci		    &state->pkg.source_object->package.elements[this_index];
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci		/*
22562306a36Sopenharmony_ci		 * Check for:
22662306a36Sopenharmony_ci		 * 1) An uninitialized package element. It is completely
22762306a36Sopenharmony_ci		 *    legal to declare a package and leave it uninitialized
22862306a36Sopenharmony_ci		 * 2) Not an internal object - can be a namespace node instead
22962306a36Sopenharmony_ci		 * 3) Any type other than a package. Packages are handled in else
23062306a36Sopenharmony_ci		 *    case below.
23162306a36Sopenharmony_ci		 */
23262306a36Sopenharmony_ci		if ((!this_source_obj) ||
23362306a36Sopenharmony_ci		    (ACPI_GET_DESCRIPTOR_TYPE(this_source_obj) !=
23462306a36Sopenharmony_ci		     ACPI_DESC_TYPE_OPERAND) ||
23562306a36Sopenharmony_ci		    (this_source_obj->common.type != ACPI_TYPE_PACKAGE)) {
23662306a36Sopenharmony_ci			status =
23762306a36Sopenharmony_ci			    walk_callback(ACPI_COPY_TYPE_SIMPLE,
23862306a36Sopenharmony_ci					  this_source_obj, state, context);
23962306a36Sopenharmony_ci			if (ACPI_FAILURE(status)) {
24062306a36Sopenharmony_ci				return_ACPI_STATUS(status);
24162306a36Sopenharmony_ci			}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci			state->pkg.index++;
24462306a36Sopenharmony_ci			while (state->pkg.index >=
24562306a36Sopenharmony_ci			       state->pkg.source_object->package.count) {
24662306a36Sopenharmony_ci				/*
24762306a36Sopenharmony_ci				 * We've handled all of the objects at this level,  This means
24862306a36Sopenharmony_ci				 * that we have just completed a package. That package may
24962306a36Sopenharmony_ci				 * have contained one or more packages itself.
25062306a36Sopenharmony_ci				 *
25162306a36Sopenharmony_ci				 * Delete this state and pop the previous state (package).
25262306a36Sopenharmony_ci				 */
25362306a36Sopenharmony_ci				acpi_ut_delete_generic_state(state);
25462306a36Sopenharmony_ci				state = acpi_ut_pop_generic_state(&state_list);
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci				/* Finished when there are no more states */
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci				if (!state) {
25962306a36Sopenharmony_ci					/*
26062306a36Sopenharmony_ci					 * We have handled all of the objects in the top level
26162306a36Sopenharmony_ci					 * package just add the length of the package objects
26262306a36Sopenharmony_ci					 * and exit
26362306a36Sopenharmony_ci					 */
26462306a36Sopenharmony_ci					return_ACPI_STATUS(AE_OK);
26562306a36Sopenharmony_ci				}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci				/*
26862306a36Sopenharmony_ci				 * Go back up a level and move the index past the just
26962306a36Sopenharmony_ci				 * completed package object.
27062306a36Sopenharmony_ci				 */
27162306a36Sopenharmony_ci				state->pkg.index++;
27262306a36Sopenharmony_ci			}
27362306a36Sopenharmony_ci		} else {
27462306a36Sopenharmony_ci			/* This is a subobject of type package */
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci			status =
27762306a36Sopenharmony_ci			    walk_callback(ACPI_COPY_TYPE_PACKAGE,
27862306a36Sopenharmony_ci					  this_source_obj, state, context);
27962306a36Sopenharmony_ci			if (ACPI_FAILURE(status)) {
28062306a36Sopenharmony_ci				return_ACPI_STATUS(status);
28162306a36Sopenharmony_ci			}
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci			/*
28462306a36Sopenharmony_ci			 * Push the current state and create a new one
28562306a36Sopenharmony_ci			 * The callback above returned a new target package object.
28662306a36Sopenharmony_ci			 */
28762306a36Sopenharmony_ci			acpi_ut_push_generic_state(&state_list, state);
28862306a36Sopenharmony_ci			state =
28962306a36Sopenharmony_ci			    acpi_ut_create_pkg_state(this_source_obj,
29062306a36Sopenharmony_ci						     state->pkg.this_target_obj,
29162306a36Sopenharmony_ci						     0);
29262306a36Sopenharmony_ci			if (!state) {
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci				/* Free any stacked Update State objects */
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci				while (state_list) {
29762306a36Sopenharmony_ci					state =
29862306a36Sopenharmony_ci					    acpi_ut_pop_generic_state
29962306a36Sopenharmony_ci					    (&state_list);
30062306a36Sopenharmony_ci					acpi_ut_delete_generic_state(state);
30162306a36Sopenharmony_ci				}
30262306a36Sopenharmony_ci				return_ACPI_STATUS(AE_NO_MEMORY);
30362306a36Sopenharmony_ci			}
30462306a36Sopenharmony_ci		}
30562306a36Sopenharmony_ci	}
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	/* We should never get here */
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	ACPI_ERROR((AE_INFO, "State list did not terminate correctly"));
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	return_ACPI_STATUS(AE_AML_INTERNAL);
31262306a36Sopenharmony_ci}
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci#ifdef ACPI_DEBUG_OUTPUT
31562306a36Sopenharmony_ci/*******************************************************************************
31662306a36Sopenharmony_ci *
31762306a36Sopenharmony_ci * FUNCTION:    acpi_ut_display_init_pathname
31862306a36Sopenharmony_ci *
31962306a36Sopenharmony_ci * PARAMETERS:  type                - Object type of the node
32062306a36Sopenharmony_ci *              obj_handle          - Handle whose pathname will be displayed
32162306a36Sopenharmony_ci *              path                - Additional path string to be appended.
32262306a36Sopenharmony_ci *                                      (NULL if no extra path)
32362306a36Sopenharmony_ci *
32462306a36Sopenharmony_ci * RETURN:      acpi_status
32562306a36Sopenharmony_ci *
32662306a36Sopenharmony_ci * DESCRIPTION: Display full pathname of an object, DEBUG ONLY
32762306a36Sopenharmony_ci *
32862306a36Sopenharmony_ci ******************************************************************************/
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_civoid
33162306a36Sopenharmony_ciacpi_ut_display_init_pathname(u8 type,
33262306a36Sopenharmony_ci			      struct acpi_namespace_node *obj_handle,
33362306a36Sopenharmony_ci			      const char *path)
33462306a36Sopenharmony_ci{
33562306a36Sopenharmony_ci	acpi_status status;
33662306a36Sopenharmony_ci	struct acpi_buffer buffer;
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	ACPI_FUNCTION_ENTRY();
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	/* Only print the path if the appropriate debug level is enabled */
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
34362306a36Sopenharmony_ci		return;
34462306a36Sopenharmony_ci	}
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	/* Get the full pathname to the node */
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
34962306a36Sopenharmony_ci	status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE);
35062306a36Sopenharmony_ci	if (ACPI_FAILURE(status)) {
35162306a36Sopenharmony_ci		return;
35262306a36Sopenharmony_ci	}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	/* Print what we're doing */
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci	switch (type) {
35762306a36Sopenharmony_ci	case ACPI_TYPE_METHOD:
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci		acpi_os_printf("Executing  ");
36062306a36Sopenharmony_ci		break;
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	default:
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci		acpi_os_printf("Initializing ");
36562306a36Sopenharmony_ci		break;
36662306a36Sopenharmony_ci	}
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	/* Print the object type and pathname */
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	acpi_os_printf("%-12s %s",
37162306a36Sopenharmony_ci		       acpi_ut_get_type_name(type), (char *)buffer.pointer);
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	/* Extra path is used to append names like _STA, _INI, etc. */
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	if (path) {
37662306a36Sopenharmony_ci		acpi_os_printf(".%s", path);
37762306a36Sopenharmony_ci	}
37862306a36Sopenharmony_ci	acpi_os_printf("\n");
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	ACPI_FREE(buffer.pointer);
38162306a36Sopenharmony_ci}
38262306a36Sopenharmony_ci#endif
383