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 "aslcompiler.h"
46 #include "aslcompiler.y.h"
47 #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         UtConvertBackslashes (Gbl_OutputFilenamePrefix);
926     }
927     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
928 
929     /* Signature */
930 
931     Child = Child->Asl.Next;
932     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
933     if (Child->Asl.Value.String)
934     {
935         Gbl_TableSignature = Child->Asl.Value.String;
936         if (ACPI_STRLEN (Gbl_TableSignature) != 4)
937         {
938             AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
939                 "Length not exactly 4");
940         }
941 
942         for (i = 0; i < 4; i++)
943         {
944             if (!isalnum ((int) Gbl_TableSignature[i]))
945             {
946                 AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
947                     "Contains non-alphanumeric characters");
948             }
949         }
950     }
951 
952     /* Revision */
953 
954     Child = Child->Asl.Next;
955     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
956     /*
957      * We used the revision to set the integer width earlier
958      */
959 
960     /* OEMID */
961 
962     Child = Child->Asl.Next;
963     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
964 
965     /* OEM TableID */
966 
967     Child = Child->Asl.Next;
968     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
969     if (Child->Asl.Value.String)
970     {
971         Length = ACPI_STRLEN (Child->Asl.Value.String);
972         Gbl_TableId = AcpiOsAllocate (Length + 1);
973         ACPI_STRCPY (Gbl_TableId, Child->Asl.Value.String);
974 
975         /*
976          * Convert anything non-alphanumeric to an underscore. This
977          * allows us to use the TableID to generate unique C symbols.
978          */
979         for (i = 0; i < Length; i++)
980         {
981             if (!isalnum ((int) Gbl_TableId[i]))
982             {
983                 Gbl_TableId[i] = '_';
984             }
985         }
986     }
987 
988     /* OEM Revision */
989 
990     Child = Child->Asl.Next;
991     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
992 }
993 
994 
995 /*******************************************************************************
996  *
997  * FUNCTION:    UtGetArg
998  *
999  * PARAMETERS:  Op              - Get an argument for this op
1000  *              Argn            - Nth argument to get
1001  *
1002  * RETURN:      The argument (as an Op object). NULL if argument does not exist
1003  *
1004  * DESCRIPTION: Get the specified op's argument (peer)
1005  *
1006  ******************************************************************************/
1007 
1008 ACPI_PARSE_OBJECT *
1009 UtGetArg (
1010     ACPI_PARSE_OBJECT       *Op,
1011     UINT32                  Argn)
1012 {
1013     ACPI_PARSE_OBJECT       *Arg = NULL;
1014 
1015 
1016     /* Get the requested argument object */
1017 
1018     Arg = Op->Asl.Child;
1019     while (Arg && Argn)
1020     {
1021         Argn--;
1022         Arg = Arg->Asl.Next;
1023     }
1024 
1025     return (Arg);
1026 }
1027 
1028 
1029 /*******************************************************************************
1030  *
1031  * FUNCTION:    OpnAttachNameToNode
1032  *
1033  * PARAMETERS:  Op        - The parent parse node
1034  *
1035  * RETURN:      None
1036  *
1037  * DESCRIPTION: For the named ASL/AML operators, get the actual name from the
1038  *              argument list and attach it to the parent node so that we
1039  *              can get to it quickly later.
1040  *
1041  ******************************************************************************/
1042 
1043 static void
1044 OpnAttachNameToNode (
1045     ACPI_PARSE_OBJECT       *Op)
1046 {
1047     ACPI_PARSE_OBJECT       *Child = NULL;
1048 
1049 
1050     if (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)
1051     {
1052         Child = UtGetArg (Op, 0);
1053     }
1054     else switch (Op->Asl.AmlOpcode)
1055     {
1056     case AML_DATA_REGION_OP:
1057     case AML_DEVICE_OP:
1058     case AML_EVENT_OP:
1059     case AML_METHOD_OP:
1060     case AML_MUTEX_OP:
1061     case AML_REGION_OP:
1062     case AML_POWER_RES_OP:
1063     case AML_PROCESSOR_OP:
1064     case AML_THERMAL_ZONE_OP:
1065     case AML_NAME_OP:
1066     case AML_SCOPE_OP:
1067 
1068         Child = UtGetArg (Op, 0);
1069         break;
1070 
1071     case AML_ALIAS_OP:
1072 
1073         Child = UtGetArg (Op, 1);
1074         break;
1075 
1076     case AML_CREATE_BIT_FIELD_OP:
1077     case AML_CREATE_BYTE_FIELD_OP:
1078     case AML_CREATE_WORD_FIELD_OP:
1079     case AML_CREATE_DWORD_FIELD_OP:
1080     case AML_CREATE_QWORD_FIELD_OP:
1081 
1082         Child = UtGetArg (Op, 2);
1083         break;
1084 
1085     case AML_CREATE_FIELD_OP:
1086 
1087         Child = UtGetArg (Op, 3);
1088         break;
1089 
1090     case AML_BANK_FIELD_OP:
1091     case AML_INDEX_FIELD_OP:
1092     case AML_FIELD_OP:
1093 
1094         return;
1095 
1096     default:
1097 
1098         return;
1099     }
1100 
1101     if (Child)
1102     {
1103         UtAttachNamepathToOwner (Op, Child);
1104     }
1105 }
1106 
1107 
1108 /*******************************************************************************
1109  *
1110  * FUNCTION:    OpnGenerateAmlOperands
1111  *
1112  * PARAMETERS:  Op        - The parent parse node
1113  *
1114  * RETURN:      None
1115  *
1116  * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more
1117  *              complex AML opcodes require processing of the child nodes
1118  *              (arguments/operands).
1119  *
1120  ******************************************************************************/
1121 
1122 void
1123 OpnGenerateAmlOperands (
1124     ACPI_PARSE_OBJECT       *Op)
1125 {
1126 
1127 
1128     if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)
1129     {
1130         return;
1131     }
1132 
1133     switch (Op->Asl.ParseOpcode)
1134     {
1135     case PARSEOP_DEFINITIONBLOCK:
1136 
1137         OpnDoDefinitionBlock (Op);
1138         break;
1139 
1140     case PARSEOP_METHOD:
1141 
1142         OpnDoMethod (Op);
1143         break;
1144 
1145     case PARSEOP_MUTEX:
1146 
1147         OpnDoMutex (Op);
1148         break;
1149 
1150     case PARSEOP_FIELD:
1151 
1152         OpnDoField (Op);
1153         break;
1154 
1155     case PARSEOP_INDEXFIELD:
1156 
1157         OpnDoIndexField (Op);
1158         break;
1159 
1160     case PARSEOP_BANKFIELD:
1161 
1162         OpnDoBankField (Op);
1163         break;
1164 
1165     case PARSEOP_BUFFER:
1166 
1167         OpnDoBuffer (Op);
1168         break;
1169 
1170     case PARSEOP_LOADTABLE:
1171 
1172         OpnDoLoadTable (Op);
1173         break;
1174 
1175     case PARSEOP_OPERATIONREGION:
1176 
1177         OpnDoRegion (Op);
1178         break;
1179 
1180     case PARSEOP_RESOURCETEMPLATE:
1181 
1182         RsDoResourceTemplate (Op);
1183         break;
1184 
1185     case PARSEOP_NAMESEG:
1186     case PARSEOP_NAMESTRING:
1187     case PARSEOP_METHODCALL:
1188     case PARSEOP_STRING_LITERAL:
1189 
1190         break;
1191 
1192     default:
1193 
1194         break;
1195     }
1196 
1197     /* TBD: move */
1198 
1199     OpnAttachNameToNode (Op);
1200 }
1201