dbcmds.c revision 1.1.1.5 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 "acpi.h"
45 #include "accommon.h"
46 #include "acevents.h"
47 #include "acdebug.h"
48 #include "acnamesp.h"
49 #include "acresrc.h"
50 #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
60 static void
61 AcpiDmCompareAmlResources (
62 UINT8 *Aml1Buffer,
63 ACPI_RSDESC_SIZE Aml1BufferLength,
64 UINT8 *Aml2Buffer,
65 ACPI_RSDESC_SIZE Aml2BufferLength);
66
67 static ACPI_STATUS
68 AcpiDmTestResourceConversion (
69 ACPI_NAMESPACE_NODE *Node,
70 char *Name);
71
72 static ACPI_STATUS
73 AcpiDbResourceCallback (
74 ACPI_RESOURCE *Resource,
75 void *Context);
76
77 static ACPI_STATUS
78 AcpiDbDeviceResources (
79 ACPI_HANDLE ObjHandle,
80 UINT32 NestingLevel,
81 void *Context,
82 void **ReturnValue);
83
84 static void
85 AcpiDbDoOneSleepState (
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
102 ACPI_NAMESPACE_NODE *
103 AcpiDbConvertToNode (
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
164 ACPI_STATUS
165 AcpiDbSleep (
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
210 static void
211 AcpiDbDoOneSleepState (
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
283 ErrorExit:
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
301 void
302 AcpiDbDisplayLocks (
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
330 void
331 AcpiDbDisplayTableInfo (
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
426 void
427 AcpiDbUnloadAcpiTable (
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
470 void
471 AcpiDbSendNotify (
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
519 void
520 AcpiDbDisplayInterfaces (
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
609 void
610 AcpiDbDisplayTemplate (
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
658 DumpBuffer:
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
685 static void
686 AcpiDmCompareAmlResources (
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
787 static ACPI_STATUS
788 AcpiDmTestResourceConversion (
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);
846 Exit2:
847 ACPI_FREE (ResourceBuffer.Pointer);
848 Exit1:
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
867 static ACPI_STATUS
868 AcpiDbResourceCallback (
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
889 static ACPI_STATUS
890 AcpiDbDeviceResources (
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
963 GetCrs:
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
1038 EndCrs:
1039 ACPI_FREE (ReturnBuffer.Pointer);
1040 }
1041
1042
1043 /* _PRS */
1044
1045 GetPrs:
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
1078 GetAei:
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
1109 Cleanup:
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
1129 void
1130 AcpiDbDisplayResources (
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
1184 void
1185 AcpiDbGenerateGpe (
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
1220 void
1221 AcpiDbGenerateSci (
1222 void)
1223 {
1224 AcpiEvSciDispatch ();
1225 }
1226
1227 #endif /* !ACPI_REDUCED_HARDWARE */
1228
1229 #endif /* ACPI_DEBUGGER */
1230