1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
2 | /****************************************************************************** |
3 | * |
4 | * Module Name: exdebug - Support for stores to the AML Debug Object |
5 | * |
6 | * Copyright (C) 2000 - 2023, Intel Corp. |
7 | * |
8 | *****************************************************************************/ |
9 | |
10 | #include <acpi/acpi.h> |
11 | #include "accommon.h" |
12 | #include "acinterp.h" |
13 | |
14 | #define _COMPONENT ACPI_EXECUTER |
15 | ACPI_MODULE_NAME("exdebug" ) |
16 | |
17 | #ifndef ACPI_NO_ERROR_MESSAGES |
18 | /******************************************************************************* |
19 | * |
20 | * FUNCTION: acpi_ex_do_debug_object |
21 | * |
22 | * PARAMETERS: source_desc - Object to be output to "Debug Object" |
23 | * level - Indentation level (used for packages) |
24 | * index - Current package element, zero if not pkg |
25 | * |
26 | * RETURN: None |
27 | * |
28 | * DESCRIPTION: Handles stores to the AML Debug Object. For example: |
29 | * Store(INT1, Debug) |
30 | * |
31 | * This function is not compiled if ACPI_NO_ERROR_MESSAGES is set. |
32 | * |
33 | * This function is only enabled if acpi_gbl_enable_aml_debug_object is set, or |
34 | * if ACPI_LV_DEBUG_OBJECT is set in the acpi_dbg_level. Thus, in the normal |
35 | * operational case, stores to the debug object are ignored but can be easily |
36 | * enabled if necessary. |
37 | * |
38 | ******************************************************************************/ |
39 | void |
40 | acpi_ex_do_debug_object(union acpi_operand_object *source_desc, |
41 | u32 level, u32 index) |
42 | { |
43 | u32 i; |
44 | u32 timer; |
45 | union acpi_operand_object *object_desc; |
46 | u32 value; |
47 | |
48 | ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc); |
49 | |
50 | /* Output must be enabled via the debug_object global or the dbg_level */ |
51 | |
52 | if (!acpi_gbl_enable_aml_debug_object && |
53 | !(acpi_dbg_level & ACPI_LV_DEBUG_OBJECT)) { |
54 | return_VOID; |
55 | } |
56 | |
57 | /* Newline -- don't emit the line header */ |
58 | |
59 | if (source_desc && |
60 | (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) && |
61 | (source_desc->common.type == ACPI_TYPE_STRING)) { |
62 | if ((source_desc->string.length == 1) && |
63 | (*source_desc->string.pointer == '\n')) { |
64 | acpi_os_printf(format: "\n" ); |
65 | return_VOID; |
66 | } |
67 | } |
68 | |
69 | /* |
70 | * Print line header as long as we are not in the middle of an |
71 | * object display |
72 | */ |
73 | if (!((level > 0) && index == 0)) { |
74 | if (acpi_gbl_display_debug_timer) { |
75 | /* |
76 | * We will emit the current timer value (in microseconds) with each |
77 | * debug output. Only need the lower 26 bits. This allows for 67 |
78 | * million microseconds or 67 seconds before rollover. |
79 | * |
80 | * Convert 100 nanosecond units to microseconds |
81 | */ |
82 | timer = ((u32)acpi_os_get_timer() / 10); |
83 | timer &= 0x03FFFFFF; |
84 | |
85 | acpi_os_printf(format: "ACPI Debug: T=0x%8.8X %*s" , timer, |
86 | level, " " ); |
87 | } else { |
88 | acpi_os_printf(format: "ACPI Debug: %*s" , level, " " ); |
89 | } |
90 | } |
91 | |
92 | /* Display the index for package output only */ |
93 | |
94 | if (index > 0) { |
95 | acpi_os_printf(format: "(%.2u) " , index - 1); |
96 | } |
97 | |
98 | if (!source_desc) { |
99 | acpi_os_printf(format: "[Null Object]\n" ); |
100 | return_VOID; |
101 | } |
102 | |
103 | if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) { |
104 | |
105 | /* No object type prefix needed for integers and strings */ |
106 | |
107 | if ((source_desc->common.type != ACPI_TYPE_INTEGER) && |
108 | (source_desc->common.type != ACPI_TYPE_STRING)) { |
109 | acpi_os_printf(format: "%s " , |
110 | acpi_ut_get_object_type_name |
111 | (obj_desc: source_desc)); |
112 | } |
113 | |
114 | if (!acpi_ut_valid_internal_object(object: source_desc)) { |
115 | acpi_os_printf(format: "%p, Invalid Internal Object!\n" , |
116 | source_desc); |
117 | return_VOID; |
118 | } |
119 | } else if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == |
120 | ACPI_DESC_TYPE_NAMED) { |
121 | acpi_os_printf(format: "%s (Node %p)\n" , |
122 | acpi_ut_get_type_name(type: ((struct |
123 | acpi_namespace_node *) |
124 | source_desc)->type), |
125 | source_desc); |
126 | return_VOID; |
127 | } else { |
128 | return_VOID; |
129 | } |
130 | |
131 | /* source_desc is of type ACPI_DESC_TYPE_OPERAND */ |
132 | |
133 | switch (source_desc->common.type) { |
134 | case ACPI_TYPE_INTEGER: |
135 | |
136 | /* Output correct integer width */ |
137 | |
138 | if (acpi_gbl_integer_byte_width == 4) { |
139 | acpi_os_printf(format: "0x%8.8X\n" , |
140 | (u32)source_desc->integer.value); |
141 | } else { |
142 | acpi_os_printf(format: "0x%8.8X%8.8X\n" , |
143 | ACPI_FORMAT_UINT64(source_desc->integer. |
144 | value)); |
145 | } |
146 | break; |
147 | |
148 | case ACPI_TYPE_BUFFER: |
149 | |
150 | acpi_os_printf(format: "[0x%.2X]\n" , (u32)source_desc->buffer.length); |
151 | acpi_ut_dump_buffer(buffer: source_desc->buffer.pointer, |
152 | count: (source_desc->buffer.length < 256) ? |
153 | source_desc->buffer.length : 256, |
154 | DB_BYTE_DISPLAY, offset: 0); |
155 | break; |
156 | |
157 | case ACPI_TYPE_STRING: |
158 | |
159 | acpi_os_printf(format: "\"%s\"\n" , source_desc->string.pointer); |
160 | break; |
161 | |
162 | case ACPI_TYPE_PACKAGE: |
163 | |
164 | acpi_os_printf(format: "(Contains 0x%.2X Elements):\n" , |
165 | source_desc->package.count); |
166 | |
167 | /* Output the entire contents of the package */ |
168 | |
169 | for (i = 0; i < source_desc->package.count; i++) { |
170 | acpi_ex_do_debug_object(source_desc: source_desc->package. |
171 | elements[i], level: level + 4, index: i + 1); |
172 | } |
173 | break; |
174 | |
175 | case ACPI_TYPE_LOCAL_REFERENCE: |
176 | |
177 | acpi_os_printf(format: "[%s] " , |
178 | acpi_ut_get_reference_name(object: source_desc)); |
179 | |
180 | /* Decode the reference */ |
181 | |
182 | switch (source_desc->reference.class) { |
183 | case ACPI_REFCLASS_INDEX: |
184 | |
185 | acpi_os_printf(format: "0x%X\n" , source_desc->reference.value); |
186 | break; |
187 | |
188 | case ACPI_REFCLASS_TABLE: |
189 | |
190 | /* Case for ddb_handle */ |
191 | |
192 | acpi_os_printf(format: "Table Index 0x%X\n" , |
193 | source_desc->reference.value); |
194 | return_VOID; |
195 | |
196 | default: |
197 | |
198 | break; |
199 | } |
200 | |
201 | acpi_os_printf(format: " " ); |
202 | |
203 | /* Check for valid node first, then valid object */ |
204 | |
205 | if (source_desc->reference.node) { |
206 | if (ACPI_GET_DESCRIPTOR_TYPE |
207 | (source_desc->reference.node) != |
208 | ACPI_DESC_TYPE_NAMED) { |
209 | acpi_os_printf |
210 | (format: " %p - Not a valid namespace node\n" , |
211 | source_desc->reference.node); |
212 | } else { |
213 | acpi_os_printf(format: "Node %p [%4.4s] " , |
214 | source_desc->reference.node, |
215 | (source_desc->reference.node)-> |
216 | name.ascii); |
217 | |
218 | switch ((source_desc->reference.node)->type) { |
219 | |
220 | /* These types have no attached object */ |
221 | |
222 | case ACPI_TYPE_DEVICE: |
223 | acpi_os_printf(format: "Device\n" ); |
224 | break; |
225 | |
226 | case ACPI_TYPE_THERMAL: |
227 | acpi_os_printf(format: "Thermal Zone\n" ); |
228 | break; |
229 | |
230 | default: |
231 | |
232 | acpi_ex_do_debug_object(source_desc: (source_desc-> |
233 | reference. |
234 | node)->object, |
235 | level: level + 4, index: 0); |
236 | break; |
237 | } |
238 | } |
239 | } else if (source_desc->reference.object) { |
240 | if (ACPI_GET_DESCRIPTOR_TYPE |
241 | (source_desc->reference.object) == |
242 | ACPI_DESC_TYPE_NAMED) { |
243 | |
244 | /* Reference object is a namespace node */ |
245 | |
246 | acpi_ex_do_debug_object(ACPI_CAST_PTR |
247 | (union |
248 | acpi_operand_object, |
249 | source_desc->reference. |
250 | object), level: level + 4, index: 0); |
251 | } else { |
252 | object_desc = source_desc->reference.object; |
253 | value = source_desc->reference.value; |
254 | |
255 | switch (object_desc->common.type) { |
256 | case ACPI_TYPE_BUFFER: |
257 | |
258 | acpi_os_printf(format: "Buffer[%u] = 0x%2.2X\n" , |
259 | value, |
260 | *source_desc->reference. |
261 | index_pointer); |
262 | break; |
263 | |
264 | case ACPI_TYPE_STRING: |
265 | |
266 | acpi_os_printf |
267 | (format: "String[%u] = \"%c\" (0x%2.2X)\n" , |
268 | value, |
269 | *source_desc->reference. |
270 | index_pointer, |
271 | *source_desc->reference. |
272 | index_pointer); |
273 | break; |
274 | |
275 | case ACPI_TYPE_PACKAGE: |
276 | |
277 | acpi_os_printf(format: "Package[%u] = " , value); |
278 | if (!(*source_desc->reference.where)) { |
279 | acpi_os_printf |
280 | (format: "[Uninitialized Package Element]\n" ); |
281 | } else { |
282 | acpi_ex_do_debug_object |
283 | (source_desc: *source_desc->reference. |
284 | where, level: level + 4, index: 0); |
285 | } |
286 | break; |
287 | |
288 | default: |
289 | |
290 | acpi_os_printf |
291 | (format: "Unknown Reference object type %X\n" , |
292 | object_desc->common.type); |
293 | break; |
294 | } |
295 | } |
296 | } |
297 | break; |
298 | |
299 | default: |
300 | |
301 | acpi_os_printf(format: "(Descriptor %p)\n" , source_desc); |
302 | break; |
303 | } |
304 | |
305 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "\n" )); |
306 | return_VOID; |
307 | } |
308 | #endif |
309 | |