1 | /****************************************************************************** |
2 | * |
3 | * Module Name: exdebug - Support for stores to the AML Debug Object |
4 | * |
5 | *****************************************************************************/ |
6 | |
7 | /* |
8 | * Copyright (C) 2000 - 2016, Intel Corp. |
9 | * All rights reserved. |
10 | * |
11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions |
13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright |
15 | * notice, this list of conditions, and the following disclaimer, |
16 | * without modification. |
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer |
18 | * substantially similar to the "NO WARRANTY" disclaimer below |
19 | * ("Disclaimer") and any redistribution must be conditioned upon |
20 | * including a substantially similar Disclaimer requirement for further |
21 | * binary redistribution. |
22 | * 3. Neither the names of the above-listed copyright holders nor the names |
23 | * of any contributors may be used to endorse or promote products derived |
24 | * from this software without specific prior written permission. |
25 | * |
26 | * Alternatively, this software may be distributed under the terms of the |
27 | * GNU General Public License ("GPL") version 2 as published by the Free |
28 | * Software Foundation. |
29 | * |
30 | * NO WARRANTY |
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR |
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
41 | * POSSIBILITY OF SUCH DAMAGES. |
42 | */ |
43 | |
44 | #include "acpi.h" |
45 | #include "accommon.h" |
46 | #include "acinterp.h" |
47 | |
48 | |
49 | #define _COMPONENT ACPI_EXECUTER |
50 | ACPI_MODULE_NAME ("exdebug" ) |
51 | |
52 | |
53 | #ifndef ACPI_NO_ERROR_MESSAGES |
54 | /******************************************************************************* |
55 | * |
56 | * FUNCTION: AcpiExDoDebugObject |
57 | * |
58 | * PARAMETERS: SourceDesc - Object to be output to "Debug Object" |
59 | * Level - Indentation level (used for packages) |
60 | * Index - Current package element, zero if not pkg |
61 | * |
62 | * RETURN: None |
63 | * |
64 | * DESCRIPTION: Handles stores to the AML Debug Object. For example: |
65 | * Store(INT1, Debug) |
66 | * |
67 | * This function is not compiled if ACPI_NO_ERROR_MESSAGES is set. |
68 | * |
69 | * This function is only enabled if AcpiGbl_EnableAmlDebugObject is set. |
70 | * Thus, in the normal operational case, stores to the debug object are |
71 | * ignored but can be easily enabled if necessary. |
72 | * |
73 | ******************************************************************************/ |
74 | |
75 | void |
76 | AcpiExDoDebugObject ( |
77 | ACPI_OPERAND_OBJECT *SourceDesc, |
78 | UINT32 Level, |
79 | UINT32 Index) |
80 | { |
81 | UINT32 i; |
82 | UINT32 Timer; |
83 | ACPI_OPERAND_OBJECT *ObjectDesc; |
84 | UINT32 Value; |
85 | |
86 | |
87 | ACPI_FUNCTION_TRACE_PTR (ExDoDebugObject, SourceDesc); |
88 | |
89 | |
90 | /* Output must be enabled via the DebugObject global */ |
91 | |
92 | if (!AcpiGbl_EnableAmlDebugObject) |
93 | { |
94 | return_VOID; |
95 | } |
96 | |
97 | /* Null string or newline -- don't emit the line header */ |
98 | |
99 | if (SourceDesc && |
100 | (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_OPERAND) && |
101 | (SourceDesc->Common.Type == ACPI_TYPE_STRING)) |
102 | { |
103 | if ((SourceDesc->String.Length == 0) || |
104 | ((SourceDesc->String.Length == 1) && |
105 | (*SourceDesc->String.Pointer == '\n'))) |
106 | { |
107 | AcpiOsPrintf ("\n" ); |
108 | return_VOID; |
109 | } |
110 | } |
111 | |
112 | /* |
113 | * Print line header as long as we are not in the middle of an |
114 | * object display |
115 | */ |
116 | if (!((Level > 0) && Index == 0)) |
117 | { |
118 | if (AcpiGbl_DisplayDebugTimer) |
119 | { |
120 | /* |
121 | * We will emit the current timer value (in microseconds) with each |
122 | * debug output. Only need the lower 26 bits. This allows for 67 |
123 | * million microseconds or 67 seconds before rollover. |
124 | * |
125 | * Convert 100 nanosecond units to microseconds |
126 | */ |
127 | Timer = ((UINT32) AcpiOsGetTimer () / 10); |
128 | Timer &= 0x03FFFFFF; |
129 | |
130 | AcpiOsPrintf ("[ACPI Debug T=0x%8.8X] %*s" , Timer, Level, " " ); |
131 | } |
132 | else |
133 | { |
134 | AcpiOsPrintf ("[ACPI Debug] %*s" , Level, " " ); |
135 | } |
136 | } |
137 | |
138 | /* Display the index for package output only */ |
139 | |
140 | if (Index > 0) |
141 | { |
142 | AcpiOsPrintf ("(%.2u) " , Index - 1); |
143 | } |
144 | |
145 | if (!SourceDesc) |
146 | { |
147 | AcpiOsPrintf ("[Null Object]\n" ); |
148 | return_VOID; |
149 | } |
150 | |
151 | if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_OPERAND) |
152 | { |
153 | /* No object type prefix needed for integers and strings */ |
154 | |
155 | if ((SourceDesc->Common.Type != ACPI_TYPE_INTEGER) && |
156 | (SourceDesc->Common.Type != ACPI_TYPE_STRING)) |
157 | { |
158 | AcpiOsPrintf ("%s " , AcpiUtGetObjectTypeName (SourceDesc)); |
159 | } |
160 | |
161 | if (!AcpiUtValidInternalObject (SourceDesc)) |
162 | { |
163 | AcpiOsPrintf ("%p, Invalid Internal Object!\n" , SourceDesc); |
164 | return_VOID; |
165 | } |
166 | } |
167 | else if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_NAMED) |
168 | { |
169 | AcpiOsPrintf ("%s (Node %p)\n" , |
170 | AcpiUtGetTypeName (((ACPI_NAMESPACE_NODE *) SourceDesc)->Type), |
171 | SourceDesc); |
172 | return_VOID; |
173 | } |
174 | else |
175 | { |
176 | return_VOID; |
177 | } |
178 | |
179 | /* SourceDesc is of type ACPI_DESC_TYPE_OPERAND */ |
180 | |
181 | switch (SourceDesc->Common.Type) |
182 | { |
183 | case ACPI_TYPE_INTEGER: |
184 | |
185 | /* Output correct integer width */ |
186 | |
187 | if (AcpiGbl_IntegerByteWidth == 4) |
188 | { |
189 | AcpiOsPrintf ("0x%8.8X\n" , |
190 | (UINT32) SourceDesc->Integer.Value); |
191 | } |
192 | else |
193 | { |
194 | AcpiOsPrintf ("0x%8.8X%8.8X\n" , |
195 | ACPI_FORMAT_UINT64 (SourceDesc->Integer.Value)); |
196 | } |
197 | break; |
198 | |
199 | case ACPI_TYPE_BUFFER: |
200 | |
201 | AcpiOsPrintf ("[0x%.2X]\n" , (UINT32) SourceDesc->Buffer.Length); |
202 | AcpiUtDumpBuffer (SourceDesc->Buffer.Pointer, |
203 | (SourceDesc->Buffer.Length < 256) ? |
204 | SourceDesc->Buffer.Length : 256, DB_BYTE_DISPLAY, 0); |
205 | break; |
206 | |
207 | case ACPI_TYPE_STRING: |
208 | |
209 | AcpiOsPrintf ("\"%s\"\n" , SourceDesc->String.Pointer); |
210 | break; |
211 | |
212 | case ACPI_TYPE_PACKAGE: |
213 | |
214 | AcpiOsPrintf ("(Contains 0x%.2X Elements):\n" , |
215 | SourceDesc->Package.Count); |
216 | |
217 | /* Output the entire contents of the package */ |
218 | |
219 | for (i = 0; i < SourceDesc->Package.Count; i++) |
220 | { |
221 | AcpiExDoDebugObject (SourceDesc->Package.Elements[i], |
222 | Level + 4, i + 1); |
223 | } |
224 | break; |
225 | |
226 | case ACPI_TYPE_LOCAL_REFERENCE: |
227 | |
228 | AcpiOsPrintf ("[%s] " , AcpiUtGetReferenceName (SourceDesc)); |
229 | |
230 | /* Decode the reference */ |
231 | |
232 | switch (SourceDesc->Reference.Class) |
233 | { |
234 | case ACPI_REFCLASS_INDEX: |
235 | |
236 | AcpiOsPrintf ("0x%X\n" , SourceDesc->Reference.Value); |
237 | break; |
238 | |
239 | case ACPI_REFCLASS_TABLE: |
240 | |
241 | /* Case for DdbHandle */ |
242 | |
243 | AcpiOsPrintf ("Table Index 0x%X\n" , SourceDesc->Reference.Value); |
244 | return_VOID; |
245 | |
246 | default: |
247 | |
248 | break; |
249 | } |
250 | |
251 | AcpiOsPrintf (" " ); |
252 | |
253 | /* Check for valid node first, then valid object */ |
254 | |
255 | if (SourceDesc->Reference.Node) |
256 | { |
257 | if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc->Reference.Node) != |
258 | ACPI_DESC_TYPE_NAMED) |
259 | { |
260 | AcpiOsPrintf (" %p - Not a valid namespace node\n" , |
261 | SourceDesc->Reference.Node); |
262 | } |
263 | else |
264 | { |
265 | AcpiOsPrintf ("Node %p [%4.4s] " , SourceDesc->Reference.Node, |
266 | (SourceDesc->Reference.Node)->Name.Ascii); |
267 | |
268 | switch ((SourceDesc->Reference.Node)->Type) |
269 | { |
270 | /* These types have no attached object */ |
271 | |
272 | case ACPI_TYPE_DEVICE: |
273 | AcpiOsPrintf ("Device\n" ); |
274 | break; |
275 | |
276 | case ACPI_TYPE_THERMAL: |
277 | AcpiOsPrintf ("Thermal Zone\n" ); |
278 | break; |
279 | |
280 | default: |
281 | |
282 | AcpiExDoDebugObject ((SourceDesc->Reference.Node)->Object, |
283 | Level + 4, 0); |
284 | break; |
285 | } |
286 | } |
287 | } |
288 | else if (SourceDesc->Reference.Object) |
289 | { |
290 | if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc->Reference.Object) == |
291 | ACPI_DESC_TYPE_NAMED) |
292 | { |
293 | /* Reference object is a namespace node */ |
294 | |
295 | AcpiExDoDebugObject (ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, |
296 | SourceDesc->Reference.Object), |
297 | Level + 4, 0); |
298 | } |
299 | else |
300 | { |
301 | ObjectDesc = SourceDesc->Reference.Object; |
302 | Value = SourceDesc->Reference.Value; |
303 | |
304 | switch (ObjectDesc->Common.Type) |
305 | { |
306 | case ACPI_TYPE_BUFFER: |
307 | |
308 | AcpiOsPrintf ("Buffer[%u] = 0x%2.2X\n" , |
309 | Value, *SourceDesc->Reference.IndexPointer); |
310 | break; |
311 | |
312 | case ACPI_TYPE_STRING: |
313 | |
314 | AcpiOsPrintf ("String[%u] = \"%c\" (0x%2.2X)\n" , |
315 | Value, *SourceDesc->Reference.IndexPointer, |
316 | *SourceDesc->Reference.IndexPointer); |
317 | break; |
318 | |
319 | case ACPI_TYPE_PACKAGE: |
320 | |
321 | AcpiOsPrintf ("Package[%u] = " , Value); |
322 | if (!(*SourceDesc->Reference.Where)) |
323 | { |
324 | AcpiOsPrintf ("[Uninitialized Package Element]\n" ); |
325 | } |
326 | else |
327 | { |
328 | AcpiExDoDebugObject (*SourceDesc->Reference.Where, |
329 | Level+4, 0); |
330 | } |
331 | break; |
332 | |
333 | default: |
334 | |
335 | AcpiOsPrintf ("Unknown Reference object type %X\n" , |
336 | ObjectDesc->Common.Type); |
337 | break; |
338 | } |
339 | } |
340 | } |
341 | break; |
342 | |
343 | default: |
344 | |
345 | AcpiOsPrintf ("(Descriptor %p)\n" , SourceDesc); |
346 | break; |
347 | } |
348 | |
349 | ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "\n" )); |
350 | return_VOID; |
351 | } |
352 | #endif |
353 | |