xref: /freebsd/sys/contrib/dev/acpica/components/debugger/dbtest.c (revision 8ef24a0d4b28fe230e20637f56869cc4148cd2ca)
1 /*******************************************************************************
2  *
3  * Module Name: dbtest - Various debug-related tests
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, 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/acdebug.h>
47 #include <contrib/dev/acpica/include/acnamesp.h>
48 #include <contrib/dev/acpica/include/acpredef.h>
49 
50 
51 #define _COMPONENT          ACPI_CA_DEBUGGER
52         ACPI_MODULE_NAME    ("dbtest")
53 
54 
55 /* Local prototypes */
56 
57 static void
58 AcpiDbTestAllObjects (
59     void);
60 
61 static ACPI_STATUS
62 AcpiDbTestOneObject (
63     ACPI_HANDLE             ObjHandle,
64     UINT32                  NestingLevel,
65     void                    *Context,
66     void                    **ReturnValue);
67 
68 static ACPI_STATUS
69 AcpiDbTestIntegerType (
70     ACPI_NAMESPACE_NODE     *Node,
71     UINT32                  BitLength);
72 
73 static ACPI_STATUS
74 AcpiDbTestBufferType (
75     ACPI_NAMESPACE_NODE     *Node,
76     UINT32                  BitLength);
77 
78 static ACPI_STATUS
79 AcpiDbTestStringType (
80     ACPI_NAMESPACE_NODE     *Node,
81     UINT32                  ByteLength);
82 
83 static ACPI_STATUS
84 AcpiDbReadFromObject (
85     ACPI_NAMESPACE_NODE     *Node,
86     ACPI_OBJECT_TYPE        ExpectedType,
87     ACPI_OBJECT             **Value);
88 
89 static ACPI_STATUS
90 AcpiDbWriteToObject (
91     ACPI_NAMESPACE_NODE     *Node,
92     ACPI_OBJECT             *Value);
93 
94 static void
95 AcpiDbEvaluateAllPredefinedNames (
96     char                    *CountArg);
97 
98 static ACPI_STATUS
99 AcpiDbEvaluateOnePredefinedName (
100     ACPI_HANDLE             ObjHandle,
101     UINT32                  NestingLevel,
102     void                    *Context,
103     void                    **ReturnValue);
104 
105 /*
106  * Test subcommands
107  */
108 static ACPI_DB_ARGUMENT_INFO    AcpiDbTestTypes [] =
109 {
110     {"OBJECTS"},
111     {"PREDEFINED"},
112     {NULL}           /* Must be null terminated */
113 };
114 
115 #define CMD_TEST_OBJECTS        0
116 #define CMD_TEST_PREDEFINED     1
117 
118 #define BUFFER_FILL_VALUE       0xFF
119 
120 /*
121  * Support for the special debugger read/write control methods.
122  * These methods are installed into the current namespace and are
123  * used to read and write the various namespace objects. The point
124  * is to force the AML interpreter do all of the work.
125  */
126 #define ACPI_DB_READ_METHOD     "\\_T98"
127 #define ACPI_DB_WRITE_METHOD    "\\_T99"
128 
129 static ACPI_HANDLE          ReadHandle = NULL;
130 static ACPI_HANDLE          WriteHandle = NULL;
131 
132 /* ASL Definitions of the debugger read/write control methods */
133 
134 #if 0
135 DefinitionBlock ("ssdt.aml", "SSDT", 2, "Intel", "DEBUG", 0x00000001)
136 {
137     Method (_T98, 1, NotSerialized)     /* Read */
138     {
139         Return (DeRefOf (Arg0))
140     }
141 }
142 DefinitionBlock ("ssdt2.aml", "SSDT", 2, "Intel", "DEBUG", 0x00000001)
143 {
144     Method (_T99, 2, NotSerialized)     /* Write */
145     {
146         Store (Arg1, Arg0)
147     }
148 }
149 #endif
150 
151 static unsigned char ReadMethodCode[] =
152 {
153     0x53,0x53,0x44,0x54,0x2E,0x00,0x00,0x00,  /* 00000000    "SSDT...." */
154     0x02,0xC9,0x49,0x6E,0x74,0x65,0x6C,0x00,  /* 00000008    "..Intel." */
155     0x44,0x45,0x42,0x55,0x47,0x00,0x00,0x00,  /* 00000010    "DEBUG..." */
156     0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C,  /* 00000018    "....INTL" */
157     0x18,0x12,0x13,0x20,0x14,0x09,0x5F,0x54,  /* 00000020    "... .._T" */
158     0x39,0x38,0x01,0xA4,0x83,0x68             /* 00000028    "98...h"   */
159 };
160 
161 static unsigned char WriteMethodCode[] =
162 {
163     0x53,0x53,0x44,0x54,0x2E,0x00,0x00,0x00,  /* 00000000    "SSDT...." */
164     0x02,0x15,0x49,0x6E,0x74,0x65,0x6C,0x00,  /* 00000008    "..Intel." */
165     0x44,0x45,0x42,0x55,0x47,0x00,0x00,0x00,  /* 00000010    "DEBUG..." */
166     0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C,  /* 00000018    "....INTL" */
167     0x18,0x12,0x13,0x20,0x14,0x09,0x5F,0x54,  /* 00000020    "... .._T" */
168     0x39,0x39,0x02,0x70,0x69,0x68             /* 00000028    "99.pih"   */
169 };
170 
171 
172 /*******************************************************************************
173  *
174  * FUNCTION:    AcpiDbExecuteTest
175  *
176  * PARAMETERS:  TypeArg         - Subcommand
177  *
178  * RETURN:      None
179  *
180  * DESCRIPTION: Execute various debug tests.
181  *
182  * Note: Code is prepared for future expansion of the TEST command.
183  *
184  ******************************************************************************/
185 
186 void
187 AcpiDbExecuteTest (
188     char                    *TypeArg)
189 {
190     UINT32                  Temp;
191 
192 
193     AcpiUtStrupr (TypeArg);
194     Temp = AcpiDbMatchArgument (TypeArg, AcpiDbTestTypes);
195     if (Temp == ACPI_TYPE_NOT_FOUND)
196     {
197         AcpiOsPrintf ("Invalid or unsupported argument\n");
198         return;
199     }
200 
201     switch (Temp)
202     {
203     case CMD_TEST_OBJECTS:
204 
205         AcpiDbTestAllObjects ();
206         break;
207 
208     case CMD_TEST_PREDEFINED:
209 
210         AcpiDbEvaluateAllPredefinedNames (NULL);
211         break;
212 
213     default:
214         break;
215     }
216 }
217 
218 
219 /*******************************************************************************
220  *
221  * FUNCTION:    AcpiDbTestAllObjects
222  *
223  * PARAMETERS:  None
224  *
225  * RETURN:      None
226  *
227  * DESCRIPTION: This test implements the OBJECTS subcommand. It exercises the
228  *              namespace by reading/writing/comparing all data objects such
229  *              as integers, strings, buffers, fields, buffer fields, etc.
230  *
231  ******************************************************************************/
232 
233 static void
234 AcpiDbTestAllObjects (
235     void)
236 {
237     ACPI_STATUS             Status;
238 
239 
240     /* Install the debugger read-object control method if necessary */
241 
242     if (!ReadHandle)
243     {
244         Status = AcpiInstallMethod (ReadMethodCode);
245         if (ACPI_FAILURE (Status))
246         {
247             AcpiOsPrintf ("%s, Could not install debugger read method\n",
248                 AcpiFormatException (Status));
249             return;
250         }
251 
252         Status = AcpiGetHandle (NULL, ACPI_DB_READ_METHOD, &ReadHandle);
253         if (ACPI_FAILURE (Status))
254         {
255             AcpiOsPrintf ("Could not obtain handle for debug method %s\n",
256                 ACPI_DB_READ_METHOD);
257             return;
258         }
259     }
260 
261     /* Install the debugger write-object control method if necessary */
262 
263     if (!WriteHandle)
264     {
265         Status = AcpiInstallMethod (WriteMethodCode);
266         if (ACPI_FAILURE (Status))
267         {
268             AcpiOsPrintf ("%s, Could not install debugger write method\n",
269                 AcpiFormatException (Status));
270             return;
271         }
272 
273         Status = AcpiGetHandle (NULL, ACPI_DB_WRITE_METHOD, &WriteHandle);
274         if (ACPI_FAILURE (Status))
275         {
276             AcpiOsPrintf ("Could not obtain handle for debug method %s\n",
277                 ACPI_DB_WRITE_METHOD);
278             return;
279         }
280     }
281 
282     /* Walk the entire namespace, testing each supported named data object */
283 
284     (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
285         ACPI_UINT32_MAX, AcpiDbTestOneObject, NULL, NULL, NULL);
286 }
287 
288 
289 /*******************************************************************************
290  *
291  * FUNCTION:    AcpiDbTestOneObject
292  *
293  * PARAMETERS:  ACPI_WALK_CALLBACK
294  *
295  * RETURN:      Status
296  *
297  * DESCRIPTION: Test one namespace object. Supported types are Integer,
298  *              String, Buffer, BufferField, and FieldUnit. All other object
299  *              types are simply ignored.
300  *
301  *              Note: Support for Packages is not implemented.
302  *
303  ******************************************************************************/
304 
305 static ACPI_STATUS
306 AcpiDbTestOneObject (
307     ACPI_HANDLE             ObjHandle,
308     UINT32                  NestingLevel,
309     void                    *Context,
310     void                    **ReturnValue)
311 {
312     ACPI_NAMESPACE_NODE     *Node;
313     ACPI_OPERAND_OBJECT     *ObjDesc;
314     ACPI_OPERAND_OBJECT     *RegionObj;
315     ACPI_OBJECT_TYPE        LocalType;
316     UINT32                  BitLength = 0;
317     UINT32                  ByteLength = 0;
318     ACPI_STATUS             Status = AE_OK;
319 
320 
321     Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
322     ObjDesc = Node->Object;
323 
324     /*
325      * For the supported types, get the actual bit length or
326      * byte length. Map the type to one of Integer/String/Buffer.
327      */
328     switch (Node->Type)
329     {
330     case ACPI_TYPE_INTEGER:
331 
332         /* Integer width is either 32 or 64 */
333 
334         LocalType = ACPI_TYPE_INTEGER;
335         BitLength = AcpiGbl_IntegerBitWidth;
336         break;
337 
338     case ACPI_TYPE_STRING:
339 
340         LocalType = ACPI_TYPE_STRING;
341         ByteLength = ObjDesc->String.Length;
342         break;
343 
344     case ACPI_TYPE_BUFFER:
345 
346         LocalType = ACPI_TYPE_BUFFER;
347         ByteLength = ObjDesc->Buffer.Length;
348         BitLength = ByteLength * 8;
349         break;
350 
351     case ACPI_TYPE_FIELD_UNIT:
352     case ACPI_TYPE_BUFFER_FIELD:
353     case ACPI_TYPE_LOCAL_REGION_FIELD:
354     case ACPI_TYPE_LOCAL_INDEX_FIELD:
355     case ACPI_TYPE_LOCAL_BANK_FIELD:
356 
357         LocalType = ACPI_TYPE_INTEGER;
358         if (ObjDesc)
359         {
360             /*
361              * Returned object will be a Buffer if the field length
362              * is larger than the size of an Integer (32 or 64 bits
363              * depending on the DSDT version).
364              */
365             BitLength = ObjDesc->CommonField.BitLength;
366             ByteLength = ACPI_ROUND_BITS_UP_TO_BYTES (BitLength);
367             if (BitLength > AcpiGbl_IntegerBitWidth)
368             {
369                 LocalType = ACPI_TYPE_BUFFER;
370             }
371         }
372         break;
373 
374     default:
375 
376         /* Ignore all other types */
377 
378         return (AE_OK);
379     }
380 
381     /* Emit the common prefix: Type:Name */
382 
383     AcpiOsPrintf ("%14s: %4.4s",
384         AcpiUtGetTypeName (Node->Type), Node->Name.Ascii);
385     if (!ObjDesc)
386     {
387         AcpiOsPrintf (" Ignoring, no attached object\n");
388         return (AE_OK);
389     }
390 
391     /*
392      * Check for unsupported region types. Note: AcpiExec simulates
393      * access to SystemMemory, SystemIO, PCI_Config, and EC.
394      */
395     switch (Node->Type)
396     {
397     case ACPI_TYPE_LOCAL_REGION_FIELD:
398 
399         RegionObj = ObjDesc->Field.RegionObj;
400         switch (RegionObj->Region.SpaceId)
401         {
402         case ACPI_ADR_SPACE_SYSTEM_MEMORY:
403         case ACPI_ADR_SPACE_SYSTEM_IO:
404         case ACPI_ADR_SPACE_PCI_CONFIG:
405         case ACPI_ADR_SPACE_EC:
406 
407             break;
408 
409         default:
410 
411             AcpiOsPrintf ("      %s space is not supported [%4.4s]\n",
412                 AcpiUtGetRegionName (RegionObj->Region.SpaceId),
413                 RegionObj->Region.Node->Name.Ascii);
414             return (AE_OK);
415         }
416         break;
417 
418     default:
419         break;
420     }
421 
422     /* At this point, we have resolved the object to one of the major types */
423 
424     switch (LocalType)
425     {
426     case ACPI_TYPE_INTEGER:
427 
428         Status = AcpiDbTestIntegerType (Node, BitLength);
429         break;
430 
431     case ACPI_TYPE_STRING:
432 
433         Status = AcpiDbTestStringType (Node, ByteLength);
434         break;
435 
436     case ACPI_TYPE_BUFFER:
437 
438         Status = AcpiDbTestBufferType (Node, BitLength);
439         break;
440 
441     default:
442 
443         AcpiOsPrintf (" Ignoring, type not implemented (%2.2X)",
444             LocalType);
445         break;
446     }
447 
448     switch (Node->Type)
449     {
450     case ACPI_TYPE_LOCAL_REGION_FIELD:
451 
452         RegionObj = ObjDesc->Field.RegionObj;
453         AcpiOsPrintf (" (%s)",
454             AcpiUtGetRegionName (RegionObj->Region.SpaceId));
455         break;
456 
457     default:
458         break;
459     }
460 
461     AcpiOsPrintf ("\n");
462     return (Status);
463 }
464 
465 
466 /*******************************************************************************
467  *
468  * FUNCTION:    AcpiDbTestIntegerType
469  *
470  * PARAMETERS:  Node                - Parent NS node for the object
471  *              BitLength           - Actual length of the object. Used for
472  *                                    support of arbitrary length FieldUnit
473  *                                    and BufferField objects.
474  *
475  * RETURN:      Status
476  *
477  * DESCRIPTION: Test read/write for an Integer-valued object. Performs a
478  *              write/read/compare of an arbitrary new value, then performs
479  *              a write/read/compare of the original value.
480  *
481  ******************************************************************************/
482 
483 static ACPI_STATUS
484 AcpiDbTestIntegerType (
485     ACPI_NAMESPACE_NODE     *Node,
486     UINT32                  BitLength)
487 {
488     ACPI_OBJECT             *Temp1 = NULL;
489     ACPI_OBJECT             *Temp2 = NULL;
490     ACPI_OBJECT             *Temp3 = NULL;
491     ACPI_OBJECT             WriteValue;
492     UINT64                  ValueToWrite;
493     ACPI_STATUS             Status;
494 
495 
496     if (BitLength > 64)
497     {
498         AcpiOsPrintf (" Invalid length for an Integer: %u", BitLength);
499         return (AE_OK);
500     }
501 
502     /* Read the original value */
503 
504     Status = AcpiDbReadFromObject (Node, ACPI_TYPE_INTEGER, &Temp1);
505     if (ACPI_FAILURE (Status))
506     {
507         return (Status);
508     }
509 
510     AcpiOsPrintf (" (%4.4X/%3.3X) %8.8X%8.8X",
511         BitLength, ACPI_ROUND_BITS_UP_TO_BYTES (BitLength),
512         ACPI_FORMAT_UINT64 (Temp1->Integer.Value));
513 
514     ValueToWrite = ACPI_UINT64_MAX >> (64 - BitLength);
515     if (Temp1->Integer.Value == ValueToWrite)
516     {
517         ValueToWrite = 0;
518     }
519 
520     /* Write a new value */
521 
522     WriteValue.Type = ACPI_TYPE_INTEGER;
523     WriteValue.Integer.Value = ValueToWrite;
524     Status = AcpiDbWriteToObject (Node, &WriteValue);
525     if (ACPI_FAILURE (Status))
526     {
527         goto Exit;
528     }
529 
530     /* Ensure that we can read back the new value */
531 
532     Status = AcpiDbReadFromObject (Node, ACPI_TYPE_INTEGER, &Temp2);
533     if (ACPI_FAILURE (Status))
534     {
535         goto Exit;
536     }
537 
538     if (Temp2->Integer.Value != ValueToWrite)
539     {
540         AcpiOsPrintf (" MISMATCH 2: %8.8X%8.8X, expecting %8.8X%8.8X",
541             ACPI_FORMAT_UINT64 (Temp2->Integer.Value),
542             ACPI_FORMAT_UINT64 (ValueToWrite));
543     }
544 
545     /* Write back the original value */
546 
547     WriteValue.Integer.Value = Temp1->Integer.Value;
548     Status = AcpiDbWriteToObject (Node, &WriteValue);
549     if (ACPI_FAILURE (Status))
550     {
551         goto Exit;
552     }
553 
554     /* Ensure that we can read back the original value */
555 
556     Status = AcpiDbReadFromObject (Node, ACPI_TYPE_INTEGER, &Temp3);
557     if (ACPI_FAILURE (Status))
558     {
559         goto Exit;
560     }
561 
562     if (Temp3->Integer.Value != Temp1->Integer.Value)
563     {
564         AcpiOsPrintf (" MISMATCH 3: %8.8X%8.8X, expecting %8.8X%8.8X",
565             ACPI_FORMAT_UINT64 (Temp3->Integer.Value),
566             ACPI_FORMAT_UINT64 (Temp1->Integer.Value));
567     }
568 
569 Exit:
570     if (Temp1) {AcpiOsFree (Temp1);}
571     if (Temp2) {AcpiOsFree (Temp2);}
572     if (Temp3) {AcpiOsFree (Temp3);}
573     return (AE_OK);
574 }
575 
576 
577 /*******************************************************************************
578  *
579  * FUNCTION:    AcpiDbTestBufferType
580  *
581  * PARAMETERS:  Node                - Parent NS node for the object
582  *              BitLength           - Actual length of the object.
583  *
584  * RETURN:      Status
585  *
586  * DESCRIPTION: Test read/write for an Buffer-valued object. Performs a
587  *              write/read/compare of an arbitrary new value, then performs
588  *              a write/read/compare of the original value.
589  *
590  ******************************************************************************/
591 
592 static ACPI_STATUS
593 AcpiDbTestBufferType (
594     ACPI_NAMESPACE_NODE     *Node,
595     UINT32                  BitLength)
596 {
597     ACPI_OBJECT             *Temp1 = NULL;
598     ACPI_OBJECT             *Temp2 = NULL;
599     ACPI_OBJECT             *Temp3 = NULL;
600     UINT8                   *Buffer;
601     ACPI_OBJECT             WriteValue;
602     ACPI_STATUS             Status;
603     UINT32                  ByteLength;
604     UINT32                  i;
605     UINT8                   ExtraBits;
606 
607 
608     ByteLength = ACPI_ROUND_BITS_UP_TO_BYTES (BitLength);
609     if (ByteLength == 0)
610     {
611         AcpiOsPrintf (" Ignoring zero length buffer");
612         return (AE_OK);
613     }
614 
615     /* Allocate a local buffer */
616 
617     Buffer = ACPI_ALLOCATE_ZEROED (ByteLength);
618     if (!Buffer)
619     {
620         return (AE_NO_MEMORY);
621     }
622 
623     /* Read the original value */
624 
625     Status = AcpiDbReadFromObject (Node, ACPI_TYPE_BUFFER, &Temp1);
626     if (ACPI_FAILURE (Status))
627     {
628         goto Exit;
629     }
630 
631     /* Emit a few bytes of the buffer */
632 
633     AcpiOsPrintf (" (%4.4X/%3.3X)", BitLength, Temp1->Buffer.Length);
634     for (i = 0; ((i < 4) && (i < ByteLength)); i++)
635     {
636         AcpiOsPrintf (" %2.2X", Temp1->Buffer.Pointer[i]);
637     }
638     AcpiOsPrintf ("...  ");
639 
640     /*
641      * Write a new value.
642      *
643      * Handle possible extra bits at the end of the buffer. Can
644      * happen for FieldUnits larger than an integer, but the bit
645      * count is not an integral number of bytes. Zero out the
646      * unused bits.
647      */
648     memset (Buffer, BUFFER_FILL_VALUE, ByteLength);
649     ExtraBits = BitLength % 8;
650     if (ExtraBits)
651     {
652         Buffer [ByteLength - 1] = ACPI_MASK_BITS_ABOVE (ExtraBits);
653     }
654 
655     WriteValue.Type = ACPI_TYPE_BUFFER;
656     WriteValue.Buffer.Length = ByteLength;
657     WriteValue.Buffer.Pointer = Buffer;
658 
659     Status = AcpiDbWriteToObject (Node, &WriteValue);
660     if (ACPI_FAILURE (Status))
661     {
662         goto Exit;
663     }
664 
665     /* Ensure that we can read back the new value */
666 
667     Status = AcpiDbReadFromObject (Node, ACPI_TYPE_BUFFER, &Temp2);
668     if (ACPI_FAILURE (Status))
669     {
670         goto Exit;
671     }
672 
673     if (memcmp (Temp2->Buffer.Pointer, Buffer, ByteLength))
674     {
675         AcpiOsPrintf (" MISMATCH 2: New buffer value");
676     }
677 
678     /* Write back the original value */
679 
680     WriteValue.Buffer.Length = ByteLength;
681     WriteValue.Buffer.Pointer = Temp1->Buffer.Pointer;
682 
683     Status = AcpiDbWriteToObject (Node, &WriteValue);
684     if (ACPI_FAILURE (Status))
685     {
686         goto Exit;
687     }
688 
689     /* Ensure that we can read back the original value */
690 
691     Status = AcpiDbReadFromObject (Node, ACPI_TYPE_BUFFER, &Temp3);
692     if (ACPI_FAILURE (Status))
693     {
694         goto Exit;
695     }
696 
697     if (memcmp (Temp1->Buffer.Pointer,
698             Temp3->Buffer.Pointer, ByteLength))
699     {
700         AcpiOsPrintf (" MISMATCH 3: While restoring original buffer");
701     }
702 
703 Exit:
704     ACPI_FREE (Buffer);
705     if (Temp1) {AcpiOsFree (Temp1);}
706     if (Temp2) {AcpiOsFree (Temp2);}
707     if (Temp3) {AcpiOsFree (Temp3);}
708     return (Status);
709 }
710 
711 
712 /*******************************************************************************
713  *
714  * FUNCTION:    AcpiDbTestStringType
715  *
716  * PARAMETERS:  Node                - Parent NS node for the object
717  *              ByteLength          - Actual length of the object.
718  *
719  * RETURN:      Status
720  *
721  * DESCRIPTION: Test read/write for an String-valued object. Performs a
722  *              write/read/compare of an arbitrary new value, then performs
723  *              a write/read/compare of the original value.
724  *
725  ******************************************************************************/
726 
727 static ACPI_STATUS
728 AcpiDbTestStringType (
729     ACPI_NAMESPACE_NODE     *Node,
730     UINT32                  ByteLength)
731 {
732     ACPI_OBJECT             *Temp1 = NULL;
733     ACPI_OBJECT             *Temp2 = NULL;
734     ACPI_OBJECT             *Temp3 = NULL;
735     char                    *ValueToWrite = "Test String from AML Debugger";
736     ACPI_OBJECT             WriteValue;
737     ACPI_STATUS             Status;
738 
739 
740     /* Read the original value */
741 
742     Status = AcpiDbReadFromObject (Node, ACPI_TYPE_STRING, &Temp1);
743     if (ACPI_FAILURE (Status))
744     {
745         return (Status);
746     }
747 
748     AcpiOsPrintf (" (%4.4X/%3.3X) \"%s\"", (Temp1->String.Length * 8),
749         Temp1->String.Length, Temp1->String.Pointer);
750 
751     /* Write a new value */
752 
753     WriteValue.Type = ACPI_TYPE_STRING;
754     WriteValue.String.Length = strlen (ValueToWrite);
755     WriteValue.String.Pointer = ValueToWrite;
756 
757     Status = AcpiDbWriteToObject (Node, &WriteValue);
758     if (ACPI_FAILURE (Status))
759     {
760         goto Exit;
761     }
762 
763     /* Ensure that we can read back the new value */
764 
765     Status = AcpiDbReadFromObject (Node, ACPI_TYPE_STRING, &Temp2);
766     if (ACPI_FAILURE (Status))
767     {
768         goto Exit;
769     }
770 
771     if (strcmp (Temp2->String.Pointer, ValueToWrite))
772     {
773         AcpiOsPrintf (" MISMATCH 2: %s, expecting %s",
774             Temp2->String.Pointer, ValueToWrite);
775     }
776 
777     /* Write back the original value */
778 
779     WriteValue.String.Length = strlen (Temp1->String.Pointer);
780     WriteValue.String.Pointer = Temp1->String.Pointer;
781 
782     Status = AcpiDbWriteToObject (Node, &WriteValue);
783     if (ACPI_FAILURE (Status))
784     {
785         goto Exit;
786     }
787 
788     /* Ensure that we can read back the original value */
789 
790     Status = AcpiDbReadFromObject (Node, ACPI_TYPE_STRING, &Temp3);
791     if (ACPI_FAILURE (Status))
792     {
793         goto Exit;
794     }
795 
796     if (strcmp (Temp1->String.Pointer, Temp3->String.Pointer))
797     {
798         AcpiOsPrintf (" MISMATCH 3: %s, expecting %s",
799             Temp3->String.Pointer, Temp1->String.Pointer);
800     }
801 
802 Exit:
803     if (Temp1) {AcpiOsFree (Temp1);}
804     if (Temp2) {AcpiOsFree (Temp2);}
805     if (Temp3) {AcpiOsFree (Temp3);}
806     return (Status);
807 }
808 
809 
810 /*******************************************************************************
811  *
812  * FUNCTION:    AcpiDbReadFromObject
813  *
814  * PARAMETERS:  Node                - Parent NS node for the object
815  *              ExpectedType        - Object type expected from the read
816  *              Value               - Where the value read is returned
817  *
818  * RETURN:      Status
819  *
820  * DESCRIPTION: Performs a read from the specified object by invoking the
821  *              special debugger control method that reads the object. Thus,
822  *              the AML interpreter is doing all of the work, increasing the
823  *              validity of the test.
824  *
825  ******************************************************************************/
826 
827 static ACPI_STATUS
828 AcpiDbReadFromObject (
829     ACPI_NAMESPACE_NODE     *Node,
830     ACPI_OBJECT_TYPE        ExpectedType,
831     ACPI_OBJECT             **Value)
832 {
833     ACPI_OBJECT             *RetValue;
834     ACPI_OBJECT_LIST        ParamObjects;
835     ACPI_OBJECT             Params[2];
836     ACPI_BUFFER             ReturnObj;
837     ACPI_STATUS             Status;
838 
839 
840     Params[0].Type = ACPI_TYPE_LOCAL_REFERENCE;
841     Params[0].Reference.ActualType = Node->Type;
842     Params[0].Reference.Handle = ACPI_CAST_PTR (ACPI_HANDLE, Node);
843 
844     ParamObjects.Count = 1;
845     ParamObjects.Pointer = Params;
846 
847     ReturnObj.Length  = ACPI_ALLOCATE_BUFFER;
848 
849     AcpiGbl_MethodExecuting = TRUE;
850     Status = AcpiEvaluateObject (ReadHandle, NULL,
851         &ParamObjects, &ReturnObj);
852     AcpiGbl_MethodExecuting = FALSE;
853 
854     if (ACPI_FAILURE (Status))
855     {
856         AcpiOsPrintf ("Could not read from object, %s",
857             AcpiFormatException (Status));
858         return (Status);
859     }
860 
861     RetValue = (ACPI_OBJECT *) ReturnObj.Pointer;
862 
863     switch (RetValue->Type)
864     {
865     case ACPI_TYPE_INTEGER:
866     case ACPI_TYPE_BUFFER:
867     case ACPI_TYPE_STRING:
868         /*
869          * Did we receive the type we wanted? Most important for the
870          * Integer/Buffer case (when a field is larger than an Integer,
871          * it should return a Buffer).
872          */
873         if (RetValue->Type != ExpectedType)
874         {
875             AcpiOsPrintf (" Type mismatch:  Expected %s, Received %s",
876                 AcpiUtGetTypeName (ExpectedType),
877                 AcpiUtGetTypeName (RetValue->Type));
878 
879             return (AE_TYPE);
880         }
881 
882         *Value = RetValue;
883         break;
884 
885     default:
886 
887         AcpiOsPrintf (" Unsupported return object type, %s",
888             AcpiUtGetTypeName (RetValue->Type));
889 
890         AcpiOsFree (ReturnObj.Pointer);
891         return (AE_TYPE);
892     }
893 
894     return (Status);
895 }
896 
897 
898 /*******************************************************************************
899  *
900  * FUNCTION:    AcpiDbWriteToObject
901  *
902  * PARAMETERS:  Node                - Parent NS node for the object
903  *              Value               - Value to be written
904  *
905  * RETURN:      Status
906  *
907  * DESCRIPTION: Performs a write to the specified object by invoking the
908  *              special debugger control method that writes the object. Thus,
909  *              the AML interpreter is doing all of the work, increasing the
910  *              validity of the test.
911  *
912  ******************************************************************************/
913 
914 static ACPI_STATUS
915 AcpiDbWriteToObject (
916     ACPI_NAMESPACE_NODE     *Node,
917     ACPI_OBJECT             *Value)
918 {
919     ACPI_OBJECT_LIST        ParamObjects;
920     ACPI_OBJECT             Params[2];
921     ACPI_STATUS             Status;
922 
923 
924     Params[0].Type = ACPI_TYPE_LOCAL_REFERENCE;
925     Params[0].Reference.ActualType = Node->Type;
926     Params[0].Reference.Handle = ACPI_CAST_PTR (ACPI_HANDLE, Node);
927 
928     /* Copy the incoming user parameter */
929 
930     memcpy (&Params[1], Value, sizeof (ACPI_OBJECT));
931 
932     ParamObjects.Count = 2;
933     ParamObjects.Pointer = Params;
934 
935     AcpiGbl_MethodExecuting = TRUE;
936     Status = AcpiEvaluateObject (WriteHandle, NULL, &ParamObjects, NULL);
937     AcpiGbl_MethodExecuting = FALSE;
938 
939     if (ACPI_FAILURE (Status))
940     {
941         AcpiOsPrintf ("Could not write to object, %s",
942             AcpiFormatException (Status));
943     }
944 
945     return (Status);
946 }
947 
948 
949 /*******************************************************************************
950  *
951  * FUNCTION:    AcpiDbEvaluateAllPredefinedNames
952  *
953  * PARAMETERS:  CountArg            - Max number of methods to execute
954  *
955  * RETURN:      None
956  *
957  * DESCRIPTION: Namespace batch execution. Execute predefined names in the
958  *              namespace, up to the max count, if specified.
959  *
960  ******************************************************************************/
961 
962 static void
963 AcpiDbEvaluateAllPredefinedNames (
964     char                    *CountArg)
965 {
966     ACPI_DB_EXECUTE_WALK    Info;
967 
968 
969     Info.Count = 0;
970     Info.MaxCount = ACPI_UINT32_MAX;
971 
972     if (CountArg)
973     {
974         Info.MaxCount = strtoul (CountArg, NULL, 0);
975     }
976 
977     /* Search all nodes in namespace */
978 
979     (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
980         ACPI_UINT32_MAX, AcpiDbEvaluateOnePredefinedName, NULL,
981         (void *) &Info, NULL);
982 
983     AcpiOsPrintf (
984         "Evaluated %u predefined names in the namespace\n", Info.Count);
985 }
986 
987 
988 /*******************************************************************************
989  *
990  * FUNCTION:    AcpiDbEvaluateOnePredefinedName
991  *
992  * PARAMETERS:  Callback from WalkNamespace
993  *
994  * RETURN:      Status
995  *
996  * DESCRIPTION: Batch execution module. Currently only executes predefined
997  *              ACPI names.
998  *
999  ******************************************************************************/
1000 
1001 static ACPI_STATUS
1002 AcpiDbEvaluateOnePredefinedName (
1003     ACPI_HANDLE             ObjHandle,
1004     UINT32                  NestingLevel,
1005     void                    *Context,
1006     void                    **ReturnValue)
1007 {
1008     ACPI_NAMESPACE_NODE         *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
1009     ACPI_DB_EXECUTE_WALK        *Info = (ACPI_DB_EXECUTE_WALK *) Context;
1010     char                        *Pathname;
1011     const ACPI_PREDEFINED_INFO  *Predefined;
1012     ACPI_DEVICE_INFO            *ObjInfo;
1013     ACPI_OBJECT_LIST            ParamObjects;
1014     ACPI_OBJECT                 Params[ACPI_METHOD_NUM_ARGS];
1015     ACPI_OBJECT                 *ThisParam;
1016     ACPI_BUFFER                 ReturnObj;
1017     ACPI_STATUS                 Status;
1018     UINT16                      ArgTypeList;
1019     UINT8                       ArgCount;
1020     UINT8                       ArgType;
1021     UINT32                      i;
1022 
1023 
1024     /* The name must be a predefined ACPI name */
1025 
1026     Predefined = AcpiUtMatchPredefinedMethod (Node->Name.Ascii);
1027     if (!Predefined)
1028     {
1029         return (AE_OK);
1030     }
1031 
1032     if (Node->Type == ACPI_TYPE_LOCAL_SCOPE)
1033     {
1034         return (AE_OK);
1035     }
1036 
1037     Pathname = AcpiNsGetNormalizedPathname (Node, TRUE);
1038     if (!Pathname)
1039     {
1040         return (AE_OK);
1041     }
1042 
1043     /* Get the object info for number of method parameters */
1044 
1045     Status = AcpiGetObjectInfo (ObjHandle, &ObjInfo);
1046     if (ACPI_FAILURE (Status))
1047     {
1048         ACPI_FREE (Pathname);
1049         return (Status);
1050     }
1051 
1052     ParamObjects.Count = 0;
1053     ParamObjects.Pointer = NULL;
1054 
1055     if (ObjInfo->Type == ACPI_TYPE_METHOD)
1056     {
1057         /* Setup default parameters (with proper types) */
1058 
1059         ArgTypeList = Predefined->Info.ArgumentList;
1060         ArgCount = METHOD_GET_ARG_COUNT (ArgTypeList);
1061 
1062         /*
1063          * Setup the ACPI-required number of arguments, regardless of what
1064          * the actual method defines. If there is a difference, then the
1065          * method is wrong and a warning will be issued during execution.
1066          */
1067         ThisParam = Params;
1068         for (i = 0; i < ArgCount; i++)
1069         {
1070             ArgType = METHOD_GET_NEXT_TYPE (ArgTypeList);
1071             ThisParam->Type = ArgType;
1072 
1073             switch (ArgType)
1074             {
1075             case ACPI_TYPE_INTEGER:
1076 
1077                 ThisParam->Integer.Value = 1;
1078                 break;
1079 
1080             case ACPI_TYPE_STRING:
1081 
1082                 ThisParam->String.Pointer =
1083                     "This is the default argument string";
1084                 ThisParam->String.Length =
1085                     strlen (ThisParam->String.Pointer);
1086                 break;
1087 
1088             case ACPI_TYPE_BUFFER:
1089 
1090                 ThisParam->Buffer.Pointer = (UINT8 *) Params; /* just a garbage buffer */
1091                 ThisParam->Buffer.Length = 48;
1092                 break;
1093 
1094              case ACPI_TYPE_PACKAGE:
1095 
1096                 ThisParam->Package.Elements = NULL;
1097                 ThisParam->Package.Count = 0;
1098                 break;
1099 
1100            default:
1101 
1102                 AcpiOsPrintf ("%s: Unsupported argument type: %u\n",
1103                     Pathname, ArgType);
1104                 break;
1105             }
1106 
1107             ThisParam++;
1108         }
1109 
1110         ParamObjects.Count = ArgCount;
1111         ParamObjects.Pointer = Params;
1112     }
1113 
1114     ACPI_FREE (ObjInfo);
1115     ReturnObj.Pointer = NULL;
1116     ReturnObj.Length = ACPI_ALLOCATE_BUFFER;
1117 
1118     /* Do the actual method execution */
1119 
1120     AcpiGbl_MethodExecuting = TRUE;
1121 
1122     Status = AcpiEvaluateObject (Node, NULL, &ParamObjects, &ReturnObj);
1123 
1124     AcpiOsPrintf ("%-32s returned %s\n",
1125         Pathname, AcpiFormatException (Status));
1126     AcpiGbl_MethodExecuting = FALSE;
1127     ACPI_FREE (Pathname);
1128 
1129     /* Ignore status from method execution */
1130 
1131     Status = AE_OK;
1132 
1133     /* Update count, check if we have executed enough methods */
1134 
1135     Info->Count++;
1136     if (Info->Count >= Info->MaxCount)
1137     {
1138         Status = AE_CTRL_TERMINATE;
1139     }
1140 
1141     return (Status);
1142 }
1143