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