]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/contrib/dev/acpica/compiler/asloperands.c
MFC r368207,368607:
[FreeBSD/stable/10.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 - 2016, 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 <contrib/dev/acpica/compiler/aslcompiler.h>
45 #include "aslcompiler.y.h"
46 #include <contrib/dev/acpica/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
192         Concurrency = (UINT8) Next->Asl.Value.Integer;
193     }
194
195     /* Put the bits in their proper places */
196
197     MethodFlags = (UINT8)
198         ((NumArgs & 0x7) |
199         ((Serialized & 0x1) << 3) |
200         ((Concurrency & 0xF) << 4));
201
202     /* Use the last node for the combined flags byte */
203
204     Next->Asl.Value.Integer = MethodFlags;
205     Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
206     Next->Asl.AmlLength = 1;
207     Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
208
209     /* Save the arg count in the first node */
210
211     Op->Asl.Extra = NumArgs;
212 }
213
214
215 /*******************************************************************************
216  *
217  * FUNCTION:    OpnDoFieldCommon
218  *
219  * PARAMETERS:  FieldOp       - Node for an ASL field
220  *              Op            - The parent parse node
221  *
222  * RETURN:      None
223  *
224  * DESCRIPTION: Construct the AML operands for the various field keywords,
225  *              FIELD, BANKFIELD, INDEXFIELD
226  *
227  ******************************************************************************/
228
229 static void
230 OpnDoFieldCommon (
231     ACPI_PARSE_OBJECT       *FieldOp,
232     ACPI_PARSE_OBJECT       *Op)
233 {
234     ACPI_PARSE_OBJECT       *Next;
235     ACPI_PARSE_OBJECT       *PkgLengthNode;
236     UINT32                  CurrentBitOffset;
237     UINT32                  NewBitOffset;
238     UINT8                   AccessType;
239     UINT8                   LockRule;
240     UINT8                   UpdateRule;
241     UINT8                   FieldFlags;
242     UINT32                  MinimumLength;
243
244
245     /* AccessType -- not optional, so no need to check for DEFAULT_ARG */
246
247     AccessType = (UINT8) Op->Asl.Value.Integer;
248     Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
249
250     /* Set the access type in the parent (field) node for use later */
251
252     FieldOp->Asl.Value.Integer = AccessType;
253
254     /* LockRule -- not optional, so no need to check for DEFAULT_ARG */
255
256     Next = Op->Asl.Next;
257     LockRule = (UINT8) Next->Asl.Value.Integer;
258     Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
259
260     /* UpdateRule -- not optional, so no need to check for DEFAULT_ARG */
261
262     Next = Next->Asl.Next;
263     UpdateRule = (UINT8) Next->Asl.Value.Integer;
264
265     /*
266      * Generate the flags byte. The various fields are already
267      * in the right bit position via translation from the
268      * keywords by the parser.
269      */
270     FieldFlags = (UINT8) (AccessType | LockRule | UpdateRule);
271
272     /* Use the previous node to be the FieldFlags node */
273
274     /* Set the node to RAW_DATA */
275
276     Next->Asl.Value.Integer = FieldFlags;
277     Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
278     Next->Asl.AmlLength = 1;
279     Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
280
281     /* Process the FieldUnitList */
282
283     Next = Next->Asl.Next;
284     CurrentBitOffset = 0;
285
286     while (Next)
287     {
288         /* Save the offset of this field unit */
289
290         Next->Asl.ExtraValue = CurrentBitOffset;
291
292         switch (Next->Asl.ParseOpcode)
293         {
294         case PARSEOP_ACCESSAS:
295
296             PkgLengthNode = Next->Asl.Child;
297             AccessType = (UINT8) PkgLengthNode->Asl.Value.Integer;
298
299             /* Nothing additional to do */
300             break;
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         case PARSEOP_NAMESEG:
346         case PARSEOP_RESERVED_BYTES:
347
348             /* Named or reserved field entry */
349
350             PkgLengthNode = Next->Asl.Child;
351             NewBitOffset = (UINT32) PkgLengthNode->Asl.Value.Integer;
352             CurrentBitOffset += NewBitOffset;
353
354             /* Save the current AccessAs value for error checking later */
355
356             switch (AccessType)
357             {
358                 case AML_FIELD_ACCESS_ANY:
359                 case AML_FIELD_ACCESS_BYTE:
360                 case AML_FIELD_ACCESS_BUFFER:
361                 default:
362
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
384             /* All supported field opcodes must appear above */
385
386             break;
387         }
388
389         /* Move on to next entry in the field list */
390
391         Next = Next->Asl.Next;
392     }
393 }
394
395
396 /*******************************************************************************
397  *
398  * FUNCTION:    OpnDoField
399  *
400  * PARAMETERS:  Op        - The parent parse node
401  *
402  * RETURN:      None
403  *
404  * DESCRIPTION: Construct the AML operands for the FIELD ASL keyword
405  *
406  ******************************************************************************/
407
408 static void
409 OpnDoField (
410     ACPI_PARSE_OBJECT       *Op)
411 {
412     ACPI_PARSE_OBJECT       *Next;
413
414
415     /* Opcode is parent node */
416     /* First child is field name */
417
418     Next = Op->Asl.Child;
419
420     /* Second child is the AccessType */
421
422     OpnDoFieldCommon (Op, Next->Asl.Next);
423 }
424
425
426 /*******************************************************************************
427  *
428  * FUNCTION:    OpnDoIndexField
429  *
430  * PARAMETERS:  Op        - The parent parse node
431  *
432  * RETURN:      None
433  *
434  * DESCRIPTION: Construct the AML operands for the INDEXFIELD ASL keyword
435  *
436  ******************************************************************************/
437
438 static void
439 OpnDoIndexField (
440     ACPI_PARSE_OBJECT       *Op)
441 {
442     ACPI_PARSE_OBJECT       *Next;
443
444
445     /* Opcode is parent node */
446     /* First child is the index name */
447
448     Next = Op->Asl.Child;
449
450     /* Second child is the data name */
451
452     Next = Next->Asl.Next;
453
454     /* Third child is the AccessType */
455
456     OpnDoFieldCommon (Op, Next->Asl.Next);
457 }
458
459
460 /*******************************************************************************
461  *
462  * FUNCTION:    OpnDoBankField
463  *
464  * PARAMETERS:  Op        - The parent parse node
465  *
466  * RETURN:      None
467  *
468  * DESCRIPTION: Construct the AML operands for the BANKFIELD ASL keyword
469  *
470  ******************************************************************************/
471
472 static void
473 OpnDoBankField (
474     ACPI_PARSE_OBJECT       *Op)
475 {
476     ACPI_PARSE_OBJECT       *Next;
477
478
479     /* Opcode is parent node */
480     /* First child is the region name */
481
482     Next = Op->Asl.Child;
483
484     /* Second child is the bank name */
485
486     Next = Next->Asl.Next;
487
488     /* Third child is the bank value */
489
490     Next = Next->Asl.Next;
491
492     /* Fourth child is the AccessType */
493
494     OpnDoFieldCommon (Op, Next->Asl.Next);
495 }
496
497
498 /*******************************************************************************
499  *
500  * FUNCTION:    OpnDoRegion
501  *
502  * PARAMETERS:  Op        - The parent parse node
503  *
504  * RETURN:      None
505  *
506  * DESCRIPTION: Tries to get the length of the region. Can only do this at
507  *              compile time if the length is a constant.
508  *
509  ******************************************************************************/
510
511 static void
512 OpnDoRegion (
513     ACPI_PARSE_OBJECT       *Op)
514 {
515     ACPI_PARSE_OBJECT       *Next;
516
517
518     /* Opcode is parent node */
519     /* First child is the region name */
520
521     Next = Op->Asl.Child;
522
523     /* Second child is the space ID*/
524
525     Next = Next->Asl.Next;
526
527     /* Third child is the region offset */
528
529     Next = Next->Asl.Next;
530
531     /* Fourth child is the region length */
532
533     Next = Next->Asl.Next;
534     if (Next->Asl.ParseOpcode == PARSEOP_INTEGER)
535     {
536         Op->Asl.Value.Integer = Next->Asl.Value.Integer;
537     }
538     else
539     {
540         Op->Asl.Value.Integer = ACPI_UINT64_MAX;
541     }
542 }
543
544
545 /*******************************************************************************
546  *
547  * FUNCTION:    OpnDoBuffer
548  *
549  * PARAMETERS:  Op        - The parent parse node
550  *
551  * RETURN:      None
552  *
553  * DESCRIPTION: Construct the AML operands for the BUFFER ASL keyword. We
554  *              build a single raw byte buffer from the initialization nodes,
555  *              each parse node contains a buffer byte.
556  *
557  ******************************************************************************/
558
559 static void
560 OpnDoBuffer (
561     ACPI_PARSE_OBJECT       *Op)
562 {
563     ACPI_PARSE_OBJECT       *InitializerOp;
564     ACPI_PARSE_OBJECT       *BufferLengthOp;
565
566     /* Optional arguments for this opcode with defaults */
567
568     UINT32                  BufferLength = 0;
569
570
571     /* Opcode and package length first */
572     /* Buffer Length is next, followed by the initializer list */
573
574     BufferLengthOp = Op->Asl.Child;
575     InitializerOp = BufferLengthOp->Asl.Next;
576
577     /*
578      * If the BufferLength is not an INTEGER or was not specified in the ASL
579      * (DEFAULT_ARG), it is a TermArg that is
580      * evaluated at run-time, and we are therefore finished.
581      */
582     if ((BufferLengthOp->Asl.ParseOpcode != PARSEOP_INTEGER) &&
583         (BufferLengthOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
584     {
585         return;
586     }
587
588     /*
589      * We want to count the number of items in the initializer list, because if
590      * it is larger than the buffer length, we will define the buffer size
591      * to be the size of the initializer list (as per the ACPI Specification)
592      */
593     switch (InitializerOp->Asl.ParseOpcode)
594     {
595     case PARSEOP_INTEGER:
596     case PARSEOP_BYTECONST:
597     case PARSEOP_WORDCONST:
598     case PARSEOP_DWORDCONST:
599
600         /* The peer list contains the byte list (if any...) */
601
602         while (InitializerOp)
603         {
604             /* For buffers, this is a list of raw bytes */
605
606             InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
607             InitializerOp->Asl.AmlLength = 1;
608             InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
609
610             BufferLength++;
611             InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
612         }
613         break;
614
615     case PARSEOP_STRING_LITERAL:
616
617         /*
618          * Only one initializer, the string. Buffer must be big enough to hold
619          * the string plus the null termination byte
620          */
621         BufferLength = strlen (InitializerOp->Asl.Value.String) + 1;
622
623         InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
624         InitializerOp->Asl.AmlLength = BufferLength;
625         InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
626         break;
627
628     case PARSEOP_RAW_DATA:
629
630         /* Buffer nodes are already initialized (e.g. Unicode operator) */
631         return;
632
633     case PARSEOP_DEFAULT_ARG:
634         break;
635
636     default:
637
638         AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, InitializerOp,
639             "Unknown buffer initializer opcode");
640         printf ("Unknown buffer initializer opcode [%s]\n",
641             UtGetOpName (InitializerOp->Asl.ParseOpcode));
642         return;
643     }
644
645     /* Check if initializer list is longer than the buffer length */
646
647     if (BufferLengthOp->Asl.Value.Integer > BufferLength)
648     {
649         BufferLength = (UINT32) BufferLengthOp->Asl.Value.Integer;
650     }
651
652     if (!BufferLength)
653     {
654         /* No length AND no items -- issue notice */
655
656         AslError (ASL_REMARK, ASL_MSG_BUFFER_LENGTH, BufferLengthOp, NULL);
657
658         /* But go ahead and put the buffer length of zero into the AML */
659     }
660
661     /*
662      * Just set the buffer size node to be the buffer length, regardless
663      * of whether it was previously an integer or a default_arg placeholder
664      */
665     BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
666     BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP;
667     BufferLengthOp->Asl.Value.Integer = BufferLength;
668
669     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
670
671     /* Remaining nodes are handled via the tree walk */
672 }
673
674
675 /*******************************************************************************
676  *
677  * FUNCTION:    OpnDoPackage
678  *
679  * PARAMETERS:  Op        - The parent parse node
680  *
681  * RETURN:      None
682  *
683  * DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword. NOTE:
684  *              can only be called after constants have been folded, to ensure
685  *              that the PackageLength operand has been fully reduced.
686  *
687  ******************************************************************************/
688
689 void
690 OpnDoPackage (
691     ACPI_PARSE_OBJECT       *Op)
692 {
693     ACPI_PARSE_OBJECT       *InitializerOp;
694     ACPI_PARSE_OBJECT       *PackageLengthOp;
695     UINT32                  PackageLength = 0;
696
697
698     /* Opcode and package length first, followed by the initializer list */
699
700     PackageLengthOp = Op->Asl.Child;
701     InitializerOp = PackageLengthOp->Asl.Next;
702
703     /* Count the number of items in the initializer list */
704
705     if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
706     {
707         /* The peer list contains the byte list (if any...) */
708
709         while (InitializerOp)
710         {
711             PackageLength++;
712             InitializerOp = InitializerOp->Asl.Next;
713         }
714     }
715
716     /* If package length is a constant, compare to the initializer list */
717
718     if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
719         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST))
720     {
721         if (PackageLengthOp->Asl.Value.Integer > PackageLength)
722         {
723             /*
724              * Allow package length to be longer than the initializer
725              * list -- but if the length of initializer list is nonzero,
726              * issue a message since this is probably a coding error,
727              * even though technically legal.
728              */
729             if (PackageLength > 0)
730             {
731                 AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT,
732                     PackageLengthOp, NULL);
733             }
734
735             PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer;
736         }
737         else if (PackageLengthOp->Asl.Value.Integer < PackageLength)
738         {
739             /*
740              * The package length is smaller than the length of the
741              * initializer list. This is an error as per the ACPI spec.
742              */
743             AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG,
744                 PackageLengthOp, NULL);
745         }
746     }
747
748     if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
749     {
750         /*
751          * This is the case if the PackageLength was left empty - Package()
752          * The package length becomes the length of the initializer list
753          */
754         Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER;
755         Op->Asl.Child->Asl.Value.Integer = PackageLength;
756
757         /* Set the AML opcode */
758
759         (void) OpcSetOptimalIntegerSize (Op->Asl.Child);
760     }
761
762     /* If not a variable-length package, check for a zero package length */
763
764     if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
765         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST)   ||
766         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_ZERO)         ||
767         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG))
768     {
769         if (!PackageLength)
770         {
771             /* No length AND no initializer list -- issue a remark */
772
773             AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH,
774                 PackageLengthOp, NULL);
775
776             /* But go ahead and put the buffer length of zero into the AML */
777         }
778     }
779
780     /*
781      * If the PackageLength is a constant <= 255, we can change the
782      * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode.
783      */
784     if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
785             (Op->Asl.Child->Asl.Value.Integer <= 255))  ||
786         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) ||
787         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)||
788         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO))
789     {
790         Op->Asl.AmlOpcode = AML_PACKAGE_OP;
791         Op->Asl.ParseOpcode = PARSEOP_PACKAGE;
792
793         /*
794          * Just set the package size node to be the package length, regardless
795          * of whether it was previously an integer or a default_arg placeholder
796          */
797         PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
798         PackageLengthOp->Asl.AmlLength = 1;
799         PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
800         PackageLengthOp->Asl.Value.Integer = PackageLength;
801     }
802
803     /* Remaining nodes are handled via the tree walk */
804 }
805
806
807 /*******************************************************************************
808  *
809  * FUNCTION:    OpnDoLoadTable
810  *
811  * PARAMETERS:  Op        - The parent parse node
812  *
813  * RETURN:      None
814  *
815  * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword.
816  *
817  ******************************************************************************/
818
819 static void
820 OpnDoLoadTable (
821     ACPI_PARSE_OBJECT       *Op)
822 {
823     ACPI_PARSE_OBJECT       *Next;
824
825
826     /* Opcode is parent node */
827     /* First child is the table signature */
828
829     Next = Op->Asl.Child;
830
831     /* Second child is the OEM ID*/
832
833     Next = Next->Asl.Next;
834
835     /* Third child is the OEM table ID */
836
837     Next = Next->Asl.Next;
838
839     /* Fourth child is the RootPath string */
840
841     Next = Next->Asl.Next;
842     if (Next->Asl.ParseOpcode == PARSEOP_ZERO)
843     {
844         Next->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
845         Next->Asl.Value.String = "\\";
846         Next->Asl.AmlLength = 2;
847         OpcGenerateAmlOpcode (Next);
848     }
849
850 #ifdef ASL_FUTURE_IMPLEMENTATION
851
852     /* TBD: NOT IMPLEMENTED */
853     /* Fifth child is the [optional] ParameterPathString */
854     /* Sixth child is the [optional] ParameterData */
855
856     Next = Next->Asl.Next;
857     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
858     {
859         Next->Asl.AmlLength = 1;
860         Next->Asl.ParseOpcode = ZERO;
861         OpcGenerateAmlOpcode (Next);
862     }
863
864
865     Next = Next->Asl.Next;
866     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
867     {
868         Next->Asl.AmlLength = 1;
869         Next->Asl.ParseOpcode = ZERO;
870         OpcGenerateAmlOpcode (Next);
871     }
872 #endif
873 }
874
875
876 /*******************************************************************************
877  *
878  * FUNCTION:    OpnDoDefinitionBlock
879  *
880  * PARAMETERS:  Op        - The parent parse node
881  *
882  * RETURN:      None
883  *
884  * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword
885  *
886  ******************************************************************************/
887
888 static void
889 OpnDoDefinitionBlock (
890     ACPI_PARSE_OBJECT       *Op)
891 {
892     ACPI_PARSE_OBJECT       *Child;
893     ACPI_SIZE               Length;
894     UINT32                  i;
895     char                    *Filename;
896
897
898     /*
899      * These nodes get stuffed into the table header. They are special
900      * cased when the table is written to the output file.
901      *
902      * Mark all of these nodes as non-usable so they won't get output
903      * as AML opcodes!
904      */
905
906     /* Get AML filename. Use it if non-null */
907
908     Child = Op->Asl.Child;
909     if (Child->Asl.Value.Buffer  &&
910         *Child->Asl.Value.Buffer &&
911         (Gbl_UseDefaultAmlFilename))
912     {
913         /*
914          * We will use the AML filename that is embedded in the source file
915          * for the output filename.
916          */
917         Filename = UtStringCacheCalloc (strlen (Gbl_DirectoryPath) +
918             strlen ((char *) Child->Asl.Value.Buffer) + 1);
919
920         /* Prepend the current directory path */
921
922         strcpy (Filename, Gbl_DirectoryPath);
923         strcat (Filename, (char *) Child->Asl.Value.Buffer);
924
925         Gbl_OutputFilenamePrefix = Filename;
926         UtConvertBackslashes (Gbl_OutputFilenamePrefix);
927     }
928
929     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
930
931     /* Signature */
932
933     Child = Child->Asl.Next;
934     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
935     if (Child->Asl.Value.String)
936     {
937         Gbl_TableSignature = Child->Asl.Value.String;
938         if (strlen (Gbl_TableSignature) != ACPI_NAME_SIZE)
939         {
940             AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
941                 "Length is not exactly 4");
942         }
943
944         for (i = 0; i < ACPI_NAME_SIZE; i++)
945         {
946             if (!isalnum ((int) Gbl_TableSignature[i]))
947             {
948                 AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
949                     "Contains non-alphanumeric characters");
950             }
951         }
952     }
953
954     /* Revision */
955
956     Child = Child->Asl.Next;
957     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
958     /*
959      * We used the revision to set the integer width earlier
960      */
961
962     /* OEMID */
963
964     Child = Child->Asl.Next;
965     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
966
967     /* OEM TableID */
968
969     Child = Child->Asl.Next;
970     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
971     if (Child->Asl.Value.String)
972     {
973         Length = strlen (Child->Asl.Value.String);
974         Gbl_TableId = UtStringCacheCalloc (Length + 1);
975         strcpy (Gbl_TableId, Child->Asl.Value.String);
976
977         /*
978          * Convert anything non-alphanumeric to an underscore. This
979          * allows us to use the TableID to generate unique C symbols.
980          */
981         for (i = 0; i < Length; i++)
982         {
983             if (!isalnum ((int) Gbl_TableId[i]))
984             {
985                 Gbl_TableId[i] = '_';
986             }
987         }
988     }
989
990     /* OEM Revision */
991
992     Child = Child->Asl.Next;
993     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
994 }
995
996
997 /*******************************************************************************
998  *
999  * FUNCTION:    UtGetArg
1000  *
1001  * PARAMETERS:  Op              - Get an argument for this op
1002  *              Argn            - Nth argument to get
1003  *
1004  * RETURN:      The argument (as an Op object). NULL if argument does not exist
1005  *
1006  * DESCRIPTION: Get the specified op's argument (peer)
1007  *
1008  ******************************************************************************/
1009
1010 ACPI_PARSE_OBJECT *
1011 UtGetArg (
1012     ACPI_PARSE_OBJECT       *Op,
1013     UINT32                  Argn)
1014 {
1015     ACPI_PARSE_OBJECT       *Arg = NULL;
1016
1017
1018     /* Get the requested argument object */
1019
1020     Arg = Op->Asl.Child;
1021     while (Arg && Argn)
1022     {
1023         Argn--;
1024         Arg = Arg->Asl.Next;
1025     }
1026
1027     return (Arg);
1028 }
1029
1030
1031 /*******************************************************************************
1032  *
1033  * FUNCTION:    OpnAttachNameToNode
1034  *
1035  * PARAMETERS:  Op        - The parent parse node
1036  *
1037  * RETURN:      None
1038  *
1039  * DESCRIPTION: For the named ASL/AML operators, get the actual name from the
1040  *              argument list and attach it to the parent node so that we
1041  *              can get to it quickly later.
1042  *
1043  ******************************************************************************/
1044
1045 static void
1046 OpnAttachNameToNode (
1047     ACPI_PARSE_OBJECT       *Op)
1048 {
1049     ACPI_PARSE_OBJECT       *Child = NULL;
1050
1051
1052     switch (Op->Asl.AmlOpcode)
1053     {
1054     case AML_DATA_REGION_OP:
1055     case AML_DEVICE_OP:
1056     case AML_EVENT_OP:
1057     case AML_EXTERNAL_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_DEFINITION_BLOCK:
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     default:
1189
1190         break;
1191     }
1192
1193     /* TBD: move */
1194
1195     OpnAttachNameToNode (Op);
1196 }