1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2/*******************************************************************************
3 *
4 * Module Name: utmisc - common utility procedures
5 *
6 ******************************************************************************/
7
8#include <acpi/acpi.h>
9#include "accommon.h"
10#include "acnamesp.h"
11
12#define _COMPONENT          ACPI_UTILITIES
13ACPI_MODULE_NAME("utmisc")
14
15/*******************************************************************************
16 *
17 * FUNCTION:    acpi_ut_is_pci_root_bridge
18 *
19 * PARAMETERS:  id              - The HID/CID in string format
20 *
21 * RETURN:      TRUE if the Id is a match for a PCI/PCI-Express Root Bridge
22 *
23 * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID.
24 *
25 ******************************************************************************/
26u8 acpi_ut_is_pci_root_bridge(char *id)
27{
28
29	/*
30	 * Check if this is a PCI root bridge.
31	 * ACPI 3.0+: check for a PCI Express root also.
32	 */
33	if (!(strcmp(id,
34		     PCI_ROOT_HID_STRING)) ||
35	    !(strcmp(id, PCI_EXPRESS_ROOT_HID_STRING))) {
36		return (TRUE);
37	}
38
39	return (FALSE);
40}
41
42#if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP || defined ACPI_NAMES_APP)
43/*******************************************************************************
44 *
45 * FUNCTION:    acpi_ut_is_aml_table
46 *
47 * PARAMETERS:  table               - An ACPI table
48 *
49 * RETURN:      TRUE if table contains executable AML; FALSE otherwise
50 *
51 * DESCRIPTION: Check ACPI Signature for a table that contains AML code.
52 *              Currently, these are DSDT,SSDT,PSDT. All other table types are
53 *              data tables that do not contain AML code.
54 *
55 ******************************************************************************/
56
57u8 acpi_ut_is_aml_table(struct acpi_table_header *table)
58{
59
60	/* These are the only tables that contain executable AML */
61
62	if (ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_DSDT) ||
63	    ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_PSDT) ||
64	    ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_SSDT) ||
65	    ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_OSDT) ||
66	    ACPI_IS_OEM_SIG(table->signature)) {
67		return (TRUE);
68	}
69
70	return (FALSE);
71}
72#endif
73
74/*******************************************************************************
75 *
76 * FUNCTION:    acpi_ut_dword_byte_swap
77 *
78 * PARAMETERS:  value           - Value to be converted
79 *
80 * RETURN:      u32 integer with bytes swapped
81 *
82 * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes)
83 *
84 ******************************************************************************/
85
86u32 acpi_ut_dword_byte_swap(u32 value)
87{
88	union {
89		u32 value;
90		u8 bytes[4];
91	} out;
92	union {
93		u32 value;
94		u8 bytes[4];
95	} in;
96
97	ACPI_FUNCTION_ENTRY();
98
99	in.value = value;
100
101	out.bytes[0] = in.bytes[3];
102	out.bytes[1] = in.bytes[2];
103	out.bytes[2] = in.bytes[1];
104	out.bytes[3] = in.bytes[0];
105
106	return (out.value);
107}
108
109/*******************************************************************************
110 *
111 * FUNCTION:    acpi_ut_set_integer_width
112 *
113 * PARAMETERS:  Revision            From DSDT header
114 *
115 * RETURN:      None
116 *
117 * DESCRIPTION: Set the global integer bit width based upon the revision
118 *              of the DSDT. For Revision 1 and 0, Integers are 32 bits.
119 *              For Revision 2 and above, Integers are 64 bits. Yes, this
120 *              makes a difference.
121 *
122 ******************************************************************************/
123
124void acpi_ut_set_integer_width(u8 revision)
125{
126
127	if (revision < 2) {
128
129		/* 32-bit case */
130
131		acpi_gbl_integer_bit_width = 32;
132		acpi_gbl_integer_nybble_width = 8;
133		acpi_gbl_integer_byte_width = 4;
134	} else {
135		/* 64-bit case (ACPI 2.0+) */
136
137		acpi_gbl_integer_bit_width = 64;
138		acpi_gbl_integer_nybble_width = 16;
139		acpi_gbl_integer_byte_width = 8;
140	}
141}
142
143/*******************************************************************************
144 *
145 * FUNCTION:    acpi_ut_create_update_state_and_push
146 *
147 * PARAMETERS:  object          - Object to be added to the new state
148 *              action          - Increment/Decrement
149 *              state_list      - List the state will be added to
150 *
151 * RETURN:      Status
152 *
153 * DESCRIPTION: Create a new state and push it
154 *
155 ******************************************************************************/
156
157acpi_status
158acpi_ut_create_update_state_and_push(union acpi_operand_object *object,
159				     u16 action,
160				     union acpi_generic_state **state_list)
161{
162	union acpi_generic_state *state;
163
164	ACPI_FUNCTION_ENTRY();
165
166	/* Ignore null objects; these are expected */
167
168	if (!object) {
169		return (AE_OK);
170	}
171
172	state = acpi_ut_create_update_state(object, action);
173	if (!state) {
174		return (AE_NO_MEMORY);
175	}
176
177	acpi_ut_push_generic_state(state_list, state);
178	return (AE_OK);
179}
180
181/*******************************************************************************
182 *
183 * FUNCTION:    acpi_ut_walk_package_tree
184 *
185 * PARAMETERS:  source_object       - The package to walk
186 *              target_object       - Target object (if package is being copied)
187 *              walk_callback       - Called once for each package element
188 *              context             - Passed to the callback function
189 *
190 * RETURN:      Status
191 *
192 * DESCRIPTION: Walk through a package, including subpackages
193 *
194 ******************************************************************************/
195
196acpi_status
197acpi_ut_walk_package_tree(union acpi_operand_object *source_object,
198			  void *target_object,
199			  acpi_pkg_callback walk_callback, void *context)
200{
201	acpi_status status = AE_OK;
202	union acpi_generic_state *state_list = NULL;
203	union acpi_generic_state *state;
204	union acpi_operand_object *this_source_obj;
205	u32 this_index;
206
207	ACPI_FUNCTION_TRACE(ut_walk_package_tree);
208
209	state = acpi_ut_create_pkg_state(source_object, target_object, 0);
210	if (!state) {
211		return_ACPI_STATUS(AE_NO_MEMORY);
212	}
213
214	while (state) {
215
216		/* Get one element of the package */
217
218		this_index = state->pkg.index;
219		this_source_obj =
220		    state->pkg.source_object->package.elements[this_index];
221		state->pkg.this_target_obj =
222		    &state->pkg.source_object->package.elements[this_index];
223
224		/*
225		 * Check for:
226		 * 1) An uninitialized package element. It is completely
227		 *    legal to declare a package and leave it uninitialized
228		 * 2) Not an internal object - can be a namespace node instead
229		 * 3) Any type other than a package. Packages are handled in else
230		 *    case below.
231		 */
232		if ((!this_source_obj) ||
233		    (ACPI_GET_DESCRIPTOR_TYPE(this_source_obj) !=
234		     ACPI_DESC_TYPE_OPERAND) ||
235		    (this_source_obj->common.type != ACPI_TYPE_PACKAGE)) {
236			status =
237			    walk_callback(ACPI_COPY_TYPE_SIMPLE,
238					  this_source_obj, state, context);
239			if (ACPI_FAILURE(status)) {
240				return_ACPI_STATUS(status);
241			}
242
243			state->pkg.index++;
244			while (state->pkg.index >=
245			       state->pkg.source_object->package.count) {
246				/*
247				 * We've handled all of the objects at this level,  This means
248				 * that we have just completed a package. That package may
249				 * have contained one or more packages itself.
250				 *
251				 * Delete this state and pop the previous state (package).
252				 */
253				acpi_ut_delete_generic_state(state);
254				state = acpi_ut_pop_generic_state(&state_list);
255
256				/* Finished when there are no more states */
257
258				if (!state) {
259					/*
260					 * We have handled all of the objects in the top level
261					 * package just add the length of the package objects
262					 * and exit
263					 */
264					return_ACPI_STATUS(AE_OK);
265				}
266
267				/*
268				 * Go back up a level and move the index past the just
269				 * completed package object.
270				 */
271				state->pkg.index++;
272			}
273		} else {
274			/* This is a subobject of type package */
275
276			status =
277			    walk_callback(ACPI_COPY_TYPE_PACKAGE,
278					  this_source_obj, state, context);
279			if (ACPI_FAILURE(status)) {
280				return_ACPI_STATUS(status);
281			}
282
283			/*
284			 * Push the current state and create a new one
285			 * The callback above returned a new target package object.
286			 */
287			acpi_ut_push_generic_state(&state_list, state);
288			state =
289			    acpi_ut_create_pkg_state(this_source_obj,
290						     state->pkg.this_target_obj,
291						     0);
292			if (!state) {
293
294				/* Free any stacked Update State objects */
295
296				while (state_list) {
297					state =
298					    acpi_ut_pop_generic_state
299					    (&state_list);
300					acpi_ut_delete_generic_state(state);
301				}
302				return_ACPI_STATUS(AE_NO_MEMORY);
303			}
304		}
305	}
306
307	/* We should never get here */
308
309	ACPI_ERROR((AE_INFO, "State list did not terminate correctly"));
310
311	return_ACPI_STATUS(AE_AML_INTERNAL);
312}
313
314#ifdef ACPI_DEBUG_OUTPUT
315/*******************************************************************************
316 *
317 * FUNCTION:    acpi_ut_display_init_pathname
318 *
319 * PARAMETERS:  type                - Object type of the node
320 *              obj_handle          - Handle whose pathname will be displayed
321 *              path                - Additional path string to be appended.
322 *                                      (NULL if no extra path)
323 *
324 * RETURN:      acpi_status
325 *
326 * DESCRIPTION: Display full pathname of an object, DEBUG ONLY
327 *
328 ******************************************************************************/
329
330void
331acpi_ut_display_init_pathname(u8 type,
332			      struct acpi_namespace_node *obj_handle,
333			      const char *path)
334{
335	acpi_status status;
336	struct acpi_buffer buffer;
337
338	ACPI_FUNCTION_ENTRY();
339
340	/* Only print the path if the appropriate debug level is enabled */
341
342	if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
343		return;
344	}
345
346	/* Get the full pathname to the node */
347
348	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
349	status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE);
350	if (ACPI_FAILURE(status)) {
351		return;
352	}
353
354	/* Print what we're doing */
355
356	switch (type) {
357	case ACPI_TYPE_METHOD:
358
359		acpi_os_printf("Executing  ");
360		break;
361
362	default:
363
364		acpi_os_printf("Initializing ");
365		break;
366	}
367
368	/* Print the object type and pathname */
369
370	acpi_os_printf("%-12s %s",
371		       acpi_ut_get_type_name(type), (char *)buffer.pointer);
372
373	/* Extra path is used to append names like _STA, _INI, etc. */
374
375	if (path) {
376		acpi_os_printf(".%s", path);
377	}
378	acpi_os_printf("\n");
379
380	ACPI_FREE(buffer.pointer);
381}
382#endif
383