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