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