1/******************************************************************************
2 *
3 * Module Name: asloperands - AML operand processing
4 *
5 *****************************************************************************/
6
7/******************************************************************************
8 *
9 * 1. Copyright Notice
10 *
11 * Some or all of this work - Copyright (c) 1999 - 2017, Intel Corp.
12 * All rights reserved.
13 *
14 * 2. License
15 *
16 * 2.1. This is your license from Intel Corp. under its intellectual property
17 * rights. You may have additional license terms from the party that provided
18 * you this software, covering your right to use that party's intellectual
19 * property rights.
20 *
21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22 * copy of the source code appearing in this file ("Covered Code") an
23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24 * base code distributed originally by Intel ("Original Intel Code") to copy,
25 * make derivatives, distribute, use and display any portion of the Covered
26 * Code in any form, with the right to sublicense such rights; and
27 *
28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29 * license (with the right to sublicense), under only those claims of Intel
30 * patents that are infringed by the Original Intel Code, to make, use, sell,
31 * offer to sell, and import the Covered Code and derivative works thereof
32 * solely to the minimum extent necessary to exercise the above copyright
33 * license, and in no event shall the patent license extend to any additions
34 * to or modifications of the Original Intel Code. No other license or right
35 * is granted directly or by implication, estoppel or otherwise;
36 *
37 * The above copyright and patent license is granted only if the following
38 * conditions are met:
39 *
40 * 3. Conditions
41 *
42 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43 * Redistribution of source code of any substantial portion of the Covered
44 * Code or modification with rights to further distribute source must include
45 * the above Copyright Notice, the above License, this list of Conditions,
46 * and the following Disclaimer and Export Compliance provision. In addition,
47 * Licensee must cause all Covered Code to which Licensee contributes to
48 * contain a file documenting the changes Licensee made to create that Covered
49 * Code and the date of any change. Licensee must include in that file the
50 * documentation of any changes made by any predecessor Licensee. Licensee
51 * must include a prominent statement that the modification is derived,
52 * directly or indirectly, from Original Intel Code.
53 *
54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55 * Redistribution of source code of any substantial portion of the Covered
56 * Code or modification without rights to further distribute source must
57 * include the following Disclaimer and Export Compliance provision in the
58 * documentation and/or other materials provided with distribution. In
59 * addition, Licensee may not authorize further sublicense of source of any
60 * portion of the Covered Code, and must include terms to the effect that the
61 * license from Licensee to its licensee is limited to the intellectual
62 * property embodied in the software Licensee provides to its licensee, and
63 * not to intellectual property embodied in modifications its licensee may
64 * make.
65 *
66 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67 * substantial portion of the Covered Code or modification must reproduce the
68 * above Copyright Notice, and the following Disclaimer and Export Compliance
69 * provision in the documentation and/or other materials provided with the
70 * distribution.
71 *
72 * 3.4. Intel retains all right, title, and interest in and to the Original
73 * Intel Code.
74 *
75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76 * Intel shall be used in advertising or otherwise to promote the sale, use or
77 * other dealings in products derived from or relating to the Covered Code
78 * without prior written authorization from Intel.
79 *
80 * 4. Disclaimer and Export Compliance
81 *
82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88 * PARTICULAR PURPOSE.
89 *
90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97 * LIMITED REMEDY.
98 *
99 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100 * software or system incorporating such software without first obtaining any
101 * required license or other approval from the U. S. Department of Commerce or
102 * any other agency or department of the United States Government. In the
103 * event Licensee exports any such software from the United States or
104 * re-exports any such software from a foreign destination, Licensee shall
105 * ensure that the distribution and export/re-export of the software is in
106 * compliance with all laws, regulations, orders, or other restrictions of the
107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108 * any of its subsidiaries will export/re-export any technical data, process,
109 * software, or service, directly or indirectly, to any country for which the
110 * United States government or any agency thereof requires an export license,
111 * other governmental approval, or letter of assurance, without first obtaining
112 * such license, approval or letter.
113 *
114 *****************************************************************************
115 *
116 * Alternatively, you may choose to be licensed under the terms of the
117 * following license:
118 *
119 * Redistribution and use in source and binary forms, with or without
120 * modification, are permitted provided that the following conditions
121 * are met:
122 * 1. Redistributions of source code must retain the above copyright
123 *    notice, this list of conditions, and the following disclaimer,
124 *    without modification.
125 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126 *    substantially similar to the "NO WARRANTY" disclaimer below
127 *    ("Disclaimer") and any redistribution must be conditioned upon
128 *    including a substantially similar Disclaimer requirement for further
129 *    binary redistribution.
130 * 3. Neither the names of the above-listed copyright holders nor the names
131 *    of any contributors may be used to endorse or promote products derived
132 *    from this software without specific prior written permission.
133 *
134 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145 *
146 * Alternatively, you may choose to be licensed under the terms of the
147 * GNU General Public License ("GPL") version 2 as published by the Free
148 * Software Foundation.
149 *
150 *****************************************************************************/
151
152#include <contrib/dev/acpica/compiler/aslcompiler.h>
153#include "aslcompiler.y.h"
154#include <contrib/dev/acpica/include/amlcode.h>
155
156#define _COMPONENT          ACPI_COMPILER
157        ACPI_MODULE_NAME    ("asloperands")
158
159/* Local prototypes */
160
161static void
162OpnDoField (
163    ACPI_PARSE_OBJECT       *Op);
164
165static void
166OpnDoBankField (
167    ACPI_PARSE_OBJECT       *Op);
168
169static void
170OpnDoBuffer (
171    ACPI_PARSE_OBJECT       *Op);
172
173static void
174OpnDoDefinitionBlock (
175    ACPI_PARSE_OBJECT       *Op);
176
177static void
178OpnDoFieldCommon (
179    ACPI_PARSE_OBJECT       *FieldOp,
180    ACPI_PARSE_OBJECT       *Op);
181
182static void
183OpnDoIndexField (
184    ACPI_PARSE_OBJECT       *Op);
185
186static void
187OpnDoLoadTable (
188    ACPI_PARSE_OBJECT       *Op);
189
190static void
191OpnDoMethod (
192    ACPI_PARSE_OBJECT       *Op);
193
194static void
195OpnDoMutex (
196    ACPI_PARSE_OBJECT       *Op);
197
198static void
199OpnDoRegion (
200    ACPI_PARSE_OBJECT       *Op);
201
202static void
203OpnAttachNameToNode (
204    ACPI_PARSE_OBJECT       *Op);
205
206
207/*******************************************************************************
208 *
209 * FUNCTION:    OpnDoMutex
210 *
211 * PARAMETERS:  Op        - The parent parse node
212 *
213 * RETURN:      None
214 *
215 * DESCRIPTION: Construct the operands for the MUTEX ASL keyword.
216 *
217 ******************************************************************************/
218
219static void
220OpnDoMutex (
221    ACPI_PARSE_OBJECT       *Op)
222{
223    ACPI_PARSE_OBJECT       *Next;
224
225
226    Next = Op->Asl.Child;
227    Next = Next->Asl.Next;
228
229    if (Next->Asl.Value.Integer > 15)
230    {
231        AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
232    }
233    return;
234}
235
236
237/*******************************************************************************
238 *
239 * FUNCTION:    OpnDoMethod
240 *
241 * PARAMETERS:  Op        - The parent parse node
242 *
243 * RETURN:      None
244 *
245 * DESCRIPTION: Construct the operands for the METHOD ASL keyword.
246 *
247 ******************************************************************************/
248
249static void
250OpnDoMethod (
251    ACPI_PARSE_OBJECT       *Op)
252{
253    ACPI_PARSE_OBJECT       *Next;
254
255    /* Optional arguments for this opcode with defaults */
256
257    UINT8                   NumArgs = 0;
258    UINT8                   Serialized = 0;
259    UINT8                   Concurrency = 0;
260    UINT8                   MethodFlags;
261
262
263    /* Opcode and package length first */
264    /* Method name */
265
266    Next = Op->Asl.Child;
267
268    /* Num args */
269
270    Next = Next->Asl.Next;
271    if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
272    {
273        NumArgs = (UINT8) Next->Asl.Value.Integer;
274        Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
275    }
276
277    /* Serialized Flag */
278
279    Next = Next->Asl.Next;
280    if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
281    {
282        Serialized = (UINT8) Next->Asl.Value.Integer;
283        Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
284    }
285
286    /* Concurrency value (valid values are 0-15) */
287
288    Next = Next->Asl.Next;
289    if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
290    {
291        /* This is a ByteConstExpr, so eval the constant now */
292
293        OpcAmlConstantWalk (Next, 0, NULL);
294
295        if (Next->Asl.Value.Integer > 15)
296        {
297            AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
298        }
299
300        Concurrency = (UINT8) Next->Asl.Value.Integer;
301    }
302
303    /* Put the bits in their proper places */
304
305    MethodFlags = (UINT8)
306        ((NumArgs & 0x7) |
307        ((Serialized & 0x1) << 3) |
308        ((Concurrency & 0xF) << 4));
309
310    /* Use the last node for the combined flags byte */
311
312    Next->Asl.Value.Integer = MethodFlags;
313    Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
314    Next->Asl.AmlLength = 1;
315    Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
316
317    /* Save the arg count in the first node */
318
319    Op->Asl.Extra = NumArgs;
320}
321
322
323/*******************************************************************************
324 *
325 * FUNCTION:    OpnDoFieldCommon
326 *
327 * PARAMETERS:  FieldOp       - Node for an ASL field
328 *              Op            - The parent parse node
329 *
330 * RETURN:      None
331 *
332 * DESCRIPTION: Construct the AML operands for the various field keywords,
333 *              FIELD, BANKFIELD, INDEXFIELD
334 *
335 ******************************************************************************/
336
337static void
338OpnDoFieldCommon (
339    ACPI_PARSE_OBJECT       *FieldOp,
340    ACPI_PARSE_OBJECT       *Op)
341{
342    ACPI_PARSE_OBJECT       *Next;
343    ACPI_PARSE_OBJECT       *PkgLengthNode;
344    UINT32                  CurrentBitOffset;
345    UINT32                  NewBitOffset;
346    UINT8                   AccessType;
347    UINT8                   LockRule;
348    UINT8                   UpdateRule;
349    UINT8                   FieldFlags;
350    UINT32                  MinimumLength;
351
352
353    /* AccessType -- not optional, so no need to check for DEFAULT_ARG */
354
355    AccessType = (UINT8) Op->Asl.Value.Integer;
356    Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
357
358    /* Set the access type in the parent (field) node for use later */
359
360    FieldOp->Asl.Value.Integer = AccessType;
361
362    /* LockRule -- not optional, so no need to check for DEFAULT_ARG */
363
364    Next = Op->Asl.Next;
365    LockRule = (UINT8) Next->Asl.Value.Integer;
366    Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
367
368    /* UpdateRule -- not optional, so no need to check for DEFAULT_ARG */
369
370    Next = Next->Asl.Next;
371    UpdateRule = (UINT8) Next->Asl.Value.Integer;
372
373    /*
374     * Generate the flags byte. The various fields are already
375     * in the right bit position via translation from the
376     * keywords by the parser.
377     */
378    FieldFlags = (UINT8) (AccessType | LockRule | UpdateRule);
379
380    /* Use the previous node to be the FieldFlags node */
381
382    /* Set the node to RAW_DATA */
383
384    Next->Asl.Value.Integer = FieldFlags;
385    Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
386    Next->Asl.AmlLength = 1;
387    Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
388
389    /* Process the FieldUnitList */
390
391    Next = Next->Asl.Next;
392    CurrentBitOffset = 0;
393
394    while (Next)
395    {
396        /* Save the offset of this field unit */
397
398        Next->Asl.ExtraValue = CurrentBitOffset;
399
400        switch (Next->Asl.ParseOpcode)
401        {
402        case PARSEOP_ACCESSAS:
403
404            PkgLengthNode = Next->Asl.Child;
405            AccessType = (UINT8) PkgLengthNode->Asl.Value.Integer;
406
407            /* Nothing additional to do */
408            break;
409
410        case PARSEOP_OFFSET:
411
412            /* New offset into the field */
413
414            PkgLengthNode = Next->Asl.Child;
415            NewBitOffset = ((UINT32) PkgLengthNode->Asl.Value.Integer) * 8;
416
417            /*
418             * Examine the specified offset in relation to the
419             * current offset counter.
420             */
421            if (NewBitOffset < CurrentBitOffset)
422            {
423                /*
424                 * Not allowed to specify a backwards offset!
425                 * Issue error and ignore this node.
426                 */
427                AslError (ASL_ERROR, ASL_MSG_BACKWARDS_OFFSET, PkgLengthNode,
428                    NULL);
429                Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
430                PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
431            }
432            else if ((NewBitOffset == CurrentBitOffset) && Gbl_OptimizeTrivialParseNodes)
433            {
434                /*
435                 * Offset is redundant; we don't need to output an
436                 * offset opcode. Just set these nodes to default
437                 */
438                Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
439                PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
440            }
441            else
442            {
443                /*
444                 * Valid new offset - set the value to be inserted into the AML
445                 * and update the offset counter.
446                 */
447                PkgLengthNode->Asl.Value.Integer =
448                    NewBitOffset - CurrentBitOffset;
449                CurrentBitOffset = NewBitOffset;
450            }
451            break;
452
453        case PARSEOP_NAMESEG:
454        case PARSEOP_RESERVED_BYTES:
455
456            /* Named or reserved field entry */
457
458            PkgLengthNode = Next->Asl.Child;
459            NewBitOffset = (UINT32) PkgLengthNode->Asl.Value.Integer;
460            CurrentBitOffset += NewBitOffset;
461
462            if ((NewBitOffset == 0) &&
463                (Next->Asl.ParseOpcode == PARSEOP_RESERVED_BYTES) &&
464                Gbl_OptimizeTrivialParseNodes)
465            {
466                /*
467                 * Unnamed field with a bit length of zero. We can
468                 * safely just ignore this. However, we will not ignore
469                 * a named field of zero length, we don't want to just
470                 * toss out a name.
471                 */
472                Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
473                PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
474                break;
475            }
476
477            /* Save the current AccessAs value for error checking later */
478
479            switch (AccessType)
480            {
481                case AML_FIELD_ACCESS_ANY:
482                case AML_FIELD_ACCESS_BYTE:
483                case AML_FIELD_ACCESS_BUFFER:
484                default:
485
486                    MinimumLength = 8;
487                    break;
488
489                case AML_FIELD_ACCESS_WORD:
490                    MinimumLength = 16;
491                    break;
492
493                case AML_FIELD_ACCESS_DWORD:
494                    MinimumLength = 32;
495                    break;
496
497                case AML_FIELD_ACCESS_QWORD:
498                    MinimumLength = 64;
499                    break;
500            }
501
502            PkgLengthNode->Asl.ExtraValue = MinimumLength;
503            break;
504
505        default:
506
507            /* All supported field opcodes must appear above */
508
509            break;
510        }
511
512        /* Move on to next entry in the field list */
513
514        Next = Next->Asl.Next;
515    }
516}
517
518
519/*******************************************************************************
520 *
521 * FUNCTION:    OpnDoField
522 *
523 * PARAMETERS:  Op        - The parent parse node
524 *
525 * RETURN:      None
526 *
527 * DESCRIPTION: Construct the AML operands for the FIELD ASL keyword
528 *
529 ******************************************************************************/
530
531static void
532OpnDoField (
533    ACPI_PARSE_OBJECT       *Op)
534{
535    ACPI_PARSE_OBJECT       *Next;
536
537
538    /* Opcode is parent node */
539    /* First child is field name */
540
541    Next = Op->Asl.Child;
542
543    /* Second child is the AccessType */
544
545    OpnDoFieldCommon (Op, Next->Asl.Next);
546}
547
548
549/*******************************************************************************
550 *
551 * FUNCTION:    OpnDoIndexField
552 *
553 * PARAMETERS:  Op        - The parent parse node
554 *
555 * RETURN:      None
556 *
557 * DESCRIPTION: Construct the AML operands for the INDEXFIELD ASL keyword
558 *
559 ******************************************************************************/
560
561static void
562OpnDoIndexField (
563    ACPI_PARSE_OBJECT       *Op)
564{
565    ACPI_PARSE_OBJECT       *Next;
566
567
568    /* Opcode is parent node */
569    /* First child is the index name */
570
571    Next = Op->Asl.Child;
572
573    /* Second child is the data name */
574
575    Next = Next->Asl.Next;
576
577    /* Third child is the AccessType */
578
579    OpnDoFieldCommon (Op, Next->Asl.Next);
580}
581
582
583/*******************************************************************************
584 *
585 * FUNCTION:    OpnDoBankField
586 *
587 * PARAMETERS:  Op        - The parent parse node
588 *
589 * RETURN:      None
590 *
591 * DESCRIPTION: Construct the AML operands for the BANKFIELD ASL keyword
592 *
593 ******************************************************************************/
594
595static void
596OpnDoBankField (
597    ACPI_PARSE_OBJECT       *Op)
598{
599    ACPI_PARSE_OBJECT       *Next;
600
601
602    /* Opcode is parent node */
603    /* First child is the region name */
604
605    Next = Op->Asl.Child;
606
607    /* Second child is the bank name */
608
609    Next = Next->Asl.Next;
610
611    /* Third child is the bank value */
612
613    Next = Next->Asl.Next;
614
615    /* Fourth child is the AccessType */
616
617    OpnDoFieldCommon (Op, Next->Asl.Next);
618}
619
620
621/*******************************************************************************
622 *
623 * FUNCTION:    OpnDoRegion
624 *
625 * PARAMETERS:  Op        - The parent parse node
626 *
627 * RETURN:      None
628 *
629 * DESCRIPTION: Tries to get the length of the region. Can only do this at
630 *              compile time if the length is a constant.
631 *
632 ******************************************************************************/
633
634static void
635OpnDoRegion (
636    ACPI_PARSE_OBJECT       *Op)
637{
638    ACPI_PARSE_OBJECT       *Next;
639
640
641    /* Opcode is parent node */
642    /* First child is the region name */
643
644    Next = Op->Asl.Child;
645
646    /* Second child is the space ID*/
647
648    Next = Next->Asl.Next;
649
650    /* Third child is the region offset */
651
652    Next = Next->Asl.Next;
653
654    /* Fourth child is the region length */
655
656    Next = Next->Asl.Next;
657    if (Next->Asl.ParseOpcode == PARSEOP_INTEGER)
658    {
659        Op->Asl.Value.Integer = Next->Asl.Value.Integer;
660    }
661    else
662    {
663        Op->Asl.Value.Integer = ACPI_UINT64_MAX;
664    }
665}
666
667
668/*******************************************************************************
669 *
670 * FUNCTION:    OpnDoBuffer
671 *
672 * PARAMETERS:  Op        - The parent parse node
673 *
674 * RETURN:      None
675 *
676 * DESCRIPTION: Construct the AML operands for the BUFFER ASL keyword. We
677 *              build a single raw byte buffer from the initialization nodes,
678 *              each parse node contains a buffer byte.
679 *
680 ******************************************************************************/
681
682static void
683OpnDoBuffer (
684    ACPI_PARSE_OBJECT       *Op)
685{
686    ACPI_PARSE_OBJECT       *InitializerOp;
687    ACPI_PARSE_OBJECT       *BufferLengthOp;
688
689    /* Optional arguments for this opcode with defaults */
690
691    UINT32                  BufferLength = 0;
692
693
694    /* Opcode and package length first */
695    /* Buffer Length is next, followed by the initializer list */
696
697    BufferLengthOp = Op->Asl.Child;
698    InitializerOp = BufferLengthOp->Asl.Next;
699
700    /*
701     * If the BufferLength is not an INTEGER or was not specified in the ASL
702     * (DEFAULT_ARG), it is a TermArg that is
703     * evaluated at run-time, and we are therefore finished.
704     */
705    if ((BufferLengthOp->Asl.ParseOpcode != PARSEOP_INTEGER) &&
706        (BufferLengthOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
707    {
708        return;
709    }
710
711    /*
712     * We want to count the number of items in the initializer list, because if
713     * it is larger than the buffer length, we will define the buffer size
714     * to be the size of the initializer list (as per the ACPI Specification)
715     */
716    switch (InitializerOp->Asl.ParseOpcode)
717    {
718    case PARSEOP_INTEGER:
719    case PARSEOP_BYTECONST:
720    case PARSEOP_WORDCONST:
721    case PARSEOP_DWORDCONST:
722
723        /* The peer list contains the byte list (if any...) */
724
725        while (InitializerOp)
726        {
727            /* For buffers, this is a list of raw bytes */
728
729            InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
730            InitializerOp->Asl.AmlLength = 1;
731            InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
732
733            BufferLength++;
734            InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
735        }
736        break;
737
738    case PARSEOP_STRING_LITERAL:
739
740        /*
741         * Only one initializer, the string. Buffer must be big enough to hold
742         * the string plus the null termination byte
743         */
744        BufferLength = strlen (InitializerOp->Asl.Value.String) + 1;
745
746        InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
747        InitializerOp->Asl.AmlLength = BufferLength;
748        InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
749        break;
750
751    case PARSEOP_RAW_DATA:
752
753        /* Buffer nodes are already initialized (e.g. Unicode operator) */
754        return;
755
756    case PARSEOP_DEFAULT_ARG:
757        break;
758
759    default:
760
761        AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, InitializerOp,
762            "Unknown buffer initializer opcode");
763        printf ("Unknown buffer initializer opcode [%s]\n",
764            UtGetOpName (InitializerOp->Asl.ParseOpcode));
765        return;
766    }
767
768    /* Check if initializer list is longer than the buffer length */
769
770    if (BufferLengthOp->Asl.Value.Integer > BufferLength)
771    {
772        BufferLength = (UINT32) BufferLengthOp->Asl.Value.Integer;
773    }
774
775    if (!BufferLength)
776    {
777        /* No length AND no items -- issue notice */
778
779        AslError (ASL_REMARK, ASL_MSG_BUFFER_LENGTH, BufferLengthOp, NULL);
780
781        /* But go ahead and put the buffer length of zero into the AML */
782    }
783
784    /*
785     * Just set the buffer size node to be the buffer length, regardless
786     * of whether it was previously an integer or a default_arg placeholder
787     */
788    BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
789    BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP;
790    BufferLengthOp->Asl.Value.Integer = BufferLength;
791
792    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
793
794    /* Remaining nodes are handled via the tree walk */
795}
796
797
798/*******************************************************************************
799 *
800 * FUNCTION:    OpnDoPackage
801 *
802 * PARAMETERS:  Op        - The parent parse node
803 *
804 * RETURN:      None
805 *
806 * DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword. NOTE:
807 *              can only be called after constants have been folded, to ensure
808 *              that the PackageLength operand has been fully reduced.
809 *
810 ******************************************************************************/
811
812void
813OpnDoPackage (
814    ACPI_PARSE_OBJECT       *Op)
815{
816    ACPI_PARSE_OBJECT       *InitializerOp;
817    ACPI_PARSE_OBJECT       *PackageLengthOp;
818    UINT32                  PackageLength = 0;
819
820
821    /* Opcode and package length first, followed by the initializer list */
822
823    PackageLengthOp = Op->Asl.Child;
824    InitializerOp = PackageLengthOp->Asl.Next;
825
826    /* Count the number of items in the initializer list */
827
828    if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
829    {
830        /* The peer list contains the byte list (if any...) */
831
832        while (InitializerOp)
833        {
834            PackageLength++;
835            InitializerOp = InitializerOp->Asl.Next;
836        }
837    }
838
839    /* If package length is a constant, compare to the initializer list */
840
841    if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
842        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST))
843    {
844        if (PackageLengthOp->Asl.Value.Integer > PackageLength)
845        {
846            /*
847             * Allow package length to be longer than the initializer
848             * list -- but if the length of initializer list is nonzero,
849             * issue a message since this is probably a coding error,
850             * even though technically legal.
851             */
852            if (PackageLength > 0)
853            {
854                AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT,
855                    PackageLengthOp, NULL);
856            }
857
858            PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer;
859        }
860        else if (PackageLengthOp->Asl.Value.Integer < PackageLength)
861        {
862            /*
863             * The package length is smaller than the length of the
864             * initializer list. This is an error as per the ACPI spec.
865             */
866            AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG,
867                PackageLengthOp, NULL);
868        }
869    }
870
871    if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
872    {
873        /*
874         * This is the case if the PackageLength was left empty - Package()
875         * The package length becomes the length of the initializer list
876         */
877        Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER;
878        Op->Asl.Child->Asl.Value.Integer = PackageLength;
879
880        /* Set the AML opcode */
881
882        (void) OpcSetOptimalIntegerSize (Op->Asl.Child);
883    }
884
885    /* If not a variable-length package, check for a zero package length */
886
887    if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
888        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST)   ||
889        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_ZERO)         ||
890        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG))
891    {
892        if (!PackageLength)
893        {
894            /* No length AND no initializer list -- issue a remark */
895
896            AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH,
897                PackageLengthOp, NULL);
898
899            /* But go ahead and put the buffer length of zero into the AML */
900        }
901    }
902
903    /*
904     * If the PackageLength is a constant <= 255, we can change the
905     * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode.
906     */
907    if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
908            (Op->Asl.Child->Asl.Value.Integer <= 255))  ||
909        (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) ||
910        (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)||
911        (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO))
912    {
913        Op->Asl.AmlOpcode = AML_PACKAGE_OP;
914        Op->Asl.ParseOpcode = PARSEOP_PACKAGE;
915
916        /*
917         * Just set the package size node to be the package length, regardless
918         * of whether it was previously an integer or a default_arg placeholder
919         */
920        PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
921        PackageLengthOp->Asl.AmlLength = 1;
922        PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
923        PackageLengthOp->Asl.Value.Integer = PackageLength;
924    }
925
926    /* Remaining nodes are handled via the tree walk */
927}
928
929
930/*******************************************************************************
931 *
932 * FUNCTION:    OpnDoLoadTable
933 *
934 * PARAMETERS:  Op        - The parent parse node
935 *
936 * RETURN:      None
937 *
938 * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword.
939 *
940 ******************************************************************************/
941
942static void
943OpnDoLoadTable (
944    ACPI_PARSE_OBJECT       *Op)
945{
946    ACPI_PARSE_OBJECT       *Next;
947
948
949    /* Opcode is parent node */
950    /* First child is the table signature */
951
952    Next = Op->Asl.Child;
953
954    /* Second child is the OEM ID*/
955
956    Next = Next->Asl.Next;
957
958    /* Third child is the OEM table ID */
959
960    Next = Next->Asl.Next;
961
962    /* Fourth child is the RootPath string */
963
964    Next = Next->Asl.Next;
965    if (Next->Asl.ParseOpcode == PARSEOP_ZERO)
966    {
967        Next->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
968        Next->Asl.Value.String = "\\";
969        Next->Asl.AmlLength = 2;
970        OpcGenerateAmlOpcode (Next);
971    }
972
973#ifdef ASL_FUTURE_IMPLEMENTATION
974
975    /* TBD: NOT IMPLEMENTED */
976    /* Fifth child is the [optional] ParameterPathString */
977    /* Sixth child is the [optional] ParameterData */
978
979    Next = Next->Asl.Next;
980    if (Next->Asl.ParseOpcode == DEFAULT_ARG)
981    {
982        Next->Asl.AmlLength = 1;
983        Next->Asl.ParseOpcode = ZERO;
984        OpcGenerateAmlOpcode (Next);
985    }
986
987
988    Next = Next->Asl.Next;
989    if (Next->Asl.ParseOpcode == DEFAULT_ARG)
990    {
991        Next->Asl.AmlLength = 1;
992        Next->Asl.ParseOpcode = ZERO;
993        OpcGenerateAmlOpcode (Next);
994    }
995#endif
996}
997
998
999/*******************************************************************************
1000 *
1001 * FUNCTION:    OpnDoDefinitionBlock
1002 *
1003 * PARAMETERS:  Op        - The parent parse node
1004 *
1005 * RETURN:      None
1006 *
1007 * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword
1008 *
1009 ******************************************************************************/
1010
1011static void
1012OpnDoDefinitionBlock (
1013    ACPI_PARSE_OBJECT       *Op)
1014{
1015    ACPI_PARSE_OBJECT       *Child;
1016    ACPI_SIZE               Length;
1017    UINT32                  i;
1018    char                    *Filename;
1019
1020
1021    /*
1022     * These nodes get stuffed into the table header. They are special
1023     * cased when the table is written to the output file.
1024     *
1025     * Mark all of these nodes as non-usable so they won't get output
1026     * as AML opcodes!
1027     */
1028
1029    /* Get AML filename. Use it if non-null */
1030
1031    Child = Op->Asl.Child;
1032    if (Child->Asl.Value.Buffer  &&
1033        *Child->Asl.Value.Buffer &&
1034        (Gbl_UseDefaultAmlFilename))
1035    {
1036        /*
1037         * We will use the AML filename that is embedded in the source file
1038         * for the output filename.
1039         */
1040        Filename = UtLocalCacheCalloc (strlen (Gbl_DirectoryPath) +
1041            strlen ((char *) Child->Asl.Value.Buffer) + 1);
1042
1043        /* Prepend the current directory path */
1044
1045        strcpy (Filename, Gbl_DirectoryPath);
1046        strcat (Filename, (char *) Child->Asl.Value.Buffer);
1047
1048        Gbl_OutputFilenamePrefix = Filename;
1049        UtConvertBackslashes (Gbl_OutputFilenamePrefix);
1050    }
1051
1052    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1053
1054    /* Signature */
1055
1056    Child = Child->Asl.Next;
1057    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1058    if (Child->Asl.Value.String)
1059    {
1060        Gbl_TableSignature = Child->Asl.Value.String;
1061        if (strlen (Gbl_TableSignature) != ACPI_NAME_SIZE)
1062        {
1063            AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
1064                "Length is not exactly 4");
1065        }
1066
1067        for (i = 0; i < ACPI_NAME_SIZE; i++)
1068        {
1069            if (!isalnum ((int) Gbl_TableSignature[i]))
1070            {
1071                AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
1072                    "Contains non-alphanumeric characters");
1073            }
1074        }
1075    }
1076
1077    /* Revision */
1078
1079    Child = Child->Asl.Next;
1080    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1081    /*
1082     * We used the revision to set the integer width earlier
1083     */
1084
1085    /* OEMID */
1086
1087    Child = Child->Asl.Next;
1088    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1089
1090    /* OEM TableID */
1091
1092    Child = Child->Asl.Next;
1093    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1094    if (Child->Asl.Value.String)
1095    {
1096        Length = strlen (Child->Asl.Value.String);
1097        Gbl_TableId = UtLocalCacheCalloc (Length + 1);
1098        strcpy (Gbl_TableId, Child->Asl.Value.String);
1099
1100        /*
1101         * Convert anything non-alphanumeric to an underscore. This
1102         * allows us to use the TableID to generate unique C symbols.
1103         */
1104        for (i = 0; i < Length; i++)
1105        {
1106            if (!isalnum ((int) Gbl_TableId[i]))
1107            {
1108                Gbl_TableId[i] = '_';
1109            }
1110        }
1111    }
1112
1113    /* OEM Revision */
1114
1115    Child = Child->Asl.Next;
1116    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1117}
1118
1119
1120/*******************************************************************************
1121 *
1122 * FUNCTION:    UtGetArg
1123 *
1124 * PARAMETERS:  Op              - Get an argument for this op
1125 *              Argn            - Nth argument to get
1126 *
1127 * RETURN:      The argument (as an Op object). NULL if argument does not exist
1128 *
1129 * DESCRIPTION: Get the specified op's argument (peer)
1130 *
1131 ******************************************************************************/
1132
1133ACPI_PARSE_OBJECT *
1134UtGetArg (
1135    ACPI_PARSE_OBJECT       *Op,
1136    UINT32                  Argn)
1137{
1138    ACPI_PARSE_OBJECT       *Arg = NULL;
1139
1140
1141    /* Get the requested argument object */
1142
1143    Arg = Op->Asl.Child;
1144    while (Arg && Argn)
1145    {
1146        Argn--;
1147        Arg = Arg->Asl.Next;
1148    }
1149
1150    return (Arg);
1151}
1152
1153
1154/*******************************************************************************
1155 *
1156 * FUNCTION:    OpnAttachNameToNode
1157 *
1158 * PARAMETERS:  Op        - The parent parse node
1159 *
1160 * RETURN:      None
1161 *
1162 * DESCRIPTION: For the named ASL/AML operators, get the actual name from the
1163 *              argument list and attach it to the parent node so that we
1164 *              can get to it quickly later.
1165 *
1166 ******************************************************************************/
1167
1168static void
1169OpnAttachNameToNode (
1170    ACPI_PARSE_OBJECT       *Op)
1171{
1172    ACPI_PARSE_OBJECT       *Child = NULL;
1173
1174
1175    switch (Op->Asl.AmlOpcode)
1176    {
1177    case AML_DATA_REGION_OP:
1178    case AML_DEVICE_OP:
1179    case AML_EVENT_OP:
1180    case AML_EXTERNAL_OP:
1181    case AML_METHOD_OP:
1182    case AML_MUTEX_OP:
1183    case AML_REGION_OP:
1184    case AML_POWER_RESOURCE_OP:
1185    case AML_PROCESSOR_OP:
1186    case AML_THERMAL_ZONE_OP:
1187    case AML_NAME_OP:
1188    case AML_SCOPE_OP:
1189
1190        Child = UtGetArg (Op, 0);
1191        break;
1192
1193    case AML_ALIAS_OP:
1194
1195        Child = UtGetArg (Op, 1);
1196        break;
1197
1198    case AML_CREATE_BIT_FIELD_OP:
1199    case AML_CREATE_BYTE_FIELD_OP:
1200    case AML_CREATE_WORD_FIELD_OP:
1201    case AML_CREATE_DWORD_FIELD_OP:
1202    case AML_CREATE_QWORD_FIELD_OP:
1203
1204        Child = UtGetArg (Op, 2);
1205        break;
1206
1207    case AML_CREATE_FIELD_OP:
1208
1209        Child = UtGetArg (Op, 3);
1210        break;
1211
1212    case AML_BANK_FIELD_OP:
1213    case AML_INDEX_FIELD_OP:
1214    case AML_FIELD_OP:
1215
1216        return;
1217
1218    default:
1219
1220        return;
1221    }
1222
1223    if (Child)
1224    {
1225        UtAttachNamepathToOwner (Op, Child);
1226    }
1227}
1228
1229
1230/*******************************************************************************
1231 *
1232 * FUNCTION:    OpnGenerateAmlOperands
1233 *
1234 * PARAMETERS:  Op        - The parent parse node
1235 *
1236 * RETURN:      None
1237 *
1238 * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more
1239 *              complex AML opcodes require processing of the child nodes
1240 *              (arguments/operands).
1241 *
1242 ******************************************************************************/
1243
1244void
1245OpnGenerateAmlOperands (
1246    ACPI_PARSE_OBJECT       *Op)
1247{
1248
1249
1250    if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)
1251    {
1252        return;
1253    }
1254
1255    switch (Op->Asl.ParseOpcode)
1256    {
1257    case PARSEOP_DEFINITION_BLOCK:
1258
1259        OpnDoDefinitionBlock (Op);
1260        break;
1261
1262    case PARSEOP_METHOD:
1263
1264        OpnDoMethod (Op);
1265        break;
1266
1267    case PARSEOP_MUTEX:
1268
1269        OpnDoMutex (Op);
1270        break;
1271
1272    case PARSEOP_FIELD:
1273
1274        OpnDoField (Op);
1275        break;
1276
1277    case PARSEOP_INDEXFIELD:
1278
1279        OpnDoIndexField (Op);
1280        break;
1281
1282    case PARSEOP_BANKFIELD:
1283
1284        OpnDoBankField (Op);
1285        break;
1286
1287    case PARSEOP_BUFFER:
1288
1289        OpnDoBuffer (Op);
1290        break;
1291
1292    case PARSEOP_LOADTABLE:
1293
1294        OpnDoLoadTable (Op);
1295        break;
1296
1297    case PARSEOP_OPERATIONREGION:
1298
1299        OpnDoRegion (Op);
1300        break;
1301
1302    case PARSEOP_RESOURCETEMPLATE:
1303
1304        RsDoResourceTemplate (Op);
1305        break;
1306
1307    case PARSEOP_NAMESEG:
1308    case PARSEOP_NAMESTRING:
1309    case PARSEOP_METHODCALL:
1310    case PARSEOP_STRING_LITERAL:
1311    default:
1312
1313        break;
1314    }
1315
1316    /* TBD: move */
1317
1318    OpnAttachNameToNode (Op);
1319}
1320