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 - 2018, 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 (!Gbl_ExternalRefFilename)
524 {
525 return;
526 }
527
528 /* Open the file */
529
530 ExternalRefFile = fopen (Gbl_ExternalRefFilename, "r");
531 if (!ExternalRefFile)
532 {
533 fprintf (stderr, "Could not open external reference file \"%s\"\n",
534 Gbl_ExternalRefFilename);
535 AslAbort ();
536 return;
537 }
538
539 /* Each line defines a method */
540
541 while (fgets (StringBuffer, ASL_STRING_BUFFER_SIZE, ExternalRefFile))
542 {
543 Token = strtok (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 Gbl_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 Gbl_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 Gbl_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 approperiate 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 (Gbl_ExternalRefFilename)
1398 {
1399 AcpiOsPrintf (
1400 " /*\n * External declarations were imported from\n"
1401 " * a reference file -- %s\n */\n\n",
1402 Gbl_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 char *Temp;
1497 ACPI_STATUS Status;
1498
1499
1500 ACPI_FUNCTION_TRACE (DmMarkExternalConflict);
1501
1502
1503 if (Node->Flags & ANOBJ_IS_EXTERNAL)
1504 {
1505 return_VOID;
1506 }
1507
1508 /* Get the full external and internal pathnames to the node */
1509
1510 Status = AcpiDmGetExternalAndInternalPath (Node,
1511 &ExternalPath, &InternalPath);
1512 if (ACPI_FAILURE (Status))
1513 {
1514 return_VOID;
1515 }
1516
1517 /* Remove the root backslash */
1518
1519 Status = AcpiDmRemoveRootPrefix (&InternalPath);
1520 if (ACPI_FAILURE (Status))
1521 {
1522 ACPI_FREE (InternalPath);
1523 ACPI_FREE (ExternalPath);
1524 return_VOID;
1525 }
1526
1527 while (ExternalList)
1528 {
1529 Temp = ExternalList->InternalPath;
1530 if ((*ExternalList->InternalPath == AML_ROOT_PREFIX) &&
1531 (ExternalList->InternalPath[1]))
1532 {
1533 Temp++;
1534 }
1535
1536 if (!strcmp (ExternalList->InternalPath, InternalPath))
1537 {
1538 ExternalList->Flags |= ACPI_EXT_CONFLICTING_DECLARATION;
1539 }
1540 ExternalList = ExternalList->Next;
1541 }
1542
1543 ACPI_FREE (InternalPath);
1544 ACPI_FREE (ExternalPath);
1545
1546 return_VOID;
1547 }
1548
1549
1550 /*******************************************************************************
1551 *
1552 * FUNCTION: AcpiDmConflictingDeclaration
1553 *
1554 * PARAMETERS: Path - Path with conflicting declaration
1555 *
1556 * RETURN: None
1557 *
1558 * DESCRIPTION: Emit a warning when printing conflicting ASL external
1559 * declarations.
1560 *
1561 ******************************************************************************/
1562
1563 static void
AcpiDmConflictingDeclaration(char * Path)1564 AcpiDmConflictingDeclaration (
1565 char *Path)
1566 {
1567 fprintf (stderr,
1568 " Warning - Emitting ASL code \"External (%s)\"\n"
1569 " This is a conflicting declaration with some "
1570 "other declaration within the ASL code.\n"
1571 " This external declaration may need to be "
1572 "deleted in order to recompile the dsl file.\n\n",
1573 Path);
1574 }
1575
1576
1577 /*******************************************************************************
1578 *
1579 * FUNCTION: AcpiDmEmitExternal
1580 *
1581 * PARAMETERS: Op External Parse Object
1582 *
1583 * RETURN: None
1584 *
1585 * DESCRIPTION: Emit an External() ASL statement for the current External
1586 * parse object. Note: External Ops are named types so the
1587 * namepath is contained within NameOp->Name.Path.
1588 *
1589 ******************************************************************************/
1590
1591 void
AcpiDmEmitExternal(ACPI_PARSE_OBJECT * NameOp,ACPI_PARSE_OBJECT * TypeOp)1592 AcpiDmEmitExternal (
1593 ACPI_PARSE_OBJECT *NameOp,
1594 ACPI_PARSE_OBJECT *TypeOp)
1595 {
1596 AcpiOsPrintf ("External (");
1597 AcpiDmNamestring (NameOp->Named.Path);
1598 AcpiOsPrintf ("%s)",
1599 AcpiDmGetObjectTypeName ((ACPI_OBJECT_TYPE) TypeOp->Common.Value.Integer));
1600 AcpiDmCheckForExternalConflict (NameOp->Named.Path);
1601 AcpiOsPrintf ("\n");
1602 }
1603
1604
1605 /*******************************************************************************
1606 *
1607 * FUNCTION: AcpiDmCheckForExternalConflict
1608 *
1609 * PARAMETERS: Path - Path to check
1610 *
1611 * RETURN: None
1612 *
1613 * DESCRIPTION: Search the External List to see if the input Path has a
1614 * conflicting declaration.
1615 *
1616 ******************************************************************************/
1617
1618 static void
AcpiDmCheckForExternalConflict(char * Path)1619 AcpiDmCheckForExternalConflict (
1620 char *Path)
1621 {
1622 ACPI_EXTERNAL_LIST *ExternalList = AcpiGbl_ExternalList;
1623 char *ListItemPath;
1624 char *InputPath;
1625
1626
1627 if (!Path)
1628 {
1629 return;
1630 }
1631
1632 /* Move past the root prefix '\' */
1633
1634 InputPath = Path;
1635 if ((*InputPath == AML_ROOT_PREFIX) && InputPath[1])
1636 {
1637 InputPath++;
1638 }
1639
1640 while (ExternalList)
1641 {
1642 ListItemPath = ExternalList->Path;
1643 if (ListItemPath)
1644 {
1645 /* Move past the root prefix '\' */
1646
1647 if ((*ListItemPath == AML_ROOT_PREFIX) &&
1648 ListItemPath[1])
1649 {
1650 ListItemPath++;
1651 }
1652
1653 if (!strcmp (ListItemPath, InputPath) &&
1654 (ExternalList->Flags & ACPI_EXT_CONFLICTING_DECLARATION))
1655 {
1656 AcpiOsPrintf ("%s", ExternalConflictMessage);
1657 AcpiDmConflictingDeclaration (Path);
1658
1659 return;
1660 }
1661 }
1662 ExternalList = ExternalList->Next;
1663 }
1664 }
1665 /*******************************************************************************
1666 *
1667 * FUNCTION: AcpiDmUnresolvedWarning
1668 *
1669 * PARAMETERS: Type - Where to output the warning.
1670 * 0 means write to stderr
1671 * 1 means write to AcpiOsPrintf
1672 *
1673 * RETURN: None
1674 *
1675 * DESCRIPTION: Issue warning message if there are unresolved external control
1676 * methods within the disassembly.
1677 *
1678 ******************************************************************************/
1679
1680 /*
1681 Summary of the external control method problem:
1682
1683 When the -e option is used with disassembly, the various SSDTs are simply
1684 loaded into a global namespace for the disassembler to use in order to
1685 resolve control method references (invocations).
1686
1687 The disassembler tracks any such references, and will emit an External()
1688 statement for these types of methods, with the proper number of arguments .
1689
1690 Without the SSDTs, the AML does not contain enough information to properly
1691 disassemble the control method invocation -- because the disassembler does
1692 not know how many arguments to parse.
1693
1694 An example: Assume we have two control methods. ABCD has one argument, and
1695 EFGH has zero arguments. Further, we have two additional control methods
1696 that invoke ABCD and EFGH, named T1 and T2:
1697
1698 Method (ABCD, 1)
1699 {
1700 }
1701 Method (EFGH, 0)
1702 {
1703 }
1704 Method (T1)
1705 {
1706 ABCD (Add (2, 7, Local0))
1707 }
1708 Method (T2)
1709 {
1710 EFGH ()
1711 Add (2, 7, Local0)
1712 }
1713
1714 Here is the AML code that is generated for T1 and T2:
1715
1716 185: Method (T1)
1717
1718 0000034C: 14 10 54 31 5F 5F 00 ... "..T1__."
1719
1720 186: {
1721 187: ABCD (Add (2, 7, Local0))
1722
1723 00000353: 41 42 43 44 ............ "ABCD"
1724 00000357: 72 0A 02 0A 07 60 ...... "r....`"
1725
1726 188: }
1727
1728 190: Method (T2)
1729
1730 0000035D: 14 10 54 32 5F 5F 00 ... "..T2__."
1731
1732 191: {
1733 192: EFGH ()
1734
1735 00000364: 45 46 47 48 ............ "EFGH"
1736
1737 193: Add (2, 7, Local0)
1738
1739 00000368: 72 0A 02 0A 07 60 ...... "r....`"
1740 194: }
1741
1742 Note that the AML code for T1 and T2 is essentially identical. When
1743 disassembling this code, the methods ABCD and EFGH must be known to the
1744 disassembler, otherwise it does not know how to handle the method invocations.
1745
1746 In other words, if ABCD and EFGH are actually external control methods
1747 appearing in an SSDT, the disassembler does not know what to do unless
1748 the owning SSDT has been loaded via the -e option.
1749 */
1750
1751 static char ExternalWarningPart1[600];
1752 static char ExternalWarningPart2[400];
1753 static char ExternalWarningPart3[400];
1754 static char ExternalWarningPart4[200];
1755
1756 void
AcpiDmUnresolvedWarning(UINT8 Type)1757 AcpiDmUnresolvedWarning (
1758 UINT8 Type)
1759 {
1760 char *Format;
1761 char Pad[] = " *";
1762 char NoPad[] = "";
1763
1764
1765 if (!AcpiGbl_NumExternalMethods)
1766 {
1767 return;
1768 }
1769
1770 if (AcpiGbl_NumExternalMethods == AcpiGbl_ResolvedExternalMethods)
1771 {
1772 return;
1773 }
1774
1775 Format = Type ? Pad : NoPad;
1776
1777 sprintf (ExternalWarningPart1,
1778 "%s iASL Warning: There %s %u external control method%s found during\n"
1779 "%s disassembly, but only %u %s resolved (%u unresolved). Additional\n"
1780 "%s ACPI tables may be required to properly disassemble the code. This\n"
1781 "%s resulting disassembler output file may not compile because the\n"
1782 "%s disassembler did not know how many arguments to assign to the\n"
1783 "%s unresolved methods. Note: SSDTs can be dynamically loaded at\n"
1784 "%s runtime and may or may not be available via the host OS.\n",
1785 Format, (AcpiGbl_NumExternalMethods != 1 ? "were" : "was"),
1786 AcpiGbl_NumExternalMethods, (AcpiGbl_NumExternalMethods != 1 ? "s" : ""),
1787 Format, AcpiGbl_ResolvedExternalMethods,
1788 (AcpiGbl_ResolvedExternalMethods != 1 ? "were" : "was"),
1789 (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods),
1790 Format, Format, Format, Format, Format);
1791
1792 sprintf (ExternalWarningPart2,
1793 "%s To specify the tables needed to resolve external control method\n"
1794 "%s references, the -e option can be used to specify the filenames.\n"
1795 "%s Example iASL invocations:\n"
1796 "%s iasl -e ssdt1.aml ssdt2.aml ssdt3.aml -d dsdt.aml\n"
1797 "%s iasl -e dsdt.aml ssdt2.aml -d ssdt1.aml\n"
1798 "%s iasl -e ssdt*.aml -d dsdt.aml\n",
1799 Format, Format, Format, Format, Format, Format);
1800
1801 sprintf (ExternalWarningPart3,
1802 "%s In addition, the -fe option can be used to specify a file containing\n"
1803 "%s control method external declarations with the associated method\n"
1804 "%s argument counts. Each line of the file must be of the form:\n"
1805 "%s External (<method pathname>, MethodObj, <argument count>)\n"
1806 "%s Invocation:\n"
1807 "%s iasl -fe refs.txt -d dsdt.aml\n",
1808 Format, Format, Format, Format, Format, Format);
1809
1810 sprintf (ExternalWarningPart4,
1811 "%s The following methods were unresolved and many not compile properly\n"
1812 "%s because the disassembler had to guess at the number of arguments\n"
1813 "%s required for each:\n",
1814 Format, Format, Format);
1815
1816 if (Type)
1817 {
1818 if (!AcpiGbl_ExternalFileList)
1819 {
1820 /* The -e option was not specified */
1821
1822 AcpiOsPrintf (" /*\n%s *\n%s *\n%s *\n%s */\n",
1823 ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3,
1824 ExternalWarningPart4);
1825 }
1826 else
1827 {
1828 /* The -e option was specified, but there are still some unresolved externals */
1829
1830 AcpiOsPrintf (" /*\n%s *\n%s *\n%s */\n",
1831 ExternalWarningPart1, ExternalWarningPart3, ExternalWarningPart4);
1832 }
1833 }
1834 else
1835 {
1836 if (!AcpiGbl_ExternalFileList)
1837 {
1838 /* The -e option was not specified */
1839
1840 fprintf (stderr, "\n%s\n%s\n%s\n",
1841 ExternalWarningPart1, ExternalWarningPart2, ExternalWarningPart3);
1842 }
1843 else
1844 {
1845 /* The -e option was specified, but there are still some unresolved externals */
1846
1847 fprintf (stderr, "\n%s\n%s\n",
1848 ExternalWarningPart1, ExternalWarningPart3);
1849 }
1850 }
1851 }
1852