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