dmresrc.c revision 1.14 1 /*******************************************************************************
2 *
3 * Module Name: dmresrc.c - Resource Descriptor disassembly
4 *
5 ******************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2021, 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 MERCHANTABILITY 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 "amlcode.h"
47 #include "acdisasm.h"
48
49
50 #define _COMPONENT ACPI_CA_DEBUGGER
51 ACPI_MODULE_NAME ("dbresrc")
52
53
54 /* Dispatch tables for Resource disassembly functions */
55
56 static ACPI_RESOURCE_HANDLER AcpiGbl_DmResourceDispatch [] =
57 {
58 /* Small descriptors */
59
60 NULL, /* 0x00, Reserved */
61 NULL, /* 0x01, Reserved */
62 NULL, /* 0x02, Reserved */
63 NULL, /* 0x03, Reserved */
64 AcpiDmIrqDescriptor, /* 0x04, ACPI_RESOURCE_NAME_IRQ_FORMAT */
65 AcpiDmDmaDescriptor, /* 0x05, ACPI_RESOURCE_NAME_DMA_FORMAT */
66 AcpiDmStartDependentDescriptor, /* 0x06, ACPI_RESOURCE_NAME_START_DEPENDENT */
67 AcpiDmEndDependentDescriptor, /* 0x07, ACPI_RESOURCE_NAME_END_DEPENDENT */
68 AcpiDmIoDescriptor, /* 0x08, ACPI_RESOURCE_NAME_IO_PORT */
69 AcpiDmFixedIoDescriptor, /* 0x09, ACPI_RESOURCE_NAME_FIXED_IO_PORT */
70 AcpiDmFixedDmaDescriptor, /* 0x0A, ACPI_RESOURCE_NAME_FIXED_DMA */
71 NULL, /* 0x0B, Reserved */
72 NULL, /* 0x0C, Reserved */
73 NULL, /* 0x0D, Reserved */
74 AcpiDmVendorSmallDescriptor, /* 0x0E, ACPI_RESOURCE_NAME_SMALL_VENDOR */
75 NULL, /* 0x0F, ACPI_RESOURCE_NAME_END_TAG (not used) */
76
77 /* Large descriptors */
78
79 NULL, /* 0x00, Reserved */
80 AcpiDmMemory24Descriptor, /* 0x01, ACPI_RESOURCE_NAME_MEMORY_24 */
81 AcpiDmGenericRegisterDescriptor,/* 0x02, ACPI_RESOURCE_NAME_GENERIC_REGISTER */
82 NULL, /* 0x03, Reserved */
83 AcpiDmVendorLargeDescriptor, /* 0x04, ACPI_RESOURCE_NAME_LARGE_VENDOR */
84 AcpiDmMemory32Descriptor, /* 0x05, ACPI_RESOURCE_NAME_MEMORY_32 */
85 AcpiDmFixedMemory32Descriptor, /* 0x06, ACPI_RESOURCE_NAME_FIXED_MEMORY_32 */
86 AcpiDmDwordDescriptor, /* 0x07, ACPI_RESOURCE_NAME_DWORD_ADDRESS_SPACE */
87 AcpiDmWordDescriptor, /* 0x08, ACPI_RESOURCE_NAME_WORD_ADDRESS_SPACE */
88 AcpiDmInterruptDescriptor, /* 0x09, ACPI_RESOURCE_NAME_EXTENDED_XRUPT */
89 AcpiDmQwordDescriptor, /* 0x0A, ACPI_RESOURCE_NAME_QWORD_ADDRESS_SPACE */
90 AcpiDmExtendedDescriptor, /* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS_SPACE */
91 AcpiDmGpioDescriptor, /* 0x0C, ACPI_RESOURCE_NAME_GPIO */
92 AcpiDmPinFunctionDescriptor, /* 0x0D, ACPI_RESOURCE_NAME_PIN_FUNCTION */
93 AcpiDmSerialBusDescriptor, /* 0x0E, ACPI_RESOURCE_NAME_SERIAL_BUS */
94 AcpiDmPinConfigDescriptor, /* 0x0F, ACPI_RESOURCE_NAME_PIN_CONFIG */
95 AcpiDmPinGroupDescriptor, /* 0x10, ACPI_RESOURCE_NAME_PIN_GROUP */
96 AcpiDmPinGroupFunctionDescriptor, /* 0x11, ACPI_RESOURCE_NAME_PIN_GROUP_FUNCTION */
97 AcpiDmPinGroupConfigDescriptor, /* 0x12, ACPI_RESOURCE_NAME_PIN_GROUP_CONFIG */
98 };
99
100
101 /* Only used for single-threaded applications */
102 /* TBD: remove when name is passed as parameter to the dump functions */
103
104 static UINT32 ResourceName;
105
106
107 /*******************************************************************************
108 *
109 * FUNCTION: AcpiDmDescriptorName
110 *
111 * PARAMETERS: None
112 *
113 * RETURN: None
114 *
115 * DESCRIPTION: Emit a name for the descriptor if one is present (indicated
116 * by the name being changed from the default name.) A name is only
117 * emitted if a reference to the descriptor has been made somewhere
118 * in the original ASL code.
119 *
120 ******************************************************************************/
121
122 void
123 AcpiDmDescriptorName (
124 void)
125 {
126
127 if (ResourceName == ACPI_DEFAULT_RESNAME)
128 {
129 return;
130 }
131
132 AcpiOsPrintf ("%4.4s", (char *) &ResourceName);
133 }
134
135
136 /*******************************************************************************
137 *
138 * FUNCTION: AcpiDmDumpInteger*
139 *
140 * PARAMETERS: Value - Value to emit
141 * Name - Associated name (emitted as a comment)
142 *
143 * RETURN: None
144 *
145 * DESCRIPTION: Integer output helper functions
146 *
147 ******************************************************************************/
148
149 void
150 AcpiDmDumpInteger8 (
151 UINT8 Value,
152 const char *Name)
153 {
154 AcpiOsPrintf ("0x%2.2X, // %s\n", Value, Name);
155 }
156
157 void
158 AcpiDmDumpInteger16 (
159 UINT16 Value,
160 const char *Name)
161 {
162 AcpiOsPrintf ("0x%4.4X, // %s\n", Value, Name);
163 }
164
165 void
166 AcpiDmDumpInteger32 (
167 UINT32 Value,
168 const char *Name)
169 {
170 AcpiOsPrintf ("0x%8.8X, // %s\n", Value, Name);
171 }
172
173 void
174 AcpiDmDumpInteger64 (
175 UINT64 Value,
176 const char *Name)
177 {
178 AcpiOsPrintf ("0x%8.8X%8.8X, // %s\n", ACPI_FORMAT_UINT64 (Value), Name);
179 }
180
181
182 /*******************************************************************************
183 *
184 * FUNCTION: AcpiDmBitList
185 *
186 * PARAMETERS: Mask - 16-bit value corresponding to 16 interrupt
187 * or DMA values
188 *
189 * RETURN: None
190 *
191 * DESCRIPTION: Dump a bit mask as a list of individual interrupt/DMA levels.
192 *
193 ******************************************************************************/
194
195 void
196 AcpiDmBitList (
197 UINT16 Mask)
198 {
199 UINT32 i;
200 BOOLEAN Previous = FALSE;
201
202
203 /* Open the initializer list */
204
205 AcpiOsPrintf ("{");
206
207 /* Examine each bit */
208
209 for (i = 0; i < 16; i++)
210 {
211 /* Only interested in bits that are set to 1 */
212
213 if (Mask & 1)
214 {
215 if (Previous)
216 {
217 AcpiOsPrintf (",");
218 }
219
220 Previous = TRUE;
221 AcpiOsPrintf ("%u", i);
222 }
223
224 Mask >>= 1;
225 }
226
227 /* Close list */
228
229 AcpiOsPrintf ("}\n");
230 }
231
232
233 /*******************************************************************************
234 *
235 * FUNCTION: AcpiDmResourceTemplate
236 *
237 * PARAMETERS: Info - Current parse tree walk info
238 * ByteData - Pointer to the byte list data
239 * ByteCount - Length of the byte list
240 *
241 * RETURN: None
242 *
243 * DESCRIPTION: Dump the contents of a Resource Template containing a set of
244 * Resource Descriptors.
245 *
246 ******************************************************************************/
247
248 void
249 AcpiDmResourceTemplate (
250 ACPI_OP_WALK_INFO *Info,
251 ACPI_PARSE_OBJECT *Op,
252 UINT8 *ByteData,
253 UINT32 ByteCount)
254 {
255 ACPI_STATUS Status;
256 UINT32 CurrentByteOffset;
257 UINT8 ResourceType;
258 UINT32 ResourceLength;
259 void *Aml;
260 UINT32 Level;
261 BOOLEAN DependentFns = FALSE;
262 UINT8 ResourceIndex;
263 ACPI_NAMESPACE_NODE *Node;
264
265
266 if (Op->Asl.AmlOpcode != AML_FIELD_OP)
267 {
268 Info->MappingOp = Op;
269 }
270
271 Level = Info->Level;
272 ResourceName = ACPI_DEFAULT_RESNAME;
273 Node = Op->Common.Node;
274 if (Node)
275 {
276 Node = Node->Child;
277 }
278
279 for (CurrentByteOffset = 0; CurrentByteOffset < ByteCount;)
280 {
281 Aml = &ByteData[CurrentByteOffset];
282
283 /* Get the descriptor type and length */
284
285 ResourceType = AcpiUtGetResourceType (Aml);
286 ResourceLength = AcpiUtGetResourceLength (Aml);
287
288 /* Validate the Resource Type and Resource Length */
289
290 Status = AcpiUtValidateResource (NULL, Aml, &ResourceIndex);
291 if (ACPI_FAILURE (Status))
292 {
293 AcpiOsPrintf (
294 "/*** Could not validate Resource, type (%X) %s***/\n",
295 ResourceType, AcpiFormatException (Status));
296 return;
297 }
298
299 /* Point to next descriptor */
300
301 CurrentByteOffset += AcpiUtGetDescriptorLength (Aml);
302
303 /* Descriptor pre-processing */
304
305 switch (ResourceType)
306 {
307 case ACPI_RESOURCE_NAME_START_DEPENDENT:
308
309 /* Finish a previous StartDependentFns */
310
311 if (DependentFns)
312 {
313 Level--;
314 AcpiDmIndent (Level);
315 AcpiOsPrintf ("}\n");
316 }
317 break;
318
319 case ACPI_RESOURCE_NAME_END_DEPENDENT:
320
321 Level--;
322 DependentFns = FALSE;
323 break;
324
325 case ACPI_RESOURCE_NAME_END_TAG:
326
327 /* Normal exit, the resource list is finished */
328
329 if (DependentFns)
330 {
331 /*
332 * Close an open StartDependentDescriptor. This indicates a
333 * missing EndDependentDescriptor.
334 */
335 Level--;
336
337 /* Go ahead and insert EndDependentFn() */
338
339 AcpiDmEndDependentDescriptor (Info, Aml, ResourceLength, Level);
340
341 AcpiDmIndent (Level);
342 AcpiOsPrintf (
343 "/*** Disassembler: inserted "
344 "missing EndDependentFn () ***/\n");
345 }
346 return;
347
348 default:
349
350 break;
351 }
352
353 /* Disassemble the resource structure */
354
355 if (Node)
356 {
357 ResourceName = Node->Name.Integer;
358 Node = Node->Peer;
359 }
360
361 AcpiGbl_DmResourceDispatch [ResourceIndex] (
362 Info, Aml, ResourceLength, Level);
363
364 /* Descriptor post-processing */
365
366 if (ResourceType == ACPI_RESOURCE_NAME_START_DEPENDENT)
367 {
368 DependentFns = TRUE;
369 Level++;
370 }
371 }
372 }
373
374
375 /*******************************************************************************
376 *
377 * FUNCTION: AcpiDmIsResourceTemplate
378 *
379 * PARAMETERS: WalkState - Current walk info
380 * Op - Buffer Op to be examined
381 *
382 * RETURN: Status. AE_OK if valid template
383 *
384 * DESCRIPTION: Walk a byte list to determine if it consists of a valid set
385 * of resource descriptors. Nothing is output.
386 *
387 ******************************************************************************/
388
389 ACPI_STATUS
390 AcpiDmIsResourceTemplate (
391 ACPI_WALK_STATE *WalkState,
392 ACPI_PARSE_OBJECT *Op)
393 {
394 ACPI_STATUS Status;
395 ACPI_PARSE_OBJECT *NextOp;
396 UINT8 *Aml;
397 UINT8 *EndAml;
398 UINT32 BufferLength;
399 UINT32 DeclaredBufferLength;
400
401
402 /* This op must be a buffer */
403
404 if (Op->Common.AmlOpcode != AML_BUFFER_OP)
405 {
406 return (AE_TYPE);
407 }
408
409 /*
410 * Get the declared length of the buffer.
411 * This is the nn in "Buffer (nn)"
412 */
413 NextOp = Op->Common.Value.Arg;
414 if (!NextOp)
415 {
416 AcpiOsPrintf ("NULL byte list in buffer\n");
417 return (AE_TYPE);
418 }
419
420 DeclaredBufferLength = NextOp->Common.Value.Size;
421
422 /* Get the length of the raw initialization byte list */
423
424 NextOp = NextOp->Common.Next;
425 if (!NextOp)
426 {
427 return (AE_TYPE);
428 }
429
430 Aml = NextOp->Named.Data;
431 BufferLength = NextOp->Common.Value.Size;
432
433 /*
434 * Any buffer smaller than one byte cannot possibly be a resource
435 * template. Two bytes could possibly be a "NULL" resource template
436 * with a lone end tag descriptor (as generated via
437 * "ResourceTemplate(){}"), but this would be an extremely unusual
438 * case, as the template would be essentially useless. The disassembler
439 * therefore does not recognize any two-byte buffer as a resource
440 * template.
441 */
442 if (BufferLength <= 2)
443 {
444 return (AE_TYPE);
445 }
446
447 /*
448 * Not a template if declared buffer length != actual length of the
449 * initialization byte list. Because the resource macros will create
450 * a buffer of the exact required length (buffer length will be equal
451 * to the actual length).
452 *
453 * NOTE (April 2017): Resource templates with this issue have been
454 * seen in the field. We still don't want to attempt to disassemble
455 * a buffer like this to a resource template because this output
456 * would not match the original input buffer (it would be shorter
457 * than the original when the disassembled code is recompiled).
458 * Basically, a buffer like this appears to be hand crafted in the
459 * first place, so just emitting a buffer object instead of a
460 * resource template more closely resembles the original ASL code.
461 */
462 if (DeclaredBufferLength != BufferLength)
463 {
464 return (AE_TYPE);
465 }
466
467 /* Walk the byte list, abort on any invalid descriptor type or length */
468
469 Status = AcpiUtWalkAmlResources (WalkState, Aml, BufferLength,
470 NULL, ACPI_CAST_INDIRECT_PTR (void, &EndAml));
471 if (ACPI_FAILURE (Status))
472 {
473 return (AE_TYPE);
474 }
475
476 /*
477 * For the resource template to be valid, one EndTag must appear
478 * at the very end of the ByteList, not before. (For proper disassembly
479 * of a ResourceTemplate, the buffer must not have any extra data after
480 * the EndTag.)
481 */
482 if ((Aml + BufferLength - sizeof (AML_RESOURCE_END_TAG)) != EndAml)
483 {
484 return (AE_AML_NO_RESOURCE_END_TAG);
485 }
486
487 /*
488 * All resource descriptors are valid, therefore this list appears
489 * to be a valid resource template
490 */
491 return (AE_OK);
492 }
493