aslmapoutput.c revision 1.1.1.1 1 /******************************************************************************
2 *
3 * Module Name: aslmapoutput - Output/emit the resource descriptor/device maps
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2014, 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 "acapps.h"
47 #include "aslcompiler.h"
48 #include "aslcompiler.y.h"
49 #include "acinterp.h"
50 #include "acparser.h"
51 #include "acnamesp.h"
52 #include "amlcode.h"
53
54 /* This module used for application-level code only */
55
56 #define _COMPONENT ACPI_COMPILER
57 ACPI_MODULE_NAME ("aslmapoutput")
58
59 /* Local prototypes */
60
61 static void
62 MpEmitGpioInfo (
63 void);
64
65 static void
66 MpEmitSerialInfo (
67 void);
68
69 static void
70 MpEmitDeviceTree (
71 void);
72
73 static ACPI_STATUS
74 MpEmitOneDevice (
75 ACPI_HANDLE ObjHandle,
76 UINT32 NestingLevel,
77 void *Context,
78 void **ReturnValue);
79
80 static void
81 MpXrefDevices (
82 ACPI_GPIO_INFO *Info);
83
84 static ACPI_STATUS
85 MpNamespaceXrefBegin (
86 ACPI_PARSE_OBJECT *Op,
87 UINT32 Level,
88 void *Context);
89
90
91 /* Strings used to decode flag bits */
92
93 const char *DirectionDecode[] =
94 {
95 "Both I/O ",
96 "InputOnly ",
97 "OutputOnly ",
98 "Preserve "
99 };
100
101 const char *PolarityDecode[] =
102 {
103 "ActiveHigh",
104 "ActiveLow ",
105 "ActiveBoth",
106 "Reserved "
107 };
108
109
110 /*******************************************************************************
111 *
112 * FUNCTION: MpEmitMappingInfo
113 *
114 * PARAMETERS: None
115 *
116 * RETURN: None
117 *
118 * DESCRIPTION: External interface.
119 * Create and open the mapfile and emit all of the collected
120 * hardware mapping information. Includes: GPIO information,
121 * Serial information, and a dump of the entire ACPI device tree.
122 *
123 ******************************************************************************/
124
125 void
126 MpEmitMappingInfo (
127 void)
128 {
129 char *NewFilename;
130
131
132 /* Mapfile option enabled? */
133
134 if (!Gbl_MapfileFlag)
135 {
136 return;
137 }
138
139 /* Create/Open a map file */
140
141 NewFilename = FlGenerateFilename (Gbl_OutputFilenamePrefix,
142 FILE_SUFFIX_MAP);
143 if (!NewFilename)
144 {
145 AslCommonError (ASL_ERROR, ASL_MSG_LISTING_FILENAME,
146 0, 0, 0, 0, NULL, NULL);
147 }
148
149 /* Open the hex file, text mode (closed at compiler exit) */
150
151 FlOpenFile (ASL_FILE_MAP_OUTPUT, NewFilename, "w+t");
152 AslCompilerSignon (ASL_FILE_MAP_OUTPUT);
153 AslCompilerFileHeader (ASL_FILE_MAP_OUTPUT);
154
155 if (!Gbl_GpioList)
156 {
157 FlPrintFile (ASL_FILE_MAP_OUTPUT,
158 "\nNo GPIO devices found\n");
159 }
160
161 if (!Gbl_SerialList)
162 {
163 FlPrintFile (ASL_FILE_MAP_OUTPUT,
164 "\nNo Serial devices found (I2C/SPI/UART)\n");
165 }
166
167 if (!Gbl_GpioList && !Gbl_SerialList)
168 {
169 return;
170 }
171
172 /* Headers */
173
174 FlPrintFile (ASL_FILE_MAP_OUTPUT, "\nResource Descriptor Connectivity Map\n");
175 FlPrintFile (ASL_FILE_MAP_OUTPUT, "------------------------------------\n");
176
177 /* Emit GPIO and Serial descriptors, then entire ACPI device tree */
178
179 MpEmitGpioInfo ();
180 MpEmitSerialInfo ();
181 MpEmitDeviceTree ();
182
183 /* Clear the lists - no need to free memory here */
184
185 Gbl_SerialList = NULL;
186 Gbl_GpioList = NULL;
187 }
188
189
190 /*******************************************************************************
191 *
192 * FUNCTION: MpEmitGpioInfo
193 *
194 * PARAMETERS: None
195 *
196 * RETURN: None
197 *
198 * DESCRIPTION: Emit the info about all GPIO devices found during the
199 * compile or disassembly.
200 *
201 ******************************************************************************/
202
203 static void
204 MpEmitGpioInfo (
205 void)
206 {
207 ACPI_GPIO_INFO *Info;
208 char *Type;
209 char *PrevDeviceName = NULL;
210 const char *Direction;
211 const char *Polarity;
212 char *ParentPathname;
213 const char *Description;
214 char *HidString;
215 const AH_DEVICE_ID *HidInfo;
216
217
218 /* Walk the GPIO descriptor list */
219
220 Info = Gbl_GpioList;
221 while (Info)
222 {
223 HidString = MpGetHidViaNamestring (Info->DeviceName);
224
225 /* Print header info for the controller itself */
226
227 if (!PrevDeviceName ||
228 ACPI_STRCMP (PrevDeviceName, Info->DeviceName))
229 {
230 FlPrintFile (ASL_FILE_MAP_OUTPUT,
231 "\n\nGPIO Controller: %-8s %-28s",
232 HidString, Info->DeviceName);
233
234 HidInfo = AcpiAhMatchHardwareId (HidString);
235 if (HidInfo)
236 {
237 FlPrintFile (ASL_FILE_MAP_OUTPUT, " // %s",
238 HidInfo->Description);
239 }
240
241 FlPrintFile (ASL_FILE_MAP_OUTPUT,
242 "\n\nPin Type Direction Polarity"
243 " Dest _HID Destination\n");
244 }
245
246 PrevDeviceName = Info->DeviceName;
247
248 /* Setup various strings based upon the type (GpioInt or GpioIo) */
249
250 switch (Info->Type)
251 {
252 case AML_RESOURCE_GPIO_TYPE_INT:
253
254 Type = "GpioInt";
255 Direction = "-Interrupt-";
256 Polarity = PolarityDecode[Info->Polarity];
257 break;
258
259 case AML_RESOURCE_GPIO_TYPE_IO:
260
261 Type = "GpioIo ";
262 Direction = DirectionDecode[Info->Direction];
263 Polarity = " ";
264 break;
265
266 default:
267 continue;
268 }
269
270 /* Emit the GPIO info */
271
272 FlPrintFile (ASL_FILE_MAP_OUTPUT, "%4.4X %s %s %s ",
273 Info->PinNumber, Type, Direction, Polarity);
274
275 ParentPathname = NULL;
276 HidString = MpGetConnectionInfo (Info->Op, Info->PinIndex,
277 &Info->TargetNode, &ParentPathname);
278 if (HidString)
279 {
280 /*
281 * This is a Connection() field
282 * Attempt to find all references to the field.
283 */
284 FlPrintFile (ASL_FILE_MAP_OUTPUT, "%8s %-28s",
285 HidString, ParentPathname);
286
287 MpXrefDevices (Info);
288 }
289 else
290 {
291 /*
292 * For Devices, attempt to get the _HID description string.
293 * Failing that (many _HIDs are not recognized), attempt to
294 * get the _DDN description string.
295 */
296 HidString = MpGetParentDeviceHid (Info->Op, &Info->TargetNode,
297 &ParentPathname);
298
299 FlPrintFile (ASL_FILE_MAP_OUTPUT, "%8s %-28s",
300 HidString, ParentPathname);
301
302 /* Get the _HID description or _DDN string */
303
304 HidInfo = AcpiAhMatchHardwareId (HidString);
305 if (HidInfo)
306 {
307 FlPrintFile (ASL_FILE_MAP_OUTPUT, " // %s",
308 HidInfo->Description);
309 }
310 else if ((Description = MpGetDdnValue (ParentPathname)))
311 {
312 FlPrintFile (ASL_FILE_MAP_OUTPUT, " // %s (_DDN)",
313 Description);
314 }
315 }
316
317 FlPrintFile (ASL_FILE_MAP_OUTPUT, "\n");
318 ACPI_FREE (ParentPathname);
319 Info = Info->Next;
320 }
321 }
322
323
324 /*******************************************************************************
325 *
326 * FUNCTION: MpEmitSerialInfo
327 *
328 * PARAMETERS: None
329 *
330 * RETURN: None
331 *
332 * DESCRIPTION: Emit the info about all Serial devices found during the
333 * compile or disassembly.
334 *
335 ******************************************************************************/
336
337 static void
338 MpEmitSerialInfo (
339 void)
340 {
341 ACPI_SERIAL_INFO *Info;
342 char *Type;
343 char *ParentPathname;
344 char *PrevDeviceName = NULL;
345 char *HidString;
346 const AH_DEVICE_ID *HidInfo;
347 const char *Description;
348 AML_RESOURCE *Resource;
349
350
351 /* Walk the constructed serial descriptor list */
352
353 Info = Gbl_SerialList;
354 while (Info)
355 {
356 Resource = Info->Resource;
357 switch (Resource->CommonSerialBus.Type)
358 {
359 case AML_RESOURCE_I2C_SERIALBUSTYPE:
360 Type = "I2C ";
361 break;
362
363 case AML_RESOURCE_SPI_SERIALBUSTYPE:
364 Type = "SPI ";
365 break;
366
367 case AML_RESOURCE_UART_SERIALBUSTYPE:
368 Type = "UART";
369 break;
370
371 default:
372 Type = "UNKN";
373 break;
374 }
375
376 HidString = MpGetHidViaNamestring (Info->DeviceName);
377
378 /* Print header info for the controller itself */
379
380 if (!PrevDeviceName ||
381 ACPI_STRCMP (PrevDeviceName, Info->DeviceName))
382 {
383 FlPrintFile (ASL_FILE_MAP_OUTPUT, "\n\n%s Controller: ",
384 Type);
385 FlPrintFile (ASL_FILE_MAP_OUTPUT, "%-8s %-28s",
386 HidString, Info->DeviceName);
387
388 HidInfo = AcpiAhMatchHardwareId (HidString);
389 if (HidInfo)
390 {
391 FlPrintFile (ASL_FILE_MAP_OUTPUT, " // %s",
392 HidInfo->Description);
393 }
394
395 FlPrintFile (ASL_FILE_MAP_OUTPUT, "\n\n");
396 FlPrintFile (ASL_FILE_MAP_OUTPUT,
397 "Type Address Speed Dest _HID Destination\n");
398 }
399
400 PrevDeviceName = Info->DeviceName;
401
402 FlPrintFile (ASL_FILE_MAP_OUTPUT, "%s %4.4X %8.8X ",
403 Type, Info->Address, Info->Speed);
404
405 ParentPathname = NULL;
406 HidString = MpGetConnectionInfo (Info->Op, 0, &Info->TargetNode,
407 &ParentPathname);
408 if (HidString)
409 {
410 /*
411 * This is a Connection() field
412 * Attempt to find all references to the field.
413 */
414 FlPrintFile (ASL_FILE_MAP_OUTPUT, "%8s %-28s",
415 HidString, ParentPathname);
416 }
417 else
418 {
419 /* Normal resource template */
420
421 HidString = MpGetParentDeviceHid (Info->Op, &Info->TargetNode,
422 &ParentPathname);
423 FlPrintFile (ASL_FILE_MAP_OUTPUT, "%8s %-28s",
424 HidString, ParentPathname);
425
426 /* Get the _HID description or _DDN string */
427
428 HidInfo = AcpiAhMatchHardwareId (HidString);
429 if (HidInfo)
430 {
431 FlPrintFile (ASL_FILE_MAP_OUTPUT, " // %s",
432 HidInfo->Description);
433 }
434 else if ((Description = MpGetDdnValue (ParentPathname)))
435 {
436 FlPrintFile (ASL_FILE_MAP_OUTPUT, " // %s (_DDN)",
437 Description);
438 }
439 }
440
441 FlPrintFile (ASL_FILE_MAP_OUTPUT, "\n");
442 ACPI_FREE (ParentPathname);
443 Info = Info->Next;
444 }
445 }
446
447
448 /*******************************************************************************
449 *
450 * FUNCTION: MpEmitDeviceTree
451 *
452 * PARAMETERS: None
453 *
454 * RETURN: None
455 *
456 * DESCRIPTION: Emit information about all devices within the ACPI namespace.
457 *
458 ******************************************************************************/
459
460 static void
461 MpEmitDeviceTree (
462 void)
463 {
464
465 FlPrintFile (ASL_FILE_MAP_OUTPUT, "\n\nACPI Device Tree\n");
466 FlPrintFile (ASL_FILE_MAP_OUTPUT, "----------------\n\n");
467
468 FlPrintFile (ASL_FILE_MAP_OUTPUT, "Device Pathname "
469 "_HID Description\n\n");
470
471 /* Walk the namespace from the root */
472
473 (void) AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
474 ACPI_UINT32_MAX, FALSE, MpEmitOneDevice, NULL, NULL, NULL);
475 }
476
477
478 /*******************************************************************************
479 *
480 * FUNCTION: MpEmitOneDevice
481 *
482 * PARAMETERS: ACPI_NAMESPACE_WALK callback
483 *
484 * RETURN: Status
485 *
486 * DESCRIPTION: Emit information about one ACPI device in the namespace. Used
487 * during dump of all device objects within the namespace.
488 *
489 ******************************************************************************/
490
491 static ACPI_STATUS
492 MpEmitOneDevice (
493 ACPI_HANDLE ObjHandle,
494 UINT32 NestingLevel,
495 void *Context,
496 void **ReturnValue)
497 {
498 char *DevicePathname;
499 char *DdnString;
500 char *HidString;
501 const AH_DEVICE_ID *HidInfo;
502
503
504 /* Device pathname */
505
506 DevicePathname = AcpiNsGetExternalPathname (
507 ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle));
508
509 FlPrintFile (ASL_FILE_MAP_OUTPUT, "%-32s", DevicePathname);
510
511 /* _HID or _DDN */
512
513 HidString = MpGetHidValue (
514 ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle));
515 FlPrintFile (ASL_FILE_MAP_OUTPUT, "%8s", HidString);
516
517 HidInfo = AcpiAhMatchHardwareId (HidString);
518 if (HidInfo)
519 {
520 FlPrintFile (ASL_FILE_MAP_OUTPUT, " // %s",
521 HidInfo->Description);
522 }
523 else if ((DdnString = MpGetDdnValue (DevicePathname)))
524 {
525 FlPrintFile (ASL_FILE_MAP_OUTPUT, " // %s (_DDN)", DdnString);
526 }
527
528 FlPrintFile (ASL_FILE_MAP_OUTPUT, "\n");
529 ACPI_FREE (DevicePathname);
530 return (AE_OK);
531 }
532
533
534 /*******************************************************************************
535 *
536 * FUNCTION: MpXrefDevices
537 *
538 * PARAMETERS: Info - A GPIO Info block
539 *
540 * RETURN: None
541 *
542 * DESCRIPTION: Cross-reference the parse tree and find all references to the
543 * specified GPIO device.
544 *
545 ******************************************************************************/
546
547 static void
548 MpXrefDevices (
549 ACPI_GPIO_INFO *Info)
550 {
551
552 /* Walk the entire parse tree */
553
554 TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
555 MpNamespaceXrefBegin, NULL, Info);
556
557 if (!Info->References)
558 {
559 FlPrintFile (ASL_FILE_MAP_OUTPUT, " // **** No references in table");
560 }
561 }
562
563
564 /*******************************************************************************
565 *
566 * FUNCTION: MpNamespaceXrefBegin
567 *
568 * PARAMETERS: WALK_PARSE_TREE callback
569 *
570 * RETURN: Status
571 *
572 * DESCRIPTION: Walk parse tree callback used to cross-reference GPIO pins.
573 *
574 ******************************************************************************/
575
576 static ACPI_STATUS
577 MpNamespaceXrefBegin (
578 ACPI_PARSE_OBJECT *Op,
579 UINT32 Level,
580 void *Context)
581 {
582 ACPI_GPIO_INFO *Info = ACPI_CAST_PTR (ACPI_GPIO_INFO, Context);
583 const ACPI_OPCODE_INFO *OpInfo;
584 char *DevicePathname;
585 ACPI_PARSE_OBJECT *ParentOp;
586 char *HidString;
587
588
589 ACPI_FUNCTION_TRACE_PTR (MpNamespaceXrefBegin, Op);
590
591 /*
592 * If this node is the actual declaration of a name
593 * [such as the XXXX name in "Method (XXXX)"],
594 * we are not interested in it here. We only care about names that
595 * are references to other objects within the namespace and the
596 * parent objects of name declarations
597 */
598 if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)
599 {
600 return (AE_OK);
601 }
602
603 /* We are only interested in opcodes that have an associated name */
604
605 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
606
607 if ((OpInfo->Flags & AML_NAMED) ||
608 (OpInfo->Flags & AML_CREATE))
609 {
610 return (AE_OK);
611 }
612
613 if ((Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
614 (Op->Asl.ParseOpcode != PARSEOP_NAMESEG) &&
615 (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
616 {
617 return (AE_OK);
618 }
619
620 if (!Op->Asl.Node)
621 {
622 return (AE_OK);
623 }
624
625 ParentOp = Op->Asl.Parent;
626 if (ParentOp->Asl.ParseOpcode == PARSEOP_FIELD)
627 {
628 return (AE_OK);
629 }
630
631 if (Op->Asl.Node == Info->TargetNode)
632 {
633 DevicePathname = AcpiNsGetExternalPathname (
634 Info->TargetNode);
635
636 while (ParentOp && (!ParentOp->Asl.Node))
637 {
638 ParentOp = ParentOp->Asl.Parent;
639 }
640
641 if (ParentOp)
642 {
643 DevicePathname = AcpiNsGetExternalPathname (
644 ParentOp->Asl.Node);
645
646 if (!Info->References)
647 {
648 FlPrintFile (ASL_FILE_MAP_OUTPUT, " // References:");
649 }
650
651 HidString = MpGetHidViaNamestring (DevicePathname);
652
653 FlPrintFile (ASL_FILE_MAP_OUTPUT, " %s [%s]",
654 DevicePathname, HidString);
655
656 Info->References++;
657 }
658 }
659
660 return (AE_OK);
661 }
662