1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
2 | /****************************************************************************** |
3 | * |
4 | * Module Name: dswscope - Scope stack manipulation |
5 | * |
6 | * Copyright (C) 2000 - 2023, Intel Corp. |
7 | * |
8 | *****************************************************************************/ |
9 | |
10 | #include <acpi/acpi.h> |
11 | #include "accommon.h" |
12 | #include "acdispat.h" |
13 | |
14 | #define _COMPONENT ACPI_DISPATCHER |
15 | ACPI_MODULE_NAME("dswscope" ) |
16 | |
17 | /**************************************************************************** |
18 | * |
19 | * FUNCTION: acpi_ds_scope_stack_clear |
20 | * |
21 | * PARAMETERS: walk_state - Current state |
22 | * |
23 | * RETURN: None |
24 | * |
25 | * DESCRIPTION: Pop (and free) everything on the scope stack except the |
26 | * root scope object (which remains at the stack top.) |
27 | * |
28 | ***************************************************************************/ |
29 | void acpi_ds_scope_stack_clear(struct acpi_walk_state *walk_state) |
30 | { |
31 | union acpi_generic_state *scope_info; |
32 | |
33 | ACPI_FUNCTION_NAME(ds_scope_stack_clear); |
34 | |
35 | while (walk_state->scope_info) { |
36 | |
37 | /* Pop a scope off the stack */ |
38 | |
39 | scope_info = walk_state->scope_info; |
40 | walk_state->scope_info = scope_info->scope.next; |
41 | |
42 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
43 | "Popped object type (%s)\n" , |
44 | acpi_ut_get_type_name(scope_info->common. |
45 | value))); |
46 | |
47 | acpi_ut_delete_generic_state(state: scope_info); |
48 | } |
49 | } |
50 | |
51 | /**************************************************************************** |
52 | * |
53 | * FUNCTION: acpi_ds_scope_stack_push |
54 | * |
55 | * PARAMETERS: node - Name to be made current |
56 | * type - Type of frame being pushed |
57 | * walk_state - Current state |
58 | * |
59 | * RETURN: Status |
60 | * |
61 | * DESCRIPTION: Push the current scope on the scope stack, and make the |
62 | * passed Node current. |
63 | * |
64 | ***************************************************************************/ |
65 | |
66 | acpi_status |
67 | acpi_ds_scope_stack_push(struct acpi_namespace_node *node, |
68 | acpi_object_type type, |
69 | struct acpi_walk_state *walk_state) |
70 | { |
71 | union acpi_generic_state *scope_info; |
72 | union acpi_generic_state *old_scope_info; |
73 | |
74 | ACPI_FUNCTION_TRACE(ds_scope_stack_push); |
75 | |
76 | if (!node) { |
77 | |
78 | /* Invalid scope */ |
79 | |
80 | ACPI_ERROR((AE_INFO, "Null scope parameter" )); |
81 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
82 | } |
83 | |
84 | /* Make sure object type is valid */ |
85 | |
86 | if (!acpi_ut_valid_object_type(type)) { |
87 | ACPI_WARNING((AE_INFO, "Invalid object type: 0x%X" , type)); |
88 | } |
89 | |
90 | /* Allocate a new scope object */ |
91 | |
92 | scope_info = acpi_ut_create_generic_state(); |
93 | if (!scope_info) { |
94 | return_ACPI_STATUS(AE_NO_MEMORY); |
95 | } |
96 | |
97 | /* Init new scope object */ |
98 | |
99 | scope_info->common.descriptor_type = ACPI_DESC_TYPE_STATE_WSCOPE; |
100 | scope_info->scope.node = node; |
101 | scope_info->common.value = (u16) type; |
102 | |
103 | walk_state->scope_depth++; |
104 | |
105 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
106 | "[%.2d] Pushed scope " , |
107 | (u32) walk_state->scope_depth)); |
108 | |
109 | old_scope_info = walk_state->scope_info; |
110 | if (old_scope_info) { |
111 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, |
112 | "[%4.4s] (%s)" , |
113 | acpi_ut_get_node_name(old_scope_info-> |
114 | scope.node), |
115 | acpi_ut_get_type_name(old_scope_info-> |
116 | common.value))); |
117 | } else { |
118 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, ACPI_NAMESPACE_ROOT)); |
119 | } |
120 | |
121 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, |
122 | ", New scope -> [%4.4s] (%s)\n" , |
123 | acpi_ut_get_node_name(scope_info->scope.node), |
124 | acpi_ut_get_type_name(scope_info->common.value))); |
125 | |
126 | /* Push new scope object onto stack */ |
127 | |
128 | acpi_ut_push_generic_state(list_head: &walk_state->scope_info, state: scope_info); |
129 | return_ACPI_STATUS(AE_OK); |
130 | } |
131 | |
132 | /**************************************************************************** |
133 | * |
134 | * FUNCTION: acpi_ds_scope_stack_pop |
135 | * |
136 | * PARAMETERS: walk_state - Current state |
137 | * |
138 | * RETURN: Status |
139 | * |
140 | * DESCRIPTION: Pop the scope stack once. |
141 | * |
142 | ***************************************************************************/ |
143 | |
144 | acpi_status acpi_ds_scope_stack_pop(struct acpi_walk_state *walk_state) |
145 | { |
146 | union acpi_generic_state *scope_info; |
147 | union acpi_generic_state *new_scope_info; |
148 | |
149 | ACPI_FUNCTION_TRACE(ds_scope_stack_pop); |
150 | |
151 | /* |
152 | * Pop scope info object off the stack. |
153 | */ |
154 | scope_info = acpi_ut_pop_generic_state(list_head: &walk_state->scope_info); |
155 | if (!scope_info) { |
156 | return_ACPI_STATUS(AE_STACK_UNDERFLOW); |
157 | } |
158 | |
159 | walk_state->scope_depth--; |
160 | |
161 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
162 | "[%.2d] Popped scope [%4.4s] (%s), New scope -> " , |
163 | (u32) walk_state->scope_depth, |
164 | acpi_ut_get_node_name(scope_info->scope.node), |
165 | acpi_ut_get_type_name(scope_info->common.value))); |
166 | |
167 | new_scope_info = walk_state->scope_info; |
168 | if (new_scope_info) { |
169 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "[%4.4s] (%s)\n" , |
170 | acpi_ut_get_node_name(new_scope_info-> |
171 | scope.node), |
172 | acpi_ut_get_type_name(new_scope_info-> |
173 | common.value))); |
174 | } else { |
175 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "%s\n" , |
176 | ACPI_NAMESPACE_ROOT)); |
177 | } |
178 | |
179 | acpi_ut_delete_generic_state(state: scope_info); |
180 | return_ACPI_STATUS(AE_OK); |
181 | } |
182 | |