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 - 2016, 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#include "aslcompiler.h"
117#include "aslcompiler.y.h"
118#include "amlcode.h"
119
120#define _COMPONENT          ACPI_COMPILER
121        ACPI_MODULE_NAME    ("asloperands")
122
123/* Local prototypes */
124
125static void
126OpnDoField (
127    ACPI_PARSE_OBJECT       *Op);
128
129static void
130OpnDoBankField (
131    ACPI_PARSE_OBJECT       *Op);
132
133static void
134OpnDoBuffer (
135    ACPI_PARSE_OBJECT       *Op);
136
137static void
138OpnDoDefinitionBlock (
139    ACPI_PARSE_OBJECT       *Op);
140
141static void
142OpnDoFieldCommon (
143    ACPI_PARSE_OBJECT       *FieldOp,
144    ACPI_PARSE_OBJECT       *Op);
145
146static void
147OpnDoIndexField (
148    ACPI_PARSE_OBJECT       *Op);
149
150static void
151OpnDoLoadTable (
152    ACPI_PARSE_OBJECT       *Op);
153
154static void
155OpnDoMethod (
156    ACPI_PARSE_OBJECT       *Op);
157
158static void
159OpnDoMutex (
160    ACPI_PARSE_OBJECT       *Op);
161
162static void
163OpnDoRegion (
164    ACPI_PARSE_OBJECT       *Op);
165
166static void
167OpnAttachNameToNode (
168    ACPI_PARSE_OBJECT       *Op);
169
170
171/*******************************************************************************
172 *
173 * FUNCTION:    OpnDoMutex
174 *
175 * PARAMETERS:  Op        - The parent parse node
176 *
177 * RETURN:      None
178 *
179 * DESCRIPTION: Construct the operands for the MUTEX ASL keyword.
180 *
181 ******************************************************************************/
182
183static void
184OpnDoMutex (
185    ACPI_PARSE_OBJECT       *Op)
186{
187    ACPI_PARSE_OBJECT       *Next;
188
189
190    Next = Op->Asl.Child;
191    Next = Next->Asl.Next;
192
193    if (Next->Asl.Value.Integer > 15)
194    {
195        AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
196    }
197    return;
198}
199
200
201/*******************************************************************************
202 *
203 * FUNCTION:    OpnDoMethod
204 *
205 * PARAMETERS:  Op        - The parent parse node
206 *
207 * RETURN:      None
208 *
209 * DESCRIPTION: Construct the operands for the METHOD ASL keyword.
210 *
211 ******************************************************************************/
212
213static void
214OpnDoMethod (
215    ACPI_PARSE_OBJECT       *Op)
216{
217    ACPI_PARSE_OBJECT       *Next;
218
219    /* Optional arguments for this opcode with defaults */
220
221    UINT8                   NumArgs = 0;
222    UINT8                   Serialized = 0;
223    UINT8                   Concurrency = 0;
224    UINT8                   MethodFlags;
225
226
227    /* Opcode and package length first */
228    /* Method name */
229
230    Next = Op->Asl.Child;
231
232    /* Num args */
233
234    Next = Next->Asl.Next;
235    if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
236    {
237        NumArgs = (UINT8) Next->Asl.Value.Integer;
238        Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
239    }
240
241    /* Serialized Flag */
242
243    Next = Next->Asl.Next;
244    if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
245    {
246        Serialized = (UINT8) Next->Asl.Value.Integer;
247        Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
248    }
249
250    /* Concurrency value (valid values are 0-15) */
251
252    Next = Next->Asl.Next;
253    if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
254    {
255        /* This is a ByteConstExpr, so eval the constant now */
256
257        OpcAmlConstantWalk (Next, 0, NULL);
258
259        if (Next->Asl.Value.Integer > 15)
260        {
261            AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
262        }
263
264        Concurrency = (UINT8) Next->Asl.Value.Integer;
265    }
266
267    /* Put the bits in their proper places */
268
269    MethodFlags = (UINT8)
270        ((NumArgs & 0x7) |
271        ((Serialized & 0x1) << 3) |
272        ((Concurrency & 0xF) << 4));
273
274    /* Use the last node for the combined flags byte */
275
276    Next->Asl.Value.Integer = MethodFlags;
277    Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
278    Next->Asl.AmlLength = 1;
279    Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
280
281    /* Save the arg count in the first node */
282
283    Op->Asl.Extra = NumArgs;
284}
285
286
287/*******************************************************************************
288 *
289 * FUNCTION:    OpnDoFieldCommon
290 *
291 * PARAMETERS:  FieldOp       - Node for an ASL field
292 *              Op            - The parent parse node
293 *
294 * RETURN:      None
295 *
296 * DESCRIPTION: Construct the AML operands for the various field keywords,
297 *              FIELD, BANKFIELD, INDEXFIELD
298 *
299 ******************************************************************************/
300
301static void
302OpnDoFieldCommon (
303    ACPI_PARSE_OBJECT       *FieldOp,
304    ACPI_PARSE_OBJECT       *Op)
305{
306    ACPI_PARSE_OBJECT       *Next;
307    ACPI_PARSE_OBJECT       *PkgLengthNode;
308    UINT32                  CurrentBitOffset;
309    UINT32                  NewBitOffset;
310    UINT8                   AccessType;
311    UINT8                   LockRule;
312    UINT8                   UpdateRule;
313    UINT8                   FieldFlags;
314    UINT32                  MinimumLength;
315
316
317    /* AccessType -- not optional, so no need to check for DEFAULT_ARG */
318
319    AccessType = (UINT8) Op->Asl.Value.Integer;
320    Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
321
322    /* Set the access type in the parent (field) node for use later */
323
324    FieldOp->Asl.Value.Integer = AccessType;
325
326    /* LockRule -- not optional, so no need to check for DEFAULT_ARG */
327
328    Next = Op->Asl.Next;
329    LockRule = (UINT8) Next->Asl.Value.Integer;
330    Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
331
332    /* UpdateRule -- not optional, so no need to check for DEFAULT_ARG */
333
334    Next = Next->Asl.Next;
335    UpdateRule = (UINT8) Next->Asl.Value.Integer;
336
337    /*
338     * Generate the flags byte. The various fields are already
339     * in the right bit position via translation from the
340     * keywords by the parser.
341     */
342    FieldFlags = (UINT8) (AccessType | LockRule | UpdateRule);
343
344    /* Use the previous node to be the FieldFlags node */
345
346    /* Set the node to RAW_DATA */
347
348    Next->Asl.Value.Integer = FieldFlags;
349    Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
350    Next->Asl.AmlLength = 1;
351    Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
352
353    /* Process the FieldUnitList */
354
355    Next = Next->Asl.Next;
356    CurrentBitOffset = 0;
357
358    while (Next)
359    {
360        /* Save the offset of this field unit */
361
362        Next->Asl.ExtraValue = CurrentBitOffset;
363
364        switch (Next->Asl.ParseOpcode)
365        {
366        case PARSEOP_ACCESSAS:
367
368            PkgLengthNode = Next->Asl.Child;
369            AccessType = (UINT8) PkgLengthNode->Asl.Value.Integer;
370
371            /* Nothing additional to do */
372            break;
373
374        case PARSEOP_OFFSET:
375
376            /* New offset into the field */
377
378            PkgLengthNode = Next->Asl.Child;
379            NewBitOffset = ((UINT32) PkgLengthNode->Asl.Value.Integer) * 8;
380
381            /*
382             * Examine the specified offset in relation to the
383             * current offset counter.
384             */
385            if (NewBitOffset < CurrentBitOffset)
386            {
387                /*
388                 * Not allowed to specify a backwards offset!
389                 * Issue error and ignore this node.
390                 */
391                AslError (ASL_ERROR, ASL_MSG_BACKWARDS_OFFSET, PkgLengthNode,
392                    NULL);
393                Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
394                PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
395            }
396            else if (NewBitOffset == CurrentBitOffset)
397            {
398                /*
399                 * Offset is redundant; we don't need to output an
400                 * offset opcode. Just set these nodes to default
401                 */
402                Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
403                PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
404            }
405            else
406            {
407                /*
408                 * Valid new offset - set the value to be inserted into the AML
409                 * and update the offset counter.
410                 */
411                PkgLengthNode->Asl.Value.Integer =
412                    NewBitOffset - CurrentBitOffset;
413                CurrentBitOffset = NewBitOffset;
414            }
415            break;
416
417        case PARSEOP_NAMESEG:
418        case PARSEOP_RESERVED_BYTES:
419
420            /* Named or reserved field entry */
421
422            PkgLengthNode = Next->Asl.Child;
423            NewBitOffset = (UINT32) PkgLengthNode->Asl.Value.Integer;
424            CurrentBitOffset += NewBitOffset;
425
426            /* Save the current AccessAs value for error checking later */
427
428            switch (AccessType)
429            {
430                case AML_FIELD_ACCESS_ANY:
431                case AML_FIELD_ACCESS_BYTE:
432                case AML_FIELD_ACCESS_BUFFER:
433                default:
434
435                    MinimumLength = 8;
436                    break;
437
438                case AML_FIELD_ACCESS_WORD:
439                    MinimumLength = 16;
440                    break;
441
442                case AML_FIELD_ACCESS_DWORD:
443                    MinimumLength = 32;
444                    break;
445
446                case AML_FIELD_ACCESS_QWORD:
447                    MinimumLength = 64;
448                    break;
449            }
450
451            PkgLengthNode->Asl.ExtraValue = MinimumLength;
452            break;
453
454        default:
455
456            /* All supported field opcodes must appear above */
457
458            break;
459        }
460
461        /* Move on to next entry in the field list */
462
463        Next = Next->Asl.Next;
464    }
465}
466
467
468/*******************************************************************************
469 *
470 * FUNCTION:    OpnDoField
471 *
472 * PARAMETERS:  Op        - The parent parse node
473 *
474 * RETURN:      None
475 *
476 * DESCRIPTION: Construct the AML operands for the FIELD ASL keyword
477 *
478 ******************************************************************************/
479
480static void
481OpnDoField (
482    ACPI_PARSE_OBJECT       *Op)
483{
484    ACPI_PARSE_OBJECT       *Next;
485
486
487    /* Opcode is parent node */
488    /* First child is field name */
489
490    Next = Op->Asl.Child;
491
492    /* Second child is the AccessType */
493
494    OpnDoFieldCommon (Op, Next->Asl.Next);
495}
496
497
498/*******************************************************************************
499 *
500 * FUNCTION:    OpnDoIndexField
501 *
502 * PARAMETERS:  Op        - The parent parse node
503 *
504 * RETURN:      None
505 *
506 * DESCRIPTION: Construct the AML operands for the INDEXFIELD ASL keyword
507 *
508 ******************************************************************************/
509
510static void
511OpnDoIndexField (
512    ACPI_PARSE_OBJECT       *Op)
513{
514    ACPI_PARSE_OBJECT       *Next;
515
516
517    /* Opcode is parent node */
518    /* First child is the index name */
519
520    Next = Op->Asl.Child;
521
522    /* Second child is the data name */
523
524    Next = Next->Asl.Next;
525
526    /* Third child is the AccessType */
527
528    OpnDoFieldCommon (Op, Next->Asl.Next);
529}
530
531
532/*******************************************************************************
533 *
534 * FUNCTION:    OpnDoBankField
535 *
536 * PARAMETERS:  Op        - The parent parse node
537 *
538 * RETURN:      None
539 *
540 * DESCRIPTION: Construct the AML operands for the BANKFIELD ASL keyword
541 *
542 ******************************************************************************/
543
544static void
545OpnDoBankField (
546    ACPI_PARSE_OBJECT       *Op)
547{
548    ACPI_PARSE_OBJECT       *Next;
549
550
551    /* Opcode is parent node */
552    /* First child is the region name */
553
554    Next = Op->Asl.Child;
555
556    /* Second child is the bank name */
557
558    Next = Next->Asl.Next;
559
560    /* Third child is the bank value */
561
562    Next = Next->Asl.Next;
563
564    /* Fourth child is the AccessType */
565
566    OpnDoFieldCommon (Op, Next->Asl.Next);
567}
568
569
570/*******************************************************************************
571 *
572 * FUNCTION:    OpnDoRegion
573 *
574 * PARAMETERS:  Op        - The parent parse node
575 *
576 * RETURN:      None
577 *
578 * DESCRIPTION: Tries to get the length of the region. Can only do this at
579 *              compile time if the length is a constant.
580 *
581 ******************************************************************************/
582
583static void
584OpnDoRegion (
585    ACPI_PARSE_OBJECT       *Op)
586{
587    ACPI_PARSE_OBJECT       *Next;
588
589
590    /* Opcode is parent node */
591    /* First child is the region name */
592
593    Next = Op->Asl.Child;
594
595    /* Second child is the space ID*/
596
597    Next = Next->Asl.Next;
598
599    /* Third child is the region offset */
600
601    Next = Next->Asl.Next;
602
603    /* Fourth child is the region length */
604
605    Next = Next->Asl.Next;
606    if (Next->Asl.ParseOpcode == PARSEOP_INTEGER)
607    {
608        Op->Asl.Value.Integer = Next->Asl.Value.Integer;
609    }
610    else
611    {
612        Op->Asl.Value.Integer = ACPI_UINT64_MAX;
613    }
614}
615
616
617/*******************************************************************************
618 *
619 * FUNCTION:    OpnDoBuffer
620 *
621 * PARAMETERS:  Op        - The parent parse node
622 *
623 * RETURN:      None
624 *
625 * DESCRIPTION: Construct the AML operands for the BUFFER ASL keyword. We
626 *              build a single raw byte buffer from the initialization nodes,
627 *              each parse node contains a buffer byte.
628 *
629 ******************************************************************************/
630
631static void
632OpnDoBuffer (
633    ACPI_PARSE_OBJECT       *Op)
634{
635    ACPI_PARSE_OBJECT       *InitializerOp;
636    ACPI_PARSE_OBJECT       *BufferLengthOp;
637
638    /* Optional arguments for this opcode with defaults */
639
640    UINT32                  BufferLength = 0;
641
642
643    /* Opcode and package length first */
644    /* Buffer Length is next, followed by the initializer list */
645
646    BufferLengthOp = Op->Asl.Child;
647    InitializerOp = BufferLengthOp->Asl.Next;
648
649    /*
650     * If the BufferLength is not an INTEGER or was not specified in the ASL
651     * (DEFAULT_ARG), it is a TermArg that is
652     * evaluated at run-time, and we are therefore finished.
653     */
654    if ((BufferLengthOp->Asl.ParseOpcode != PARSEOP_INTEGER) &&
655        (BufferLengthOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
656    {
657        return;
658    }
659
660    /*
661     * We want to count the number of items in the initializer list, because if
662     * it is larger than the buffer length, we will define the buffer size
663     * to be the size of the initializer list (as per the ACPI Specification)
664     */
665    switch (InitializerOp->Asl.ParseOpcode)
666    {
667    case PARSEOP_INTEGER:
668    case PARSEOP_BYTECONST:
669    case PARSEOP_WORDCONST:
670    case PARSEOP_DWORDCONST:
671
672        /* The peer list contains the byte list (if any...) */
673
674        while (InitializerOp)
675        {
676            /* For buffers, this is a list of raw bytes */
677
678            InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
679            InitializerOp->Asl.AmlLength = 1;
680            InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
681
682            BufferLength++;
683            InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
684        }
685        break;
686
687    case PARSEOP_STRING_LITERAL:
688
689        /*
690         * Only one initializer, the string. Buffer must be big enough to hold
691         * the string plus the null termination byte
692         */
693        BufferLength = strlen (InitializerOp->Asl.Value.String) + 1;
694
695        InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
696        InitializerOp->Asl.AmlLength = BufferLength;
697        InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
698        break;
699
700    case PARSEOP_RAW_DATA:
701
702        /* Buffer nodes are already initialized (e.g. Unicode operator) */
703        return;
704
705    case PARSEOP_DEFAULT_ARG:
706        break;
707
708    default:
709
710        AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, InitializerOp,
711            "Unknown buffer initializer opcode");
712        printf ("Unknown buffer initializer opcode [%s]\n",
713            UtGetOpName (InitializerOp->Asl.ParseOpcode));
714        return;
715    }
716
717    /* Check if initializer list is longer than the buffer length */
718
719    if (BufferLengthOp->Asl.Value.Integer > BufferLength)
720    {
721        BufferLength = (UINT32) BufferLengthOp->Asl.Value.Integer;
722    }
723
724    if (!BufferLength)
725    {
726        /* No length AND no items -- issue notice */
727
728        AslError (ASL_REMARK, ASL_MSG_BUFFER_LENGTH, BufferLengthOp, NULL);
729
730        /* But go ahead and put the buffer length of zero into the AML */
731    }
732
733    /*
734     * Just set the buffer size node to be the buffer length, regardless
735     * of whether it was previously an integer or a default_arg placeholder
736     */
737    BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
738    BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP;
739    BufferLengthOp->Asl.Value.Integer = BufferLength;
740
741    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
742
743    /* Remaining nodes are handled via the tree walk */
744}
745
746
747/*******************************************************************************
748 *
749 * FUNCTION:    OpnDoPackage
750 *
751 * PARAMETERS:  Op        - The parent parse node
752 *
753 * RETURN:      None
754 *
755 * DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword. NOTE:
756 *              can only be called after constants have been folded, to ensure
757 *              that the PackageLength operand has been fully reduced.
758 *
759 ******************************************************************************/
760
761void
762OpnDoPackage (
763    ACPI_PARSE_OBJECT       *Op)
764{
765    ACPI_PARSE_OBJECT       *InitializerOp;
766    ACPI_PARSE_OBJECT       *PackageLengthOp;
767    UINT32                  PackageLength = 0;
768
769
770    /* Opcode and package length first, followed by the initializer list */
771
772    PackageLengthOp = Op->Asl.Child;
773    InitializerOp = PackageLengthOp->Asl.Next;
774
775    /* Count the number of items in the initializer list */
776
777    if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
778    {
779        /* The peer list contains the byte list (if any...) */
780
781        while (InitializerOp)
782        {
783            PackageLength++;
784            InitializerOp = InitializerOp->Asl.Next;
785        }
786    }
787
788    /* If package length is a constant, compare to the initializer list */
789
790    if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
791        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST))
792    {
793        if (PackageLengthOp->Asl.Value.Integer > PackageLength)
794        {
795            /*
796             * Allow package length to be longer than the initializer
797             * list -- but if the length of initializer list is nonzero,
798             * issue a message since this is probably a coding error,
799             * even though technically legal.
800             */
801            if (PackageLength > 0)
802            {
803                AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT,
804                    PackageLengthOp, NULL);
805            }
806
807            PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer;
808        }
809        else if (PackageLengthOp->Asl.Value.Integer < PackageLength)
810        {
811            /*
812             * The package length is smaller than the length of the
813             * initializer list. This is an error as per the ACPI spec.
814             */
815            AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG,
816                PackageLengthOp, NULL);
817        }
818    }
819
820    if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
821    {
822        /*
823         * This is the case if the PackageLength was left empty - Package()
824         * The package length becomes the length of the initializer list
825         */
826        Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER;
827        Op->Asl.Child->Asl.Value.Integer = PackageLength;
828
829        /* Set the AML opcode */
830
831        (void) OpcSetOptimalIntegerSize (Op->Asl.Child);
832    }
833
834    /* If not a variable-length package, check for a zero package length */
835
836    if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
837        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST)   ||
838        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_ZERO)         ||
839        (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG))
840    {
841        if (!PackageLength)
842        {
843            /* No length AND no initializer list -- issue a remark */
844
845            AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH,
846                PackageLengthOp, NULL);
847
848            /* But go ahead and put the buffer length of zero into the AML */
849        }
850    }
851
852    /*
853     * If the PackageLength is a constant <= 255, we can change the
854     * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode.
855     */
856    if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
857            (Op->Asl.Child->Asl.Value.Integer <= 255))  ||
858        (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) ||
859        (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)||
860        (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO))
861    {
862        Op->Asl.AmlOpcode = AML_PACKAGE_OP;
863        Op->Asl.ParseOpcode = PARSEOP_PACKAGE;
864
865        /*
866         * Just set the package size node to be the package length, regardless
867         * of whether it was previously an integer or a default_arg placeholder
868         */
869        PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
870        PackageLengthOp->Asl.AmlLength = 1;
871        PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
872        PackageLengthOp->Asl.Value.Integer = PackageLength;
873    }
874
875    /* Remaining nodes are handled via the tree walk */
876}
877
878
879/*******************************************************************************
880 *
881 * FUNCTION:    OpnDoLoadTable
882 *
883 * PARAMETERS:  Op        - The parent parse node
884 *
885 * RETURN:      None
886 *
887 * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword.
888 *
889 ******************************************************************************/
890
891static void
892OpnDoLoadTable (
893    ACPI_PARSE_OBJECT       *Op)
894{
895    ACPI_PARSE_OBJECT       *Next;
896
897
898    /* Opcode is parent node */
899    /* First child is the table signature */
900
901    Next = Op->Asl.Child;
902
903    /* Second child is the OEM ID*/
904
905    Next = Next->Asl.Next;
906
907    /* Third child is the OEM table ID */
908
909    Next = Next->Asl.Next;
910
911    /* Fourth child is the RootPath string */
912
913    Next = Next->Asl.Next;
914    if (Next->Asl.ParseOpcode == PARSEOP_ZERO)
915    {
916        Next->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
917        Next->Asl.Value.String = "\\";
918        Next->Asl.AmlLength = 2;
919        OpcGenerateAmlOpcode (Next);
920    }
921
922#ifdef ASL_FUTURE_IMPLEMENTATION
923
924    /* TBD: NOT IMPLEMENTED */
925    /* Fifth child is the [optional] ParameterPathString */
926    /* Sixth child is the [optional] ParameterData */
927
928    Next = Next->Asl.Next;
929    if (Next->Asl.ParseOpcode == DEFAULT_ARG)
930    {
931        Next->Asl.AmlLength = 1;
932        Next->Asl.ParseOpcode = ZERO;
933        OpcGenerateAmlOpcode (Next);
934    }
935
936
937    Next = Next->Asl.Next;
938    if (Next->Asl.ParseOpcode == DEFAULT_ARG)
939    {
940        Next->Asl.AmlLength = 1;
941        Next->Asl.ParseOpcode = ZERO;
942        OpcGenerateAmlOpcode (Next);
943    }
944#endif
945}
946
947
948/*******************************************************************************
949 *
950 * FUNCTION:    OpnDoDefinitionBlock
951 *
952 * PARAMETERS:  Op        - The parent parse node
953 *
954 * RETURN:      None
955 *
956 * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword
957 *
958 ******************************************************************************/
959
960static void
961OpnDoDefinitionBlock (
962    ACPI_PARSE_OBJECT       *Op)
963{
964    ACPI_PARSE_OBJECT       *Child;
965    ACPI_SIZE               Length;
966    UINT32                  i;
967    char                    *Filename;
968
969
970    /*
971     * These nodes get stuffed into the table header. They are special
972     * cased when the table is written to the output file.
973     *
974     * Mark all of these nodes as non-usable so they won't get output
975     * as AML opcodes!
976     */
977
978    /* Get AML filename. Use it if non-null */
979
980    Child = Op->Asl.Child;
981    if (Child->Asl.Value.Buffer  &&
982        *Child->Asl.Value.Buffer &&
983        (Gbl_UseDefaultAmlFilename))
984    {
985        /*
986         * We will use the AML filename that is embedded in the source file
987         * for the output filename.
988         */
989        Filename = UtStringCacheCalloc (strlen (Gbl_DirectoryPath) +
990            strlen ((char *) Child->Asl.Value.Buffer) + 1);
991
992        /* Prepend the current directory path */
993
994        strcpy (Filename, Gbl_DirectoryPath);
995        strcat (Filename, (char *) Child->Asl.Value.Buffer);
996
997        Gbl_OutputFilenamePrefix = Filename;
998        UtConvertBackslashes (Gbl_OutputFilenamePrefix);
999    }
1000
1001    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1002
1003    /* Signature */
1004
1005    Child = Child->Asl.Next;
1006    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1007    if (Child->Asl.Value.String)
1008    {
1009        Gbl_TableSignature = Child->Asl.Value.String;
1010        if (strlen (Gbl_TableSignature) != ACPI_NAME_SIZE)
1011        {
1012            AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
1013                "Length is not exactly 4");
1014        }
1015
1016        for (i = 0; i < ACPI_NAME_SIZE; i++)
1017        {
1018            if (!isalnum ((int) Gbl_TableSignature[i]))
1019            {
1020                AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
1021                    "Contains non-alphanumeric characters");
1022            }
1023        }
1024    }
1025
1026    /* Revision */
1027
1028    Child = Child->Asl.Next;
1029    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1030    /*
1031     * We used the revision to set the integer width earlier
1032     */
1033
1034    /* OEMID */
1035
1036    Child = Child->Asl.Next;
1037    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1038
1039    /* OEM TableID */
1040
1041    Child = Child->Asl.Next;
1042    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1043    if (Child->Asl.Value.String)
1044    {
1045        Length = strlen (Child->Asl.Value.String);
1046        Gbl_TableId = UtStringCacheCalloc (Length + 1);
1047        strcpy (Gbl_TableId, Child->Asl.Value.String);
1048
1049        /*
1050         * Convert anything non-alphanumeric to an underscore. This
1051         * allows us to use the TableID to generate unique C symbols.
1052         */
1053        for (i = 0; i < Length; i++)
1054        {
1055            if (!isalnum ((int) Gbl_TableId[i]))
1056            {
1057                Gbl_TableId[i] = '_';
1058            }
1059        }
1060    }
1061
1062    /* OEM Revision */
1063
1064    Child = Child->Asl.Next;
1065    Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1066}
1067
1068
1069/*******************************************************************************
1070 *
1071 * FUNCTION:    UtGetArg
1072 *
1073 * PARAMETERS:  Op              - Get an argument for this op
1074 *              Argn            - Nth argument to get
1075 *
1076 * RETURN:      The argument (as an Op object). NULL if argument does not exist
1077 *
1078 * DESCRIPTION: Get the specified op's argument (peer)
1079 *
1080 ******************************************************************************/
1081
1082ACPI_PARSE_OBJECT *
1083UtGetArg (
1084    ACPI_PARSE_OBJECT       *Op,
1085    UINT32                  Argn)
1086{
1087    ACPI_PARSE_OBJECT       *Arg = NULL;
1088
1089
1090    /* Get the requested argument object */
1091
1092    Arg = Op->Asl.Child;
1093    while (Arg && Argn)
1094    {
1095        Argn--;
1096        Arg = Arg->Asl.Next;
1097    }
1098
1099    return (Arg);
1100}
1101
1102
1103/*******************************************************************************
1104 *
1105 * FUNCTION:    OpnAttachNameToNode
1106 *
1107 * PARAMETERS:  Op        - The parent parse node
1108 *
1109 * RETURN:      None
1110 *
1111 * DESCRIPTION: For the named ASL/AML operators, get the actual name from the
1112 *              argument list and attach it to the parent node so that we
1113 *              can get to it quickly later.
1114 *
1115 ******************************************************************************/
1116
1117static void
1118OpnAttachNameToNode (
1119    ACPI_PARSE_OBJECT       *Op)
1120{
1121    ACPI_PARSE_OBJECT       *Child = NULL;
1122
1123
1124    switch (Op->Asl.AmlOpcode)
1125    {
1126    case AML_DATA_REGION_OP:
1127    case AML_DEVICE_OP:
1128    case AML_EVENT_OP:
1129    case AML_EXTERNAL_OP:
1130    case AML_METHOD_OP:
1131    case AML_MUTEX_OP:
1132    case AML_REGION_OP:
1133    case AML_POWER_RES_OP:
1134    case AML_PROCESSOR_OP:
1135    case AML_THERMAL_ZONE_OP:
1136    case AML_NAME_OP:
1137    case AML_SCOPE_OP:
1138
1139        Child = UtGetArg (Op, 0);
1140        break;
1141
1142    case AML_ALIAS_OP:
1143
1144        Child = UtGetArg (Op, 1);
1145        break;
1146
1147    case AML_CREATE_BIT_FIELD_OP:
1148    case AML_CREATE_BYTE_FIELD_OP:
1149    case AML_CREATE_WORD_FIELD_OP:
1150    case AML_CREATE_DWORD_FIELD_OP:
1151    case AML_CREATE_QWORD_FIELD_OP:
1152
1153        Child = UtGetArg (Op, 2);
1154        break;
1155
1156    case AML_CREATE_FIELD_OP:
1157
1158        Child = UtGetArg (Op, 3);
1159        break;
1160
1161    case AML_BANK_FIELD_OP:
1162    case AML_INDEX_FIELD_OP:
1163    case AML_FIELD_OP:
1164
1165        return;
1166
1167    default:
1168
1169        return;
1170    }
1171
1172    if (Child)
1173    {
1174        UtAttachNamepathToOwner (Op, Child);
1175    }
1176}
1177
1178
1179/*******************************************************************************
1180 *
1181 * FUNCTION:    OpnGenerateAmlOperands
1182 *
1183 * PARAMETERS:  Op        - The parent parse node
1184 *
1185 * RETURN:      None
1186 *
1187 * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more
1188 *              complex AML opcodes require processing of the child nodes
1189 *              (arguments/operands).
1190 *
1191 ******************************************************************************/
1192
1193void
1194OpnGenerateAmlOperands (
1195    ACPI_PARSE_OBJECT       *Op)
1196{
1197
1198
1199    if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)
1200    {
1201        return;
1202    }
1203
1204    switch (Op->Asl.ParseOpcode)
1205    {
1206    case PARSEOP_DEFINITION_BLOCK:
1207
1208        OpnDoDefinitionBlock (Op);
1209        break;
1210
1211    case PARSEOP_METHOD:
1212
1213        OpnDoMethod (Op);
1214        break;
1215
1216    case PARSEOP_MUTEX:
1217
1218        OpnDoMutex (Op);
1219        break;
1220
1221    case PARSEOP_FIELD:
1222
1223        OpnDoField (Op);
1224        break;
1225
1226    case PARSEOP_INDEXFIELD:
1227
1228        OpnDoIndexField (Op);
1229        break;
1230
1231    case PARSEOP_BANKFIELD:
1232
1233        OpnDoBankField (Op);
1234        break;
1235
1236    case PARSEOP_BUFFER:
1237
1238        OpnDoBuffer (Op);
1239        break;
1240
1241    case PARSEOP_LOADTABLE:
1242
1243        OpnDoLoadTable (Op);
1244        break;
1245
1246    case PARSEOP_OPERATIONREGION:
1247
1248        OpnDoRegion (Op);
1249        break;
1250
1251    case PARSEOP_RESOURCETEMPLATE:
1252
1253        RsDoResourceTemplate (Op);
1254        break;
1255
1256    case PARSEOP_NAMESEG:
1257    case PARSEOP_NAMESTRING:
1258    case PARSEOP_METHODCALL:
1259    case PARSEOP_STRING_LITERAL:
1260    default:
1261
1262        break;
1263    }
1264
1265    /* TBD: move */
1266
1267    OpnAttachNameToNode (Op);
1268}
1269