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