OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [acpi/] [parser/] [psparse.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/******************************************************************************
2
 *
3
 * Module Name: psparse - Parser top level AML parse routines
4
 *
5
 *****************************************************************************/
6
 
7
/*
8
 * Copyright (C) 2000 - 2004, R. Byron Moore
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
 
45
/*
46
 * Parse the AML and build an operation tree as most interpreters,
47
 * like Perl, do.  Parsing is done by hand rather than with a YACC
48
 * generated parser to tightly constrain stack and dynamic memory
49
 * usage.  At the same time, parsing is kept flexible and the code
50
 * fairly compact by parsing based on a list of AML opcode
51
 * templates in aml_op_info[]
52
 */
53
 
54
#include <acpi/acpi.h>
55
#include <acpi/acparser.h>
56
#include <acpi/acdispat.h>
57
#include <acpi/amlcode.h>
58
#include <acpi/acnamesp.h>
59
#include <acpi/acinterp.h>
60
 
61
#define _COMPONENT          ACPI_PARSER
62
         ACPI_MODULE_NAME    ("psparse")
63
 
64
 
65
static u32                          acpi_gbl_depth = 0;
66
 
67
 
68
/*******************************************************************************
69
 *
70
 * FUNCTION:    acpi_ps_get_opcode_size
71
 *
72
 * PARAMETERS:  Opcode          - An AML opcode
73
 *
74
 * RETURN:      Size of the opcode, in bytes (1 or 2)
75
 *
76
 * DESCRIPTION: Get the size of the current opcode.
77
 *
78
 ******************************************************************************/
79
 
80
u32
81
acpi_ps_get_opcode_size (
82
        u32                             opcode)
83
{
84
 
85
        /* Extended (2-byte) opcode if > 255 */
86
 
87
        if (opcode > 0x00FF) {
88
                return (2);
89
        }
90
 
91
        /* Otherwise, just a single byte opcode */
92
 
93
        return (1);
94
}
95
 
96
 
97
/*******************************************************************************
98
 *
99
 * FUNCTION:    acpi_ps_peek_opcode
100
 *
101
 * PARAMETERS:  parser_state        - A parser state object
102
 *
103
 * RETURN:      Status
104
 *
105
 * DESCRIPTION: Get next AML opcode (without incrementing AML pointer)
106
 *
107
 ******************************************************************************/
108
 
109
u16
110
acpi_ps_peek_opcode (
111
        struct acpi_parse_state         *parser_state)
112
{
113
        u8                              *aml;
114
        u16                             opcode;
115
 
116
 
117
        aml = parser_state->aml;
118
        opcode = (u16) ACPI_GET8 (aml);
119
 
120
 
121
        if (opcode == AML_EXTOP) {
122
                /* Extended opcode */
123
 
124
                aml++;
125
                opcode = (u16) ((opcode << 8) | ACPI_GET8 (aml));
126
        }
127
 
128
        return (opcode);
129
}
130
 
131
 
132
/*******************************************************************************
133
 *
134
 * FUNCTION:    acpi_ps_complete_this_op
135
 *
136
 * PARAMETERS:  walk_state      - Current State
137
 *              Op              - Op to complete
138
 *
139
 * RETURN:      None.
140
 *
141
 * DESCRIPTION: Perform any cleanup at the completion of an Op.
142
 *
143
 ******************************************************************************/
144
 
145
void
146
acpi_ps_complete_this_op (
147
        struct acpi_walk_state          *walk_state,
148
        union acpi_parse_object         *op)
149
{
150
        union acpi_parse_object         *prev;
151
        union acpi_parse_object         *next;
152
        const struct acpi_opcode_info   *parent_info;
153
        union acpi_parse_object         *replacement_op = NULL;
154
 
155
 
156
        ACPI_FUNCTION_TRACE_PTR ("ps_complete_this_op", op);
157
 
158
 
159
        /* Check for null Op, can happen if AML code is corrupt */
160
 
161
        if (!op) {
162
                return_VOID;
163
        }
164
 
165
        /* Delete this op and the subtree below it if asked to */
166
 
167
        if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) == ACPI_PARSE_DELETE_TREE) &&
168
                (walk_state->op_info->class != AML_CLASS_ARGUMENT)) {
169
                /* Make sure that we only delete this subtree */
170
 
171
                if (op->common.parent) {
172
                        /*
173
                         * Check if we need to replace the operator and its subtree
174
                         * with a return value op (placeholder op)
175
                         */
176
                        parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode);
177
 
178
                        switch (parent_info->class) {
179
                        case AML_CLASS_CONTROL:
180
                                break;
181
 
182
                        case AML_CLASS_CREATE:
183
 
184
                                /*
185
                                 * These opcodes contain term_arg operands. The current
186
                                 * op must be replaced by a placeholder return op
187
                                 */
188
                                replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
189
                                if (!replacement_op) {
190
                                        return_VOID;
191
                                }
192
                                break;
193
 
194
                        case AML_CLASS_NAMED_OBJECT:
195
 
196
                                /*
197
                                 * These opcodes contain term_arg operands. The current
198
                                 * op must be replaced by a placeholder return op
199
                                 */
200
                                if ((op->common.parent->common.aml_opcode == AML_REGION_OP)      ||
201
                                        (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) ||
202
                                        (op->common.parent->common.aml_opcode == AML_BUFFER_OP)      ||
203
                                        (op->common.parent->common.aml_opcode == AML_PACKAGE_OP)     ||
204
                                        (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
205
                                        replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
206
                                        if (!replacement_op) {
207
                                                return_VOID;
208
                                        }
209
                                }
210
 
211
                                if ((op->common.parent->common.aml_opcode == AML_NAME_OP) &&
212
                                        (walk_state->descending_callback != acpi_ds_exec_begin_op)) {
213
                                        if ((op->common.aml_opcode == AML_BUFFER_OP) ||
214
                                                (op->common.aml_opcode == AML_PACKAGE_OP) ||
215
                                                (op->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
216
                                                replacement_op = acpi_ps_alloc_op (op->common.aml_opcode);
217
                                                if (!replacement_op) {
218
                                                        return_VOID;
219
                                                }
220
 
221
                                                replacement_op->named.data = op->named.data;
222
                                                replacement_op->named.length = op->named.length;
223
                                        }
224
                                }
225
                                break;
226
 
227
                        default:
228
                                replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
229
                                if (!replacement_op) {
230
                                        return_VOID;
231
                                }
232
                        }
233
 
234
                        /* We must unlink this op from the parent tree */
235
 
236
                        prev = op->common.parent->common.value.arg;
237
                        if (prev == op) {
238
                                /* This op is the first in the list */
239
 
240
                                if (replacement_op) {
241
                                        replacement_op->common.parent       = op->common.parent;
242
                                        replacement_op->common.value.arg    = NULL;
243
                                        replacement_op->common.node         = op->common.node;
244
                                        op->common.parent->common.value.arg = replacement_op;
245
                                        replacement_op->common.next         = op->common.next;
246
                                }
247
                                else {
248
                                        op->common.parent->common.value.arg    = op->common.next;
249
                                }
250
                        }
251
 
252
                        /* Search the parent list */
253
 
254
                        else while (prev) {
255
                                /* Traverse all siblings in the parent's argument list */
256
 
257
                                next = prev->common.next;
258
                                if (next == op) {
259
                                        if (replacement_op) {
260
                                                replacement_op->common.parent   = op->common.parent;
261
                                                replacement_op->common.value.arg = NULL;
262
                                                replacement_op->common.node     = op->common.node;
263
                                                prev->common.next               = replacement_op;
264
                                                replacement_op->common.next     = op->common.next;
265
                                                next = NULL;
266
                                        }
267
                                        else {
268
                                                prev->common.next = op->common.next;
269
                                                next = NULL;
270
                                        }
271
                                }
272
 
273
                                prev = next;
274
                        }
275
                }
276
 
277
                /* Now we can actually delete the subtree rooted at op */
278
 
279
                acpi_ps_delete_parse_tree (op);
280
 
281
                return_VOID;
282
        }
283
 
284
        return_VOID;
285
}
286
 
287
 
288
/*******************************************************************************
289
 *
290
 * FUNCTION:    acpi_ps_next_parse_state
291
 *
292
 * PARAMETERS:  parser_state        - Current parser state object
293
 *
294
 * RETURN:      Status
295
 *
296
 * DESCRIPTION: Update the parser state based upon the return exception from
297
 *              the parser callback.
298
 *
299
 ******************************************************************************/
300
 
301
acpi_status
302
acpi_ps_next_parse_state (
303
        struct acpi_walk_state          *walk_state,
304
        union acpi_parse_object         *op,
305
        acpi_status                     callback_status)
306
{
307
        struct acpi_parse_state         *parser_state = &walk_state->parser_state;
308
        acpi_status                     status = AE_CTRL_PENDING;
309
 
310
 
311
        ACPI_FUNCTION_TRACE_PTR ("ps_next_parse_state", op);
312
 
313
 
314
        switch (callback_status) {
315
        case AE_CTRL_TERMINATE:
316
 
317
                /*
318
                 * A control method was terminated via a RETURN statement.
319
                 * The walk of this method is complete.
320
                 */
321
                parser_state->aml = parser_state->aml_end;
322
                status = AE_CTRL_TERMINATE;
323
                break;
324
 
325
 
326
        case AE_CTRL_BREAK:
327
 
328
                parser_state->aml = walk_state->aml_last_while;
329
                walk_state->control_state->common.value = FALSE;
330
                status = AE_CTRL_BREAK;
331
                break;
332
 
333
        case AE_CTRL_CONTINUE:
334
 
335
 
336
                parser_state->aml = walk_state->aml_last_while;
337
                status = AE_CTRL_CONTINUE;
338
                break;
339
 
340
        case AE_CTRL_PENDING:
341
 
342
                parser_state->aml = walk_state->aml_last_while;
343
                break;
344
 
345
#if 0
346
        case AE_CTRL_SKIP:
347
 
348
                parser_state->aml = parser_state->scope->parse_scope.pkg_end;
349
                status = AE_OK;
350
                break;
351
#endif
352
 
353
        case AE_CTRL_TRUE:
354
 
355
                /*
356
                 * Predicate of an IF was true, and we are at the matching ELSE.
357
                 * Just close out this package
358
                 */
359
                parser_state->aml = acpi_ps_get_next_package_end (parser_state);
360
                break;
361
 
362
 
363
        case AE_CTRL_FALSE:
364
 
365
                /*
366
                 * Either an IF/WHILE Predicate was false or we encountered a BREAK
367
                 * opcode.  In both cases, we do not execute the rest of the
368
                 * package;  We simply close out the parent (finishing the walk of
369
                 * this branch of the tree) and continue execution at the parent
370
                 * level.
371
                 */
372
                parser_state->aml = parser_state->scope->parse_scope.pkg_end;
373
 
374
                /* In the case of a BREAK, just force a predicate (if any) to FALSE */
375
 
376
                walk_state->control_state->common.value = FALSE;
377
                status = AE_CTRL_END;
378
                break;
379
 
380
 
381
        case AE_CTRL_TRANSFER:
382
 
383
                /*
384
                 * A method call (invocation) -- transfer control
385
                 */
386
                status = AE_CTRL_TRANSFER;
387
                walk_state->prev_op = op;
388
                walk_state->method_call_op = op;
389
                walk_state->method_call_node = (op->common.value.arg)->common.node;
390
 
391
                /* Will return value (if any) be used by the caller? */
392
 
393
                walk_state->return_used = acpi_ds_is_result_used (op, walk_state);
394
                break;
395
 
396
 
397
        default:
398
                status = callback_status;
399
                if ((callback_status & AE_CODE_MASK) == AE_CODE_CONTROL) {
400
                        status = AE_OK;
401
                }
402
                break;
403
        }
404
 
405
        return_ACPI_STATUS (status);
406
}
407
 
408
 
409
/*******************************************************************************
410
 *
411
 * FUNCTION:    acpi_ps_parse_loop
412
 *
413
 * PARAMETERS:  parser_state        - Current parser state object
414
 *
415
 * RETURN:      Status
416
 *
417
 * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
418
 *              a tree of ops.
419
 *
420
 ******************************************************************************/
421
 
422
acpi_status
423
acpi_ps_parse_loop (
424
        struct acpi_walk_state          *walk_state)
425
{
426
        acpi_status                     status = AE_OK;
427
        union acpi_parse_object         *op = NULL;     /* current op */
428
        union acpi_parse_object         *arg = NULL;
429
        union acpi_parse_object         *pre_op = NULL;
430
        struct acpi_parse_state         *parser_state;
431
        u8                              *aml_op_start = NULL;
432
 
433
 
434
        ACPI_FUNCTION_TRACE_PTR ("ps_parse_loop", walk_state);
435
 
436
        if (walk_state->descending_callback == NULL) {
437
                return_ACPI_STATUS (AE_BAD_PARAMETER);
438
        }
439
 
440
        parser_state = &walk_state->parser_state;
441
        walk_state->arg_types = 0;
442
 
443
#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
444
        if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) {
445
                /* We are restarting a preempted control method */
446
 
447
                if (acpi_ps_has_completed_scope (parser_state)) {
448
                        /*
449
                         * We must check if a predicate to an IF or WHILE statement
450
                         * was just completed
451
                         */
452
                        if ((parser_state->scope->parse_scope.op) &&
453
                           ((parser_state->scope->parse_scope.op->common.aml_opcode == AML_IF_OP) ||
454
                                (parser_state->scope->parse_scope.op->common.aml_opcode == AML_WHILE_OP)) &&
455
                                (walk_state->control_state) &&
456
                                (walk_state->control_state->common.state ==
457
                                        ACPI_CONTROL_PREDICATE_EXECUTING)) {
458
                                /*
459
                                 * A predicate was just completed, get the value of the
460
                                 * predicate and branch based on that value
461
                                 */
462
                                walk_state->op = NULL;
463
                                status = acpi_ds_get_predicate_value (walk_state, ACPI_TO_POINTER (TRUE));
464
                                if (ACPI_FAILURE (status) &&
465
                                        ((status & AE_CODE_MASK) != AE_CODE_CONTROL)) {
466
                                        if (status == AE_AML_NO_RETURN_VALUE) {
467
                                                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
468
                                                        "Invoked method did not return a value, %s\n",
469
                                                        acpi_format_exception (status)));
470
 
471
                                        }
472
                                        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "get_predicate Failed, %s\n",
473
                                                acpi_format_exception (status)));
474
                                        return_ACPI_STATUS (status);
475
                                }
476
 
477
                                status = acpi_ps_next_parse_state (walk_state, op, status);
478
                        }
479
 
480
                        acpi_ps_pop_scope (parser_state, &op,
481
                                &walk_state->arg_types, &walk_state->arg_count);
482
                        ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op));
483
                }
484
                else if (walk_state->prev_op) {
485
                        /* We were in the middle of an op */
486
 
487
                        op = walk_state->prev_op;
488
                        walk_state->arg_types = walk_state->prev_arg_types;
489
                }
490
        }
491
#endif
492
 
493
        /*
494
         * Iterative parsing loop, while there is more aml to process:
495
         */
496
        while ((parser_state->aml < parser_state->aml_end) || (op)) {
497
                aml_op_start = parser_state->aml;
498
                if (!op) {
499
                        /* Get the next opcode from the AML stream */
500
 
501
                        walk_state->aml_offset = (u32) ACPI_PTR_DIFF (parser_state->aml,
502
                                           parser_state->aml_start);
503
                        walk_state->opcode   = acpi_ps_peek_opcode (parser_state);
504
 
505
                        /*
506
                         * First cut to determine what we have found:
507
                         * 1) A valid AML opcode
508
                         * 2) A name string
509
                         * 3) An unknown/invalid opcode
510
                         */
511
                        walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode);
512
                        switch (walk_state->op_info->class) {
513
                        case AML_CLASS_ASCII:
514
                        case AML_CLASS_PREFIX:
515
                                /*
516
                                 * Starts with a valid prefix or ASCII char, this is a name
517
                                 * string.  Convert the bare name string to a namepath.
518
                                 */
519
                                walk_state->opcode = AML_INT_NAMEPATH_OP;
520
                                walk_state->arg_types = ARGP_NAMESTRING;
521
                                break;
522
 
523
                        case AML_CLASS_UNKNOWN:
524
 
525
                                /* The opcode is unrecognized.  Just skip unknown opcodes */
526
 
527
                                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
528
                                        "Found unknown opcode %X at AML address %p offset %X, ignoring\n",
529
                                        walk_state->opcode, parser_state->aml, walk_state->aml_offset));
530
 
531
                                ACPI_DUMP_BUFFER (parser_state->aml, 128);
532
 
533
                                /* Assume one-byte bad opcode */
534
 
535
                                parser_state->aml++;
536
                                continue;
537
 
538
                        default:
539
 
540
                                /* Found opcode info, this is a normal opcode */
541
 
542
                                parser_state->aml += acpi_ps_get_opcode_size (walk_state->opcode);
543
                                walk_state->arg_types = walk_state->op_info->parse_args;
544
                                break;
545
                        }
546
 
547
                        /* Create Op structure and append to parent's argument list */
548
 
549
                        if (walk_state->op_info->flags & AML_NAMED) {
550
                                /* Allocate a new pre_op if necessary */
551
 
552
                                if (!pre_op) {
553
                                        pre_op = acpi_ps_alloc_op (walk_state->opcode);
554
                                        if (!pre_op) {
555
                                                return_ACPI_STATUS (AE_NO_MEMORY);
556
                                        }
557
                                }
558
 
559
                                pre_op->common.value.arg = NULL;
560
                                pre_op->common.aml_opcode = walk_state->opcode;
561
 
562
                                /*
563
                                 * Get and append arguments until we find the node that contains
564
                                 * the name (the type ARGP_NAME).
565
                                 */
566
                                while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) &&
567
                                          (GET_CURRENT_ARG_TYPE (walk_state->arg_types) != ARGP_NAME)) {
568
                                        status = acpi_ps_get_next_arg (walk_state, parser_state,
569
                                                         GET_CURRENT_ARG_TYPE (walk_state->arg_types), &arg);
570
                                        if (ACPI_FAILURE (status)) {
571
                                                goto close_this_op;
572
                                        }
573
 
574
                                        acpi_ps_append_arg (pre_op, arg);
575
                                        INCREMENT_ARG_LIST (walk_state->arg_types);
576
                                }
577
 
578
                                /* Make sure that we found a NAME and didn't run out of arguments */
579
 
580
                                if (!GET_CURRENT_ARG_TYPE (walk_state->arg_types)) {
581
                                        return_ACPI_STATUS (AE_AML_NO_OPERAND);
582
                                }
583
 
584
                                /* We know that this arg is a name, move to next arg */
585
 
586
                                INCREMENT_ARG_LIST (walk_state->arg_types);
587
 
588
                                /*
589
                                 * Find the object.  This will either insert the object into
590
                                 * the namespace or simply look it up
591
                                 */
592
                                walk_state->op = NULL;
593
 
594
                                status = walk_state->descending_callback (walk_state, &op);
595
                                if (ACPI_FAILURE (status)) {
596
                                        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "During name lookup/catalog, %s\n",
597
                                                        acpi_format_exception (status)));
598
                                        goto close_this_op;
599
                                }
600
 
601
                                if (op == NULL) {
602
                                        continue;
603
                                }
604
 
605
                                status = acpi_ps_next_parse_state (walk_state, op, status);
606
                                if (status == AE_CTRL_PENDING) {
607
                                        status = AE_OK;
608
                                        goto close_this_op;
609
                                }
610
 
611
                                if (ACPI_FAILURE (status)) {
612
                                        goto close_this_op;
613
                                }
614
 
615
                                acpi_ps_append_arg (op, pre_op->common.value.arg);
616
                                acpi_gbl_depth++;
617
 
618
                                if (op->common.aml_opcode == AML_REGION_OP) {
619
                                        /*
620
                                         * Defer final parsing of an operation_region body,
621
                                         * because we don't have enough info in the first pass
622
                                         * to parse it correctly (i.e., there may be method
623
                                         * calls within the term_arg elements of the body.)
624
                                         *
625
                                         * However, we must continue parsing because
626
                                         * the opregion is not a standalone package --
627
                                         * we don't know where the end is at this point.
628
                                         *
629
                                         * (Length is unknown until parse of the body complete)
630
                                         */
631
                                        op->named.data    = aml_op_start;
632
                                        op->named.length  = 0;
633
                                }
634
                        }
635
                        else {
636
                                /* Not a named opcode, just allocate Op and append to parent */
637
 
638
                                walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode);
639
                                op = acpi_ps_alloc_op (walk_state->opcode);
640
                                if (!op) {
641
                                        return_ACPI_STATUS (AE_NO_MEMORY);
642
                                }
643
 
644
                                if (walk_state->op_info->flags & AML_CREATE) {
645
                                        /*
646
                                         * Backup to beginning of create_xXXfield declaration
647
                                         * body_length is unknown until we parse the body
648
                                         */
649
                                        op->named.data    = aml_op_start;
650
                                        op->named.length  = 0;
651
                                }
652
 
653
                                acpi_ps_append_arg (acpi_ps_get_parent_scope (parser_state), op);
654
 
655
                                if ((walk_state->descending_callback != NULL)) {
656
                                        /*
657
                                         * Find the object.  This will either insert the object into
658
                                         * the namespace or simply look it up
659
                                         */
660
                                        walk_state->op = op;
661
 
662
                                        status = walk_state->descending_callback (walk_state, &op);
663
                                        status = acpi_ps_next_parse_state (walk_state, op, status);
664
                                        if (status == AE_CTRL_PENDING) {
665
                                                status = AE_OK;
666
                                                goto close_this_op;
667
                                        }
668
 
669
                                        if (ACPI_FAILURE (status)) {
670
                                                goto close_this_op;
671
                                        }
672
                                }
673
                        }
674
 
675
                        op->common.aml_offset = walk_state->aml_offset;
676
 
677
                        if (walk_state->op_info) {
678
                                ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
679
                                        "Opcode %4.4X [%s] Op %p Aml %p aml_offset %5.5X\n",
680
                                         (u32) op->common.aml_opcode, walk_state->op_info->name,
681
                                         op, parser_state->aml, op->common.aml_offset));
682
                        }
683
                }
684
 
685
 
686
                /* Start arg_count at zero because we don't know if there are any args yet */
687
 
688
                walk_state->arg_count = 0;
689
 
690
                if (walk_state->arg_types) /* Are there any arguments that must be processed? */ {
691
                        /* Get arguments */
692
 
693
                        switch (op->common.aml_opcode) {
694
                        case AML_BYTE_OP:       /* AML_BYTEDATA_ARG */
695
                        case AML_WORD_OP:       /* AML_WORDDATA_ARG */
696
                        case AML_DWORD_OP:      /* AML_DWORDATA_ARG */
697
                        case AML_QWORD_OP:      /* AML_QWORDATA_ARG */
698
                        case AML_STRING_OP:     /* AML_ASCIICHARLIST_ARG */
699
 
700
                                /* Fill in constant or string argument directly */
701
 
702
                                acpi_ps_get_next_simple_arg (parser_state,
703
                                        GET_CURRENT_ARG_TYPE (walk_state->arg_types), op);
704
                                break;
705
 
706
                        case AML_INT_NAMEPATH_OP:   /* AML_NAMESTRING_ARG */
707
 
708
                                status = acpi_ps_get_next_namepath (walk_state, parser_state, op, 1);
709
                                if (ACPI_FAILURE (status)) {
710
                                        goto close_this_op;
711
                                }
712
 
713
                                walk_state->arg_types = 0;
714
                                break;
715
 
716
                        default:
717
 
718
                                /* Op is not a constant or string, append each argument to the Op */
719
 
720
                                while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) &&
721
                                                !walk_state->arg_count) {
722
                                        walk_state->aml_offset = (u32) ACPI_PTR_DIFF (parser_state->aml,
723
                                                           parser_state->aml_start);
724
                                        status = acpi_ps_get_next_arg (walk_state, parser_state,
725
                                                         GET_CURRENT_ARG_TYPE (walk_state->arg_types), &arg);
726
                                        if (ACPI_FAILURE (status)) {
727
                                                goto close_this_op;
728
                                        }
729
 
730
                                        if (arg) {
731
                                                arg->common.aml_offset = walk_state->aml_offset;
732
                                                acpi_ps_append_arg (op, arg);
733
                                        }
734
                                        INCREMENT_ARG_LIST (walk_state->arg_types);
735
                                }
736
 
737
                                /* Special processing for certain opcodes */
738
 
739
                                switch (op->common.aml_opcode) {
740
                                case AML_METHOD_OP:
741
 
742
                                        /*
743
                                         * Skip parsing of control method
744
                                         * because we don't have enough info in the first pass
745
                                         * to parse it correctly.
746
                                         *
747
                                         * Save the length and address of the body
748
                                         */
749
                                        op->named.data   = parser_state->aml;
750
                                        op->named.length = (u32) (parser_state->pkg_end - parser_state->aml);
751
 
752
                                        /* Skip body of method */
753
 
754
                                        parser_state->aml   = parser_state->pkg_end;
755
                                        walk_state->arg_count = 0;
756
                                        break;
757
 
758
                                case AML_BUFFER_OP:
759
                                case AML_PACKAGE_OP:
760
                                case AML_VAR_PACKAGE_OP:
761
 
762
                                        if ((op->common.parent) &&
763
                                                (op->common.parent->common.aml_opcode == AML_NAME_OP) &&
764
                                                (walk_state->descending_callback != acpi_ds_exec_begin_op)) {
765
                                                /*
766
                                                 * Skip parsing of Buffers and Packages
767
                                                 * because we don't have enough info in the first pass
768
                                                 * to parse them correctly.
769
                                                 */
770
                                                op->named.data   = aml_op_start;
771
                                                op->named.length = (u32) (parser_state->pkg_end - aml_op_start);
772
 
773
                                                /* Skip body */
774
 
775
                                                parser_state->aml   = parser_state->pkg_end;
776
                                                walk_state->arg_count = 0;
777
                                        }
778
                                        break;
779
 
780
                                case AML_WHILE_OP:
781
 
782
                                        if (walk_state->control_state) {
783
                                                walk_state->control_state->control.package_end = parser_state->pkg_end;
784
                                        }
785
                                        break;
786
 
787
                                default:
788
 
789
                                        /* No action for all other opcodes */
790
                                        break;
791
                                }
792
                                break;
793
                        }
794
                }
795
 
796
                /* Check for arguments that need to be processed */
797
 
798
                if (walk_state->arg_count) {
799
                        /* There are arguments (complex ones), push Op and prepare for argument */
800
 
801
                        status = acpi_ps_push_scope (parser_state, op,
802
                                         walk_state->arg_types, walk_state->arg_count);
803
                        if (ACPI_FAILURE (status)) {
804
                                return_ACPI_STATUS (status);
805
                        }
806
                        op = NULL;
807
                        continue;
808
                }
809
 
810
                /* All arguments have been processed -- Op is complete, prepare for next */
811
 
812
                walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
813
                if (walk_state->op_info->flags & AML_NAMED) {
814
                        if (acpi_gbl_depth) {
815
                                acpi_gbl_depth--;
816
                        }
817
 
818
                        if (op->common.aml_opcode == AML_REGION_OP) {
819
                                /*
820
                                 * Skip parsing of control method or opregion body,
821
                                 * because we don't have enough info in the first pass
822
                                 * to parse them correctly.
823
                                 *
824
                                 * Completed parsing an op_region declaration, we now
825
                                 * know the length.
826
                                 */
827
                                op->named.length = (u32) (parser_state->aml - op->named.data);
828
                        }
829
                }
830
 
831
                if (walk_state->op_info->flags & AML_CREATE) {
832
                        /*
833
                         * Backup to beginning of create_xXXfield declaration (1 for
834
                         * Opcode)
835
                         *
836
                         * body_length is unknown until we parse the body
837
                         */
838
                        op->named.length = (u32) (parser_state->aml - op->named.data);
839
                }
840
 
841
                /* This op complete, notify the dispatcher */
842
 
843
                if (walk_state->ascending_callback != NULL) {
844
                        walk_state->op    = op;
845
                        walk_state->opcode = op->common.aml_opcode;
846
 
847
                        status = walk_state->ascending_callback (walk_state);
848
                        status = acpi_ps_next_parse_state (walk_state, op, status);
849
                        if (status == AE_CTRL_PENDING) {
850
                                status = AE_OK;
851
                                goto close_this_op;
852
                        }
853
                }
854
 
855
 
856
close_this_op:
857
                /*
858
                 * Finished one argument of the containing scope
859
                 */
860
                parser_state->scope->parse_scope.arg_count--;
861
 
862
                /* Close this Op (will result in parse subtree deletion) */
863
 
864
                acpi_ps_complete_this_op (walk_state, op);
865
                op = NULL;
866
                if (pre_op) {
867
                        acpi_ps_free_op (pre_op);
868
                        pre_op = NULL;
869
                }
870
 
871
                switch (status) {
872
                case AE_OK:
873
                        break;
874
 
875
 
876
                case AE_CTRL_TRANSFER:
877
 
878
                        /*
879
                         * We are about to transfer to a called method.
880
                         */
881
                        walk_state->prev_op = op;
882
                        walk_state->prev_arg_types = walk_state->arg_types;
883
                        return_ACPI_STATUS (status);
884
 
885
 
886
                case AE_CTRL_END:
887
 
888
                        acpi_ps_pop_scope (parser_state, &op,
889
                                &walk_state->arg_types, &walk_state->arg_count);
890
 
891
                        if (op) {
892
                                walk_state->op    = op;
893
                                walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
894
                                walk_state->opcode = op->common.aml_opcode;
895
 
896
                                status = walk_state->ascending_callback (walk_state);
897
                                status = acpi_ps_next_parse_state (walk_state, op, status);
898
 
899
                                acpi_ps_complete_this_op (walk_state, op);
900
                                op = NULL;
901
                        }
902
                        status = AE_OK;
903
                        break;
904
 
905
 
906
                case AE_CTRL_BREAK:
907
                case AE_CTRL_CONTINUE:
908
 
909
                        /* Pop off scopes until we find the While */
910
 
911
                        while (!op || (op->common.aml_opcode != AML_WHILE_OP)) {
912
                                acpi_ps_pop_scope (parser_state, &op,
913
                                        &walk_state->arg_types, &walk_state->arg_count);
914
                        }
915
 
916
                        /* Close this iteration of the While loop */
917
 
918
                        walk_state->op    = op;
919
                        walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
920
                        walk_state->opcode = op->common.aml_opcode;
921
 
922
                        status = walk_state->ascending_callback (walk_state);
923
                        status = acpi_ps_next_parse_state (walk_state, op, status);
924
 
925
                        acpi_ps_complete_this_op (walk_state, op);
926
                        op = NULL;
927
 
928
                        status = AE_OK;
929
                        break;
930
 
931
 
932
                case AE_CTRL_TERMINATE:
933
 
934
                        status = AE_OK;
935
 
936
                        /* Clean up */
937
                        do {
938
                                if (op) {
939
                                        acpi_ps_complete_this_op (walk_state, op);
940
                                }
941
                                acpi_ps_pop_scope (parser_state, &op,
942
                                        &walk_state->arg_types, &walk_state->arg_count);
943
 
944
                        } while (op);
945
 
946
                        return_ACPI_STATUS (status);
947
 
948
 
949
                default:  /* All other non-AE_OK status */
950
 
951
                        do {
952
                                if (op) {
953
                                        acpi_ps_complete_this_op (walk_state, op);
954
                                }
955
                                acpi_ps_pop_scope (parser_state, &op,
956
                                        &walk_state->arg_types, &walk_state->arg_count);
957
 
958
                        } while (op);
959
 
960
 
961
                        /*
962
                         * TBD: Cleanup parse ops on error
963
                         */
964
#if 0
965
                        if (op == NULL) {
966
                                acpi_ps_pop_scope (parser_state, &op,
967
                                        &walk_state->arg_types, &walk_state->arg_count);
968
                        }
969
#endif
970
                        walk_state->prev_op = op;
971
                        walk_state->prev_arg_types = walk_state->arg_types;
972
                        return_ACPI_STATUS (status);
973
                }
974
 
975
                /* This scope complete? */
976
 
977
                if (acpi_ps_has_completed_scope (parser_state)) {
978
                        acpi_ps_pop_scope (parser_state, &op,
979
                                &walk_state->arg_types, &walk_state->arg_count);
980
                        ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op));
981
                }
982
                else {
983
                        op = NULL;
984
                }
985
 
986
        } /* while parser_state->Aml */
987
 
988
 
989
        /*
990
         * Complete the last Op (if not completed), and clear the scope stack.
991
         * It is easily possible to end an AML "package" with an unbounded number
992
         * of open scopes (such as when several ASL blocks are closed with
993
         * sequential closing braces).  We want to terminate each one cleanly.
994
         */
995
        ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", op));
996
        do {
997
                if (op) {
998
                        if (walk_state->ascending_callback != NULL) {
999
                                walk_state->op    = op;
1000
                                walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
1001
                                walk_state->opcode = op->common.aml_opcode;
1002
 
1003
                                status = walk_state->ascending_callback (walk_state);
1004
                                status = acpi_ps_next_parse_state (walk_state, op, status);
1005
                                if (status == AE_CTRL_PENDING) {
1006
                                        status = AE_OK;
1007
                                        goto close_this_op;
1008
                                }
1009
 
1010
                                if (status == AE_CTRL_TERMINATE) {
1011
                                        status = AE_OK;
1012
 
1013
                                        /* Clean up */
1014
                                        do {
1015
                                                if (op) {
1016
                                                        acpi_ps_complete_this_op (walk_state, op);
1017
                                                }
1018
 
1019
                                                acpi_ps_pop_scope (parser_state, &op,
1020
                                                        &walk_state->arg_types, &walk_state->arg_count);
1021
 
1022
                                        } while (op);
1023
 
1024
                                        return_ACPI_STATUS (status);
1025
                                }
1026
 
1027
                                else if (ACPI_FAILURE (status)) {
1028
                                        acpi_ps_complete_this_op (walk_state, op);
1029
                                        return_ACPI_STATUS (status);
1030
                                }
1031
                        }
1032
 
1033
                        acpi_ps_complete_this_op (walk_state, op);
1034
                }
1035
 
1036
                acpi_ps_pop_scope (parser_state, &op, &walk_state->arg_types,
1037
                        &walk_state->arg_count);
1038
 
1039
        } while (op);
1040
 
1041
        return_ACPI_STATUS (status);
1042
}
1043
 
1044
 
1045
/*******************************************************************************
1046
 *
1047
 * FUNCTION:    acpi_ps_parse_aml
1048
 *
1049
 * PARAMETERS:  start_scope     - The starting point of the parse.  Becomes the
1050
 *                                root of the parsed op tree.
1051
 *              Aml             - Pointer to the raw AML code to parse
1052
 *              aml_size        - Length of the AML to parse
1053
 *
1054
 *
1055
 * RETURN:      Status
1056
 *
1057
 * DESCRIPTION: Parse raw AML and return a tree of ops
1058
 *
1059
 ******************************************************************************/
1060
 
1061
acpi_status
1062
acpi_ps_parse_aml (
1063
        struct acpi_walk_state          *walk_state)
1064
{
1065
        acpi_status                     status;
1066
        acpi_status                     terminate_status;
1067
        struct acpi_thread_state        *thread;
1068
        struct acpi_thread_state        *prev_walk_list = acpi_gbl_current_walk_list;
1069
        struct acpi_walk_state          *previous_walk_state;
1070
 
1071
 
1072
        ACPI_FUNCTION_TRACE ("ps_parse_aml");
1073
 
1074
        ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Entered with walk_state=%p Aml=%p size=%X\n",
1075
                walk_state, walk_state->parser_state.aml, walk_state->parser_state.aml_size));
1076
 
1077
 
1078
        /* Create and initialize a new thread state */
1079
 
1080
        thread = acpi_ut_create_thread_state ();
1081
        if (!thread) {
1082
                return_ACPI_STATUS (AE_NO_MEMORY);
1083
        }
1084
 
1085
        walk_state->thread = thread;
1086
        acpi_ds_push_walk_state (walk_state, thread);
1087
 
1088
        /*
1089
         * This global allows the AML debugger to get a handle to the currently
1090
         * executing control method.
1091
         */
1092
        acpi_gbl_current_walk_list = thread;
1093
 
1094
        /*
1095
         * Execute the walk loop as long as there is a valid Walk State.  This
1096
         * handles nested control method invocations without recursion.
1097
         */
1098
        ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "State=%p\n", walk_state));
1099
 
1100
        status = AE_OK;
1101
        while (walk_state) {
1102
                if (ACPI_SUCCESS (status)) {
1103
                        /*
1104
                         * The parse_loop executes AML until the method terminates
1105
                         * or calls another method.
1106
                         */
1107
                        status = acpi_ps_parse_loop (walk_state);
1108
                }
1109
 
1110
                ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
1111
                        "Completed one call to walk loop, %s State=%p\n",
1112
                        acpi_format_exception (status), walk_state));
1113
 
1114
                if (status == AE_CTRL_TRANSFER) {
1115
                        /*
1116
                         * A method call was detected.
1117
                         * Transfer control to the called control method
1118
                         */
1119
                        status = acpi_ds_call_control_method (thread, walk_state, NULL);
1120
 
1121
                        /*
1122
                         * If the transfer to the new method method call worked, a new walk
1123
                         * state was created -- get it
1124
                         */
1125
                        walk_state = acpi_ds_get_current_walk_state (thread);
1126
                        continue;
1127
                }
1128
                else if (status == AE_CTRL_TERMINATE) {
1129
                        status = AE_OK;
1130
                }
1131
                else if (status != AE_OK) {
1132
                        ACPI_REPORT_METHOD_ERROR ("Method execution failed",
1133
                                walk_state->method_node, NULL, status);
1134
 
1135
                        /* Check for possible multi-thread reentrancy problem */
1136
 
1137
                        if ((status == AE_ALREADY_EXISTS) &&
1138
                                (!walk_state->method_desc->method.semaphore)) {
1139
                                /*
1140
                                 * This method is marked not_serialized, but it tried to create a named
1141
                                 * object, causing the second thread entrance to fail.  We will workaround
1142
                                 * this by marking the method permanently as Serialized.
1143
                                 */
1144
                                walk_state->method_desc->method.method_flags |= AML_METHOD_SERIALIZED;
1145
                                walk_state->method_desc->method.concurrency = 1;
1146
                        }
1147
                }
1148
 
1149
                if (walk_state->method_desc) {
1150
                        /* Decrement the thread count on the method parse tree */
1151
 
1152
                        if (walk_state->method_desc->method.thread_count) {
1153
                                walk_state->method_desc->method.thread_count--;
1154
                        }
1155
                }
1156
 
1157
                /* We are done with this walk, move on to the parent if any */
1158
 
1159
                walk_state = acpi_ds_pop_walk_state (thread);
1160
 
1161
                /* Reset the current scope to the beginning of scope stack */
1162
 
1163
                acpi_ds_scope_stack_clear (walk_state);
1164
 
1165
                /*
1166
                 * If we just returned from the execution of a control method,
1167
                 * there's lots of cleanup to do
1168
                 */
1169
                if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) {
1170
                        terminate_status = acpi_ds_terminate_control_method (walk_state);
1171
                        if (ACPI_FAILURE (terminate_status)) {
1172
                                ACPI_REPORT_ERROR ((
1173
                                        "Could not terminate control method properly\n"));
1174
 
1175
                                /* Ignore error and continue */
1176
                        }
1177
                }
1178
 
1179
                /* Delete this walk state and all linked control states */
1180
 
1181
                acpi_ps_cleanup_scope (&walk_state->parser_state);
1182
 
1183
                previous_walk_state = walk_state;
1184
 
1185
                ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "return_value=%p, State=%p\n",
1186
                        walk_state->return_desc, walk_state));
1187
 
1188
                /* Check if we have restarted a preempted walk */
1189
 
1190
                walk_state = acpi_ds_get_current_walk_state (thread);
1191
                if (walk_state) {
1192
                        if (ACPI_SUCCESS (status)) {
1193
                                /*
1194
                                 * There is another walk state, restart it.
1195
                                 * If the method return value is not used by the parent,
1196
                                 * The object is deleted
1197
                                 */
1198
                                status = acpi_ds_restart_control_method (walk_state,
1199
                                                 previous_walk_state->return_desc);
1200
                                if (ACPI_SUCCESS (status)) {
1201
                                        walk_state->walk_type |= ACPI_WALK_METHOD_RESTART;
1202
                                }
1203
                        }
1204
                        else {
1205
                                /* On error, delete any return object */
1206
 
1207
                                acpi_ut_remove_reference (previous_walk_state->return_desc);
1208
                        }
1209
                }
1210
 
1211
                /*
1212
                 * Just completed a 1st-level method, save the final internal return
1213
                 * value (if any)
1214
                 */
1215
                else if (previous_walk_state->caller_return_desc) {
1216
                        *(previous_walk_state->caller_return_desc) = previous_walk_state->return_desc; /* NULL if no return value */
1217
                }
1218
                else if (previous_walk_state->return_desc) {
1219
                        /* Caller doesn't want it, must delete it */
1220
 
1221
                        acpi_ut_remove_reference (previous_walk_state->return_desc);
1222
                }
1223
 
1224
                acpi_ds_delete_walk_state (previous_walk_state);
1225
        }
1226
 
1227
        /* Normal exit */
1228
 
1229
        acpi_ex_release_all_mutexes (thread);
1230
        acpi_ut_delete_generic_state (ACPI_CAST_PTR (union acpi_generic_state, thread));
1231
        acpi_gbl_current_walk_list = prev_walk_list;
1232
        return_ACPI_STATUS (status);
1233
}
1234
 
1235
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.