dbcmds.c revision 281075
1/*******************************************************************************
2 *
3 * Module Name: dbcmds - Miscellaneous debug commands and output routines
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2015, 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#include <contrib/dev/acpica/include/acpi.h>
45#include <contrib/dev/acpica/include/accommon.h>
46#include <contrib/dev/acpica/include/acevents.h>
47#include <contrib/dev/acpica/include/acdebug.h>
48#include <contrib/dev/acpica/include/acnamesp.h>
49#include <contrib/dev/acpica/include/acresrc.h>
50#include <contrib/dev/acpica/include/actables.h>
51
52#ifdef ACPI_DEBUGGER
53
54#define _COMPONENT          ACPI_CA_DEBUGGER
55        ACPI_MODULE_NAME    ("dbcmds")
56
57
58/* Local prototypes */
59
60static void
61AcpiDmCompareAmlResources (
62    UINT8                   *Aml1Buffer,
63    ACPI_RSDESC_SIZE        Aml1BufferLength,
64    UINT8                   *Aml2Buffer,
65    ACPI_RSDESC_SIZE        Aml2BufferLength);
66
67static ACPI_STATUS
68AcpiDmTestResourceConversion (
69    ACPI_NAMESPACE_NODE     *Node,
70    char                    *Name);
71
72static ACPI_STATUS
73AcpiDbResourceCallback (
74    ACPI_RESOURCE           *Resource,
75    void                    *Context);
76
77static ACPI_STATUS
78AcpiDbDeviceResources (
79    ACPI_HANDLE             ObjHandle,
80    UINT32                  NestingLevel,
81    void                    *Context,
82    void                    **ReturnValue);
83
84static void
85AcpiDbDoOneSleepState (
86    UINT8                   SleepState);
87
88
89/*******************************************************************************
90 *
91 * FUNCTION:    AcpiDbConvertToNode
92 *
93 * PARAMETERS:  InString            - String to convert
94 *
95 * RETURN:      Pointer to a NS node
96 *
97 * DESCRIPTION: Convert a string to a valid NS pointer. Handles numeric or
98 *              alphanumeric strings.
99 *
100 ******************************************************************************/
101
102ACPI_NAMESPACE_NODE *
103AcpiDbConvertToNode (
104    char                    *InString)
105{
106    ACPI_NAMESPACE_NODE     *Node;
107    ACPI_SIZE               Address;
108
109
110    if ((*InString >= 0x30) && (*InString <= 0x39))
111    {
112        /* Numeric argument, convert */
113
114        Address = ACPI_STRTOUL (InString, NULL, 16);
115        Node = ACPI_TO_POINTER (Address);
116        if (!AcpiOsReadable (Node, sizeof (ACPI_NAMESPACE_NODE)))
117        {
118            AcpiOsPrintf ("Address %p is invalid",
119                Node);
120            return (NULL);
121        }
122
123        /* Make sure pointer is valid NS node */
124
125        if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED)
126        {
127            AcpiOsPrintf ("Address %p is not a valid namespace node [%s]\n",
128                    Node, AcpiUtGetDescriptorName (Node));
129            return (NULL);
130        }
131    }
132    else
133    {
134        /*
135         * Alpha argument: The parameter is a name string that must be
136         * resolved to a Namespace object.
137         */
138        Node = AcpiDbLocalNsLookup (InString);
139        if (!Node)
140        {
141            AcpiOsPrintf ("Could not find [%s] in namespace, defaulting to root node\n",
142                InString);
143            Node = AcpiGbl_RootNode;
144        }
145    }
146
147    return (Node);
148}
149
150
151/*******************************************************************************
152 *
153 * FUNCTION:    AcpiDbSleep
154 *
155 * PARAMETERS:  ObjectArg           - Desired sleep state (0-5). NULL means
156 *                                    invoke all possible sleep states.
157 *
158 * RETURN:      Status
159 *
160 * DESCRIPTION: Simulate sleep/wake sequences
161 *
162 ******************************************************************************/
163
164ACPI_STATUS
165AcpiDbSleep (
166    char                    *ObjectArg)
167{
168    UINT8                   SleepState;
169    UINT32                  i;
170
171
172    ACPI_FUNCTION_TRACE (AcpiDbSleep);
173
174
175    /* Null input (no arguments) means to invoke all sleep states */
176
177    if (!ObjectArg)
178    {
179        AcpiOsPrintf ("Invoking all possible sleep states, 0-%d\n",
180            ACPI_S_STATES_MAX);
181
182        for (i = 0; i <= ACPI_S_STATES_MAX; i++)
183        {
184            AcpiDbDoOneSleepState ((UINT8) i);
185        }
186
187        return_ACPI_STATUS (AE_OK);
188    }
189
190    /* Convert argument to binary and invoke the sleep state */
191
192    SleepState = (UINT8) ACPI_STRTOUL (ObjectArg, NULL, 0);
193    AcpiDbDoOneSleepState (SleepState);
194    return_ACPI_STATUS (AE_OK);
195}
196
197
198/*******************************************************************************
199 *
200 * FUNCTION:    AcpiDbDoOneSleepState
201 *
202 * PARAMETERS:  SleepState          - Desired sleep state (0-5)
203 *
204 * RETURN:      Status
205 *
206 * DESCRIPTION: Simulate a sleep/wake sequence
207 *
208 ******************************************************************************/
209
210static void
211AcpiDbDoOneSleepState (
212    UINT8                   SleepState)
213{
214    ACPI_STATUS             Status;
215    UINT8                   SleepTypeA;
216    UINT8                   SleepTypeB;
217
218
219    /* Validate parameter */
220
221    if (SleepState > ACPI_S_STATES_MAX)
222    {
223        AcpiOsPrintf ("Sleep state %d out of range (%d max)\n",
224            SleepState, ACPI_S_STATES_MAX);
225        return;
226    }
227
228    AcpiOsPrintf ("\n---- Invoking sleep state S%d (%s):\n",
229        SleepState, AcpiGbl_SleepStateNames[SleepState]);
230
231    /* Get the values for the sleep type registers (for display only) */
232
233    Status = AcpiGetSleepTypeData (SleepState, &SleepTypeA, &SleepTypeB);
234    if (ACPI_FAILURE (Status))
235    {
236        AcpiOsPrintf ("Could not evaluate [%s] method, %s\n",
237            AcpiGbl_SleepStateNames[SleepState],
238            AcpiFormatException (Status));
239        return;
240    }
241
242    AcpiOsPrintf (
243        "Register values for sleep state S%d: Sleep-A: %.2X, Sleep-B: %.2X\n",
244        SleepState, SleepTypeA, SleepTypeB);
245
246    /* Invoke the various sleep/wake interfaces */
247
248    AcpiOsPrintf ("**** Sleep: Prepare to sleep (S%d) ****\n",
249        SleepState);
250    Status = AcpiEnterSleepStatePrep (SleepState);
251    if (ACPI_FAILURE (Status))
252    {
253        goto ErrorExit;
254    }
255
256    AcpiOsPrintf ("**** Sleep: Going to sleep (S%d) ****\n",
257        SleepState);
258    Status = AcpiEnterSleepState (SleepState);
259    if (ACPI_FAILURE (Status))
260    {
261        goto ErrorExit;
262    }
263
264    AcpiOsPrintf ("**** Wake: Prepare to return from sleep (S%d) ****\n",
265        SleepState);
266    Status = AcpiLeaveSleepStatePrep (SleepState);
267    if (ACPI_FAILURE (Status))
268    {
269        goto ErrorExit;
270    }
271
272    AcpiOsPrintf ("**** Wake: Return from sleep (S%d) ****\n",
273        SleepState);
274    Status = AcpiLeaveSleepState (SleepState);
275    if (ACPI_FAILURE (Status))
276    {
277        goto ErrorExit;
278    }
279
280    return;
281
282
283ErrorExit:
284    ACPI_EXCEPTION ((AE_INFO, Status, "During invocation of sleep state S%d",
285        SleepState));
286}
287
288
289/*******************************************************************************
290 *
291 * FUNCTION:    AcpiDbDisplayLocks
292 *
293 * PARAMETERS:  None
294 *
295 * RETURN:      None
296 *
297 * DESCRIPTION: Display information about internal mutexes.
298 *
299 ******************************************************************************/
300
301void
302AcpiDbDisplayLocks (
303    void)
304{
305    UINT32                  i;
306
307
308    for (i = 0; i < ACPI_MAX_MUTEX; i++)
309    {
310        AcpiOsPrintf ("%26s : %s\n", AcpiUtGetMutexName (i),
311            AcpiGbl_MutexInfo[i].ThreadId == ACPI_MUTEX_NOT_ACQUIRED
312                ? "Locked" : "Unlocked");
313    }
314}
315
316
317/*******************************************************************************
318 *
319 * FUNCTION:    AcpiDbDisplayTableInfo
320 *
321 * PARAMETERS:  TableArg            - Name of table to be displayed
322 *
323 * RETURN:      None
324 *
325 * DESCRIPTION: Display information about loaded tables. Current
326 *              implementation displays all loaded tables.
327 *
328 ******************************************************************************/
329
330void
331AcpiDbDisplayTableInfo (
332    char                    *TableArg)
333{
334    UINT32                  i;
335    ACPI_TABLE_DESC         *TableDesc;
336    ACPI_STATUS             Status;
337
338
339    /* Header */
340
341    AcpiOsPrintf ("Idx ID    Status Type              TableHeader (Sig, Address, Length)\n");
342
343    /* Walk the entire root table list */
344
345    for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
346    {
347        TableDesc = &AcpiGbl_RootTableList.Tables[i];
348
349        /* Index and Table ID */
350
351        AcpiOsPrintf ("%3u %.2u ", i, TableDesc->OwnerId);
352
353        /* Decode the table flags */
354
355        if (!(TableDesc->Flags & ACPI_TABLE_IS_LOADED))
356        {
357            AcpiOsPrintf ("NotLoaded ");
358        }
359        else
360        {
361            AcpiOsPrintf ("   Loaded ");
362        }
363
364        switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK)
365        {
366        case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
367
368            AcpiOsPrintf ("External/virtual  ");
369            break;
370
371        case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
372
373            AcpiOsPrintf ("Internal/physical ");
374            break;
375
376        case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
377
378            AcpiOsPrintf ("Internal/virtual  ");
379            break;
380
381        default:
382
383            AcpiOsPrintf ("INVALID TYPE      ");
384            break;
385        }
386
387        /* Make sure that the table is mapped */
388
389        Status = AcpiTbValidateTable (TableDesc);
390        if (ACPI_FAILURE (Status))
391        {
392            return;
393        }
394
395        /* Dump the table header */
396
397        if (TableDesc->Pointer)
398        {
399            AcpiTbPrintTableHeader (TableDesc->Address, TableDesc->Pointer);
400        }
401        else
402        {
403            /* If the pointer is null, the table has been unloaded */
404
405            ACPI_INFO ((AE_INFO, "%4.4s - Table has been unloaded",
406                TableDesc->Signature.Ascii));
407        }
408    }
409}
410
411
412/*******************************************************************************
413 *
414 * FUNCTION:    AcpiDbUnloadAcpiTable
415 *
416 * PARAMETERS:  ObjectName          - Namespace pathname for an object that
417 *                                    is owned by the table to be unloaded
418 *
419 * RETURN:      None
420 *
421 * DESCRIPTION: Unload an ACPI table, via any namespace node that is owned
422 *              by the table.
423 *
424 ******************************************************************************/
425
426void
427AcpiDbUnloadAcpiTable (
428    char                    *ObjectName)
429{
430    ACPI_NAMESPACE_NODE     *Node;
431    ACPI_STATUS             Status;
432
433
434    /* Translate name to an Named object */
435
436    Node = AcpiDbConvertToNode (ObjectName);
437    if (!Node)
438    {
439        return;
440    }
441
442    Status = AcpiUnloadParentTable (ACPI_CAST_PTR (ACPI_HANDLE, Node));
443    if (ACPI_SUCCESS (Status))
444    {
445        AcpiOsPrintf ("Parent of [%s] (%p) unloaded and uninstalled\n",
446            ObjectName, Node);
447    }
448    else
449    {
450        AcpiOsPrintf ("%s, while unloading parent table of [%s]\n",
451            AcpiFormatException (Status), ObjectName);
452    }
453}
454
455
456/*******************************************************************************
457 *
458 * FUNCTION:    AcpiDbSendNotify
459 *
460 * PARAMETERS:  Name                - Name of ACPI object where to send notify
461 *              Value               - Value of the notify to send.
462 *
463 * RETURN:      None
464 *
465 * DESCRIPTION: Send an ACPI notification. The value specified is sent to the
466 *              named object as an ACPI notify.
467 *
468 ******************************************************************************/
469
470void
471AcpiDbSendNotify (
472    char                    *Name,
473    UINT32                  Value)
474{
475    ACPI_NAMESPACE_NODE     *Node;
476    ACPI_STATUS             Status;
477
478
479    /* Translate name to an Named object */
480
481    Node = AcpiDbConvertToNode (Name);
482    if (!Node)
483    {
484        return;
485    }
486
487    /* Dispatch the notify if legal */
488
489    if (AcpiEvIsNotifyObject (Node))
490    {
491        Status = AcpiEvQueueNotifyRequest (Node, Value);
492        if (ACPI_FAILURE (Status))
493        {
494            AcpiOsPrintf ("Could not queue notify\n");
495        }
496    }
497    else
498    {
499        AcpiOsPrintf (
500            "Named object [%4.4s] Type %s, must be Device/Thermal/Processor type\n",
501            AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type));
502    }
503}
504
505
506/*******************************************************************************
507 *
508 * FUNCTION:    AcpiDbDisplayInterfaces
509 *
510 * PARAMETERS:  ActionArg           - Null, "install", or "remove"
511 *              InterfaceNameArg    - Name for install/remove options
512 *
513 * RETURN:      None
514 *
515 * DESCRIPTION: Display or modify the global _OSI interface list
516 *
517 ******************************************************************************/
518
519void
520AcpiDbDisplayInterfaces (
521    char                    *ActionArg,
522    char                    *InterfaceNameArg)
523{
524    ACPI_INTERFACE_INFO     *NextInterface;
525    char                    *SubString;
526    ACPI_STATUS             Status;
527
528
529    /* If no arguments, just display current interface list */
530
531    if (!ActionArg)
532    {
533        (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex,
534                    ACPI_WAIT_FOREVER);
535
536        NextInterface = AcpiGbl_SupportedInterfaces;
537        while (NextInterface)
538        {
539            if (!(NextInterface->Flags & ACPI_OSI_INVALID))
540            {
541                AcpiOsPrintf ("%s\n", NextInterface->Name);
542            }
543            NextInterface = NextInterface->Next;
544        }
545
546        AcpiOsReleaseMutex (AcpiGbl_OsiMutex);
547        return;
548    }
549
550    /* If ActionArg exists, so must InterfaceNameArg */
551
552    if (!InterfaceNameArg)
553    {
554        AcpiOsPrintf ("Missing Interface Name argument\n");
555        return;
556    }
557
558    /* Uppercase the action for match below */
559
560    AcpiUtStrupr (ActionArg);
561
562    /* Install - install an interface */
563
564    SubString = ACPI_STRSTR ("INSTALL", ActionArg);
565    if (SubString)
566    {
567        Status = AcpiInstallInterface (InterfaceNameArg);
568        if (ACPI_FAILURE (Status))
569        {
570            AcpiOsPrintf ("%s, while installing \"%s\"\n",
571                AcpiFormatException (Status), InterfaceNameArg);
572        }
573        return;
574    }
575
576    /* Remove - remove an interface */
577
578    SubString = ACPI_STRSTR ("REMOVE", ActionArg);
579    if (SubString)
580    {
581        Status = AcpiRemoveInterface (InterfaceNameArg);
582        if (ACPI_FAILURE (Status))
583        {
584            AcpiOsPrintf ("%s, while removing \"%s\"\n",
585                AcpiFormatException (Status), InterfaceNameArg);
586        }
587        return;
588    }
589
590    /* Invalid ActionArg */
591
592    AcpiOsPrintf ("Invalid action argument: %s\n", ActionArg);
593    return;
594}
595
596
597/*******************************************************************************
598 *
599 * FUNCTION:    AcpiDbDisplayTemplate
600 *
601 * PARAMETERS:  BufferArg           - Buffer name or address
602 *
603 * RETURN:      None
604 *
605 * DESCRIPTION: Dump a buffer that contains a resource template
606 *
607 ******************************************************************************/
608
609void
610AcpiDbDisplayTemplate (
611    char                    *BufferArg)
612{
613    ACPI_NAMESPACE_NODE     *Node;
614    ACPI_STATUS             Status;
615    ACPI_BUFFER             ReturnBuffer;
616
617
618    /* Translate BufferArg to an Named object */
619
620    Node = AcpiDbConvertToNode (BufferArg);
621    if (!Node || (Node == AcpiGbl_RootNode))
622    {
623        AcpiOsPrintf ("Invalid argument: %s\n", BufferArg);
624        return;
625    }
626
627    /* We must have a buffer object */
628
629    if (Node->Type != ACPI_TYPE_BUFFER)
630    {
631        AcpiOsPrintf ("Not a Buffer object, cannot be a template: %s\n",
632            BufferArg);
633        return;
634    }
635
636    ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE;
637    ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
638
639    /* Attempt to convert the raw buffer to a resource list */
640
641    Status = AcpiRsCreateResourceList (Node->Object, &ReturnBuffer);
642
643    AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);
644    AcpiDbgLevel |= ACPI_LV_RESOURCES;
645
646    if (ACPI_FAILURE (Status))
647    {
648        AcpiOsPrintf ("Could not convert Buffer to a resource list: %s, %s\n",
649            BufferArg, AcpiFormatException (Status));
650        goto DumpBuffer;
651    }
652
653    /* Now we can dump the resource list */
654
655    AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE,
656        ReturnBuffer.Pointer));
657
658DumpBuffer:
659    AcpiOsPrintf ("\nRaw data buffer:\n");
660    AcpiUtDebugDumpBuffer ((UINT8 *) Node->Object->Buffer.Pointer,
661        Node->Object->Buffer.Length,
662        DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
663
664    AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
665    return;
666}
667
668
669/*******************************************************************************
670 *
671 * FUNCTION:    AcpiDmCompareAmlResources
672 *
673 * PARAMETERS:  Aml1Buffer          - Contains first resource list
674 *              Aml1BufferLength    - Length of first resource list
675 *              Aml2Buffer          - Contains second resource list
676 *              Aml2BufferLength    - Length of second resource list
677 *
678 * RETURN:      None
679 *
680 * DESCRIPTION: Compare two AML resource lists, descriptor by descriptor (in
681 *              order to isolate a miscompare to an individual resource)
682 *
683 ******************************************************************************/
684
685static void
686AcpiDmCompareAmlResources (
687    UINT8                   *Aml1Buffer,
688    ACPI_RSDESC_SIZE        Aml1BufferLength,
689    UINT8                   *Aml2Buffer,
690    ACPI_RSDESC_SIZE        Aml2BufferLength)
691{
692    UINT8                   *Aml1;
693    UINT8                   *Aml2;
694    UINT8                   *Aml1End;
695    UINT8                   *Aml2End;
696    ACPI_RSDESC_SIZE        Aml1Length;
697    ACPI_RSDESC_SIZE        Aml2Length;
698    ACPI_RSDESC_SIZE        Offset = 0;
699    UINT8                   ResourceType;
700    UINT32                  Count = 0;
701    UINT32                  i;
702
703
704    /* Compare overall buffer sizes (may be different due to size rounding) */
705
706    if (Aml1BufferLength != Aml2BufferLength)
707    {
708        AcpiOsPrintf (
709            "**** Buffer length mismatch in converted AML: Original %X, New %X ****\n",
710            Aml1BufferLength, Aml2BufferLength);
711    }
712
713    Aml1 = Aml1Buffer;
714    Aml2 = Aml2Buffer;
715    Aml1End = Aml1Buffer + Aml1BufferLength;
716    Aml2End = Aml2Buffer + Aml2BufferLength;
717
718    /* Walk the descriptor lists, comparing each descriptor */
719
720    while ((Aml1 < Aml1End) && (Aml2 < Aml2End))
721    {
722        /* Get the lengths of each descriptor */
723
724        Aml1Length = AcpiUtGetDescriptorLength (Aml1);
725        Aml2Length = AcpiUtGetDescriptorLength (Aml2);
726        ResourceType = AcpiUtGetResourceType (Aml1);
727
728        /* Check for descriptor length match */
729
730        if (Aml1Length != Aml2Length)
731        {
732            AcpiOsPrintf (
733                "**** Length mismatch in descriptor [%.2X] type %2.2X, Offset %8.8X Len1 %X, Len2 %X ****\n",
734                Count, ResourceType, Offset, Aml1Length, Aml2Length);
735        }
736
737        /* Check for descriptor byte match */
738
739        else if (ACPI_MEMCMP (Aml1, Aml2, Aml1Length))
740        {
741            AcpiOsPrintf (
742                "**** Data mismatch in descriptor [%.2X] type %2.2X, Offset %8.8X ****\n",
743                Count, ResourceType, Offset);
744
745            for (i = 0; i < Aml1Length; i++)
746            {
747                if (Aml1[i] != Aml2[i])
748                {
749                    AcpiOsPrintf (
750                        "Mismatch at byte offset %.2X: is %2.2X, should be %2.2X\n",
751                        i, Aml2[i], Aml1[i]);
752                }
753            }
754        }
755
756        /* Exit on EndTag descriptor */
757
758        if (ResourceType == ACPI_RESOURCE_NAME_END_TAG)
759        {
760            return;
761        }
762
763        /* Point to next descriptor in each buffer */
764
765        Count++;
766        Offset += Aml1Length;
767        Aml1 += Aml1Length;
768        Aml2 += Aml2Length;
769    }
770}
771
772
773/*******************************************************************************
774 *
775 * FUNCTION:    AcpiDmTestResourceConversion
776 *
777 * PARAMETERS:  Node                - Parent device node
778 *              Name                - resource method name (_CRS)
779 *
780 * RETURN:      Status
781 *
782 * DESCRIPTION: Compare the original AML with a conversion of the AML to
783 *              internal resource list, then back to AML.
784 *
785 ******************************************************************************/
786
787static ACPI_STATUS
788AcpiDmTestResourceConversion (
789    ACPI_NAMESPACE_NODE     *Node,
790    char                    *Name)
791{
792    ACPI_STATUS             Status;
793    ACPI_BUFFER             ReturnBuffer;
794    ACPI_BUFFER             ResourceBuffer;
795    ACPI_BUFFER             NewAml;
796    ACPI_OBJECT             *OriginalAml;
797
798
799    AcpiOsPrintf ("Resource Conversion Comparison:\n");
800
801    NewAml.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
802    ReturnBuffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
803    ResourceBuffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
804
805    /* Get the original _CRS AML resource template */
806
807    Status = AcpiEvaluateObject (Node, Name, NULL, &ReturnBuffer);
808    if (ACPI_FAILURE (Status))
809    {
810        AcpiOsPrintf ("Could not obtain %s: %s\n",
811            Name, AcpiFormatException (Status));
812        return (Status);
813    }
814
815    /* Get the AML resource template, converted to internal resource structs */
816
817    Status = AcpiGetCurrentResources (Node, &ResourceBuffer);
818    if (ACPI_FAILURE (Status))
819    {
820        AcpiOsPrintf ("AcpiGetCurrentResources failed: %s\n",
821            AcpiFormatException (Status));
822        goto Exit1;
823    }
824
825    /* Convert internal resource list to external AML resource template */
826
827    Status = AcpiRsCreateAmlResources (&ResourceBuffer, &NewAml);
828    if (ACPI_FAILURE (Status))
829    {
830        AcpiOsPrintf ("AcpiRsCreateAmlResources failed: %s\n",
831            AcpiFormatException (Status));
832        goto Exit2;
833    }
834
835    /* Compare original AML to the newly created AML resource list */
836
837    OriginalAml = ReturnBuffer.Pointer;
838
839    AcpiDmCompareAmlResources (OriginalAml->Buffer.Pointer,
840        (ACPI_RSDESC_SIZE) OriginalAml->Buffer.Length,
841        NewAml.Pointer, (ACPI_RSDESC_SIZE) NewAml.Length);
842
843    /* Cleanup and exit */
844
845    ACPI_FREE (NewAml.Pointer);
846Exit2:
847    ACPI_FREE (ResourceBuffer.Pointer);
848Exit1:
849    ACPI_FREE (ReturnBuffer.Pointer);
850    return (Status);
851}
852
853
854/*******************************************************************************
855 *
856 * FUNCTION:    AcpiDbResourceCallback
857 *
858 * PARAMETERS:  ACPI_WALK_RESOURCE_CALLBACK
859 *
860 * RETURN:      Status
861 *
862 * DESCRIPTION: Simple callback to exercise AcpiWalkResources and
863 *              AcpiWalkResourceBuffer.
864 *
865 ******************************************************************************/
866
867static ACPI_STATUS
868AcpiDbResourceCallback (
869    ACPI_RESOURCE           *Resource,
870    void                    *Context)
871{
872
873    return (AE_OK);
874}
875
876
877/*******************************************************************************
878 *
879 * FUNCTION:    AcpiDbDeviceResources
880 *
881 * PARAMETERS:  ACPI_WALK_CALLBACK
882 *
883 * RETURN:      Status
884 *
885 * DESCRIPTION: Display the _PRT/_CRS/_PRS resources for a device object.
886 *
887 ******************************************************************************/
888
889static ACPI_STATUS
890AcpiDbDeviceResources (
891    ACPI_HANDLE             ObjHandle,
892    UINT32                  NestingLevel,
893    void                    *Context,
894    void                    **ReturnValue)
895{
896    ACPI_NAMESPACE_NODE     *Node;
897    ACPI_NAMESPACE_NODE     *PrtNode = NULL;
898    ACPI_NAMESPACE_NODE     *CrsNode = NULL;
899    ACPI_NAMESPACE_NODE     *PrsNode = NULL;
900    ACPI_NAMESPACE_NODE     *AeiNode = NULL;
901    char                    *ParentPath;
902    ACPI_BUFFER             ReturnBuffer;
903    ACPI_STATUS             Status;
904
905
906    Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
907    ParentPath = AcpiNsGetExternalPathname (Node);
908    if (!ParentPath)
909    {
910        return (AE_NO_MEMORY);
911    }
912
913    /* Get handles to the resource methods for this device */
914
915    (void) AcpiGetHandle (Node, METHOD_NAME__PRT, ACPI_CAST_PTR (ACPI_HANDLE, &PrtNode));
916    (void) AcpiGetHandle (Node, METHOD_NAME__CRS, ACPI_CAST_PTR (ACPI_HANDLE, &CrsNode));
917    (void) AcpiGetHandle (Node, METHOD_NAME__PRS, ACPI_CAST_PTR (ACPI_HANDLE, &PrsNode));
918    (void) AcpiGetHandle (Node, METHOD_NAME__AEI, ACPI_CAST_PTR (ACPI_HANDLE, &AeiNode));
919    if (!PrtNode && !CrsNode && !PrsNode && !AeiNode)
920    {
921        goto Cleanup;   /* Nothing to do */
922    }
923
924    AcpiOsPrintf ("\nDevice: %s\n", ParentPath);
925
926    /* Prepare for a return object of arbitrary size */
927
928    ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
929    ReturnBuffer.Length  = ACPI_DEBUG_BUFFER_SIZE;
930
931
932    /* _PRT */
933
934    if (PrtNode)
935    {
936        AcpiOsPrintf ("Evaluating _PRT\n");
937
938        Status = AcpiEvaluateObject (PrtNode, NULL, NULL, &ReturnBuffer);
939        if (ACPI_FAILURE (Status))
940        {
941            AcpiOsPrintf ("Could not evaluate _PRT: %s\n",
942                AcpiFormatException (Status));
943            goto GetCrs;
944        }
945
946        ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
947        ReturnBuffer.Length  = ACPI_DEBUG_BUFFER_SIZE;
948
949        Status = AcpiGetIrqRoutingTable (Node, &ReturnBuffer);
950        if (ACPI_FAILURE (Status))
951        {
952            AcpiOsPrintf ("GetIrqRoutingTable failed: %s\n",
953                AcpiFormatException (Status));
954            goto GetCrs;
955        }
956
957        AcpiRsDumpIrqList (ACPI_CAST_PTR (UINT8, AcpiGbl_DbBuffer));
958    }
959
960
961    /* _CRS */
962
963GetCrs:
964    if (CrsNode)
965    {
966        AcpiOsPrintf ("Evaluating _CRS\n");
967
968        ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
969        ReturnBuffer.Length  = ACPI_DEBUG_BUFFER_SIZE;
970
971        Status = AcpiEvaluateObject (CrsNode, NULL, NULL, &ReturnBuffer);
972        if (ACPI_FAILURE (Status))
973        {
974            AcpiOsPrintf ("Could not evaluate _CRS: %s\n",
975                AcpiFormatException (Status));
976            goto GetPrs;
977        }
978
979        /* This code exercises the AcpiWalkResources interface */
980
981        Status = AcpiWalkResources (Node, METHOD_NAME__CRS,
982            AcpiDbResourceCallback, NULL);
983        if (ACPI_FAILURE (Status))
984        {
985            AcpiOsPrintf ("AcpiWalkResources failed: %s\n",
986                AcpiFormatException (Status));
987            goto GetPrs;
988        }
989
990        /* Get the _CRS resource list (test ALLOCATE buffer) */
991
992        ReturnBuffer.Pointer = NULL;
993        ReturnBuffer.Length  = ACPI_ALLOCATE_LOCAL_BUFFER;
994
995        Status = AcpiGetCurrentResources (Node, &ReturnBuffer);
996        if (ACPI_FAILURE (Status))
997        {
998            AcpiOsPrintf ("AcpiGetCurrentResources failed: %s\n",
999                AcpiFormatException (Status));
1000            goto GetPrs;
1001        }
1002
1003        /* This code exercises the AcpiWalkResourceBuffer interface */
1004
1005        Status = AcpiWalkResourceBuffer (&ReturnBuffer,
1006            AcpiDbResourceCallback, NULL);
1007        if (ACPI_FAILURE (Status))
1008        {
1009            AcpiOsPrintf ("AcpiWalkResourceBuffer failed: %s\n",
1010                AcpiFormatException (Status));
1011            goto EndCrs;
1012        }
1013
1014        /* Dump the _CRS resource list */
1015
1016        AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE,
1017            ReturnBuffer.Pointer));
1018
1019        /*
1020         * Perform comparison of original AML to newly created AML. This
1021         * tests both the AML->Resource conversion and the Resource->AML
1022         * conversion.
1023         */
1024        (void) AcpiDmTestResourceConversion (Node, METHOD_NAME__CRS);
1025
1026        /* Execute _SRS with the resource list */
1027
1028        AcpiOsPrintf ("Evaluating _SRS\n");
1029
1030        Status = AcpiSetCurrentResources (Node, &ReturnBuffer);
1031        if (ACPI_FAILURE (Status))
1032        {
1033            AcpiOsPrintf ("AcpiSetCurrentResources failed: %s\n",
1034                AcpiFormatException (Status));
1035            goto EndCrs;
1036        }
1037
1038EndCrs:
1039        ACPI_FREE (ReturnBuffer.Pointer);
1040    }
1041
1042
1043    /* _PRS */
1044
1045GetPrs:
1046    if (PrsNode)
1047    {
1048        AcpiOsPrintf ("Evaluating _PRS\n");
1049
1050        ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
1051        ReturnBuffer.Length  = ACPI_DEBUG_BUFFER_SIZE;
1052
1053        Status = AcpiEvaluateObject (PrsNode, NULL, NULL, &ReturnBuffer);
1054        if (ACPI_FAILURE (Status))
1055        {
1056            AcpiOsPrintf ("Could not evaluate _PRS: %s\n",
1057                AcpiFormatException (Status));
1058            goto GetAei;
1059        }
1060
1061        ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
1062        ReturnBuffer.Length  = ACPI_DEBUG_BUFFER_SIZE;
1063
1064        Status = AcpiGetPossibleResources (Node, &ReturnBuffer);
1065        if (ACPI_FAILURE (Status))
1066        {
1067            AcpiOsPrintf ("AcpiGetPossibleResources failed: %s\n",
1068                AcpiFormatException (Status));
1069            goto GetAei;
1070        }
1071
1072        AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE, AcpiGbl_DbBuffer));
1073    }
1074
1075
1076    /* _AEI */
1077
1078GetAei:
1079    if (AeiNode)
1080    {
1081        AcpiOsPrintf ("Evaluating _AEI\n");
1082
1083        ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
1084        ReturnBuffer.Length  = ACPI_DEBUG_BUFFER_SIZE;
1085
1086        Status = AcpiEvaluateObject (AeiNode, NULL, NULL, &ReturnBuffer);
1087        if (ACPI_FAILURE (Status))
1088        {
1089            AcpiOsPrintf ("Could not evaluate _AEI: %s\n",
1090                AcpiFormatException (Status));
1091            goto Cleanup;
1092        }
1093
1094        ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
1095        ReturnBuffer.Length  = ACPI_DEBUG_BUFFER_SIZE;
1096
1097        Status = AcpiGetEventResources (Node, &ReturnBuffer);
1098        if (ACPI_FAILURE (Status))
1099        {
1100            AcpiOsPrintf ("AcpiGetEventResources failed: %s\n",
1101                AcpiFormatException (Status));
1102            goto Cleanup;
1103        }
1104
1105        AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE, AcpiGbl_DbBuffer));
1106    }
1107
1108
1109Cleanup:
1110    ACPI_FREE (ParentPath);
1111    return (AE_OK);
1112}
1113
1114
1115/*******************************************************************************
1116 *
1117 * FUNCTION:    AcpiDbDisplayResources
1118 *
1119 * PARAMETERS:  ObjectArg           - String object name or object pointer.
1120 *                                    NULL or "*" means "display resources for
1121 *                                    all devices"
1122 *
1123 * RETURN:      None
1124 *
1125 * DESCRIPTION: Display the resource objects associated with a device.
1126 *
1127 ******************************************************************************/
1128
1129void
1130AcpiDbDisplayResources (
1131    char                    *ObjectArg)
1132{
1133    ACPI_NAMESPACE_NODE     *Node;
1134
1135
1136    AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);
1137    AcpiDbgLevel |= ACPI_LV_RESOURCES;
1138
1139    /* Asterisk means "display resources for all devices" */
1140
1141    if (!ObjectArg || (!ACPI_STRCMP (ObjectArg, "*")))
1142    {
1143        (void) AcpiWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
1144                    ACPI_UINT32_MAX, AcpiDbDeviceResources, NULL, NULL, NULL);
1145    }
1146    else
1147    {
1148        /* Convert string to object pointer */
1149
1150        Node = AcpiDbConvertToNode (ObjectArg);
1151        if (Node)
1152        {
1153            if (Node->Type != ACPI_TYPE_DEVICE)
1154            {
1155                AcpiOsPrintf ("%4.4s: Name is not a device object (%s)\n",
1156                    Node->Name.Ascii, AcpiUtGetTypeName (Node->Type));
1157            }
1158            else
1159            {
1160                (void) AcpiDbDeviceResources (Node, 0, NULL, NULL);
1161            }
1162        }
1163    }
1164
1165    AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
1166}
1167
1168
1169#if (!ACPI_REDUCED_HARDWARE)
1170/*******************************************************************************
1171 *
1172 * FUNCTION:    AcpiDbGenerateGpe
1173 *
1174 * PARAMETERS:  GpeArg              - Raw GPE number, ascii string
1175 *              BlockArg            - GPE block number, ascii string
1176 *                                    0 or 1 for FADT GPE blocks
1177 *
1178 * RETURN:      None
1179 *
1180 * DESCRIPTION: Simulate firing of a GPE
1181 *
1182 ******************************************************************************/
1183
1184void
1185AcpiDbGenerateGpe (
1186    char                    *GpeArg,
1187    char                    *BlockArg)
1188{
1189    UINT32                  BlockNumber = 0;
1190    UINT32                  GpeNumber;
1191    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
1192
1193
1194    GpeNumber = ACPI_STRTOUL (GpeArg, NULL, 0);
1195
1196    /*
1197     * If no block arg, or block arg == 0 or 1, use the FADT-defined
1198     * GPE blocks.
1199     */
1200    if (BlockArg)
1201    {
1202        BlockNumber = ACPI_STRTOUL (BlockArg, NULL, 0);
1203        if (BlockNumber == 1)
1204        {
1205            BlockNumber = 0;
1206        }
1207    }
1208
1209    GpeEventInfo = AcpiEvGetGpeEventInfo (ACPI_TO_POINTER (BlockNumber),
1210        GpeNumber);
1211    if (!GpeEventInfo)
1212    {
1213        AcpiOsPrintf ("Invalid GPE\n");
1214        return;
1215    }
1216
1217    (void) AcpiEvGpeDispatch (NULL, GpeEventInfo, GpeNumber);
1218}
1219
1220void
1221AcpiDbGenerateSci (
1222    void)
1223{
1224    AcpiEvSciDispatch ();
1225}
1226
1227#endif /* !ACPI_REDUCED_HARDWARE */
1228
1229#endif /* ACPI_DEBUGGER */
1230