Subversion Repositories Kolibri OS

Rev

Rev 1498 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1498 serge 1
/*******************************************************************************
2
 *
3
 * Module Name: dbexec - debugger control method execution
4
 *
5
 ******************************************************************************/
6
 
7
/******************************************************************************
8
 *
9
 * 1. Copyright Notice
10
 *
2216 Serge 11
 * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
1498 serge 12
 * All rights reserved.
13
 *
14
 * 2. License
15
 *
16
 * 2.1. This is your license from Intel Corp. under its intellectual property
17
 * rights.  You may have additional license terms from the party that provided
18
 * you this software, covering your right to use that party's intellectual
19
 * property rights.
20
 *
21
 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22
 * copy of the source code appearing in this file ("Covered Code") an
23
 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24
 * base code distributed originally by Intel ("Original Intel Code") to copy,
25
 * make derivatives, distribute, use and display any portion of the Covered
26
 * Code in any form, with the right to sublicense such rights; and
27
 *
28
 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29
 * license (with the right to sublicense), under only those claims of Intel
30
 * patents that are infringed by the Original Intel Code, to make, use, sell,
31
 * offer to sell, and import the Covered Code and derivative works thereof
32
 * solely to the minimum extent necessary to exercise the above copyright
33
 * license, and in no event shall the patent license extend to any additions
34
 * to or modifications of the Original Intel Code.  No other license or right
35
 * is granted directly or by implication, estoppel or otherwise;
36
 *
37
 * The above copyright and patent license is granted only if the following
38
 * conditions are met:
39
 *
40
 * 3. Conditions
41
 *
42
 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43
 * Redistribution of source code of any substantial portion of the Covered
44
 * Code or modification with rights to further distribute source must include
45
 * the above Copyright Notice, the above License, this list of Conditions,
46
 * and the following Disclaimer and Export Compliance provision.  In addition,
47
 * Licensee must cause all Covered Code to which Licensee contributes to
48
 * contain a file documenting the changes Licensee made to create that Covered
49
 * Code and the date of any change.  Licensee must include in that file the
50
 * documentation of any changes made by any predecessor Licensee.  Licensee
51
 * must include a prominent statement that the modification is derived,
52
 * directly or indirectly, from Original Intel Code.
53
 *
54
 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55
 * Redistribution of source code of any substantial portion of the Covered
56
 * Code or modification without rights to further distribute source must
57
 * include the following Disclaimer and Export Compliance provision in the
58
 * documentation and/or other materials provided with distribution.  In
59
 * addition, Licensee may not authorize further sublicense of source of any
60
 * portion of the Covered Code, and must include terms to the effect that the
61
 * license from Licensee to its licensee is limited to the intellectual
62
 * property embodied in the software Licensee provides to its licensee, and
63
 * not to intellectual property embodied in modifications its licensee may
64
 * make.
65
 *
66
 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67
 * substantial portion of the Covered Code or modification must reproduce the
68
 * above Copyright Notice, and the following Disclaimer and Export Compliance
69
 * provision in the documentation and/or other materials provided with the
70
 * distribution.
71
 *
72
 * 3.4. Intel retains all right, title, and interest in and to the Original
73
 * Intel Code.
74
 *
75
 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76
 * Intel shall be used in advertising or otherwise to promote the sale, use or
77
 * other dealings in products derived from or relating to the Covered Code
78
 * without prior written authorization from Intel.
79
 *
80
 * 4. Disclaimer and Export Compliance
81
 *
82
 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83
 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84
 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
85
 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
86
 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
87
 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88
 * PARTICULAR PURPOSE.
89
 *
90
 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91
 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92
 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93
 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94
 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95
 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
96
 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97
 * LIMITED REMEDY.
98
 *
99
 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100
 * software or system incorporating such software without first obtaining any
101
 * required license or other approval from the U. S. Department of Commerce or
102
 * any other agency or department of the United States Government.  In the
103
 * event Licensee exports any such software from the United States or
104
 * re-exports any such software from a foreign destination, Licensee shall
105
 * ensure that the distribution and export/re-export of the software is in
106
 * compliance with all laws, regulations, orders, or other restrictions of the
107
 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108
 * any of its subsidiaries will export/re-export any technical data, process,
109
 * software, or service, directly or indirectly, to any country for which the
110
 * United States government or any agency thereof requires an export license,
111
 * other governmental approval, or letter of assurance, without first obtaining
112
 * such license, approval or letter.
113
 *
114
 *****************************************************************************/
115
 
116
 
117
#include "acpi.h"
118
#include "accommon.h"
119
#include "acdebug.h"
120
#include "acnamesp.h"
121
 
122
#ifdef ACPI_DEBUGGER
123
 
124
#define _COMPONENT          ACPI_CA_DEBUGGER
125
        ACPI_MODULE_NAME    ("dbexec")
126
 
127
 
2216 Serge 128
static ACPI_DB_METHOD_INFO          AcpiGbl_DbMethodInfo;
129
#define DB_DEFAULT_PKG_ELEMENTS     33
1498 serge 130
 
131
/* Local prototypes */
132
 
133
static ACPI_STATUS
134
AcpiDbExecuteMethod (
135
    ACPI_DB_METHOD_INFO     *Info,
136
    ACPI_BUFFER             *ReturnObj);
137
 
138
static void
139
AcpiDbExecuteSetup (
140
    ACPI_DB_METHOD_INFO     *Info);
141
 
142
static UINT32
143
AcpiDbGetOutstandingAllocations (
144
    void);
145
 
146
static void ACPI_SYSTEM_XFACE
147
AcpiDbMethodThread (
148
    void                    *Context);
149
 
150
static ACPI_STATUS
151
AcpiDbExecutionWalk (
152
    ACPI_HANDLE             ObjHandle,
153
    UINT32                  NestingLevel,
154
    void                    *Context,
155
    void                    **ReturnValue);
156
 
2216 Serge 157
static ACPI_STATUS
158
AcpiDbHexCharToValue (
159
    int                     HexChar,
160
    UINT8                   *ReturnValue);
1498 serge 161
 
2216 Serge 162
static ACPI_STATUS
163
AcpiDbConvertToPackage (
164
    char                    *String,
165
    ACPI_OBJECT             *Object);
166
 
167
static ACPI_STATUS
168
AcpiDbConvertToObject (
169
    ACPI_OBJECT_TYPE        Type,
170
    char                    *String,
171
    ACPI_OBJECT             *Object);
172
 
173
static void
174
AcpiDbDeleteObjects (
175
    UINT32                  Count,
176
    ACPI_OBJECT             *Objects);
177
 
178
 
1498 serge 179
/*******************************************************************************
180
 *
2216 Serge 181
 * FUNCTION:    AcpiDbHexCharToValue
182
 *
183
 * PARAMETERS:  HexChar             - Ascii Hex digit, 0-9|a-f|A-F
184
 *              ReturnValue         - Where the converted value is returned
185
 *
186
 * RETURN:      Status
187
 *
188
 * DESCRIPTION: Convert a single hex character to a 4-bit number (0-16).
189
 *
190
 ******************************************************************************/
191
 
192
static ACPI_STATUS
193
AcpiDbHexCharToValue (
194
    int                     HexChar,
195
    UINT8                   *ReturnValue)
196
{
197
    UINT8                   Value;
198
 
199
 
200
    /* Digit must be ascii [0-9a-fA-F] */
201
 
202
    if (!ACPI_IS_XDIGIT (HexChar))
203
    {
204
        return (AE_BAD_HEX_CONSTANT);
205
    }
206
 
207
    if (HexChar <= 0x39)
208
    {
209
        Value = (UINT8) (HexChar - 0x30);
210
    }
211
    else
212
    {
213
        Value = (UINT8) (ACPI_TOUPPER (HexChar) - 0x37);
214
    }
215
 
216
    *ReturnValue = Value;
217
    return (AE_OK);
218
}
219
 
220
 
221
/*******************************************************************************
222
 *
223
 * FUNCTION:    AcpiDbHexByteToBinary
224
 *
225
 * PARAMETERS:  HexByte             - Double hex digit (0x00 - 0xFF) in format:
226
 *                                    HiByte then LoByte.
227
 *              ReturnValue         - Where the converted value is returned
228
 *
229
 * RETURN:      Status
230
 *
231
 * DESCRIPTION: Convert two hex characters to an 8 bit number (0 - 255).
232
 *
233
 ******************************************************************************/
234
 
235
static ACPI_STATUS
236
AcpiDbHexByteToBinary (
237
    char                    *HexByte,
238
    UINT8                   *ReturnValue)
239
{
240
    UINT8                   Local0;
241
    UINT8                   Local1;
242
    ACPI_STATUS             Status;
243
 
244
 
245
    /* High byte */
246
 
247
    Status = AcpiDbHexCharToValue (HexByte[0], &Local0);
248
    if (ACPI_FAILURE (Status))
249
    {
250
        return (Status);
251
    }
252
 
253
    /* Low byte */
254
 
255
    Status = AcpiDbHexCharToValue (HexByte[1], &Local1);
256
    if (ACPI_FAILURE (Status))
257
    {
258
        return (Status);
259
    }
260
 
261
    *ReturnValue = (UINT8) ((Local0 << 4) | Local1);
262
    return (AE_OK);
263
}
264
 
265
 
266
/*******************************************************************************
267
 *
268
 * FUNCTION:    AcpiDbConvertToBuffer
269
 *
270
 * PARAMETERS:  String              - Input string to be converted
271
 *              Object              - Where the buffer object is returned
272
 *
273
 * RETURN:      Status
274
 *
275
 * DESCRIPTION: Convert a string to a buffer object. String is treated a list
276
 *              of buffer elements, each separated by a space or comma.
277
 *
278
 ******************************************************************************/
279
 
280
static ACPI_STATUS
281
AcpiDbConvertToBuffer (
282
    char                    *String,
283
    ACPI_OBJECT             *Object)
284
{
285
    UINT32                  i;
286
    UINT32                  j;
287
    UINT32                  Length;
288
    UINT8                   *Buffer;
289
    ACPI_STATUS             Status;
290
 
291
 
292
    /* Generate the final buffer length */
293
 
294
    for (i = 0, Length = 0; String[i];)
295
    {
296
        i+=2;
297
        Length++;
298
 
299
        while (String[i] &&
300
              ((String[i] == ',') || (String[i] == ' ')))
301
        {
302
            i++;
303
        }
304
    }
305
 
306
    Buffer = ACPI_ALLOCATE (Length);
307
    if (!Buffer)
308
    {
309
        return (AE_NO_MEMORY);
310
    }
311
 
312
    /* Convert the command line bytes to the buffer */
313
 
314
    for (i = 0, j = 0; String[i];)
315
    {
316
        Status = AcpiDbHexByteToBinary (&String[i], &Buffer[j]);
317
        if (ACPI_FAILURE (Status))
318
        {
319
            ACPI_FREE (Buffer);
320
            return (Status);
321
        }
322
 
323
        j++;
324
        i+=2;
325
        while (String[i] &&
326
              ((String[i] == ',') || (String[i] == ' ')))
327
        {
328
            i++;
329
        }
330
    }
331
 
332
    Object->Type = ACPI_TYPE_BUFFER;
333
    Object->Buffer.Pointer = Buffer;
334
    Object->Buffer.Length = Length;
335
    return (AE_OK);
336
}
337
 
338
 
339
/*******************************************************************************
340
 *
341
 * FUNCTION:    AcpiDbConvertToPackage
342
 *
343
 * PARAMETERS:  String              - Input string to be converted
344
 *              Object              - Where the package object is returned
345
 *
346
 * RETURN:      Status
347
 *
348
 * DESCRIPTION: Convert a string to a package object. Handles nested packages
349
 *              via recursion with AcpiDbConvertToObject.
350
 *
351
 ******************************************************************************/
352
 
353
static ACPI_STATUS
354
AcpiDbConvertToPackage (
355
    char                    *String,
356
    ACPI_OBJECT             *Object)
357
{
358
    char                    *This;
359
    char                    *Next;
360
    UINT32                  i;
361
    ACPI_OBJECT_TYPE        Type;
362
    ACPI_OBJECT             *Elements;
363
    ACPI_STATUS             Status;
364
 
365
 
366
    Elements = ACPI_ALLOCATE_ZEROED (
367
        DB_DEFAULT_PKG_ELEMENTS * sizeof (ACPI_OBJECT));
368
 
369
    This = String;
370
    for (i = 0; i < (DB_DEFAULT_PKG_ELEMENTS - 1); i++)
371
    {
372
        This = AcpiDbGetNextToken (This, &Next, &Type);
373
        if (!This)
374
        {
375
            break;
376
        }
377
 
378
        /* Recursive call to convert each package element */
379
 
380
        Status = AcpiDbConvertToObject (Type, This, &Elements[i]);
381
        if (ACPI_FAILURE (Status))
382
        {
383
            AcpiDbDeleteObjects (i + 1, Elements);
384
            ACPI_FREE (Elements);
385
            return (Status);
386
        }
387
 
388
        This = Next;
389
    }
390
 
391
    Object->Type = ACPI_TYPE_PACKAGE;
392
    Object->Package.Count = i;
393
    Object->Package.Elements = Elements;
394
    return (AE_OK);
395
}
396
 
397
 
398
/*******************************************************************************
399
 *
400
 * FUNCTION:    AcpiDbConvertToObject
401
 *
402
 * PARAMETERS:  Type                - Object type as determined by parser
403
 *              String              - Input string to be converted
404
 *              Object              - Where the new object is returned
405
 *
406
 * RETURN:      Status
407
 *
408
 * DESCRIPTION: Convert a typed and tokenized string to an ACPI_OBJECT. Typing:
409
 *              1) String objects were surrounded by quotes.
410
 *              2) Buffer objects were surrounded by parentheses.
411
 *              3) Package objects were surrounded by brackets "[]".
412
 *              4) All standalone tokens are treated as integers.
413
 *
414
 ******************************************************************************/
415
 
416
static ACPI_STATUS
417
AcpiDbConvertToObject (
418
    ACPI_OBJECT_TYPE        Type,
419
    char                    *String,
420
    ACPI_OBJECT             *Object)
421
{
422
    ACPI_STATUS             Status = AE_OK;
423
 
424
 
425
    switch (Type)
426
    {
427
    case ACPI_TYPE_STRING:
428
        Object->Type = ACPI_TYPE_STRING;
429
        Object->String.Pointer = String;
430
        Object->String.Length = (UINT32) ACPI_STRLEN (String);
431
        break;
432
 
433
    case ACPI_TYPE_BUFFER:
434
        Status = AcpiDbConvertToBuffer (String, Object);
435
        break;
436
 
437
    case ACPI_TYPE_PACKAGE:
438
        Status = AcpiDbConvertToPackage (String, Object);
439
        break;
440
 
441
    default:
442
        Object->Type = ACPI_TYPE_INTEGER;
443
        Status = AcpiUtStrtoul64 (String, 16, &Object->Integer.Value);
444
        break;
445
    }
446
 
447
    return (Status);
448
}
449
 
450
 
451
/*******************************************************************************
452
 *
453
 * FUNCTION:    AcpiDbDeleteObjects
454
 *
455
 * PARAMETERS:  Count               - Count of objects in the list
456
 *              Objects             - Array of ACPI_OBJECTs to be deleted
457
 *
458
 * RETURN:      None
459
 *
460
 * DESCRIPTION: Delete a list of ACPI_OBJECTS. Handles packages and nested
461
 *              packages via recursion.
462
 *
463
 ******************************************************************************/
464
 
465
static void
466
AcpiDbDeleteObjects (
467
    UINT32                  Count,
468
    ACPI_OBJECT             *Objects)
469
{
470
    UINT32                  i;
471
 
472
 
473
    for (i = 0; i < Count; i++)
474
    {
475
        switch (Objects[i].Type)
476
        {
477
        case ACPI_TYPE_BUFFER:
478
            ACPI_FREE (Objects[i].Buffer.Pointer);
479
            break;
480
 
481
        case ACPI_TYPE_PACKAGE:
482
 
483
            /* Recursive call to delete package elements */
484
 
485
            AcpiDbDeleteObjects (Objects[i].Package.Count,
486
                Objects[i].Package.Elements);
487
 
488
            /* Free the elements array */
489
 
490
            ACPI_FREE (Objects[i].Package.Elements);
491
            break;
492
 
493
        default:
494
            break;
495
        }
496
    }
497
}
498
 
499
 
500
/*******************************************************************************
501
 *
1498 serge 502
 * FUNCTION:    AcpiDbExecuteMethod
503
 *
504
 * PARAMETERS:  Info            - Valid info segment
505
 *              ReturnObj       - Where to put return object
506
 *
507
 * RETURN:      Status
508
 *
509
 * DESCRIPTION: Execute a control method.
510
 *
511
 ******************************************************************************/
512
 
513
static ACPI_STATUS
514
AcpiDbExecuteMethod (
515
    ACPI_DB_METHOD_INFO     *Info,
516
    ACPI_BUFFER             *ReturnObj)
517
{
518
    ACPI_STATUS             Status;
519
    ACPI_OBJECT_LIST        ParamObjects;
520
    ACPI_OBJECT             Params[ACPI_METHOD_NUM_ARGS];
521
    ACPI_HANDLE             Handle;
2216 Serge 522
    ACPI_DEVICE_INFO        *ObjInfo;
1498 serge 523
    UINT32                  i;
524
 
525
 
2216 Serge 526
    ACPI_FUNCTION_TRACE (DbExecuteMethod);
527
 
528
 
1498 serge 529
    if (AcpiGbl_DbOutputToFile && !AcpiDbgLevel)
530
    {
531
        AcpiOsPrintf ("Warning: debug output is not enabled!\n");
532
    }
533
 
534
    /* Get the NS node, determines existence also */
535
 
536
    Status = AcpiGetHandle (NULL, Info->Pathname, &Handle);
537
    if (ACPI_FAILURE (Status))
538
    {
2216 Serge 539
        return_ACPI_STATUS (Status);
1498 serge 540
    }
541
 
542
    /* Get the object info for number of method parameters */
543
 
544
    Status = AcpiGetObjectInfo (Handle, &ObjInfo);
545
    if (ACPI_FAILURE (Status))
546
    {
2216 Serge 547
        return_ACPI_STATUS (Status);
1498 serge 548
    }
549
 
550
    ParamObjects.Pointer = NULL;
551
    ParamObjects.Count   = 0;
552
 
553
    if (ObjInfo->Type == ACPI_TYPE_METHOD)
554
    {
555
        /* Are there arguments to the method? */
556
 
2216 Serge 557
        i = 0;
1498 serge 558
        if (Info->Args && Info->Args[0])
559
        {
2216 Serge 560
            /* Get arguments passed on the command line */
561
 
562
            for (; Info->Args[i] &&
563
                (i < ACPI_METHOD_NUM_ARGS) &&
564
                (i < ObjInfo->ParamCount);
565
                i++)
1498 serge 566
            {
2216 Serge 567
                /* Convert input string (token) to an actual ACPI_OBJECT */
568
 
569
                Status = AcpiDbConvertToObject (Info->Types[i],
570
                    Info->Args[i], &Params[i]);
571
                if (ACPI_FAILURE (Status))
572
                {
573
                    ACPI_EXCEPTION ((AE_INFO, Status,
574
                        "While parsing method arguments"));
575
                    goto Cleanup;
576
                }
1498 serge 577
            }
2216 Serge 578
        }
1498 serge 579
 
2216 Serge 580
        /* Create additional "default" parameters as needed */
581
 
582
        if (i < ObjInfo->ParamCount)
1498 serge 583
        {
2216 Serge 584
            AcpiOsPrintf ("Adding %u arguments containing default values\n",
585
                ObjInfo->ParamCount - i);
1498 serge 586
 
2216 Serge 587
            for (; i < ObjInfo->ParamCount; i++)
1498 serge 588
            {
589
                switch (i)
590
                {
591
                case 0:
592
 
593
                    Params[0].Type           = ACPI_TYPE_INTEGER;
594
                    Params[0].Integer.Value  = 0x01020304;
595
                    break;
596
 
597
                case 1:
598
 
599
                    Params[1].Type           = ACPI_TYPE_STRING;
600
                    Params[1].String.Length  = 12;
601
                    Params[1].String.Pointer = "AML Debugger";
602
                    break;
603
 
604
                default:
605
 
606
                    Params[i].Type           = ACPI_TYPE_INTEGER;
607
                    Params[i].Integer.Value  = i * (UINT64) 0x1000;
608
                    break;
609
                }
610
            }
2216 Serge 611
        }
1498 serge 612
 
2216 Serge 613
        ParamObjects.Count = ObjInfo->ParamCount;
614
        ParamObjects.Pointer = Params;
1498 serge 615
    }
616
 
617
    /* Prepare for a return object of arbitrary size */
618
 
619
    ReturnObj->Pointer = AcpiGbl_DbBuffer;
620
    ReturnObj->Length  = ACPI_DEBUG_BUFFER_SIZE;
621
 
622
    /* Do the actual method execution */
623
 
624
    AcpiGbl_MethodExecuting = TRUE;
625
    Status = AcpiEvaluateObject (NULL,
2216 Serge 626
        Info->Pathname, &ParamObjects, ReturnObj);
1498 serge 627
 
628
    AcpiGbl_CmSingleStep = FALSE;
629
    AcpiGbl_MethodExecuting = FALSE;
630
 
2216 Serge 631
    if (ACPI_FAILURE (Status))
632
    {
633
        ACPI_EXCEPTION ((AE_INFO, Status,
634
            "while executing %s from debugger", Info->Pathname));
635
 
636
        if (Status == AE_BUFFER_OVERFLOW)
637
        {
638
            ACPI_ERROR ((AE_INFO,
639
                "Possible overflow of internal debugger buffer (size 0x%X needed 0x%X)",
640
                ACPI_DEBUG_BUFFER_SIZE, (UINT32) ReturnObj->Length));
641
        }
642
    }
643
 
644
Cleanup:
645
    AcpiDbDeleteObjects (ObjInfo->ParamCount, Params);
646
    ACPI_FREE (ObjInfo);
647
 
648
    return_ACPI_STATUS (Status);
1498 serge 649
}
650
 
651
 
652
/*******************************************************************************
653
 *
654
 * FUNCTION:    AcpiDbExecuteSetup
655
 *
656
 * PARAMETERS:  Info            - Valid method info
657
 *
658
 * RETURN:      None
659
 *
660
 * DESCRIPTION: Setup info segment prior to method execution
661
 *
662
 ******************************************************************************/
663
 
664
static void
665
AcpiDbExecuteSetup (
666
    ACPI_DB_METHOD_INFO     *Info)
667
{
668
 
669
    /* Catenate the current scope to the supplied name */
670
 
671
    Info->Pathname[0] = 0;
672
    if ((Info->Name[0] != '\\') &&
673
        (Info->Name[0] != '/'))
674
    {
675
        ACPI_STRCAT (Info->Pathname, AcpiGbl_DbScopeBuf);
676
    }
677
 
678
    ACPI_STRCAT (Info->Pathname, Info->Name);
679
    AcpiDbPrepNamestring (Info->Pathname);
680
 
681
    AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);
682
    AcpiOsPrintf ("Executing %s\n", Info->Pathname);
683
 
684
    if (Info->Flags & EX_SINGLE_STEP)
685
    {
686
        AcpiGbl_CmSingleStep = TRUE;
687
        AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
688
    }
689
 
690
    else
691
    {
692
        /* No single step, allow redirection to a file */
693
 
694
        AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);
695
    }
696
}
697
 
698
 
699
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
700
UINT32
701
AcpiDbGetCacheInfo (
702
    ACPI_MEMORY_LIST        *Cache)
703
{
704
 
705
    return (Cache->TotalAllocated - Cache->TotalFreed - Cache->CurrentDepth);
706
}
707
#endif
708
 
709
/*******************************************************************************
710
 *
711
 * FUNCTION:    AcpiDbGetOutstandingAllocations
712
 *
713
 * PARAMETERS:  None
714
 *
715
 * RETURN:      Current global allocation count minus cache entries
716
 *
717
 * DESCRIPTION: Determine the current number of "outstanding" allocations --
718
 *              those allocations that have not been freed and also are not
719
 *              in one of the various object caches.
720
 *
721
 ******************************************************************************/
722
 
723
static UINT32
724
AcpiDbGetOutstandingAllocations (
725
    void)
726
{
727
    UINT32                  Outstanding = 0;
728
 
729
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
730
 
731
    Outstanding += AcpiDbGetCacheInfo (AcpiGbl_StateCache);
732
    Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeCache);
733
    Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeExtCache);
734
    Outstanding += AcpiDbGetCacheInfo (AcpiGbl_OperandCache);
735
#endif
736
 
737
    return (Outstanding);
738
}
739
 
740
 
741
/*******************************************************************************
742
 *
743
 * FUNCTION:    AcpiDbExecutionWalk
744
 *
745
 * PARAMETERS:  WALK_CALLBACK
746
 *
747
 * RETURN:      Status
748
 *
749
 * DESCRIPTION: Execute a control method.  Name is relative to the current
750
 *              scope.
751
 *
752
 ******************************************************************************/
753
 
754
static ACPI_STATUS
755
AcpiDbExecutionWalk (
756
    ACPI_HANDLE             ObjHandle,
757
    UINT32                  NestingLevel,
758
    void                    *Context,
759
    void                    **ReturnValue)
760
{
761
    ACPI_OPERAND_OBJECT     *ObjDesc;
762
    ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
763
    ACPI_BUFFER             ReturnObj;
764
    ACPI_STATUS             Status;
765
 
766
 
767
    ObjDesc = AcpiNsGetAttachedObject (Node);
768
    if (ObjDesc->Method.ParamCount)
769
    {
770
        return (AE_OK);
771
    }
772
 
773
    ReturnObj.Pointer = NULL;
774
    ReturnObj.Length = ACPI_ALLOCATE_BUFFER;
775
 
776
    AcpiNsPrintNodePathname (Node, "Execute");
777
 
778
    /* Do the actual method execution */
779
 
780
    AcpiOsPrintf ("\n");
781
    AcpiGbl_MethodExecuting = TRUE;
782
 
783
    Status = AcpiEvaluateObject (Node, NULL, NULL, &ReturnObj);
784
 
785
    AcpiOsPrintf ("[%4.4s] returned %s\n", AcpiUtGetNodeName (Node),
786
            AcpiFormatException (Status));
787
    AcpiGbl_MethodExecuting = FALSE;
788
 
789
    return (AE_OK);
790
}
791
 
792
 
793
/*******************************************************************************
794
 *
795
 * FUNCTION:    AcpiDbExecute
796
 *
797
 * PARAMETERS:  Name                - Name of method to execute
798
 *              Args                - Parameters to the method
799
 *              Flags               - single step/no single step
800
 *
801
 * RETURN:      None
802
 *
803
 * DESCRIPTION: Execute a control method.  Name is relative to the current
804
 *              scope.
805
 *
806
 ******************************************************************************/
807
 
808
void
809
AcpiDbExecute (
810
    char                    *Name,
811
    char                    **Args,
2216 Serge 812
    ACPI_OBJECT_TYPE        *Types,
1498 serge 813
    UINT32                  Flags)
814
{
815
    ACPI_STATUS             Status;
816
    ACPI_BUFFER             ReturnObj;
817
    char                    *NameString;
818
 
819
 
820
#ifdef ACPI_DEBUG_OUTPUT
821
    UINT32                  PreviousAllocations;
822
    UINT32                  Allocations;
823
 
824
 
825
    /* Memory allocation tracking */
826
 
827
    PreviousAllocations = AcpiDbGetOutstandingAllocations ();
828
#endif
829
 
830
    if (*Name == '*')
831
    {
832
        (void) AcpiWalkNamespace (ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT,
833
                    ACPI_UINT32_MAX, AcpiDbExecutionWalk, NULL, NULL, NULL);
834
        return;
835
    }
836
    else
837
    {
838
        NameString = ACPI_ALLOCATE (ACPI_STRLEN (Name) + 1);
839
        if (!NameString)
840
        {
841
            return;
842
        }
843
 
844
        ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO));
845
 
846
        ACPI_STRCPY (NameString, Name);
847
        AcpiUtStrupr (NameString);
848
        AcpiGbl_DbMethodInfo.Name = NameString;
849
        AcpiGbl_DbMethodInfo.Args = Args;
2216 Serge 850
        AcpiGbl_DbMethodInfo.Types = Types;
1498 serge 851
        AcpiGbl_DbMethodInfo.Flags = Flags;
852
 
853
        ReturnObj.Pointer = NULL;
854
        ReturnObj.Length = ACPI_ALLOCATE_BUFFER;
855
 
856
        AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo);
857
        Status = AcpiDbExecuteMethod (&AcpiGbl_DbMethodInfo, &ReturnObj);
858
        ACPI_FREE (NameString);
859
    }
860
 
861
    /*
862
     * Allow any handlers in separate threads to complete.
863
     * (Such as Notify handlers invoked from AML executed above).
864
     */
865
    AcpiOsSleep ((UINT64) 10);
866
 
867
 
868
#ifdef ACPI_DEBUG_OUTPUT
869
 
870
    /* Memory allocation tracking */
871
 
872
    Allocations = AcpiDbGetOutstandingAllocations () - PreviousAllocations;
873
 
874
    AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);
875
 
876
    if (Allocations > 0)
877
    {
878
        AcpiOsPrintf ("Outstanding: 0x%X allocations after execution\n",
879
                        Allocations);
880
    }
881
#endif
882
 
883
    if (ACPI_FAILURE (Status))
884
    {
885
        AcpiOsPrintf ("Execution of %s failed with status %s\n",
886
            AcpiGbl_DbMethodInfo.Pathname, AcpiFormatException (Status));
887
    }
888
    else
889
    {
890
        /* Display a return object, if any */
891
 
892
        if (ReturnObj.Length)
893
        {
894
            AcpiOsPrintf ("Execution of %s returned object %p Buflen %X\n",
895
                AcpiGbl_DbMethodInfo.Pathname, ReturnObj.Pointer,
896
                (UINT32) ReturnObj.Length);
897
            AcpiDbDumpExternalObject (ReturnObj.Pointer, 1);
898
        }
899
        else
900
        {
901
            AcpiOsPrintf ("No return object from execution of %s\n",
902
                AcpiGbl_DbMethodInfo.Pathname);
903
        }
904
    }
905
 
906
    AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
907
}
908
 
909
 
910
/*******************************************************************************
911
 *
912
 * FUNCTION:    AcpiDbMethodThread
913
 *
914
 * PARAMETERS:  Context             - Execution info segment
915
 *
916
 * RETURN:      None
917
 *
918
 * DESCRIPTION: Debugger execute thread.  Waits for a command line, then
919
 *              simply dispatches it.
920
 *
921
 ******************************************************************************/
922
 
923
static void ACPI_SYSTEM_XFACE
924
AcpiDbMethodThread (
925
    void                    *Context)
926
{
927
    ACPI_STATUS             Status;
928
    ACPI_DB_METHOD_INFO     *Info = Context;
929
    ACPI_DB_METHOD_INFO     LocalInfo;
930
    UINT32                  i;
931
    UINT8                   Allow;
932
    ACPI_BUFFER             ReturnObj;
933
 
934
 
935
    /*
936
     * AcpiGbl_DbMethodInfo.Arguments will be passed as method arguments.
937
     * Prevent AcpiGbl_DbMethodInfo from being modified by multiple threads
938
     * concurrently.
939
     *
940
     * Note: The arguments we are passing are used by the ASL test suite
941
     * (aslts). Do not change them without updating the tests.
942
     */
943
    (void) AcpiOsWaitSemaphore (Info->InfoGate, 1, ACPI_WAIT_FOREVER);
944
 
945
    if (Info->InitArgs)
946
    {
947
        AcpiDbUInt32ToHexString (Info->NumCreated, Info->IndexOfThreadStr);
2216 Serge 948
        AcpiDbUInt32ToHexString ((UINT32) AcpiOsGetThreadId (), Info->IdOfThreadStr);
1498 serge 949
    }
950
 
951
    if (Info->Threads && (Info->NumCreated < Info->NumThreads))
952
    {
2216 Serge 953
        Info->Threads[Info->NumCreated++] = AcpiOsGetThreadId();
1498 serge 954
    }
955
 
956
    LocalInfo = *Info;
957
    LocalInfo.Args = LocalInfo.Arguments;
958
    LocalInfo.Arguments[0] = LocalInfo.NumThreadsStr;
959
    LocalInfo.Arguments[1] = LocalInfo.IdOfThreadStr;
960
    LocalInfo.Arguments[2] = LocalInfo.IndexOfThreadStr;
961
    LocalInfo.Arguments[3] = NULL;
962
 
2216 Serge 963
    LocalInfo.Types = LocalInfo.ArgTypes;
964
 
1498 serge 965
    (void) AcpiOsSignalSemaphore (Info->InfoGate, 1);
966
 
967
    for (i = 0; i < Info->NumLoops; i++)
968
    {
969
        Status = AcpiDbExecuteMethod (&LocalInfo, &ReturnObj);
970
        if (ACPI_FAILURE (Status))
971
        {
972
            AcpiOsPrintf ("%s During execution of %s at iteration %X\n",
973
                AcpiFormatException (Status), Info->Pathname, i);
974
            if (Status == AE_ABORT_METHOD)
975
            {
976
                break;
977
            }
978
        }
979
 
980
#if 0
981
        if ((i % 100) == 0)
982
        {
983
            AcpiOsPrintf ("%u executions, Thread 0x%x\n", i, AcpiOsGetThreadId ());
984
        }
985
 
986
        if (ReturnObj.Length)
987
        {
988
            AcpiOsPrintf ("Execution of %s returned object %p Buflen %X\n",
989
                Info->Pathname, ReturnObj.Pointer, (UINT32) ReturnObj.Length);
990
            AcpiDbDumpExternalObject (ReturnObj.Pointer, 1);
991
        }
992
#endif
993
    }
994
 
995
    /* Signal our completion */
996
 
997
    Allow = 0;
998
    (void) AcpiOsWaitSemaphore (Info->ThreadCompleteGate, 1, ACPI_WAIT_FOREVER);
999
    Info->NumCompleted++;
1000
 
1001
    if (Info->NumCompleted == Info->NumThreads)
1002
    {
1003
        /* Do signal for main thread once only */
1004
        Allow = 1;
1005
    }
1006
 
1007
    (void) AcpiOsSignalSemaphore (Info->ThreadCompleteGate, 1);
1008
 
1009
    if (Allow)
1010
    {
1011
        Status = AcpiOsSignalSemaphore (Info->MainThreadGate, 1);
1012
        if (ACPI_FAILURE (Status))
1013
        {
1014
            AcpiOsPrintf ("Could not signal debugger thread sync semaphore, %s\n",
1015
                AcpiFormatException (Status));
1016
        }
1017
    }
1018
}
1019
 
1020
 
1021
/*******************************************************************************
1022
 *
1023
 * FUNCTION:    AcpiDbCreateExecutionThreads
1024
 *
1025
 * PARAMETERS:  NumThreadsArg           - Number of threads to create
1026
 *              NumLoopsArg             - Loop count for the thread(s)
1027
 *              MethodNameArg           - Control method to execute
1028
 *
1029
 * RETURN:      None
1030
 *
1031
 * DESCRIPTION: Create threads to execute method(s)
1032
 *
1033
 ******************************************************************************/
1034
 
1035
void
1036
AcpiDbCreateExecutionThreads (
1037
    char                    *NumThreadsArg,
1038
    char                    *NumLoopsArg,
1039
    char                    *MethodNameArg)
1040
{
1041
    ACPI_STATUS             Status;
1042
    UINT32                  NumThreads;
1043
    UINT32                  NumLoops;
1044
    UINT32                  i;
1045
    UINT32                  Size;
1046
    ACPI_MUTEX              MainThreadGate;
1047
    ACPI_MUTEX              ThreadCompleteGate;
1048
    ACPI_MUTEX              InfoGate;
1049
 
1050
 
1051
    /* Get the arguments */
1052
 
1053
    NumThreads = ACPI_STRTOUL (NumThreadsArg, NULL, 0);
1054
    NumLoops   = ACPI_STRTOUL (NumLoopsArg, NULL, 0);
1055
 
1056
    if (!NumThreads || !NumLoops)
1057
    {
1058
        AcpiOsPrintf ("Bad argument: Threads %X, Loops %X\n",
1059
            NumThreads, NumLoops);
1060
        return;
1061
    }
1062
 
1063
    /*
1064
     * Create the semaphore for synchronization of
1065
     * the created threads with the main thread.
1066
     */
1067
    Status = AcpiOsCreateSemaphore (1, 0, &MainThreadGate);
1068
    if (ACPI_FAILURE (Status))
1069
    {
1070
        AcpiOsPrintf ("Could not create semaphore for synchronization with the main thread, %s\n",
1071
            AcpiFormatException (Status));
1072
        return;
1073
    }
1074
 
1075
    /*
1076
     * Create the semaphore for synchronization
1077
     * between the created threads.
1078
     */
1079
    Status = AcpiOsCreateSemaphore (1, 1, &ThreadCompleteGate);
1080
    if (ACPI_FAILURE (Status))
1081
    {
1082
        AcpiOsPrintf ("Could not create semaphore for synchronization between the created threads, %s\n",
1083
            AcpiFormatException (Status));
1084
        (void) AcpiOsDeleteSemaphore (MainThreadGate);
1085
        return;
1086
    }
1087
 
1088
    Status = AcpiOsCreateSemaphore (1, 1, &InfoGate);
1089
    if (ACPI_FAILURE (Status))
1090
    {
1091
        AcpiOsPrintf ("Could not create semaphore for synchronization of AcpiGbl_DbMethodInfo, %s\n",
1092
            AcpiFormatException (Status));
1093
        (void) AcpiOsDeleteSemaphore (ThreadCompleteGate);
1094
        (void) AcpiOsDeleteSemaphore (MainThreadGate);
1095
        return;
1096
    }
1097
 
1098
    ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO));
1099
 
1100
    /* Array to store IDs of threads */
1101
 
1102
    AcpiGbl_DbMethodInfo.NumThreads = NumThreads;
2216 Serge 1103
    Size = sizeof (ACPI_THREAD_ID) * AcpiGbl_DbMethodInfo.NumThreads;
1104
    AcpiGbl_DbMethodInfo.Threads = AcpiOsAllocate (Size);
1498 serge 1105
    if (AcpiGbl_DbMethodInfo.Threads == NULL)
1106
    {
1107
        AcpiOsPrintf ("No memory for thread IDs array\n");
1108
        (void) AcpiOsDeleteSemaphore (MainThreadGate);
1109
        (void) AcpiOsDeleteSemaphore (ThreadCompleteGate);
1110
        (void) AcpiOsDeleteSemaphore (InfoGate);
1111
        return;
1112
    }
1113
    ACPI_MEMSET (AcpiGbl_DbMethodInfo.Threads, 0, Size);
1114
 
1115
    /* Setup the context to be passed to each thread */
1116
 
1117
    AcpiGbl_DbMethodInfo.Name = MethodNameArg;
1118
    AcpiGbl_DbMethodInfo.Flags = 0;
1119
    AcpiGbl_DbMethodInfo.NumLoops = NumLoops;
1120
    AcpiGbl_DbMethodInfo.MainThreadGate = MainThreadGate;
1121
    AcpiGbl_DbMethodInfo.ThreadCompleteGate = ThreadCompleteGate;
1122
    AcpiGbl_DbMethodInfo.InfoGate = InfoGate;
1123
 
1124
    /* Init arguments to be passed to method */
1125
 
1126
    AcpiGbl_DbMethodInfo.InitArgs = 1;
1127
    AcpiGbl_DbMethodInfo.Args = AcpiGbl_DbMethodInfo.Arguments;
1128
    AcpiGbl_DbMethodInfo.Arguments[0] = AcpiGbl_DbMethodInfo.NumThreadsStr;
1129
    AcpiGbl_DbMethodInfo.Arguments[1] = AcpiGbl_DbMethodInfo.IdOfThreadStr;
1130
    AcpiGbl_DbMethodInfo.Arguments[2] = AcpiGbl_DbMethodInfo.IndexOfThreadStr;
1131
    AcpiGbl_DbMethodInfo.Arguments[3] = NULL;
2216 Serge 1132
 
1133
    AcpiGbl_DbMethodInfo.Types = AcpiGbl_DbMethodInfo.ArgTypes;
1134
    AcpiGbl_DbMethodInfo.ArgTypes[0] = ACPI_TYPE_INTEGER;
1135
    AcpiGbl_DbMethodInfo.ArgTypes[1] = ACPI_TYPE_INTEGER;
1136
    AcpiGbl_DbMethodInfo.ArgTypes[2] = ACPI_TYPE_INTEGER;
1137
 
1498 serge 1138
    AcpiDbUInt32ToHexString (NumThreads, AcpiGbl_DbMethodInfo.NumThreadsStr);
1139
 
1140
    AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo);
1141
 
1142
    /* Create the threads */
1143
 
1144
    AcpiOsPrintf ("Creating %X threads to execute %X times each\n",
1145
        NumThreads, NumLoops);
1146
 
1147
    for (i = 0; i < (NumThreads); i++)
1148
    {
1149
        Status = AcpiOsExecute (OSL_DEBUGGER_THREAD, AcpiDbMethodThread,
1150
            &AcpiGbl_DbMethodInfo);
1151
        if (ACPI_FAILURE (Status))
1152
        {
1153
            break;
1154
        }
1155
    }
1156
 
1157
    /* Wait for all threads to complete */
1158
 
1159
    (void) AcpiOsWaitSemaphore (MainThreadGate, 1, ACPI_WAIT_FOREVER);
1160
 
1161
    AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);
1162
    AcpiOsPrintf ("All threads (%X) have completed\n", NumThreads);
1163
    AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
1164
 
1165
    /* Cleanup and exit */
1166
 
1167
    (void) AcpiOsDeleteSemaphore (MainThreadGate);
1168
    (void) AcpiOsDeleteSemaphore (ThreadCompleteGate);
1169
    (void) AcpiOsDeleteSemaphore (InfoGate);
1170
 
1171
    AcpiOsFree (AcpiGbl_DbMethodInfo.Threads);
1172
    AcpiGbl_DbMethodInfo.Threads = NULL;
1173
}
1174
 
1175
#endif /* ACPI_DEBUGGER */
1176