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