1 /******************************************************************************
2 *
3 * Module Name: dmextern - Support for External() ASL statements
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2023, 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 MERCHANTABILITY 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 "acpi.h"
45 #include "accommon.h"
46 #include "amlcode.h"
47 #include "acnamesp.h"
48 #include "acdisasm.h"
49 #include "aslcompiler.h"
50 #include <stdio.h>
51 #include <errno.h>
52
53
54 /*
55 * This module is used for application-level code (iASL disassembler) only.
56 *
57 * It contains the code to create and emit any necessary External() ASL
58 * statements for the module being disassembled.
59 */
60 #define _COMPONENT ACPI_CA_DISASSEMBLER
61 ACPI_MODULE_NAME ("dmextern")
62
63
64 /*
65 * This table maps ACPI_OBJECT_TYPEs to the corresponding ASL
66 * ObjectTypeKeyword. Used to generate typed external declarations
67 */
68 static const char *AcpiGbl_DmTypeNames[] =
69 {
70 /* 00 */ ", UnknownObj", /* Type ANY */
71 /* 01 */ ", IntObj",
72 /* 02 */ ", StrObj",
73 /* 03 */ ", BuffObj",
74 /* 04 */ ", PkgObj",
75 /* 05 */ ", FieldUnitObj",
76 /* 06 */ ", DeviceObj",
77 /* 07 */ ", EventObj",
78 /* 08 */ ", MethodObj",
79 /* 09 */ ", MutexObj",
80 /* 10 */ ", OpRegionObj",
81 /* 11 */ ", PowerResObj",
82 /* 12 */ ", ProcessorObj",
83 /* 13 */ ", ThermalZoneObj",
84 /* 14 */ ", BuffFieldObj",
85 /* 15 */ ", DDBHandleObj",
86 /* 16 */ "", /* Debug object */
87 /* 17 */ ", FieldUnitObj",
88 /* 18 */ ", FieldUnitObj",
89 /* 19 */ ", FieldUnitObj"
90 };
91
92 #define METHOD_SEPARATORS " \t,()\n"
93
94 static const char *ExternalConflictMessage =
95 " // Conflicts with a later declaration";
96
97
98 /* Local prototypes */
99
100 static const char *
101 AcpiDmGetObjectTypeName (
102 ACPI_OBJECT_TYPE Type);
103
104 static char *
105 AcpiDmNormalizeParentPrefix (
106 ACPI_PARSE_OBJECT *Op,
107 char *Path);
108
109 static ACPI_STATUS
110 AcpiDmGetExternalAndInternalPath (
111 ACPI_NAMESPACE_NODE *Node,
112 char **ExternalPath,
113 char **InternalPath);
114
115 static ACPI_STATUS
116 AcpiDmRemoveRootPrefix (
117 char **Path);
118
119 static void
120 AcpiDmAddPathToExternalList (
121 char *Path,
122 UINT8 Type,
123 UINT32 Value,
124 UINT16 Flags);
125
126 static ACPI_STATUS
127 AcpiDmCreateNewExternal (
128 char *ExternalPath,
129 char *InternalPath,
130 UINT8 Type,
131 UINT32 Value,
132 UINT16 Flags);
133
134 static void
135 AcpiDmCheckForExternalConflict (
136 char *Path);
137
138 static ACPI_STATUS
139 AcpiDmResolveExternal (
140 char *Path,
141 UINT8 Type,
142 ACPI_NAMESPACE_NODE **Node);
143
144
145 static void
146 AcpiDmConflictingDeclaration (
147 char *Path);
148
149
150 /*******************************************************************************
151 *
152 * FUNCTION: AcpiDmGetObjectTypeName
153 *
154 * PARAMETERS: Type - An ACPI_OBJECT_TYPE
155 *
156 * RETURN: Pointer to a string
157 *
158 * DESCRIPTION: Map an object type to the ASL object type string.
159 *
160 ******************************************************************************/
161
162 static const char *
AcpiDmGetObjectTypeName(ACPI_OBJECT_TYPE Type)163 AcpiDmGetObjectTypeName (
164 ACPI_OBJECT_TYPE Type)
165 {
166
167 if (Type == ACPI_TYPE_LOCAL_SCOPE)
168 {
169 Type = ACPI_TYPE_DEVICE;
170 }
171 else if (Type > ACPI_TYPE_LOCAL_INDEX_FIELD)
172 {
173 return ("");
174 }
175
176 return (AcpiGbl_DmTypeNames[Type]);
177 }
178
179
180 /*******************************************************************************
181 *
182 * FUNCTION: AcpiDmNormalizeParentPrefix
183 *
184 * PARAMETERS: Op - Parse op
185 * Path - Path with parent prefix
186 *
187 * RETURN: The full pathname to the object (from the namespace root)
188 *
189 * DESCRIPTION: Returns the full pathname of a path with parent prefix
190 * The caller must free the fullpath returned.
191 *
192 ******************************************************************************/
193
194 static char *
AcpiDmNormalizeParentPrefix(ACPI_PARSE_OBJECT * Op,char * Path)195 AcpiDmNormalizeParentPrefix (
196 ACPI_PARSE_OBJECT *Op,
197 char *Path)
198 {
199 ACPI_NAMESPACE_NODE *Node;
200 char *Fullpath;
201 char *ParentPath;
202 ACPI_SIZE Length;
203 UINT32 Index = 0;
204
205
206 if (!Op)
207 {
208 return (NULL);
209 }
210
211 /* Search upwards in the parse tree until we reach the next namespace node */
212
213 Op = Op->Common.Parent;
214 while (Op)
215 {
216 if (Op->Common.Node)
217 {
218 break;
219 }
220
221 Op = Op->Common.Parent;
222 }
223
224 if (!Op)
225 {
226 return (NULL);
227 }
228
229 /*
230 * Find the actual parent node for the reference:
231 * Remove all carat prefixes from the input path.
232 * There may be multiple parent prefixes (For example, ^^^M000)
233 */
234 Node = Op->Common.Node;
235 while (Node && (*Path == (UINT8) AML_PARENT_PREFIX))
236 {
237 Node = Node->Parent;
238 Path++;
239 }
240
241 if (!Node)
242 {
243 return (NULL);
244 }
245
246 /* Get the full pathname for the parent node */
247
248 ParentPath = AcpiNsGetExternalPathname (Node);
249 if (!ParentPath)
250 {
251 return (NULL);
252 }
253
254 Length = (strlen (ParentPath) + strlen (Path) + 1);
255 if (ParentPath[1])
256 {
257 /*
258 * If ParentPath is not just a simple '\', increment the length
259 * for the required dot separator (ParentPath.Path)
260 */
261 Length++;
262
263 /* For External() statements, we do not want a leading '\' */
264
265 if (*ParentPath == AML_ROOT_PREFIX)
266 {
267 Index = 1;
268 }
269 }
270
271 Fullpath = ACPI_ALLOCATE_ZEROED (Length);
272 if (!Fullpath)
273 {
274 goto Cleanup;
275 }
276
277 /*
278 * Concatenate parent fullpath and path. For example,
279 * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT"
280 *
281 * Copy the parent path
282 */
283 strcpy (Fullpath, &ParentPath[Index]);
284
285 /*
286 * Add dot separator
287 * (don't need dot if parent fullpath is a single backslash)
288 */
289 if (ParentPath[1])
290 {
291 strcat (Fullpath, ".");
292 }
293
294 /* Copy child path (carat parent prefix(es) were skipped above) */
295
296 strcat (Fullpath, Path);
297
298 Cleanup:
299 ACPI_FREE (ParentPath);
300 return (Fullpath);
301 }
302
303
304 /*******************************************************************************
305 *
306 * FUNCTION: AcpiDmAddToExternalFileList
307 *
308 * PARAMETERS: PathList - Single path or list separated by comma
309 *
310 * RETURN: None
311 *
312 * DESCRIPTION: Add external files to global list
313 *
314 ******************************************************************************/
315
316 ACPI_STATUS
AcpiDmAddToExternalFileList(char * Pathname)317 AcpiDmAddToExternalFileList (
318 char *Pathname)
319 {
320 ACPI_EXTERNAL_FILE *ExternalFile;
321 char *LocalPathname;
322
323
324 if (!Pathname)
325 {
326 return (AE_OK);
327 }
328
329 LocalPathname = ACPI_ALLOCATE (strlen (Pathname) + 1);
330 if (!LocalPathname)
331 {
332 return (AE_NO_MEMORY);
333 }
334
335 ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE));
336 if (!ExternalFile)
337 {
338 ACPI_FREE (LocalPathname);
339 return (AE_NO_MEMORY);
340 }
341
342 /* Take a copy of the file pathname */
343
344 strcpy (LocalPathname, Pathname);
345 ExternalFile->Path = LocalPathname;
346
347 if (AcpiGbl_ExternalFileList)
348 {
349 ExternalFile->Next = AcpiGbl_ExternalFileList;
350 }
351
352 AcpiGbl_ExternalFileList = ExternalFile;
353 return (AE_OK);
354 }
355
356
357 /*******************************************************************************
358 *
359 * FUNCTION: AcpiDmClearExternalFileList
360 *
361 * PARAMETERS: None
362 *
363 * RETURN: None
364 *
365 * DESCRIPTION: Clear the external file list
366 *
367 ******************************************************************************/
368
369 void
AcpiDmClearExternalFileList(void)370 AcpiDmClearExternalFileList (
371 void)
372 {
373 ACPI_EXTERNAL_FILE *NextExternal;
374
375
376 while (AcpiGbl_ExternalFileList)
377 {
378 NextExternal = AcpiGbl_ExternalFileList->Next;
379 ACPI_FREE (AcpiGbl_ExternalFileList->Path);
380 ACPI_FREE (AcpiGbl_ExternalFileList);
381 AcpiGbl_ExternalFileList = NextExternal;
382 }
383 }
384
385
386 /*******************************************************************************
387 *
388 * FUNCTION: AcpiDmGetExternalsFromFile
389 *
390 * PARAMETERS: None
391 *
392 * RETURN: None
393 *
394 * DESCRIPTION: Process the optional external reference file.
395 *
396 * Each line in the file should be of the form:
397 * External (<Method namepath>, MethodObj, <ArgCount>)
398 *
399 * Example:
400 * External (_SB_.PCI0.XHC_.PS0X, MethodObj, 4)
401 *
402 ******************************************************************************/
403
404 void
AcpiDmGetExternalsFromFile(void)405 AcpiDmGetExternalsFromFile (
406 void)
407 {
408 FILE *ExternalRefFile;
409 char *Token;
410 char *MethodName;
411 UINT32 ArgCount;
412 UINT32 ImportCount = 0;
413
414
415 if (!AslGbl_ExternalRefFilename)
416 {
417 return;
418 }
419
420 /* Open the file */
421
422 ExternalRefFile = fopen (AslGbl_ExternalRefFilename, "r");
423 if (!ExternalRefFile)
424 {
425 fprintf (stderr, "Could not open external reference file \"%s\"\n",
426 AslGbl_ExternalRefFilename);
427 AslAbort ();
428 return;
429 }
430
431 /* Each line defines a method */
432
433 while (fgets (AslGbl_StringBuffer, ASL_STRING_BUFFER_SIZE, ExternalRefFile))
434 {
435 Token = strtok (AslGbl_StringBuffer, METHOD_SEPARATORS); /* "External" */
436 if (!Token)
437 {
438 continue;
439 }
440
441 if (strcmp (Token, "External"))
442 {
443 continue;
444 }
445
446 MethodName = strtok (NULL, METHOD_SEPARATORS); /* Method namepath */
447 if (!MethodName)
448 {
449 continue;
450 }
451
452 Token = strtok (NULL, METHOD_SEPARATORS); /* "MethodObj" */
453 if (!Token)
454 {
455 continue;
456 }
457
458 if (strcmp (Token, "MethodObj"))
459 {
460 continue;
461 }
462
463 Token = strtok (NULL, METHOD_SEPARATORS); /* Arg count */
464 if (!Token)
465 {
466 continue;
467 }
468
469 /* Convert arg count string to an integer */
470
471 errno = 0;
472 ArgCount = strtoul (Token, NULL, 0);
473 if (errno)
474 {
475 fprintf (stderr, "Invalid argument count (%s)\n", Token);
476 continue;
477 }
478
479 if (ArgCount > 7)
480 {
481 fprintf (stderr, "Invalid argument count (%u)\n", ArgCount);
482 continue;
483 }
484
485 /* Add this external to the global list */
486
487 AcpiOsPrintf ("%s: Importing method external (%u arguments) %s\n",
488 AslGbl_ExternalRefFilename, ArgCount, MethodName);
489
490 AcpiDmAddPathToExternalList (MethodName, ACPI_TYPE_METHOD,
491 ArgCount, (ACPI_EXT_RESOLVED_REFERENCE | ACPI_EXT_ORIGIN_FROM_FILE));
492 ImportCount++;
493 }
494
495 if (!ImportCount)
496 {
497 fprintf (stderr,
498 "Did not find any external methods in reference file \"%s\"\n",
499 AslGbl_ExternalRefFilename);
500 }
501 else
502 {
503 /* Add the external(s) to the namespace */
504
505 AcpiDmAddExternalListToNamespace ();
506
507 AcpiOsPrintf ("%s: Imported %u external method definitions\n",
508 AslGbl_ExternalRefFilename, ImportCount);
509 }
510
511 fclose (ExternalRefFile);
512 }
513
514
515 /*******************************************************************************
516 *
517 * FUNCTION: AcpiDmAddOpToExternalList
518 *
519 * PARAMETERS: Op - Current parser Op
520 * Path - Internal (AML) path to the object
521 * Type - ACPI object type to be added
522 * Value - Arg count if adding a Method object
523 * Flags - To be passed to the external object
524 *
525 * RETURN: None
526 *
527 * DESCRIPTION: Insert a new name into the global list of Externals which
528 * will in turn be later emitted as an External() declaration
529 * in the disassembled output.
530 *
531 * This function handles the most common case where the referenced
532 * name is simply not found in the constructed namespace.
533 *
534 ******************************************************************************/
535
536 void
AcpiDmAddOpToExternalList(ACPI_PARSE_OBJECT * Op,char * Path,UINT8 Type,UINT32 Value,UINT16 Flags)537 AcpiDmAddOpToExternalList (
538 ACPI_PARSE_OBJECT *Op,
539 char *Path,
540 UINT8 Type,
541 UINT32 Value,
542 UINT16 Flags)
543 {
544 char *ExternalPath;
545 char *InternalPath = Path;
546 char *Temp;
547 ACPI_STATUS Status;
548
549
550 ACPI_FUNCTION_TRACE (DmAddOpToExternalList);
551
552
553 if (!Path)
554 {
555 return_VOID;
556 }
557
558 /* Remove a root backslash if present */
559
560 if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
561 {
562 Path++;
563 }
564
565 /* Externalize the pathname */
566
567 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path,
568 NULL, &ExternalPath);
569 if (ACPI_FAILURE (Status))
570 {
571 return_VOID;
572 }
573
574 /*
575 * Get the full pathname from the root if "Path" has one or more
576 * parent prefixes (^). Note: path will not contain a leading '\'.
577 */
578 if (*Path == (UINT8) AML_PARENT_PREFIX)
579 {
580 Temp = AcpiDmNormalizeParentPrefix (Op, ExternalPath);
581
582 /* Set new external path */
583
584 ACPI_FREE (ExternalPath);
585 ExternalPath = Temp;
586 if (!Temp)
587 {
588 return_VOID;
589 }
590
591 /* Create the new internal pathname */
592
593 Flags |= ACPI_EXT_INTERNAL_PATH_ALLOCATED;
594 Status = AcpiNsInternalizeName (ExternalPath, &InternalPath);
595 if (ACPI_FAILURE (Status))
596 {
597 ACPI_FREE (ExternalPath);
598 return_VOID;
599 }
600 }
601
602 /* Create the new External() declaration node */
603
604 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
605 Type, Value, Flags);
606 if (ACPI_FAILURE (Status))
607 {
608 ACPI_FREE (ExternalPath);
609 if (Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
610 {
611 ACPI_FREE (InternalPath);
612 }
613 }
614
615 return_VOID;
616 }
617
618
619 /*******************************************************************************
620 *
621 * FUNCTION: AcpiDmGetExternalAndInternalPath
622 *
623 * PARAMETERS: Node - Namespace node for object to be added
624 * ExternalPath - Will contain the external path of the node
625 * InternalPath - Will contain the internal path of the node
626 *
627 * RETURN: None
628 *
629 * DESCRIPTION: Get the External and Internal path from the given node.
630 *
631 ******************************************************************************/
632
633 static ACPI_STATUS
AcpiDmGetExternalAndInternalPath(ACPI_NAMESPACE_NODE * Node,char ** ExternalPath,char ** InternalPath)634 AcpiDmGetExternalAndInternalPath (
635 ACPI_NAMESPACE_NODE *Node,
636 char **ExternalPath,
637 char **InternalPath)
638 {
639 ACPI_STATUS Status;
640
641
642 if (!Node)
643 {
644 return (AE_BAD_PARAMETER);
645 }
646
647 /* Get the full external and internal pathnames to the node */
648
649 *ExternalPath = AcpiNsGetExternalPathname (Node);
650 if (!*ExternalPath)
651 {
652 return (AE_BAD_PATHNAME);
653 }
654
655 Status = AcpiNsInternalizeName (*ExternalPath, InternalPath);
656 if (ACPI_FAILURE (Status))
657 {
658 ACPI_FREE (*ExternalPath);
659 return (Status);
660 }
661
662 return (AE_OK);
663 }
664
665
666 /*******************************************************************************
667 *
668 * FUNCTION: AcpiDmRemoveRootPrefix
669 *
670 * PARAMETERS: Path - Remove Root prefix from this Path
671 *
672 * RETURN: None
673 *
674 * DESCRIPTION: Remove the root prefix character '\' from Path.
675 *
676 ******************************************************************************/
677
678 static ACPI_STATUS
AcpiDmRemoveRootPrefix(char ** Path)679 AcpiDmRemoveRootPrefix (
680 char **Path)
681 {
682 char *InputPath = *Path;
683
684
685 if ((*InputPath == AML_ROOT_PREFIX) && (InputPath[1]))
686 {
687 if (!memmove(InputPath, InputPath+1, strlen(InputPath)))
688 {
689 return (AE_ERROR);
690 }
691
692 *Path = InputPath;
693 }
694
695 return (AE_OK);
696 }
697
698
699 /*******************************************************************************
700 *
701 * FUNCTION: AcpiDmAddNodeToExternalList
702 *
703 * PARAMETERS: Node - Namespace node for object to be added
704 * Type - ACPI object type to be added
705 * Value - Arg count if adding a Method object
706 * Flags - To be passed to the external object
707 *
708 * RETURN: None
709 *
710 * DESCRIPTION: Insert a new name into the global list of Externals which
711 * will in turn be later emitted as an External() declaration
712 * in the disassembled output.
713 *
714 * This function handles the case where the referenced name has
715 * been found in the namespace, but the name originated in a
716 * table other than the one that is being disassembled (such
717 * as a table that is added via the iASL -e option).
718 *
719 ******************************************************************************/
720
721 void
AcpiDmAddNodeToExternalList(ACPI_NAMESPACE_NODE * Node,UINT8 Type,UINT32 Value,UINT16 Flags)722 AcpiDmAddNodeToExternalList (
723 ACPI_NAMESPACE_NODE *Node,
724 UINT8 Type,
725 UINT32 Value,
726 UINT16 Flags)
727 {
728 char *ExternalPath;
729 char *InternalPath;
730 ACPI_STATUS Status;
731
732
733 ACPI_FUNCTION_TRACE (DmAddNodeToExternalList);
734
735 /* Get the full external and internal pathnames to the node */
736
737 Status = AcpiDmGetExternalAndInternalPath (Node, &ExternalPath, &InternalPath);
738 if (ACPI_FAILURE (Status))
739 {
740 return_VOID;
741 }
742
743 /* Remove the root backslash */
744
745 Status = AcpiDmRemoveRootPrefix (&ExternalPath);
746 if (ACPI_FAILURE (Status))
747 {
748 ACPI_FREE (ExternalPath);
749 ACPI_FREE (InternalPath);
750 return_VOID;
751 }
752
753 /* Create the new External() declaration node */
754
755 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, Type,
756 Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
757 if (ACPI_FAILURE (Status))
758 {
759 ACPI_FREE (ExternalPath);
760 ACPI_FREE (InternalPath);
761 }
762
763 return_VOID;
764 }
765
766
767 /*******************************************************************************
768 *
769 * FUNCTION: AcpiDmAddPathToExternalList
770 *
771 * PARAMETERS: Path - External name of the object to be added
772 * Type - ACPI object type to be added
773 * Value - Arg count if adding a Method object
774 * Flags - To be passed to the external object
775 *
776 * RETURN: None
777 *
778 * DESCRIPTION: Insert a new name into the global list of Externals which
779 * will in turn be later emitted as an External() declaration
780 * in the disassembled output.
781 *
782 * This function currently is used to add externals via a
783 * reference file (via the -fe iASL option).
784 *
785 ******************************************************************************/
786
787 static void
AcpiDmAddPathToExternalList(char * Path,UINT8 Type,UINT32 Value,UINT16 Flags)788 AcpiDmAddPathToExternalList (
789 char *Path,
790 UINT8 Type,
791 UINT32 Value,
792 UINT16 Flags)
793 {
794 char *InternalPath;
795 char *ExternalPath;
796 ACPI_STATUS Status;
797
798
799 ACPI_FUNCTION_TRACE (DmAddPathToExternalList);
800
801
802 if (!Path)
803 {
804 return_VOID;
805 }
806
807 /* Remove a root backslash if present */
808
809 if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
810 {
811 Path++;
812 }
813
814 /* Create the internal and external pathnames */
815
816 Status = AcpiNsInternalizeName (Path, &InternalPath);
817 if (ACPI_FAILURE (Status))
818 {
819 return_VOID;
820 }
821
822 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath,
823 NULL, &ExternalPath);
824 if (ACPI_FAILURE (Status))
825 {
826 ACPI_FREE (InternalPath);
827 return_VOID;
828 }
829
830 /* Create the new External() declaration node */
831
832 Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath,
833 Type, Value, (Flags | ACPI_EXT_INTERNAL_PATH_ALLOCATED));
834 if (ACPI_FAILURE (Status))
835 {
836 ACPI_FREE (ExternalPath);
837 ACPI_FREE (InternalPath);
838 }
839
840 return_VOID;
841 }
842
843
844 /*******************************************************************************
845 *
846 * FUNCTION: AcpiDmCreateNewExternal
847 *
848 * PARAMETERS: ExternalPath - External path to the object
849 * InternalPath - Internal (AML) path to the object
850 * Type - ACPI object type to be added
851 * Value - Arg count if adding a Method object
852 * Flags - To be passed to the external object
853 *
854 * RETURN: Status
855 *
856 * DESCRIPTION: Common low-level function to insert a new name into the global
857 * list of Externals which will in turn be later emitted as
858 * External() declarations in the disassembled output.
859 *
860 * Note: The external name should not include a root prefix
861 * (backslash). We do not want External() statements to contain
862 * a leading '\', as this prevents duplicate external statements
863 * of the form:
864 *
865 * External (\ABCD)
866 * External (ABCD)
867 *
868 * This would cause a compile time error when the disassembled
869 * output file is recompiled.
870 *
871 * There are two cases that are handled here. For both, we emit
872 * an External() statement:
873 * 1) The name was simply not found in the namespace.
874 * 2) The name was found, but it originated in a table other than
875 * the table that is being disassembled.
876 *
877 ******************************************************************************/
878
879 static ACPI_STATUS
AcpiDmCreateNewExternal(char * ExternalPath,char * InternalPath,UINT8 Type,UINT32 Value,UINT16 Flags)880 AcpiDmCreateNewExternal (
881 char *ExternalPath,
882 char *InternalPath,
883 UINT8 Type,
884 UINT32 Value,
885 UINT16 Flags)
886 {
887 ACPI_EXTERNAL_LIST *NewExternal;
888 ACPI_EXTERNAL_LIST *NextExternal;
889 ACPI_EXTERNAL_LIST *PrevExternal = NULL;
890
891
892 ACPI_FUNCTION_TRACE (DmCreateNewExternal);
893
894
895 /* Check all existing externals to ensure no duplicates */
896
897 NextExternal = AcpiGbl_ExternalList;
898 while (NextExternal)
899 {
900 /* Check for duplicates */
901
902 if (!strcmp (ExternalPath, NextExternal->Path))
903 {
904 /*
905 * If this external came from an External() opcode, we are
906 * finished with this one. (No need to check any further).
907 */
908 if (NextExternal->Flags & ACPI_EXT_ORIGIN_FROM_OPCODE)
909 {
910 return_ACPI_STATUS (AE_ALREADY_EXISTS);
911 }
912
913 /* Allow upgrade of type from ANY */
914
915 else if ((NextExternal->Type == ACPI_TYPE_ANY) &&
916 (Type != ACPI_TYPE_ANY))
917 {
918 NextExternal->Type = Type;
919 }
920
921 /* Update the argument count as necessary */
922
923 if (Value < NextExternal->Value)
924 {
925 NextExternal->Value = Value;
926 }
927
928 /* Update flags. */
929
930 NextExternal->Flags |= Flags;
931 NextExternal->Flags &= ~ACPI_EXT_INTERNAL_PATH_ALLOCATED;
932
933 return_ACPI_STATUS (AE_ALREADY_EXISTS);
934 }
935
936 NextExternal = NextExternal->Next;
937 }
938
939 /* Allocate and init a new External() descriptor */
940
941 NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
942 if (!NewExternal)
943 {
944 return_ACPI_STATUS (AE_NO_MEMORY);
945 }
946
947 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
948 "Adding external reference node (%s) type [%s]\n",
949 ExternalPath, AcpiUtGetTypeName (Type)));
950
951 NewExternal->Flags = Flags;
952 NewExternal->Value = Value;
953 NewExternal->Path = ExternalPath;
954 NewExternal->Type = Type;
955 NewExternal->Length = (UINT16) strlen (ExternalPath);
956 NewExternal->InternalPath = InternalPath;
957
958 /* Link the new descriptor into the global list, alphabetically ordered */
959
960 NextExternal = AcpiGbl_ExternalList;
961 while (NextExternal)
962 {
963 if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0)
964 {
965 if (PrevExternal)
966 {
967 PrevExternal->Next = NewExternal;
968 }
969 else
970 {
971 AcpiGbl_ExternalList = NewExternal;
972 }
973
974 NewExternal->Next = NextExternal;
975 return_ACPI_STATUS (AE_OK);
976 }
977
978 PrevExternal = NextExternal;
979 NextExternal = NextExternal->Next;
980 }
981
982 if (PrevExternal)
983 {
984 PrevExternal->Next = NewExternal;
985 }
986 else
987 {
988 AcpiGbl_ExternalList = NewExternal;
989 }
990
991 return_ACPI_STATUS (AE_OK);
992 }
993
994
995 /*******************************************************************************
996 *
997 * FUNCTION: AcpiDmResolveExternal
998 *
999 * PARAMETERS: Path - Path of the external
1000 * Type - Type of the external
1001 * Node - Input node for AcpiNsLookup
1002 *
1003 * RETURN: Status
1004 *
1005 * DESCRIPTION: Resolve the external within the namespace by AcpiNsLookup.
1006 * If the returned node is an external and has the same type
1007 * we assume that it was either an existing external or a
1008 *
1009 ******************************************************************************/
1010
1011 static ACPI_STATUS
AcpiDmResolveExternal(char * Path,UINT8 Type,ACPI_NAMESPACE_NODE ** Node)1012 AcpiDmResolveExternal (
1013 char *Path,
1014 UINT8 Type,
1015 ACPI_NAMESPACE_NODE **Node)
1016 {
1017 ACPI_STATUS Status;
1018
1019
1020 Status = AcpiNsLookup (NULL, Path, Type,
1021 ACPI_IMODE_LOAD_PASS1,
1022 ACPI_NS_ERROR_IF_FOUND | ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE,
1023 NULL, Node);
1024
1025 if (!Node)
1026 {
1027 ACPI_EXCEPTION ((AE_INFO, Status,
1028 "while adding external to namespace [%s]", Path));
1029 }
1030
1031 /* Note the asl code "external(a) external(a)" is acceptable ASL */
1032
1033 else if ((*Node)->Type == Type &&
1034 (*Node)->Flags & ANOBJ_IS_EXTERNAL)
1035 {
1036 return (AE_OK);
1037 }
1038 else
1039 {
1040 ACPI_EXCEPTION ((AE_INFO, AE_ERROR,
1041 "[%s] has conflicting declarations", Path));
1042 }
1043
1044 return (AE_ERROR);
1045 }
1046
1047
1048 /*******************************************************************************
1049 *
1050 * FUNCTION: AcpiDmCreateSubobjectForExternal
1051 *
1052 * PARAMETERS: Type - Type of the external
1053 * Node - Namespace node from AcpiNsLookup
1054 * ParamCount - Value to be used for Method
1055 *
1056 * RETURN: None
1057 *
1058 * DESCRIPTION: Add one external to the namespace. Allows external to be
1059 * "resolved".
1060 *
1061 ******************************************************************************/
1062
1063 void
AcpiDmCreateSubobjectForExternal(UINT8 Type,ACPI_NAMESPACE_NODE ** Node,UINT32 ParamCount)1064 AcpiDmCreateSubobjectForExternal (
1065 UINT8 Type,
1066 ACPI_NAMESPACE_NODE **Node,
1067 UINT32 ParamCount)
1068 {
1069 ACPI_OPERAND_OBJECT *ObjDesc;
1070
1071
1072 switch (Type)
1073 {
1074 case ACPI_TYPE_METHOD:
1075
1076 /* For methods, we need to save the argument count */
1077
1078 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
1079 ObjDesc->Method.ParamCount = (UINT8) ParamCount;
1080 (*Node)->Object = ObjDesc;
1081 break;
1082
1083 case ACPI_TYPE_REGION:
1084
1085 /* Regions require a region sub-object */
1086
1087 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION);
1088 ObjDesc->Region.Node = *Node;
1089 (*Node)->Object = ObjDesc;
1090 break;
1091
1092 default:
1093
1094 break;
1095 }
1096 }
1097
1098
1099 /*******************************************************************************
1100 *
1101 * FUNCTION: AcpiDmAddOneExternalToNamespace
1102 *
1103 * PARAMETERS: Path - External parse object
1104 * Type - Type of parse object
1105 * ParamCount - External method parameter count
1106 *
1107 * RETURN: None
1108 *
1109 * DESCRIPTION: Add one external to the namespace by resolvign the external
1110 * (by performing a namespace lookup) and annotating the resulting
1111 * namespace node with the appropriate information if the type
1112 * is ACPI_TYPE_REGION or ACPI_TYPE_METHOD.
1113 *
1114 ******************************************************************************/
1115
1116 void
AcpiDmAddOneExternalToNamespace(char * Path,UINT8 Type,UINT32 ParamCount)1117 AcpiDmAddOneExternalToNamespace (
1118 char *Path,
1119 UINT8 Type,
1120 UINT32 ParamCount)
1121 {
1122 ACPI_STATUS Status;
1123 ACPI_NAMESPACE_NODE *Node;
1124
1125
1126 Status = AcpiDmResolveExternal (Path, Type, &Node);
1127
1128 if (ACPI_FAILURE (Status))
1129 {
1130 return;
1131 }
1132
1133 AcpiDmCreateSubobjectForExternal (Type, &Node, ParamCount);
1134
1135 }
1136
1137
1138 /*******************************************************************************
1139 *
1140 * FUNCTION: AcpiDmAddExternalListToNamespace
1141 *
1142 * PARAMETERS: None
1143 *
1144 * RETURN: None
1145 *
1146 * DESCRIPTION: Add all externals within AcpiGbl_ExternalList to the namespace.
1147 * Allows externals to be "resolved".
1148 *
1149 ******************************************************************************/
1150
1151 void
AcpiDmAddExternalListToNamespace(void)1152 AcpiDmAddExternalListToNamespace (
1153 void)
1154 {
1155 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList;
1156
1157
1158 while (External)
1159 {
1160 AcpiDmAddOneExternalToNamespace (External->InternalPath,
1161 External->Type, External->Value);
1162 External = External->Next;
1163 }
1164 }
1165
1166
1167 /*******************************************************************************
1168 *
1169 * FUNCTION: AcpiDmGetUnresolvedExternalMethodCount
1170 *
1171 * PARAMETERS: None
1172 *
1173 * RETURN: The number of unresolved control method externals in the
1174 * external list
1175 *
1176 * DESCRIPTION: Return the number of unresolved external methods that have been
1177 * generated. If any unresolved control method externals have been
1178 * found, we must re-parse the entire definition block with the new
1179 * information (number of arguments for the methods.)
1180 * This is limitation of AML, we don't know the number of arguments
1181 * from the control method invocation itself.
1182 *
1183 * Note: resolved external control methods are external control
1184 * methods encoded with the AML_EXTERNAL_OP bytecode within the
1185 * AML being disassembled.
1186 *
1187 ******************************************************************************/
1188
1189 UINT32
AcpiDmGetUnresolvedExternalMethodCount(void)1190 AcpiDmGetUnresolvedExternalMethodCount (
1191 void)
1192 {
1193 ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList;
1194 UINT32 Count = 0;
1195
1196
1197 while (External)
1198 {
1199 if (External->Type == ACPI_TYPE_METHOD &&
1200 !(External->Flags & ACPI_EXT_ORIGIN_FROM_OPCODE))
1201 {
1202 Count++;
1203 }
1204
1205 External = External->Next;
1206 }
1207
1208 return (Count);
1209 }
1210
1211
1212 /*******************************************************************************
1213 *
1214 * FUNCTION: AcpiDmClearExternalList
1215 *
1216 * PARAMETERS: None
1217 *
1218 * RETURN: None
1219 *
1220 * DESCRIPTION: Free the entire External info list
1221 *
1222 ******************************************************************************/
1223
1224 void
AcpiDmClearExternalList(void)1225 AcpiDmClearExternalList (
1226 void)
1227 {
1228 ACPI_EXTERNAL_LIST *NextExternal;
1229
1230
1231 while (AcpiGbl_ExternalList)
1232 {
1233 NextExternal = AcpiGbl_ExternalList->Next;
1234 ACPI_FREE (AcpiGbl_ExternalList->Path);
1235 ACPI_FREE (AcpiGbl_ExternalList);
1236 AcpiGbl_ExternalList = NextExternal;
1237 }
1238 }
1239
1240
1241 /*******************************************************************************
1242 *
1243 * FUNCTION: AcpiDmEmitExternals
1244 *
1245 * PARAMETERS: None
1246 *
1247 * RETURN: None
1248 *
1249 * DESCRIPTION: Emit an External() ASL statement for each of the externals in
1250 * the global external info list.
1251 *
1252 ******************************************************************************/
1253
1254 void
AcpiDmEmitExternals(void)1255 AcpiDmEmitExternals (
1256 void)
1257 {
1258 ACPI_EXTERNAL_LIST *NextExternal;
1259
1260
1261 if (!AcpiGbl_ExternalList)
1262 {
1263 return;
1264 }
1265
1266 /*
1267 * Determine the number of control methods in the external list, and
1268 * also how many of those externals were resolved via the namespace.
1269 */
1270 NextExternal = AcpiGbl_ExternalList;
1271 while (NextExternal)
1272 {
1273 if (NextExternal->Type == ACPI_TYPE_METHOD)
1274 {
1275 AcpiGbl_NumExternalMethods++;
1276 if (NextExternal->Flags & ACPI_EXT_RESOLVED_REFERENCE)
1277 {
1278 AcpiGbl_ResolvedExternalMethods++;
1279 }
1280 }
1281
1282 NextExternal = NextExternal->Next;
1283 }
1284
1285 /* Check if any control methods were unresolved */
1286
1287 AcpiDmUnresolvedWarning (1);
1288
1289 if (AslGbl_ExternalRefFilename)
1290 {
1291 AcpiOsPrintf (
1292 " /*\n * External declarations were imported from\n"
1293 " * a reference file -- %s\n */\n\n",
1294 AslGbl_ExternalRefFilename);
1295 }
1296
1297 /*
1298 * Walk and emit the list of externals found during the AML parsing
1299 */
1300 while (AcpiGbl_ExternalList)
1301 {
1302 if (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_EXTERNAL_EMITTED))
1303 {
1304 AcpiOsPrintf (" External (%s%s)",
1305 AcpiGbl_ExternalList->Path,
1306 AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type));
1307
1308 /* Check for "unresolved" method reference */
1309
1310 if ((AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) &&
1311 (!(AcpiGbl_ExternalList->Flags & ACPI_EXT_RESOLVED_REFERENCE)))
1312 {
1313 AcpiOsPrintf (" // Warning: Unknown method, "
1314 "guessing %u arguments",
1315 AcpiGbl_ExternalList->Value);
1316 }
1317
1318 /* Check for external from a external references file */
1319
1320 else if (AcpiGbl_ExternalList->Flags & ACPI_EXT_ORIGIN_FROM_FILE)
1321 {
1322 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1323 {
1324 AcpiOsPrintf (" // %u Arguments",
1325 AcpiGbl_ExternalList->Value);
1326 }
1327
1328 AcpiOsPrintf (" // From external reference file");
1329 }
1330
1331 /* This is the normal external case */
1332
1333 else
1334 {
1335 /* For methods, add a comment with the number of arguments */
1336
1337 if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
1338 {
1339 AcpiOsPrintf (" // %u Arguments",
1340 AcpiGbl_ExternalList->Value);
1341 }
1342 }
1343
1344 if (AcpiGbl_ExternalList->Flags &= ACPI_EXT_CONFLICTING_DECLARATION)
1345 {
1346 AcpiOsPrintf ("%s", ExternalConflictMessage);
1347 AcpiDmConflictingDeclaration (AcpiGbl_ExternalList->Path);
1348 }
1349 AcpiOsPrintf ("\n");
1350 }
1351
1352 /* Free this external info block and move on to next external */
1353
1354 NextExternal = AcpiGbl_ExternalList->Next;
1355 if (AcpiGbl_ExternalList->Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED)
1356 {
1357 ACPI_FREE (AcpiGbl_ExternalList->InternalPath);
1358 }
1359
1360 ACPI_FREE (AcpiGbl_ExternalList->Path);
1361 ACPI_FREE (AcpiGbl_ExternalList);
1362 AcpiGbl_ExternalList = NextExternal;
1363 }
1364
1365 AcpiOsPrintf ("\n");
1366 }
1367
1368
1369 /*******************************************************************************
1370 *
1371 * FUNCTION: AcpiDmMarkExternalConflict
1372 *
1373 * PARAMETERS: Path - Namepath to search
1374 *
1375 * RETURN: ExternalList
1376 *
1377 * DESCRIPTION: Search the AcpiGbl_ExternalList for a matching path
1378 *
1379 ******************************************************************************/
1380
1381 void
AcpiDmMarkExternalConflict(ACPI_NAMESPACE_NODE * Node)1382 AcpiDmMarkExternalConflict (
1383 ACPI_NAMESPACE_NODE *Node)
1384 {
1385 ACPI_EXTERNAL_LIST *ExternalList = AcpiGbl_ExternalList;
1386 char *ExternalPath;
1387 char *InternalPath;
1388 ACPI_STATUS Status;
1389
1390
1391 ACPI_FUNCTION_TRACE (DmMarkExternalConflict);
1392
1393
1394 if (Node->Flags & ANOBJ_IS_EXTERNAL)
1395 {
1396 return_VOID;
1397 }
1398
1399 /* Get the full external and internal pathnames to the node */
1400
1401 Status = AcpiDmGetExternalAndInternalPath (Node,
1402 &ExternalPath, &InternalPath);
1403 if (ACPI_FAILURE (Status))
1404 {
1405 return_VOID;
1406 }
1407
1408 /* Remove the root backslash */
1409
1410 Status = AcpiDmRemoveRootPrefix (&InternalPath);
1411 if (ACPI_FAILURE (Status))
1412 {
1413 ACPI_FREE (InternalPath);
1414 ACPI_FREE (ExternalPath);
1415 return_VOID;
1416 }
1417
1418 while (ExternalList)
1419 {
1420 if (!strcmp (ExternalList->InternalPath, InternalPath))
1421 {
1422 ExternalList->Flags |= ACPI_EXT_CONFLICTING_DECLARATION;
1423 }
1424 ExternalList = ExternalList->Next;
1425 }
1426
1427 ACPI_FREE (InternalPath);
1428 ACPI_FREE (ExternalPath);
1429
1430 return_VOID;
1431 }
1432
1433
1434 /*******************************************************************************
1435 *
1436 * FUNCTION: AcpiDmConflictingDeclaration
1437 *
1438 * PARAMETERS: Path - Path with conflicting declaration
1439 *
1440 * RETURN: None
1441 *
1442 * DESCRIPTION: Emit a warning when printing conflicting ASL external
1443 * declarations.
1444 *
1445 ******************************************************************************/
1446
1447 static void
AcpiDmConflictingDeclaration(char * Path)1448 AcpiDmConflictingDeclaration (
1449 char *Path)
1450 {
1451 fprintf (stderr,
1452 " Warning - Emitting ASL code \"External (%s)\"\n"
1453 " This is a conflicting declaration with some "
1454 "other declaration within the ASL code.\n"
1455 " This external declaration may need to be "
1456 "deleted in order to recompile the dsl file.\n\n",
1457 Path);
1458 }
1459
1460
1461 /*******************************************************************************
1462 *
1463 * FUNCTION: AcpiDmEmitExternal
1464 *
1465 * PARAMETERS: Op External Parse Object
1466 *
1467 * RETURN: None
1468 *
1469 * DESCRIPTION: Emit an External() ASL statement for the current External
1470 * parse object. Note: External Ops are named types so the
1471 * namepath is contained within NameOp->Name.Path.
1472 *
1473 ******************************************************************************/
1474
1475 void
AcpiDmEmitExternal(ACPI_PARSE_OBJECT * NameOp,ACPI_PARSE_OBJECT * TypeOp)1476 AcpiDmEmitExternal (
1477 ACPI_PARSE_OBJECT *NameOp,
1478 ACPI_PARSE_OBJECT *TypeOp)
1479 {
1480 AcpiOsPrintf ("External (");
1481 AcpiDmNamestring (NameOp->Named.Path);
1482 AcpiOsPrintf ("%s)",
1483 AcpiDmGetObjectTypeName ((ACPI_OBJECT_TYPE) TypeOp->Common.Value.Integer));
1484 AcpiDmCheckForExternalConflict (NameOp->Named.Path);
1485 AcpiOsPrintf ("\n");
1486 }
1487
1488
1489 /*******************************************************************************
1490 *
1491 * FUNCTION: AcpiDmCheckForExternalConflict
1492 *
1493 * PARAMETERS: Path - Path to check
1494 *
1495 * RETURN: None
1496 *
1497 * DESCRIPTION: Search the External List to see if the input Path has a
1498 * conflicting declaration.
1499 *
1500 ******************************************************************************/
1501
1502 static void
AcpiDmCheckForExternalConflict(char * Path)1503 AcpiDmCheckForExternalConflict (
1504 char *Path)
1505 {
1506 ACPI_EXTERNAL_LIST *ExternalList = AcpiGbl_ExternalList;
1507 char *ListItemPath;
1508 char *InputPath;
1509
1510
1511 if (!Path)
1512 {
1513 return;
1514 }
1515
1516 /* Move past the root prefix '\' */
1517
1518 InputPath = Path;
1519 if ((*InputPath == AML_ROOT_PREFIX) && InputPath[1])
1520 {
1521 InputPath++;
1522 }
1523
1524 while (ExternalList)
1525 {
1526 ListItemPath = ExternalList->Path;
1527 if (ListItemPath)
1528 {
1529 /* Move past the root prefix '\' */
1530
1531 if ((*ListItemPath == AML_ROOT_PREFIX) &&
1532 ListItemPath[1])
1533 {
1534 ListItemPath++;
1535 }
1536
1537 if (!strcmp (ListItemPath, InputPath) &&
1538 (ExternalList->Flags & ACPI_EXT_CONFLICTING_DECLARATION))
1539 {
1540 AcpiOsPrintf ("%s", ExternalConflictMessage);
1541 AcpiDmConflictingDeclaration (Path);
1542
1543 return;
1544 }
1545 }
1546 ExternalList = ExternalList->Next;
1547 }
1548 }
1549 /*******************************************************************************
1550 *
1551 * FUNCTION: AcpiDmUnresolvedWarning
1552 *
1553 * PARAMETERS: Type - Where to output the warning.
1554 * 0 means write to stderr
1555 * 1 means write to AcpiOsPrintf
1556 *
1557 * RETURN: None
1558 *
1559 * DESCRIPTION: Issue warning message if there are unresolved external control
1560 * methods within the disassembly.
1561 *
1562 ******************************************************************************/
1563
1564 /*
1565 Summary of the external control method problem:
1566
1567 When the -e option is used with disassembly, the various SSDTs are simply
1568 loaded into a global namespace for the disassembler to use in order to
1569 resolve control method references (invocations).
1570
1571 The disassembler tracks any such references, and will emit an External()
1572 statement for these types of methods, with the proper number of arguments .
1573
1574 Without the SSDTs, the AML does not contain enough information to properly
1575 disassemble the control method invocation -- because the disassembler does
1576 not know how many arguments to parse.
1577
1578 An example: Assume we have two control methods. ABCD has one argument, and
1579 EFGH has zero arguments. Further, we have two additional control methods
1580 that invoke ABCD and EFGH, named T1 and T2:
1581
1582 Method (ABCD, 1)
1583 {
1584 }
1585 Method (EFGH, 0)
1586 {
1587 }
1588 Method (T1)
1589 {
1590 ABCD (Add (2, 7, Local0))
1591 }
1592 Method (T2)
1593 {
1594 EFGH ()
1595 Add (2, 7, Local0)
1596 }
1597
1598 Here is the AML code that is generated for T1 and T2:
1599
1600 185: Method (T1)
1601
1602 0000034C: 14 10 54 31 5F 5F 00 ... "..T1__."
1603
1604 186: {
1605 187: ABCD (Add (2, 7, Local0))
1606
1607 00000353: 41 42 43 44 ............ "ABCD"
1608 00000357: 72 0A 02 0A 07 60 ...... "r....`"
1609
1610 188: }
1611
1612 190: Method (T2)
1613
1614 0000035D: 14 10 54 32 5F 5F 00 ... "..T2__."
1615
1616 191: {
1617 192: EFGH ()
1618
1619 00000364: 45 46 47 48 ............ "EFGH"
1620
1621 193: Add (2, 7, Local0)
1622
1623 00000368: 72 0A 02 0A 07 60 ...... "r....`"
1624 194: }
1625
1626 Note that the AML code for T1 and T2 is essentially identical. When
1627 disassembling this code, the methods ABCD and EFGH must be known to the
1628 disassembler, otherwise it does not know how to handle the method invocations.
1629
1630 In other words, if ABCD and EFGH are actually external control methods
1631 appearing in an SSDT, the disassembler does not know what to do unless
1632 the owning SSDT has been loaded via the -e option.
1633 */
1634
1635 static char ExternalWarningPart1[600];
1636 static char ExternalWarningPart2[400];
1637 static char ExternalWarningPart3[400];
1638 static char ExternalWarningPart4[200];
1639
1640 void
AcpiDmUnresolvedWarning(UINT8 Type)1641 AcpiDmUnresolvedWarning (
1642 UINT8 Type)
1643 {
1644 char *Format;
1645 char Pad[] = " *";
1646 char NoPad[] = "";
1647
1648
1649 if (!AcpiGbl_NumExternalMethods)
1650 {
1651 return;
1652 }
1653
1654 if (AcpiGbl_NumExternalMethods == AcpiGbl_ResolvedExternalMethods)
1655 {
1656 return;
1657 }
1658
1659 Format = Type ? Pad : NoPad;
1660
1661 sprintf (ExternalWarningPart1,
1662 "%s iASL Warning: There %s %u external control method%s found during\n"
1663 "%s disassembly, but only %u %s resolved (%u unresolved). Additional\n"
1664 "%s ACPI tables may be required to properly disassemble the code. This\n"
1665 "%s resulting disassembler output file may not compile because the\n"
1666 "%s disassembler did not know how many arguments to assign to the\n"
1667 "%s unresolved methods. Note: SSDTs can be dynamically loaded at\n"
1668 "%s runtime and may or may not be available via the host OS.\n",
1669 Format, (AcpiGbl_NumExternalMethods != 1 ? "were" : "was"),
1670 AcpiGbl_NumExternalMethods, (AcpiGbl_NumExternalMethods != 1 ? "s" : ""),
1671 Format, AcpiGbl_ResolvedExternalMethods,
1672 (AcpiGbl_ResolvedExternalMethods != 1 ? "were" : "was"),
1673 (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods),
1674 Format, Format, Format, Format, Format);
1675
1676 sprintf (ExternalWarningPart2,
1677 "%s To specify the tables needed to resolve external control method\n"
1678 "%s references, the -e option can be used to specify the filenames.\n"
1679 "%s Example iASL invocations:\n"
1680 "%s iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n"
1681 "%s iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n"
1682 "%s iasl -e ssdt*.aml -d dsdt.aml\n",
1683 Format, Format, Format, Format, Format, Format);
1684
1685 sprintf (ExternalWarningPart3,
1686 "%s In addition, the -fe option can be used to specify a file containing\n"
1687 "%s control method external declarations with the associated method\n"
1688 "%s argument counts. Each line of the file must be of the form:\n"
1689 "%s External (<method pathname>, MethodObj, <argument count>)\n"
1690 "%s Invocation:\n"
1691 "%s iasl -fe refs.txt -d dsdt.aml\n",
1692 Format, Format, Format, Format, Format, Format);
1693
1694 sprintf (ExternalWarningPart4,
1695 "%s The following methods were unresolved and many not compile properly\n"
1696 "%s because the disassembler had to guess at the number of arguments\n"
1697 "%s required for each:\n",
1698 Format, Format, Format);
1699
1700 if (Type)
1701 {
1702 if (!AcpiGbl_ExternalFileList)
1703 {
1704 /* The -e option was not specified */
1705
1706 AcpiOsPrintf (" /*\n%s *\n%s *\n%s *\n%s */\n",
1707 ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3,
1708 ExternalWarningPart4);
1709 }
1710 else
1711 {
1712 /* The -e option was specified, but there are still some unresolved externals */
1713
1714 AcpiOsPrintf (" /*\n%s *\n%s *\n%s */\n",
1715 ExternalWarningPart1, ExternalWarningPart3, ExternalWarningPart4);
1716 }
1717 }
1718 else
1719 {
1720 if (!AcpiGbl_ExternalFileList)
1721 {
1722 /* The -e option was not specified */
1723
1724 fprintf (stderr, "\n%s\n%s\n%s\n",
1725 ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3);
1726 }
1727 else
1728 {
1729 /* The -e option was specified, but there are still some unresolved externals */
1730
1731 fprintf (stderr, "\n%s\n%s\n",
1732 ExternalWarningPart1, ExternalWarningPart3);
1733 }
1734 }
1735 }
1736