asloperands.c revision 256281
1/******************************************************************************
2 *
3 * Module Name: asloperands - AML operand processing
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2013, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <contrib/dev/acpica/compiler/aslcompiler.h>
46#include "aslcompiler.y.h"
47#include <contrib/dev/acpica/include/amlcode.h>
48
49#define _COMPONENT          ACPI_COMPILER
50        ACPI_MODULE_NAME    ("asloperands")
51
52/* Local prototypes */
53
54static void
55OpnDoField (
56    ACPI_PARSE_OBJECT       *Op);
57
58static void
59OpnDoBankField (
60    ACPI_PARSE_OBJECT       *Op);
61
62static void
63OpnDoBuffer (
64    ACPI_PARSE_OBJECT       *Op);
65
66static void
67OpnDoDefinitionBlock (
68    ACPI_PARSE_OBJECT       *Op);
69
70static void
71OpnDoFieldCommon (
72    ACPI_PARSE_OBJECT       *FieldOp,
73    ACPI_PARSE_OBJECT       *Op);
74
75static void
76OpnDoIndexField (
77    ACPI_PARSE_OBJECT       *Op);
78
79static void
80OpnDoLoadTable (
81    ACPI_PARSE_OBJECT       *Op);
82
83static void
84OpnDoMethod (
85    ACPI_PARSE_OBJECT       *Op);
86
87static void
88OpnDoMutex (
89    ACPI_PARSE_OBJECT       *Op);
90
91static void
92OpnDoRegion (
93    ACPI_PARSE_OBJECT       *Op);
94
95static void
96OpnAttachNameToNode (
97    ACPI_PARSE_OBJECT       *Op);
98
99
100/*******************************************************************************
101 *
102 * FUNCTION:    OpnDoMutex
103 *
104 * PARAMETERS:  Op        - The parent parse node
105 *
106 * RETURN:      None
107 *
108 * DESCRIPTION: Construct the operands for the MUTEX ASL keyword.
109 *
110 ******************************************************************************/
111
112static void
113OpnDoMutex (
114    ACPI_PARSE_OBJECT       *Op)
115{
116    ACPI_PARSE_OBJECT       *Next;
117
118
119    Next = Op->Asl.Child;
120    Next = Next->Asl.Next;
121
122    if (Next->Asl.Value.Integer > 15)
123    {
124        AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
125    }
126    return;
127}
128
129
130/*******************************************************************************
131 *
132 * FUNCTION:    OpnDoMethod
133 *
134 * PARAMETERS:  Op        - The parent parse node
135 *
136 * RETURN:      None
137 *
138 * DESCRIPTION: Construct the operands for the METHOD ASL keyword.
139 *
140 ******************************************************************************/
141
142static void
143OpnDoMethod (
144    ACPI_PARSE_OBJECT       *Op)
145{
146    ACPI_PARSE_OBJECT       *Next;
147
148    /* Optional arguments for this opcode with defaults */
149
150    UINT8                   NumArgs = 0;
151    UINT8                   Serialized = 0;
152    UINT8                   Concurrency = 0;
153    UINT8                   MethodFlags;
154
155
156    /* Opcode and package length first */
157    /* Method name */
158
159    Next = Op->Asl.Child;
160
161    /* Num args */
162
163    Next = Next->Asl.Next;
164    if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
165    {
166        NumArgs = (UINT8) Next->Asl.Value.Integer;
167        Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
168    }
169
170    /* Serialized Flag */
171
172    Next = Next->Asl.Next;
173    if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
174    {
175        Serialized = (UINT8) Next->Asl.Value.Integer;
176        Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
177    }
178
179    /* Concurrency value (valid values are 0-15) */
180
181    Next = Next->Asl.Next;
182    if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
183    {
184        /* This is a ByteConstExpr, so eval the constant now */
185
186        OpcAmlConstantWalk (Next, 0, NULL);
187
188        if (Next->Asl.Value.Integer > 15)
189        {
190            AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
191        }
192        Concurrency = (UINT8) Next->Asl.Value.Integer;
193    }
194
195    /* Put the bits in their proper places */
196
197    MethodFlags = (UINT8) ((NumArgs & 0x7) |
198                          ((Serialized & 0x1) << 3) |
199                          ((Concurrency & 0xF) << 4));
200
201    /* Use the last node for the combined flags byte */
202
203    Next->Asl.Value.Integer = MethodFlags;
204    Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
205    Next->Asl.AmlLength = 1;
206    Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
207
208    /* Save the arg count in the first node */
209
210    Op->Asl.Extra = NumArgs;
211}
212
213
214/*******************************************************************************
215 *
216 * FUNCTION:    OpnDoFieldCommon
217 *
218 * PARAMETERS:  FieldOp       - Node for an ASL field
219 *              Op            - The parent parse node
220 *
221 * RETURN:      None
222 *
223 * DESCRIPTION: Construct the AML operands for the various field keywords,
224 *              FIELD, BANKFIELD, INDEXFIELD
225 *
226 ******************************************************************************/
227
228static void
229OpnDoFieldCommon (
230    ACPI_PARSE_OBJECT       *FieldOp,
231    ACPI_PARSE_OBJECT       *Op)
232{
233    ACPI_PARSE_OBJECT       *Next;
234    ACPI_PARSE_OBJECT       *PkgLengthNode;
235    UINT32                  CurrentBitOffset;
236    UINT32                  NewBitOffset;
237    UINT8                   AccessType;
238    UINT8                   LockRule;
239    UINT8                   UpdateRule;
240    UINT8                   FieldFlags;
241    UINT32                  MinimumLength;
242
243
244    /* AccessType -- not optional, so no need to check for DEFAULT_ARG */
245
246    AccessType = (UINT8) Op->Asl.Value.Integer;
247    Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
248
249    /* Set the access type in the parent (field) node for use later */
250
251    FieldOp->Asl.Value.Integer = AccessType;
252
253    /* LockRule -- not optional, so no need to check for DEFAULT_ARG */
254
255    Next = Op->Asl.Next;
256    LockRule = (UINT8) Next->Asl.Value.Integer;
257    Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
258
259    /* UpdateRule -- not optional, so no need to check for DEFAULT_ARG */
260
261    Next = Next->Asl.Next;
262    UpdateRule = (UINT8) Next->Asl.Value.Integer;
263
264    /*
265     * Generate the flags byte. The various fields are already
266     * in the right bit position via translation from the
267     * keywords by the parser.
268     */
269    FieldFlags = (UINT8) (AccessType | LockRule | UpdateRule);
270
271    /* Use the previous node to be the FieldFlags node */
272
273    /* Set the node to RAW_DATA */
274
275    Next->Asl.Value.Integer = FieldFlags;
276    Next->Asl.AmlOpcode     = AML_RAW_DATA_BYTE;
277    Next->Asl.AmlLength     = 1;
278    Next->Asl.ParseOpcode   = PARSEOP_RAW_DATA;
279
280    /* Process the FieldUnitList */
281
282    Next = Next->Asl.Next;
283    CurrentBitOffset = 0;
284
285    while (Next)
286    {
287        /* Save the offset of this field unit */
288
289        Next->Asl.ExtraValue = CurrentBitOffset;
290
291        switch (Next->Asl.ParseOpcode)
292        {
293        case PARSEOP_ACCESSAS:
294
295            PkgLengthNode = Next->Asl.Child;
296            AccessType = (UINT8) PkgLengthNode->Asl.Value.Integer;
297
298            /* Nothing additional to do */
299            break;
300
301        case PARSEOP_OFFSET:
302
303            /* New offset into the field */
304
305            PkgLengthNode = Next->Asl.Child;
306            NewBitOffset = ((UINT32) PkgLengthNode->Asl.Value.Integer) * 8;
307
308            /*
309             * Examine the specified offset in relation to the
310             * current offset counter.
311             */
312            if (NewBitOffset < CurrentBitOffset)
313            {
314                /*
315                 * Not allowed to specify a backwards offset!
316                 * Issue error and ignore this node.
317                 */
318                AslError (ASL_ERROR, ASL_MSG_BACKWARDS_OFFSET, PkgLengthNode,
319                    NULL);
320                Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
321                PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
322            }
323            else if (NewBitOffset == CurrentBitOffset)
324            {
325                /*
326                 * Offset is redundant; we don't need to output an
327                 * offset opcode. Just set these nodes to default
328                 */
329                Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
330                PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
331            }
332            else
333            {
334                /*
335                 * Valid new offset - set the value to be inserted into the AML
336                 * and update the offset counter.
337                 */
338                PkgLengthNode->Asl.Value.Integer =
339                    NewBitOffset - CurrentBitOffset;
340                CurrentBitOffset = NewBitOffset;
341            }
342            break;
343
344        case PARSEOP_NAMESEG:
345        case PARSEOP_RESERVED_BYTES:
346
347            /* Named or reserved field entry */
348
349            PkgLengthNode     = Next->Asl.Child;
350            NewBitOffset      = (UINT32) PkgLengthNode->Asl.Value.Integer;
351            CurrentBitOffset += NewBitOffset;
352
353            /* Save the current AccessAs value for error checking later */
354
355            switch (AccessType)
356            {
357                case AML_FIELD_ACCESS_ANY:
358                case AML_FIELD_ACCESS_BYTE:
359                case AML_FIELD_ACCESS_BUFFER:
360                default:
361
362                    MinimumLength = 8;
363                    break;
364
365                case AML_FIELD_ACCESS_WORD:
366                    MinimumLength = 16;
367                    break;
368
369                case AML_FIELD_ACCESS_DWORD:
370                    MinimumLength = 32;
371                    break;
372
373                case AML_FIELD_ACCESS_QWORD:
374                    MinimumLength = 64;
375                    break;
376            }
377
378            PkgLengthNode->Asl.ExtraValue = MinimumLength;
379            break;
380
381        default:
382
383            /* All supported field opcodes must appear above */
384
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    case PARSEOP_STRING_LITERAL:
615
616        /*
617         * Only one initializer, the string. Buffer must be big enough to hold
618         * the string plus the null termination byte
619         */
620        BufferLength = strlen (InitializerOp->Asl.Value.String) + 1;
621
622        InitializerOp->Asl.AmlOpcode      = AML_RAW_DATA_BUFFER;
623        InitializerOp->Asl.AmlLength      = BufferLength;
624        InitializerOp->Asl.ParseOpcode    = PARSEOP_RAW_DATA;
625        break;
626
627    case PARSEOP_RAW_DATA:
628
629        /* Buffer nodes are already initialized (e.g. Unicode operator) */
630        return;
631
632    case PARSEOP_DEFAULT_ARG:
633        break;
634
635    default:
636
637        AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, InitializerOp,
638            "Unknown buffer initializer opcode");
639        printf ("Unknown buffer initializer opcode [%s]\n",
640                        UtGetOpName (InitializerOp->Asl.ParseOpcode));
641        return;
642    }
643
644    /* Check if initializer list is longer than the buffer length */
645
646    if (BufferLengthOp->Asl.Value.Integer > BufferLength)
647    {
648        BufferLength = (UINT32) BufferLengthOp->Asl.Value.Integer;
649    }
650
651    if (!BufferLength)
652    {
653        /* No length AND no items -- issue notice */
654
655        AslError (ASL_REMARK, ASL_MSG_BUFFER_LENGTH, BufferLengthOp, NULL);
656
657        /* But go ahead and put the buffer length of zero into the AML */
658    }
659
660    /*
661     * Just set the buffer size node to be the buffer length, regardless
662     * of whether it was previously an integer or a default_arg placeholder
663     */
664    BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
665    BufferLengthOp->Asl.AmlOpcode     = AML_DWORD_OP;
666    BufferLengthOp->Asl.Value.Integer = BufferLength;
667
668    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
669
670    /* Remaining nodes are handled via the tree walk */
671}
672
673
674/*******************************************************************************
675 *
676 * FUNCTION:    OpnDoPackage
677 *
678 * PARAMETERS:  Op        - The parent parse node
679 *
680 * RETURN:      None
681 *
682 * DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword. NOTE:
683 *              can only be called after constants have been folded, to ensure
684 *              that the PackageLength operand has been fully reduced.
685 *
686 ******************************************************************************/
687
688void
689OpnDoPackage (
690    ACPI_PARSE_OBJECT       *Op)
691{
692    ACPI_PARSE_OBJECT       *InitializerOp;
693    ACPI_PARSE_OBJECT       *PackageLengthOp;
694    UINT32                  PackageLength = 0;
695
696
697    /* Opcode and package length first, followed by the initializer list */
698
699    PackageLengthOp = Op->Asl.Child;
700    InitializerOp = PackageLengthOp->Asl.Next;
701
702    /* Count the number of items in the initializer list */
703
704    if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
705    {
706        /* The peer list contains the byte list (if any...) */
707
708        while (InitializerOp)
709        {
710            PackageLength++;
711            InitializerOp = InitializerOp->Asl.Next;
712        }
713    }
714
715    /* If package length is a constant, compare to the initializer list */
716
717    if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
718        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST))
719    {
720        if (PackageLengthOp->Asl.Value.Integer > PackageLength)
721        {
722            /*
723             * Allow package length to be longer than the initializer
724             * list -- but if the length of initializer list is nonzero,
725             * issue a message since this is probably a coding error,
726             * even though technically legal.
727             */
728            if (PackageLength > 0)
729            {
730                AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT,
731                    PackageLengthOp, NULL);
732            }
733
734            PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer;
735        }
736        else if (PackageLengthOp->Asl.Value.Integer < PackageLength)
737        {
738            /*
739             * The package length is smaller than the length of the
740             * initializer list. This is an error as per the ACPI spec.
741             */
742            AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG,
743                PackageLengthOp, NULL);
744        }
745    }
746
747    if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
748    {
749        /*
750         * This is the case if the PackageLength was left empty - Package()
751         * The package length becomes the length of the initializer list
752         */
753        Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER;
754        Op->Asl.Child->Asl.Value.Integer = PackageLength;
755
756        /* Set the AML opcode */
757
758        (void) OpcSetOptimalIntegerSize (Op->Asl.Child);
759    }
760
761    /* If not a variable-length package, check for a zero package length */
762
763    if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
764        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST)   ||
765        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_ZERO)         ||
766        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG))
767    {
768        if (!PackageLength)
769        {
770            /* No length AND no initializer list -- issue a remark */
771
772            AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH,
773                PackageLengthOp, NULL);
774
775            /* But go ahead and put the buffer length of zero into the AML */
776        }
777    }
778
779    /*
780     * If the PackageLength is a constant <= 255, we can change the
781     * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode.
782     */
783    if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
784            (Op->Asl.Child->Asl.Value.Integer <= 255))  ||
785        (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) ||
786        (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)||
787        (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO))
788    {
789        Op->Asl.AmlOpcode = AML_PACKAGE_OP;
790        Op->Asl.ParseOpcode = PARSEOP_PACKAGE;
791
792        /*
793         * Just set the package size node to be the package length, regardless
794         * of whether it was previously an integer or a default_arg placeholder
795         */
796        PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
797        PackageLengthOp->Asl.AmlLength = 1;
798        PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
799        PackageLengthOp->Asl.Value.Integer = PackageLength;
800    }
801
802    /* Remaining nodes are handled via the tree walk */
803}
804
805
806/*******************************************************************************
807 *
808 * FUNCTION:    OpnDoLoadTable
809 *
810 * PARAMETERS:  Op        - The parent parse node
811 *
812 * RETURN:      None
813 *
814 * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword.
815 *
816 ******************************************************************************/
817
818static void
819OpnDoLoadTable (
820    ACPI_PARSE_OBJECT       *Op)
821{
822    ACPI_PARSE_OBJECT       *Next;
823
824
825    /* Opcode is parent node */
826    /* First child is the table signature */
827
828    Next = Op->Asl.Child;
829
830    /* Second child is the OEM ID*/
831
832    Next = Next->Asl.Next;
833
834    /* Third child is the OEM table ID */
835
836    Next = Next->Asl.Next;
837
838    /* Fourth child is the RootPath string */
839
840    Next = Next->Asl.Next;
841    if (Next->Asl.ParseOpcode == PARSEOP_ZERO)
842    {
843        Next->Asl.ParseOpcode    = PARSEOP_STRING_LITERAL;
844        Next->Asl.Value.String   = "\\";
845        Next->Asl.AmlLength      = 2;
846        OpcGenerateAmlOpcode (Next);
847    }
848
849#ifdef ASL_FUTURE_IMPLEMENTATION
850
851    /* TBD: NOT IMPLEMENTED */
852    /* Fifth child is the [optional] ParameterPathString */
853    /* Sixth child is the [optional] ParameterData */
854
855    Next = Next->Asl.Next;
856    if (Next->Asl.ParseOpcode == DEFAULT_ARG)
857    {
858        Next->Asl.AmlLength = 1;
859        Next->Asl.ParseOpcode = ZERO;
860        OpcGenerateAmlOpcode (Next);
861    }
862
863
864    Next = Next->Asl.Next;
865    if (Next->Asl.ParseOpcode == DEFAULT_ARG)
866    {
867        Next->Asl.AmlLength = 1;
868        Next->Asl.ParseOpcode = ZERO;
869        OpcGenerateAmlOpcode (Next);
870    }
871#endif
872}
873
874
875/*******************************************************************************
876 *
877 * FUNCTION:    OpnDoDefinitionBlock
878 *
879 * PARAMETERS:  Op        - The parent parse node
880 *
881 * RETURN:      None
882 *
883 * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword
884 *
885 ******************************************************************************/
886
887static void
888OpnDoDefinitionBlock (
889    ACPI_PARSE_OBJECT       *Op)
890{
891    ACPI_PARSE_OBJECT       *Child;
892    ACPI_SIZE               Length;
893    UINT32                  i;
894    char                    *Filename;
895
896
897    /*
898     * These nodes get stuffed into the table header. They are special
899     * cased when the table is written to the output file.
900     *
901     * Mark all of these nodes as non-usable so they won't get output
902     * as AML opcodes!
903     */
904
905    /* Get AML filename. Use it if non-null */
906
907    Child = Op->Asl.Child;
908    if (Child->Asl.Value.Buffer  &&
909        *Child->Asl.Value.Buffer &&
910        (Gbl_UseDefaultAmlFilename))
911    {
912        /*
913         * We will use the AML filename that is embedded in the source file
914         * for the output filename.
915         */
916        Filename = ACPI_ALLOCATE (strlen (Gbl_DirectoryPath) +
917                    strlen ((char *) Child->Asl.Value.Buffer) + 1);
918
919        /* Prepend the current directory path */
920
921        strcpy (Filename, Gbl_DirectoryPath);
922        strcat (Filename, (char *) Child->Asl.Value.Buffer);
923
924        Gbl_OutputFilenamePrefix = Filename;
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 = AcpiOsAllocate (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