asloperands.c revision 306536
1/******************************************************************************
2 *
3 * Module Name: asloperands - AML operand processing
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2016, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <contrib/dev/acpica/compiler/aslcompiler.h>
45#include "aslcompiler.y.h"
46#include <contrib/dev/acpica/include/amlcode.h>
47
48#define _COMPONENT          ACPI_COMPILER
49        ACPI_MODULE_NAME    ("asloperands")
50
51/* Local prototypes */
52
53static void
54OpnDoField (
55    ACPI_PARSE_OBJECT       *Op);
56
57static void
58OpnDoBankField (
59    ACPI_PARSE_OBJECT       *Op);
60
61static void
62OpnDoBuffer (
63    ACPI_PARSE_OBJECT       *Op);
64
65static void
66OpnDoDefinitionBlock (
67    ACPI_PARSE_OBJECT       *Op);
68
69static void
70OpnDoFieldCommon (
71    ACPI_PARSE_OBJECT       *FieldOp,
72    ACPI_PARSE_OBJECT       *Op);
73
74static void
75OpnDoIndexField (
76    ACPI_PARSE_OBJECT       *Op);
77
78static void
79OpnDoLoadTable (
80    ACPI_PARSE_OBJECT       *Op);
81
82static void
83OpnDoMethod (
84    ACPI_PARSE_OBJECT       *Op);
85
86static void
87OpnDoMutex (
88    ACPI_PARSE_OBJECT       *Op);
89
90static void
91OpnDoRegion (
92    ACPI_PARSE_OBJECT       *Op);
93
94static void
95OpnAttachNameToNode (
96    ACPI_PARSE_OBJECT       *Op);
97
98
99/*******************************************************************************
100 *
101 * FUNCTION:    OpnDoMutex
102 *
103 * PARAMETERS:  Op        - The parent parse node
104 *
105 * RETURN:      None
106 *
107 * DESCRIPTION: Construct the operands for the MUTEX ASL keyword.
108 *
109 ******************************************************************************/
110
111static void
112OpnDoMutex (
113    ACPI_PARSE_OBJECT       *Op)
114{
115    ACPI_PARSE_OBJECT       *Next;
116
117
118    Next = Op->Asl.Child;
119    Next = Next->Asl.Next;
120
121    if (Next->Asl.Value.Integer > 15)
122    {
123        AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
124    }
125    return;
126}
127
128
129/*******************************************************************************
130 *
131 * FUNCTION:    OpnDoMethod
132 *
133 * PARAMETERS:  Op        - The parent parse node
134 *
135 * RETURN:      None
136 *
137 * DESCRIPTION: Construct the operands for the METHOD ASL keyword.
138 *
139 ******************************************************************************/
140
141static void
142OpnDoMethod (
143    ACPI_PARSE_OBJECT       *Op)
144{
145    ACPI_PARSE_OBJECT       *Next;
146
147    /* Optional arguments for this opcode with defaults */
148
149    UINT8                   NumArgs = 0;
150    UINT8                   Serialized = 0;
151    UINT8                   Concurrency = 0;
152    UINT8                   MethodFlags;
153
154
155    /* Opcode and package length first */
156    /* Method name */
157
158    Next = Op->Asl.Child;
159
160    /* Num args */
161
162    Next = Next->Asl.Next;
163    if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
164    {
165        NumArgs = (UINT8) Next->Asl.Value.Integer;
166        Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
167    }
168
169    /* Serialized Flag */
170
171    Next = Next->Asl.Next;
172    if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
173    {
174        Serialized = (UINT8) Next->Asl.Value.Integer;
175        Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
176    }
177
178    /* Concurrency value (valid values are 0-15) */
179
180    Next = Next->Asl.Next;
181    if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
182    {
183        /* This is a ByteConstExpr, so eval the constant now */
184
185        OpcAmlConstantWalk (Next, 0, NULL);
186
187        if (Next->Asl.Value.Integer > 15)
188        {
189            AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
190        }
191
192        Concurrency = (UINT8) Next->Asl.Value.Integer;
193    }
194
195    /* Put the bits in their proper places */
196
197    MethodFlags = (UINT8)
198        ((NumArgs & 0x7) |
199        ((Serialized & 0x1) << 3) |
200        ((Concurrency & 0xF) << 4));
201
202    /* Use the last node for the combined flags byte */
203
204    Next->Asl.Value.Integer = MethodFlags;
205    Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
206    Next->Asl.AmlLength = 1;
207    Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
208
209    /* Save the arg count in the first node */
210
211    Op->Asl.Extra = NumArgs;
212}
213
214
215/*******************************************************************************
216 *
217 * FUNCTION:    OpnDoFieldCommon
218 *
219 * PARAMETERS:  FieldOp       - Node for an ASL field
220 *              Op            - The parent parse node
221 *
222 * RETURN:      None
223 *
224 * DESCRIPTION: Construct the AML operands for the various field keywords,
225 *              FIELD, BANKFIELD, INDEXFIELD
226 *
227 ******************************************************************************/
228
229static void
230OpnDoFieldCommon (
231    ACPI_PARSE_OBJECT       *FieldOp,
232    ACPI_PARSE_OBJECT       *Op)
233{
234    ACPI_PARSE_OBJECT       *Next;
235    ACPI_PARSE_OBJECT       *PkgLengthNode;
236    UINT32                  CurrentBitOffset;
237    UINT32                  NewBitOffset;
238    UINT8                   AccessType;
239    UINT8                   LockRule;
240    UINT8                   UpdateRule;
241    UINT8                   FieldFlags;
242    UINT32                  MinimumLength;
243
244
245    /* AccessType -- not optional, so no need to check for DEFAULT_ARG */
246
247    AccessType = (UINT8) Op->Asl.Value.Integer;
248    Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
249
250    /* Set the access type in the parent (field) node for use later */
251
252    FieldOp->Asl.Value.Integer = AccessType;
253
254    /* LockRule -- not optional, so no need to check for DEFAULT_ARG */
255
256    Next = Op->Asl.Next;
257    LockRule = (UINT8) Next->Asl.Value.Integer;
258    Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
259
260    /* UpdateRule -- not optional, so no need to check for DEFAULT_ARG */
261
262    Next = Next->Asl.Next;
263    UpdateRule = (UINT8) Next->Asl.Value.Integer;
264
265    /*
266     * Generate the flags byte. The various fields are already
267     * in the right bit position via translation from the
268     * keywords by the parser.
269     */
270    FieldFlags = (UINT8) (AccessType | LockRule | UpdateRule);
271
272    /* Use the previous node to be the FieldFlags node */
273
274    /* Set the node to RAW_DATA */
275
276    Next->Asl.Value.Integer = FieldFlags;
277    Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
278    Next->Asl.AmlLength = 1;
279    Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
280
281    /* Process the FieldUnitList */
282
283    Next = Next->Asl.Next;
284    CurrentBitOffset = 0;
285
286    while (Next)
287    {
288        /* Save the offset of this field unit */
289
290        Next->Asl.ExtraValue = CurrentBitOffset;
291
292        switch (Next->Asl.ParseOpcode)
293        {
294        case PARSEOP_ACCESSAS:
295
296            PkgLengthNode = Next->Asl.Child;
297            AccessType = (UINT8) PkgLengthNode->Asl.Value.Integer;
298
299            /* Nothing additional to do */
300            break;
301
302        case PARSEOP_OFFSET:
303
304            /* New offset into the field */
305
306            PkgLengthNode = Next->Asl.Child;
307            NewBitOffset = ((UINT32) PkgLengthNode->Asl.Value.Integer) * 8;
308
309            /*
310             * Examine the specified offset in relation to the
311             * current offset counter.
312             */
313            if (NewBitOffset < CurrentBitOffset)
314            {
315                /*
316                 * Not allowed to specify a backwards offset!
317                 * Issue error and ignore this node.
318                 */
319                AslError (ASL_ERROR, ASL_MSG_BACKWARDS_OFFSET, PkgLengthNode,
320                    NULL);
321                Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
322                PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
323            }
324            else if (NewBitOffset == CurrentBitOffset)
325            {
326                /*
327                 * Offset is redundant; we don't need to output an
328                 * offset opcode. Just set these nodes to default
329                 */
330                Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
331                PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
332            }
333            else
334            {
335                /*
336                 * Valid new offset - set the value to be inserted into the AML
337                 * and update the offset counter.
338                 */
339                PkgLengthNode->Asl.Value.Integer =
340                    NewBitOffset - CurrentBitOffset;
341                CurrentBitOffset = NewBitOffset;
342            }
343            break;
344
345        case PARSEOP_NAMESEG:
346        case PARSEOP_RESERVED_BYTES:
347
348            /* Named or reserved field entry */
349
350            PkgLengthNode = Next->Asl.Child;
351            NewBitOffset = (UINT32) PkgLengthNode->Asl.Value.Integer;
352            CurrentBitOffset += NewBitOffset;
353
354            /* Save the current AccessAs value for error checking later */
355
356            switch (AccessType)
357            {
358                case AML_FIELD_ACCESS_ANY:
359                case AML_FIELD_ACCESS_BYTE:
360                case AML_FIELD_ACCESS_BUFFER:
361                default:
362
363                    MinimumLength = 8;
364                    break;
365
366                case AML_FIELD_ACCESS_WORD:
367                    MinimumLength = 16;
368                    break;
369
370                case AML_FIELD_ACCESS_DWORD:
371                    MinimumLength = 32;
372                    break;
373
374                case AML_FIELD_ACCESS_QWORD:
375                    MinimumLength = 64;
376                    break;
377            }
378
379            PkgLengthNode->Asl.ExtraValue = MinimumLength;
380            break;
381
382        default:
383
384            /* All supported field opcodes must appear above */
385
386            break;
387        }
388
389        /* Move on to next entry in the field list */
390
391        Next = Next->Asl.Next;
392    }
393}
394
395
396/*******************************************************************************
397 *
398 * FUNCTION:    OpnDoField
399 *
400 * PARAMETERS:  Op        - The parent parse node
401 *
402 * RETURN:      None
403 *
404 * DESCRIPTION: Construct the AML operands for the FIELD ASL keyword
405 *
406 ******************************************************************************/
407
408static void
409OpnDoField (
410    ACPI_PARSE_OBJECT       *Op)
411{
412    ACPI_PARSE_OBJECT       *Next;
413
414
415    /* Opcode is parent node */
416    /* First child is field name */
417
418    Next = Op->Asl.Child;
419
420    /* Second child is the AccessType */
421
422    OpnDoFieldCommon (Op, Next->Asl.Next);
423}
424
425
426/*******************************************************************************
427 *
428 * FUNCTION:    OpnDoIndexField
429 *
430 * PARAMETERS:  Op        - The parent parse node
431 *
432 * RETURN:      None
433 *
434 * DESCRIPTION: Construct the AML operands for the INDEXFIELD ASL keyword
435 *
436 ******************************************************************************/
437
438static void
439OpnDoIndexField (
440    ACPI_PARSE_OBJECT       *Op)
441{
442    ACPI_PARSE_OBJECT       *Next;
443
444
445    /* Opcode is parent node */
446    /* First child is the index name */
447
448    Next = Op->Asl.Child;
449
450    /* Second child is the data name */
451
452    Next = Next->Asl.Next;
453
454    /* Third child is the AccessType */
455
456    OpnDoFieldCommon (Op, Next->Asl.Next);
457}
458
459
460/*******************************************************************************
461 *
462 * FUNCTION:    OpnDoBankField
463 *
464 * PARAMETERS:  Op        - The parent parse node
465 *
466 * RETURN:      None
467 *
468 * DESCRIPTION: Construct the AML operands for the BANKFIELD ASL keyword
469 *
470 ******************************************************************************/
471
472static void
473OpnDoBankField (
474    ACPI_PARSE_OBJECT       *Op)
475{
476    ACPI_PARSE_OBJECT       *Next;
477
478
479    /* Opcode is parent node */
480    /* First child is the region name */
481
482    Next = Op->Asl.Child;
483
484    /* Second child is the bank name */
485
486    Next = Next->Asl.Next;
487
488    /* Third child is the bank value */
489
490    Next = Next->Asl.Next;
491
492    /* Fourth child is the AccessType */
493
494    OpnDoFieldCommon (Op, Next->Asl.Next);
495}
496
497
498/*******************************************************************************
499 *
500 * FUNCTION:    OpnDoRegion
501 *
502 * PARAMETERS:  Op        - The parent parse node
503 *
504 * RETURN:      None
505 *
506 * DESCRIPTION: Tries to get the length of the region. Can only do this at
507 *              compile time if the length is a constant.
508 *
509 ******************************************************************************/
510
511static void
512OpnDoRegion (
513    ACPI_PARSE_OBJECT       *Op)
514{
515    ACPI_PARSE_OBJECT       *Next;
516
517
518    /* Opcode is parent node */
519    /* First child is the region name */
520
521    Next = Op->Asl.Child;
522
523    /* Second child is the space ID*/
524
525    Next = Next->Asl.Next;
526
527    /* Third child is the region offset */
528
529    Next = Next->Asl.Next;
530
531    /* Fourth child is the region length */
532
533    Next = Next->Asl.Next;
534    if (Next->Asl.ParseOpcode == PARSEOP_INTEGER)
535    {
536        Op->Asl.Value.Integer = Next->Asl.Value.Integer;
537    }
538    else
539    {
540        Op->Asl.Value.Integer = ACPI_UINT64_MAX;
541    }
542}
543
544
545/*******************************************************************************
546 *
547 * FUNCTION:    OpnDoBuffer
548 *
549 * PARAMETERS:  Op        - The parent parse node
550 *
551 * RETURN:      None
552 *
553 * DESCRIPTION: Construct the AML operands for the BUFFER ASL keyword. We
554 *              build a single raw byte buffer from the initialization nodes,
555 *              each parse node contains a buffer byte.
556 *
557 ******************************************************************************/
558
559static void
560OpnDoBuffer (
561    ACPI_PARSE_OBJECT       *Op)
562{
563    ACPI_PARSE_OBJECT       *InitializerOp;
564    ACPI_PARSE_OBJECT       *BufferLengthOp;
565
566    /* Optional arguments for this opcode with defaults */
567
568    UINT32                  BufferLength = 0;
569
570
571    /* Opcode and package length first */
572    /* Buffer Length is next, followed by the initializer list */
573
574    BufferLengthOp = Op->Asl.Child;
575    InitializerOp = BufferLengthOp->Asl.Next;
576
577    /*
578     * If the BufferLength is not an INTEGER or was not specified in the ASL
579     * (DEFAULT_ARG), it is a TermArg that is
580     * evaluated at run-time, and we are therefore finished.
581     */
582    if ((BufferLengthOp->Asl.ParseOpcode != PARSEOP_INTEGER) &&
583        (BufferLengthOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
584    {
585        return;
586    }
587
588    /*
589     * We want to count the number of items in the initializer list, because if
590     * it is larger than the buffer length, we will define the buffer size
591     * to be the size of the initializer list (as per the ACPI Specification)
592     */
593    switch (InitializerOp->Asl.ParseOpcode)
594    {
595    case PARSEOP_INTEGER:
596    case PARSEOP_BYTECONST:
597    case PARSEOP_WORDCONST:
598    case PARSEOP_DWORDCONST:
599
600        /* The peer list contains the byte list (if any...) */
601
602        while (InitializerOp)
603        {
604            /* For buffers, this is a list of raw bytes */
605
606            InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
607            InitializerOp->Asl.AmlLength = 1;
608            InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
609
610            BufferLength++;
611            InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
612        }
613        break;
614
615    case PARSEOP_STRING_LITERAL:
616
617        /*
618         * Only one initializer, the string. Buffer must be big enough to hold
619         * the string plus the null termination byte
620         */
621        BufferLength = strlen (InitializerOp->Asl.Value.String) + 1;
622
623        InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
624        InitializerOp->Asl.AmlLength = BufferLength;
625        InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
626        break;
627
628    case PARSEOP_RAW_DATA:
629
630        /* Buffer nodes are already initialized (e.g. Unicode operator) */
631        return;
632
633    case PARSEOP_DEFAULT_ARG:
634        break;
635
636    default:
637
638        AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, InitializerOp,
639            "Unknown buffer initializer opcode");
640        printf ("Unknown buffer initializer opcode [%s]\n",
641            UtGetOpName (InitializerOp->Asl.ParseOpcode));
642        return;
643    }
644
645    /* Check if initializer list is longer than the buffer length */
646
647    if (BufferLengthOp->Asl.Value.Integer > BufferLength)
648    {
649        BufferLength = (UINT32) BufferLengthOp->Asl.Value.Integer;
650    }
651
652    if (!BufferLength)
653    {
654        /* No length AND no items -- issue notice */
655
656        AslError (ASL_REMARK, ASL_MSG_BUFFER_LENGTH, BufferLengthOp, NULL);
657
658        /* But go ahead and put the buffer length of zero into the AML */
659    }
660
661    /*
662     * Just set the buffer size node to be the buffer length, regardless
663     * of whether it was previously an integer or a default_arg placeholder
664     */
665    BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
666    BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP;
667    BufferLengthOp->Asl.Value.Integer = BufferLength;
668
669    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
670
671    /* Remaining nodes are handled via the tree walk */
672}
673
674
675/*******************************************************************************
676 *
677 * FUNCTION:    OpnDoPackage
678 *
679 * PARAMETERS:  Op        - The parent parse node
680 *
681 * RETURN:      None
682 *
683 * DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword. NOTE:
684 *              can only be called after constants have been folded, to ensure
685 *              that the PackageLength operand has been fully reduced.
686 *
687 ******************************************************************************/
688
689void
690OpnDoPackage (
691    ACPI_PARSE_OBJECT       *Op)
692{
693    ACPI_PARSE_OBJECT       *InitializerOp;
694    ACPI_PARSE_OBJECT       *PackageLengthOp;
695    UINT32                  PackageLength = 0;
696
697
698    /* Opcode and package length first, followed by the initializer list */
699
700    PackageLengthOp = Op->Asl.Child;
701    InitializerOp = PackageLengthOp->Asl.Next;
702
703    /* Count the number of items in the initializer list */
704
705    if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
706    {
707        /* The peer list contains the byte list (if any...) */
708
709        while (InitializerOp)
710        {
711            PackageLength++;
712            InitializerOp = InitializerOp->Asl.Next;
713        }
714    }
715
716    /* If package length is a constant, compare to the initializer list */
717
718    if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
719        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST))
720    {
721        if (PackageLengthOp->Asl.Value.Integer > PackageLength)
722        {
723            /*
724             * Allow package length to be longer than the initializer
725             * list -- but if the length of initializer list is nonzero,
726             * issue a message since this is probably a coding error,
727             * even though technically legal.
728             */
729            if (PackageLength > 0)
730            {
731                AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT,
732                    PackageLengthOp, NULL);
733            }
734
735            PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer;
736        }
737        else if (PackageLengthOp->Asl.Value.Integer < PackageLength)
738        {
739            /*
740             * The package length is smaller than the length of the
741             * initializer list. This is an error as per the ACPI spec.
742             */
743            AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG,
744                PackageLengthOp, NULL);
745        }
746    }
747
748    if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
749    {
750        /*
751         * This is the case if the PackageLength was left empty - Package()
752         * The package length becomes the length of the initializer list
753         */
754        Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER;
755        Op->Asl.Child->Asl.Value.Integer = PackageLength;
756
757        /* Set the AML opcode */
758
759        (void) OpcSetOptimalIntegerSize (Op->Asl.Child);
760    }
761
762    /* If not a variable-length package, check for a zero package length */
763
764    if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
765        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST)   ||
766        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_ZERO)         ||
767        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG))
768    {
769        if (!PackageLength)
770        {
771            /* No length AND no initializer list -- issue a remark */
772
773            AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH,
774                PackageLengthOp, NULL);
775
776            /* But go ahead and put the buffer length of zero into the AML */
777        }
778    }
779
780    /*
781     * If the PackageLength is a constant <= 255, we can change the
782     * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode.
783     */
784    if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
785            (Op->Asl.Child->Asl.Value.Integer <= 255))  ||
786        (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) ||
787        (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)||
788        (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO))
789    {
790        Op->Asl.AmlOpcode = AML_PACKAGE_OP;
791        Op->Asl.ParseOpcode = PARSEOP_PACKAGE;
792
793        /*
794         * Just set the package size node to be the package length, regardless
795         * of whether it was previously an integer or a default_arg placeholder
796         */
797        PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
798        PackageLengthOp->Asl.AmlLength = 1;
799        PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
800        PackageLengthOp->Asl.Value.Integer = PackageLength;
801    }
802
803    /* Remaining nodes are handled via the tree walk */
804}
805
806
807/*******************************************************************************
808 *
809 * FUNCTION:    OpnDoLoadTable
810 *
811 * PARAMETERS:  Op        - The parent parse node
812 *
813 * RETURN:      None
814 *
815 * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword.
816 *
817 ******************************************************************************/
818
819static void
820OpnDoLoadTable (
821    ACPI_PARSE_OBJECT       *Op)
822{
823    ACPI_PARSE_OBJECT       *Next;
824
825
826    /* Opcode is parent node */
827    /* First child is the table signature */
828
829    Next = Op->Asl.Child;
830
831    /* Second child is the OEM ID*/
832
833    Next = Next->Asl.Next;
834
835    /* Third child is the OEM table ID */
836
837    Next = Next->Asl.Next;
838
839    /* Fourth child is the RootPath string */
840
841    Next = Next->Asl.Next;
842    if (Next->Asl.ParseOpcode == PARSEOP_ZERO)
843    {
844        Next->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
845        Next->Asl.Value.String = "\\";
846        Next->Asl.AmlLength = 2;
847        OpcGenerateAmlOpcode (Next);
848    }
849
850#ifdef ASL_FUTURE_IMPLEMENTATION
851
852    /* TBD: NOT IMPLEMENTED */
853    /* Fifth child is the [optional] ParameterPathString */
854    /* Sixth child is the [optional] ParameterData */
855
856    Next = Next->Asl.Next;
857    if (Next->Asl.ParseOpcode == DEFAULT_ARG)
858    {
859        Next->Asl.AmlLength = 1;
860        Next->Asl.ParseOpcode = ZERO;
861        OpcGenerateAmlOpcode (Next);
862    }
863
864
865    Next = Next->Asl.Next;
866    if (Next->Asl.ParseOpcode == DEFAULT_ARG)
867    {
868        Next->Asl.AmlLength = 1;
869        Next->Asl.ParseOpcode = ZERO;
870        OpcGenerateAmlOpcode (Next);
871    }
872#endif
873}
874
875
876/*******************************************************************************
877 *
878 * FUNCTION:    OpnDoDefinitionBlock
879 *
880 * PARAMETERS:  Op        - The parent parse node
881 *
882 * RETURN:      None
883 *
884 * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword
885 *
886 ******************************************************************************/
887
888static void
889OpnDoDefinitionBlock (
890    ACPI_PARSE_OBJECT       *Op)
891{
892    ACPI_PARSE_OBJECT       *Child;
893    ACPI_SIZE               Length;
894    UINT32                  i;
895    char                    *Filename;
896
897
898    /*
899     * These nodes get stuffed into the table header. They are special
900     * cased when the table is written to the output file.
901     *
902     * Mark all of these nodes as non-usable so they won't get output
903     * as AML opcodes!
904     */
905
906    /* Get AML filename. Use it if non-null */
907
908    Child = Op->Asl.Child;
909    if (Child->Asl.Value.Buffer  &&
910        *Child->Asl.Value.Buffer &&
911        (Gbl_UseDefaultAmlFilename))
912    {
913        /*
914         * We will use the AML filename that is embedded in the source file
915         * for the output filename.
916         */
917        Filename = UtStringCacheCalloc (strlen (Gbl_DirectoryPath) +
918            strlen ((char *) Child->Asl.Value.Buffer) + 1);
919
920        /* Prepend the current directory path */
921
922        strcpy (Filename, Gbl_DirectoryPath);
923        strcat (Filename, (char *) Child->Asl.Value.Buffer);
924
925        Gbl_OutputFilenamePrefix = Filename;
926        UtConvertBackslashes (Gbl_OutputFilenamePrefix);
927    }
928
929    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
930
931    /* Signature */
932
933    Child = Child->Asl.Next;
934    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
935    if (Child->Asl.Value.String)
936    {
937        Gbl_TableSignature = Child->Asl.Value.String;
938        if (strlen (Gbl_TableSignature) != ACPI_NAME_SIZE)
939        {
940            AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
941                "Length is not exactly 4");
942        }
943
944        for (i = 0; i < ACPI_NAME_SIZE; i++)
945        {
946            if (!isalnum ((int) Gbl_TableSignature[i]))
947            {
948                AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
949                    "Contains non-alphanumeric characters");
950            }
951        }
952    }
953
954    /* Revision */
955
956    Child = Child->Asl.Next;
957    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
958    /*
959     * We used the revision to set the integer width earlier
960     */
961
962    /* OEMID */
963
964    Child = Child->Asl.Next;
965    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
966
967    /* OEM TableID */
968
969    Child = Child->Asl.Next;
970    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
971    if (Child->Asl.Value.String)
972    {
973        Length = strlen (Child->Asl.Value.String);
974        Gbl_TableId = UtStringCacheCalloc (Length + 1);
975        strcpy (Gbl_TableId, Child->Asl.Value.String);
976
977        /*
978         * Convert anything non-alphanumeric to an underscore. This
979         * allows us to use the TableID to generate unique C symbols.
980         */
981        for (i = 0; i < Length; i++)
982        {
983            if (!isalnum ((int) Gbl_TableId[i]))
984            {
985                Gbl_TableId[i] = '_';
986            }
987        }
988    }
989
990    /* OEM Revision */
991
992    Child = Child->Asl.Next;
993    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
994}
995
996
997/*******************************************************************************
998 *
999 * FUNCTION:    UtGetArg
1000 *
1001 * PARAMETERS:  Op              - Get an argument for this op
1002 *              Argn            - Nth argument to get
1003 *
1004 * RETURN:      The argument (as an Op object). NULL if argument does not exist
1005 *
1006 * DESCRIPTION: Get the specified op's argument (peer)
1007 *
1008 ******************************************************************************/
1009
1010ACPI_PARSE_OBJECT *
1011UtGetArg (
1012    ACPI_PARSE_OBJECT       *Op,
1013    UINT32                  Argn)
1014{
1015    ACPI_PARSE_OBJECT       *Arg = NULL;
1016
1017
1018    /* Get the requested argument object */
1019
1020    Arg = Op->Asl.Child;
1021    while (Arg && Argn)
1022    {
1023        Argn--;
1024        Arg = Arg->Asl.Next;
1025    }
1026
1027    return (Arg);
1028}
1029
1030
1031/*******************************************************************************
1032 *
1033 * FUNCTION:    OpnAttachNameToNode
1034 *
1035 * PARAMETERS:  Op        - The parent parse node
1036 *
1037 * RETURN:      None
1038 *
1039 * DESCRIPTION: For the named ASL/AML operators, get the actual name from the
1040 *              argument list and attach it to the parent node so that we
1041 *              can get to it quickly later.
1042 *
1043 ******************************************************************************/
1044
1045static void
1046OpnAttachNameToNode (
1047    ACPI_PARSE_OBJECT       *Op)
1048{
1049    ACPI_PARSE_OBJECT       *Child = NULL;
1050
1051
1052    switch (Op->Asl.AmlOpcode)
1053    {
1054    case AML_DATA_REGION_OP:
1055    case AML_DEVICE_OP:
1056    case AML_EVENT_OP:
1057    case AML_EXTERNAL_OP:
1058    case AML_METHOD_OP:
1059    case AML_MUTEX_OP:
1060    case AML_REGION_OP:
1061    case AML_POWER_RES_OP:
1062    case AML_PROCESSOR_OP:
1063    case AML_THERMAL_ZONE_OP:
1064    case AML_NAME_OP:
1065    case AML_SCOPE_OP:
1066
1067        Child = UtGetArg (Op, 0);
1068        break;
1069
1070    case AML_ALIAS_OP:
1071
1072        Child = UtGetArg (Op, 1);
1073        break;
1074
1075    case AML_CREATE_BIT_FIELD_OP:
1076    case AML_CREATE_BYTE_FIELD_OP:
1077    case AML_CREATE_WORD_FIELD_OP:
1078    case AML_CREATE_DWORD_FIELD_OP:
1079    case AML_CREATE_QWORD_FIELD_OP:
1080
1081        Child = UtGetArg (Op, 2);
1082        break;
1083
1084    case AML_CREATE_FIELD_OP:
1085
1086        Child = UtGetArg (Op, 3);
1087        break;
1088
1089    case AML_BANK_FIELD_OP:
1090    case AML_INDEX_FIELD_OP:
1091    case AML_FIELD_OP:
1092
1093        return;
1094
1095    default:
1096
1097        return;
1098    }
1099
1100    if (Child)
1101    {
1102        UtAttachNamepathToOwner (Op, Child);
1103    }
1104}
1105
1106
1107/*******************************************************************************
1108 *
1109 * FUNCTION:    OpnGenerateAmlOperands
1110 *
1111 * PARAMETERS:  Op        - The parent parse node
1112 *
1113 * RETURN:      None
1114 *
1115 * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more
1116 *              complex AML opcodes require processing of the child nodes
1117 *              (arguments/operands).
1118 *
1119 ******************************************************************************/
1120
1121void
1122OpnGenerateAmlOperands (
1123    ACPI_PARSE_OBJECT       *Op)
1124{
1125
1126
1127    if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)
1128    {
1129        return;
1130    }
1131
1132    switch (Op->Asl.ParseOpcode)
1133    {
1134    case PARSEOP_DEFINITION_BLOCK:
1135
1136        OpnDoDefinitionBlock (Op);
1137        break;
1138
1139    case PARSEOP_METHOD:
1140
1141        OpnDoMethod (Op);
1142        break;
1143
1144    case PARSEOP_MUTEX:
1145
1146        OpnDoMutex (Op);
1147        break;
1148
1149    case PARSEOP_FIELD:
1150
1151        OpnDoField (Op);
1152        break;
1153
1154    case PARSEOP_INDEXFIELD:
1155
1156        OpnDoIndexField (Op);
1157        break;
1158
1159    case PARSEOP_BANKFIELD:
1160
1161        OpnDoBankField (Op);
1162        break;
1163
1164    case PARSEOP_BUFFER:
1165
1166        OpnDoBuffer (Op);
1167        break;
1168
1169    case PARSEOP_LOADTABLE:
1170
1171        OpnDoLoadTable (Op);
1172        break;
1173
1174    case PARSEOP_OPERATIONREGION:
1175
1176        OpnDoRegion (Op);
1177        break;
1178
1179    case PARSEOP_RESOURCETEMPLATE:
1180
1181        RsDoResourceTemplate (Op);
1182        break;
1183
1184    case PARSEOP_NAMESEG:
1185    case PARSEOP_NAMESTRING:
1186    case PARSEOP_METHODCALL:
1187    case PARSEOP_STRING_LITERAL:
1188    default:
1189
1190        break;
1191    }
1192
1193    /* TBD: move */
1194
1195    OpnAttachNameToNode (Op);
1196}
1197