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