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