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