dmresrc.c revision 1.9 1 /*******************************************************************************
2 *
3 * Module Name: dmresrc.c - Resource Descriptor disassembly
4 *
5 ******************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2017, 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 "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 - Curent 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 DependentFns = FALSE;
337
338 /* Go ahead and insert EndDependentFn() */
339
340 AcpiDmEndDependentDescriptor (Info, Aml, ResourceLength, Level);
341
342 AcpiDmIndent (Level);
343 AcpiOsPrintf (
344 "/*** Disassembler: inserted "
345 "missing EndDependentFn () ***/\n");
346 }
347 return;
348
349 default:
350
351 break;
352 }
353
354 /* Disassemble the resource structure */
355
356 if (Node)
357 {
358 ResourceName = Node->Name.Integer;
359 Node = Node->Peer;
360 }
361
362 AcpiGbl_DmResourceDispatch [ResourceIndex] (
363 Info, Aml, ResourceLength, Level);
364
365 /* Descriptor post-processing */
366
367 if (ResourceType == ACPI_RESOURCE_NAME_START_DEPENDENT)
368 {
369 DependentFns = TRUE;
370 Level++;
371 }
372 }
373 }
374
375
376 /*******************************************************************************
377 *
378 * FUNCTION: AcpiDmIsResourceTemplate
379 *
380 * PARAMETERS: WalkState - Current walk info
381 * Op - Buffer Op to be examined
382 *
383 * RETURN: Status. AE_OK if valid template
384 *
385 * DESCRIPTION: Walk a byte list to determine if it consists of a valid set
386 * of resource descriptors. Nothing is output.
387 *
388 ******************************************************************************/
389
390 ACPI_STATUS
391 AcpiDmIsResourceTemplate (
392 ACPI_WALK_STATE *WalkState,
393 ACPI_PARSE_OBJECT *Op)
394 {
395 ACPI_STATUS Status;
396 ACPI_PARSE_OBJECT *NextOp;
397 UINT8 *Aml;
398 UINT8 *EndAml;
399 UINT32 BufferLength;
400 UINT32 DeclaredBufferLength;
401
402
403 /* This op must be a buffer */
404
405 if (Op->Common.AmlOpcode != AML_BUFFER_OP)
406 {
407 return (AE_TYPE);
408 }
409
410 /*
411 * Get the declared length of the buffer.
412 * This is the nn in "Buffer (nn)"
413 */
414 NextOp = Op->Common.Value.Arg;
415 if (!NextOp)
416 {
417 AcpiOsPrintf ("NULL byte list in buffer\n");
418 return (AE_TYPE);
419 }
420
421 DeclaredBufferLength = NextOp->Common.Value.Size;
422
423 /* Get the length of the raw initialization byte list */
424
425 NextOp = NextOp->Common.Next;
426 if (!NextOp)
427 {
428 return (AE_TYPE);
429 }
430
431 Aml = NextOp->Named.Data;
432 BufferLength = NextOp->Common.Value.Size;
433
434 /*
435 * Any buffer smaller than one byte cannot possibly be a resource
436 * template. Two bytes could possibly be a "NULL" resource template
437 * with a lone end tag descriptor (as generated via
438 * "ResourceTemplate(){}"), but this would be an extremely unusual
439 * case, as the template would be essentially useless. The disassembler
440 * therefore does not recognize any two-byte buffer as a resource
441 * template.
442 */
443 if (BufferLength <= 2)
444 {
445 return (AE_TYPE);
446 }
447
448 /*
449 * Not a template if declared buffer length != actual length of the
450 * intialization byte list. Because the resource macros will create
451 * a buffer of the exact required length (buffer length will be equal
452 * to the actual length).
453 *
454 * NOTE (April 2017): Resource templates with this issue have been
455 * seen in the field. We still don't want to attempt to disassemble
456 * a buffer like this to a resource template because this output
457 * would not match the original input buffer (it would be shorter
458 * than the original when the disassembled code is recompiled).
459 * Basically, a buffer like this appears to be hand crafted in the
460 * first place, so just emitting a buffer object instead of a
461 * resource template more closely resembles the original ASL code.
462 */
463 if (DeclaredBufferLength != BufferLength)
464 {
465 return (AE_TYPE);
466 }
467
468 /* Walk the byte list, abort on any invalid descriptor type or length */
469
470 Status = AcpiUtWalkAmlResources (WalkState, Aml, BufferLength,
471 NULL, ACPI_CAST_INDIRECT_PTR (void, &EndAml));
472 if (ACPI_FAILURE (Status))
473 {
474 return (AE_TYPE);
475 }
476
477 /*
478 * For the resource template to be valid, one EndTag must appear
479 * at the very end of the ByteList, not before. (For proper disassembly
480 * of a ResourceTemplate, the buffer must not have any extra data after
481 * the EndTag.)
482 */
483 if ((Aml + BufferLength - sizeof (AML_RESOURCE_END_TAG)) != EndAml)
484 {
485 return (AE_AML_NO_RESOURCE_END_TAG);
486 }
487
488 /*
489 * All resource descriptors are valid, therefore this list appears
490 * to be a valid resource template
491 */
492 return (AE_OK);
493 }
494