dbcmds.c revision 217365
1/*******************************************************************************
2 *
3 * Module Name: dbcmds - debug commands and output routines
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2011, 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
45#include <contrib/dev/acpica/include/acpi.h>
46#include <contrib/dev/acpica/include/accommon.h>
47#include <contrib/dev/acpica/include/acdispat.h>
48#include <contrib/dev/acpica/include/acnamesp.h>
49#include <contrib/dev/acpica/include/acevents.h>
50#include <contrib/dev/acpica/include/acdebug.h>
51#include <contrib/dev/acpica/include/acresrc.h>
52#include <contrib/dev/acpica/include/acdisasm.h>
53#include <contrib/dev/acpica/include/actables.h>
54#include <contrib/dev/acpica/include/acparser.h>
55
56#ifdef ACPI_DEBUGGER
57
58#define _COMPONENT          ACPI_CA_DEBUGGER
59        ACPI_MODULE_NAME    ("dbcmds")
60
61
62/* Local prototypes */
63
64static ACPI_STATUS
65AcpiDbIntegrityWalk (
66    ACPI_HANDLE             ObjHandle,
67    UINT32                  NestingLevel,
68    void                    *Context,
69    void                    **ReturnValue);
70
71static ACPI_STATUS
72AcpiDbWalkAndMatchName (
73    ACPI_HANDLE             ObjHandle,
74    UINT32                  NestingLevel,
75    void                    *Context,
76    void                    **ReturnValue);
77
78static ACPI_STATUS
79AcpiDbWalkForReferences (
80    ACPI_HANDLE             ObjHandle,
81    UINT32                  NestingLevel,
82    void                    *Context,
83    void                    **ReturnValue);
84
85static ACPI_STATUS
86AcpiDbWalkForSpecificObjects (
87    ACPI_HANDLE             ObjHandle,
88    UINT32                  NestingLevel,
89    void                    *Context,
90    void                    **ReturnValue);
91
92static ACPI_NAMESPACE_NODE *
93AcpiDbConvertToNode (
94    char                    *InString);
95
96static void
97AcpiDmCompareAmlResources (
98    UINT8                   *Aml1Buffer,
99    ACPI_RSDESC_SIZE        Aml1BufferLength,
100    UINT8                   *Aml2Buffer,
101    ACPI_RSDESC_SIZE        Aml2BufferLength);
102
103static ACPI_STATUS
104AcpiDmTestResourceConversion (
105    ACPI_NAMESPACE_NODE     *Node,
106    char                    *Name);
107
108
109/*
110 * Arguments for the Objects command
111 * These object types map directly to the ACPI_TYPES
112 */
113static ARGUMENT_INFO        AcpiDbObjectTypes [] =
114{
115    {"ANY"},
116    {"INTEGERS"},
117    {"STRINGS"},
118    {"BUFFERS"},
119    {"PACKAGES"},
120    {"FIELDS"},
121    {"DEVICES"},
122    {"EVENTS"},
123    {"METHODS"},
124    {"MUTEXES"},
125    {"REGIONS"},
126    {"POWERRESOURCES"},
127    {"PROCESSORS"},
128    {"THERMALZONES"},
129    {"BUFFERFIELDS"},
130    {"DDBHANDLES"},
131    {"DEBUG"},
132    {"REGIONFIELDS"},
133    {"BANKFIELDS"},
134    {"INDEXFIELDS"},
135    {"REFERENCES"},
136    {"ALIAS"},
137    {NULL}           /* Must be null terminated */
138};
139
140
141/*******************************************************************************
142 *
143 * FUNCTION:    AcpiDbConvertToNode
144 *
145 * PARAMETERS:  InString        - String to convert
146 *
147 * RETURN:      Pointer to a NS node
148 *
149 * DESCRIPTION: Convert a string to a valid NS pointer.  Handles numeric or
150 *              alpha strings.
151 *
152 ******************************************************************************/
153
154static ACPI_NAMESPACE_NODE *
155AcpiDbConvertToNode (
156    char                    *InString)
157{
158    ACPI_NAMESPACE_NODE     *Node;
159
160
161    if ((*InString >= 0x30) && (*InString <= 0x39))
162    {
163        /* Numeric argument, convert */
164
165        Node = ACPI_TO_POINTER (ACPI_STRTOUL (InString, NULL, 16));
166        if (!AcpiOsReadable (Node, sizeof (ACPI_NAMESPACE_NODE)))
167        {
168            AcpiOsPrintf ("Address %p is invalid in this address space\n",
169                Node);
170            return (NULL);
171        }
172
173        /* Make sure pointer is valid NS node */
174
175        if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED)
176        {
177            AcpiOsPrintf ("Address %p is not a valid NS node [%s]\n",
178                    Node, AcpiUtGetDescriptorName (Node));
179            return (NULL);
180        }
181    }
182    else
183    {
184        /* Alpha argument */
185        /* The parameter is a name string that must be resolved to a
186         * Named obj
187         */
188        Node = AcpiDbLocalNsLookup (InString);
189        if (!Node)
190        {
191            Node = AcpiGbl_RootNode;
192        }
193    }
194
195    return (Node);
196}
197
198
199/*******************************************************************************
200 *
201 * FUNCTION:    AcpiDbSleep
202 *
203 * PARAMETERS:  ObjectArg       - Desired sleep state (0-5)
204 *
205 * RETURN:      Status
206 *
207 * DESCRIPTION: Simulate a sleep/wake sequence
208 *
209 ******************************************************************************/
210
211ACPI_STATUS
212AcpiDbSleep (
213    char                    *ObjectArg)
214{
215    ACPI_STATUS             Status;
216    UINT8                   SleepState;
217
218
219    SleepState = (UINT8) ACPI_STRTOUL (ObjectArg, NULL, 0);
220
221    AcpiOsPrintf ("**** Prepare to sleep ****\n");
222    Status = AcpiEnterSleepStatePrep (SleepState);
223    if (ACPI_FAILURE (Status))
224    {
225        return (Status);
226    }
227
228    AcpiOsPrintf ("**** Going to sleep ****\n");
229    Status = AcpiEnterSleepState (SleepState);
230    if (ACPI_FAILURE (Status))
231    {
232        return (Status);
233    }
234
235    AcpiOsPrintf ("**** returning from sleep ****\n");
236    Status = AcpiLeaveSleepState (SleepState);
237
238    return (Status);
239}
240
241
242/*******************************************************************************
243 *
244 * FUNCTION:    AcpiDbWalkForReferences
245 *
246 * PARAMETERS:  Callback from WalkNamespace
247 *
248 * RETURN:      Status
249 *
250 * DESCRIPTION: Check if this namespace object refers to the target object
251 *              that is passed in as the context value.
252 *
253 * Note: Currently doesn't check subobjects within the Node's object
254 *
255 ******************************************************************************/
256
257static ACPI_STATUS
258AcpiDbWalkForReferences (
259    ACPI_HANDLE             ObjHandle,
260    UINT32                  NestingLevel,
261    void                    *Context,
262    void                    **ReturnValue)
263{
264    ACPI_OPERAND_OBJECT     *ObjDesc = (ACPI_OPERAND_OBJECT  *) Context;
265    ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
266
267
268    /* Check for match against the namespace node itself */
269
270    if (Node == (void *) ObjDesc)
271    {
272        AcpiOsPrintf ("Object is a Node [%4.4s]\n",
273            AcpiUtGetNodeName (Node));
274    }
275
276    /* Check for match against the object attached to the node */
277
278    if (AcpiNsGetAttachedObject (Node) == ObjDesc)
279    {
280        AcpiOsPrintf ("Reference at Node->Object %p [%4.4s]\n",
281            Node, AcpiUtGetNodeName (Node));
282    }
283
284    return (AE_OK);
285}
286
287
288/*******************************************************************************
289 *
290 * FUNCTION:    AcpiDbFindReferences
291 *
292 * PARAMETERS:  ObjectArg       - String with hex value of the object
293 *
294 * RETURN:      None
295 *
296 * DESCRIPTION: Search namespace for all references to the input object
297 *
298 ******************************************************************************/
299
300void
301AcpiDbFindReferences (
302    char                    *ObjectArg)
303{
304    ACPI_OPERAND_OBJECT     *ObjDesc;
305
306
307    /* Convert string to object pointer */
308
309    ObjDesc = ACPI_TO_POINTER (ACPI_STRTOUL (ObjectArg, NULL, 16));
310
311    /* Search all nodes in namespace */
312
313    (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
314                    AcpiDbWalkForReferences, NULL, (void *) ObjDesc, NULL);
315}
316
317
318/*******************************************************************************
319 *
320 * FUNCTION:    AcpiDbWalkForPredefinedNames
321 *
322 * PARAMETERS:  Callback from WalkNamespace
323 *
324 * RETURN:      Status
325 *
326 * DESCRIPTION: Detect and display predefined ACPI names (names that start with
327 *              an underscore)
328 *
329 ******************************************************************************/
330
331static ACPI_STATUS
332AcpiDbWalkForPredefinedNames (
333    ACPI_HANDLE             ObjHandle,
334    UINT32                  NestingLevel,
335    void                    *Context,
336    void                    **ReturnValue)
337{
338    ACPI_NAMESPACE_NODE         *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
339    UINT32                      *Count = (UINT32 *) Context;
340    const ACPI_PREDEFINED_INFO  *Predefined;
341    const ACPI_PREDEFINED_INFO  *Package = NULL;
342    char                        *Pathname;
343
344
345    Predefined = AcpiNsCheckForPredefinedName (Node);
346    if (!Predefined)
347    {
348        return (AE_OK);
349    }
350
351    Pathname = AcpiNsGetExternalPathname (Node);
352    if (!Pathname)
353    {
354        return (AE_OK);
355    }
356
357    /* If method returns a package, the info is in the next table entry */
358
359    if (Predefined->Info.ExpectedBtypes & ACPI_BTYPE_PACKAGE)
360    {
361        Package = Predefined + 1;
362    }
363
364    AcpiOsPrintf ("%-32s arg %X ret %2.2X", Pathname,
365        Predefined->Info.ParamCount, Predefined->Info.ExpectedBtypes);
366
367    if (Package)
368    {
369        AcpiOsPrintf (" PkgType %2.2X ObjType %2.2X Count %2.2X",
370            Package->RetInfo.Type, Package->RetInfo.ObjectType1,
371            Package->RetInfo.Count1);
372    }
373
374    AcpiOsPrintf("\n");
375
376    AcpiNsCheckParameterCount (Pathname, Node, ACPI_UINT32_MAX, Predefined);
377    ACPI_FREE (Pathname);
378    (*Count)++;
379
380    return (AE_OK);
381}
382
383
384/*******************************************************************************
385 *
386 * FUNCTION:    AcpiDbCheckPredefinedNames
387 *
388 * PARAMETERS:  None
389 *
390 * RETURN:      None
391 *
392 * DESCRIPTION: Validate all predefined names in the namespace
393 *
394 ******************************************************************************/
395
396void
397AcpiDbCheckPredefinedNames (
398    void)
399{
400    UINT32                  Count = 0;
401
402
403    /* Search all nodes in namespace */
404
405    (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
406                AcpiDbWalkForPredefinedNames, NULL, (void *) &Count, NULL);
407
408    AcpiOsPrintf ("Found %u predefined names in the namespace\n", Count);
409}
410
411
412/*******************************************************************************
413 *
414 * FUNCTION:    AcpiDbWalkForExecute
415 *
416 * PARAMETERS:  Callback from WalkNamespace
417 *
418 * RETURN:      Status
419 *
420 * DESCRIPTION: Batch execution module. Currently only executes predefined
421 *              ACPI names.
422 *
423 ******************************************************************************/
424
425static ACPI_STATUS
426AcpiDbWalkForExecute (
427    ACPI_HANDLE             ObjHandle,
428    UINT32                  NestingLevel,
429    void                    *Context,
430    void                    **ReturnValue)
431{
432    ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
433    ACPI_EXECUTE_WALK       *Info = (ACPI_EXECUTE_WALK *) Context;
434    ACPI_BUFFER             ReturnObj;
435    ACPI_STATUS             Status;
436    char                    *Pathname;
437    UINT32                  i;
438    ACPI_DEVICE_INFO        *ObjInfo;
439    ACPI_OBJECT_LIST        ParamObjects;
440    ACPI_OBJECT             Params[ACPI_METHOD_NUM_ARGS];
441    const ACPI_PREDEFINED_INFO *Predefined;
442
443
444    Predefined = AcpiNsCheckForPredefinedName (Node);
445    if (!Predefined)
446    {
447        return (AE_OK);
448    }
449
450    if (Node->Type == ACPI_TYPE_LOCAL_SCOPE)
451    {
452        return (AE_OK);
453    }
454
455    Pathname = AcpiNsGetExternalPathname (Node);
456    if (!Pathname)
457    {
458        return (AE_OK);
459    }
460
461    /* Get the object info for number of method parameters */
462
463    Status = AcpiGetObjectInfo (ObjHandle, &ObjInfo);
464    if (ACPI_FAILURE (Status))
465    {
466        return (Status);
467    }
468
469    ParamObjects.Pointer = NULL;
470    ParamObjects.Count   = 0;
471
472    if (ObjInfo->Type == ACPI_TYPE_METHOD)
473    {
474        /* Setup default parameters */
475
476        for (i = 0; i < ObjInfo->ParamCount; i++)
477        {
478            Params[i].Type           = ACPI_TYPE_INTEGER;
479            Params[i].Integer.Value  = 1;
480        }
481
482        ParamObjects.Pointer     = Params;
483        ParamObjects.Count       = ObjInfo->ParamCount;
484    }
485
486    ACPI_FREE (ObjInfo);
487    ReturnObj.Pointer = NULL;
488    ReturnObj.Length = ACPI_ALLOCATE_BUFFER;
489
490    /* Do the actual method execution */
491
492    AcpiGbl_MethodExecuting = TRUE;
493
494    Status = AcpiEvaluateObject (Node, NULL, &ParamObjects, &ReturnObj);
495
496    AcpiOsPrintf ("%-32s returned %s\n", Pathname, AcpiFormatException (Status));
497    AcpiGbl_MethodExecuting = FALSE;
498    ACPI_FREE (Pathname);
499
500    /* Ignore status from method execution */
501
502    Status = AE_OK;
503
504    /* Update count, check if we have executed enough methods */
505
506    Info->Count++;
507    if (Info->Count >= Info->MaxCount)
508    {
509        Status = AE_CTRL_TERMINATE;
510    }
511
512    return (Status);
513}
514
515
516/*******************************************************************************
517 *
518 * FUNCTION:    AcpiDbBatchExecute
519 *
520 * PARAMETERS:  CountArg            - Max number of methods to execute
521 *
522 * RETURN:      None
523 *
524 * DESCRIPTION: Namespace batch execution. Execute predefined names in the
525 *              namespace, up to the max count, if specified.
526 *
527 ******************************************************************************/
528
529void
530AcpiDbBatchExecute (
531    char                    *CountArg)
532{
533    ACPI_EXECUTE_WALK       Info;
534
535
536    Info.Count = 0;
537    Info.MaxCount = ACPI_UINT32_MAX;
538
539    if (CountArg)
540    {
541        Info.MaxCount = ACPI_STRTOUL (CountArg, NULL, 0);
542    }
543
544
545    /* Search all nodes in namespace */
546
547    (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
548                AcpiDbWalkForExecute, NULL, (void *) &Info, NULL);
549
550    AcpiOsPrintf ("Executed %u predefined names in the namespace\n", Info.Count);
551}
552
553
554/*******************************************************************************
555 *
556 * FUNCTION:    AcpiDbDisplayLocks
557 *
558 * PARAMETERS:  None
559 *
560 * RETURN:      None
561 *
562 * DESCRIPTION: Display information about internal mutexes.
563 *
564 ******************************************************************************/
565
566void
567AcpiDbDisplayLocks (
568    void)
569{
570    UINT32                  i;
571
572
573    for (i = 0; i < ACPI_MAX_MUTEX; i++)
574    {
575        AcpiOsPrintf ("%26s : %s\n", AcpiUtGetMutexName (i),
576            AcpiGbl_MutexInfo[i].ThreadId == ACPI_MUTEX_NOT_ACQUIRED
577                ? "Locked" : "Unlocked");
578    }
579}
580
581
582/*******************************************************************************
583 *
584 * FUNCTION:    AcpiDbDisplayTableInfo
585 *
586 * PARAMETERS:  TableArg        - String with name of table to be displayed
587 *
588 * RETURN:      None
589 *
590 * DESCRIPTION: Display information about loaded tables.  Current
591 *              implementation displays all loaded tables.
592 *
593 ******************************************************************************/
594
595void
596AcpiDbDisplayTableInfo (
597    char                    *TableArg)
598{
599    UINT32                  i;
600    ACPI_TABLE_DESC         *TableDesc;
601    ACPI_STATUS             Status;
602
603
604    /* Walk the entire root table list */
605
606    for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
607    {
608        TableDesc = &AcpiGbl_RootTableList.Tables[i];
609        AcpiOsPrintf ("%u ", i);
610
611        /* Make sure that the table is mapped */
612
613        Status = AcpiTbVerifyTable (TableDesc);
614        if (ACPI_FAILURE (Status))
615        {
616            return;
617        }
618
619        /* Dump the table header */
620
621        if (TableDesc->Pointer)
622        {
623            AcpiTbPrintTableHeader (TableDesc->Address, TableDesc->Pointer);
624        }
625        else
626        {
627            /* If the pointer is null, the table has been unloaded */
628
629            ACPI_INFO ((AE_INFO, "%4.4s - Table has been unloaded",
630                TableDesc->Signature.Ascii));
631        }
632    }
633}
634
635
636/*******************************************************************************
637 *
638 * FUNCTION:    AcpiDbUnloadAcpiTable
639 *
640 * PARAMETERS:  TableArg        - Name of the table to be unloaded
641 *              InstanceArg     - Which instance of the table to unload (if
642 *                                there are multiple tables of the same type)
643 *
644 * RETURN:      Nonde
645 *
646 * DESCRIPTION: Unload an ACPI table.
647 *              Instance is not implemented
648 *
649 ******************************************************************************/
650
651void
652AcpiDbUnloadAcpiTable (
653    char                    *TableArg,
654    char                    *InstanceArg)
655{
656/* TBD: Need to reimplement for new data structures */
657
658#if 0
659    UINT32                  i;
660    ACPI_STATUS             Status;
661
662
663    /* Search all tables for the target type */
664
665    for (i = 0; i < (ACPI_TABLE_ID_MAX+1); i++)
666    {
667        if (!ACPI_STRNCMP (TableArg, AcpiGbl_TableData[i].Signature,
668                AcpiGbl_TableData[i].SigLength))
669        {
670            /* Found the table, unload it */
671
672            Status = AcpiUnloadTable (i);
673            if (ACPI_SUCCESS (Status))
674            {
675                AcpiOsPrintf ("[%s] unloaded and uninstalled\n", TableArg);
676            }
677            else
678            {
679                AcpiOsPrintf ("%s, while unloading [%s]\n",
680                    AcpiFormatException (Status), TableArg);
681            }
682
683            return;
684        }
685    }
686
687    AcpiOsPrintf ("Unknown table type [%s]\n", TableArg);
688#endif
689}
690
691
692/*******************************************************************************
693 *
694 * FUNCTION:    AcpiDbSetMethodBreakpoint
695 *
696 * PARAMETERS:  Location            - AML offset of breakpoint
697 *              WalkState           - Current walk info
698 *              Op                  - Current Op (from parse walk)
699 *
700 * RETURN:      None
701 *
702 * DESCRIPTION: Set a breakpoint in a control method at the specified
703 *              AML offset
704 *
705 ******************************************************************************/
706
707void
708AcpiDbSetMethodBreakpoint (
709    char                    *Location,
710    ACPI_WALK_STATE         *WalkState,
711    ACPI_PARSE_OBJECT       *Op)
712{
713    UINT32                  Address;
714
715
716    if (!Op)
717    {
718        AcpiOsPrintf ("There is no method currently executing\n");
719        return;
720    }
721
722    /* Get and verify the breakpoint address */
723
724    Address = ACPI_STRTOUL (Location, NULL, 16);
725    if (Address <= Op->Common.AmlOffset)
726    {
727        AcpiOsPrintf ("Breakpoint %X is beyond current address %X\n",
728            Address, Op->Common.AmlOffset);
729    }
730
731    /* Save breakpoint in current walk */
732
733    WalkState->UserBreakpoint = Address;
734    AcpiOsPrintf ("Breakpoint set at AML offset %X\n", Address);
735}
736
737
738/*******************************************************************************
739 *
740 * FUNCTION:    AcpiDbSetMethodCallBreakpoint
741 *
742 * PARAMETERS:  Op                  - Current Op (from parse walk)
743 *
744 * RETURN:      None
745 *
746 * DESCRIPTION: Set a breakpoint in a control method at the specified
747 *              AML offset
748 *
749 ******************************************************************************/
750
751void
752AcpiDbSetMethodCallBreakpoint (
753    ACPI_PARSE_OBJECT       *Op)
754{
755
756
757    if (!Op)
758    {
759        AcpiOsPrintf ("There is no method currently executing\n");
760        return;
761    }
762
763    AcpiGbl_StepToNextCall = TRUE;
764}
765
766
767/*******************************************************************************
768 *
769 * FUNCTION:    AcpiDbDisassembleAml
770 *
771 * PARAMETERS:  Statements          - Number of statements to disassemble
772 *              Op                  - Current Op (from parse walk)
773 *
774 * RETURN:      None
775 *
776 * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
777 *              of statements specified.
778 *
779 ******************************************************************************/
780
781void
782AcpiDbDisassembleAml (
783    char                    *Statements,
784    ACPI_PARSE_OBJECT       *Op)
785{
786    UINT32                  NumStatements = 8;
787
788
789    if (!Op)
790    {
791        AcpiOsPrintf ("There is no method currently executing\n");
792        return;
793    }
794
795    if (Statements)
796    {
797        NumStatements = ACPI_STRTOUL (Statements, NULL, 0);
798    }
799
800#ifdef ACPI_DISASSEMBLER
801    AcpiDmDisassemble (NULL, Op, NumStatements);
802#endif
803}
804
805
806/*******************************************************************************
807 *
808 * FUNCTION:    AcpiDbDisassembleMethod
809 *
810 * PARAMETERS:  Name            - Name of control method
811 *
812 * RETURN:      None
813 *
814 * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
815 *              of statements specified.
816 *
817 ******************************************************************************/
818
819ACPI_STATUS
820AcpiDbDisassembleMethod (
821    char                    *Name)
822{
823    ACPI_STATUS             Status;
824    ACPI_PARSE_OBJECT       *Op;
825    ACPI_WALK_STATE         *WalkState;
826    ACPI_OPERAND_OBJECT     *ObjDesc;
827    ACPI_NAMESPACE_NODE     *Method;
828
829
830    Method = AcpiDbConvertToNode (Name);
831    if (!Method)
832    {
833        return (AE_BAD_PARAMETER);
834    }
835
836    ObjDesc = Method->Object;
837
838    Op = AcpiPsCreateScopeOp ();
839    if (!Op)
840    {
841        return (AE_NO_MEMORY);
842    }
843
844    /* Create and initialize a new walk state */
845
846    WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL);
847    if (!WalkState)
848    {
849        return (AE_NO_MEMORY);
850    }
851
852    Status = AcpiDsInitAmlWalk (WalkState, Op, NULL,
853                    ObjDesc->Method.AmlStart,
854                    ObjDesc->Method.AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
855    if (ACPI_FAILURE (Status))
856    {
857        return (Status);
858    }
859
860    /* Parse the AML */
861
862    WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
863    WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
864    Status = AcpiPsParseAml (WalkState);
865
866#ifdef ACPI_DISASSEMBLER
867    AcpiDmDisassemble (NULL, Op, 0);
868#endif
869    AcpiPsDeleteParseTree (Op);
870    return (AE_OK);
871}
872
873
874/*******************************************************************************
875 *
876 * FUNCTION:    AcpiDbDumpNamespace
877 *
878 * PARAMETERS:  StartArg        - Node to begin namespace dump
879 *              DepthArg        - Maximum tree depth to be dumped
880 *
881 * RETURN:      None
882 *
883 * DESCRIPTION: Dump entire namespace or a subtree.  Each node is displayed
884 *              with type and other information.
885 *
886 ******************************************************************************/
887
888void
889AcpiDbDumpNamespace (
890    char                    *StartArg,
891    char                    *DepthArg)
892{
893    ACPI_HANDLE             SubtreeEntry = AcpiGbl_RootNode;
894    UINT32                  MaxDepth = ACPI_UINT32_MAX;
895
896
897    /* No argument given, just start at the root and dump entire namespace */
898
899    if (StartArg)
900    {
901        SubtreeEntry = AcpiDbConvertToNode (StartArg);
902        if (!SubtreeEntry)
903        {
904            return;
905        }
906
907        /* Now we can check for the depth argument */
908
909        if (DepthArg)
910        {
911            MaxDepth = ACPI_STRTOUL (DepthArg, NULL, 0);
912        }
913    }
914
915    AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);
916    AcpiOsPrintf ("ACPI Namespace (from %4.4s (%p) subtree):\n",
917        ((ACPI_NAMESPACE_NODE *) SubtreeEntry)->Name.Ascii, SubtreeEntry);
918
919    /* Display the subtree */
920
921    AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);
922    AcpiNsDumpObjects (ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, MaxDepth,
923        ACPI_OWNER_ID_MAX, SubtreeEntry);
924    AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
925}
926
927
928/*******************************************************************************
929 *
930 * FUNCTION:    AcpiDbDumpNamespaceByOwner
931 *
932 * PARAMETERS:  OwnerArg        - Owner ID whose nodes will be displayed
933 *              DepthArg        - Maximum tree depth to be dumped
934 *
935 * RETURN:      None
936 *
937 * DESCRIPTION: Dump elements of the namespace that are owned by the OwnerId.
938 *
939 ******************************************************************************/
940
941void
942AcpiDbDumpNamespaceByOwner (
943    char                    *OwnerArg,
944    char                    *DepthArg)
945{
946    ACPI_HANDLE             SubtreeEntry = AcpiGbl_RootNode;
947    UINT32                  MaxDepth = ACPI_UINT32_MAX;
948    ACPI_OWNER_ID           OwnerId;
949
950
951    OwnerId = (ACPI_OWNER_ID) ACPI_STRTOUL (OwnerArg, NULL, 0);
952
953    /* Now we can check for the depth argument */
954
955    if (DepthArg)
956    {
957        MaxDepth = ACPI_STRTOUL (DepthArg, NULL, 0);
958    }
959
960    AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);
961    AcpiOsPrintf ("ACPI Namespace by owner %X:\n", OwnerId);
962
963    /* Display the subtree */
964
965    AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);
966    AcpiNsDumpObjects (ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, MaxDepth, OwnerId,
967        SubtreeEntry);
968    AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
969}
970
971
972/*******************************************************************************
973 *
974 * FUNCTION:    AcpiDbSendNotify
975 *
976 * PARAMETERS:  Name            - Name of ACPI object to send the notify to
977 *              Value           - Value of the notify to send.
978 *
979 * RETURN:      None
980 *
981 * DESCRIPTION: Send an ACPI notification.  The value specified is sent to the
982 *              named object as an ACPI notify.
983 *
984 ******************************************************************************/
985
986void
987AcpiDbSendNotify (
988    char                    *Name,
989    UINT32                  Value)
990{
991    ACPI_NAMESPACE_NODE     *Node;
992    ACPI_STATUS             Status;
993
994
995    /* Translate name to an Named object */
996
997    Node = AcpiDbConvertToNode (Name);
998    if (!Node)
999    {
1000        return;
1001    }
1002
1003    /* Decode Named object type */
1004
1005    switch (Node->Type)
1006    {
1007    case ACPI_TYPE_DEVICE:
1008    case ACPI_TYPE_THERMAL:
1009
1010         /* Send the notify */
1011
1012        Status = AcpiEvQueueNotifyRequest (Node, Value);
1013        if (ACPI_FAILURE (Status))
1014        {
1015            AcpiOsPrintf ("Could not queue notify\n");
1016        }
1017        break;
1018
1019    default:
1020        AcpiOsPrintf ("Named object is not a device or a thermal object\n");
1021        break;
1022    }
1023}
1024
1025
1026/*******************************************************************************
1027 *
1028 * FUNCTION:    AcpiDbSetMethodData
1029 *
1030 * PARAMETERS:  TypeArg         - L for local, A for argument
1031 *              IndexArg        - which one
1032 *              ValueArg        - Value to set.
1033 *
1034 * RETURN:      None
1035 *
1036 * DESCRIPTION: Set a local or argument for the running control method.
1037 *              NOTE: only object supported is Number.
1038 *
1039 ******************************************************************************/
1040
1041void
1042AcpiDbSetMethodData (
1043    char                    *TypeArg,
1044    char                    *IndexArg,
1045    char                    *ValueArg)
1046{
1047    char                    Type;
1048    UINT32                  Index;
1049    UINT32                  Value;
1050    ACPI_WALK_STATE         *WalkState;
1051    ACPI_OPERAND_OBJECT     *ObjDesc;
1052    ACPI_STATUS             Status;
1053    ACPI_NAMESPACE_NODE     *Node;
1054
1055
1056    /* Validate TypeArg */
1057
1058    AcpiUtStrupr (TypeArg);
1059    Type = TypeArg[0];
1060    if ((Type != 'L') &&
1061        (Type != 'A') &&
1062        (Type != 'N'))
1063    {
1064        AcpiOsPrintf ("Invalid SET operand: %s\n", TypeArg);
1065        return;
1066    }
1067
1068    Value = ACPI_STRTOUL (ValueArg, NULL, 16);
1069
1070    if (Type == 'N')
1071    {
1072        Node = AcpiDbConvertToNode (IndexArg);
1073        if (Node->Type != ACPI_TYPE_INTEGER)
1074        {
1075            AcpiOsPrintf ("Can only set Integer nodes\n");
1076            return;
1077        }
1078        ObjDesc = Node->Object;
1079        ObjDesc->Integer.Value = Value;
1080        return;
1081    }
1082
1083    /* Get the index and value */
1084
1085    Index = ACPI_STRTOUL (IndexArg, NULL, 16);
1086
1087    WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList);
1088    if (!WalkState)
1089    {
1090        AcpiOsPrintf ("There is no method currently executing\n");
1091        return;
1092    }
1093
1094    /* Create and initialize the new object */
1095
1096    ObjDesc = AcpiUtCreateIntegerObject ((UINT64) Value);
1097    if (!ObjDesc)
1098    {
1099        AcpiOsPrintf ("Could not create an internal object\n");
1100        return;
1101    }
1102
1103    /* Store the new object into the target */
1104
1105    switch (Type)
1106    {
1107    case 'A':
1108
1109        /* Set a method argument */
1110
1111        if (Index > ACPI_METHOD_MAX_ARG)
1112        {
1113            AcpiOsPrintf ("Arg%u - Invalid argument name\n", Index);
1114            goto Cleanup;
1115        }
1116
1117        Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_ARG, Index, ObjDesc,
1118                    WalkState);
1119        if (ACPI_FAILURE (Status))
1120        {
1121            goto Cleanup;
1122        }
1123
1124        ObjDesc = WalkState->Arguments[Index].Object;
1125
1126        AcpiOsPrintf ("Arg%u: ", Index);
1127        AcpiDmDisplayInternalObject (ObjDesc, WalkState);
1128        break;
1129
1130    case 'L':
1131
1132        /* Set a method local */
1133
1134        if (Index > ACPI_METHOD_MAX_LOCAL)
1135        {
1136            AcpiOsPrintf ("Local%u - Invalid local variable name\n", Index);
1137            goto Cleanup;
1138        }
1139
1140        Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_LOCAL, Index, ObjDesc,
1141                    WalkState);
1142        if (ACPI_FAILURE (Status))
1143        {
1144            goto Cleanup;
1145        }
1146
1147        ObjDesc = WalkState->LocalVariables[Index].Object;
1148
1149        AcpiOsPrintf ("Local%u: ", Index);
1150        AcpiDmDisplayInternalObject (ObjDesc, WalkState);
1151        break;
1152
1153    default:
1154        break;
1155    }
1156
1157Cleanup:
1158    AcpiUtRemoveReference (ObjDesc);
1159}
1160
1161
1162/*******************************************************************************
1163 *
1164 * FUNCTION:    AcpiDbWalkForSpecificObjects
1165 *
1166 * PARAMETERS:  Callback from WalkNamespace
1167 *
1168 * RETURN:      Status
1169 *
1170 * DESCRIPTION: Display short info about objects in the namespace
1171 *
1172 ******************************************************************************/
1173
1174static ACPI_STATUS
1175AcpiDbWalkForSpecificObjects (
1176    ACPI_HANDLE             ObjHandle,
1177    UINT32                  NestingLevel,
1178    void                    *Context,
1179    void                    **ReturnValue)
1180{
1181    ACPI_WALK_INFO          *Info = (ACPI_WALK_INFO *) Context;
1182    ACPI_BUFFER             Buffer;
1183    ACPI_STATUS             Status;
1184
1185
1186    Info->Count++;
1187
1188    /* Get and display the full pathname to this object */
1189
1190    Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
1191    Status = AcpiNsHandleToPathname (ObjHandle, &Buffer);
1192    if (ACPI_FAILURE (Status))
1193    {
1194        AcpiOsPrintf ("Could Not get pathname for object %p\n", ObjHandle);
1195        return (AE_OK);
1196    }
1197
1198    AcpiOsPrintf ("%32s", (char *) Buffer.Pointer);
1199    ACPI_FREE (Buffer.Pointer);
1200
1201    /* Dump short info about the object */
1202
1203    (void) AcpiNsDumpOneObject (ObjHandle, NestingLevel, Info, NULL);
1204    return (AE_OK);
1205}
1206
1207
1208/*******************************************************************************
1209 *
1210 * FUNCTION:    AcpiDbDisplayObjects
1211 *
1212 * PARAMETERS:  ObjTypeArg          - Type of object to display
1213 *              DisplayCountArg     - Max depth to display
1214 *
1215 * RETURN:      None
1216 *
1217 * DESCRIPTION: Display objects in the namespace of the requested type
1218 *
1219 ******************************************************************************/
1220
1221ACPI_STATUS
1222AcpiDbDisplayObjects (
1223    char                    *ObjTypeArg,
1224    char                    *DisplayCountArg)
1225{
1226    ACPI_WALK_INFO          Info;
1227    ACPI_OBJECT_TYPE        Type;
1228
1229
1230    /* Get the object type */
1231
1232    Type = AcpiDbMatchArgument (ObjTypeArg, AcpiDbObjectTypes);
1233    if (Type == ACPI_TYPE_NOT_FOUND)
1234    {
1235        AcpiOsPrintf ("Invalid or unsupported argument\n");
1236        return (AE_OK);
1237    }
1238
1239    AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);
1240    AcpiOsPrintf (
1241        "Objects of type [%s] defined in the current ACPI Namespace:\n",
1242        AcpiUtGetTypeName (Type));
1243
1244    AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);
1245
1246    Info.Count = 0;
1247    Info.OwnerId = ACPI_OWNER_ID_MAX;
1248    Info.DebugLevel = ACPI_UINT32_MAX;
1249    Info.DisplayType = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT;
1250
1251    /* Walk the namespace from the root */
1252
1253    (void) AcpiWalkNamespace (Type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
1254                AcpiDbWalkForSpecificObjects, NULL, (void *) &Info, NULL);
1255
1256    AcpiOsPrintf (
1257        "\nFound %u objects of type [%s] in the current ACPI Namespace\n",
1258        Info.Count, AcpiUtGetTypeName (Type));
1259
1260    AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
1261    return (AE_OK);
1262}
1263
1264
1265/*******************************************************************************
1266 *
1267 * FUNCTION:    AcpiDbDisplayInterfaces
1268 *
1269 * PARAMETERS:  ActionArg           - Null, "install", or "remove"
1270 *              InterfaceNameArg    - Name for install/remove options
1271 *
1272 * RETURN:      None
1273 *
1274 * DESCRIPTION: Display or modify the global _OSI interface list
1275 *
1276 ******************************************************************************/
1277
1278void
1279AcpiDbDisplayInterfaces (
1280    char                    *ActionArg,
1281    char                    *InterfaceNameArg)
1282{
1283    ACPI_INTERFACE_INFO     *NextInterface;
1284    char                    *SubString;
1285    ACPI_STATUS             Status;
1286
1287
1288    /* If no arguments, just display current interface list */
1289
1290    if (!ActionArg)
1291    {
1292        (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex,
1293                    ACPI_WAIT_FOREVER);
1294
1295        NextInterface = AcpiGbl_SupportedInterfaces;
1296
1297        while (NextInterface)
1298        {
1299            if (!(NextInterface->Flags & ACPI_OSI_INVALID))
1300            {
1301                AcpiOsPrintf ("%s\n", NextInterface->Name);
1302            }
1303            NextInterface = NextInterface->Next;
1304        }
1305
1306        AcpiOsReleaseMutex (AcpiGbl_OsiMutex);
1307        return;
1308    }
1309
1310    /* If ActionArg exists, so must InterfaceNameArg */
1311
1312    if (!InterfaceNameArg)
1313    {
1314        AcpiOsPrintf ("Missing Interface Name argument\n");
1315        return;
1316    }
1317
1318    /* Uppercase the action for match below */
1319
1320    AcpiUtStrupr (ActionArg);
1321
1322    /* Install - install an interface */
1323
1324    SubString = ACPI_STRSTR ("INSTALL", ActionArg);
1325    if (SubString)
1326    {
1327        Status = AcpiInstallInterface (InterfaceNameArg);
1328        if (ACPI_FAILURE (Status))
1329        {
1330            AcpiOsPrintf ("%s, while installing \"%s\"\n",
1331                AcpiFormatException (Status), InterfaceNameArg);
1332        }
1333        return;
1334    }
1335
1336    /* Remove - remove an interface */
1337
1338    SubString = ACPI_STRSTR ("REMOVE", ActionArg);
1339    if (SubString)
1340    {
1341        Status = AcpiRemoveInterface (InterfaceNameArg);
1342        if (ACPI_FAILURE (Status))
1343        {
1344            AcpiOsPrintf ("%s, while removing \"%s\"\n",
1345                AcpiFormatException (Status), InterfaceNameArg);
1346        }
1347        return;
1348    }
1349
1350    /* Invalid ActionArg */
1351
1352    AcpiOsPrintf ("Invalid action argument: %s\n", ActionArg);
1353    return;
1354}
1355
1356
1357/*******************************************************************************
1358 *
1359 * FUNCTION:    AcpiDbWalkAndMatchName
1360 *
1361 * PARAMETERS:  Callback from WalkNamespace
1362 *
1363 * RETURN:      Status
1364 *
1365 * DESCRIPTION: Find a particular name/names within the namespace.  Wildcards
1366 *              are supported -- '?' matches any character.
1367 *
1368 ******************************************************************************/
1369
1370static ACPI_STATUS
1371AcpiDbWalkAndMatchName (
1372    ACPI_HANDLE             ObjHandle,
1373    UINT32                  NestingLevel,
1374    void                    *Context,
1375    void                    **ReturnValue)
1376{
1377    ACPI_STATUS             Status;
1378    char                    *RequestedName = (char *) Context;
1379    UINT32                  i;
1380    ACPI_BUFFER             Buffer;
1381    ACPI_WALK_INFO          Info;
1382
1383
1384    /* Check for a name match */
1385
1386    for (i = 0; i < 4; i++)
1387    {
1388        /* Wildcard support */
1389
1390        if ((RequestedName[i] != '?') &&
1391            (RequestedName[i] != ((ACPI_NAMESPACE_NODE *) ObjHandle)->Name.Ascii[i]))
1392        {
1393            /* No match, just exit */
1394
1395            return (AE_OK);
1396        }
1397    }
1398
1399    /* Get the full pathname to this object */
1400
1401    Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
1402    Status = AcpiNsHandleToPathname (ObjHandle, &Buffer);
1403    if (ACPI_FAILURE (Status))
1404    {
1405        AcpiOsPrintf ("Could Not get pathname for object %p\n", ObjHandle);
1406    }
1407    else
1408    {
1409        Info.OwnerId = ACPI_OWNER_ID_MAX;
1410        Info.DebugLevel = ACPI_UINT32_MAX;
1411        Info.DisplayType = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT;
1412
1413        AcpiOsPrintf ("%32s", (char *) Buffer.Pointer);
1414        (void) AcpiNsDumpOneObject (ObjHandle, NestingLevel, &Info, NULL);
1415        ACPI_FREE (Buffer.Pointer);
1416    }
1417
1418    return (AE_OK);
1419}
1420
1421
1422/*******************************************************************************
1423 *
1424 * FUNCTION:    AcpiDbFindNameInNamespace
1425 *
1426 * PARAMETERS:  NameArg         - The 4-character ACPI name to find.
1427 *                                wildcards are supported.
1428 *
1429 * RETURN:      None
1430 *
1431 * DESCRIPTION: Search the namespace for a given name (with wildcards)
1432 *
1433 ******************************************************************************/
1434
1435ACPI_STATUS
1436AcpiDbFindNameInNamespace (
1437    char                    *NameArg)
1438{
1439    char                    AcpiName[5] = "____";
1440    char                    *AcpiNamePtr = AcpiName;
1441
1442
1443    if (ACPI_STRLEN (NameArg) > 4)
1444    {
1445        AcpiOsPrintf ("Name must be no longer than 4 characters\n");
1446        return (AE_OK);
1447    }
1448
1449    /* Pad out name with underscores as necessary to create a 4-char name */
1450
1451    AcpiUtStrupr (NameArg);
1452    while (*NameArg)
1453    {
1454        *AcpiNamePtr = *NameArg;
1455        AcpiNamePtr++;
1456        NameArg++;
1457    }
1458
1459    /* Walk the namespace from the root */
1460
1461    (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
1462                        AcpiDbWalkAndMatchName, NULL, AcpiName, NULL);
1463
1464    AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
1465    return (AE_OK);
1466}
1467
1468
1469/*******************************************************************************
1470 *
1471 * FUNCTION:    AcpiDbSetScope
1472 *
1473 * PARAMETERS:  Name                - New scope path
1474 *
1475 * RETURN:      Status
1476 *
1477 * DESCRIPTION: Set the "current scope" as maintained by this utility.
1478 *              The scope is used as a prefix to ACPI paths.
1479 *
1480 ******************************************************************************/
1481
1482void
1483AcpiDbSetScope (
1484    char                    *Name)
1485{
1486    ACPI_STATUS             Status;
1487    ACPI_NAMESPACE_NODE     *Node;
1488
1489
1490    if (!Name || Name[0] == 0)
1491    {
1492        AcpiOsPrintf ("Current scope: %s\n", AcpiGbl_DbScopeBuf);
1493        return;
1494    }
1495
1496    AcpiDbPrepNamestring (Name);
1497
1498    if (Name[0] == '\\')
1499    {
1500        /* Validate new scope from the root */
1501
1502        Status = AcpiNsGetNode (AcpiGbl_RootNode, Name, ACPI_NS_NO_UPSEARCH,
1503                    &Node);
1504        if (ACPI_FAILURE (Status))
1505        {
1506            goto ErrorExit;
1507        }
1508
1509        ACPI_STRCPY (AcpiGbl_DbScopeBuf, Name);
1510        ACPI_STRCAT (AcpiGbl_DbScopeBuf, "\\");
1511    }
1512    else
1513    {
1514        /* Validate new scope relative to old scope */
1515
1516        Status = AcpiNsGetNode (AcpiGbl_DbScopeNode, Name, ACPI_NS_NO_UPSEARCH,
1517                    &Node);
1518        if (ACPI_FAILURE (Status))
1519        {
1520            goto ErrorExit;
1521        }
1522
1523        ACPI_STRCAT (AcpiGbl_DbScopeBuf, Name);
1524        ACPI_STRCAT (AcpiGbl_DbScopeBuf, "\\");
1525    }
1526
1527    AcpiGbl_DbScopeNode = Node;
1528    AcpiOsPrintf ("New scope: %s\n", AcpiGbl_DbScopeBuf);
1529    return;
1530
1531ErrorExit:
1532
1533    AcpiOsPrintf ("Could not attach scope: %s, %s\n",
1534        Name, AcpiFormatException (Status));
1535}
1536
1537
1538/*******************************************************************************
1539 *
1540 * FUNCTION:    AcpiDmCompareAmlResources
1541 *
1542 * PARAMETERS:  Aml1Buffer          - Contains first resource list
1543 *              Aml1BufferLength    - Length of first resource list
1544 *              Aml2Buffer          - Contains second resource list
1545 *              Aml2BufferLength    - Length of second resource list
1546 *
1547 * RETURN:      None
1548 *
1549 * DESCRIPTION: Compare two AML resource lists, descriptor by descriptor (in
1550 *              order to isolate a miscompare to an individual resource)
1551 *
1552 ******************************************************************************/
1553
1554static void
1555AcpiDmCompareAmlResources (
1556    UINT8                   *Aml1Buffer,
1557    ACPI_RSDESC_SIZE        Aml1BufferLength,
1558    UINT8                   *Aml2Buffer,
1559    ACPI_RSDESC_SIZE        Aml2BufferLength)
1560{
1561    UINT8                   *Aml1;
1562    UINT8                   *Aml2;
1563    ACPI_RSDESC_SIZE        Aml1Length;
1564    ACPI_RSDESC_SIZE        Aml2Length;
1565    ACPI_RSDESC_SIZE        Offset = 0;
1566    UINT8                   ResourceType;
1567    UINT32                  Count = 0;
1568
1569
1570    /* Compare overall buffer sizes (may be different due to size rounding) */
1571
1572    if (Aml1BufferLength != Aml2BufferLength)
1573    {
1574        AcpiOsPrintf (
1575            "**** Buffer length mismatch in converted AML: original %X new %X ****\n",
1576            Aml1BufferLength, Aml2BufferLength);
1577    }
1578
1579    Aml1 = Aml1Buffer;
1580    Aml2 = Aml2Buffer;
1581
1582    /* Walk the descriptor lists, comparing each descriptor */
1583
1584    while (Aml1 < (Aml1Buffer + Aml1BufferLength))
1585    {
1586        /* Get the lengths of each descriptor */
1587
1588        Aml1Length = AcpiUtGetDescriptorLength (Aml1);
1589        Aml2Length = AcpiUtGetDescriptorLength (Aml2);
1590        ResourceType = AcpiUtGetResourceType (Aml1);
1591
1592        /* Check for descriptor length match */
1593
1594        if (Aml1Length != Aml2Length)
1595        {
1596            AcpiOsPrintf (
1597                "**** Length mismatch in descriptor [%.2X] type %2.2X, Offset %8.8X L1 %X L2 %X ****\n",
1598                Count, ResourceType, Offset, Aml1Length, Aml2Length);
1599        }
1600
1601        /* Check for descriptor byte match */
1602
1603        else if (ACPI_MEMCMP (Aml1, Aml2, Aml1Length))
1604        {
1605            AcpiOsPrintf (
1606                "**** Data mismatch in descriptor [%.2X] type %2.2X, Offset %8.8X ****\n",
1607                Count, ResourceType, Offset);
1608        }
1609
1610        /* Exit on EndTag descriptor */
1611
1612        if (ResourceType == ACPI_RESOURCE_NAME_END_TAG)
1613        {
1614            return;
1615        }
1616
1617        /* Point to next descriptor in each buffer */
1618
1619        Count++;
1620        Offset += Aml1Length;
1621        Aml1 += Aml1Length;
1622        Aml2 += Aml2Length;
1623    }
1624}
1625
1626
1627/*******************************************************************************
1628 *
1629 * FUNCTION:    AcpiDmTestResourceConversion
1630 *
1631 * PARAMETERS:  Node            - Parent device node
1632 *              Name            - resource method name (_CRS)
1633 *
1634 * RETURN:      Status
1635 *
1636 * DESCRIPTION: Compare the original AML with a conversion of the AML to
1637 *              internal resource list, then back to AML.
1638 *
1639 ******************************************************************************/
1640
1641static ACPI_STATUS
1642AcpiDmTestResourceConversion (
1643    ACPI_NAMESPACE_NODE     *Node,
1644    char                    *Name)
1645{
1646    ACPI_STATUS             Status;
1647    ACPI_BUFFER             ReturnObj;
1648    ACPI_BUFFER             ResourceObj;
1649    ACPI_BUFFER             NewAml;
1650    ACPI_OBJECT             *OriginalAml;
1651
1652
1653    AcpiOsPrintf ("Resource Conversion Comparison:\n");
1654
1655    NewAml.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
1656    ReturnObj.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
1657    ResourceObj.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
1658
1659    /* Get the original _CRS AML resource template */
1660
1661    Status = AcpiEvaluateObject (Node, Name, NULL, &ReturnObj);
1662    if (ACPI_FAILURE (Status))
1663    {
1664        AcpiOsPrintf ("Could not obtain %s: %s\n",
1665            Name, AcpiFormatException (Status));
1666        return (Status);
1667    }
1668
1669    /* Get the AML resource template, converted to internal resource structs */
1670
1671    Status = AcpiGetCurrentResources (Node, &ResourceObj);
1672    if (ACPI_FAILURE (Status))
1673    {
1674        AcpiOsPrintf ("AcpiGetCurrentResources failed: %s\n",
1675            AcpiFormatException (Status));
1676        goto Exit1;
1677    }
1678
1679    /* Convert internal resource list to external AML resource template */
1680
1681    Status = AcpiRsCreateAmlResources (ResourceObj.Pointer, &NewAml);
1682    if (ACPI_FAILURE (Status))
1683    {
1684        AcpiOsPrintf ("AcpiRsCreateAmlResources failed: %s\n",
1685            AcpiFormatException (Status));
1686        goto Exit2;
1687    }
1688
1689    /* Compare original AML to the newly created AML resource list */
1690
1691    OriginalAml = ReturnObj.Pointer;
1692
1693    AcpiDmCompareAmlResources (
1694        OriginalAml->Buffer.Pointer, (ACPI_RSDESC_SIZE) OriginalAml->Buffer.Length,
1695        NewAml.Pointer, (ACPI_RSDESC_SIZE) NewAml.Length);
1696
1697    /* Cleanup and exit */
1698
1699    ACPI_FREE (NewAml.Pointer);
1700Exit2:
1701    ACPI_FREE (ResourceObj.Pointer);
1702Exit1:
1703    ACPI_FREE (ReturnObj.Pointer);
1704    return (Status);
1705}
1706
1707
1708/*******************************************************************************
1709 *
1710 * FUNCTION:    AcpiDbDisplayResources
1711 *
1712 * PARAMETERS:  ObjectArg       - String with hex value of the object
1713 *
1714 * RETURN:      None
1715 *
1716 * DESCRIPTION: Display the resource objects associated with a device.
1717 *
1718 ******************************************************************************/
1719
1720void
1721AcpiDbDisplayResources (
1722    char                    *ObjectArg)
1723{
1724    ACPI_NAMESPACE_NODE     *Node;
1725    ACPI_STATUS             Status;
1726    ACPI_BUFFER             ReturnObj;
1727
1728
1729    AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);
1730    AcpiDbgLevel |= ACPI_LV_RESOURCES;
1731
1732    /* Convert string to object pointer */
1733
1734    Node = AcpiDbConvertToNode (ObjectArg);
1735    if (!Node)
1736    {
1737        return;
1738    }
1739
1740    /* Prepare for a return object of arbitrary size */
1741
1742    ReturnObj.Pointer = AcpiGbl_DbBuffer;
1743    ReturnObj.Length  = ACPI_DEBUG_BUFFER_SIZE;
1744
1745    /* _PRT */
1746
1747    AcpiOsPrintf ("Evaluating _PRT\n");
1748
1749    /* Check if _PRT exists */
1750
1751    Status = AcpiEvaluateObject (Node, METHOD_NAME__PRT, NULL, &ReturnObj);
1752    if (ACPI_FAILURE (Status))
1753    {
1754        AcpiOsPrintf ("Could not obtain _PRT: %s\n",
1755            AcpiFormatException (Status));
1756        goto GetCrs;
1757    }
1758
1759    ReturnObj.Pointer = AcpiGbl_DbBuffer;
1760    ReturnObj.Length  = ACPI_DEBUG_BUFFER_SIZE;
1761
1762    Status = AcpiGetIrqRoutingTable (Node, &ReturnObj);
1763    if (ACPI_FAILURE (Status))
1764    {
1765        AcpiOsPrintf ("GetIrqRoutingTable failed: %s\n",
1766            AcpiFormatException (Status));
1767        goto GetCrs;
1768    }
1769
1770    AcpiRsDumpIrqList (ACPI_CAST_PTR (UINT8, AcpiGbl_DbBuffer));
1771
1772
1773    /* _CRS */
1774
1775GetCrs:
1776    AcpiOsPrintf ("Evaluating _CRS\n");
1777
1778    ReturnObj.Pointer = AcpiGbl_DbBuffer;
1779    ReturnObj.Length  = ACPI_DEBUG_BUFFER_SIZE;
1780
1781    /* Check if _CRS exists */
1782
1783    Status = AcpiEvaluateObject (Node, METHOD_NAME__CRS, NULL, &ReturnObj);
1784    if (ACPI_FAILURE (Status))
1785    {
1786        AcpiOsPrintf ("Could not obtain _CRS: %s\n",
1787            AcpiFormatException (Status));
1788        goto GetPrs;
1789    }
1790
1791    /* Get the _CRS resource list */
1792
1793    ReturnObj.Pointer = AcpiGbl_DbBuffer;
1794    ReturnObj.Length  = ACPI_DEBUG_BUFFER_SIZE;
1795
1796    Status = AcpiGetCurrentResources (Node, &ReturnObj);
1797    if (ACPI_FAILURE (Status))
1798    {
1799        AcpiOsPrintf ("AcpiGetCurrentResources failed: %s\n",
1800            AcpiFormatException (Status));
1801        goto GetPrs;
1802    }
1803
1804    /* Dump the _CRS resource list */
1805
1806    AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE,
1807        ReturnObj.Pointer));
1808
1809    /*
1810     * Perform comparison of original AML to newly created AML. This tests both
1811     * the AML->Resource conversion and the Resource->Aml conversion.
1812     */
1813    Status = AcpiDmTestResourceConversion (Node, METHOD_NAME__CRS);
1814
1815    /* Execute _SRS with the resource list */
1816
1817    Status = AcpiSetCurrentResources (Node, &ReturnObj);
1818    if (ACPI_FAILURE (Status))
1819    {
1820        AcpiOsPrintf ("AcpiSetCurrentResources failed: %s\n",
1821            AcpiFormatException (Status));
1822        goto GetPrs;
1823    }
1824
1825
1826    /* _PRS */
1827
1828GetPrs:
1829    AcpiOsPrintf ("Evaluating _PRS\n");
1830
1831    ReturnObj.Pointer = AcpiGbl_DbBuffer;
1832    ReturnObj.Length  = ACPI_DEBUG_BUFFER_SIZE;
1833
1834    /* Check if _PRS exists */
1835
1836    Status = AcpiEvaluateObject (Node, METHOD_NAME__PRS, NULL, &ReturnObj);
1837    if (ACPI_FAILURE (Status))
1838    {
1839        AcpiOsPrintf ("Could not obtain _PRS: %s\n",
1840            AcpiFormatException (Status));
1841        goto Cleanup;
1842    }
1843
1844    ReturnObj.Pointer = AcpiGbl_DbBuffer;
1845    ReturnObj.Length  = ACPI_DEBUG_BUFFER_SIZE;
1846
1847    Status = AcpiGetPossibleResources (Node, &ReturnObj);
1848    if (ACPI_FAILURE (Status))
1849    {
1850        AcpiOsPrintf ("AcpiGetPossibleResources failed: %s\n",
1851            AcpiFormatException (Status));
1852        goto Cleanup;
1853    }
1854
1855    AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE, AcpiGbl_DbBuffer));
1856
1857Cleanup:
1858
1859    AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
1860    return;
1861}
1862
1863
1864/*******************************************************************************
1865 *
1866 * FUNCTION:    AcpiDbIntegrityWalk
1867 *
1868 * PARAMETERS:  Callback from WalkNamespace
1869 *
1870 * RETURN:      Status
1871 *
1872 * DESCRIPTION: Examine one NS node for valid values.
1873 *
1874 ******************************************************************************/
1875
1876static ACPI_STATUS
1877AcpiDbIntegrityWalk (
1878    ACPI_HANDLE             ObjHandle,
1879    UINT32                  NestingLevel,
1880    void                    *Context,
1881    void                    **ReturnValue)
1882{
1883    ACPI_INTEGRITY_INFO     *Info = (ACPI_INTEGRITY_INFO *) Context;
1884    ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
1885    ACPI_OPERAND_OBJECT     *Object;
1886    BOOLEAN                 Alias = TRUE;
1887
1888
1889    Info->Nodes++;
1890
1891    /* Verify the NS node, and dereference aliases */
1892
1893    while (Alias)
1894    {
1895        if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED)
1896        {
1897            AcpiOsPrintf ("Invalid Descriptor Type for Node %p [%s] - is %2.2X should be %2.2X\n",
1898                Node, AcpiUtGetDescriptorName (Node), ACPI_GET_DESCRIPTOR_TYPE (Node),
1899                ACPI_DESC_TYPE_NAMED);
1900            return (AE_OK);
1901        }
1902
1903        if ((Node->Type == ACPI_TYPE_LOCAL_ALIAS)  ||
1904            (Node->Type == ACPI_TYPE_LOCAL_METHOD_ALIAS))
1905        {
1906            Node = (ACPI_NAMESPACE_NODE *) Node->Object;
1907        }
1908        else
1909        {
1910            Alias = FALSE;
1911        }
1912    }
1913
1914    if (Node->Type > ACPI_TYPE_LOCAL_MAX)
1915    {
1916        AcpiOsPrintf ("Invalid Object Type for Node %p, Type = %X\n",
1917            Node, Node->Type);
1918        return (AE_OK);
1919    }
1920
1921    if (!AcpiUtValidAcpiName (Node->Name.Integer))
1922    {
1923        AcpiOsPrintf ("Invalid AcpiName for Node %p\n", Node);
1924        return (AE_OK);
1925    }
1926
1927    Object = AcpiNsGetAttachedObject (Node);
1928    if (Object)
1929    {
1930        Info->Objects++;
1931        if (ACPI_GET_DESCRIPTOR_TYPE (Object) != ACPI_DESC_TYPE_OPERAND)
1932        {
1933            AcpiOsPrintf ("Invalid Descriptor Type for Object %p [%s]\n",
1934                Object, AcpiUtGetDescriptorName (Object));
1935        }
1936    }
1937
1938    return (AE_OK);
1939}
1940
1941
1942/*******************************************************************************
1943 *
1944 * FUNCTION:    AcpiDbCheckIntegrity
1945 *
1946 * PARAMETERS:  None
1947 *
1948 * RETURN:      None
1949 *
1950 * DESCRIPTION: Check entire namespace for data structure integrity
1951 *
1952 ******************************************************************************/
1953
1954void
1955AcpiDbCheckIntegrity (
1956    void)
1957{
1958    ACPI_INTEGRITY_INFO     Info = {0,0};
1959
1960    /* Search all nodes in namespace */
1961
1962    (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
1963                    AcpiDbIntegrityWalk, NULL, (void *) &Info, NULL);
1964
1965    AcpiOsPrintf ("Verified %u namespace nodes with %u Objects\n",
1966        Info.Nodes, Info.Objects);
1967}
1968
1969
1970/*******************************************************************************
1971 *
1972 * FUNCTION:    AcpiDbGenerateGpe
1973 *
1974 * PARAMETERS:  GpeArg          - Raw GPE number, ascii string
1975 *              BlockArg        - GPE block number, ascii string
1976 *                                0 or 1 for FADT GPE blocks
1977 *
1978 * RETURN:      None
1979 *
1980 * DESCRIPTION: Generate a GPE
1981 *
1982 ******************************************************************************/
1983
1984void
1985AcpiDbGenerateGpe (
1986    char                    *GpeArg,
1987    char                    *BlockArg)
1988{
1989    UINT32                  BlockNumber;
1990    UINT32                  GpeNumber;
1991    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
1992
1993
1994    GpeNumber   = ACPI_STRTOUL (GpeArg, NULL, 0);
1995    BlockNumber = ACPI_STRTOUL (BlockArg, NULL, 0);
1996
1997
1998    GpeEventInfo = AcpiEvGetGpeEventInfo (ACPI_TO_POINTER (BlockNumber),
1999        GpeNumber);
2000    if (!GpeEventInfo)
2001    {
2002        AcpiOsPrintf ("Invalid GPE\n");
2003        return;
2004    }
2005
2006    (void) AcpiEvGpeDispatch (NULL, GpeEventInfo, GpeNumber);
2007}
2008
2009
2010/*******************************************************************************
2011 *
2012 * FUNCTION:    AcpiDbBusWalk
2013 *
2014 * PARAMETERS:  Callback from WalkNamespace
2015 *
2016 * RETURN:      Status
2017 *
2018 * DESCRIPTION: Display info about device objects that have a corresponding
2019 *              _PRT method.
2020 *
2021 ******************************************************************************/
2022
2023static ACPI_STATUS
2024AcpiDbBusWalk (
2025    ACPI_HANDLE             ObjHandle,
2026    UINT32                  NestingLevel,
2027    void                    *Context,
2028    void                    **ReturnValue)
2029{
2030    ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
2031    ACPI_STATUS             Status;
2032    ACPI_BUFFER             Buffer;
2033    ACPI_NAMESPACE_NODE     *TempNode;
2034    ACPI_DEVICE_INFO        *Info;
2035    UINT32                  i;
2036
2037
2038    if ((Node->Type != ACPI_TYPE_DEVICE) &&
2039        (Node->Type != ACPI_TYPE_PROCESSOR))
2040    {
2041        return (AE_OK);
2042    }
2043
2044    /* Exit if there is no _PRT under this device */
2045
2046    Status = AcpiGetHandle (Node, METHOD_NAME__PRT,
2047                ACPI_CAST_PTR (ACPI_HANDLE, &TempNode));
2048    if (ACPI_FAILURE (Status))
2049    {
2050        return (AE_OK);
2051    }
2052
2053    /* Get the full path to this device object */
2054
2055    Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
2056    Status = AcpiNsHandleToPathname (ObjHandle, &Buffer);
2057    if (ACPI_FAILURE (Status))
2058    {
2059        AcpiOsPrintf ("Could Not get pathname for object %p\n", ObjHandle);
2060        return (AE_OK);
2061    }
2062
2063    Status = AcpiGetObjectInfo (ObjHandle, &Info);
2064    if (ACPI_FAILURE (Status))
2065    {
2066        return (AE_OK);
2067    }
2068
2069    /* Display the full path */
2070
2071    AcpiOsPrintf ("%-32s Type %X", (char *) Buffer.Pointer, Node->Type);
2072    ACPI_FREE (Buffer.Pointer);
2073
2074    if (Info->Flags & ACPI_PCI_ROOT_BRIDGE)
2075    {
2076        AcpiOsPrintf ("  - Is PCI Root Bridge");
2077    }
2078    AcpiOsPrintf ("\n");
2079
2080    /* _PRT info */
2081
2082    AcpiOsPrintf ("_PRT: %p\n", TempNode);
2083
2084    /* Dump _ADR, _HID, _UID, _CID */
2085
2086    if (Info->Valid & ACPI_VALID_ADR)
2087    {
2088        AcpiOsPrintf ("_ADR: %8.8X%8.8X\n", ACPI_FORMAT_UINT64 (Info->Address));
2089    }
2090    else
2091    {
2092        AcpiOsPrintf ("_ADR: <Not Present>\n");
2093    }
2094
2095    if (Info->Valid & ACPI_VALID_HID)
2096    {
2097        AcpiOsPrintf ("_HID: %s\n", Info->HardwareId.String);
2098    }
2099    else
2100    {
2101        AcpiOsPrintf ("_HID: <Not Present>\n");
2102    }
2103
2104    if (Info->Valid & ACPI_VALID_UID)
2105    {
2106        AcpiOsPrintf ("_UID: %s\n", Info->UniqueId.String);
2107    }
2108    else
2109    {
2110        AcpiOsPrintf ("_UID: <Not Present>\n");
2111    }
2112
2113    if (Info->Valid & ACPI_VALID_CID)
2114    {
2115        for (i = 0; i < Info->CompatibleIdList.Count; i++)
2116        {
2117            AcpiOsPrintf ("_CID: %s\n",
2118                Info->CompatibleIdList.Ids[i].String);
2119        }
2120    }
2121    else
2122    {
2123        AcpiOsPrintf ("_CID: <Not Present>\n");
2124    }
2125
2126    ACPI_FREE (Info);
2127    return (AE_OK);
2128}
2129
2130
2131/*******************************************************************************
2132 *
2133 * FUNCTION:    AcpiDbGetBusInfo
2134 *
2135 * PARAMETERS:  None
2136 *
2137 * RETURN:      None
2138 *
2139 * DESCRIPTION: Display info about system busses.
2140 *
2141 ******************************************************************************/
2142
2143void
2144AcpiDbGetBusInfo (
2145    void)
2146{
2147    /* Search all nodes in namespace */
2148
2149    (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
2150                    AcpiDbBusWalk, NULL, NULL, NULL);
2151}
2152
2153#endif /* ACPI_DEBUGGER */
2154