Sync ACPICA with Intel's version 20150619.
[dragonfly.git] / sys / contrib / dev / acpica / source / compiler / asloperands.c
1 /******************************************************************************
2  *
3  * Module Name: asloperands - AML operand processing
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2015, 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 #include "aslcompiler.h"
45 #include "aslcompiler.y.h"
46 #include "amlcode.h"
47
48 #define _COMPONENT          ACPI_COMPILER
49         ACPI_MODULE_NAME    ("asloperands")
50
51 /* Local prototypes */
52
53 static void
54 OpnDoField (
55     ACPI_PARSE_OBJECT       *Op);
56
57 static void
58 OpnDoBankField (
59     ACPI_PARSE_OBJECT       *Op);
60
61 static void
62 OpnDoBuffer (
63     ACPI_PARSE_OBJECT       *Op);
64
65 static void
66 OpnDoDefinitionBlock (
67     ACPI_PARSE_OBJECT       *Op);
68
69 static void
70 OpnDoFieldCommon (
71     ACPI_PARSE_OBJECT       *FieldOp,
72     ACPI_PARSE_OBJECT       *Op);
73
74 static void
75 OpnDoIndexField (
76     ACPI_PARSE_OBJECT       *Op);
77
78 static void
79 OpnDoLoadTable (
80     ACPI_PARSE_OBJECT       *Op);
81
82 static void
83 OpnDoMethod (
84     ACPI_PARSE_OBJECT       *Op);
85
86 static void
87 OpnDoMutex (
88     ACPI_PARSE_OBJECT       *Op);
89
90 static void
91 OpnDoRegion (
92     ACPI_PARSE_OBJECT       *Op);
93
94 static void
95 OpnAttachNameToNode (
96     ACPI_PARSE_OBJECT       *Op);
97
98
99 /*******************************************************************************
100  *
101  * FUNCTION:    OpnDoMutex
102  *
103  * PARAMETERS:  Op        - The parent parse node
104  *
105  * RETURN:      None
106  *
107  * DESCRIPTION: Construct the operands for the MUTEX ASL keyword.
108  *
109  ******************************************************************************/
110
111 static void
112 OpnDoMutex (
113     ACPI_PARSE_OBJECT       *Op)
114 {
115     ACPI_PARSE_OBJECT       *Next;
116
117
118     Next = Op->Asl.Child;
119     Next = Next->Asl.Next;
120
121     if (Next->Asl.Value.Integer > 15)
122     {
123         AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
124     }
125     return;
126 }
127
128
129 /*******************************************************************************
130  *
131  * FUNCTION:    OpnDoMethod
132  *
133  * PARAMETERS:  Op        - The parent parse node
134  *
135  * RETURN:      None
136  *
137  * DESCRIPTION: Construct the operands for the METHOD ASL keyword.
138  *
139  ******************************************************************************/
140
141 static void
142 OpnDoMethod (
143     ACPI_PARSE_OBJECT       *Op)
144 {
145     ACPI_PARSE_OBJECT       *Next;
146
147     /* Optional arguments for this opcode with defaults */
148
149     UINT8                   NumArgs = 0;
150     UINT8                   Serialized = 0;
151     UINT8                   Concurrency = 0;
152     UINT8                   MethodFlags;
153
154
155     /* Opcode and package length first */
156     /* Method name */
157
158     Next = Op->Asl.Child;
159
160     /* Num args */
161
162     Next = Next->Asl.Next;
163     if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
164     {
165         NumArgs = (UINT8) Next->Asl.Value.Integer;
166         Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
167     }
168
169     /* Serialized Flag */
170
171     Next = Next->Asl.Next;
172     if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
173     {
174         Serialized = (UINT8) Next->Asl.Value.Integer;
175         Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
176     }
177
178     /* Concurrency value (valid values are 0-15) */
179
180     Next = Next->Asl.Next;
181     if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
182     {
183         /* This is a ByteConstExpr, so eval the constant now */
184
185         OpcAmlConstantWalk (Next, 0, NULL);
186
187         if (Next->Asl.Value.Integer > 15)
188         {
189             AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
190         }
191         Concurrency = (UINT8) Next->Asl.Value.Integer;
192     }
193
194     /* Put the bits in their proper places */
195
196     MethodFlags = (UINT8) ((NumArgs & 0x7) |
197                           ((Serialized & 0x1) << 3) |
198                           ((Concurrency & 0xF) << 4));
199
200     /* Use the last node for the combined flags byte */
201
202     Next->Asl.Value.Integer = MethodFlags;
203     Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
204     Next->Asl.AmlLength = 1;
205     Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
206
207     /* Save the arg count in the first node */
208
209     Op->Asl.Extra = NumArgs;
210 }
211
212
213 /*******************************************************************************
214  *
215  * FUNCTION:    OpnDoFieldCommon
216  *
217  * PARAMETERS:  FieldOp       - Node for an ASL field
218  *              Op            - The parent parse node
219  *
220  * RETURN:      None
221  *
222  * DESCRIPTION: Construct the AML operands for the various field keywords,
223  *              FIELD, BANKFIELD, INDEXFIELD
224  *
225  ******************************************************************************/
226
227 static void
228 OpnDoFieldCommon (
229     ACPI_PARSE_OBJECT       *FieldOp,
230     ACPI_PARSE_OBJECT       *Op)
231 {
232     ACPI_PARSE_OBJECT       *Next;
233     ACPI_PARSE_OBJECT       *PkgLengthNode;
234     UINT32                  CurrentBitOffset;
235     UINT32                  NewBitOffset;
236     UINT8                   AccessType;
237     UINT8                   LockRule;
238     UINT8                   UpdateRule;
239     UINT8                   FieldFlags;
240     UINT32                  MinimumLength;
241
242
243     /* AccessType -- not optional, so no need to check for DEFAULT_ARG */
244
245     AccessType = (UINT8) Op->Asl.Value.Integer;
246     Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
247
248     /* Set the access type in the parent (field) node for use later */
249
250     FieldOp->Asl.Value.Integer = AccessType;
251
252     /* LockRule -- not optional, so no need to check for DEFAULT_ARG */
253
254     Next = Op->Asl.Next;
255     LockRule = (UINT8) Next->Asl.Value.Integer;
256     Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
257
258     /* UpdateRule -- not optional, so no need to check for DEFAULT_ARG */
259
260     Next = Next->Asl.Next;
261     UpdateRule = (UINT8) Next->Asl.Value.Integer;
262
263     /*
264      * Generate the flags byte. The various fields are already
265      * in the right bit position via translation from the
266      * keywords by the parser.
267      */
268     FieldFlags = (UINT8) (AccessType | LockRule | UpdateRule);
269
270     /* Use the previous node to be the FieldFlags node */
271
272     /* Set the node to RAW_DATA */
273
274     Next->Asl.Value.Integer = FieldFlags;
275     Next->Asl.AmlOpcode     = AML_RAW_DATA_BYTE;
276     Next->Asl.AmlLength     = 1;
277     Next->Asl.ParseOpcode   = PARSEOP_RAW_DATA;
278
279     /* Process the FieldUnitList */
280
281     Next = Next->Asl.Next;
282     CurrentBitOffset = 0;
283
284     while (Next)
285     {
286         /* Save the offset of this field unit */
287
288         Next->Asl.ExtraValue = CurrentBitOffset;
289
290         switch (Next->Asl.ParseOpcode)
291         {
292         case PARSEOP_ACCESSAS:
293
294             PkgLengthNode = Next->Asl.Child;
295             AccessType = (UINT8) PkgLengthNode->Asl.Value.Integer;
296
297             /* Nothing additional to do */
298             break;
299
300         case PARSEOP_OFFSET:
301
302             /* New offset into the field */
303
304             PkgLengthNode = Next->Asl.Child;
305             NewBitOffset = ((UINT32) PkgLengthNode->Asl.Value.Integer) * 8;
306
307             /*
308              * Examine the specified offset in relation to the
309              * current offset counter.
310              */
311             if (NewBitOffset < CurrentBitOffset)
312             {
313                 /*
314                  * Not allowed to specify a backwards offset!
315                  * Issue error and ignore this node.
316                  */
317                 AslError (ASL_ERROR, ASL_MSG_BACKWARDS_OFFSET, PkgLengthNode,
318                     NULL);
319                 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
320                 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
321             }
322             else if (NewBitOffset == CurrentBitOffset)
323             {
324                 /*
325                  * Offset is redundant; we don't need to output an
326                  * offset opcode. Just set these nodes to default
327                  */
328                 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
329                 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
330             }
331             else
332             {
333                 /*
334                  * Valid new offset - set the value to be inserted into the AML
335                  * and update the offset counter.
336                  */
337                 PkgLengthNode->Asl.Value.Integer =
338                     NewBitOffset - CurrentBitOffset;
339                 CurrentBitOffset = NewBitOffset;
340             }
341             break;
342
343         case PARSEOP_NAMESEG:
344         case PARSEOP_RESERVED_BYTES:
345
346             /* Named or reserved field entry */
347
348             PkgLengthNode     = Next->Asl.Child;
349             NewBitOffset      = (UINT32) PkgLengthNode->Asl.Value.Integer;
350             CurrentBitOffset += NewBitOffset;
351
352             /* Save the current AccessAs value for error checking later */
353
354             switch (AccessType)
355             {
356                 case AML_FIELD_ACCESS_ANY:
357                 case AML_FIELD_ACCESS_BYTE:
358                 case AML_FIELD_ACCESS_BUFFER:
359                 default:
360
361                     MinimumLength = 8;
362                     break;
363
364                 case AML_FIELD_ACCESS_WORD:
365                     MinimumLength = 16;
366                     break;
367
368                 case AML_FIELD_ACCESS_DWORD:
369                     MinimumLength = 32;
370                     break;
371
372                 case AML_FIELD_ACCESS_QWORD:
373                     MinimumLength = 64;
374                     break;
375             }
376
377             PkgLengthNode->Asl.ExtraValue = MinimumLength;
378             break;
379
380         default:
381
382             /* All supported field opcodes must appear above */
383
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     case PARSEOP_STRING_LITERAL:
614
615         /*
616          * Only one initializer, the string. Buffer must be big enough to hold
617          * the string plus the null termination byte
618          */
619         BufferLength = strlen (InitializerOp->Asl.Value.String) + 1;
620
621         InitializerOp->Asl.AmlOpcode      = AML_RAW_DATA_BUFFER;
622         InitializerOp->Asl.AmlLength      = BufferLength;
623         InitializerOp->Asl.ParseOpcode    = PARSEOP_RAW_DATA;
624         break;
625
626     case PARSEOP_RAW_DATA:
627
628         /* Buffer nodes are already initialized (e.g. Unicode operator) */
629         return;
630
631     case PARSEOP_DEFAULT_ARG:
632         break;
633
634     default:
635
636         AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, InitializerOp,
637             "Unknown buffer initializer opcode");
638         printf ("Unknown buffer initializer opcode [%s]\n",
639                         UtGetOpName (InitializerOp->Asl.ParseOpcode));
640         return;
641     }
642
643     /* Check if initializer list is longer than the buffer length */
644
645     if (BufferLengthOp->Asl.Value.Integer > BufferLength)
646     {
647         BufferLength = (UINT32) BufferLengthOp->Asl.Value.Integer;
648     }
649
650     if (!BufferLength)
651     {
652         /* No length AND no items -- issue notice */
653
654         AslError (ASL_REMARK, ASL_MSG_BUFFER_LENGTH, BufferLengthOp, NULL);
655
656         /* But go ahead and put the buffer length of zero into the AML */
657     }
658
659     /*
660      * Just set the buffer size node to be the buffer length, regardless
661      * of whether it was previously an integer or a default_arg placeholder
662      */
663     BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
664     BufferLengthOp->Asl.AmlOpcode     = AML_DWORD_OP;
665     BufferLengthOp->Asl.Value.Integer = BufferLength;
666
667     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
668
669     /* Remaining nodes are handled via the tree walk */
670 }
671
672
673 /*******************************************************************************
674  *
675  * FUNCTION:    OpnDoPackage
676  *
677  * PARAMETERS:  Op        - The parent parse node
678  *
679  * RETURN:      None
680  *
681  * DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword. NOTE:
682  *              can only be called after constants have been folded, to ensure
683  *              that the PackageLength operand has been fully reduced.
684  *
685  ******************************************************************************/
686
687 void
688 OpnDoPackage (
689     ACPI_PARSE_OBJECT       *Op)
690 {
691     ACPI_PARSE_OBJECT       *InitializerOp;
692     ACPI_PARSE_OBJECT       *PackageLengthOp;
693     UINT32                  PackageLength = 0;
694
695
696     /* Opcode and package length first, followed by the initializer list */
697
698     PackageLengthOp = Op->Asl.Child;
699     InitializerOp = PackageLengthOp->Asl.Next;
700
701     /* Count the number of items in the initializer list */
702
703     if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
704     {
705         /* The peer list contains the byte list (if any...) */
706
707         while (InitializerOp)
708         {
709             PackageLength++;
710             InitializerOp = InitializerOp->Asl.Next;
711         }
712     }
713
714     /* If package length is a constant, compare to the initializer list */
715
716     if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
717         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST))
718     {
719         if (PackageLengthOp->Asl.Value.Integer > PackageLength)
720         {
721             /*
722              * Allow package length to be longer than the initializer
723              * list -- but if the length of initializer list is nonzero,
724              * issue a message since this is probably a coding error,
725              * even though technically legal.
726              */
727             if (PackageLength > 0)
728             {
729                 AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT,
730                     PackageLengthOp, NULL);
731             }
732
733             PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer;
734         }
735         else if (PackageLengthOp->Asl.Value.Integer < PackageLength)
736         {
737             /*
738              * The package length is smaller than the length of the
739              * initializer list. This is an error as per the ACPI spec.
740              */
741             AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG,
742                 PackageLengthOp, NULL);
743         }
744     }
745
746     if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
747     {
748         /*
749          * This is the case if the PackageLength was left empty - Package()
750          * The package length becomes the length of the initializer list
751          */
752         Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER;
753         Op->Asl.Child->Asl.Value.Integer = PackageLength;
754
755         /* Set the AML opcode */
756
757         (void) OpcSetOptimalIntegerSize (Op->Asl.Child);
758     }
759
760     /* If not a variable-length package, check for a zero package length */
761
762     if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
763         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST)   ||
764         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_ZERO)         ||
765         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG))
766     {
767         if (!PackageLength)
768         {
769             /* No length AND no initializer list -- issue a remark */
770
771             AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH,
772                 PackageLengthOp, NULL);
773
774             /* But go ahead and put the buffer length of zero into the AML */
775         }
776     }
777
778     /*
779      * If the PackageLength is a constant <= 255, we can change the
780      * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode.
781      */
782     if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
783             (Op->Asl.Child->Asl.Value.Integer <= 255))  ||
784         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) ||
785         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)||
786         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO))
787     {
788         Op->Asl.AmlOpcode = AML_PACKAGE_OP;
789         Op->Asl.ParseOpcode = PARSEOP_PACKAGE;
790
791         /*
792          * Just set the package size node to be the package length, regardless
793          * of whether it was previously an integer or a default_arg placeholder
794          */
795         PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
796         PackageLengthOp->Asl.AmlLength = 1;
797         PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
798         PackageLengthOp->Asl.Value.Integer = PackageLength;
799     }
800
801     /* Remaining nodes are handled via the tree walk */
802 }
803
804
805 /*******************************************************************************
806  *
807  * FUNCTION:    OpnDoLoadTable
808  *
809  * PARAMETERS:  Op        - The parent parse node
810  *
811  * RETURN:      None
812  *
813  * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword.
814  *
815  ******************************************************************************/
816
817 static void
818 OpnDoLoadTable (
819     ACPI_PARSE_OBJECT       *Op)
820 {
821     ACPI_PARSE_OBJECT       *Next;
822
823
824     /* Opcode is parent node */
825     /* First child is the table signature */
826
827     Next = Op->Asl.Child;
828
829     /* Second child is the OEM ID*/
830
831     Next = Next->Asl.Next;
832
833     /* Third child is the OEM table ID */
834
835     Next = Next->Asl.Next;
836
837     /* Fourth child is the RootPath string */
838
839     Next = Next->Asl.Next;
840     if (Next->Asl.ParseOpcode == PARSEOP_ZERO)
841     {
842         Next->Asl.ParseOpcode    = PARSEOP_STRING_LITERAL;
843         Next->Asl.Value.String   = "\\";
844         Next->Asl.AmlLength      = 2;
845         OpcGenerateAmlOpcode (Next);
846     }
847
848 #ifdef ASL_FUTURE_IMPLEMENTATION
849
850     /* TBD: NOT IMPLEMENTED */
851     /* Fifth child is the [optional] ParameterPathString */
852     /* Sixth child is the [optional] ParameterData */
853
854     Next = Next->Asl.Next;
855     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
856     {
857         Next->Asl.AmlLength = 1;
858         Next->Asl.ParseOpcode = ZERO;
859         OpcGenerateAmlOpcode (Next);
860     }
861
862
863     Next = Next->Asl.Next;
864     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
865     {
866         Next->Asl.AmlLength = 1;
867         Next->Asl.ParseOpcode = ZERO;
868         OpcGenerateAmlOpcode (Next);
869     }
870 #endif
871 }
872
873
874 /*******************************************************************************
875  *
876  * FUNCTION:    OpnDoDefinitionBlock
877  *
878  * PARAMETERS:  Op        - The parent parse node
879  *
880  * RETURN:      None
881  *
882  * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword
883  *
884  ******************************************************************************/
885
886 static void
887 OpnDoDefinitionBlock (
888     ACPI_PARSE_OBJECT       *Op)
889 {
890     ACPI_PARSE_OBJECT       *Child;
891     ACPI_SIZE               Length;
892     UINT32                  i;
893     char                    *Filename;
894
895
896     /*
897      * These nodes get stuffed into the table header. They are special
898      * cased when the table is written to the output file.
899      *
900      * Mark all of these nodes as non-usable so they won't get output
901      * as AML opcodes!
902      */
903
904     /* Get AML filename. Use it if non-null */
905
906     Child = Op->Asl.Child;
907     if (Child->Asl.Value.Buffer  &&
908         *Child->Asl.Value.Buffer &&
909         (Gbl_UseDefaultAmlFilename))
910     {
911         /*
912          * We will use the AML filename that is embedded in the source file
913          * for the output filename.
914          */
915         Filename = UtStringCacheCalloc (strlen (Gbl_DirectoryPath) +
916             strlen ((char *) Child->Asl.Value.Buffer) + 1);
917
918         /* Prepend the current directory path */
919
920         strcpy (Filename, Gbl_DirectoryPath);
921         strcat (Filename, (char *) Child->Asl.Value.Buffer);
922
923         Gbl_OutputFilenamePrefix = Filename;
924         UtConvertBackslashes (Gbl_OutputFilenamePrefix);
925     }
926     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
927
928     /* Signature */
929
930     Child = Child->Asl.Next;
931     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
932     if (Child->Asl.Value.String)
933     {
934         Gbl_TableSignature = Child->Asl.Value.String;
935         if (strlen (Gbl_TableSignature) != 4)
936         {
937             AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
938                 "Length not exactly 4");
939         }
940
941         for (i = 0; i < 4; i++)
942         {
943             if (!isalnum ((int) Gbl_TableSignature[i]))
944             {
945                 AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
946                     "Contains non-alphanumeric characters");
947             }
948         }
949     }
950
951     /* Revision */
952
953     Child = Child->Asl.Next;
954     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
955     /*
956      * We used the revision to set the integer width earlier
957      */
958
959     /* OEMID */
960
961     Child = Child->Asl.Next;
962     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
963
964     /* OEM TableID */
965
966     Child = Child->Asl.Next;
967     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
968     if (Child->Asl.Value.String)
969     {
970         Length = strlen (Child->Asl.Value.String);
971         Gbl_TableId = UtStringCacheCalloc (Length + 1);
972         strcpy (Gbl_TableId, Child->Asl.Value.String);
973
974         /*
975          * Convert anything non-alphanumeric to an underscore. This
976          * allows us to use the TableID to generate unique C symbols.
977          */
978         for (i = 0; i < Length; i++)
979         {
980             if (!isalnum ((int) Gbl_TableId[i]))
981             {
982                 Gbl_TableId[i] = '_';
983             }
984         }
985     }
986
987     /* OEM Revision */
988
989     Child = Child->Asl.Next;
990     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
991 }
992
993
994 /*******************************************************************************
995  *
996  * FUNCTION:    UtGetArg
997  *
998  * PARAMETERS:  Op              - Get an argument for this op
999  *              Argn            - Nth argument to get
1000  *
1001  * RETURN:      The argument (as an Op object). NULL if argument does not exist
1002  *
1003  * DESCRIPTION: Get the specified op's argument (peer)
1004  *
1005  ******************************************************************************/
1006
1007 ACPI_PARSE_OBJECT *
1008 UtGetArg (
1009     ACPI_PARSE_OBJECT       *Op,
1010     UINT32                  Argn)
1011 {
1012     ACPI_PARSE_OBJECT       *Arg = NULL;
1013
1014
1015     /* Get the requested argument object */
1016
1017     Arg = Op->Asl.Child;
1018     while (Arg && Argn)
1019     {
1020         Argn--;
1021         Arg = Arg->Asl.Next;
1022     }
1023
1024     return (Arg);
1025 }
1026
1027
1028 /*******************************************************************************
1029  *
1030  * FUNCTION:    OpnAttachNameToNode
1031  *
1032  * PARAMETERS:  Op        - The parent parse node
1033  *
1034  * RETURN:      None
1035  *
1036  * DESCRIPTION: For the named ASL/AML operators, get the actual name from the
1037  *              argument list and attach it to the parent node so that we
1038  *              can get to it quickly later.
1039  *
1040  ******************************************************************************/
1041
1042 static void
1043 OpnAttachNameToNode (
1044     ACPI_PARSE_OBJECT       *Op)
1045 {
1046     ACPI_PARSE_OBJECT       *Child = NULL;
1047
1048
1049     if (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)
1050     {
1051         Child = UtGetArg (Op, 0);
1052     }
1053     else switch (Op->Asl.AmlOpcode)
1054     {
1055     case AML_DATA_REGION_OP:
1056     case AML_DEVICE_OP:
1057     case AML_EVENT_OP:
1058     case AML_METHOD_OP:
1059     case AML_MUTEX_OP:
1060     case AML_REGION_OP:
1061     case AML_POWER_RES_OP:
1062     case AML_PROCESSOR_OP:
1063     case AML_THERMAL_ZONE_OP:
1064     case AML_NAME_OP:
1065     case AML_SCOPE_OP:
1066
1067         Child = UtGetArg (Op, 0);
1068         break;
1069
1070     case AML_ALIAS_OP:
1071
1072         Child = UtGetArg (Op, 1);
1073         break;
1074
1075     case AML_CREATE_BIT_FIELD_OP:
1076     case AML_CREATE_BYTE_FIELD_OP:
1077     case AML_CREATE_WORD_FIELD_OP:
1078     case AML_CREATE_DWORD_FIELD_OP:
1079     case AML_CREATE_QWORD_FIELD_OP:
1080
1081         Child = UtGetArg (Op, 2);
1082         break;
1083
1084     case AML_CREATE_FIELD_OP:
1085
1086         Child = UtGetArg (Op, 3);
1087         break;
1088
1089     case AML_BANK_FIELD_OP:
1090     case AML_INDEX_FIELD_OP:
1091     case AML_FIELD_OP:
1092
1093         return;
1094
1095     default:
1096
1097         return;
1098     }
1099
1100     if (Child)
1101     {
1102         UtAttachNamepathToOwner (Op, Child);
1103     }
1104 }
1105
1106
1107 /*******************************************************************************
1108  *
1109  * FUNCTION:    OpnGenerateAmlOperands
1110  *
1111  * PARAMETERS:  Op        - The parent parse node
1112  *
1113  * RETURN:      None
1114  *
1115  * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more
1116  *              complex AML opcodes require processing of the child nodes
1117  *              (arguments/operands).
1118  *
1119  ******************************************************************************/
1120
1121 void
1122 OpnGenerateAmlOperands (
1123     ACPI_PARSE_OBJECT       *Op)
1124 {
1125
1126
1127     if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)
1128     {
1129         return;
1130     }
1131
1132     switch (Op->Asl.ParseOpcode)
1133     {
1134     case PARSEOP_DEFINITIONBLOCK:
1135
1136         OpnDoDefinitionBlock (Op);
1137         break;
1138
1139     case PARSEOP_METHOD:
1140
1141         OpnDoMethod (Op);
1142         break;
1143
1144     case PARSEOP_MUTEX:
1145
1146         OpnDoMutex (Op);
1147         break;
1148
1149     case PARSEOP_FIELD:
1150
1151         OpnDoField (Op);
1152         break;
1153
1154     case PARSEOP_INDEXFIELD:
1155
1156         OpnDoIndexField (Op);
1157         break;
1158
1159     case PARSEOP_BANKFIELD:
1160
1161         OpnDoBankField (Op);
1162         break;
1163
1164     case PARSEOP_BUFFER:
1165
1166         OpnDoBuffer (Op);
1167         break;
1168
1169     case PARSEOP_LOADTABLE:
1170
1171         OpnDoLoadTable (Op);
1172         break;
1173
1174     case PARSEOP_OPERATIONREGION:
1175
1176         OpnDoRegion (Op);
1177         break;
1178
1179     case PARSEOP_RESOURCETEMPLATE:
1180
1181         RsDoResourceTemplate (Op);
1182         break;
1183
1184     case PARSEOP_NAMESEG:
1185     case PARSEOP_NAMESTRING:
1186     case PARSEOP_METHODCALL:
1187     case PARSEOP_STRING_LITERAL:
1188
1189         break;
1190
1191     default:
1192
1193         break;
1194     }
1195
1196     /* TBD: move */
1197
1198     OpnAttachNameToNode (Op);
1199 }