1 /******************************************************************************
2  *
3  * Module Name: nsdump - table dumping routines for debug
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2014, 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 MERCHANTIBILITY 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 #define __NSDUMP_C__
45 
46 #include "acpi.h"
47 #include "accommon.h"
48 #include "acnamesp.h"
49 #include "acoutput.h"
50 
51 
52 #define _COMPONENT          ACPI_NAMESPACE
53         ACPI_MODULE_NAME    ("nsdump")
54 
55 /* Local prototypes */
56 
57 #ifdef ACPI_OBSOLETE_FUNCTIONS
58 void
59 AcpiNsDumpRootDevices (
60     void);
61 
62 static ACPI_STATUS
63 AcpiNsDumpOneDevice (
64     ACPI_HANDLE             ObjHandle,
65     UINT32                  Level,
66     void                    *Context,
67     void                    **ReturnValue);
68 #endif
69 
70 
71 #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
72 
73 static ACPI_STATUS
74 AcpiNsDumpOneObjectPath (
75     ACPI_HANDLE             ObjHandle,
76     UINT32                  Level,
77     void                    *Context,
78     void                    **ReturnValue);
79 
80 static ACPI_STATUS
81 AcpiNsGetMaxDepth (
82     ACPI_HANDLE             ObjHandle,
83     UINT32                  Level,
84     void                    *Context,
85     void                    **ReturnValue);
86 
87 
88 /*******************************************************************************
89  *
90  * FUNCTION:    AcpiNsPrintPathname
91  *
92  * PARAMETERS:  NumSegments         - Number of ACPI name segments
93  *              Pathname            - The compressed (internal) path
94  *
95  * RETURN:      None
96  *
97  * DESCRIPTION: Print an object's full namespace pathname
98  *
99  ******************************************************************************/
100 
101 void
102 AcpiNsPrintPathname (
103     UINT32                  NumSegments,
104     char                    *Pathname)
105 {
106     UINT32                  i;
107 
108 
109     ACPI_FUNCTION_NAME (NsPrintPathname);
110 
111 
112     /* Check if debug output enabled */
113 
114     if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_NAMES, ACPI_NAMESPACE))
115     {
116         return;
117     }
118 
119     /* Print the entire name */
120 
121     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "["));
122 
123     while (NumSegments)
124     {
125         for (i = 0; i < 4; i++)
126         {
127             ACPI_IS_PRINT (Pathname[i]) ?
128                 AcpiOsPrintf ("%c", Pathname[i]) :
129                 AcpiOsPrintf ("?");
130         }
131 
132         Pathname += ACPI_NAME_SIZE;
133         NumSegments--;
134         if (NumSegments)
135         {
136             AcpiOsPrintf (".");
137         }
138     }
139 
140     AcpiOsPrintf ("]\n");
141 }
142 
143 
144 /*******************************************************************************
145  *
146  * FUNCTION:    AcpiNsDumpPathname
147  *
148  * PARAMETERS:  Handle              - Object
149  *              Msg                 - Prefix message
150  *              Level               - Desired debug level
151  *              Component           - Caller's component ID
152  *
153  * RETURN:      None
154  *
155  * DESCRIPTION: Print an object's full namespace pathname
156  *              Manages allocation/freeing of a pathname buffer
157  *
158  ******************************************************************************/
159 
160 void
161 AcpiNsDumpPathname (
162     ACPI_HANDLE             Handle,
163     char                    *Msg,
164     UINT32                  Level,
165     UINT32                  Component)
166 {
167 
168     ACPI_FUNCTION_TRACE (NsDumpPathname);
169 
170 
171     /* Do this only if the requested debug level and component are enabled */
172 
173     if (!ACPI_IS_DEBUG_ENABLED (Level, Component))
174     {
175         return_VOID;
176     }
177 
178     /* Convert handle to a full pathname and print it (with supplied message) */
179 
180     AcpiNsPrintNodePathname (Handle, Msg);
181     AcpiOsPrintf ("\n");
182     return_VOID;
183 }
184 
185 
186 /*******************************************************************************
187  *
188  * FUNCTION:    AcpiNsDumpOneObject
189  *
190  * PARAMETERS:  ObjHandle           - Node to be dumped
191  *              Level               - Nesting level of the handle
192  *              Context             - Passed into WalkNamespace
193  *              ReturnValue         - Not used
194  *
195  * RETURN:      Status
196  *
197  * DESCRIPTION: Dump a single Node
198  *              This procedure is a UserFunction called by AcpiNsWalkNamespace.
199  *
200  ******************************************************************************/
201 
202 ACPI_STATUS
203 AcpiNsDumpOneObject (
204     ACPI_HANDLE             ObjHandle,
205     UINT32                  Level,
206     void                    *Context,
207     void                    **ReturnValue)
208 {
209     ACPI_WALK_INFO          *Info = (ACPI_WALK_INFO *) Context;
210     ACPI_NAMESPACE_NODE     *ThisNode;
211     ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
212     ACPI_OBJECT_TYPE        ObjType;
213     ACPI_OBJECT_TYPE        Type;
214     UINT32                  BytesToDump;
215     UINT32                  DbgLevel;
216     UINT32                  i;
217 
218 
219     ACPI_FUNCTION_NAME (NsDumpOneObject);
220 
221 
222     /* Is output enabled? */
223 
224     if (!(AcpiDbgLevel & Info->DebugLevel))
225     {
226         return (AE_OK);
227     }
228 
229     if (!ObjHandle)
230     {
231         ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Null object handle\n"));
232         return (AE_OK);
233     }
234 
235     ThisNode = AcpiNsValidateHandle (ObjHandle);
236     if (!ThisNode)
237     {
238         ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Invalid object handle %p\n",
239             ObjHandle));
240         return (AE_OK);
241     }
242 
243     Type = ThisNode->Type;
244 
245     /* Check if the owner matches */
246 
247     if ((Info->OwnerId != ACPI_OWNER_ID_MAX) &&
248         (Info->OwnerId != ThisNode->OwnerId))
249     {
250         return (AE_OK);
251     }
252 
253     if (!(Info->DisplayType & ACPI_DISPLAY_SHORT))
254     {
255         /* Indent the object according to the level */
256 
257         AcpiOsPrintf ("%2d%*s", (UINT32) Level - 1, (int) Level * 2, " ");
258 
259         /* Check the node type and name */
260 
261         if (Type > ACPI_TYPE_LOCAL_MAX)
262         {
263             ACPI_WARNING ((AE_INFO, "Invalid ACPI Object Type 0x%08X", Type));
264         }
265 
266         AcpiOsPrintf ("%4.4s", AcpiUtGetNodeName (ThisNode));
267     }
268 
269     /* Now we can print out the pertinent information */
270 
271     AcpiOsPrintf (" %-12s %p %2.2X ",
272             AcpiUtGetTypeName (Type), ThisNode, ThisNode->OwnerId);
273 
274     DbgLevel = AcpiDbgLevel;
275     AcpiDbgLevel = 0;
276     ObjDesc = AcpiNsGetAttachedObject (ThisNode);
277     AcpiDbgLevel = DbgLevel;
278 
279     /* Temp nodes are those nodes created by a control method */
280 
281     if (ThisNode->Flags & ANOBJ_TEMPORARY)
282     {
283         AcpiOsPrintf ("(T) ");
284     }
285 
286     switch (Info->DisplayType & ACPI_DISPLAY_MASK)
287     {
288     case ACPI_DISPLAY_SUMMARY:
289 
290         if (!ObjDesc)
291         {
292             /* No attached object. Some types should always have an object */
293 
294             switch (Type)
295             {
296             case ACPI_TYPE_INTEGER:
297             case ACPI_TYPE_PACKAGE:
298             case ACPI_TYPE_BUFFER:
299             case ACPI_TYPE_STRING:
300             case ACPI_TYPE_METHOD:
301 
302                 AcpiOsPrintf ("<No attached object>");
303                 break;
304 
305             default:
306 
307                 break;
308             }
309 
310             AcpiOsPrintf ("\n");
311             return (AE_OK);
312         }
313 
314         switch (Type)
315         {
316         case ACPI_TYPE_PROCESSOR:
317 
318             AcpiOsPrintf ("ID %02X Len %02X Addr %p\n",
319                 ObjDesc->Processor.ProcId, ObjDesc->Processor.Length,
320                 ACPI_CAST_PTR (void, ObjDesc->Processor.Address));
321             break;
322 
323         case ACPI_TYPE_DEVICE:
324 
325             AcpiOsPrintf ("Notify Object: %p\n", ObjDesc);
326             break;
327 
328         case ACPI_TYPE_METHOD:
329 
330             AcpiOsPrintf ("Args %X Len %.4X Aml %p\n",
331                 (UINT32) ObjDesc->Method.ParamCount,
332                 ObjDesc->Method.AmlLength, ObjDesc->Method.AmlStart);
333             break;
334 
335         case ACPI_TYPE_INTEGER:
336 
337             AcpiOsPrintf ("= %8.8X%8.8X\n",
338                 ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value));
339             break;
340 
341         case ACPI_TYPE_PACKAGE:
342 
343             if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
344             {
345                 AcpiOsPrintf ("Elements %.2X\n",
346                     ObjDesc->Package.Count);
347             }
348             else
349             {
350                 AcpiOsPrintf ("[Length not yet evaluated]\n");
351             }
352             break;
353 
354         case ACPI_TYPE_BUFFER:
355 
356             if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
357             {
358                 AcpiOsPrintf ("Len %.2X",
359                             ObjDesc->Buffer.Length);
360 
361                 /* Dump some of the buffer */
362 
363                 if (ObjDesc->Buffer.Length > 0)
364                 {
365                     AcpiOsPrintf (" =");
366                     for (i = 0; (i < ObjDesc->Buffer.Length && i < 12); i++)
367                     {
368                         AcpiOsPrintf (" %.2hX", ObjDesc->Buffer.Pointer[i]);
369                     }
370                 }
371                 AcpiOsPrintf ("\n");
372             }
373             else
374             {
375                 AcpiOsPrintf ("[Length not yet evaluated]\n");
376             }
377             break;
378 
379         case ACPI_TYPE_STRING:
380 
381             AcpiOsPrintf ("Len %.2X ", ObjDesc->String.Length);
382             AcpiUtPrintString (ObjDesc->String.Pointer, 32);
383             AcpiOsPrintf ("\n");
384             break;
385 
386         case ACPI_TYPE_REGION:
387 
388             AcpiOsPrintf ("[%s]",
389                 AcpiUtGetRegionName (ObjDesc->Region.SpaceId));
390             if (ObjDesc->Region.Flags & AOPOBJ_DATA_VALID)
391             {
392                 AcpiOsPrintf (" Addr %8.8X%8.8X Len %.4X\n",
393                     ACPI_FORMAT_NATIVE_UINT (ObjDesc->Region.Address),
394                     ObjDesc->Region.Length);
395             }
396             else
397             {
398                 AcpiOsPrintf (" [Address/Length not yet evaluated]\n");
399             }
400             break;
401 
402         case ACPI_TYPE_LOCAL_REFERENCE:
403 
404             AcpiOsPrintf ("[%s]\n", AcpiUtGetReferenceName (ObjDesc));
405             break;
406 
407         case ACPI_TYPE_BUFFER_FIELD:
408 
409             if (ObjDesc->BufferField.BufferObj &&
410                 ObjDesc->BufferField.BufferObj->Buffer.Node)
411             {
412                 AcpiOsPrintf ("Buf [%4.4s]",
413                     AcpiUtGetNodeName (
414                         ObjDesc->BufferField.BufferObj->Buffer.Node));
415             }
416             break;
417 
418         case ACPI_TYPE_LOCAL_REGION_FIELD:
419 
420             AcpiOsPrintf ("Rgn [%4.4s]",
421                 AcpiUtGetNodeName (
422                     ObjDesc->CommonField.RegionObj->Region.Node));
423             break;
424 
425         case ACPI_TYPE_LOCAL_BANK_FIELD:
426 
427             AcpiOsPrintf ("Rgn [%4.4s] Bnk [%4.4s]",
428                 AcpiUtGetNodeName (
429                     ObjDesc->CommonField.RegionObj->Region.Node),
430                 AcpiUtGetNodeName (
431                     ObjDesc->BankField.BankObj->CommonField.Node));
432             break;
433 
434         case ACPI_TYPE_LOCAL_INDEX_FIELD:
435 
436             AcpiOsPrintf ("Idx [%4.4s] Dat [%4.4s]",
437                 AcpiUtGetNodeName (
438                     ObjDesc->IndexField.IndexObj->CommonField.Node),
439                 AcpiUtGetNodeName (
440                     ObjDesc->IndexField.DataObj->CommonField.Node));
441             break;
442 
443         case ACPI_TYPE_LOCAL_ALIAS:
444         case ACPI_TYPE_LOCAL_METHOD_ALIAS:
445 
446             AcpiOsPrintf ("Target %4.4s (%p)\n",
447                 AcpiUtGetNodeName (ObjDesc), ObjDesc);
448             break;
449 
450         default:
451 
452             AcpiOsPrintf ("Object %p\n", ObjDesc);
453             break;
454         }
455 
456         /* Common field handling */
457 
458         switch (Type)
459         {
460         case ACPI_TYPE_BUFFER_FIELD:
461         case ACPI_TYPE_LOCAL_REGION_FIELD:
462         case ACPI_TYPE_LOCAL_BANK_FIELD:
463         case ACPI_TYPE_LOCAL_INDEX_FIELD:
464 
465             AcpiOsPrintf (" Off %.3X Len %.2X Acc %.2hd\n",
466                 (ObjDesc->CommonField.BaseByteOffset * 8)
467                     + ObjDesc->CommonField.StartFieldBitOffset,
468                 ObjDesc->CommonField.BitLength,
469                 ObjDesc->CommonField.AccessByteWidth);
470             break;
471 
472         default:
473 
474             break;
475         }
476         break;
477 
478     case ACPI_DISPLAY_OBJECTS:
479 
480         AcpiOsPrintf ("O:%p", ObjDesc);
481         if (!ObjDesc)
482         {
483             /* No attached object, we are done */
484 
485             AcpiOsPrintf ("\n");
486             return (AE_OK);
487         }
488 
489         AcpiOsPrintf ("(R%u)", ObjDesc->Common.ReferenceCount);
490 
491         switch (Type)
492         {
493         case ACPI_TYPE_METHOD:
494 
495             /* Name is a Method and its AML offset/length are set */
496 
497             AcpiOsPrintf (" M:%p-%X\n", ObjDesc->Method.AmlStart,
498                 ObjDesc->Method.AmlLength);
499             break;
500 
501         case ACPI_TYPE_INTEGER:
502 
503             AcpiOsPrintf (" I:%8.8X8.8%X\n",
504                 ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value));
505             break;
506 
507         case ACPI_TYPE_STRING:
508 
509             AcpiOsPrintf (" S:%p-%X\n", ObjDesc->String.Pointer,
510                 ObjDesc->String.Length);
511             break;
512 
513         case ACPI_TYPE_BUFFER:
514 
515             AcpiOsPrintf (" B:%p-%X\n", ObjDesc->Buffer.Pointer,
516                 ObjDesc->Buffer.Length);
517             break;
518 
519         default:
520 
521             AcpiOsPrintf ("\n");
522             break;
523         }
524         break;
525 
526     default:
527         AcpiOsPrintf ("\n");
528         break;
529     }
530 
531     /* If debug turned off, done */
532 
533     if (!(AcpiDbgLevel & ACPI_LV_VALUES))
534     {
535         return (AE_OK);
536     }
537 
538     /* If there is an attached object, display it */
539 
540     DbgLevel     = AcpiDbgLevel;
541     AcpiDbgLevel = 0;
542     ObjDesc      = AcpiNsGetAttachedObject (ThisNode);
543     AcpiDbgLevel = DbgLevel;
544 
545     /* Dump attached objects */
546 
547     while (ObjDesc)
548     {
549         ObjType = ACPI_TYPE_INVALID;
550         AcpiOsPrintf ("Attached Object %p: ", ObjDesc);
551 
552         /* Decode the type of attached object and dump the contents */
553 
554         switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
555         {
556         case ACPI_DESC_TYPE_NAMED:
557 
558             AcpiOsPrintf ("(Ptr to Node)\n");
559             BytesToDump = sizeof (ACPI_NAMESPACE_NODE);
560             ACPI_DUMP_BUFFER (ObjDesc, BytesToDump);
561             break;
562 
563         case ACPI_DESC_TYPE_OPERAND:
564 
565             ObjType = ObjDesc->Common.Type;
566 
567             if (ObjType > ACPI_TYPE_LOCAL_MAX)
568             {
569                 AcpiOsPrintf ("(Pointer to ACPI Object type %.2X [UNKNOWN])\n",
570                     ObjType);
571                 BytesToDump = 32;
572             }
573             else
574             {
575                 AcpiOsPrintf ("(Pointer to ACPI Object type %.2X [%s])\n",
576                     ObjType, AcpiUtGetTypeName (ObjType));
577                 BytesToDump = sizeof (ACPI_OPERAND_OBJECT);
578             }
579 
580             ACPI_DUMP_BUFFER (ObjDesc, BytesToDump);
581             break;
582 
583         default:
584 
585             break;
586         }
587 
588         /* If value is NOT an internal object, we are done */
589 
590         if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND)
591         {
592             goto Cleanup;
593         }
594 
595         /* Valid object, get the pointer to next level, if any */
596 
597         switch (ObjType)
598         {
599         case ACPI_TYPE_BUFFER:
600         case ACPI_TYPE_STRING:
601             /*
602              * NOTE: takes advantage of common fields between string/buffer
603              */
604             BytesToDump = ObjDesc->String.Length;
605             ObjDesc = (void *) ObjDesc->String.Pointer;
606             AcpiOsPrintf ( "(Buffer/String pointer %p length %X)\n",
607                 ObjDesc, BytesToDump);
608             ACPI_DUMP_BUFFER (ObjDesc, BytesToDump);
609             goto Cleanup;
610 
611         case ACPI_TYPE_BUFFER_FIELD:
612 
613             ObjDesc = (ACPI_OPERAND_OBJECT *) ObjDesc->BufferField.BufferObj;
614             break;
615 
616         case ACPI_TYPE_PACKAGE:
617 
618             ObjDesc = (void *) ObjDesc->Package.Elements;
619             break;
620 
621         case ACPI_TYPE_METHOD:
622 
623             ObjDesc = (void *) ObjDesc->Method.AmlStart;
624             break;
625 
626         case ACPI_TYPE_LOCAL_REGION_FIELD:
627 
628             ObjDesc = (void *) ObjDesc->Field.RegionObj;
629             break;
630 
631         case ACPI_TYPE_LOCAL_BANK_FIELD:
632 
633             ObjDesc = (void *) ObjDesc->BankField.RegionObj;
634             break;
635 
636         case ACPI_TYPE_LOCAL_INDEX_FIELD:
637 
638             ObjDesc = (void *) ObjDesc->IndexField.IndexObj;
639             break;
640 
641         default:
642 
643             goto Cleanup;
644         }
645 
646         ObjType = ACPI_TYPE_INVALID;   /* Terminate loop after next pass */
647     }
648 
649 Cleanup:
650     AcpiOsPrintf ("\n");
651     return (AE_OK);
652 }
653 
654 
655 /*******************************************************************************
656  *
657  * FUNCTION:    AcpiNsDumpObjects
658  *
659  * PARAMETERS:  Type                - Object type to be dumped
660  *              DisplayType         - 0 or ACPI_DISPLAY_SUMMARY
661  *              MaxDepth            - Maximum depth of dump. Use ACPI_UINT32_MAX
662  *                                    for an effectively unlimited depth.
663  *              OwnerId             - Dump only objects owned by this ID. Use
664  *                                    ACPI_UINT32_MAX to match all owners.
665  *              StartHandle         - Where in namespace to start/end search
666  *
667  * RETURN:      None
668  *
669  * DESCRIPTION: Dump typed objects within the loaded namespace. Uses
670  *              AcpiNsWalkNamespace in conjunction with AcpiNsDumpOneObject.
671  *
672  ******************************************************************************/
673 
674 void
675 AcpiNsDumpObjects (
676     ACPI_OBJECT_TYPE        Type,
677     UINT8                   DisplayType,
678     UINT32                  MaxDepth,
679     ACPI_OWNER_ID           OwnerId,
680     ACPI_HANDLE             StartHandle)
681 {
682     ACPI_WALK_INFO          Info;
683     ACPI_STATUS             Status;
684 
685 
686     ACPI_FUNCTION_ENTRY ();
687 
688 
689     /*
690      * Just lock the entire namespace for the duration of the dump.
691      * We don't want any changes to the namespace during this time,
692      * especially the temporary nodes since we are going to display
693      * them also.
694      */
695     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
696     if (ACPI_FAILURE (Status))
697     {
698         AcpiOsPrintf ("Could not acquire namespace mutex\n");
699         return;
700     }
701 
702     Info.DebugLevel = ACPI_LV_TABLES;
703     Info.OwnerId = OwnerId;
704     Info.DisplayType = DisplayType;
705 
706     (void) AcpiNsWalkNamespace (Type, StartHandle, MaxDepth,
707                 ACPI_NS_WALK_NO_UNLOCK | ACPI_NS_WALK_TEMP_NODES,
708                 AcpiNsDumpOneObject, NULL, (void *) &Info, NULL);
709 
710     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
711 }
712 
713 
714 /*******************************************************************************
715  *
716  * FUNCTION:    AcpiNsDumpOneObjectPath, AcpiNsGetMaxDepth
717  *
718  * PARAMETERS:  ObjHandle           - Node to be dumped
719  *              Level               - Nesting level of the handle
720  *              Context             - Passed into WalkNamespace
721  *              ReturnValue         - Not used
722  *
723  * RETURN:      Status
724  *
725  * DESCRIPTION: Dump the full pathname to a namespace object. AcpNsGetMaxDepth
726  *              computes the maximum nesting depth in the namespace tree, in
727  *              order to simplify formatting in AcpiNsDumpOneObjectPath.
728  *              These procedures are UserFunctions called by AcpiNsWalkNamespace.
729  *
730  ******************************************************************************/
731 
732 static ACPI_STATUS
733 AcpiNsDumpOneObjectPath (
734     ACPI_HANDLE             ObjHandle,
735     UINT32                  Level,
736     void                    *Context,
737     void                    **ReturnValue)
738 {
739     UINT32                  MaxLevel = *((UINT32 *) Context);
740     char                    *Pathname;
741     ACPI_NAMESPACE_NODE     *Node;
742     int                     PathIndent;
743 
744 
745     if (!ObjHandle)
746     {
747         return (AE_OK);
748     }
749 
750     Node = AcpiNsValidateHandle (ObjHandle);
751     if (!Node)
752     {
753         /* Ignore bad node during namespace walk */
754 
755         return (AE_OK);
756     }
757 
758     Pathname = AcpiNsGetExternalPathname (Node);
759 
760     PathIndent = 1;
761     if (Level <= MaxLevel)
762     {
763         PathIndent = MaxLevel - Level + 1;
764     }
765 
766     AcpiOsPrintf ("%2d%*s%-12s%*s",
767         Level, Level, " ", AcpiUtGetTypeName (Node->Type),
768         PathIndent, " ");
769 
770     AcpiOsPrintf ("%s\n", &Pathname[1]);
771     ACPI_FREE (Pathname);
772     return (AE_OK);
773 }
774 
775 
776 static ACPI_STATUS
777 AcpiNsGetMaxDepth (
778     ACPI_HANDLE             ObjHandle,
779     UINT32                  Level,
780     void                    *Context,
781     void                    **ReturnValue)
782 {
783     UINT32                  *MaxLevel = (UINT32 *) Context;
784 
785 
786     if (Level > *MaxLevel)
787     {
788         *MaxLevel = Level;
789     }
790     return (AE_OK);
791 }
792 
793 
794 /*******************************************************************************
795  *
796  * FUNCTION:    AcpiNsDumpObjectPaths
797  *
798  * PARAMETERS:  Type                - Object type to be dumped
799  *              DisplayType         - 0 or ACPI_DISPLAY_SUMMARY
800  *              MaxDepth            - Maximum depth of dump. Use ACPI_UINT32_MAX
801  *                                    for an effectively unlimited depth.
802  *              OwnerId             - Dump only objects owned by this ID. Use
803  *                                    ACPI_UINT32_MAX to match all owners.
804  *              StartHandle         - Where in namespace to start/end search
805  *
806  * RETURN:      None
807  *
808  * DESCRIPTION: Dump full object pathnames within the loaded namespace. Uses
809  *              AcpiNsWalkNamespace in conjunction with AcpiNsDumpOneObjectPath.
810  *
811  ******************************************************************************/
812 
813 void
814 AcpiNsDumpObjectPaths (
815     ACPI_OBJECT_TYPE        Type,
816     UINT8                   DisplayType,
817     UINT32                  MaxDepth,
818     ACPI_OWNER_ID           OwnerId,
819     ACPI_HANDLE             StartHandle)
820 {
821     ACPI_STATUS             Status;
822     UINT32                  MaxLevel = 0;
823 
824 
825     ACPI_FUNCTION_ENTRY ();
826 
827 
828     /*
829      * Just lock the entire namespace for the duration of the dump.
830      * We don't want any changes to the namespace during this time,
831      * especially the temporary nodes since we are going to display
832      * them also.
833      */
834     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
835     if (ACPI_FAILURE (Status))
836     {
837         AcpiOsPrintf ("Could not acquire namespace mutex\n");
838         return;
839     }
840 
841     /* Get the max depth of the namespace tree, for formatting later */
842 
843     (void) AcpiNsWalkNamespace (Type, StartHandle, MaxDepth,
844                 ACPI_NS_WALK_NO_UNLOCK | ACPI_NS_WALK_TEMP_NODES,
845                 AcpiNsGetMaxDepth, NULL, (void *) &MaxLevel, NULL);
846 
847     /* Now dump the entire namespace */
848 
849     (void) AcpiNsWalkNamespace (Type, StartHandle, MaxDepth,
850                 ACPI_NS_WALK_NO_UNLOCK | ACPI_NS_WALK_TEMP_NODES,
851                 AcpiNsDumpOneObjectPath, NULL, (void *) &MaxLevel, NULL);
852 
853     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
854 }
855 
856 
857 /*******************************************************************************
858  *
859  * FUNCTION:    AcpiNsDumpEntry
860  *
861  * PARAMETERS:  Handle              - Node to be dumped
862  *              DebugLevel          - Output level
863  *
864  * RETURN:      None
865  *
866  * DESCRIPTION: Dump a single Node
867  *
868  ******************************************************************************/
869 
870 void
871 AcpiNsDumpEntry (
872     ACPI_HANDLE             Handle,
873     UINT32                  DebugLevel)
874 {
875     ACPI_WALK_INFO          Info;
876 
877 
878     ACPI_FUNCTION_ENTRY ();
879 
880 
881     Info.DebugLevel = DebugLevel;
882     Info.OwnerId = ACPI_OWNER_ID_MAX;
883     Info.DisplayType = ACPI_DISPLAY_SUMMARY;
884 
885     (void) AcpiNsDumpOneObject (Handle, 1, &Info, NULL);
886 }
887 
888 
889 #ifdef ACPI_ASL_COMPILER
890 /*******************************************************************************
891  *
892  * FUNCTION:    AcpiNsDumpTables
893  *
894  * PARAMETERS:  SearchBase          - Root of subtree to be dumped, or
895  *                                    NS_ALL to dump the entire namespace
896  *              MaxDepth            - Maximum depth of dump. Use INT_MAX
897  *                                    for an effectively unlimited depth.
898  *
899  * RETURN:      None
900  *
901  * DESCRIPTION: Dump the name space, or a portion of it.
902  *
903  ******************************************************************************/
904 
905 void
906 AcpiNsDumpTables (
907     ACPI_HANDLE             SearchBase,
908     UINT32                  MaxDepth)
909 {
910     ACPI_HANDLE             SearchHandle = SearchBase;
911 
912 
913     ACPI_FUNCTION_TRACE (NsDumpTables);
914 
915 
916     if (!AcpiGbl_RootNode)
917     {
918         /*
919          * If the name space has not been initialized,
920          * there is nothing to dump.
921          */
922         ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "namespace not initialized!\n"));
923         return_VOID;
924     }
925 
926     if (ACPI_NS_ALL == SearchBase)
927     {
928         /* Entire namespace */
929 
930         SearchHandle = AcpiGbl_RootNode;
931         ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "\\\n"));
932     }
933 
934     AcpiNsDumpObjects (ACPI_TYPE_ANY, ACPI_DISPLAY_OBJECTS, MaxDepth,
935             ACPI_OWNER_ID_MAX, SearchHandle);
936     return_VOID;
937 }
938 #endif
939 #endif
940