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