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
57static void
58AcpiDbTestAllObjects (
59    void);
60
61static ACPI_STATUS
62AcpiDbTestOneObject (
63    ACPI_HANDLE             ObjHandle,
64    UINT32                  NestingLevel,
65    void                    *Context,
66    void                    **ReturnValue);
67
68static ACPI_STATUS
69AcpiDbTestIntegerType (
70    ACPI_NAMESPACE_NODE     *Node,
71    UINT32                  BitLength);
72
73static ACPI_STATUS
74AcpiDbTestBufferType (
75    ACPI_NAMESPACE_NODE     *Node,
76    UINT32                  BitLength);
77
78static ACPI_STATUS
79AcpiDbTestStringType (
80    ACPI_NAMESPACE_NODE     *Node,
81    UINT32                  ByteLength);
82
83static ACPI_STATUS
84AcpiDbReadFromObject (
85    ACPI_NAMESPACE_NODE     *Node,
86    ACPI_OBJECT_TYPE        ExpectedType,
87    ACPI_OBJECT             **Value);
88
89static ACPI_STATUS
90AcpiDbWriteToObject (
91    ACPI_NAMESPACE_NODE     *Node,
92    ACPI_OBJECT             *Value);
93
94static void
95AcpiDbEvaluateAllPredefinedNames (
96    char                    *CountArg);
97
98static ACPI_STATUS
99AcpiDbEvaluateOnePredefinedName (
100    ACPI_HANDLE             ObjHandle,
101    UINT32                  NestingLevel,
102    void                    *Context,
103    void                    **ReturnValue);
104
105/*
106 * Test subcommands
107 */
108static 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
129static ACPI_HANDLE          ReadHandle = NULL;
130static ACPI_HANDLE          WriteHandle = NULL;
131
132/* ASL Definitions of the debugger read/write control methods */
133
134#if 0
135DefinitionBlock ("ssdt.aml", "SSDT", 2, "Intel", "DEBUG", 0x00000001)
136{
137    Method (_T98, 1, NotSerialized)     /* Read */
138    {
139        Return (DeRefOf (Arg0))
140    }
141}
142DefinitionBlock ("ssdt2.aml", "SSDT", 2, "Intel", "DEBUG", 0x00000001)
143{
144    Method (_T99, 2, NotSerialized)     /* Write */
145    {
146        Store (Arg1, Arg0)
147    }
148}
149#endif
150
151static 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
161static 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
186void
187AcpiDbExecuteTest (
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
233static void
234AcpiDbTestAllObjects (
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
305static ACPI_STATUS
306AcpiDbTestOneObject (
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
483static ACPI_STATUS
484AcpiDbTestIntegerType (
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
569Exit:
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
592static ACPI_STATUS
593AcpiDbTestBufferType (
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
703Exit:
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
727static ACPI_STATUS
728AcpiDbTestStringType (
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
802Exit:
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
827static ACPI_STATUS
828AcpiDbReadFromObject (
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
914static ACPI_STATUS
915AcpiDbWriteToObject (
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
962static void
963AcpiDbEvaluateAllPredefinedNames (
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
1001static ACPI_STATUS
1002AcpiDbEvaluateOnePredefinedName (
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