xref: /illumos-gate/usr/src/cmd/acpi/iasl/asloperands.c (revision bc36eafd)
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 "aslcompiler.h"
45 #include "aslcompiler.y.h"
46 #include "amlcode.h"
47 
48 #define _COMPONENT          ACPI_COMPILER
49         ACPI_MODULE_NAME    ("asloperands")
50 
51 /* Local prototypes */
52 
53 static void
54 OpnDoField (
55     ACPI_PARSE_OBJECT       *Op);
56 
57 static void
58 OpnDoBankField (
59     ACPI_PARSE_OBJECT       *Op);
60 
61 static void
62 OpnDoBuffer (
63     ACPI_PARSE_OBJECT       *Op);
64 
65 static void
66 OpnDoDefinitionBlock (
67     ACPI_PARSE_OBJECT       *Op);
68 
69 static void
70 OpnDoFieldCommon (
71     ACPI_PARSE_OBJECT       *FieldOp,
72     ACPI_PARSE_OBJECT       *Op);
73 
74 static void
75 OpnDoIndexField (
76     ACPI_PARSE_OBJECT       *Op);
77 
78 static void
79 OpnDoLoadTable (
80     ACPI_PARSE_OBJECT       *Op);
81 
82 static void
83 OpnDoMethod (
84     ACPI_PARSE_OBJECT       *Op);
85 
86 static void
87 OpnDoMutex (
88     ACPI_PARSE_OBJECT       *Op);
89 
90 static void
91 OpnDoRegion (
92     ACPI_PARSE_OBJECT       *Op);
93 
94 static void
95 OpnAttachNameToNode (
96     ACPI_PARSE_OBJECT       *Op);
97 
98 
99 /*******************************************************************************
100  *
101  * FUNCTION:    OpnDoMutex
102  *
103  * PARAMETERS:  Op        - The parent parse node
104  *
105  * RETURN:      None
106  *
107  * DESCRIPTION: Construct the operands for the MUTEX ASL keyword.
108  *
109  ******************************************************************************/
110 
111 static void
112 OpnDoMutex (
113     ACPI_PARSE_OBJECT       *Op)
114 {
115     ACPI_PARSE_OBJECT       *Next;
116 
117 
118     Next = Op->Asl.Child;
119     Next = Next->Asl.Next;
120 
121     if (Next->Asl.Value.Integer > 15)
122     {
123         AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
124     }
125     return;
126 }
127 
128 
129 /*******************************************************************************
130  *
131  * FUNCTION:    OpnDoMethod
132  *
133  * PARAMETERS:  Op        - The parent parse node
134  *
135  * RETURN:      None
136  *
137  * DESCRIPTION: Construct the operands for the METHOD ASL keyword.
138  *
139  ******************************************************************************/
140 
141 static void
142 OpnDoMethod (
143     ACPI_PARSE_OBJECT       *Op)
144 {
145     ACPI_PARSE_OBJECT       *Next;
146 
147     /* Optional arguments for this opcode with defaults */
148 
149     UINT8                   NumArgs = 0;
150     UINT8                   Serialized = 0;
151     UINT8                   Concurrency = 0;
152     UINT8                   MethodFlags;
153 
154 
155     /* Opcode and package length first */
156     /* Method name */
157 
158     Next = Op->Asl.Child;
159 
160     /* Num args */
161 
162     Next = Next->Asl.Next;
163     if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
164     {
165         NumArgs = (UINT8) Next->Asl.Value.Integer;
166         Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
167     }
168 
169     /* Serialized Flag */
170 
171     Next = Next->Asl.Next;
172     if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
173     {
174         Serialized = (UINT8) Next->Asl.Value.Integer;
175         Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
176     }
177 
178     /* Concurrency value (valid values are 0-15) */
179 
180     Next = Next->Asl.Next;
181     if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
182     {
183         /* This is a ByteConstExpr, so eval the constant now */
184 
185         OpcAmlConstantWalk (Next, 0, NULL);
186 
187         if (Next->Asl.Value.Integer > 15)
188         {
189             AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
190         }
191 
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 }
1197