Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/acpica/common/dmextern.c
48375 views
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 - 2025, 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 <contrib/dev/acpica/include/acpi.h>
153
#include <contrib/dev/acpica/include/accommon.h>
154
#include <contrib/dev/acpica/include/amlcode.h>
155
#include <contrib/dev/acpica/include/acnamesp.h>
156
#include <contrib/dev/acpica/include/acdisasm.h>
157
#include <contrib/dev/acpica/compiler/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 *
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1845