asloperands.c revision 229989
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        if (Next->Asl.Value.Integer > 15)
186        {
187            AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
188        }
189        Concurrency = (UINT8) Next->Asl.Value.Integer;
190    }
191
192    /* Put the bits in their proper places */
193
194    MethodFlags = (UINT8) ((NumArgs & 0x7) |
195                          ((Serialized & 0x1) << 3) |
196                          ((Concurrency & 0xF) << 4));
197
198    /* Use the last node for the combined flags byte */
199
200    Next->Asl.Value.Integer = MethodFlags;
201    Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
202    Next->Asl.AmlLength = 1;
203    Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
204
205    /* Save the arg count in the first node */
206
207    Op->Asl.Extra = NumArgs;
208}
209
210
211/*******************************************************************************
212 *
213 * FUNCTION:    OpnDoFieldCommon
214 *
215 * PARAMETERS:  FieldOp       - Node for an ASL field
216 *              Op            - The parent parse node
217 *
218 * RETURN:      None
219 *
220 * DESCRIPTION: Construct the AML operands for the various field keywords,
221 *              FIELD, BANKFIELD, INDEXFIELD
222 *
223 ******************************************************************************/
224
225static void
226OpnDoFieldCommon (
227    ACPI_PARSE_OBJECT       *FieldOp,
228    ACPI_PARSE_OBJECT       *Op)
229{
230    ACPI_PARSE_OBJECT       *Next;
231    ACPI_PARSE_OBJECT       *PkgLengthNode;
232    UINT32                  CurrentBitOffset;
233    UINT32                  NewBitOffset;
234    UINT8                   AccessType;
235    UINT8                   LockRule;
236    UINT8                   UpdateRule;
237    UINT8                   FieldFlags;
238    UINT32                  MinimumLength;
239
240
241    /* AccessType -- not optional, so no need to check for DEFAULT_ARG */
242
243    AccessType = (UINT8) Op->Asl.Value.Integer;
244    Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
245
246    /* Set the access type in the parent (field) node for use later */
247
248    FieldOp->Asl.Value.Integer = AccessType;
249
250    /* LockRule -- not optional, so no need to check for DEFAULT_ARG */
251
252    Next = Op->Asl.Next;
253    LockRule = (UINT8) Next->Asl.Value.Integer;
254    Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
255
256    /* UpdateRule -- not optional, so no need to check for DEFAULT_ARG */
257
258    Next = Next->Asl.Next;
259    UpdateRule = (UINT8) Next->Asl.Value.Integer;
260
261    /*
262     * Generate the flags byte.  The various fields are already
263     * in the right bit position via translation from the
264     * keywords by the parser.
265     */
266    FieldFlags = (UINT8) (AccessType | LockRule | UpdateRule);
267
268    /* Use the previous node to be the FieldFlags node */
269
270    /* Set the node to RAW_DATA */
271
272    Next->Asl.Value.Integer = FieldFlags;
273    Next->Asl.AmlOpcode     = AML_RAW_DATA_BYTE;
274    Next->Asl.AmlLength     = 1;
275    Next->Asl.ParseOpcode   = PARSEOP_RAW_DATA;
276
277    /* Process the FieldUnitList */
278
279    Next = Next->Asl.Next;
280    CurrentBitOffset = 0;
281
282    while (Next)
283    {
284        /* Save the offset of this field unit */
285
286        Next->Asl.ExtraValue = CurrentBitOffset;
287
288        switch (Next->Asl.ParseOpcode)
289        {
290        case PARSEOP_ACCESSAS:
291
292            PkgLengthNode = Next->Asl.Child;
293            AccessType = (UINT8) PkgLengthNode->Asl.Value.Integer;
294
295            /* Nothing additional to do */
296            break;
297
298
299        case PARSEOP_OFFSET:
300
301            /* New offset into the field */
302
303            PkgLengthNode = Next->Asl.Child;
304            NewBitOffset = ((UINT32) PkgLengthNode->Asl.Value.Integer) * 8;
305
306            /*
307             * Examine the specified offset in relation to the
308             * current offset counter.
309             */
310            if (NewBitOffset < CurrentBitOffset)
311            {
312                /*
313                 * Not allowed to specify a backwards offset!
314                 * Issue error and ignore this node.
315                 */
316                AslError (ASL_ERROR, ASL_MSG_BACKWARDS_OFFSET, PkgLengthNode,
317                    NULL);
318                Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
319                PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
320            }
321            else if (NewBitOffset == CurrentBitOffset)
322            {
323                /*
324                 * Offset is redundant; we don't need to output an
325                 * offset opcode.  Just set these nodes to default
326                 */
327                Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
328                PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
329            }
330            else
331            {
332                /*
333                 * Valid new offset - set the value to be inserted into the AML
334                 * and update the offset counter.
335                 */
336                PkgLengthNode->Asl.Value.Integer =
337                    NewBitOffset - CurrentBitOffset;
338                CurrentBitOffset = NewBitOffset;
339            }
340            break;
341
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                    MinimumLength = 8;
361                    break;
362
363                case AML_FIELD_ACCESS_WORD:
364                    MinimumLength = 16;
365                    break;
366
367                case AML_FIELD_ACCESS_DWORD:
368                    MinimumLength = 32;
369                    break;
370
371                case AML_FIELD_ACCESS_QWORD:
372                    MinimumLength = 64;
373                    break;
374            }
375
376            PkgLengthNode->Asl.ExtraValue = MinimumLength;
377            break;
378
379        default:
380            /* All supported field opcodes must appear above */
381            break;
382        }
383
384        /* Move on to next entry in the field list */
385
386        Next = Next->Asl.Next;
387    }
388}
389
390
391/*******************************************************************************
392 *
393 * FUNCTION:    OpnDoField
394 *
395 * PARAMETERS:  Op        - The parent parse node
396 *
397 * RETURN:      None
398 *
399 * DESCRIPTION: Construct the AML operands for the FIELD ASL keyword
400 *
401 ******************************************************************************/
402
403static void
404OpnDoField (
405    ACPI_PARSE_OBJECT       *Op)
406{
407    ACPI_PARSE_OBJECT       *Next;
408
409
410    /* Opcode is parent node */
411    /* First child is field name */
412
413    Next = Op->Asl.Child;
414
415    /* Second child is the AccessType */
416
417    OpnDoFieldCommon (Op, Next->Asl.Next);
418}
419
420
421/*******************************************************************************
422 *
423 * FUNCTION:    OpnDoIndexField
424 *
425 * PARAMETERS:  Op        - The parent parse node
426 *
427 * RETURN:      None
428 *
429 * DESCRIPTION: Construct the AML operands for the INDEXFIELD ASL keyword
430 *
431 ******************************************************************************/
432
433static void
434OpnDoIndexField (
435    ACPI_PARSE_OBJECT       *Op)
436{
437    ACPI_PARSE_OBJECT       *Next;
438
439
440    /* Opcode is parent node */
441    /* First child is the index name */
442
443    Next = Op->Asl.Child;
444
445    /* Second child is the data name */
446
447    Next = Next->Asl.Next;
448
449    /* Third child is the AccessType */
450
451    OpnDoFieldCommon (Op, Next->Asl.Next);
452}
453
454
455/*******************************************************************************
456 *
457 * FUNCTION:    OpnDoBankField
458 *
459 * PARAMETERS:  Op        - The parent parse node
460 *
461 * RETURN:      None
462 *
463 * DESCRIPTION: Construct the AML operands for the BANKFIELD ASL keyword
464 *
465 ******************************************************************************/
466
467static void
468OpnDoBankField (
469    ACPI_PARSE_OBJECT       *Op)
470{
471    ACPI_PARSE_OBJECT       *Next;
472
473
474    /* Opcode is parent node */
475    /* First child is the region name */
476
477    Next = Op->Asl.Child;
478
479    /* Second child is the bank name */
480
481    Next = Next->Asl.Next;
482
483    /* Third child is the bank value */
484
485    Next = Next->Asl.Next;
486
487    /* Fourth child is the AccessType */
488
489    OpnDoFieldCommon (Op, Next->Asl.Next);
490}
491
492
493/*******************************************************************************
494 *
495 * FUNCTION:    OpnDoRegion
496 *
497 * PARAMETERS:  Op        - The parent parse node
498 *
499 * RETURN:      None
500 *
501 * DESCRIPTION: Tries to get the length of the region.  Can only do this at
502 *              compile time if the length is a constant.
503 *
504 ******************************************************************************/
505
506static void
507OpnDoRegion (
508    ACPI_PARSE_OBJECT       *Op)
509{
510    ACPI_PARSE_OBJECT       *Next;
511
512
513    /* Opcode is parent node */
514    /* First child is the region name */
515
516    Next = Op->Asl.Child;
517
518    /* Second child is the space ID*/
519
520    Next = Next->Asl.Next;
521
522    /* Third child is the region offset */
523
524    Next = Next->Asl.Next;
525
526    /* Fourth child is the region length */
527
528    Next = Next->Asl.Next;
529    if (Next->Asl.ParseOpcode == PARSEOP_INTEGER)
530    {
531        Op->Asl.Value.Integer = Next->Asl.Value.Integer;
532    }
533    else
534    {
535        Op->Asl.Value.Integer = ACPI_UINT64_MAX;
536    }
537}
538
539
540/*******************************************************************************
541 *
542 * FUNCTION:    OpnDoBuffer
543 *
544 * PARAMETERS:  Op        - The parent parse node
545 *
546 * RETURN:      None
547 *
548 * DESCRIPTION: Construct the AML operands for the BUFFER ASL keyword.  We
549 *              build a single raw byte buffer from the initialization nodes,
550 *              each parse node contains a buffer byte.
551 *
552 ******************************************************************************/
553
554static void
555OpnDoBuffer (
556    ACPI_PARSE_OBJECT       *Op)
557{
558    ACPI_PARSE_OBJECT       *InitializerOp;
559    ACPI_PARSE_OBJECT       *BufferLengthOp;
560
561    /* Optional arguments for this opcode with defaults */
562
563    UINT32                  BufferLength = 0;
564
565
566    /* Opcode and package length first */
567    /* Buffer Length is next, followed by the initializer list */
568
569    BufferLengthOp = Op->Asl.Child;
570    InitializerOp = BufferLengthOp->Asl.Next;
571
572    /*
573     * If the BufferLength is not an INTEGER or was not specified in the ASL
574     * (DEFAULT_ARG), it is a TermArg that is
575     * evaluated at run-time, and we are therefore finished.
576     */
577    if ((BufferLengthOp->Asl.ParseOpcode != PARSEOP_INTEGER) &&
578        (BufferLengthOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
579    {
580        return;
581    }
582
583    /*
584     * We want to count the number of items in the initializer list, because if
585     * it is larger than the buffer length, we will define the buffer size
586     * to be the size of the initializer list (as per the ACPI Specification)
587     */
588    switch (InitializerOp->Asl.ParseOpcode)
589    {
590    case PARSEOP_INTEGER:
591    case PARSEOP_BYTECONST:
592    case PARSEOP_WORDCONST:
593    case PARSEOP_DWORDCONST:
594
595        /* The peer list contains the byte list (if any...) */
596
597        while (InitializerOp)
598        {
599            /* For buffers, this is a list of raw bytes */
600
601            InitializerOp->Asl.AmlOpcode      = AML_RAW_DATA_BYTE;
602            InitializerOp->Asl.AmlLength      = 1;
603            InitializerOp->Asl.ParseOpcode    = PARSEOP_RAW_DATA;
604
605            BufferLength++;
606            InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
607        }
608        break;
609
610
611    case PARSEOP_STRING_LITERAL:
612
613        /*
614         * Only one initializer, the string.  Buffer must be big enough to hold
615         * the string plus the null termination byte
616         */
617        BufferLength = strlen (InitializerOp->Asl.Value.String) + 1;
618
619        InitializerOp->Asl.AmlOpcode      = AML_RAW_DATA_BUFFER;
620        InitializerOp->Asl.AmlLength      = BufferLength;
621        InitializerOp->Asl.ParseOpcode    = PARSEOP_RAW_DATA;
622        break;
623
624
625    case PARSEOP_RAW_DATA:
626
627        /* Buffer nodes are already initialized (e.g. Unicode operator) */
628        return;
629
630
631    case PARSEOP_DEFAULT_ARG:
632        break;
633
634
635    default:
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 = ACPI_ALLOCATE (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    }
925    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
926
927    /* Signature */
928
929    Child = Child->Asl.Next;
930    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
931    if (Child->Asl.Value.String)
932    {
933        Gbl_TableSignature = Child->Asl.Value.String;
934        if (ACPI_STRLEN (Gbl_TableSignature) != 4)
935        {
936            AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
937                "Length not exactly 4");
938        }
939
940        for (i = 0; i < 4; i++)
941        {
942            if (!isalnum ((int) Gbl_TableSignature[i]))
943            {
944                AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
945                    "Contains non-alphanumeric characters");
946            }
947        }
948    }
949
950    /* Revision */
951
952    Child = Child->Asl.Next;
953    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
954    /*
955     * We used the revision to set the integer width earlier
956     */
957
958    /* OEMID */
959
960    Child = Child->Asl.Next;
961    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
962
963    /* OEM TableID */
964
965    Child = Child->Asl.Next;
966    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
967    if (Child->Asl.Value.String)
968    {
969        Length = ACPI_STRLEN (Child->Asl.Value.String);
970        Gbl_TableId = AcpiOsAllocate (Length + 1);
971        ACPI_STRCPY (Gbl_TableId, Child->Asl.Value.String);
972
973        for (i = 0; i < Length; i++)
974        {
975            if (Gbl_TableId[i] == ' ')
976            {
977                Gbl_TableId[i] = 0;
978                break;
979            }
980        }
981    }
982
983    /* OEM Revision */
984
985    Child = Child->Asl.Next;
986    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
987}
988
989
990/*******************************************************************************
991 *
992 * FUNCTION:    UtGetArg
993 *
994 * PARAMETERS:  Op              - Get an argument for this op
995 *              Argn            - Nth argument to get
996 *
997 * RETURN:      The argument (as an Op object).  NULL if argument does not exist
998 *
999 * DESCRIPTION: Get the specified op's argument (peer)
1000 *
1001 ******************************************************************************/
1002
1003ACPI_PARSE_OBJECT *
1004UtGetArg (
1005    ACPI_PARSE_OBJECT       *Op,
1006    UINT32                  Argn)
1007{
1008    ACPI_PARSE_OBJECT       *Arg = NULL;
1009
1010
1011    /* Get the requested argument object */
1012
1013    Arg = Op->Asl.Child;
1014    while (Arg && Argn)
1015    {
1016        Argn--;
1017        Arg = Arg->Asl.Next;
1018    }
1019
1020    return (Arg);
1021}
1022
1023
1024/*******************************************************************************
1025 *
1026 * FUNCTION:    OpnAttachNameToNode
1027 *
1028 * PARAMETERS:  Op        - The parent parse node
1029 *
1030 * RETURN:      None
1031 *
1032 * DESCRIPTION: For the named ASL/AML operators, get the actual name from the
1033 *              argument list and attach it to the parent node so that we
1034 *              can get to it quickly later.
1035 *
1036 ******************************************************************************/
1037
1038static void
1039OpnAttachNameToNode (
1040    ACPI_PARSE_OBJECT       *Op)
1041{
1042    ACPI_PARSE_OBJECT       *Child = NULL;
1043
1044
1045    if (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)
1046    {
1047        Child = UtGetArg (Op, 0);
1048    }
1049    else switch (Op->Asl.AmlOpcode)
1050    {
1051    case AML_DATA_REGION_OP:
1052    case AML_DEVICE_OP:
1053    case AML_EVENT_OP:
1054    case AML_METHOD_OP:
1055    case AML_MUTEX_OP:
1056    case AML_REGION_OP:
1057    case AML_POWER_RES_OP:
1058    case AML_PROCESSOR_OP:
1059    case AML_THERMAL_ZONE_OP:
1060    case AML_NAME_OP:
1061    case AML_SCOPE_OP:
1062
1063        Child = UtGetArg (Op, 0);
1064        break;
1065
1066    case AML_ALIAS_OP:
1067
1068        Child = UtGetArg (Op, 1);
1069        break;
1070
1071    case AML_CREATE_BIT_FIELD_OP:
1072    case AML_CREATE_BYTE_FIELD_OP:
1073    case AML_CREATE_WORD_FIELD_OP:
1074    case AML_CREATE_DWORD_FIELD_OP:
1075    case AML_CREATE_QWORD_FIELD_OP:
1076
1077        Child = UtGetArg (Op, 2);
1078        break;
1079
1080    case AML_CREATE_FIELD_OP:
1081
1082        Child = UtGetArg (Op, 3);
1083        break;
1084
1085    case AML_BANK_FIELD_OP:
1086    case AML_INDEX_FIELD_OP:
1087    case AML_FIELD_OP:
1088
1089        return;
1090
1091    default:
1092        return;
1093    }
1094
1095    if (Child)
1096    {
1097        UtAttachNamepathToOwner (Op, Child);
1098    }
1099}
1100
1101
1102/*******************************************************************************
1103 *
1104 * FUNCTION:    OpnGenerateAmlOperands
1105 *
1106 * PARAMETERS:  Op        - The parent parse node
1107 *
1108 * RETURN:      None
1109 *
1110 * DESCRIPTION: Prepare nodes to be output as AML data and operands.  The more
1111 *              complex AML opcodes require processing of the child nodes
1112 *              (arguments/operands).
1113 *
1114 ******************************************************************************/
1115
1116void
1117OpnGenerateAmlOperands (
1118    ACPI_PARSE_OBJECT       *Op)
1119{
1120
1121
1122    if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)
1123    {
1124        return;
1125    }
1126
1127    switch (Op->Asl.ParseOpcode)
1128    {
1129    case PARSEOP_DEFINITIONBLOCK:
1130        OpnDoDefinitionBlock (Op);
1131        break;
1132
1133    case PARSEOP_METHOD:
1134        OpnDoMethod (Op);
1135        break;
1136
1137    case PARSEOP_MUTEX:
1138        OpnDoMutex (Op);
1139        break;
1140
1141    case PARSEOP_FIELD:
1142        OpnDoField (Op);
1143        break;
1144
1145    case PARSEOP_INDEXFIELD:
1146        OpnDoIndexField (Op);
1147        break;
1148
1149    case PARSEOP_BANKFIELD:
1150        OpnDoBankField (Op);
1151        break;
1152
1153    case PARSEOP_BUFFER:
1154        OpnDoBuffer (Op);
1155        break;
1156
1157    case PARSEOP_LOADTABLE:
1158        OpnDoLoadTable (Op);
1159        break;
1160
1161    case PARSEOP_OPERATIONREGION:
1162        OpnDoRegion (Op);
1163        break;
1164
1165    case PARSEOP_RESOURCETEMPLATE:
1166        RsDoResourceTemplate (Op);
1167        break;
1168
1169    case PARSEOP_NAMESEG:
1170    case PARSEOP_NAMESTRING:
1171    case PARSEOP_METHODCALL:
1172    case PARSEOP_STRING_LITERAL:
1173        break;
1174
1175    default:
1176        break;
1177    }
1178
1179    /* TBD: move */
1180
1181    OpnAttachNameToNode (Op);
1182}
1183
1184
1185