xref: /netbsd-src/sys/external/bsd/acpica/dist/debugger/dbnames.c (revision 987b04d624d6d5e25e3e80d683a4ebe80fe47dcf)
1 /*******************************************************************************
2  *
3  * Module Name: dbnames - Debugger commands for the acpi namespace
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2023, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "acpi.h"
45 #include "accommon.h"
46 #include "acnamesp.h"
47 #include "acdebug.h"
48 #include "acpredef.h"
49 #include "acinterp.h"
50 
51 
52 #define _COMPONENT          ACPI_CA_DEBUGGER
53         ACPI_MODULE_NAME    ("dbnames")
54 
55 
56 /* Local prototypes */
57 
58 static ACPI_STATUS
59 AcpiDbWalkAndMatchName (
60     ACPI_HANDLE             ObjHandle,
61     UINT32                  NestingLevel,
62     void                    *Context,
63     void                    **ReturnValue);
64 
65 static ACPI_STATUS
66 AcpiDbWalkForPredefinedNames (
67     ACPI_HANDLE             ObjHandle,
68     UINT32                  NestingLevel,
69     void                    *Context,
70     void                    **ReturnValue);
71 
72 static ACPI_STATUS
73 AcpiDbWalkForSpecificObjects (
74     ACPI_HANDLE             ObjHandle,
75     UINT32                  NestingLevel,
76     void                    *Context,
77     void                    **ReturnValue);
78 
79 static ACPI_STATUS
80 AcpiDbWalkForObjectCounts (
81     ACPI_HANDLE             ObjHandle,
82     UINT32                  NestingLevel,
83     void                    *Context,
84     void                    **ReturnValue);
85 
86 static ACPI_STATUS
87 AcpiDbIntegrityWalk (
88     ACPI_HANDLE             ObjHandle,
89     UINT32                  NestingLevel,
90     void                    *Context,
91     void                    **ReturnValue);
92 
93 static ACPI_STATUS
94 AcpiDbWalkForReferences (
95     ACPI_HANDLE             ObjHandle,
96     UINT32                  NestingLevel,
97     void                    *Context,
98     void                    **ReturnValue);
99 
100 static ACPI_STATUS
101 AcpiDbBusWalk (
102     ACPI_HANDLE             ObjHandle,
103     UINT32                  NestingLevel,
104     void                    *Context,
105     void                    **ReturnValue);
106 
107 /*
108  * Arguments for the Objects command
109  * These object types map directly to the ACPI_TYPES
110  */
111 static ACPI_DB_ARGUMENT_INFO    AcpiDbObjectTypes [] =
112 {
113     {"ANY"},
114     {"INTEGERS"},
115     {"STRINGS"},
116     {"BUFFERS"},
117     {"PACKAGES"},
118     {"FIELDS"},
119     {"DEVICES"},
120     {"EVENTS"},
121     {"METHODS"},
122     {"MUTEXES"},
123     {"REGIONS"},
124     {"POWERRESOURCES"},
125     {"PROCESSORS"},
126     {"THERMALZONES"},
127     {"BUFFERFIELDS"},
128     {"DDBHANDLES"},
129     {"DEBUG"},
130     {"REGIONFIELDS"},
131     {"BANKFIELDS"},
132     {"INDEXFIELDS"},
133     {"REFERENCES"},
134     {"ALIASES"},
135     {"METHODALIASES"},
136     {"NOTIFY"},
137     {"ADDRESSHANDLER"},
138     {"RESOURCE"},
139     {"RESOURCEFIELD"},
140     {"SCOPES"},
141     {NULL}           /* Must be null terminated */
142 };
143 
144 
145 /*******************************************************************************
146  *
147  * FUNCTION:    AcpiDbSetScope
148  *
149  * PARAMETERS:  Name                - New scope path
150  *
151  * RETURN:      Status
152  *
153  * DESCRIPTION: Set the "current scope" as maintained by this utility.
154  *              The scope is used as a prefix to ACPI paths.
155  *
156  ******************************************************************************/
157 
158 void
159 AcpiDbSetScope (
160     char                    *Name)
161 {
162     ACPI_STATUS             Status;
163     ACPI_NAMESPACE_NODE     *Node;
164 
165 
166     if (!Name || Name[0] == 0)
167     {
168         AcpiOsPrintf ("Current scope: %s\n", AcpiGbl_DbScopeBuf);
169         return;
170     }
171 
172     AcpiDbPrepNamestring (Name);
173 
174     if (ACPI_IS_ROOT_PREFIX (Name[0]))
175     {
176         /* Validate new scope from the root */
177 
178         Status = AcpiNsGetNode (AcpiGbl_RootNode, Name,
179             ACPI_NS_NO_UPSEARCH, &Node);
180         if (ACPI_FAILURE (Status))
181         {
182             goto ErrorExit;
183         }
184 
185         AcpiGbl_DbScopeBuf[0] = 0;
186     }
187     else
188     {
189         /* Validate new scope relative to old scope */
190 
191         Status = AcpiNsGetNode (AcpiGbl_DbScopeNode, Name,
192             ACPI_NS_NO_UPSEARCH, &Node);
193         if (ACPI_FAILURE (Status))
194         {
195             goto ErrorExit;
196         }
197     }
198 
199     /* Build the final pathname */
200 
201     if (AcpiUtSafeStrcat (AcpiGbl_DbScopeBuf, sizeof (AcpiGbl_DbScopeBuf),
202         Name))
203     {
204         Status = AE_BUFFER_OVERFLOW;
205         goto ErrorExit;
206     }
207 
208     if (AcpiUtSafeStrcat (AcpiGbl_DbScopeBuf, sizeof (AcpiGbl_DbScopeBuf),
209 	    __UNCONST("\\")))
210     {
211         Status = AE_BUFFER_OVERFLOW;
212         goto ErrorExit;
213     }
214 
215     AcpiGbl_DbScopeNode = Node;
216     AcpiOsPrintf ("New scope: %s\n", AcpiGbl_DbScopeBuf);
217     return;
218 
219 ErrorExit:
220 
221     AcpiOsPrintf ("Could not attach scope: %s, %s\n",
222         Name, AcpiFormatException (Status));
223 }
224 
225 
226 /*******************************************************************************
227  *
228  * FUNCTION:    AcpiDbDumpNamespace
229  *
230  * PARAMETERS:  StartArg        - Node to begin namespace dump
231  *              DepthArg        - Maximum tree depth to be dumped
232  *
233  * RETURN:      None
234  *
235  * DESCRIPTION: Dump entire namespace or a subtree. Each node is displayed
236  *              with type and other information.
237  *
238  ******************************************************************************/
239 
240 void
241 AcpiDbDumpNamespace (
242     char                    *StartArg,
243     char                    *DepthArg)
244 {
245     ACPI_HANDLE             SubtreeEntry = AcpiGbl_RootNode;
246     UINT32                  MaxDepth = ACPI_UINT32_MAX;
247 
248 
249     /* No argument given, just start at the root and dump entire namespace */
250 
251     if (StartArg)
252     {
253         SubtreeEntry = AcpiDbConvertToNode (StartArg);
254         if (!SubtreeEntry)
255         {
256             return;
257         }
258 
259         /* Now we can check for the depth argument */
260 
261         if (DepthArg)
262         {
263             MaxDepth = strtoul (DepthArg, NULL, 0);
264         }
265     }
266 
267     AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);
268 
269     if (((ACPI_NAMESPACE_NODE *) SubtreeEntry)->Parent)
270     {
271         AcpiOsPrintf ("ACPI Namespace (from %4.4s (%p) subtree):\n",
272             ((ACPI_NAMESPACE_NODE *) SubtreeEntry)->Name.Ascii, SubtreeEntry);
273     }
274     else
275     {
276         AcpiOsPrintf ("ACPI Namespace (from %s):\n",
277             ACPI_NAMESPACE_ROOT);
278     }
279 
280     /* Display the subtree */
281 
282     AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);
283     AcpiNsDumpObjects (ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, MaxDepth,
284         ACPI_OWNER_ID_MAX, SubtreeEntry);
285     AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
286 }
287 
288 
289 /*******************************************************************************
290  *
291  * FUNCTION:    AcpiDbDumpNamespacePaths
292  *
293  * PARAMETERS:  None
294  *
295  * RETURN:      None
296  *
297  * DESCRIPTION: Dump entire namespace with full object pathnames and object
298  *              type information. Alternative to "namespace" command.
299  *
300  ******************************************************************************/
301 
302 void
303 AcpiDbDumpNamespacePaths (
304     void)
305 {
306 
307     AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);
308     AcpiOsPrintf ("ACPI Namespace (from root):\n");
309 
310     /* Display the entire namespace */
311 
312     AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);
313     AcpiNsDumpObjectPaths (ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY,
314         ACPI_UINT32_MAX, ACPI_OWNER_ID_MAX, AcpiGbl_RootNode);
315 
316     AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
317 }
318 
319 
320 /*******************************************************************************
321  *
322  * FUNCTION:    AcpiDbDumpNamespaceByOwner
323  *
324  * PARAMETERS:  OwnerArg        - Owner ID whose nodes will be displayed
325  *              DepthArg        - Maximum tree depth to be dumped
326  *
327  * RETURN:      None
328  *
329  * DESCRIPTION: Dump elements of the namespace that are owned by the OwnerId.
330  *
331  ******************************************************************************/
332 
333 void
334 AcpiDbDumpNamespaceByOwner (
335     char                    *OwnerArg,
336     char                    *DepthArg)
337 {
338     ACPI_HANDLE             SubtreeEntry = AcpiGbl_RootNode;
339     UINT32                  MaxDepth = ACPI_UINT32_MAX;
340     ACPI_OWNER_ID           OwnerId;
341 
342 
343     OwnerId = (ACPI_OWNER_ID) strtoul (OwnerArg, NULL, 0);
344 
345     /* Now we can check for the depth argument */
346 
347     if (DepthArg)
348     {
349         MaxDepth = strtoul (DepthArg, NULL, 0);
350     }
351 
352     AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);
353     AcpiOsPrintf ("ACPI Namespace by owner %X:\n", OwnerId);
354 
355     /* Display the subtree */
356 
357     AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);
358     AcpiNsDumpObjects (ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, MaxDepth,
359         OwnerId, SubtreeEntry);
360     AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
361 }
362 
363 
364 /*******************************************************************************
365  *
366  * FUNCTION:    AcpiDbWalkAndMatchName
367  *
368  * PARAMETERS:  Callback from WalkNamespace
369  *
370  * RETURN:      Status
371  *
372  * DESCRIPTION: Find a particular name/names within the namespace. Wildcards
373  *              are supported -- '?' matches any character.
374  *
375  ******************************************************************************/
376 
377 static ACPI_STATUS
378 AcpiDbWalkAndMatchName (
379     ACPI_HANDLE             ObjHandle,
380     UINT32                  NestingLevel,
381     void                    *Context,
382     void                    **ReturnValue)
383 {
384     ACPI_STATUS             Status;
385     char                    *RequestedName = (char *) Context;
386     UINT32                  i;
387     ACPI_BUFFER             Buffer;
388     ACPI_WALK_INFO          Info;
389 
390 
391     /* Check for a name match */
392 
393     for (i = 0; i < 4; i++)
394     {
395         /* Wildcard support */
396 
397         if ((RequestedName[i] != '?') &&
398             (RequestedName[i] != ((ACPI_NAMESPACE_NODE *)
399                 ObjHandle)->Name.Ascii[i]))
400         {
401             /* No match, just exit */
402 
403             return (AE_OK);
404         }
405     }
406 
407     /* Get the full pathname to this object */
408 
409     Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
410     Status = AcpiNsHandleToPathname (ObjHandle, &Buffer, TRUE);
411     if (ACPI_FAILURE (Status))
412     {
413         AcpiOsPrintf ("Could Not get pathname for object %p\n",
414             ObjHandle);
415     }
416     else
417     {
418         Info.Count = 0;
419         Info.OwnerId = ACPI_OWNER_ID_MAX;
420         Info.DebugLevel = ACPI_UINT32_MAX;
421         Info.DisplayType = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT;
422 
423         AcpiOsPrintf ("%32s", (char *) Buffer.Pointer);
424         (void) AcpiNsDumpOneObject (ObjHandle, NestingLevel, &Info, NULL);
425         ACPI_FREE (Buffer.Pointer);
426     }
427 
428     return (AE_OK);
429 }
430 
431 
432 /*******************************************************************************
433  *
434  * FUNCTION:    AcpiDbFindNameInNamespace
435  *
436  * PARAMETERS:  NameArg         - The 4-character ACPI name to find.
437  *                                wildcards are supported.
438  *
439  * RETURN:      None
440  *
441  * DESCRIPTION: Search the namespace for a given name (with wildcards)
442  *
443  ******************************************************************************/
444 
445 ACPI_STATUS
446 AcpiDbFindNameInNamespace (
447     char                    *NameArg)
448 {
449     char                    AcpiName[5] = "____";
450     char                    *AcpiNamePtr = AcpiName;
451 
452 
453     if (strlen (NameArg) > ACPI_NAMESEG_SIZE)
454     {
455         AcpiOsPrintf ("Name must be no longer than 4 characters\n");
456         return (AE_OK);
457     }
458 
459     /* Pad out name with underscores as necessary to create a 4-char name */
460 
461     AcpiUtStrupr (NameArg);
462     while (*NameArg)
463     {
464         *AcpiNamePtr = *NameArg;
465         AcpiNamePtr++;
466         NameArg++;
467     }
468 
469     /* Walk the namespace from the root */
470 
471     (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
472         ACPI_UINT32_MAX, AcpiDbWalkAndMatchName, NULL, AcpiName, NULL);
473 
474     AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
475     return (AE_OK);
476 }
477 
478 
479 /*******************************************************************************
480  *
481  * FUNCTION:    AcpiDbWalkForPredefinedNames
482  *
483  * PARAMETERS:  Callback from WalkNamespace
484  *
485  * RETURN:      Status
486  *
487  * DESCRIPTION: Detect and display predefined ACPI names (names that start with
488  *              an underscore)
489  *
490  ******************************************************************************/
491 
492 static ACPI_STATUS
493 AcpiDbWalkForPredefinedNames (
494     ACPI_HANDLE             ObjHandle,
495     UINT32                  NestingLevel,
496     void                    *Context,
497     void                    **ReturnValue)
498 {
499     ACPI_NAMESPACE_NODE         *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
500     UINT32                      *Count = (UINT32 *) Context;
501     const ACPI_PREDEFINED_INFO  *Predefined;
502     const ACPI_PREDEFINED_INFO  *Package = NULL;
503     char                        *Pathname;
504     char                        StringBuffer[48];
505 
506 
507     Predefined = AcpiUtMatchPredefinedMethod (Node->Name.Ascii);
508     if (!Predefined)
509     {
510         return (AE_OK);
511     }
512 
513     Pathname = AcpiNsGetNormalizedPathname (Node, TRUE);
514     if (!Pathname)
515     {
516         return (AE_OK);
517     }
518 
519     /* If method returns a package, the info is in the next table entry */
520 
521     if (Predefined->Info.ExpectedBtypes & ACPI_RTYPE_PACKAGE)
522     {
523         Package = Predefined + 1;
524     }
525 
526     AcpiUtGetExpectedReturnTypes (StringBuffer,
527         Predefined->Info.ExpectedBtypes);
528 
529     AcpiOsPrintf ("%-32s Arguments %X, Return Types: %s", Pathname,
530         METHOD_GET_ARG_COUNT (Predefined->Info.ArgumentList),
531         StringBuffer);
532 
533     if (Package)
534     {
535         AcpiOsPrintf (" (PkgType %2.2X, ObjType %2.2X, Count %2.2X)",
536             Package->RetInfo.Type, Package->RetInfo.ObjectType1,
537             Package->RetInfo.Count1);
538     }
539 
540     AcpiOsPrintf("\n");
541 
542     /* Check that the declared argument count matches the ACPI spec */
543 
544     AcpiNsCheckAcpiCompliance (Pathname, Node, Predefined);
545 
546     ACPI_FREE (Pathname);
547     (*Count)++;
548     return (AE_OK);
549 }
550 
551 
552 /*******************************************************************************
553  *
554  * FUNCTION:    AcpiDbCheckPredefinedNames
555  *
556  * PARAMETERS:  None
557  *
558  * RETURN:      None
559  *
560  * DESCRIPTION: Validate all predefined names in the namespace
561  *
562  ******************************************************************************/
563 
564 void
565 AcpiDbCheckPredefinedNames (
566     void)
567 {
568     UINT32                  Count = 0;
569 
570 
571     /* Search all nodes in namespace */
572 
573     (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
574         ACPI_UINT32_MAX, AcpiDbWalkForPredefinedNames,
575         NULL, (void *) &Count, NULL);
576 
577     AcpiOsPrintf ("Found %u predefined names in the namespace\n", Count);
578 }
579 
580 
581 /*******************************************************************************
582  *
583  * FUNCTION:    AcpiDbWalkForObjectCounts
584  *
585  * PARAMETERS:  Callback from WalkNamespace
586  *
587  * RETURN:      Status
588  *
589  * DESCRIPTION: Display short info about objects in the namespace
590  *
591  ******************************************************************************/
592 
593 static ACPI_STATUS
594 AcpiDbWalkForObjectCounts (
595     ACPI_HANDLE             ObjHandle,
596     UINT32                  NestingLevel,
597     void                    *Context,
598     void                    **ReturnValue)
599 {
600     ACPI_OBJECT_INFO        *Info = (ACPI_OBJECT_INFO *) Context;
601     ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
602 
603 
604     if (Node->Type > ACPI_TYPE_NS_NODE_MAX)
605     {
606         AcpiOsPrintf ("[%4.4s]: Unknown object type %X\n",
607             Node->Name.Ascii, Node->Type);
608     }
609     else
610     {
611         Info->Types[Node->Type]++;
612     }
613 
614     return (AE_OK);
615 }
616 
617 
618 /*******************************************************************************
619  *
620  * FUNCTION:    AcpiDbWalkForFields
621  *
622  * PARAMETERS:  Callback from WalkNamespace
623  *
624  * RETURN:      Status
625  *
626  * DESCRIPTION: Display short info about objects in the namespace
627  *
628  ******************************************************************************/
629 
630 static ACPI_STATUS
631 AcpiDbWalkForFields (
632     ACPI_HANDLE             ObjHandle,
633     UINT32                  NestingLevel,
634     void                    *Context,
635     void                    **ReturnValue)
636 {
637     ACPI_OBJECT             *RetValue;
638     ACPI_REGION_WALK_INFO   *Info = (ACPI_REGION_WALK_INFO *) Context;
639     ACPI_BUFFER             Buffer;
640     ACPI_STATUS             Status;
641     ACPI_NAMESPACE_NODE     *Node = AcpiNsValidateHandle (ObjHandle);
642 
643 
644     if (!Node)
645     {
646        return (AE_OK);
647     }
648     if (Node->Object->Field.RegionObj->Region.SpaceId != Info->AddressSpaceId)
649     {
650        return (AE_OK);
651     }
652 
653     Info->Count++;
654 
655     /* Get and display the full pathname to this object */
656 
657     Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
658     Status = AcpiNsHandleToPathname (ObjHandle, &Buffer, TRUE);
659     if (ACPI_FAILURE (Status))
660     {
661         AcpiOsPrintf ("Could Not get pathname for object %p\n", ObjHandle);
662         return (AE_OK);
663     }
664 
665     AcpiOsPrintf ("%s ", (char *) Buffer.Pointer);
666     ACPI_FREE (Buffer.Pointer);
667 
668     Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
669     Status = AcpiEvaluateObject (ObjHandle, NULL, NULL, &Buffer);
670     if (ACPI_FAILURE (Status))
671     {
672         AcpiOsPrintf ("Could Not evaluate object %p\n", ObjHandle);
673         return (AE_OK);
674     }
675 
676     /*
677      * Since this is a field unit, surround the output in braces
678      */
679     AcpiOsPrintf ("{");
680 
681     RetValue = (ACPI_OBJECT *) Buffer.Pointer;
682     switch (RetValue->Type)
683     {
684         case ACPI_TYPE_INTEGER:
685 
686             AcpiOsPrintf ("%8.8X%8.8X", ACPI_FORMAT_UINT64 (RetValue->Integer.Value));
687             break;
688 
689         case ACPI_TYPE_BUFFER:
690 
691             AcpiUtDumpBuffer (RetValue->Buffer.Pointer,
692                 RetValue->Buffer.Length, DB_DISPLAY_DATA_ONLY | DB_BYTE_DISPLAY, 0);
693             break;
694 
695         default:
696 
697             break;
698     }
699 
700     AcpiOsPrintf ("}\n");
701 
702     ACPI_FREE (Buffer.Pointer);
703     return (AE_OK);
704 }
705 
706 
707 /*******************************************************************************
708  *
709  * FUNCTION:    AcpiDbWalkForSpecificObjects
710  *
711  * PARAMETERS:  Callback from WalkNamespace
712  *
713  * RETURN:      Status
714  *
715  * DESCRIPTION: Display short info about objects in the namespace
716  *
717  ******************************************************************************/
718 
719 static ACPI_STATUS
720 AcpiDbWalkForSpecificObjects (
721     ACPI_HANDLE             ObjHandle,
722     UINT32                  NestingLevel,
723     void                    *Context,
724     void                    **ReturnValue)
725 {
726     ACPI_WALK_INFO          *Info = (ACPI_WALK_INFO *) Context;
727     ACPI_BUFFER             Buffer;
728     ACPI_STATUS             Status;
729 
730 
731     Info->Count++;
732 
733     /* Get and display the full pathname to this object */
734 
735     Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
736     Status = AcpiNsHandleToPathname (ObjHandle, &Buffer, TRUE);
737     if (ACPI_FAILURE (Status))
738     {
739         AcpiOsPrintf ("Could Not get pathname for object %p\n", ObjHandle);
740         return (AE_OK);
741     }
742 
743     AcpiOsPrintf ("%32s", (char *) Buffer.Pointer);
744     ACPI_FREE (Buffer.Pointer);
745 
746     /* Dump short info about the object */
747 
748     (void) AcpiNsDumpOneObject (ObjHandle, NestingLevel, Info, NULL);
749     return (AE_OK);
750 }
751 
752 
753 /*******************************************************************************
754  *
755  * FUNCTION:    AcpiDbDisplayObjects
756  *
757  * PARAMETERS:  ObjTypeArg          - Type of object to display
758  *              DisplayCountArg     - Max depth to display
759  *
760  * RETURN:      None
761  *
762  * DESCRIPTION: Display objects in the namespace of the requested type
763  *
764  ******************************************************************************/
765 
766 ACPI_STATUS
767 AcpiDbDisplayObjects (
768     char                    *ObjTypeArg,
769     char                    *DisplayCountArg)
770 {
771     ACPI_WALK_INFO          Info;
772     ACPI_OBJECT_TYPE        Type;
773     ACPI_OBJECT_INFO        *ObjectInfo;
774     UINT32                  i;
775     UINT32                  TotalObjects = 0;
776 
777 
778     /* No argument means display summary/count of all object types */
779 
780     if (!ObjTypeArg)
781     {
782         ObjectInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_OBJECT_INFO));
783 
784         if (!ObjectInfo)
785                 return (AE_NO_MEMORY);
786 
787         /* Walk the namespace from the root */
788 
789         (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
790             ACPI_UINT32_MAX, AcpiDbWalkForObjectCounts, NULL,
791             (void *) ObjectInfo, NULL);
792 
793         AcpiOsPrintf ("\nSummary of namespace objects:\n\n");
794 
795         for (i = 0; i < ACPI_TOTAL_TYPES; i++)
796         {
797             AcpiOsPrintf ("%8u   %s\n", ObjectInfo->Types[i],
798                 AcpiUtGetTypeName (i));
799 
800             TotalObjects += ObjectInfo->Types[i];
801         }
802 
803         AcpiOsPrintf ("\n%8u   Total namespace objects\n\n",
804             TotalObjects);
805 
806         ACPI_FREE (ObjectInfo);
807         return (AE_OK);
808     }
809 
810     /* Get the object type */
811 
812     Type = AcpiDbMatchArgument (ObjTypeArg, AcpiDbObjectTypes);
813     if (Type == ACPI_TYPE_NOT_FOUND)
814     {
815         AcpiOsPrintf ("Invalid or unsupported argument\n");
816         return (AE_OK);
817     }
818 
819     AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);
820     AcpiOsPrintf (
821         "Objects of type [%s] defined in the current ACPI Namespace:\n",
822         AcpiUtGetTypeName (Type));
823 
824     AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);
825 
826     Info.Count = 0;
827     Info.OwnerId = ACPI_OWNER_ID_MAX;
828     Info.DebugLevel = ACPI_UINT32_MAX;
829     Info.DisplayType = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT;
830 
831     /* Walk the namespace from the root */
832 
833     (void) AcpiWalkNamespace (Type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
834         AcpiDbWalkForSpecificObjects, NULL, (void *) &Info, NULL);
835 
836     AcpiOsPrintf (
837         "\nFound %u objects of type [%s] in the current ACPI Namespace\n",
838         Info.Count, AcpiUtGetTypeName (Type));
839 
840     AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
841     return (AE_OK);
842 }
843 
844 
845 /*******************************************************************************
846  *
847  * FUNCTION:    AcpiDbDisplayFields
848  *
849  * PARAMETERS:  ObjTypeArg          - Type of object to display
850  *              DisplayCountArg     - Max depth to display
851  *
852  * RETURN:      None
853  *
854  * DESCRIPTION: Display objects in the namespace of the requested type
855  *
856  ******************************************************************************/
857 
858 ACPI_STATUS
859 AcpiDbDisplayFields (
860     UINT32                  AddressSpaceId)
861 {
862     ACPI_REGION_WALK_INFO  Info;
863 
864 
865     Info.Count = 0;
866     Info.OwnerId = ACPI_OWNER_ID_MAX;
867     Info.DebugLevel = ACPI_UINT32_MAX;
868     Info.DisplayType = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT;
869     Info.AddressSpaceId = AddressSpaceId;
870 
871     /* Walk the namespace from the root */
872 
873     (void) AcpiWalkNamespace (ACPI_TYPE_LOCAL_REGION_FIELD, ACPI_ROOT_OBJECT,
874           ACPI_UINT32_MAX, AcpiDbWalkForFields, NULL,
875           (void *) &Info, NULL);
876 
877     return (AE_OK);
878 }
879 
880 
881 /*******************************************************************************
882  *
883  * FUNCTION:    AcpiDbIntegrityWalk
884  *
885  * PARAMETERS:  Callback from WalkNamespace
886  *
887  * RETURN:      Status
888  *
889  * DESCRIPTION: Examine one NS node for valid values.
890  *
891  ******************************************************************************/
892 
893 static ACPI_STATUS
894 AcpiDbIntegrityWalk (
895     ACPI_HANDLE             ObjHandle,
896     UINT32                  NestingLevel,
897     void                    *Context,
898     void                    **ReturnValue)
899 {
900     ACPI_INTEGRITY_INFO     *Info = (ACPI_INTEGRITY_INFO *) Context;
901     ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
902     ACPI_OPERAND_OBJECT     *Object;
903     BOOLEAN                 Alias = TRUE;
904 
905 
906     Info->Nodes++;
907 
908     /* Verify the NS node, and dereference aliases */
909 
910     while (Alias)
911     {
912         if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED)
913         {
914             AcpiOsPrintf (
915                 "Invalid Descriptor Type for Node %p [%s] - "
916                 "is %2.2X should be %2.2X\n",
917                 Node, AcpiUtGetDescriptorName (Node),
918                 ACPI_GET_DESCRIPTOR_TYPE (Node), ACPI_DESC_TYPE_NAMED);
919             return (AE_OK);
920         }
921 
922         if ((Node->Type == ACPI_TYPE_LOCAL_ALIAS)  ||
923             (Node->Type == ACPI_TYPE_LOCAL_METHOD_ALIAS))
924         {
925             Node = (ACPI_NAMESPACE_NODE *) Node->Object;
926         }
927         else
928         {
929             Alias = FALSE;
930         }
931     }
932 
933     if (Node->Type > ACPI_TYPE_LOCAL_MAX)
934     {
935         AcpiOsPrintf ("Invalid Object Type for Node %p, Type = %X\n",
936             Node, Node->Type);
937         return (AE_OK);
938     }
939 
940     if (!AcpiUtValidNameseg (Node->Name.Ascii))
941     {
942         AcpiOsPrintf ("Invalid AcpiName for Node %p\n", Node);
943         return (AE_OK);
944     }
945 
946     Object = AcpiNsGetAttachedObject (Node);
947     if (Object)
948     {
949         Info->Objects++;
950         if (ACPI_GET_DESCRIPTOR_TYPE (Object) != ACPI_DESC_TYPE_OPERAND)
951         {
952             AcpiOsPrintf ("Invalid Descriptor Type for Object %p [%s]\n",
953                 Object, AcpiUtGetDescriptorName (Object));
954         }
955     }
956 
957     return (AE_OK);
958 }
959 
960 
961 /*******************************************************************************
962  *
963  * FUNCTION:    AcpiDbCheckIntegrity
964  *
965  * PARAMETERS:  None
966  *
967  * RETURN:      None
968  *
969  * DESCRIPTION: Check entire namespace for data structure integrity
970  *
971  ******************************************************************************/
972 
973 void
974 AcpiDbCheckIntegrity (
975     void)
976 {
977     ACPI_INTEGRITY_INFO     Info = {0,0};
978 
979     /* Search all nodes in namespace */
980 
981     (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
982         ACPI_UINT32_MAX, AcpiDbIntegrityWalk, NULL, (void *) &Info, NULL);
983 
984     AcpiOsPrintf ("Verified %u namespace nodes with %u Objects\n",
985         Info.Nodes, Info.Objects);
986 }
987 
988 
989 /*******************************************************************************
990  *
991  * FUNCTION:    AcpiDbWalkForReferences
992  *
993  * PARAMETERS:  Callback from WalkNamespace
994  *
995  * RETURN:      Status
996  *
997  * DESCRIPTION: Check if this namespace object refers to the target object
998  *              that is passed in as the context value.
999  *
1000  * Note: Currently doesn't check subobjects within the Node's object
1001  *
1002  ******************************************************************************/
1003 
1004 static ACPI_STATUS
1005 AcpiDbWalkForReferences (
1006     ACPI_HANDLE             ObjHandle,
1007     UINT32                  NestingLevel,
1008     void                    *Context,
1009     void                    **ReturnValue)
1010 {
1011     ACPI_OPERAND_OBJECT     *ObjDesc = (ACPI_OPERAND_OBJECT  *) Context;
1012     ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
1013 
1014 
1015     /* Check for match against the namespace node itself */
1016 
1017     if (Node == (void *) ObjDesc)
1018     {
1019         AcpiOsPrintf ("Object is a Node [%4.4s]\n",
1020             AcpiUtGetNodeName (Node));
1021     }
1022 
1023     /* Check for match against the object attached to the node */
1024 
1025     if (AcpiNsGetAttachedObject (Node) == ObjDesc)
1026     {
1027         AcpiOsPrintf ("Reference at Node->Object %p [%4.4s]\n",
1028             Node, AcpiUtGetNodeName (Node));
1029     }
1030 
1031     return (AE_OK);
1032 }
1033 
1034 
1035 /*******************************************************************************
1036  *
1037  * FUNCTION:    AcpiDbFindReferences
1038  *
1039  * PARAMETERS:  ObjectArg       - String with hex value of the object
1040  *
1041  * RETURN:      None
1042  *
1043  * DESCRIPTION: Search namespace for all references to the input object
1044  *
1045  ******************************************************************************/
1046 
1047 void
1048 AcpiDbFindReferences (
1049     char                    *ObjectArg)
1050 {
1051     ACPI_OPERAND_OBJECT     *ObjDesc;
1052     ACPI_SIZE               Address;
1053 
1054 
1055     /* Convert string to object pointer */
1056 
1057     Address = strtoul (ObjectArg, NULL, 16);
1058     ObjDesc = ACPI_TO_POINTER (Address);
1059 
1060     /* Search all nodes in namespace */
1061 
1062     (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
1063         ACPI_UINT32_MAX, AcpiDbWalkForReferences, NULL,
1064         (void *) ObjDesc, NULL);
1065 }
1066 
1067 
1068 /*******************************************************************************
1069  *
1070  * FUNCTION:    AcpiDbBusWalk
1071  *
1072  * PARAMETERS:  Callback from WalkNamespace
1073  *
1074  * RETURN:      Status
1075  *
1076  * DESCRIPTION: Display info about device objects that have a corresponding
1077  *              _PRT method.
1078  *
1079  ******************************************************************************/
1080 
1081 static ACPI_STATUS
1082 AcpiDbBusWalk (
1083     ACPI_HANDLE             ObjHandle,
1084     UINT32                  NestingLevel,
1085     void                    *Context,
1086     void                    **ReturnValue)
1087 {
1088     ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
1089     ACPI_STATUS             Status;
1090     ACPI_BUFFER             Buffer;
1091     ACPI_NAMESPACE_NODE     *TempNode;
1092     ACPI_DEVICE_INFO        *Info;
1093     UINT32                  i;
1094 
1095 
1096     if ((Node->Type != ACPI_TYPE_DEVICE) &&
1097         (Node->Type != ACPI_TYPE_PROCESSOR))
1098     {
1099         return (AE_OK);
1100     }
1101 
1102     /* Exit if there is no _PRT under this device */
1103 
1104     Status = AcpiGetHandle (Node, METHOD_NAME__PRT,
1105         ACPI_CAST_PTR (ACPI_HANDLE, &TempNode));
1106     if (ACPI_FAILURE (Status))
1107     {
1108         return (AE_OK);
1109     }
1110 
1111     /* Get the full path to this device object */
1112 
1113     Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
1114     Status = AcpiNsHandleToPathname (ObjHandle, &Buffer, TRUE);
1115     if (ACPI_FAILURE (Status))
1116     {
1117         AcpiOsPrintf ("Could Not get pathname for object %p\n",
1118             ObjHandle);
1119         return (AE_OK);
1120     }
1121 
1122     Status = AcpiGetObjectInfo (ObjHandle, &Info);
1123     if (ACPI_FAILURE (Status))
1124     {
1125         return (AE_OK);
1126     }
1127 
1128     /* Display the full path */
1129 
1130     AcpiOsPrintf ("%-32s Type %X", (char *) Buffer.Pointer, Node->Type);
1131     ACPI_FREE (Buffer.Pointer);
1132 
1133     if (Info->Flags & ACPI_PCI_ROOT_BRIDGE)
1134     {
1135         AcpiOsPrintf ("  - Is PCI Root Bridge");
1136     }
1137     AcpiOsPrintf ("\n");
1138 
1139     /* _PRT info */
1140 
1141     AcpiOsPrintf ("_PRT: %p\n", TempNode);
1142 
1143     /* Dump _ADR, _HID, _UID, _CID */
1144 
1145     if (Info->Valid & ACPI_VALID_ADR)
1146     {
1147         AcpiOsPrintf ("_ADR: %8.8X%8.8X\n",
1148             ACPI_FORMAT_UINT64 (Info->Address));
1149     }
1150     else
1151     {
1152         AcpiOsPrintf ("_ADR: <Not Present>\n");
1153     }
1154 
1155     if (Info->Valid & ACPI_VALID_HID)
1156     {
1157         AcpiOsPrintf ("_HID: %s\n", Info->HardwareId.String);
1158     }
1159     else
1160     {
1161         AcpiOsPrintf ("_HID: <Not Present>\n");
1162     }
1163 
1164     if (Info->Valid & ACPI_VALID_UID)
1165     {
1166         AcpiOsPrintf ("_UID: %s\n", Info->UniqueId.String);
1167     }
1168     else
1169     {
1170         AcpiOsPrintf ("_UID: <Not Present>\n");
1171     }
1172 
1173     if (Info->Valid & ACPI_VALID_CID)
1174     {
1175         for (i = 0; i < Info->CompatibleIdList.Count; i++)
1176         {
1177             AcpiOsPrintf ("_CID: %s\n",
1178                 Info->CompatibleIdList.Ids[i].String);
1179         }
1180     }
1181     else
1182     {
1183         AcpiOsPrintf ("_CID: <Not Present>\n");
1184     }
1185 
1186     ACPI_FREE (Info);
1187     return (AE_OK);
1188 }
1189 
1190 
1191 /*******************************************************************************
1192  *
1193  * FUNCTION:    AcpiDbGetBusInfo
1194  *
1195  * PARAMETERS:  None
1196  *
1197  * RETURN:      None
1198  *
1199  * DESCRIPTION: Display info about system buses.
1200  *
1201  ******************************************************************************/
1202 
1203 void
1204 AcpiDbGetBusInfo (
1205     void)
1206 {
1207     /* Search all nodes in namespace */
1208 
1209     (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
1210         ACPI_UINT32_MAX, AcpiDbBusWalk, NULL, NULL, NULL);
1211 }
1212