1 /****************************************************************************** 2 * 3 * Module Name: dmextern - Support for External() ASL statements 4 * 5 *****************************************************************************/ 6 7 /****************************************************************************** 8 * 9 * 1. Copyright Notice 10 * 11 * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. 12 * All rights reserved. 13 * 14 * 2. License 15 * 16 * 2.1. This is your license from Intel Corp. under its intellectual property 17 * rights. You may have additional license terms from the party that provided 18 * you this software, covering your right to use that party's intellectual 19 * property rights. 20 * 21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22 * copy of the source code appearing in this file ("Covered Code") an 23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24 * base code distributed originally by Intel ("Original Intel Code") to copy, 25 * make derivatives, distribute, use and display any portion of the Covered 26 * Code in any form, with the right to sublicense such rights; and 27 * 28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29 * license (with the right to sublicense), under only those claims of Intel 30 * patents that are infringed by the Original Intel Code, to make, use, sell, 31 * offer to sell, and import the Covered Code and derivative works thereof 32 * solely to the minimum extent necessary to exercise the above copyright 33 * license, and in no event shall the patent license extend to any additions 34 * to or modifications of the Original Intel Code. No other license or right 35 * is granted directly or by implication, estoppel or otherwise; 36 * 37 * The above copyright and patent license is granted only if the following 38 * conditions are met: 39 * 40 * 3. Conditions 41 * 42 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43 * Redistribution of source code of any substantial portion of the Covered 44 * Code or modification with rights to further distribute source must include 45 * the above Copyright Notice, the above License, this list of Conditions, 46 * and the following Disclaimer and Export Compliance provision. In addition, 47 * Licensee must cause all Covered Code to which Licensee contributes to 48 * contain a file documenting the changes Licensee made to create that Covered 49 * Code and the date of any change. Licensee must include in that file the 50 * documentation of any changes made by any predecessor Licensee. Licensee 51 * must include a prominent statement that the modification is derived, 52 * directly or indirectly, from Original Intel Code. 53 * 54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55 * Redistribution of source code of any substantial portion of the Covered 56 * Code or modification without rights to further distribute source must 57 * include the following Disclaimer and Export Compliance provision in the 58 * documentation and/or other materials provided with distribution. In 59 * addition, Licensee may not authorize further sublicense of source of any 60 * portion of the Covered Code, and must include terms to the effect that the 61 * license from Licensee to its licensee is limited to the intellectual 62 * property embodied in the software Licensee provides to its licensee, and 63 * not to intellectual property embodied in modifications its licensee may 64 * make. 65 * 66 * 3.3. Redistribution of Executable. Redistribution in executable form of any 67 * substantial portion of the Covered Code or modification must reproduce the 68 * above Copyright Notice, and the following Disclaimer and Export Compliance 69 * provision in the documentation and/or other materials provided with the 70 * distribution. 71 * 72 * 3.4. Intel retains all right, title, and interest in and to the Original 73 * Intel Code. 74 * 75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76 * Intel shall be used in advertising or otherwise to promote the sale, use or 77 * other dealings in products derived from or relating to the Covered Code 78 * without prior written authorization from Intel. 79 * 80 * 4. Disclaimer and Export Compliance 81 * 82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88 * PARTICULAR PURPOSE. 89 * 90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97 * LIMITED REMEDY. 98 * 99 * 4.3. Licensee shall not export, either directly or indirectly, any of this 100 * software or system incorporating such software without first obtaining any 101 * required license or other approval from the U. S. Department of Commerce or 102 * any other agency or department of the United States Government. In the 103 * event Licensee exports any such software from the United States or 104 * re-exports any such software from a foreign destination, Licensee shall 105 * ensure that the distribution and export/re-export of the software is in 106 * compliance with all laws, regulations, orders, or other restrictions of the 107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108 * any of its subsidiaries will export/re-export any technical data, process, 109 * software, or service, directly or indirectly, to any country for which the 110 * United States government or any agency thereof requires an export license, 111 * other governmental approval, or letter of assurance, without first obtaining 112 * such license, approval or letter. 113 * 114 *****************************************************************************/ 115 116 #include <contrib/dev/acpica/include/acpi.h> 117 #include <contrib/dev/acpica/include/accommon.h> 118 #include <contrib/dev/acpica/include/amlcode.h> 119 #include <contrib/dev/acpica/include/acnamesp.h> 120 #include <contrib/dev/acpica/include/acdisasm.h> 121 122 123 /* 124 * This module is used for application-level code (iASL disassembler) only. 125 * 126 * It contains the code to create and emit any necessary External() ASL 127 * statements for the module being disassembled. 128 */ 129 #define _COMPONENT ACPI_CA_DISASSEMBLER 130 ACPI_MODULE_NAME ("dmextern") 131 132 133 /* 134 * This table maps ACPI_OBJECT_TYPEs to the corresponding ASL 135 * ObjectTypeKeyword. Used to generate typed external declarations 136 */ 137 static const char *AcpiGbl_DmTypeNames[] = 138 { 139 /* 00 */ "", /* Type ANY */ 140 /* 01 */ ", IntObj", 141 /* 02 */ ", StrObj", 142 /* 03 */ ", BuffObj", 143 /* 04 */ ", PkgObj", 144 /* 05 */ ", FieldUnitObj", 145 /* 06 */ ", DeviceObj", 146 /* 07 */ ", EventObj", 147 /* 08 */ ", MethodObj", 148 /* 09 */ ", MutexObj", 149 /* 10 */ ", OpRegionObj", 150 /* 11 */ ", PowerResObj", 151 /* 12 */ ", ProcessorObj", 152 /* 13 */ ", ThermalZoneObj", 153 /* 14 */ ", BuffFieldObj", 154 /* 15 */ ", DDBHandleObj", 155 /* 16 */ "", /* Debug object */ 156 /* 17 */ ", FieldUnitObj", 157 /* 18 */ ", FieldUnitObj", 158 /* 19 */ ", FieldUnitObj" 159 }; 160 161 162 /* Local prototypes */ 163 164 static const char * 165 AcpiDmGetObjectTypeName ( 166 ACPI_OBJECT_TYPE Type); 167 168 static char * 169 AcpiDmNormalizeParentPrefix ( 170 ACPI_PARSE_OBJECT *Op, 171 char *Path); 172 173 174 /******************************************************************************* 175 * 176 * FUNCTION: AcpiDmGetObjectTypeName 177 * 178 * PARAMETERS: Type - An ACPI_OBJECT_TYPE 179 * 180 * RETURN: Pointer to a string 181 * 182 * DESCRIPTION: Map an object type to the ASL object type string. 183 * 184 ******************************************************************************/ 185 186 static const char * 187 AcpiDmGetObjectTypeName ( 188 ACPI_OBJECT_TYPE Type) 189 { 190 191 if (Type == ACPI_TYPE_LOCAL_SCOPE) 192 { 193 Type = ACPI_TYPE_DEVICE; 194 } 195 196 else if (Type > ACPI_TYPE_LOCAL_INDEX_FIELD) 197 { 198 return (""); 199 } 200 201 return (AcpiGbl_DmTypeNames[Type]); 202 } 203 204 205 /******************************************************************************* 206 * 207 * FUNCTION: AcpiDmNormalizeParentPrefix 208 * 209 * PARAMETERS: Op - Parse op 210 * Path - Path with parent prefix 211 * 212 * RETURN: The full pathname to the object (from the namespace root) 213 * 214 * DESCRIPTION: Returns the full pathname of a path with parent prefix 215 * The caller must free the fullpath returned. 216 * 217 ******************************************************************************/ 218 219 static char * 220 AcpiDmNormalizeParentPrefix ( 221 ACPI_PARSE_OBJECT *Op, 222 char *Path) 223 { 224 ACPI_NAMESPACE_NODE *Node; 225 char *Fullpath; 226 char *ParentPath; 227 ACPI_SIZE Length; 228 229 230 /* Search upwards in the parse tree until we reach a namespace node */ 231 232 while (Op) 233 { 234 if (Op->Common.Node) 235 { 236 break; 237 } 238 239 Op = Op->Common.Parent; 240 } 241 242 if (!Op) 243 { 244 return (NULL); 245 } 246 247 /* 248 * Find the actual parent node for the reference: 249 * Remove all carat prefixes from the input path. 250 * There may be multiple parent prefixes (For example, ^^^M000) 251 */ 252 Node = Op->Common.Node; 253 while (Node && (*Path == (UINT8) AML_PARENT_PREFIX)) 254 { 255 Node = Node->Parent; 256 Path++; 257 } 258 259 if (!Node) 260 { 261 return (NULL); 262 } 263 264 /* Get the full pathname for the parent node */ 265 266 ParentPath = AcpiNsGetExternalPathname (Node); 267 if (!ParentPath) 268 { 269 return (NULL); 270 } 271 272 Length = (ACPI_STRLEN (ParentPath) + ACPI_STRLEN (Path) + 1); 273 if (ParentPath[1]) 274 { 275 /* 276 * If ParentPath is not just a simple '\', increment the length 277 * for the required dot separator (ParentPath.Path) 278 */ 279 Length++; 280 } 281 282 Fullpath = ACPI_ALLOCATE_ZEROED (Length); 283 if (!Fullpath) 284 { 285 goto Cleanup; 286 } 287 288 /* 289 * Concatenate parent fullpath and path. For example, 290 * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT" 291 * 292 * Copy the parent path 293 */ 294 ACPI_STRCAT (Fullpath, ParentPath); 295 296 /* Add dot separator (don't need dot if parent fullpath is a single "\") */ 297 298 if (ParentPath[1]) 299 { 300 ACPI_STRCAT (Fullpath, "."); 301 } 302 303 /* Copy child path (carat parent prefix(es) were skipped above) */ 304 305 ACPI_STRCAT (Fullpath, Path); 306 307 Cleanup: 308 ACPI_FREE (ParentPath); 309 return (Fullpath); 310 } 311 312 313 /******************************************************************************* 314 * 315 * FUNCTION: AcpiDmAddToExternalFileList 316 * 317 * PARAMETERS: PathList - Single path or list separated by comma 318 * 319 * RETURN: None 320 * 321 * DESCRIPTION: Add external files to global list 322 * 323 ******************************************************************************/ 324 325 ACPI_STATUS 326 AcpiDmAddToExternalFileList ( 327 char *PathList) 328 { 329 ACPI_EXTERNAL_FILE *ExternalFile; 330 char *Path; 331 char *TmpPath; 332 333 334 if (!PathList) 335 { 336 return (AE_OK); 337 } 338 339 Path = strtok (PathList, ","); 340 341 while (Path) 342 { 343 TmpPath = ACPI_ALLOCATE_ZEROED (ACPI_STRLEN (Path) + 1); 344 if (!TmpPath) 345 { 346 return (AE_NO_MEMORY); 347 } 348 349 ACPI_STRCPY (TmpPath, Path); 350 351 ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE)); 352 if (!ExternalFile) 353 { 354 ACPI_FREE (TmpPath); 355 return (AE_NO_MEMORY); 356 } 357 358 ExternalFile->Path = TmpPath; 359 360 if (AcpiGbl_ExternalFileList) 361 { 362 ExternalFile->Next = AcpiGbl_ExternalFileList; 363 } 364 365 AcpiGbl_ExternalFileList = ExternalFile; 366 Path = strtok (NULL, ","); 367 } 368 369 return (AE_OK); 370 } 371 372 373 /******************************************************************************* 374 * 375 * FUNCTION: AcpiDmClearExternalFileList 376 * 377 * PARAMETERS: None 378 * 379 * RETURN: None 380 * 381 * DESCRIPTION: Clear the external file list 382 * 383 ******************************************************************************/ 384 385 void 386 AcpiDmClearExternalFileList ( 387 void) 388 { 389 ACPI_EXTERNAL_FILE *NextExternal; 390 391 392 while (AcpiGbl_ExternalFileList) 393 { 394 NextExternal = AcpiGbl_ExternalFileList->Next; 395 ACPI_FREE (AcpiGbl_ExternalFileList->Path); 396 ACPI_FREE (AcpiGbl_ExternalFileList); 397 AcpiGbl_ExternalFileList = NextExternal; 398 } 399 } 400 401 402 /******************************************************************************* 403 * 404 * FUNCTION: AcpiDmAddToExternalList 405 * 406 * PARAMETERS: Op - Current parser Op 407 * Path - Internal (AML) path to the object 408 * Type - ACPI object type to be added 409 * Value - Arg count if adding a Method object 410 * 411 * RETURN: None 412 * 413 * DESCRIPTION: Insert a new name into the global list of Externals which 414 * will in turn be later emitted as an External() declaration 415 * in the disassembled output. 416 * 417 ******************************************************************************/ 418 419 void 420 AcpiDmAddToExternalList ( 421 ACPI_PARSE_OBJECT *Op, 422 char *Path, 423 UINT8 Type, 424 UINT32 Value) 425 { 426 char *ExternalPath; 427 char *Fullpath = NULL; 428 ACPI_EXTERNAL_LIST *NewExternal; 429 ACPI_EXTERNAL_LIST *NextExternal; 430 ACPI_EXTERNAL_LIST *PrevExternal = NULL; 431 ACPI_STATUS Status; 432 433 434 if (!Path) 435 { 436 return; 437 } 438 439 /* Externalize the ACPI path */ 440 441 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path, 442 NULL, &ExternalPath); 443 if (ACPI_FAILURE (Status)) 444 { 445 return; 446 } 447 448 /* Get the full pathname from root if "Path" has a parent prefix */ 449 450 if (*Path == (UINT8) AML_PARENT_PREFIX) 451 { 452 Fullpath = AcpiDmNormalizeParentPrefix (Op, ExternalPath); 453 if (Fullpath) 454 { 455 /* Set new external path */ 456 457 ACPI_FREE (ExternalPath); 458 ExternalPath = Fullpath; 459 } 460 } 461 462 /* Check all existing externals to ensure no duplicates */ 463 464 NextExternal = AcpiGbl_ExternalList; 465 while (NextExternal) 466 { 467 if (!ACPI_STRCMP (ExternalPath, NextExternal->Path)) 468 { 469 /* Duplicate method, check that the Value (ArgCount) is the same */ 470 471 if ((NextExternal->Type == ACPI_TYPE_METHOD) && 472 (NextExternal->Value != Value)) 473 { 474 ACPI_ERROR ((AE_INFO, 475 "Argument count mismatch for method %s %u %u", 476 NextExternal->Path, NextExternal->Value, Value)); 477 } 478 479 /* Allow upgrade of type from ANY */ 480 481 else if (NextExternal->Type == ACPI_TYPE_ANY) 482 { 483 NextExternal->Type = Type; 484 NextExternal->Value = Value; 485 } 486 487 ACPI_FREE (ExternalPath); 488 return; 489 } 490 491 NextExternal = NextExternal->Next; 492 } 493 494 /* Allocate and init a new External() descriptor */ 495 496 NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST)); 497 if (!NewExternal) 498 { 499 ACPI_FREE (ExternalPath); 500 return; 501 } 502 503 NewExternal->Path = ExternalPath; 504 NewExternal->Type = Type; 505 NewExternal->Value = Value; 506 NewExternal->Length = (UINT16) ACPI_STRLEN (ExternalPath); 507 508 /* Was the external path with parent prefix normalized to a fullpath? */ 509 510 if (Fullpath == ExternalPath) 511 { 512 /* Get new internal path */ 513 514 Status = AcpiNsInternalizeName (ExternalPath, &Path); 515 if (ACPI_FAILURE (Status)) 516 { 517 ACPI_FREE (ExternalPath); 518 ACPI_FREE (NewExternal); 519 return; 520 } 521 522 /* Set flag to indicate External->InternalPath need to be freed */ 523 524 NewExternal->Flags |= ACPI_IPATH_ALLOCATED; 525 } 526 527 NewExternal->InternalPath = Path; 528 529 /* Link the new descriptor into the global list, ordered by string length */ 530 531 NextExternal = AcpiGbl_ExternalList; 532 while (NextExternal) 533 { 534 if (NewExternal->Length <= NextExternal->Length) 535 { 536 if (PrevExternal) 537 { 538 PrevExternal->Next = NewExternal; 539 } 540 else 541 { 542 AcpiGbl_ExternalList = NewExternal; 543 } 544 545 NewExternal->Next = NextExternal; 546 return; 547 } 548 549 PrevExternal = NextExternal; 550 NextExternal = NextExternal->Next; 551 } 552 553 if (PrevExternal) 554 { 555 PrevExternal->Next = NewExternal; 556 } 557 else 558 { 559 AcpiGbl_ExternalList = NewExternal; 560 } 561 } 562 563 564 /******************************************************************************* 565 * 566 * FUNCTION: AcpiDmAddExternalsToNamespace 567 * 568 * PARAMETERS: None 569 * 570 * RETURN: None 571 * 572 * DESCRIPTION: Add all externals to the namespace. Allows externals to be 573 * "resolved". 574 * 575 ******************************************************************************/ 576 577 void 578 AcpiDmAddExternalsToNamespace ( 579 void) 580 { 581 ACPI_STATUS Status; 582 ACPI_NAMESPACE_NODE *Node; 583 ACPI_OPERAND_OBJECT *MethodDesc; 584 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList; 585 586 587 while (External) 588 { 589 /* Add the external name (object) into the namespace */ 590 591 Status = AcpiNsLookup (NULL, External->InternalPath, External->Type, 592 ACPI_IMODE_LOAD_PASS1, 593 ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE, 594 NULL, &Node); 595 596 if (ACPI_FAILURE (Status)) 597 { 598 ACPI_EXCEPTION ((AE_INFO, Status, 599 "while adding external to namespace [%s]", 600 External->Path)); 601 } 602 else if (External->Type == ACPI_TYPE_METHOD) 603 { 604 /* For methods, we need to save the argument count */ 605 606 MethodDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD); 607 MethodDesc->Method.ParamCount = (UINT8) External->Value; 608 Node->Object = MethodDesc; 609 } 610 611 External = External->Next; 612 } 613 } 614 615 616 /******************************************************************************* 617 * 618 * FUNCTION: AcpiDmGetExternalMethodCount 619 * 620 * PARAMETERS: None 621 * 622 * RETURN: The number of control method externals in the external list 623 * 624 * DESCRIPTION: Return the number of method externals that have been generated. 625 * If any control method externals have been found, we must 626 * re-parse the entire definition block with the new information 627 * (number of arguments for the methods.) This is limitation of 628 * AML, we don't know the number of arguments from the control 629 * method invocation itself. 630 * 631 ******************************************************************************/ 632 633 UINT32 634 AcpiDmGetExternalMethodCount ( 635 void) 636 { 637 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList; 638 UINT32 Count = 0; 639 640 641 while (External) 642 { 643 if (External->Type == ACPI_TYPE_METHOD) 644 { 645 Count++; 646 } 647 648 External = External->Next; 649 } 650 651 return (Count); 652 } 653 654 655 /******************************************************************************* 656 * 657 * FUNCTION: AcpiDmClearExternalList 658 * 659 * PARAMETERS: None 660 * 661 * RETURN: None 662 * 663 * DESCRIPTION: Free the entire External info list 664 * 665 ******************************************************************************/ 666 667 void 668 AcpiDmClearExternalList ( 669 void) 670 { 671 ACPI_EXTERNAL_LIST *NextExternal; 672 673 674 while (AcpiGbl_ExternalList) 675 { 676 NextExternal = AcpiGbl_ExternalList->Next; 677 ACPI_FREE (AcpiGbl_ExternalList->Path); 678 ACPI_FREE (AcpiGbl_ExternalList); 679 AcpiGbl_ExternalList = NextExternal; 680 } 681 } 682 683 684 /******************************************************************************* 685 * 686 * FUNCTION: AcpiDmEmitExternals 687 * 688 * PARAMETERS: None 689 * 690 * RETURN: None 691 * 692 * DESCRIPTION: Emit an External() ASL statement for each of the externals in 693 * the global external info list. 694 * 695 ******************************************************************************/ 696 697 void 698 AcpiDmEmitExternals ( 699 void) 700 { 701 ACPI_EXTERNAL_LIST *NextExternal; 702 703 704 if (!AcpiGbl_ExternalList) 705 { 706 return; 707 } 708 709 /* 710 * Walk the list of externals (unresolved references) 711 * found during the AML parsing 712 */ 713 while (AcpiGbl_ExternalList) 714 { 715 AcpiOsPrintf (" External (%s%s", 716 AcpiGbl_ExternalList->Path, 717 AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type)); 718 719 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) 720 { 721 AcpiOsPrintf (") // %u Arguments\n", 722 AcpiGbl_ExternalList->Value); 723 } 724 else 725 { 726 AcpiOsPrintf (")\n"); 727 } 728 729 /* Free this external info block and move on to next external */ 730 731 NextExternal = AcpiGbl_ExternalList->Next; 732 if (AcpiGbl_ExternalList->Flags & ACPI_IPATH_ALLOCATED) 733 { 734 ACPI_FREE (AcpiGbl_ExternalList->InternalPath); 735 } 736 737 ACPI_FREE (AcpiGbl_ExternalList->Path); 738 ACPI_FREE (AcpiGbl_ExternalList); 739 AcpiGbl_ExternalList = NextExternal; 740 } 741 742 AcpiOsPrintf ("\n"); 743 } 744 745