]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/contrib/dev/acpica/compiler/asloperands.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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 - 2013, 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         case PARSEOP_OFFSET:
302
303             /* New offset into the field */
304
305             PkgLengthNode = Next->Asl.Child;
306             NewBitOffset = ((UINT32) PkgLengthNode->Asl.Value.Integer) * 8;
307
308             /*
309              * Examine the specified offset in relation to the
310              * current offset counter.
311              */
312             if (NewBitOffset < CurrentBitOffset)
313             {
314                 /*
315                  * Not allowed to specify a backwards offset!
316                  * Issue error and ignore this node.
317                  */
318                 AslError (ASL_ERROR, ASL_MSG_BACKWARDS_OFFSET, PkgLengthNode,
319                     NULL);
320                 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
321                 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
322             }
323             else if (NewBitOffset == CurrentBitOffset)
324             {
325                 /*
326                  * Offset is redundant; we don't need to output an
327                  * offset opcode. Just set these nodes to default
328                  */
329                 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
330                 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
331             }
332             else
333             {
334                 /*
335                  * Valid new offset - set the value to be inserted into the AML
336                  * and update the offset counter.
337                  */
338                 PkgLengthNode->Asl.Value.Integer =
339                     NewBitOffset - CurrentBitOffset;
340                 CurrentBitOffset = NewBitOffset;
341             }
342             break;
343
344         case PARSEOP_NAMESEG:
345         case PARSEOP_RESERVED_BYTES:
346
347             /* Named or reserved field entry */
348
349             PkgLengthNode     = Next->Asl.Child;
350             NewBitOffset      = (UINT32) PkgLengthNode->Asl.Value.Integer;
351             CurrentBitOffset += NewBitOffset;
352
353             /* Save the current AccessAs value for error checking later */
354
355             switch (AccessType)
356             {
357                 case AML_FIELD_ACCESS_ANY:
358                 case AML_FIELD_ACCESS_BYTE:
359                 case AML_FIELD_ACCESS_BUFFER:
360                 default:
361
362                     MinimumLength = 8;
363                     break;
364
365                 case AML_FIELD_ACCESS_WORD:
366                     MinimumLength = 16;
367                     break;
368
369                 case AML_FIELD_ACCESS_DWORD:
370                     MinimumLength = 32;
371                     break;
372
373                 case AML_FIELD_ACCESS_QWORD:
374                     MinimumLength = 64;
375                     break;
376             }
377
378             PkgLengthNode->Asl.ExtraValue = MinimumLength;
379             break;
380
381         default:
382
383             /* All supported field opcodes must appear above */
384
385             break;
386         }
387
388         /* Move on to next entry in the field list */
389
390         Next = Next->Asl.Next;
391     }
392 }
393
394
395 /*******************************************************************************
396  *
397  * FUNCTION:    OpnDoField
398  *
399  * PARAMETERS:  Op        - The parent parse node
400  *
401  * RETURN:      None
402  *
403  * DESCRIPTION: Construct the AML operands for the FIELD ASL keyword
404  *
405  ******************************************************************************/
406
407 static void
408 OpnDoField (
409     ACPI_PARSE_OBJECT       *Op)
410 {
411     ACPI_PARSE_OBJECT       *Next;
412
413
414     /* Opcode is parent node */
415     /* First child is field name */
416
417     Next = Op->Asl.Child;
418
419     /* Second child is the AccessType */
420
421     OpnDoFieldCommon (Op, Next->Asl.Next);
422 }
423
424
425 /*******************************************************************************
426  *
427  * FUNCTION:    OpnDoIndexField
428  *
429  * PARAMETERS:  Op        - The parent parse node
430  *
431  * RETURN:      None
432  *
433  * DESCRIPTION: Construct the AML operands for the INDEXFIELD ASL keyword
434  *
435  ******************************************************************************/
436
437 static void
438 OpnDoIndexField (
439     ACPI_PARSE_OBJECT       *Op)
440 {
441     ACPI_PARSE_OBJECT       *Next;
442
443
444     /* Opcode is parent node */
445     /* First child is the index name */
446
447     Next = Op->Asl.Child;
448
449     /* Second child is the data name */
450
451     Next = Next->Asl.Next;
452
453     /* Third child is the AccessType */
454
455     OpnDoFieldCommon (Op, Next->Asl.Next);
456 }
457
458
459 /*******************************************************************************
460  *
461  * FUNCTION:    OpnDoBankField
462  *
463  * PARAMETERS:  Op        - The parent parse node
464  *
465  * RETURN:      None
466  *
467  * DESCRIPTION: Construct the AML operands for the BANKFIELD ASL keyword
468  *
469  ******************************************************************************/
470
471 static void
472 OpnDoBankField (
473     ACPI_PARSE_OBJECT       *Op)
474 {
475     ACPI_PARSE_OBJECT       *Next;
476
477
478     /* Opcode is parent node */
479     /* First child is the region name */
480
481     Next = Op->Asl.Child;
482
483     /* Second child is the bank name */
484
485     Next = Next->Asl.Next;
486
487     /* Third child is the bank value */
488
489     Next = Next->Asl.Next;
490
491     /* Fourth child is the AccessType */
492
493     OpnDoFieldCommon (Op, Next->Asl.Next);
494 }
495
496
497 /*******************************************************************************
498  *
499  * FUNCTION:    OpnDoRegion
500  *
501  * PARAMETERS:  Op        - The parent parse node
502  *
503  * RETURN:      None
504  *
505  * DESCRIPTION: Tries to get the length of the region. Can only do this at
506  *              compile time if the length is a constant.
507  *
508  ******************************************************************************/
509
510 static void
511 OpnDoRegion (
512     ACPI_PARSE_OBJECT       *Op)
513 {
514     ACPI_PARSE_OBJECT       *Next;
515
516
517     /* Opcode is parent node */
518     /* First child is the region name */
519
520     Next = Op->Asl.Child;
521
522     /* Second child is the space ID*/
523
524     Next = Next->Asl.Next;
525
526     /* Third child is the region offset */
527
528     Next = Next->Asl.Next;
529
530     /* Fourth child is the region length */
531
532     Next = Next->Asl.Next;
533     if (Next->Asl.ParseOpcode == PARSEOP_INTEGER)
534     {
535         Op->Asl.Value.Integer = Next->Asl.Value.Integer;
536     }
537     else
538     {
539         Op->Asl.Value.Integer = ACPI_UINT64_MAX;
540     }
541 }
542
543
544 /*******************************************************************************
545  *
546  * FUNCTION:    OpnDoBuffer
547  *
548  * PARAMETERS:  Op        - The parent parse node
549  *
550  * RETURN:      None
551  *
552  * DESCRIPTION: Construct the AML operands for the BUFFER ASL keyword. We
553  *              build a single raw byte buffer from the initialization nodes,
554  *              each parse node contains a buffer byte.
555  *
556  ******************************************************************************/
557
558 static void
559 OpnDoBuffer (
560     ACPI_PARSE_OBJECT       *Op)
561 {
562     ACPI_PARSE_OBJECT       *InitializerOp;
563     ACPI_PARSE_OBJECT       *BufferLengthOp;
564
565     /* Optional arguments for this opcode with defaults */
566
567     UINT32                  BufferLength = 0;
568
569
570     /* Opcode and package length first */
571     /* Buffer Length is next, followed by the initializer list */
572
573     BufferLengthOp = Op->Asl.Child;
574     InitializerOp = BufferLengthOp->Asl.Next;
575
576     /*
577      * If the BufferLength is not an INTEGER or was not specified in the ASL
578      * (DEFAULT_ARG), it is a TermArg that is
579      * evaluated at run-time, and we are therefore finished.
580      */
581     if ((BufferLengthOp->Asl.ParseOpcode != PARSEOP_INTEGER) &&
582         (BufferLengthOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
583     {
584         return;
585     }
586
587     /*
588      * We want to count the number of items in the initializer list, because if
589      * it is larger than the buffer length, we will define the buffer size
590      * to be the size of the initializer list (as per the ACPI Specification)
591      */
592     switch (InitializerOp->Asl.ParseOpcode)
593     {
594     case PARSEOP_INTEGER:
595     case PARSEOP_BYTECONST:
596     case PARSEOP_WORDCONST:
597     case PARSEOP_DWORDCONST:
598
599         /* The peer list contains the byte list (if any...) */
600
601         while (InitializerOp)
602         {
603             /* For buffers, this is a list of raw bytes */
604
605             InitializerOp->Asl.AmlOpcode      = AML_RAW_DATA_BYTE;
606             InitializerOp->Asl.AmlLength      = 1;
607             InitializerOp->Asl.ParseOpcode    = PARSEOP_RAW_DATA;
608
609             BufferLength++;
610             InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
611         }
612         break;
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     case PARSEOP_RAW_DATA:
628
629         /* Buffer nodes are already initialized (e.g. Unicode operator) */
630         return;
631
632     case PARSEOP_DEFAULT_ARG:
633         break;
634
635     default:
636
637         AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, InitializerOp,
638             "Unknown buffer initializer opcode");
639         printf ("Unknown buffer initializer opcode [%s]\n",
640                         UtGetOpName (InitializerOp->Asl.ParseOpcode));
641         return;
642     }
643
644     /* Check if initializer list is longer than the buffer length */
645
646     if (BufferLengthOp->Asl.Value.Integer > BufferLength)
647     {
648         BufferLength = (UINT32) BufferLengthOp->Asl.Value.Integer;
649     }
650
651     if (!BufferLength)
652     {
653         /* No length AND no items -- issue notice */
654
655         AslError (ASL_REMARK, ASL_MSG_BUFFER_LENGTH, BufferLengthOp, NULL);
656
657         /* But go ahead and put the buffer length of zero into the AML */
658     }
659
660     /*
661      * Just set the buffer size node to be the buffer length, regardless
662      * of whether it was previously an integer or a default_arg placeholder
663      */
664     BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
665     BufferLengthOp->Asl.AmlOpcode     = AML_DWORD_OP;
666     BufferLengthOp->Asl.Value.Integer = BufferLength;
667
668     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
669
670     /* Remaining nodes are handled via the tree walk */
671 }
672
673
674 /*******************************************************************************
675  *
676  * FUNCTION:    OpnDoPackage
677  *
678  * PARAMETERS:  Op        - The parent parse node
679  *
680  * RETURN:      None
681  *
682  * DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword. NOTE:
683  *              can only be called after constants have been folded, to ensure
684  *              that the PackageLength operand has been fully reduced.
685  *
686  ******************************************************************************/
687
688 void
689 OpnDoPackage (
690     ACPI_PARSE_OBJECT       *Op)
691 {
692     ACPI_PARSE_OBJECT       *InitializerOp;
693     ACPI_PARSE_OBJECT       *PackageLengthOp;
694     UINT32                  PackageLength = 0;
695
696
697     /* Opcode and package length first, followed by the initializer list */
698
699     PackageLengthOp = Op->Asl.Child;
700     InitializerOp = PackageLengthOp->Asl.Next;
701
702     /* Count the number of items in the initializer list */
703
704     if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
705     {
706         /* The peer list contains the byte list (if any...) */
707
708         while (InitializerOp)
709         {
710             PackageLength++;
711             InitializerOp = InitializerOp->Asl.Next;
712         }
713     }
714
715     /* If package length is a constant, compare to the initializer list */
716
717     if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
718         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST))
719     {
720         if (PackageLengthOp->Asl.Value.Integer > PackageLength)
721         {
722             /*
723              * Allow package length to be longer than the initializer
724              * list -- but if the length of initializer list is nonzero,
725              * issue a message since this is probably a coding error,
726              * even though technically legal.
727              */
728             if (PackageLength > 0)
729             {
730                 AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT,
731                     PackageLengthOp, NULL);
732             }
733
734             PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer;
735         }
736         else if (PackageLengthOp->Asl.Value.Integer < PackageLength)
737         {
738             /*
739              * The package length is smaller than the length of the
740              * initializer list. This is an error as per the ACPI spec.
741              */
742             AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG,
743                 PackageLengthOp, NULL);
744         }
745     }
746
747     if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
748     {
749         /*
750          * This is the case if the PackageLength was left empty - Package()
751          * The package length becomes the length of the initializer list
752          */
753         Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER;
754         Op->Asl.Child->Asl.Value.Integer = PackageLength;
755
756         /* Set the AML opcode */
757
758         (void) OpcSetOptimalIntegerSize (Op->Asl.Child);
759     }
760
761     /* If not a variable-length package, check for a zero package length */
762
763     if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
764         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST)   ||
765         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_ZERO)         ||
766         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG))
767     {
768         if (!PackageLength)
769         {
770             /* No length AND no initializer list -- issue a remark */
771
772             AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH,
773                 PackageLengthOp, NULL);
774
775             /* But go ahead and put the buffer length of zero into the AML */
776         }
777     }
778
779     /*
780      * If the PackageLength is a constant <= 255, we can change the
781      * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode.
782      */
783     if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
784             (Op->Asl.Child->Asl.Value.Integer <= 255))  ||
785         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) ||
786         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)||
787         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO))
788     {
789         Op->Asl.AmlOpcode = AML_PACKAGE_OP;
790         Op->Asl.ParseOpcode = PARSEOP_PACKAGE;
791
792         /*
793          * Just set the package size node to be the package length, regardless
794          * of whether it was previously an integer or a default_arg placeholder
795          */
796         PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
797         PackageLengthOp->Asl.AmlLength = 1;
798         PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
799         PackageLengthOp->Asl.Value.Integer = PackageLength;
800     }
801
802     /* Remaining nodes are handled via the tree walk */
803 }
804
805
806 /*******************************************************************************
807  *
808  * FUNCTION:    OpnDoLoadTable
809  *
810  * PARAMETERS:  Op        - The parent parse node
811  *
812  * RETURN:      None
813  *
814  * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword.
815  *
816  ******************************************************************************/
817
818 static void
819 OpnDoLoadTable (
820     ACPI_PARSE_OBJECT       *Op)
821 {
822     ACPI_PARSE_OBJECT       *Next;
823
824
825     /* Opcode is parent node */
826     /* First child is the table signature */
827
828     Next = Op->Asl.Child;
829
830     /* Second child is the OEM ID*/
831
832     Next = Next->Asl.Next;
833
834     /* Third child is the OEM table ID */
835
836     Next = Next->Asl.Next;
837
838     /* Fourth child is the RootPath string */
839
840     Next = Next->Asl.Next;
841     if (Next->Asl.ParseOpcode == PARSEOP_ZERO)
842     {
843         Next->Asl.ParseOpcode    = PARSEOP_STRING_LITERAL;
844         Next->Asl.Value.String   = "\\";
845         Next->Asl.AmlLength      = 2;
846         OpcGenerateAmlOpcode (Next);
847     }
848
849 #ifdef ASL_FUTURE_IMPLEMENTATION
850
851     /* TBD: NOT IMPLEMENTED */
852     /* Fifth child is the [optional] ParameterPathString */
853     /* Sixth child is the [optional] ParameterData */
854
855     Next = Next->Asl.Next;
856     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
857     {
858         Next->Asl.AmlLength = 1;
859         Next->Asl.ParseOpcode = ZERO;
860         OpcGenerateAmlOpcode (Next);
861     }
862
863
864     Next = Next->Asl.Next;
865     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
866     {
867         Next->Asl.AmlLength = 1;
868         Next->Asl.ParseOpcode = ZERO;
869         OpcGenerateAmlOpcode (Next);
870     }
871 #endif
872 }
873
874
875 /*******************************************************************************
876  *
877  * FUNCTION:    OpnDoDefinitionBlock
878  *
879  * PARAMETERS:  Op        - The parent parse node
880  *
881  * RETURN:      None
882  *
883  * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword
884  *
885  ******************************************************************************/
886
887 static void
888 OpnDoDefinitionBlock (
889     ACPI_PARSE_OBJECT       *Op)
890 {
891     ACPI_PARSE_OBJECT       *Child;
892     ACPI_SIZE               Length;
893     UINT32                  i;
894     char                    *Filename;
895
896
897     /*
898      * These nodes get stuffed into the table header. They are special
899      * cased when the table is written to the output file.
900      *
901      * Mark all of these nodes as non-usable so they won't get output
902      * as AML opcodes!
903      */
904
905     /* Get AML filename. Use it if non-null */
906
907     Child = Op->Asl.Child;
908     if (Child->Asl.Value.Buffer  &&
909         *Child->Asl.Value.Buffer &&
910         (Gbl_UseDefaultAmlFilename))
911     {
912         /*
913          * We will use the AML filename that is embedded in the source file
914          * for the output filename.
915          */
916         Filename = ACPI_ALLOCATE (strlen (Gbl_DirectoryPath) +
917                     strlen ((char *) Child->Asl.Value.Buffer) + 1);
918
919         /* Prepend the current directory path */
920
921         strcpy (Filename, Gbl_DirectoryPath);
922         strcat (Filename, (char *) Child->Asl.Value.Buffer);
923
924         Gbl_OutputFilenamePrefix = Filename;
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 (ACPI_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 = ACPI_STRLEN (Child->Asl.Value.String);
971         Gbl_TableId = AcpiOsAllocate (Length + 1);
972         ACPI_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 }