xref: /freebsd/sys/contrib/dev/acpica/common/dmextern.c (revision 6e660824a82f590542932de52f128db584029893)
1 /******************************************************************************
2  *
3  * Module Name: dmextern - Support for External() ASL statements
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2013, 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 <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>
49 #include <stdio.h>
50 
51 
52 /*
53  * This module is used for application-level code (iASL disassembler) only.
54  *
55  * It contains the code to create and emit any necessary External() ASL
56  * statements for the module being disassembled.
57  */
58 #define _COMPONENT          ACPI_CA_DISASSEMBLER
59         ACPI_MODULE_NAME    ("dmextern")
60 
61 
62 /*
63  * This table maps ACPI_OBJECT_TYPEs to the corresponding ASL
64  * ObjectTypeKeyword. Used to generate typed external declarations
65  */
66 static const char           *AcpiGbl_DmTypeNames[] =
67 {
68     /* 00 */ "",                    /* Type ANY */
69     /* 01 */ ", IntObj",
70     /* 02 */ ", StrObj",
71     /* 03 */ ", BuffObj",
72     /* 04 */ ", PkgObj",
73     /* 05 */ ", FieldUnitObj",
74     /* 06 */ ", DeviceObj",
75     /* 07 */ ", EventObj",
76     /* 08 */ ", MethodObj",
77     /* 09 */ ", MutexObj",
78     /* 10 */ ", OpRegionObj",
79     /* 11 */ ", PowerResObj",
80     /* 12 */ ", ProcessorObj",
81     /* 13 */ ", ThermalZoneObj",
82     /* 14 */ ", BuffFieldObj",
83     /* 15 */ ", DDBHandleObj",
84     /* 16 */ "",                    /* Debug object */
85     /* 17 */ ", FieldUnitObj",
86     /* 18 */ ", FieldUnitObj",
87     /* 19 */ ", FieldUnitObj"
88 };
89 
90 
91 /* Local prototypes */
92 
93 static const char *
94 AcpiDmGetObjectTypeName (
95     ACPI_OBJECT_TYPE        Type);
96 
97 static char *
98 AcpiDmNormalizeParentPrefix (
99     ACPI_PARSE_OBJECT       *Op,
100     char                    *Path);
101 
102 
103 /*******************************************************************************
104  *
105  * FUNCTION:    AcpiDmGetObjectTypeName
106  *
107  * PARAMETERS:  Type                - An ACPI_OBJECT_TYPE
108  *
109  * RETURN:      Pointer to a string
110  *
111  * DESCRIPTION: Map an object type to the ASL object type string.
112  *
113  ******************************************************************************/
114 
115 static const char *
116 AcpiDmGetObjectTypeName (
117     ACPI_OBJECT_TYPE        Type)
118 {
119 
120     if (Type == ACPI_TYPE_LOCAL_SCOPE)
121     {
122         Type = ACPI_TYPE_DEVICE;
123     }
124 
125     else if (Type > ACPI_TYPE_LOCAL_INDEX_FIELD)
126     {
127         return ("");
128     }
129 
130     return (AcpiGbl_DmTypeNames[Type]);
131 }
132 
133 
134 /*******************************************************************************
135  *
136  * FUNCTION:    AcpiDmNormalizeParentPrefix
137  *
138  * PARAMETERS:  Op                  - Parse op
139  *              Path                - Path with parent prefix
140  *
141  * RETURN:      The full pathname to the object (from the namespace root)
142  *
143  * DESCRIPTION: Returns the full pathname of a path with parent prefix
144  *              The caller must free the fullpath returned.
145  *
146  ******************************************************************************/
147 
148 static char *
149 AcpiDmNormalizeParentPrefix (
150     ACPI_PARSE_OBJECT       *Op,
151     char                    *Path)
152 {
153     ACPI_NAMESPACE_NODE     *Node;
154     char                    *Fullpath;
155     char                    *ParentPath;
156     ACPI_SIZE               Length;
157     UINT32                  Index = 0;
158 
159 
160     if (!Op)
161     {
162         return (NULL);
163     }
164 
165     /* Search upwards in the parse tree until we reach the next namespace node */
166 
167     Op = Op->Common.Parent;
168     while (Op)
169     {
170         if (Op->Common.Node)
171         {
172             break;
173         }
174 
175         Op = Op->Common.Parent;
176     }
177 
178     if (!Op)
179     {
180         return (NULL);
181     }
182 
183     /*
184      * Find the actual parent node for the reference:
185      * Remove all carat prefixes from the input path.
186      * There may be multiple parent prefixes (For example, ^^^M000)
187      */
188     Node = Op->Common.Node;
189     while (Node && (*Path == (UINT8) AML_PARENT_PREFIX))
190     {
191         Node = Node->Parent;
192         Path++;
193     }
194 
195     if (!Node)
196     {
197         return (NULL);
198     }
199 
200     /* Get the full pathname for the parent node */
201 
202     ParentPath = AcpiNsGetExternalPathname (Node);
203     if (!ParentPath)
204     {
205         return (NULL);
206     }
207 
208     Length = (ACPI_STRLEN (ParentPath) + ACPI_STRLEN (Path) + 1);
209     if (ParentPath[1])
210     {
211         /*
212          * If ParentPath is not just a simple '\', increment the length
213          * for the required dot separator (ParentPath.Path)
214          */
215         Length++;
216 
217         /* For External() statements, we do not want a leading '\' */
218 
219         if (*ParentPath == AML_ROOT_PREFIX)
220         {
221             Index = 1;
222         }
223     }
224 
225     Fullpath = ACPI_ALLOCATE_ZEROED (Length);
226     if (!Fullpath)
227     {
228         goto Cleanup;
229     }
230 
231     /*
232      * Concatenate parent fullpath and path. For example,
233      * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT"
234      *
235      * Copy the parent path
236      */
237     ACPI_STRCPY (Fullpath, &ParentPath[Index]);
238 
239     /*
240      * Add dot separator
241      * (don't need dot if parent fullpath is a single backslash)
242      */
243     if (ParentPath[1])
244     {
245         ACPI_STRCAT (Fullpath, ".");
246     }
247 
248     /* Copy child path (carat parent prefix(es) were skipped above) */
249 
250     ACPI_STRCAT (Fullpath, Path);
251 
252 Cleanup:
253     ACPI_FREE (ParentPath);
254     return (Fullpath);
255 }
256 
257 
258 /*******************************************************************************
259  *
260  * FUNCTION:    AcpiDmAddToExternalFileList
261  *
262  * PARAMETERS:  PathList            - Single path or list separated by comma
263  *
264  * RETURN:      None
265  *
266  * DESCRIPTION: Add external files to global list
267  *
268  ******************************************************************************/
269 
270 ACPI_STATUS
271 AcpiDmAddToExternalFileList (
272     char                    *PathList)
273 {
274     ACPI_EXTERNAL_FILE      *ExternalFile;
275     char                    *Path;
276     char                    *TmpPath;
277 
278 
279     if (!PathList)
280     {
281         return (AE_OK);
282     }
283 
284     Path = strtok (PathList, ",");
285 
286     while (Path)
287     {
288         TmpPath = ACPI_ALLOCATE_ZEROED (ACPI_STRLEN (Path) + 1);
289         if (!TmpPath)
290         {
291             return (AE_NO_MEMORY);
292         }
293 
294         ACPI_STRCPY (TmpPath, Path);
295 
296         ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE));
297         if (!ExternalFile)
298         {
299             ACPI_FREE (TmpPath);
300             return (AE_NO_MEMORY);
301         }
302 
303         ExternalFile->Path = TmpPath;
304 
305         if (AcpiGbl_ExternalFileList)
306         {
307             ExternalFile->Next = AcpiGbl_ExternalFileList;
308         }
309 
310         AcpiGbl_ExternalFileList = ExternalFile;
311         Path = strtok (NULL, ",");
312     }
313 
314     return (AE_OK);
315 }
316 
317 
318 /*******************************************************************************
319  *
320  * FUNCTION:    AcpiDmClearExternalFileList
321  *
322  * PARAMETERS:  None
323  *
324  * RETURN:      None
325  *
326  * DESCRIPTION: Clear the external file list
327  *
328  ******************************************************************************/
329 
330 void
331 AcpiDmClearExternalFileList (
332     void)
333 {
334     ACPI_EXTERNAL_FILE      *NextExternal;
335 
336 
337     while (AcpiGbl_ExternalFileList)
338     {
339         NextExternal = AcpiGbl_ExternalFileList->Next;
340         ACPI_FREE (AcpiGbl_ExternalFileList->Path);
341         ACPI_FREE (AcpiGbl_ExternalFileList);
342         AcpiGbl_ExternalFileList = NextExternal;
343     }
344 }
345 
346 
347 /*******************************************************************************
348  *
349  * FUNCTION:    AcpiDmAddToExternalList
350  *
351  * PARAMETERS:  Op                  - Current parser Op
352  *              Path                - Internal (AML) path to the object
353  *              Type                - ACPI object type to be added
354  *              Value               - Arg count if adding a Method object
355  *
356  * RETURN:      None
357  *
358  * DESCRIPTION: Insert a new name into the global list of Externals which
359  *              will in turn be later emitted as an External() declaration
360  *              in the disassembled output.
361  *
362  ******************************************************************************/
363 
364 void
365 AcpiDmAddToExternalList (
366     ACPI_PARSE_OBJECT       *Op,
367     char                    *Path,
368     UINT8                   Type,
369     UINT32                  Value)
370 {
371     char                    *ExternalPath;
372     char                    *Fullpath = NULL;
373     ACPI_EXTERNAL_LIST      *NewExternal;
374     ACPI_EXTERNAL_LIST      *NextExternal;
375     ACPI_EXTERNAL_LIST      *PrevExternal = NULL;
376     ACPI_STATUS             Status;
377     BOOLEAN                 Resolved = FALSE;
378 
379 
380     if (!Path)
381     {
382         return;
383     }
384 
385     if (Type == ACPI_TYPE_METHOD)
386     {
387         if (Value & 0x80)
388         {
389             Resolved = TRUE;
390         }
391         Value &= 0x07;
392     }
393 
394     /*
395      * We don't want External() statements to contain a leading '\'.
396      * This prevents duplicate external statements of the form:
397      *
398      *    External (\ABCD)
399      *    External (ABCD)
400      *
401      * This would cause a compile time error when the disassembled
402      * output file is recompiled.
403      */
404     if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
405     {
406         Path++;
407     }
408 
409     /* Externalize the ACPI pathname */
410 
411     Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path,
412                 NULL, &ExternalPath);
413     if (ACPI_FAILURE (Status))
414     {
415         return;
416     }
417 
418     /*
419      * Get the full pathname from the root if "Path" has one or more
420      * parent prefixes (^). Note: path will not contain a leading '\'.
421      */
422     if (*Path == (UINT8) AML_PARENT_PREFIX)
423     {
424         Fullpath = AcpiDmNormalizeParentPrefix (Op, ExternalPath);
425         if (Fullpath)
426         {
427             /* Set new external path */
428 
429             ACPI_FREE (ExternalPath);
430             ExternalPath = Fullpath;
431         }
432     }
433 
434     /* Check all existing externals to ensure no duplicates */
435 
436     NextExternal = AcpiGbl_ExternalList;
437     while (NextExternal)
438     {
439         if (!ACPI_STRCMP (ExternalPath, NextExternal->Path))
440         {
441             /* Duplicate method, check that the Value (ArgCount) is the same */
442 
443             if ((NextExternal->Type == ACPI_TYPE_METHOD) &&
444                 (NextExternal->Value != Value))
445             {
446                 ACPI_ERROR ((AE_INFO,
447                     "Argument count mismatch for method %s %u %u",
448                     NextExternal->Path, NextExternal->Value, Value));
449             }
450 
451             /* Allow upgrade of type from ANY */
452 
453             else if (NextExternal->Type == ACPI_TYPE_ANY)
454             {
455                 NextExternal->Type = Type;
456                 NextExternal->Value = Value;
457             }
458 
459             ACPI_FREE (ExternalPath);
460             return;
461         }
462 
463         NextExternal = NextExternal->Next;
464     }
465 
466     /* Allocate and init a new External() descriptor */
467 
468     NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
469     if (!NewExternal)
470     {
471         ACPI_FREE (ExternalPath);
472         return;
473     }
474 
475     NewExternal->Path = ExternalPath;
476     NewExternal->Type = Type;
477     NewExternal->Value = Value;
478     NewExternal->Resolved = Resolved;
479     NewExternal->Length = (UINT16) ACPI_STRLEN (ExternalPath);
480 
481     /* Was the external path with parent prefix normalized to a fullpath? */
482 
483     if (Fullpath == ExternalPath)
484     {
485         /* Get new internal path */
486 
487         Status = AcpiNsInternalizeName (ExternalPath, &Path);
488         if (ACPI_FAILURE (Status))
489         {
490             ACPI_FREE (ExternalPath);
491             ACPI_FREE (NewExternal);
492             return;
493         }
494 
495         /* Set flag to indicate External->InternalPath need to be freed */
496 
497         NewExternal->Flags |= ACPI_IPATH_ALLOCATED;
498     }
499 
500     NewExternal->InternalPath = Path;
501 
502     /* Link the new descriptor into the global list, alphabetically ordered */
503 
504     NextExternal = AcpiGbl_ExternalList;
505     while (NextExternal)
506     {
507         if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0)
508         {
509             if (PrevExternal)
510             {
511                 PrevExternal->Next = NewExternal;
512             }
513             else
514             {
515                 AcpiGbl_ExternalList = NewExternal;
516             }
517 
518             NewExternal->Next = NextExternal;
519             return;
520         }
521 
522         PrevExternal = NextExternal;
523         NextExternal = NextExternal->Next;
524     }
525 
526     if (PrevExternal)
527     {
528         PrevExternal->Next = NewExternal;
529     }
530     else
531     {
532         AcpiGbl_ExternalList = NewExternal;
533     }
534 }
535 
536 
537 /*******************************************************************************
538  *
539  * FUNCTION:    AcpiDmAddExternalsToNamespace
540  *
541  * PARAMETERS:  None
542  *
543  * RETURN:      None
544  *
545  * DESCRIPTION: Add all externals to the namespace. Allows externals to be
546  *              "resolved".
547  *
548  ******************************************************************************/
549 
550 void
551 AcpiDmAddExternalsToNamespace (
552     void)
553 {
554     ACPI_STATUS             Status;
555     ACPI_NAMESPACE_NODE     *Node;
556     ACPI_OPERAND_OBJECT     *ObjDesc;
557     ACPI_EXTERNAL_LIST      *External = AcpiGbl_ExternalList;
558 
559 
560     while (External)
561     {
562         /* Add the external name (object) into the namespace */
563 
564         Status = AcpiNsLookup (NULL, External->InternalPath, External->Type,
565                    ACPI_IMODE_LOAD_PASS1,
566                    ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE,
567                    NULL, &Node);
568 
569         if (ACPI_FAILURE (Status))
570         {
571             ACPI_EXCEPTION ((AE_INFO, Status,
572                 "while adding external to namespace [%s]",
573                 External->Path));
574         }
575 
576         else switch (External->Type)
577         {
578         case ACPI_TYPE_METHOD:
579 
580             /* For methods, we need to save the argument count */
581 
582             ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
583             ObjDesc->Method.ParamCount = (UINT8) External->Value;
584             Node->Object = ObjDesc;
585             break;
586 
587         case ACPI_TYPE_REGION:
588 
589             /* Regions require a region sub-object */
590 
591             ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION);
592             ObjDesc->Region.Node = Node;
593             Node->Object = ObjDesc;
594             break;
595 
596         default:
597 
598             break;
599         }
600 
601         External = External->Next;
602     }
603 }
604 
605 
606 /*******************************************************************************
607  *
608  * FUNCTION:    AcpiDmGetExternalMethodCount
609  *
610  * PARAMETERS:  None
611  *
612  * RETURN:      The number of control method externals in the external list
613  *
614  * DESCRIPTION: Return the number of method externals that have been generated.
615  *              If any control method externals have been found, we must
616  *              re-parse the entire definition block with the new information
617  *              (number of arguments for the methods.) This is limitation of
618  *              AML, we don't know the number of arguments from the control
619  *              method invocation itself.
620  *
621  ******************************************************************************/
622 
623 UINT32
624 AcpiDmGetExternalMethodCount (
625     void)
626 {
627     ACPI_EXTERNAL_LIST      *External = AcpiGbl_ExternalList;
628     UINT32                  Count = 0;
629 
630 
631     while (External)
632     {
633         if (External->Type == ACPI_TYPE_METHOD)
634         {
635             Count++;
636         }
637 
638         External = External->Next;
639     }
640 
641     return (Count);
642 }
643 
644 
645 /*******************************************************************************
646  *
647  * FUNCTION:    AcpiDmClearExternalList
648  *
649  * PARAMETERS:  None
650  *
651  * RETURN:      None
652  *
653  * DESCRIPTION: Free the entire External info list
654  *
655  ******************************************************************************/
656 
657 void
658 AcpiDmClearExternalList (
659     void)
660 {
661     ACPI_EXTERNAL_LIST      *NextExternal;
662 
663 
664     while (AcpiGbl_ExternalList)
665     {
666         NextExternal = AcpiGbl_ExternalList->Next;
667         ACPI_FREE (AcpiGbl_ExternalList->Path);
668         ACPI_FREE (AcpiGbl_ExternalList);
669         AcpiGbl_ExternalList = NextExternal;
670     }
671 }
672 
673 
674 /*******************************************************************************
675  *
676  * FUNCTION:    AcpiDmEmitExternals
677  *
678  * PARAMETERS:  None
679  *
680  * RETURN:      None
681  *
682  * DESCRIPTION: Emit an External() ASL statement for each of the externals in
683  *              the global external info list.
684  *
685  ******************************************************************************/
686 
687 void
688 AcpiDmEmitExternals (
689     void)
690 {
691     ACPI_EXTERNAL_LIST      *NextExternal;
692 
693 
694     if (!AcpiGbl_ExternalList)
695     {
696         return;
697     }
698 
699     /*
700      * Determine the number of control methods in the external list, and
701      * also how many of those externals were resolved via the namespace.
702      */
703     NextExternal = AcpiGbl_ExternalList;
704     while (NextExternal)
705     {
706         if (NextExternal->Type == ACPI_TYPE_METHOD)
707         {
708             AcpiGbl_NumExternalMethods++;
709             if (NextExternal->Resolved)
710             {
711                 AcpiGbl_ResolvedExternalMethods++;
712             }
713         }
714 
715         NextExternal = NextExternal->Next;
716     }
717 
718     /* Check if any control methods were unresolved */
719 
720     AcpiDmUnresolvedWarning (1);
721 
722     /* Emit any unresolved method externals in a single text block */
723 
724     NextExternal = AcpiGbl_ExternalList;
725     while (NextExternal)
726     {
727         if ((NextExternal->Type == ACPI_TYPE_METHOD) &&
728             (!NextExternal->Resolved))
729         {
730             AcpiOsPrintf ("    External (%s%s",
731                 NextExternal->Path,
732                 AcpiDmGetObjectTypeName (NextExternal->Type));
733 
734             AcpiOsPrintf (")    // Warning: Unresolved Method, "
735                 "guessing %u arguments (may be incorrect, see warning above)\n",
736                 NextExternal->Value);
737 
738             NextExternal->Emitted = TRUE;
739         }
740 
741         NextExternal = NextExternal->Next;
742     }
743 
744     AcpiOsPrintf ("\n");
745 
746     /*
747      * Walk the list of externals (unresolved references)
748      * found during the AML parsing
749      */
750     while (AcpiGbl_ExternalList)
751     {
752         if (!AcpiGbl_ExternalList->Emitted)
753         {
754             AcpiOsPrintf ("    External (%s%s",
755                 AcpiGbl_ExternalList->Path,
756                 AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type));
757 
758             /* For methods, add a comment with the number of arguments */
759 
760             if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
761             {
762                 AcpiOsPrintf (")    // %u Arguments\n",
763                     AcpiGbl_ExternalList->Value);
764             }
765             else
766             {
767                 AcpiOsPrintf (")\n");
768             }
769         }
770 
771         /* Free this external info block and move on to next external */
772 
773         NextExternal = AcpiGbl_ExternalList->Next;
774         if (AcpiGbl_ExternalList->Flags & ACPI_IPATH_ALLOCATED)
775         {
776             ACPI_FREE (AcpiGbl_ExternalList->InternalPath);
777         }
778 
779         ACPI_FREE (AcpiGbl_ExternalList->Path);
780         ACPI_FREE (AcpiGbl_ExternalList);
781         AcpiGbl_ExternalList = NextExternal;
782     }
783 
784     AcpiOsPrintf ("\n");
785 }
786 
787 
788 /*******************************************************************************
789  *
790  * FUNCTION:    AcpiDmUnresolvedWarning
791  *
792  * PARAMETERS:  Type                - Where to output the warning.
793  *                                    0 means write to stderr
794  *                                    1 means write to AcpiOsPrintf
795  *
796  * RETURN:      None
797  *
798  * DESCRIPTION: Issue warning message if there are unresolved external control
799  *              methods within the disassembly.
800  *
801  ******************************************************************************/
802 
803 #if 0
804 Summary of the external control method problem:
805 
806 When the -e option is used with disassembly, the various SSDTs are simply
807 loaded into a global namespace for the disassembler to use in order to
808 resolve control method references (invocations).
809 
810 The disassembler tracks any such references, and will emit an External()
811 statement for these types of methods, with the proper number of arguments .
812 
813 Without the SSDTs, the AML does not contain enough information to properly
814 disassemble the control method invocation -- because the disassembler does
815 not know how many arguments to parse.
816 
817 An example: Assume we have two control methods. ABCD has one argument, and
818 EFGH has zero arguments. Further, we have two additional control methods
819 that invoke ABCD and EFGH, named T1 and T2:
820 
821     Method (ABCD, 1)
822     {
823     }
824     Method (EFGH, 0)
825     {
826     }
827     Method (T1)
828     {
829         ABCD (Add (2, 7, Local0))
830     }
831     Method (T2)
832     {
833         EFGH ()
834         Add (2, 7, Local0)
835     }
836 
837 Here is the AML code that is generated for T1 and T2:
838 
839      185:      Method (T1)
840 
841 0000034C:  14 10 54 31 5F 5F 00 ...    "..T1__."
842 
843      186:      {
844      187:          ABCD (Add (2, 7, Local0))
845 
846 00000353:  41 42 43 44 ............    "ABCD"
847 00000357:  72 0A 02 0A 07 60 ......    "r....`"
848 
849      188:      }
850 
851      190:      Method (T2)
852 
853 0000035D:  14 10 54 32 5F 5F 00 ...    "..T2__."
854 
855      191:      {
856      192:          EFGH ()
857 
858 00000364:  45 46 47 48 ............    "EFGH"
859 
860      193:          Add (2, 7, Local0)
861 
862 00000368:  72 0A 02 0A 07 60 ......    "r....`"
863      194:      }
864 
865 Note that the AML code for T1 and T2 is essentially identical. When
866 disassembling this code, the methods ABCD and EFGH must be known to the
867 disassembler, otherwise it does not know how to handle the method invocations.
868 
869 In other words, if ABCD and EFGH are actually external control methods
870 appearing in an SSDT, the disassembler does not know what to do unless
871 the owning SSDT has been loaded via the -e option.
872 #endif
873 
874 void
875 AcpiDmUnresolvedWarning (
876     UINT8                   Type)
877 {
878 
879     if (!AcpiGbl_NumExternalMethods)
880     {
881         return;
882     }
883 
884     if (Type)
885     {
886         if (!AcpiGbl_ExternalFileList)
887         {
888             /* The -e option was not specified */
889 
890            AcpiOsPrintf ("    /*\n"
891                 "     * iASL Warning: There were %u external control methods found during\n"
892                 "     * disassembly, but additional ACPI tables to resolve these externals\n"
893                 "     * were not specified. This resulting disassembler output file may not\n"
894                 "     * compile because the disassembler did not know how many arguments\n"
895                 "     * to assign to these methods. To specify the tables needed to resolve\n"
896                 "     * external control method references, use the one of the following\n"
897                 "     * example iASL invocations:\n"
898                 "     *     iasl -e <ssdt1.aml,ssdt2.aml...> -d <dsdt.aml>\n"
899                 "     *     iasl -e <dsdt.aml,ssdt2.aml...> -d <ssdt1.aml>\n"
900                 "     */\n",
901                 AcpiGbl_NumExternalMethods);
902         }
903         else if (AcpiGbl_NumExternalMethods != AcpiGbl_ResolvedExternalMethods)
904         {
905             /* The -e option was specified, but there are still some unresolved externals */
906 
907             AcpiOsPrintf ("    /*\n"
908                 "     * iASL Warning: There were %u external control methods found during\n"
909                 "     * disassembly, but only %u %s resolved (%u unresolved). Additional\n"
910                 "     * ACPI tables are required to properly disassemble the code. This\n"
911                 "     * resulting disassembler output file may not compile because the\n"
912                 "     * disassembler did not know how many arguments to assign to the\n"
913                 "     * unresolved methods.\n"
914                 "     */\n",
915                 AcpiGbl_NumExternalMethods, AcpiGbl_ResolvedExternalMethods,
916                 (AcpiGbl_ResolvedExternalMethods > 1 ? "were" : "was"),
917                 (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods));
918         }
919     }
920     else
921     {
922         if (!AcpiGbl_ExternalFileList)
923         {
924             /* The -e option was not specified */
925 
926             fprintf (stderr, "\n"
927                 "iASL Warning: There were %u external control methods found during\n"
928                 "disassembly, but additional ACPI tables to resolve these externals\n"
929                 "were not specified. The resulting disassembler output file may not\n"
930                 "compile because the disassembler did not know how many arguments\n"
931                 "to assign to these methods. To specify the tables needed to resolve\n"
932                 "external control method references, use the one of the following\n"
933                 "example iASL invocations:\n"
934                 "    iasl -e <ssdt1.aml,ssdt2.aml...> -d <dsdt.aml>\n"
935                 "    iasl -e <dsdt.aml,ssdt2.aml...> -d <ssdt1.aml>\n",
936                 AcpiGbl_NumExternalMethods);
937         }
938         else if (AcpiGbl_NumExternalMethods != AcpiGbl_ResolvedExternalMethods)
939         {
940             /* The -e option was specified, but there are still some unresolved externals */
941 
942             fprintf (stderr, "\n"
943                 "iASL Warning: There were %u external control methods found during\n"
944                 "disassembly, but only %u %s resolved (%u unresolved). Additional\n"
945                 "ACPI tables are required to properly disassemble the code. The\n"
946                 "resulting disassembler output file may not compile because the\n"
947                 "disassembler did not know how many arguments to assign to the\n"
948                 "unresolved methods.\n",
949                 AcpiGbl_NumExternalMethods, AcpiGbl_ResolvedExternalMethods,
950                 (AcpiGbl_ResolvedExternalMethods > 1 ? "were" : "was"),
951                 (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods));
952         }
953     }
954 }
955