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 - 2009, 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 = AcpiNsGetParentNode (Node); 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 Fullpath = ACPI_ALLOCATE_ZEROED (Length); 274 if (!Fullpath) 275 { 276 goto Cleanup; 277 } 278 279 /* 280 * Concatenate parent fullpath and path. For example, 281 * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT" 282 * 283 * Copy the parent path 284 */ 285 ACPI_STRCAT (Fullpath, ParentPath); 286 287 /* Add dot separator (don't need dot if parent fullpath is a single "\") */ 288 289 if (ParentPath[1]) 290 { 291 ACPI_STRCAT (Fullpath, "."); 292 } 293 294 /* Copy child path (carat parent prefix(es) were skipped above) */ 295 296 ACPI_STRCAT (Fullpath, Path); 297 298 Cleanup: 299 ACPI_FREE (ParentPath); 300 return (Fullpath); 301 } 302 303 304 /******************************************************************************* 305 * 306 * FUNCTION: AcpiDmAddToExternalList 307 * 308 * PARAMETERS: Op - Current parser Op 309 * Path - Internal (AML) path to the object 310 * Type - ACPI object type to be added 311 * Value - Arg count if adding a Method object 312 * 313 * RETURN: None 314 * 315 * DESCRIPTION: Insert a new name into the global list of Externals which 316 * will in turn be later emitted as an External() declaration 317 * in the disassembled output. 318 * 319 ******************************************************************************/ 320 321 void 322 AcpiDmAddToExternalList ( 323 ACPI_PARSE_OBJECT *Op, 324 char *Path, 325 UINT8 Type, 326 UINT32 Value) 327 { 328 char *ExternalPath; 329 char *Fullpath = NULL; 330 ACPI_EXTERNAL_LIST *NewExternal; 331 ACPI_EXTERNAL_LIST *NextExternal; 332 ACPI_EXTERNAL_LIST *PrevExternal = NULL; 333 ACPI_STATUS Status; 334 335 336 if (!Path) 337 { 338 return; 339 } 340 341 /* Externalize the ACPI path */ 342 343 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path, 344 NULL, &ExternalPath); 345 if (ACPI_FAILURE (Status)) 346 { 347 return; 348 } 349 350 /* Get the full pathname from root if "Path" has a parent prefix */ 351 352 if (*Path == (UINT8) AML_PARENT_PREFIX) 353 { 354 Fullpath = AcpiDmNormalizeParentPrefix (Op, ExternalPath); 355 if (Fullpath) 356 { 357 /* Set new external path */ 358 359 ACPI_FREE (ExternalPath); 360 ExternalPath = Fullpath; 361 } 362 } 363 364 /* Check all existing externals to ensure no duplicates */ 365 366 NextExternal = AcpiGbl_ExternalList; 367 while (NextExternal) 368 { 369 if (!ACPI_STRCMP (ExternalPath, NextExternal->Path)) 370 { 371 /* Duplicate method, check that the Value (ArgCount) is the same */ 372 373 if ((NextExternal->Type == ACPI_TYPE_METHOD) && 374 (NextExternal->Value != Value)) 375 { 376 ACPI_ERROR ((AE_INFO, 377 "Argument count mismatch for method %s %d %d", 378 NextExternal->Path, NextExternal->Value, Value)); 379 } 380 381 /* Allow upgrade of type from ANY */ 382 383 else if (NextExternal->Type == ACPI_TYPE_ANY) 384 { 385 NextExternal->Type = Type; 386 NextExternal->Value = Value; 387 } 388 389 ACPI_FREE (ExternalPath); 390 return; 391 } 392 393 NextExternal = NextExternal->Next; 394 } 395 396 /* Allocate and init a new External() descriptor */ 397 398 NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST)); 399 if (!NewExternal) 400 { 401 ACPI_FREE (ExternalPath); 402 return; 403 } 404 405 NewExternal->Path = ExternalPath; 406 NewExternal->Type = Type; 407 NewExternal->Value = Value; 408 NewExternal->Length = (UINT16) ACPI_STRLEN (ExternalPath); 409 410 /* Was the external path with parent prefix normalized to a fullpath? */ 411 412 if (Fullpath == ExternalPath) 413 { 414 /* Get new internal path */ 415 416 Status = AcpiNsInternalizeName (ExternalPath, &Path); 417 if (ACPI_FAILURE (Status)) 418 { 419 ACPI_FREE (ExternalPath); 420 ACPI_FREE (NewExternal); 421 return; 422 } 423 424 /* Set flag to indicate External->InternalPath need to be freed */ 425 426 NewExternal->Flags |= ACPI_IPATH_ALLOCATED; 427 } 428 429 NewExternal->InternalPath = Path; 430 431 /* Link the new descriptor into the global list, ordered by string length */ 432 433 NextExternal = AcpiGbl_ExternalList; 434 while (NextExternal) 435 { 436 if (NewExternal->Length <= NextExternal->Length) 437 { 438 if (PrevExternal) 439 { 440 PrevExternal->Next = NewExternal; 441 } 442 else 443 { 444 AcpiGbl_ExternalList = NewExternal; 445 } 446 447 NewExternal->Next = NextExternal; 448 return; 449 } 450 451 PrevExternal = NextExternal; 452 NextExternal = NextExternal->Next; 453 } 454 455 if (PrevExternal) 456 { 457 PrevExternal->Next = NewExternal; 458 } 459 else 460 { 461 AcpiGbl_ExternalList = NewExternal; 462 } 463 } 464 465 466 /******************************************************************************* 467 * 468 * FUNCTION: AcpiDmAddExternalsToNamespace 469 * 470 * PARAMETERS: None 471 * 472 * RETURN: None 473 * 474 * DESCRIPTION: Add all externals to the namespace. Allows externals to be 475 * "resolved". 476 * 477 ******************************************************************************/ 478 479 void 480 AcpiDmAddExternalsToNamespace ( 481 void) 482 { 483 ACPI_STATUS Status; 484 ACPI_NAMESPACE_NODE *Node; 485 ACPI_OPERAND_OBJECT *MethodDesc; 486 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList; 487 488 489 while (External) 490 { 491 /* Add the external name (object) into the namespace */ 492 493 Status = AcpiNsLookup (NULL, External->InternalPath, External->Type, 494 ACPI_IMODE_LOAD_PASS1, 495 ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE, 496 NULL, &Node); 497 498 if (ACPI_FAILURE (Status)) 499 { 500 ACPI_EXCEPTION ((AE_INFO, Status, 501 "while adding external to namespace [%s]", 502 External->Path)); 503 } 504 else if (External->Type == ACPI_TYPE_METHOD) 505 { 506 /* For methods, we need to save the argument count */ 507 508 MethodDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD); 509 MethodDesc->Method.ParamCount = (UINT8) External->Value; 510 Node->Object = MethodDesc; 511 } 512 513 External = External->Next; 514 } 515 } 516 517 518 /******************************************************************************* 519 * 520 * FUNCTION: AcpiDmGetExternalMethodCount 521 * 522 * PARAMETERS: None 523 * 524 * RETURN: The number of control method externals in the external list 525 * 526 * DESCRIPTION: Return the number of method externals that have been generated. 527 * If any control method externals have been found, we must 528 * re-parse the entire definition block with the new information 529 * (number of arguments for the methods.) This is limitation of 530 * AML, we don't know the number of arguments from the control 531 * method invocation itself. 532 * 533 ******************************************************************************/ 534 535 UINT32 536 AcpiDmGetExternalMethodCount ( 537 void) 538 { 539 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList; 540 UINT32 Count = 0; 541 542 543 while (External) 544 { 545 if (External->Type == ACPI_TYPE_METHOD) 546 { 547 Count++; 548 } 549 550 External = External->Next; 551 } 552 553 return (Count); 554 } 555 556 557 /******************************************************************************* 558 * 559 * FUNCTION: AcpiDmClearExternalList 560 * 561 * PARAMETERS: None 562 * 563 * RETURN: None 564 * 565 * DESCRIPTION: Free the entire External info list 566 * 567 ******************************************************************************/ 568 569 void 570 AcpiDmClearExternalList ( 571 void) 572 { 573 ACPI_EXTERNAL_LIST *NextExternal; 574 575 576 while (AcpiGbl_ExternalList) 577 { 578 NextExternal = AcpiGbl_ExternalList->Next; 579 ACPI_FREE (AcpiGbl_ExternalList->Path); 580 ACPI_FREE (AcpiGbl_ExternalList); 581 AcpiGbl_ExternalList = NextExternal; 582 } 583 } 584 585 586 /******************************************************************************* 587 * 588 * FUNCTION: AcpiDmEmitExternals 589 * 590 * PARAMETERS: None 591 * 592 * RETURN: None 593 * 594 * DESCRIPTION: Emit an External() ASL statement for each of the externals in 595 * the global external info list. 596 * 597 ******************************************************************************/ 598 599 void 600 AcpiDmEmitExternals ( 601 void) 602 { 603 ACPI_EXTERNAL_LIST *NextExternal; 604 605 606 if (!AcpiGbl_ExternalList) 607 { 608 return; 609 } 610 611 /* 612 * Walk the list of externals (unresolved references) 613 * found during the AML parsing 614 */ 615 while (AcpiGbl_ExternalList) 616 { 617 AcpiOsPrintf (" External (%s%s", 618 AcpiGbl_ExternalList->Path, 619 AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type)); 620 621 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) 622 { 623 AcpiOsPrintf (") // %d Arguments\n", 624 AcpiGbl_ExternalList->Value); 625 } 626 else 627 { 628 AcpiOsPrintf (")\n"); 629 } 630 631 /* Free this external info block and move on to next external */ 632 633 NextExternal = AcpiGbl_ExternalList->Next; 634 if (AcpiGbl_ExternalList->Flags & ACPI_IPATH_ALLOCATED) 635 { 636 ACPI_FREE (AcpiGbl_ExternalList->InternalPath); 637 } 638 639 ACPI_FREE (AcpiGbl_ExternalList->Path); 640 ACPI_FREE (AcpiGbl_ExternalList); 641 AcpiGbl_ExternalList = NextExternal; 642 } 643 644 AcpiOsPrintf ("\n"); 645 } 646 647