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