1 /******************************************************************************
3 * Module Name: dmextern - Support for External() ASL statements
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2011, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
44 #include <contrib/dev/acpica/include/acpi.h>
45 #include <contrib/dev/acpica/include/accommon.h>
46 #include <contrib/dev/acpica/include/amlcode.h>
47 #include <contrib/dev/acpica/include/acnamesp.h>
48 #include <contrib/dev/acpica/include/acdisasm.h>
52 * This module is used for application-level code (iASL disassembler) only.
54 * It contains the code to create and emit any necessary External() ASL
55 * statements for the module being disassembled.
57 #define _COMPONENT ACPI_CA_DISASSEMBLER
58 ACPI_MODULE_NAME ("dmextern")
62 * This table maps ACPI_OBJECT_TYPEs to the corresponding ASL
63 * ObjectTypeKeyword. Used to generate typed external declarations
65 static const char *AcpiGbl_DmTypeNames[] =
67 /* 00 */ "", /* Type ANY */
72 /* 05 */ ", FieldUnitObj",
73 /* 06 */ ", DeviceObj",
74 /* 07 */ ", EventObj",
75 /* 08 */ ", MethodObj",
76 /* 09 */ ", MutexObj",
77 /* 10 */ ", OpRegionObj",
78 /* 11 */ ", PowerResObj",
79 /* 12 */ ", ProcessorObj",
80 /* 13 */ ", ThermalZoneObj",
81 /* 14 */ ", BuffFieldObj",
82 /* 15 */ ", DDBHandleObj",
83 /* 16 */ "", /* Debug object */
84 /* 17 */ ", FieldUnitObj",
85 /* 18 */ ", FieldUnitObj",
86 /* 19 */ ", FieldUnitObj"
90 /* Local prototypes */
93 AcpiDmGetObjectTypeName (
94 ACPI_OBJECT_TYPE Type);
97 AcpiDmNormalizeParentPrefix (
98 ACPI_PARSE_OBJECT *Op,
102 /*******************************************************************************
104 * FUNCTION: AcpiDmGetObjectTypeName
106 * PARAMETERS: Type - An ACPI_OBJECT_TYPE
108 * RETURN: Pointer to a string
110 * DESCRIPTION: Map an object type to the ASL object type string.
112 ******************************************************************************/
115 AcpiDmGetObjectTypeName (
116 ACPI_OBJECT_TYPE Type)
119 if (Type == ACPI_TYPE_LOCAL_SCOPE)
121 Type = ACPI_TYPE_DEVICE;
124 else if (Type > ACPI_TYPE_LOCAL_INDEX_FIELD)
129 return (AcpiGbl_DmTypeNames[Type]);
133 /*******************************************************************************
135 * FUNCTION: AcpiDmNormalizeParentPrefix
137 * PARAMETERS: Op - Parse op
138 * Path - Path with parent prefix
140 * RETURN: The full pathname to the object (from the namespace root)
142 * DESCRIPTION: Returns the full pathname of a path with parent prefix
143 * The caller must free the fullpath returned.
145 ******************************************************************************/
148 AcpiDmNormalizeParentPrefix (
149 ACPI_PARSE_OBJECT *Op,
152 ACPI_NAMESPACE_NODE *Node;
158 /* Search upwards in the parse tree until we reach a namespace node */
167 Op = Op->Common.Parent;
176 * Find the actual parent node for the reference:
177 * Remove all carat prefixes from the input path.
178 * There may be multiple parent prefixes (For example, ^^^M000)
180 Node = Op->Common.Node;
181 while (Node && (*Path == (UINT8) AML_PARENT_PREFIX))
192 /* Get the full pathname for the parent node */
194 ParentPath = AcpiNsGetExternalPathname (Node);
200 Length = (ACPI_STRLEN (ParentPath) + ACPI_STRLEN (Path) + 1);
204 * If ParentPath is not just a simple '\', increment the length
205 * for the required dot separator (ParentPath.Path)
210 Fullpath = ACPI_ALLOCATE_ZEROED (Length);
217 * Concatenate parent fullpath and path. For example,
218 * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT"
220 * Copy the parent path
222 ACPI_STRCAT (Fullpath, ParentPath);
224 /* Add dot separator (don't need dot if parent fullpath is a single "\") */
228 ACPI_STRCAT (Fullpath, ".");
231 /* Copy child path (carat parent prefix(es) were skipped above) */
233 ACPI_STRCAT (Fullpath, Path);
236 ACPI_FREE (ParentPath);
241 /*******************************************************************************
243 * FUNCTION: AcpiDmAddToExternalFileList
245 * PARAMETERS: PathList - Single path or list separated by comma
249 * DESCRIPTION: Add external files to global list
251 ******************************************************************************/
254 AcpiDmAddToExternalFileList (
257 ACPI_EXTERNAL_FILE *ExternalFile;
267 Path = strtok (PathList, ",");
271 TmpPath = ACPI_ALLOCATE_ZEROED (ACPI_STRLEN (Path) + 1);
274 return (AE_NO_MEMORY);
277 ACPI_STRCPY (TmpPath, Path);
279 ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE));
283 return (AE_NO_MEMORY);
286 ExternalFile->Path = TmpPath;
288 if (AcpiGbl_ExternalFileList)
290 ExternalFile->Next = AcpiGbl_ExternalFileList;
293 AcpiGbl_ExternalFileList = ExternalFile;
294 Path = strtok (NULL, ",");
301 /*******************************************************************************
303 * FUNCTION: AcpiDmClearExternalFileList
309 * DESCRIPTION: Clear the external file list
311 ******************************************************************************/
314 AcpiDmClearExternalFileList (
317 ACPI_EXTERNAL_FILE *NextExternal;
320 while (AcpiGbl_ExternalFileList)
322 NextExternal = AcpiGbl_ExternalFileList->Next;
323 ACPI_FREE (AcpiGbl_ExternalFileList->Path);
324 ACPI_FREE (AcpiGbl_ExternalFileList);
325 AcpiGbl_ExternalFileList = NextExternal;
330 /*******************************************************************************
332 * FUNCTION: AcpiDmAddToExternalList
334 * PARAMETERS: Op - Current parser Op
335 * Path - Internal (AML) path to the object
336 * Type - ACPI object type to be added
337 * Value - Arg count if adding a Method object
341 * DESCRIPTION: Insert a new name into the global list of Externals which
342 * will in turn be later emitted as an External() declaration
343 * in the disassembled output.
345 ******************************************************************************/
348 AcpiDmAddToExternalList (
349 ACPI_PARSE_OBJECT *Op,
355 char *Fullpath = NULL;
356 ACPI_EXTERNAL_LIST *NewExternal;
357 ACPI_EXTERNAL_LIST *NextExternal;
358 ACPI_EXTERNAL_LIST *PrevExternal = NULL;
367 /* Externalize the ACPI path */
369 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path,
370 NULL, &ExternalPath);
371 if (ACPI_FAILURE (Status))
376 /* Get the full pathname from root if "Path" has a parent prefix */
378 if (*Path == (UINT8) AML_PARENT_PREFIX)
380 Fullpath = AcpiDmNormalizeParentPrefix (Op, ExternalPath);
383 /* Set new external path */
385 ACPI_FREE (ExternalPath);
386 ExternalPath = Fullpath;
390 /* Check all existing externals to ensure no duplicates */
392 NextExternal = AcpiGbl_ExternalList;
395 if (!ACPI_STRCMP (ExternalPath, NextExternal->Path))
397 /* Duplicate method, check that the Value (ArgCount) is the same */
399 if ((NextExternal->Type == ACPI_TYPE_METHOD) &&
400 (NextExternal->Value != Value))
402 ACPI_ERROR ((AE_INFO,
403 "Argument count mismatch for method %s %u %u",
404 NextExternal->Path, NextExternal->Value, Value));
407 /* Allow upgrade of type from ANY */
409 else if (NextExternal->Type == ACPI_TYPE_ANY)
411 NextExternal->Type = Type;
412 NextExternal->Value = Value;
415 ACPI_FREE (ExternalPath);
419 NextExternal = NextExternal->Next;
422 /* Allocate and init a new External() descriptor */
424 NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
427 ACPI_FREE (ExternalPath);
431 NewExternal->Path = ExternalPath;
432 NewExternal->Type = Type;
433 NewExternal->Value = Value;
434 NewExternal->Length = (UINT16) ACPI_STRLEN (ExternalPath);
436 /* Was the external path with parent prefix normalized to a fullpath? */
438 if (Fullpath == ExternalPath)
440 /* Get new internal path */
442 Status = AcpiNsInternalizeName (ExternalPath, &Path);
443 if (ACPI_FAILURE (Status))
445 ACPI_FREE (ExternalPath);
446 ACPI_FREE (NewExternal);
450 /* Set flag to indicate External->InternalPath need to be freed */
452 NewExternal->Flags |= ACPI_IPATH_ALLOCATED;
455 NewExternal->InternalPath = Path;
457 /* Link the new descriptor into the global list, ordered by string length */
459 NextExternal = AcpiGbl_ExternalList;
462 if (NewExternal->Length <= NextExternal->Length)
466 PrevExternal->Next = NewExternal;
470 AcpiGbl_ExternalList = NewExternal;
473 NewExternal->Next = NextExternal;
477 PrevExternal = NextExternal;
478 NextExternal = NextExternal->Next;
483 PrevExternal->Next = NewExternal;
487 AcpiGbl_ExternalList = NewExternal;
492 /*******************************************************************************
494 * FUNCTION: AcpiDmAddExternalsToNamespace
500 * DESCRIPTION: Add all externals to the namespace. Allows externals to be
503 ******************************************************************************/
506 AcpiDmAddExternalsToNamespace (
510 ACPI_NAMESPACE_NODE *Node;
511 ACPI_OPERAND_OBJECT *MethodDesc;
512 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList;
517 /* Add the external name (object) into the namespace */
519 Status = AcpiNsLookup (NULL, External->InternalPath, External->Type,
520 ACPI_IMODE_LOAD_PASS1,
521 ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE,
524 if (ACPI_FAILURE (Status))
526 ACPI_EXCEPTION ((AE_INFO, Status,
527 "while adding external to namespace [%s]",
530 else if (External->Type == ACPI_TYPE_METHOD)
532 /* For methods, we need to save the argument count */
534 MethodDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
535 MethodDesc->Method.ParamCount = (UINT8) External->Value;
536 Node->Object = MethodDesc;
539 External = External->Next;
544 /*******************************************************************************
546 * FUNCTION: AcpiDmGetExternalMethodCount
550 * RETURN: The number of control method externals in the external list
552 * DESCRIPTION: Return the number of method externals that have been generated.
553 * If any control method externals have been found, we must
554 * re-parse the entire definition block with the new information
555 * (number of arguments for the methods.) This is limitation of
556 * AML, we don't know the number of arguments from the control
557 * method invocation itself.
559 ******************************************************************************/
562 AcpiDmGetExternalMethodCount (
565 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList;
571 if (External->Type == ACPI_TYPE_METHOD)
576 External = External->Next;
583 /*******************************************************************************
585 * FUNCTION: AcpiDmClearExternalList
591 * DESCRIPTION: Free the entire External info list
593 ******************************************************************************/
596 AcpiDmClearExternalList (
599 ACPI_EXTERNAL_LIST *NextExternal;
602 while (AcpiGbl_ExternalList)
604 NextExternal = AcpiGbl_ExternalList->Next;
605 ACPI_FREE (AcpiGbl_ExternalList->Path);
606 ACPI_FREE (AcpiGbl_ExternalList);
607 AcpiGbl_ExternalList = NextExternal;
612 /*******************************************************************************
614 * FUNCTION: AcpiDmEmitExternals
620 * DESCRIPTION: Emit an External() ASL statement for each of the externals in
621 * the global external info list.
623 ******************************************************************************/
626 AcpiDmEmitExternals (
629 ACPI_EXTERNAL_LIST *NextExternal;
632 if (!AcpiGbl_ExternalList)
638 * Walk the list of externals (unresolved references)
639 * found during the AML parsing
641 while (AcpiGbl_ExternalList)
643 AcpiOsPrintf (" External (%s%s",
644 AcpiGbl_ExternalList->Path,
645 AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type));
647 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
649 AcpiOsPrintf (") // %u Arguments\n",
650 AcpiGbl_ExternalList->Value);
654 AcpiOsPrintf (")\n");
657 /* Free this external info block and move on to next external */
659 NextExternal = AcpiGbl_ExternalList->Next;
660 if (AcpiGbl_ExternalList->Flags & ACPI_IPATH_ALLOCATED)
662 ACPI_FREE (AcpiGbl_ExternalList->InternalPath);
665 ACPI_FREE (AcpiGbl_ExternalList->Path);
666 ACPI_FREE (AcpiGbl_ExternalList);
667 AcpiGbl_ExternalList = NextExternal;