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