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 - 2012, 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 "acpi.h" 117#include "accommon.h" 118#include "amlcode.h" 119#include "acnamesp.h" 120#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 */ 137static 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 164static const char * 165AcpiDmGetObjectTypeName ( 166 ACPI_OBJECT_TYPE Type); 167 168static char * 169AcpiDmNormalizeParentPrefix ( 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 186static const char * 187AcpiDmGetObjectTypeName ( 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 219static char * 220AcpiDmNormalizeParentPrefix ( 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 /* 297 * Add dot separator 298 * (don't need dot if parent fullpath is a single backslash) 299 */ 300 if (ParentPath[1]) 301 { 302 ACPI_STRCAT (Fullpath, "."); 303 } 304 305 /* Copy child path (carat parent prefix(es) were skipped above) */ 306 307 ACPI_STRCAT (Fullpath, Path); 308 309Cleanup: 310 ACPI_FREE (ParentPath); 311 return (Fullpath); 312} 313 314 315/******************************************************************************* 316 * 317 * FUNCTION: AcpiDmAddToExternalFileList 318 * 319 * PARAMETERS: PathList - Single path or list separated by comma 320 * 321 * RETURN: None 322 * 323 * DESCRIPTION: Add external files to global list 324 * 325 ******************************************************************************/ 326 327ACPI_STATUS 328AcpiDmAddToExternalFileList ( 329 char *PathList) 330{ 331 ACPI_EXTERNAL_FILE *ExternalFile; 332 char *Path; 333 char *TmpPath; 334 335 336 if (!PathList) 337 { 338 return (AE_OK); 339 } 340 341 Path = strtok (PathList, ","); 342 343 while (Path) 344 { 345 TmpPath = ACPI_ALLOCATE_ZEROED (ACPI_STRLEN (Path) + 1); 346 if (!TmpPath) 347 { 348 return (AE_NO_MEMORY); 349 } 350 351 ACPI_STRCPY (TmpPath, Path); 352 353 ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE)); 354 if (!ExternalFile) 355 { 356 ACPI_FREE (TmpPath); 357 return (AE_NO_MEMORY); 358 } 359 360 ExternalFile->Path = TmpPath; 361 362 if (AcpiGbl_ExternalFileList) 363 { 364 ExternalFile->Next = AcpiGbl_ExternalFileList; 365 } 366 367 AcpiGbl_ExternalFileList = ExternalFile; 368 Path = strtok (NULL, ","); 369 } 370 371 return (AE_OK); 372} 373 374 375/******************************************************************************* 376 * 377 * FUNCTION: AcpiDmClearExternalFileList 378 * 379 * PARAMETERS: None 380 * 381 * RETURN: None 382 * 383 * DESCRIPTION: Clear the external file list 384 * 385 ******************************************************************************/ 386 387void 388AcpiDmClearExternalFileList ( 389 void) 390{ 391 ACPI_EXTERNAL_FILE *NextExternal; 392 393 394 while (AcpiGbl_ExternalFileList) 395 { 396 NextExternal = AcpiGbl_ExternalFileList->Next; 397 ACPI_FREE (AcpiGbl_ExternalFileList->Path); 398 ACPI_FREE (AcpiGbl_ExternalFileList); 399 AcpiGbl_ExternalFileList = NextExternal; 400 } 401} 402 403 404/******************************************************************************* 405 * 406 * FUNCTION: AcpiDmAddToExternalList 407 * 408 * PARAMETERS: Op - Current parser Op 409 * Path - Internal (AML) path to the object 410 * Type - ACPI object type to be added 411 * Value - Arg count if adding a Method object 412 * 413 * RETURN: None 414 * 415 * DESCRIPTION: Insert a new name into the global list of Externals which 416 * will in turn be later emitted as an External() declaration 417 * in the disassembled output. 418 * 419 ******************************************************************************/ 420 421void 422AcpiDmAddToExternalList ( 423 ACPI_PARSE_OBJECT *Op, 424 char *Path, 425 UINT8 Type, 426 UINT32 Value) 427{ 428 char *ExternalPath; 429 char *Fullpath = NULL; 430 ACPI_EXTERNAL_LIST *NewExternal; 431 ACPI_EXTERNAL_LIST *NextExternal; 432 ACPI_EXTERNAL_LIST *PrevExternal = NULL; 433 ACPI_STATUS Status; 434 435 436 if (!Path) 437 { 438 return; 439 } 440 441 /* Externalize the ACPI path */ 442 443 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path, 444 NULL, &ExternalPath); 445 if (ACPI_FAILURE (Status)) 446 { 447 return; 448 } 449 450 /* Get the full pathname from root if "Path" has a parent prefix */ 451 452 if (*Path == (UINT8) AML_PARENT_PREFIX) 453 { 454 Fullpath = AcpiDmNormalizeParentPrefix (Op, ExternalPath); 455 if (Fullpath) 456 { 457 /* Set new external path */ 458 459 ACPI_FREE (ExternalPath); 460 ExternalPath = Fullpath; 461 } 462 } 463 464 /* Check all existing externals to ensure no duplicates */ 465 466 NextExternal = AcpiGbl_ExternalList; 467 while (NextExternal) 468 { 469 if (!ACPI_STRCMP (ExternalPath, NextExternal->Path)) 470 { 471 /* Duplicate method, check that the Value (ArgCount) is the same */ 472 473 if ((NextExternal->Type == ACPI_TYPE_METHOD) && 474 (NextExternal->Value != Value)) 475 { 476 ACPI_ERROR ((AE_INFO, 477 "Argument count mismatch for method %s %u %u", 478 NextExternal->Path, NextExternal->Value, Value)); 479 } 480 481 /* Allow upgrade of type from ANY */ 482 483 else if (NextExternal->Type == ACPI_TYPE_ANY) 484 { 485 NextExternal->Type = Type; 486 NextExternal->Value = Value; 487 } 488 489 ACPI_FREE (ExternalPath); 490 return; 491 } 492 493 NextExternal = NextExternal->Next; 494 } 495 496 /* Allocate and init a new External() descriptor */ 497 498 NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST)); 499 if (!NewExternal) 500 { 501 ACPI_FREE (ExternalPath); 502 return; 503 } 504 505 NewExternal->Path = ExternalPath; 506 NewExternal->Type = Type; 507 NewExternal->Value = Value; 508 NewExternal->Length = (UINT16) ACPI_STRLEN (ExternalPath); 509 510 /* Was the external path with parent prefix normalized to a fullpath? */ 511 512 if (Fullpath == ExternalPath) 513 { 514 /* Get new internal path */ 515 516 Status = AcpiNsInternalizeName (ExternalPath, &Path); 517 if (ACPI_FAILURE (Status)) 518 { 519 ACPI_FREE (ExternalPath); 520 ACPI_FREE (NewExternal); 521 return; 522 } 523 524 /* Set flag to indicate External->InternalPath need to be freed */ 525 526 NewExternal->Flags |= ACPI_IPATH_ALLOCATED; 527 } 528 529 NewExternal->InternalPath = Path; 530 531 /* Link the new descriptor into the global list, alphabetically ordered */ 532 533 NextExternal = AcpiGbl_ExternalList; 534 while (NextExternal) 535 { 536 if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0) 537 { 538 if (PrevExternal) 539 { 540 PrevExternal->Next = NewExternal; 541 } 542 else 543 { 544 AcpiGbl_ExternalList = NewExternal; 545 } 546 547 NewExternal->Next = NextExternal; 548 return; 549 } 550 551 PrevExternal = NextExternal; 552 NextExternal = NextExternal->Next; 553 } 554 555 if (PrevExternal) 556 { 557 PrevExternal->Next = NewExternal; 558 } 559 else 560 { 561 AcpiGbl_ExternalList = NewExternal; 562 } 563} 564 565 566/******************************************************************************* 567 * 568 * FUNCTION: AcpiDmAddExternalsToNamespace 569 * 570 * PARAMETERS: None 571 * 572 * RETURN: None 573 * 574 * DESCRIPTION: Add all externals to the namespace. Allows externals to be 575 * "resolved". 576 * 577 ******************************************************************************/ 578 579void 580AcpiDmAddExternalsToNamespace ( 581 void) 582{ 583 ACPI_STATUS Status; 584 ACPI_NAMESPACE_NODE *Node; 585 ACPI_OPERAND_OBJECT *ObjDesc; 586 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList; 587 588 589 while (External) 590 { 591 /* Add the external name (object) into the namespace */ 592 593 Status = AcpiNsLookup (NULL, External->InternalPath, External->Type, 594 ACPI_IMODE_LOAD_PASS1, 595 ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE, 596 NULL, &Node); 597 598 if (ACPI_FAILURE (Status)) 599 { 600 ACPI_EXCEPTION ((AE_INFO, Status, 601 "while adding external to namespace [%s]", 602 External->Path)); 603 } 604 605 else switch (External->Type) 606 { 607 case ACPI_TYPE_METHOD: 608 609 /* For methods, we need to save the argument count */ 610 611 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD); 612 ObjDesc->Method.ParamCount = (UINT8) External->Value; 613 Node->Object = ObjDesc; 614 break; 615 616 case ACPI_TYPE_REGION: 617 618 /* Regions require a region sub-object */ 619 620 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION); 621 ObjDesc->Region.Node = Node; 622 Node->Object = ObjDesc; 623 break; 624 625 default: 626 break; 627 } 628 629 External = External->Next; 630 } 631} 632 633 634/******************************************************************************* 635 * 636 * FUNCTION: AcpiDmGetExternalMethodCount 637 * 638 * PARAMETERS: None 639 * 640 * RETURN: The number of control method externals in the external list 641 * 642 * DESCRIPTION: Return the number of method externals that have been generated. 643 * If any control method externals have been found, we must 644 * re-parse the entire definition block with the new information 645 * (number of arguments for the methods.) This is limitation of 646 * AML, we don't know the number of arguments from the control 647 * method invocation itself. 648 * 649 ******************************************************************************/ 650 651UINT32 652AcpiDmGetExternalMethodCount ( 653 void) 654{ 655 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList; 656 UINT32 Count = 0; 657 658 659 while (External) 660 { 661 if (External->Type == ACPI_TYPE_METHOD) 662 { 663 Count++; 664 } 665 666 External = External->Next; 667 } 668 669 return (Count); 670} 671 672 673/******************************************************************************* 674 * 675 * FUNCTION: AcpiDmClearExternalList 676 * 677 * PARAMETERS: None 678 * 679 * RETURN: None 680 * 681 * DESCRIPTION: Free the entire External info list 682 * 683 ******************************************************************************/ 684 685void 686AcpiDmClearExternalList ( 687 void) 688{ 689 ACPI_EXTERNAL_LIST *NextExternal; 690 691 692 while (AcpiGbl_ExternalList) 693 { 694 NextExternal = AcpiGbl_ExternalList->Next; 695 ACPI_FREE (AcpiGbl_ExternalList->Path); 696 ACPI_FREE (AcpiGbl_ExternalList); 697 AcpiGbl_ExternalList = NextExternal; 698 } 699} 700 701 702/******************************************************************************* 703 * 704 * FUNCTION: AcpiDmEmitExternals 705 * 706 * PARAMETERS: None 707 * 708 * RETURN: None 709 * 710 * DESCRIPTION: Emit an External() ASL statement for each of the externals in 711 * the global external info list. 712 * 713 ******************************************************************************/ 714 715void 716AcpiDmEmitExternals ( 717 void) 718{ 719 ACPI_EXTERNAL_LIST *NextExternal; 720 721 722 if (!AcpiGbl_ExternalList) 723 { 724 return; 725 } 726 727 /* 728 * Walk the list of externals (unresolved references) 729 * found during the AML parsing 730 */ 731 while (AcpiGbl_ExternalList) 732 { 733 AcpiOsPrintf (" External (%s%s", 734 AcpiGbl_ExternalList->Path, 735 AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type)); 736 737 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) 738 { 739 AcpiOsPrintf (") // %u Arguments\n", 740 AcpiGbl_ExternalList->Value); 741 } 742 else 743 { 744 AcpiOsPrintf (")\n"); 745 } 746 747 /* Free this external info block and move on to next external */ 748 749 NextExternal = AcpiGbl_ExternalList->Next; 750 if (AcpiGbl_ExternalList->Flags & ACPI_IPATH_ALLOCATED) 751 { 752 ACPI_FREE (AcpiGbl_ExternalList->InternalPath); 753 } 754 755 ACPI_FREE (AcpiGbl_ExternalList->Path); 756 ACPI_FREE (AcpiGbl_ExternalList); 757 AcpiGbl_ExternalList = NextExternal; 758 } 759 760 AcpiOsPrintf ("\n"); 761} 762