asloperands.c revision 281075
1/******************************************************************************
2 *
3 * Module Name: asloperands - AML operand processing
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2015, 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        Concurrency = (UINT8) Next->Asl.Value.Integer;
192    }
193
194    /* Put the bits in their proper places */
195
196    MethodFlags = (UINT8) ((NumArgs & 0x7) |
197                          ((Serialized & 0x1) << 3) |
198                          ((Concurrency & 0xF) << 4));
199
200    /* Use the last node for the combined flags byte */
201
202    Next->Asl.Value.Integer = MethodFlags;
203    Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
204    Next->Asl.AmlLength = 1;
205    Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
206
207    /* Save the arg count in the first node */
208
209    Op->Asl.Extra = NumArgs;
210}
211
212
213/*******************************************************************************
214 *
215 * FUNCTION:    OpnDoFieldCommon
216 *
217 * PARAMETERS:  FieldOp       - Node for an ASL field
218 *              Op            - The parent parse node
219 *
220 * RETURN:      None
221 *
222 * DESCRIPTION: Construct the AML operands for the various field keywords,
223 *              FIELD, BANKFIELD, INDEXFIELD
224 *
225 ******************************************************************************/
226
227static void
228OpnDoFieldCommon (
229    ACPI_PARSE_OBJECT       *FieldOp,
230    ACPI_PARSE_OBJECT       *Op)
231{
232    ACPI_PARSE_OBJECT       *Next;
233    ACPI_PARSE_OBJECT       *PkgLengthNode;
234    UINT32                  CurrentBitOffset;
235    UINT32                  NewBitOffset;
236    UINT8                   AccessType;
237    UINT8                   LockRule;
238    UINT8                   UpdateRule;
239    UINT8                   FieldFlags;
240    UINT32                  MinimumLength;
241
242
243    /* AccessType -- not optional, so no need to check for DEFAULT_ARG */
244
245    AccessType = (UINT8) Op->Asl.Value.Integer;
246    Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
247
248    /* Set the access type in the parent (field) node for use later */
249
250    FieldOp->Asl.Value.Integer = AccessType;
251
252    /* LockRule -- not optional, so no need to check for DEFAULT_ARG */
253
254    Next = Op->Asl.Next;
255    LockRule = (UINT8) Next->Asl.Value.Integer;
256    Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
257
258    /* UpdateRule -- not optional, so no need to check for DEFAULT_ARG */
259
260    Next = Next->Asl.Next;
261    UpdateRule = (UINT8) Next->Asl.Value.Integer;
262
263    /*
264     * Generate the flags byte. The various fields are already
265     * in the right bit position via translation from the
266     * keywords by the parser.
267     */
268    FieldFlags = (UINT8) (AccessType | LockRule | UpdateRule);
269
270    /* Use the previous node to be the FieldFlags node */
271
272    /* Set the node to RAW_DATA */
273
274    Next->Asl.Value.Integer = FieldFlags;
275    Next->Asl.AmlOpcode     = AML_RAW_DATA_BYTE;
276    Next->Asl.AmlLength     = 1;
277    Next->Asl.ParseOpcode   = PARSEOP_RAW_DATA;
278
279    /* Process the FieldUnitList */
280
281    Next = Next->Asl.Next;
282    CurrentBitOffset = 0;
283
284    while (Next)
285    {
286        /* Save the offset of this field unit */
287
288        Next->Asl.ExtraValue = CurrentBitOffset;
289
290        switch (Next->Asl.ParseOpcode)
291        {
292        case PARSEOP_ACCESSAS:
293
294            PkgLengthNode = Next->Asl.Child;
295            AccessType = (UINT8) PkgLengthNode->Asl.Value.Integer;
296
297            /* Nothing additional to do */
298            break;
299
300        case PARSEOP_OFFSET:
301
302            /* New offset into the field */
303
304            PkgLengthNode = Next->Asl.Child;
305            NewBitOffset = ((UINT32) PkgLengthNode->Asl.Value.Integer) * 8;
306
307            /*
308             * Examine the specified offset in relation to the
309             * current offset counter.
310             */
311            if (NewBitOffset < CurrentBitOffset)
312            {
313                /*
314                 * Not allowed to specify a backwards offset!
315                 * Issue error and ignore this node.
316                 */
317                AslError (ASL_ERROR, ASL_MSG_BACKWARDS_OFFSET, PkgLengthNode,
318                    NULL);
319                Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
320                PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
321            }
322            else if (NewBitOffset == CurrentBitOffset)
323            {
324                /*
325                 * Offset is redundant; we don't need to output an
326                 * offset opcode. Just set these nodes to default
327                 */
328                Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
329                PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
330            }
331            else
332            {
333                /*
334                 * Valid new offset - set the value to be inserted into the AML
335                 * and update the offset counter.
336                 */
337                PkgLengthNode->Asl.Value.Integer =
338                    NewBitOffset - CurrentBitOffset;
339                CurrentBitOffset = NewBitOffset;
340            }
341            break;
342
343        case PARSEOP_NAMESEG:
344        case PARSEOP_RESERVED_BYTES:
345
346            /* Named or reserved field entry */
347
348            PkgLengthNode     = Next->Asl.Child;
349            NewBitOffset      = (UINT32) PkgLengthNode->Asl.Value.Integer;
350            CurrentBitOffset += NewBitOffset;
351
352            /* Save the current AccessAs value for error checking later */
353
354            switch (AccessType)
355            {
356                case AML_FIELD_ACCESS_ANY:
357                case AML_FIELD_ACCESS_BYTE:
358                case AML_FIELD_ACCESS_BUFFER:
359                default:
360
361                    MinimumLength = 8;
362                    break;
363
364                case AML_FIELD_ACCESS_WORD:
365                    MinimumLength = 16;
366                    break;
367
368                case AML_FIELD_ACCESS_DWORD:
369                    MinimumLength = 32;
370                    break;
371
372                case AML_FIELD_ACCESS_QWORD:
373                    MinimumLength = 64;
374                    break;
375            }
376
377            PkgLengthNode->Asl.ExtraValue = MinimumLength;
378            break;
379
380        default:
381
382            /* All supported field opcodes must appear above */
383
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    case PARSEOP_STRING_LITERAL:
614
615        /*
616         * Only one initializer, the string. Buffer must be big enough to hold
617         * the string plus the null termination byte
618         */
619        BufferLength = strlen (InitializerOp->Asl.Value.String) + 1;
620
621        InitializerOp->Asl.AmlOpcode      = AML_RAW_DATA_BUFFER;
622        InitializerOp->Asl.AmlLength      = BufferLength;
623        InitializerOp->Asl.ParseOpcode    = PARSEOP_RAW_DATA;
624        break;
625
626    case PARSEOP_RAW_DATA:
627
628        /* Buffer nodes are already initialized (e.g. Unicode operator) */
629        return;
630
631    case PARSEOP_DEFAULT_ARG:
632        break;
633
634    default:
635
636        AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, InitializerOp,
637            "Unknown buffer initializer opcode");
638        printf ("Unknown buffer initializer opcode [%s]\n",
639                        UtGetOpName (InitializerOp->Asl.ParseOpcode));
640        return;
641    }
642
643    /* Check if initializer list is longer than the buffer length */
644
645    if (BufferLengthOp->Asl.Value.Integer > BufferLength)
646    {
647        BufferLength = (UINT32) BufferLengthOp->Asl.Value.Integer;
648    }
649
650    if (!BufferLength)
651    {
652        /* No length AND no items -- issue notice */
653
654        AslError (ASL_REMARK, ASL_MSG_BUFFER_LENGTH, BufferLengthOp, NULL);
655
656        /* But go ahead and put the buffer length of zero into the AML */
657    }
658
659    /*
660     * Just set the buffer size node to be the buffer length, regardless
661     * of whether it was previously an integer or a default_arg placeholder
662     */
663    BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
664    BufferLengthOp->Asl.AmlOpcode     = AML_DWORD_OP;
665    BufferLengthOp->Asl.Value.Integer = BufferLength;
666
667    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
668
669    /* Remaining nodes are handled via the tree walk */
670}
671
672
673/*******************************************************************************
674 *
675 * FUNCTION:    OpnDoPackage
676 *
677 * PARAMETERS:  Op        - The parent parse node
678 *
679 * RETURN:      None
680 *
681 * DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword. NOTE:
682 *              can only be called after constants have been folded, to ensure
683 *              that the PackageLength operand has been fully reduced.
684 *
685 ******************************************************************************/
686
687void
688OpnDoPackage (
689    ACPI_PARSE_OBJECT       *Op)
690{
691    ACPI_PARSE_OBJECT       *InitializerOp;
692    ACPI_PARSE_OBJECT       *PackageLengthOp;
693    UINT32                  PackageLength = 0;
694
695
696    /* Opcode and package length first, followed by the initializer list */
697
698    PackageLengthOp = Op->Asl.Child;
699    InitializerOp = PackageLengthOp->Asl.Next;
700
701    /* Count the number of items in the initializer list */
702
703    if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
704    {
705        /* The peer list contains the byte list (if any...) */
706
707        while (InitializerOp)
708        {
709            PackageLength++;
710            InitializerOp = InitializerOp->Asl.Next;
711        }
712    }
713
714    /* If package length is a constant, compare to the initializer list */
715
716    if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
717        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST))
718    {
719        if (PackageLengthOp->Asl.Value.Integer > PackageLength)
720        {
721            /*
722             * Allow package length to be longer than the initializer
723             * list -- but if the length of initializer list is nonzero,
724             * issue a message since this is probably a coding error,
725             * even though technically legal.
726             */
727            if (PackageLength > 0)
728            {
729                AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT,
730                    PackageLengthOp, NULL);
731            }
732
733            PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer;
734        }
735        else if (PackageLengthOp->Asl.Value.Integer < PackageLength)
736        {
737            /*
738             * The package length is smaller than the length of the
739             * initializer list. This is an error as per the ACPI spec.
740             */
741            AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG,
742                PackageLengthOp, NULL);
743        }
744    }
745
746    if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
747    {
748        /*
749         * This is the case if the PackageLength was left empty - Package()
750         * The package length becomes the length of the initializer list
751         */
752        Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER;
753        Op->Asl.Child->Asl.Value.Integer = PackageLength;
754
755        /* Set the AML opcode */
756
757        (void) OpcSetOptimalIntegerSize (Op->Asl.Child);
758    }
759
760    /* If not a variable-length package, check for a zero package length */
761
762    if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
763        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST)   ||
764        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_ZERO)         ||
765        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG))
766    {
767        if (!PackageLength)
768        {
769            /* No length AND no initializer list -- issue a remark */
770
771            AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH,
772                PackageLengthOp, NULL);
773
774            /* But go ahead and put the buffer length of zero into the AML */
775        }
776    }
777
778    /*
779     * If the PackageLength is a constant <= 255, we can change the
780     * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode.
781     */
782    if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
783            (Op->Asl.Child->Asl.Value.Integer <= 255))  ||
784        (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) ||
785        (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)||
786        (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO))
787    {
788        Op->Asl.AmlOpcode = AML_PACKAGE_OP;
789        Op->Asl.ParseOpcode = PARSEOP_PACKAGE;
790
791        /*
792         * Just set the package size node to be the package length, regardless
793         * of whether it was previously an integer or a default_arg placeholder
794         */
795        PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
796        PackageLengthOp->Asl.AmlLength = 1;
797        PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
798        PackageLengthOp->Asl.Value.Integer = PackageLength;
799    }
800
801    /* Remaining nodes are handled via the tree walk */
802}
803
804
805/*******************************************************************************
806 *
807 * FUNCTION:    OpnDoLoadTable
808 *
809 * PARAMETERS:  Op        - The parent parse node
810 *
811 * RETURN:      None
812 *
813 * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword.
814 *
815 ******************************************************************************/
816
817static void
818OpnDoLoadTable (
819    ACPI_PARSE_OBJECT       *Op)
820{
821    ACPI_PARSE_OBJECT       *Next;
822
823
824    /* Opcode is parent node */
825    /* First child is the table signature */
826
827    Next = Op->Asl.Child;
828
829    /* Second child is the OEM ID*/
830
831    Next = Next->Asl.Next;
832
833    /* Third child is the OEM table ID */
834
835    Next = Next->Asl.Next;
836
837    /* Fourth child is the RootPath string */
838
839    Next = Next->Asl.Next;
840    if (Next->Asl.ParseOpcode == PARSEOP_ZERO)
841    {
842        Next->Asl.ParseOpcode    = PARSEOP_STRING_LITERAL;
843        Next->Asl.Value.String   = "\\";
844        Next->Asl.AmlLength      = 2;
845        OpcGenerateAmlOpcode (Next);
846    }
847
848#ifdef ASL_FUTURE_IMPLEMENTATION
849
850    /* TBD: NOT IMPLEMENTED */
851    /* Fifth child is the [optional] ParameterPathString */
852    /* Sixth child is the [optional] ParameterData */
853
854    Next = Next->Asl.Next;
855    if (Next->Asl.ParseOpcode == DEFAULT_ARG)
856    {
857        Next->Asl.AmlLength = 1;
858        Next->Asl.ParseOpcode = ZERO;
859        OpcGenerateAmlOpcode (Next);
860    }
861
862
863    Next = Next->Asl.Next;
864    if (Next->Asl.ParseOpcode == DEFAULT_ARG)
865    {
866        Next->Asl.AmlLength = 1;
867        Next->Asl.ParseOpcode = ZERO;
868        OpcGenerateAmlOpcode (Next);
869    }
870#endif
871}
872
873
874/*******************************************************************************
875 *
876 * FUNCTION:    OpnDoDefinitionBlock
877 *
878 * PARAMETERS:  Op        - The parent parse node
879 *
880 * RETURN:      None
881 *
882 * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword
883 *
884 ******************************************************************************/
885
886static void
887OpnDoDefinitionBlock (
888    ACPI_PARSE_OBJECT       *Op)
889{
890    ACPI_PARSE_OBJECT       *Child;
891    ACPI_SIZE               Length;
892    UINT32                  i;
893    char                    *Filename;
894
895
896    /*
897     * These nodes get stuffed into the table header. They are special
898     * cased when the table is written to the output file.
899     *
900     * Mark all of these nodes as non-usable so they won't get output
901     * as AML opcodes!
902     */
903
904    /* Get AML filename. Use it if non-null */
905
906    Child = Op->Asl.Child;
907    if (Child->Asl.Value.Buffer  &&
908        *Child->Asl.Value.Buffer &&
909        (Gbl_UseDefaultAmlFilename))
910    {
911        /*
912         * We will use the AML filename that is embedded in the source file
913         * for the output filename.
914         */
915        Filename = UtStringCacheCalloc (strlen (Gbl_DirectoryPath) +
916            strlen ((char *) Child->Asl.Value.Buffer) + 1);
917
918        /* Prepend the current directory path */
919
920        strcpy (Filename, Gbl_DirectoryPath);
921        strcat (Filename, (char *) Child->Asl.Value.Buffer);
922
923        Gbl_OutputFilenamePrefix = Filename;
924        UtConvertBackslashes (Gbl_OutputFilenamePrefix);
925    }
926    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
927
928    /* Signature */
929
930    Child = Child->Asl.Next;
931    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
932    if (Child->Asl.Value.String)
933    {
934        Gbl_TableSignature = Child->Asl.Value.String;
935        if (ACPI_STRLEN (Gbl_TableSignature) != 4)
936        {
937            AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
938                "Length not exactly 4");
939        }
940
941        for (i = 0; i < 4; i++)
942        {
943            if (!isalnum ((int) Gbl_TableSignature[i]))
944            {
945                AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
946                    "Contains non-alphanumeric characters");
947            }
948        }
949    }
950
951    /* Revision */
952
953    Child = Child->Asl.Next;
954    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
955    /*
956     * We used the revision to set the integer width earlier
957     */
958
959    /* OEMID */
960
961    Child = Child->Asl.Next;
962    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
963
964    /* OEM TableID */
965
966    Child = Child->Asl.Next;
967    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
968    if (Child->Asl.Value.String)
969    {
970        Length = ACPI_STRLEN (Child->Asl.Value.String);
971        Gbl_TableId = UtStringCacheCalloc (Length + 1);
972        ACPI_STRCPY (Gbl_TableId, Child->Asl.Value.String);
973
974        /*
975         * Convert anything non-alphanumeric to an underscore. This
976         * allows us to use the TableID to generate unique C symbols.
977         */
978        for (i = 0; i < Length; i++)
979        {
980            if (!isalnum ((int) Gbl_TableId[i]))
981            {
982                Gbl_TableId[i] = '_';
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
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_DEFINITIONBLOCK:
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
1189        break;
1190
1191    default:
1192
1193        break;
1194    }
1195
1196    /* TBD: move */
1197
1198    OpnAttachNameToNode (Op);
1199}
1200