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 - 2020, 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)
433            {
434                /*
435                 * This Offset() operator is redundant and not needed,
436                 * because the offset value is the same as the current
437                 * offset.
438                 */
439                AslError (ASL_REMARK, ASL_MSG_OFFSET, PkgLengthNode, NULL);
440
441                if (AslGbl_OptimizeTrivialParseNodes)
442                {
443                    /*
444                     * Optimize this Offset() operator by removing/ignoring
445                     * it. Set the related nodes to default.
446                     */
447                    Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
448                    PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
449
450                    AslError (ASL_OPTIMIZATION, ASL_MSG_OFFSET, PkgLengthNode,
451                        "Optimizer has removed statement");
452                }
453                else
454                {
455                    /* Optimization is disabled, treat as a valid Offset */
456
457                    PkgLengthNode->Asl.Value.Integer =
458                        NewBitOffset - CurrentBitOffset;
459                    CurrentBitOffset = NewBitOffset;
460                }
461            }
462            else
463            {
464                /*
465                 * Valid new offset - set the value to be inserted into the AML
466                 * and update the offset counter.
467                 */
468                PkgLengthNode->Asl.Value.Integer =
469                    NewBitOffset - CurrentBitOffset;
470                CurrentBitOffset = NewBitOffset;
471            }
472            break;
473
474        case PARSEOP_NAMESEG:
475        case PARSEOP_RESERVED_BYTES:
476
477            /* Named or reserved field entry */
478
479            PkgLengthNode = Next->Asl.Child;
480            NewBitOffset = (UINT32) PkgLengthNode->Asl.Value.Integer;
481            CurrentBitOffset += NewBitOffset;
482
483            if ((NewBitOffset == 0) &&
484                (Next->Asl.ParseOpcode == PARSEOP_RESERVED_BYTES) &&
485                AslGbl_OptimizeTrivialParseNodes)
486            {
487                /*
488                 * Unnamed field with a bit length of zero. We can
489                 * safely just ignore this. However, we will not ignore
490                 * a named field of zero length, we don't want to just
491                 * toss out a name.
492                 */
493                Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
494                PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
495                break;
496            }
497
498            /* Save the current AccessAs value for error checking later */
499
500            switch (AccessType)
501            {
502                case AML_FIELD_ACCESS_ANY:
503                case AML_FIELD_ACCESS_BYTE:
504                case AML_FIELD_ACCESS_BUFFER:
505                default:
506
507                    MinimumLength = 8;
508                    break;
509
510                case AML_FIELD_ACCESS_WORD:
511                    MinimumLength = 16;
512                    break;
513
514                case AML_FIELD_ACCESS_DWORD:
515                    MinimumLength = 32;
516                    break;
517
518                case AML_FIELD_ACCESS_QWORD:
519                    MinimumLength = 64;
520                    break;
521            }
522
523            PkgLengthNode->Asl.ExtraValue = MinimumLength;
524            break;
525
526        default:
527
528            /* All supported field opcodes must appear above */
529
530            break;
531        }
532
533        /* Move on to next entry in the field list */
534
535        Next = Next->Asl.Next;
536    }
537}
538
539
540/*******************************************************************************
541 *
542 * FUNCTION:    OpnDoField
543 *
544 * PARAMETERS:  Op        - The parent parse node
545 *
546 * RETURN:      None
547 *
548 * DESCRIPTION: Construct the AML operands for the FIELD ASL keyword
549 *
550 ******************************************************************************/
551
552static void
553OpnDoField (
554    ACPI_PARSE_OBJECT       *Op)
555{
556    ACPI_PARSE_OBJECT       *Next;
557
558
559    /* Opcode is parent node */
560    /* First child is field name */
561
562    Next = Op->Asl.Child;
563
564    /* Second child is the AccessType */
565
566    OpnDoFieldCommon (Op, Next->Asl.Next);
567}
568
569
570/*******************************************************************************
571 *
572 * FUNCTION:    OpnDoIndexField
573 *
574 * PARAMETERS:  Op        - The parent parse node
575 *
576 * RETURN:      None
577 *
578 * DESCRIPTION: Construct the AML operands for the INDEXFIELD ASL keyword
579 *
580 ******************************************************************************/
581
582static void
583OpnDoIndexField (
584    ACPI_PARSE_OBJECT       *Op)
585{
586    ACPI_PARSE_OBJECT       *Next;
587
588
589    /* Opcode is parent node */
590    /* First child is the index name */
591
592    Next = Op->Asl.Child;
593
594    /* Second child is the data name */
595
596    Next = Next->Asl.Next;
597
598    /* Third child is the AccessType */
599
600    OpnDoFieldCommon (Op, Next->Asl.Next);
601}
602
603
604/*******************************************************************************
605 *
606 * FUNCTION:    OpnDoBankField
607 *
608 * PARAMETERS:  Op        - The parent parse node
609 *
610 * RETURN:      None
611 *
612 * DESCRIPTION: Construct the AML operands for the BANKFIELD ASL keyword
613 *
614 ******************************************************************************/
615
616static void
617OpnDoBankField (
618    ACPI_PARSE_OBJECT       *Op)
619{
620    ACPI_PARSE_OBJECT       *Next;
621
622
623    /* Opcode is parent node */
624    /* First child is the region name */
625
626    Next = Op->Asl.Child;
627
628    /* Second child is the bank name */
629
630    Next = Next->Asl.Next;
631
632    /* Third child is the bank value */
633
634    Next = Next->Asl.Next;
635
636    /* Fourth child is the AccessType */
637
638    OpnDoFieldCommon (Op, Next->Asl.Next);
639}
640
641
642/*******************************************************************************
643 *
644 * FUNCTION:    OpnDoRegion
645 *
646 * PARAMETERS:  Op        - The parent parse node
647 *
648 * RETURN:      None
649 *
650 * DESCRIPTION: Tries to get the length of the region. Can only do this at
651 *              compile time if the length is a constant.
652 *
653 ******************************************************************************/
654
655static void
656OpnDoRegion (
657    ACPI_PARSE_OBJECT       *Op)
658{
659    ACPI_PARSE_OBJECT       *Next;
660    ACPI_ADR_SPACE_TYPE     SpaceId;
661
662
663    /* Opcode is parent node */
664    /* First child is the region name */
665
666    Next = Op->Asl.Child;
667
668    /* Second child is the space ID */
669
670    Next = Next->Asl.Next;
671    SpaceId = (ACPI_ADR_SPACE_TYPE) Next->Common.Value.Integer;
672
673    /* Third child is the region offset */
674
675    Next = Next->Asl.Next;
676
677    /* Fourth child is the region length */
678
679    Next = Next->Asl.Next;
680    if (Next->Asl.ParseOpcode == PARSEOP_INTEGER)
681    {
682        /* Check for zero length */
683
684        Op->Asl.Value.Integer = Next->Asl.Value.Integer;
685        if (!Op->Asl.Value.Integer && (SpaceId < ACPI_NUM_PREDEFINED_REGIONS))
686        {
687            AslError (ASL_ERROR, ASL_MSG_REGION_LENGTH, Op, NULL);
688        }
689    }
690    else
691    {
692        Op->Asl.Value.Integer = ACPI_UINT64_MAX;
693    }
694}
695
696
697/*******************************************************************************
698 *
699 * FUNCTION:    OpnDoBuffer
700 *
701 * PARAMETERS:  Op        - The parent parse node
702 *
703 * RETURN:      None
704 *
705 * DESCRIPTION: Construct the AML operands for the BUFFER ASL keyword. We
706 *              build a single raw byte buffer from the initialization nodes,
707 *              each parse node contains a buffer byte.
708 *
709 ******************************************************************************/
710
711static void
712OpnDoBuffer (
713    ACPI_PARSE_OBJECT       *Op)
714{
715    ACPI_PARSE_OBJECT       *InitializerOp;
716    ACPI_PARSE_OBJECT       *BufferLengthOp;
717
718    /* Optional arguments for this opcode with defaults */
719
720    UINT32                  BufferLength = 0;
721
722
723    /* Opcode and package length first */
724    /* Buffer Length is next, followed by the initializer list */
725
726    BufferLengthOp = Op->Asl.Child;
727    InitializerOp = BufferLengthOp->Asl.Next;
728
729    /*
730     * If the BufferLength is not an INTEGER or was not specified in the ASL
731     * (DEFAULT_ARG), it is a TermArg that is
732     * evaluated at run-time, and we are therefore finished.
733     */
734    if ((BufferLengthOp->Asl.ParseOpcode != PARSEOP_INTEGER) &&
735        (BufferLengthOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
736    {
737        return;
738    }
739
740    /*
741     * We want to count the number of items in the initializer list, because if
742     * it is larger than the buffer length, we will define the buffer size
743     * to be the size of the initializer list (as per the ACPI Specification)
744     */
745    switch (InitializerOp->Asl.ParseOpcode)
746    {
747    case PARSEOP_INTEGER:
748    case PARSEOP_BYTECONST:
749    case PARSEOP_WORDCONST:
750    case PARSEOP_DWORDCONST:
751
752        /* The peer list contains the byte list (if any...) */
753
754        while (InitializerOp)
755        {
756            /* For buffers, this is a list of raw bytes */
757
758            InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
759            InitializerOp->Asl.AmlLength = 1;
760            InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
761
762            BufferLength++;
763            InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
764        }
765        break;
766
767    case PARSEOP_STRING_LITERAL:
768
769        /*
770         * Only one initializer, the string. Buffer must be big enough to hold
771         * the string plus the null termination byte
772         */
773        BufferLength = strlen (InitializerOp->Asl.Value.String) + 1;
774
775        InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
776        InitializerOp->Asl.AmlLength = BufferLength;
777        InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
778        break;
779
780    case PARSEOP_RAW_DATA:
781
782        /* Buffer nodes are already initialized (e.g. Unicode operator) */
783        return;
784
785    case PARSEOP_DEFAULT_ARG:
786        break;
787
788    default:
789
790        AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, InitializerOp,
791            "Unknown buffer initializer opcode");
792        printf ("Unknown buffer initializer opcode [%s]\n",
793            UtGetOpName (InitializerOp->Asl.ParseOpcode));
794        return;
795    }
796
797    /* Check if initializer list is longer than the buffer length */
798
799    if (BufferLengthOp->Asl.Value.Integer > BufferLength)
800    {
801        BufferLength = (UINT32) BufferLengthOp->Asl.Value.Integer;
802    }
803
804    if (!BufferLength)
805    {
806        /* No length AND no items -- issue notice */
807
808        AslError (ASL_REMARK, ASL_MSG_BUFFER_LENGTH, BufferLengthOp, NULL);
809
810        /* But go ahead and put the buffer length of zero into the AML */
811    }
812
813    /*
814     * Just set the buffer size node to be the buffer length, regardless
815     * of whether it was previously an integer or a default_arg placeholder
816     */
817    BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
818    BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP;
819    BufferLengthOp->Asl.Value.Integer = BufferLength;
820
821    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
822    UtSetParseOpName (BufferLengthOp);
823
824    /* Remaining nodes are handled via the tree walk */
825}
826
827
828/*******************************************************************************
829 *
830 * FUNCTION:    OpnDoPackage
831 *
832 * PARAMETERS:  Op        - The parent parse node
833 *
834 * RETURN:      None
835 *
836 * DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword. NOTE:
837 *              can only be called after constants have been folded, to ensure
838 *              that the PackageLength operand has been fully reduced.
839 *
840 ******************************************************************************/
841
842void
843OpnDoPackage (
844    ACPI_PARSE_OBJECT       *Op)
845{
846    ACPI_PARSE_OBJECT       *InitializerOp;
847    ACPI_PARSE_OBJECT       *PackageLengthOp;
848    UINT32                  PackageLength = 0;
849
850
851    /* Opcode and package length first, followed by the initializer list */
852
853    PackageLengthOp = Op->Asl.Child;
854    InitializerOp = PackageLengthOp->Asl.Next;
855
856    /* Count the number of items in the initializer list */
857
858    if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
859    {
860        /* The peer list contains the byte list (if any...) */
861
862        while (InitializerOp)
863        {
864            PackageLength++;
865            InitializerOp = InitializerOp->Asl.Next;
866        }
867    }
868
869    /* If package length is a constant, compare to the initializer list */
870
871    if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
872        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST))
873    {
874        if (PackageLengthOp->Asl.Value.Integer > PackageLength)
875        {
876            /*
877             * Allow package length to be longer than the initializer
878             * list -- but if the length of initializer list is nonzero,
879             * issue a message since this is probably a coding error,
880             * even though technically legal.
881             */
882            if (PackageLength > 0)
883            {
884                AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT,
885                    PackageLengthOp, NULL);
886            }
887
888            PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer;
889        }
890        else if (PackageLengthOp->Asl.Value.Integer < PackageLength)
891        {
892            /*
893             * The package length is smaller than the length of the
894             * initializer list. This is an error as per the ACPI spec.
895             */
896            AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG,
897                PackageLengthOp, NULL);
898        }
899    }
900
901    if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
902    {
903        /*
904         * This is the case if the PackageLength was left empty - Package()
905         * The package length becomes the length of the initializer list
906         */
907        Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER;
908        Op->Asl.Child->Asl.Value.Integer = PackageLength;
909        UtSetParseOpName (Op);
910
911        /* Set the AML opcode */
912
913        (void) OpcSetOptimalIntegerSize (Op->Asl.Child);
914    }
915
916    /* If not a variable-length package, check for a zero package length */
917
918    if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
919        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST)   ||
920        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_ZERO)         ||
921        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG))
922    {
923        if (!PackageLength)
924        {
925            /* No length AND no initializer list -- issue a remark */
926
927            AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH,
928                PackageLengthOp, NULL);
929
930            /* But go ahead and put the buffer length of zero into the AML */
931        }
932    }
933
934    /*
935     * If the PackageLength is a constant <= 255, we can change the
936     * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode.
937     */
938    if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
939            (Op->Asl.Child->Asl.Value.Integer <= 255))  ||
940        (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) ||
941        (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)||
942        (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO))
943    {
944        Op->Asl.AmlOpcode = AML_PACKAGE_OP;
945        Op->Asl.ParseOpcode = PARSEOP_PACKAGE;
946
947        /*
948         * Just set the package size node to be the package length, regardless
949         * of whether it was previously an integer or a default_arg placeholder
950         */
951        PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
952        PackageLengthOp->Asl.AmlLength = 1;
953        PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
954        PackageLengthOp->Asl.Value.Integer = PackageLength;
955    }
956
957    /* Remaining nodes are handled via the tree walk */
958}
959
960
961/*******************************************************************************
962 *
963 * FUNCTION:    OpnDoLoadTable
964 *
965 * PARAMETERS:  Op        - The parent parse node
966 *
967 * RETURN:      None
968 *
969 * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword.
970 *
971 ******************************************************************************/
972
973static void
974OpnDoLoadTable (
975    ACPI_PARSE_OBJECT       *Op)
976{
977    ACPI_PARSE_OBJECT       *Next;
978
979
980    /* Opcode is parent node */
981    /* First child is the table signature */
982
983    Next = Op->Asl.Child;
984
985    /* Second child is the OEM ID*/
986
987    Next = Next->Asl.Next;
988
989    /* Third child is the OEM table ID */
990
991    Next = Next->Asl.Next;
992
993    /* Fourth child is the RootPath string */
994
995    Next = Next->Asl.Next;
996    if (Next->Asl.ParseOpcode == PARSEOP_ZERO)
997    {
998        Next->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
999        Next->Asl.Value.String = "\\";
1000        Next->Asl.AmlLength = 2;
1001        OpcGenerateAmlOpcode (Next);
1002    }
1003
1004#ifdef ASL_FUTURE_IMPLEMENTATION
1005
1006    /* TBD: NOT IMPLEMENTED */
1007    /* Fifth child is the [optional] ParameterPathString */
1008    /* Sixth child is the [optional] ParameterData */
1009
1010    Next = Next->Asl.Next;
1011    if (Next->Asl.ParseOpcode == DEFAULT_ARG)
1012    {
1013        Next->Asl.AmlLength = 1;
1014        Next->Asl.ParseOpcode = ZERO;
1015        OpcGenerateAmlOpcode (Next);
1016    }
1017
1018
1019    Next = Next->Asl.Next;
1020    if (Next->Asl.ParseOpcode == DEFAULT_ARG)
1021    {
1022        Next->Asl.AmlLength = 1;
1023        Next->Asl.ParseOpcode = ZERO;
1024        OpcGenerateAmlOpcode (Next);
1025    }
1026#endif
1027}
1028
1029
1030/*******************************************************************************
1031 *
1032 * FUNCTION:    OpnDoDefinitionBlock
1033 *
1034 * PARAMETERS:  Op        - The parent parse node
1035 *
1036 * RETURN:      None
1037 *
1038 * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword
1039 *
1040 ******************************************************************************/
1041
1042static void
1043OpnDoDefinitionBlock (
1044    ACPI_PARSE_OBJECT       *Op)
1045{
1046    ACPI_PARSE_OBJECT       *Child;
1047    ACPI_SIZE               Length;
1048    UINT32                  i;
1049    char                    *Filename;
1050    ACPI_STATUS             Status;
1051
1052
1053    /*
1054     * These nodes get stuffed into the table header. They are special
1055     * cased when the table is written to the output file.
1056     *
1057     * Mark all of these nodes as non-usable so they won't get output
1058     * as AML opcodes!
1059     */
1060
1061    /* Get AML filename. Use it if non-null */
1062
1063    Child = Op->Asl.Child;
1064    if (Child->Asl.Value.Buffer  &&
1065        *Child->Asl.Value.Buffer &&
1066        (AslGbl_UseDefaultAmlFilename))
1067    {
1068        /*
1069         * The walk may traverse multiple definition blocks. Switch files
1070         * to ensure that the correct files are manipulated.
1071         */
1072        FlSwitchFileSet (Op->Asl.Filename);
1073
1074        /*
1075         * We will use the AML filename that is embedded in the source file
1076         * for the output filename.
1077         */
1078        Filename = UtLocalCacheCalloc (strlen (AslGbl_DirectoryPath) +
1079            strlen ((char *) Child->Asl.Value.Buffer) + 1);
1080
1081        /* Prepend the current directory path */
1082
1083        strcpy (Filename, AslGbl_DirectoryPath);
1084        strcat (Filename, (char *) Child->Asl.Value.Buffer);
1085
1086        AslGbl_OutputFilenamePrefix = Filename;
1087        UtConvertBackslashes (AslGbl_OutputFilenamePrefix);
1088
1089        /*
1090         * Use the definition block file parameter instead of the input
1091         * filename. Since all files were opened previously, remove the
1092         * existing file and open a new file with the name of this
1093         * definiton block parameter. Since AML code generation has yet
1094         * to happen, the previous file can be removed without any impacts.
1095         */
1096        FlCloseFile (ASL_FILE_AML_OUTPUT);
1097        FlDeleteFile (ASL_FILE_AML_OUTPUT);
1098        Status = FlOpenAmlOutputFile (AslGbl_OutputFilenamePrefix);
1099        if (ACPI_FAILURE (Status))
1100        {
1101            AslError (ASL_ERROR, ASL_MSG_OUTPUT_FILE_OPEN, NULL, NULL);
1102            return;
1103        }
1104    }
1105
1106    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1107
1108    /* Signature */
1109
1110    Child = Child->Asl.Next;
1111    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1112    if (Child->Asl.Value.String)
1113    {
1114        AslGbl_FilesList->TableSignature = Child->Asl.Value.String;
1115        AslGbl_TableSignature = Child->Asl.Value.String;
1116        if (strlen (AslGbl_TableSignature) != ACPI_NAMESEG_SIZE)
1117        {
1118            AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
1119                "Length must be exactly 4 characters");
1120        }
1121
1122        for (i = 0; i < ACPI_NAMESEG_SIZE; i++)
1123        {
1124            if (!isalnum ((int) AslGbl_TableSignature[i]))
1125            {
1126                AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
1127                    "Contains non-alphanumeric characters");
1128            }
1129        }
1130    }
1131
1132    /* Revision */
1133
1134    Child = Child->Asl.Next;
1135    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1136
1137    /*
1138     * We used the revision to set the integer width earlier
1139     */
1140
1141    /* OEMID */
1142
1143    Child = Child->Asl.Next;
1144    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1145    if (Child->Asl.Value.String &&
1146        strlen (Child->Asl.Value.String) > ACPI_OEM_ID_SIZE)
1147    {
1148        AslError (ASL_ERROR, ASL_MSG_OEM_ID, Child,
1149            "Length cannot exceed 6 characters");
1150    }
1151
1152    /* OEM TableID */
1153
1154    Child = Child->Asl.Next;
1155    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1156    if (Child->Asl.Value.String)
1157    {
1158        Length = strlen (Child->Asl.Value.String);
1159        if (Length > ACPI_OEM_TABLE_ID_SIZE)
1160        {
1161            AslError (ASL_ERROR, ASL_MSG_OEM_TABLE_ID, Child,
1162                "Length cannot exceed 8 characters");
1163        }
1164
1165        AslGbl_TableId = UtLocalCacheCalloc (Length + 1);
1166        strcpy (AslGbl_TableId, Child->Asl.Value.String);
1167        AslGbl_FilesList->TableId = AslGbl_TableId;
1168
1169        /*
1170         * Convert anything non-alphanumeric to an underscore. This
1171         * allows us to use the TableID to generate unique C symbols.
1172         */
1173        for (i = 0; i < Length; i++)
1174        {
1175            if (!isalnum ((int) AslGbl_TableId[i]))
1176            {
1177                AslGbl_TableId[i] = '_';
1178            }
1179        }
1180    }
1181
1182    /* OEM Revision */
1183
1184    Child = Child->Asl.Next;
1185    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1186}
1187
1188
1189/*******************************************************************************
1190 *
1191 * FUNCTION:    UtGetArg
1192 *
1193 * PARAMETERS:  Op              - Get an argument for this op
1194 *              Argn            - Nth argument to get
1195 *
1196 * RETURN:      The argument (as an Op object). NULL if argument does not exist
1197 *
1198 * DESCRIPTION: Get the specified op's argument (peer)
1199 *
1200 ******************************************************************************/
1201
1202ACPI_PARSE_OBJECT *
1203UtGetArg (
1204    ACPI_PARSE_OBJECT       *Op,
1205    UINT32                  Argn)
1206{
1207    ACPI_PARSE_OBJECT       *Arg = NULL;
1208
1209
1210    /* Get the requested argument object */
1211
1212    Arg = Op->Asl.Child;
1213    while (Arg && Argn)
1214    {
1215        Argn--;
1216        Arg = Arg->Asl.Next;
1217    }
1218
1219    return (Arg);
1220}
1221
1222
1223/*******************************************************************************
1224 *
1225 * FUNCTION:    OpnAttachNameToNode
1226 *
1227 * PARAMETERS:  Op        - The parent parse node
1228 *
1229 * RETURN:      None
1230 *
1231 * DESCRIPTION: For the named ASL/AML operators, get the actual name from the
1232 *              argument list and attach it to the parent node so that we
1233 *              can get to it quickly later.
1234 *
1235 ******************************************************************************/
1236
1237static void
1238OpnAttachNameToNode (
1239    ACPI_PARSE_OBJECT       *Op)
1240{
1241    ACPI_PARSE_OBJECT       *Child = NULL;
1242
1243
1244    switch (Op->Asl.AmlOpcode)
1245    {
1246    case AML_DATA_REGION_OP:
1247    case AML_DEVICE_OP:
1248    case AML_EVENT_OP:
1249    case AML_EXTERNAL_OP:
1250    case AML_METHOD_OP:
1251    case AML_MUTEX_OP:
1252    case AML_REGION_OP:
1253    case AML_POWER_RESOURCE_OP:
1254    case AML_PROCESSOR_OP:
1255    case AML_THERMAL_ZONE_OP:
1256    case AML_NAME_OP:
1257    case AML_SCOPE_OP:
1258
1259        Child = UtGetArg (Op, 0);
1260        break;
1261
1262    case AML_ALIAS_OP:
1263
1264        Child = UtGetArg (Op, 1);
1265        break;
1266
1267    case AML_CREATE_BIT_FIELD_OP:
1268    case AML_CREATE_BYTE_FIELD_OP:
1269    case AML_CREATE_WORD_FIELD_OP:
1270    case AML_CREATE_DWORD_FIELD_OP:
1271    case AML_CREATE_QWORD_FIELD_OP:
1272
1273        Child = UtGetArg (Op, 2);
1274        break;
1275
1276    case AML_CREATE_FIELD_OP:
1277
1278        Child = UtGetArg (Op, 3);
1279        break;
1280
1281    case AML_BANK_FIELD_OP:
1282    case AML_INDEX_FIELD_OP:
1283    case AML_FIELD_OP:
1284
1285        return;
1286
1287    default:
1288
1289        return;
1290    }
1291
1292    if (Child)
1293    {
1294        UtAttachNamepathToOwner (Op, Child);
1295    }
1296}
1297
1298
1299/*******************************************************************************
1300 *
1301 * FUNCTION:    OpnGenerateAmlOperands
1302 *
1303 * PARAMETERS:  Op        - The parent parse node
1304 *
1305 * RETURN:      None
1306 *
1307 * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more
1308 *              complex AML opcodes require processing of the child nodes
1309 *              (arguments/operands).
1310 *
1311 ******************************************************************************/
1312
1313void
1314OpnGenerateAmlOperands (
1315    ACPI_PARSE_OBJECT       *Op)
1316{
1317
1318
1319    if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)
1320    {
1321        return;
1322    }
1323
1324    switch (Op->Asl.ParseOpcode)
1325    {
1326    case PARSEOP_DEFINITION_BLOCK:
1327
1328        OpnDoDefinitionBlock (Op);
1329        break;
1330
1331    case PARSEOP_METHOD:
1332
1333        OpnDoMethod (Op);
1334        break;
1335
1336    case PARSEOP_MUTEX:
1337
1338        OpnDoMutex (Op);
1339        break;
1340
1341    case PARSEOP_FIELD:
1342
1343        OpnDoField (Op);
1344        break;
1345
1346    case PARSEOP_INDEXFIELD:
1347
1348        OpnDoIndexField (Op);
1349        break;
1350
1351    case PARSEOP_BANKFIELD:
1352
1353        OpnDoBankField (Op);
1354        break;
1355
1356    case PARSEOP_BUFFER:
1357
1358        OpnDoBuffer (Op);
1359        break;
1360
1361    case PARSEOP_LOADTABLE:
1362
1363        OpnDoLoadTable (Op);
1364        break;
1365
1366    case PARSEOP_OPERATIONREGION:
1367
1368        OpnDoRegion (Op);
1369        break;
1370
1371    case PARSEOP_RESOURCETEMPLATE:
1372
1373        RsDoResourceTemplate (Op);
1374        break;
1375
1376    case PARSEOP_NAMESEG:
1377    case PARSEOP_NAMESTRING:
1378    case PARSEOP_METHODCALL:
1379    case PARSEOP_STRING_LITERAL:
1380    default:
1381
1382        break;
1383    }
1384
1385    /* TBD: move */
1386
1387    OpnAttachNameToNode (Op);
1388}
1389