xref: /freebsd/sys/contrib/dev/acpica/compiler/asloperands.c (revision 4436b51dff5736e74da464946049ea6899a88938)
1 /******************************************************************************
2  *
3  * Module Name: asloperands - AML operand processing
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include <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         Concurrency = (UINT8) Next->Asl.Value.Integer;
192     }
193 
194     /* Put the bits in their proper places */
195 
196     MethodFlags = (UINT8) ((NumArgs & 0x7) |
197                           ((Serialized & 0x1) << 3) |
198                           ((Concurrency & 0xF) << 4));
199 
200     /* Use the last node for the combined flags byte */
201 
202     Next->Asl.Value.Integer = MethodFlags;
203     Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
204     Next->Asl.AmlLength = 1;
205     Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
206 
207     /* Save the arg count in the first node */
208 
209     Op->Asl.Extra = NumArgs;
210 }
211 
212 
213 /*******************************************************************************
214  *
215  * FUNCTION:    OpnDoFieldCommon
216  *
217  * PARAMETERS:  FieldOp       - Node for an ASL field
218  *              Op            - The parent parse node
219  *
220  * RETURN:      None
221  *
222  * DESCRIPTION: Construct the AML operands for the various field keywords,
223  *              FIELD, BANKFIELD, INDEXFIELD
224  *
225  ******************************************************************************/
226 
227 static void
228 OpnDoFieldCommon (
229     ACPI_PARSE_OBJECT       *FieldOp,
230     ACPI_PARSE_OBJECT       *Op)
231 {
232     ACPI_PARSE_OBJECT       *Next;
233     ACPI_PARSE_OBJECT       *PkgLengthNode;
234     UINT32                  CurrentBitOffset;
235     UINT32                  NewBitOffset;
236     UINT8                   AccessType;
237     UINT8                   LockRule;
238     UINT8                   UpdateRule;
239     UINT8                   FieldFlags;
240     UINT32                  MinimumLength;
241 
242 
243     /* AccessType -- not optional, so no need to check for DEFAULT_ARG */
244 
245     AccessType = (UINT8) Op->Asl.Value.Integer;
246     Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
247 
248     /* Set the access type in the parent (field) node for use later */
249 
250     FieldOp->Asl.Value.Integer = AccessType;
251 
252     /* LockRule -- not optional, so no need to check for DEFAULT_ARG */
253 
254     Next = Op->Asl.Next;
255     LockRule = (UINT8) Next->Asl.Value.Integer;
256     Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
257 
258     /* UpdateRule -- not optional, so no need to check for DEFAULT_ARG */
259 
260     Next = Next->Asl.Next;
261     UpdateRule = (UINT8) Next->Asl.Value.Integer;
262 
263     /*
264      * Generate the flags byte. The various fields are already
265      * in the right bit position via translation from the
266      * keywords by the parser.
267      */
268     FieldFlags = (UINT8) (AccessType | LockRule | UpdateRule);
269 
270     /* Use the previous node to be the FieldFlags node */
271 
272     /* Set the node to RAW_DATA */
273 
274     Next->Asl.Value.Integer = FieldFlags;
275     Next->Asl.AmlOpcode     = AML_RAW_DATA_BYTE;
276     Next->Asl.AmlLength     = 1;
277     Next->Asl.ParseOpcode   = PARSEOP_RAW_DATA;
278 
279     /* Process the FieldUnitList */
280 
281     Next = Next->Asl.Next;
282     CurrentBitOffset = 0;
283 
284     while (Next)
285     {
286         /* Save the offset of this field unit */
287 
288         Next->Asl.ExtraValue = CurrentBitOffset;
289 
290         switch (Next->Asl.ParseOpcode)
291         {
292         case PARSEOP_ACCESSAS:
293 
294             PkgLengthNode = Next->Asl.Child;
295             AccessType = (UINT8) PkgLengthNode->Asl.Value.Integer;
296 
297             /* Nothing additional to do */
298             break;
299 
300         case PARSEOP_OFFSET:
301 
302             /* New offset into the field */
303 
304             PkgLengthNode = Next->Asl.Child;
305             NewBitOffset = ((UINT32) PkgLengthNode->Asl.Value.Integer) * 8;
306 
307             /*
308              * Examine the specified offset in relation to the
309              * current offset counter.
310              */
311             if (NewBitOffset < CurrentBitOffset)
312             {
313                 /*
314                  * Not allowed to specify a backwards offset!
315                  * Issue error and ignore this node.
316                  */
317                 AslError (ASL_ERROR, ASL_MSG_BACKWARDS_OFFSET, PkgLengthNode,
318                     NULL);
319                 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
320                 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
321             }
322             else if (NewBitOffset == CurrentBitOffset)
323             {
324                 /*
325                  * Offset is redundant; we don't need to output an
326                  * offset opcode. Just set these nodes to default
327                  */
328                 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
329                 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
330             }
331             else
332             {
333                 /*
334                  * Valid new offset - set the value to be inserted into the AML
335                  * and update the offset counter.
336                  */
337                 PkgLengthNode->Asl.Value.Integer =
338                     NewBitOffset - CurrentBitOffset;
339                 CurrentBitOffset = NewBitOffset;
340             }
341             break;
342 
343         case PARSEOP_NAMESEG:
344         case PARSEOP_RESERVED_BYTES:
345 
346             /* Named or reserved field entry */
347 
348             PkgLengthNode     = Next->Asl.Child;
349             NewBitOffset      = (UINT32) PkgLengthNode->Asl.Value.Integer;
350             CurrentBitOffset += NewBitOffset;
351 
352             /* Save the current AccessAs value for error checking later */
353 
354             switch (AccessType)
355             {
356                 case AML_FIELD_ACCESS_ANY:
357                 case AML_FIELD_ACCESS_BYTE:
358                 case AML_FIELD_ACCESS_BUFFER:
359                 default:
360 
361                     MinimumLength = 8;
362                     break;
363 
364                 case AML_FIELD_ACCESS_WORD:
365                     MinimumLength = 16;
366                     break;
367 
368                 case AML_FIELD_ACCESS_DWORD:
369                     MinimumLength = 32;
370                     break;
371 
372                 case AML_FIELD_ACCESS_QWORD:
373                     MinimumLength = 64;
374                     break;
375             }
376 
377             PkgLengthNode->Asl.ExtraValue = MinimumLength;
378             break;
379 
380         default:
381 
382             /* All supported field opcodes must appear above */
383 
384             break;
385         }
386 
387         /* Move on to next entry in the field list */
388 
389         Next = Next->Asl.Next;
390     }
391 }
392 
393 
394 /*******************************************************************************
395  *
396  * FUNCTION:    OpnDoField
397  *
398  * PARAMETERS:  Op        - The parent parse node
399  *
400  * RETURN:      None
401  *
402  * DESCRIPTION: Construct the AML operands for the FIELD ASL keyword
403  *
404  ******************************************************************************/
405 
406 static void
407 OpnDoField (
408     ACPI_PARSE_OBJECT       *Op)
409 {
410     ACPI_PARSE_OBJECT       *Next;
411 
412 
413     /* Opcode is parent node */
414     /* First child is field name */
415 
416     Next = Op->Asl.Child;
417 
418     /* Second child is the AccessType */
419 
420     OpnDoFieldCommon (Op, Next->Asl.Next);
421 }
422 
423 
424 /*******************************************************************************
425  *
426  * FUNCTION:    OpnDoIndexField
427  *
428  * PARAMETERS:  Op        - The parent parse node
429  *
430  * RETURN:      None
431  *
432  * DESCRIPTION: Construct the AML operands for the INDEXFIELD ASL keyword
433  *
434  ******************************************************************************/
435 
436 static void
437 OpnDoIndexField (
438     ACPI_PARSE_OBJECT       *Op)
439 {
440     ACPI_PARSE_OBJECT       *Next;
441 
442 
443     /* Opcode is parent node */
444     /* First child is the index name */
445 
446     Next = Op->Asl.Child;
447 
448     /* Second child is the data name */
449 
450     Next = Next->Asl.Next;
451 
452     /* Third child is the AccessType */
453 
454     OpnDoFieldCommon (Op, Next->Asl.Next);
455 }
456 
457 
458 /*******************************************************************************
459  *
460  * FUNCTION:    OpnDoBankField
461  *
462  * PARAMETERS:  Op        - The parent parse node
463  *
464  * RETURN:      None
465  *
466  * DESCRIPTION: Construct the AML operands for the BANKFIELD ASL keyword
467  *
468  ******************************************************************************/
469 
470 static void
471 OpnDoBankField (
472     ACPI_PARSE_OBJECT       *Op)
473 {
474     ACPI_PARSE_OBJECT       *Next;
475 
476 
477     /* Opcode is parent node */
478     /* First child is the region name */
479 
480     Next = Op->Asl.Child;
481 
482     /* Second child is the bank name */
483 
484     Next = Next->Asl.Next;
485 
486     /* Third child is the bank value */
487 
488     Next = Next->Asl.Next;
489 
490     /* Fourth child is the AccessType */
491 
492     OpnDoFieldCommon (Op, Next->Asl.Next);
493 }
494 
495 
496 /*******************************************************************************
497  *
498  * FUNCTION:    OpnDoRegion
499  *
500  * PARAMETERS:  Op        - The parent parse node
501  *
502  * RETURN:      None
503  *
504  * DESCRIPTION: Tries to get the length of the region. Can only do this at
505  *              compile time if the length is a constant.
506  *
507  ******************************************************************************/
508 
509 static void
510 OpnDoRegion (
511     ACPI_PARSE_OBJECT       *Op)
512 {
513     ACPI_PARSE_OBJECT       *Next;
514 
515 
516     /* Opcode is parent node */
517     /* First child is the region name */
518 
519     Next = Op->Asl.Child;
520 
521     /* Second child is the space ID*/
522 
523     Next = Next->Asl.Next;
524 
525     /* Third child is the region offset */
526 
527     Next = Next->Asl.Next;
528 
529     /* Fourth child is the region length */
530 
531     Next = Next->Asl.Next;
532     if (Next->Asl.ParseOpcode == PARSEOP_INTEGER)
533     {
534         Op->Asl.Value.Integer = Next->Asl.Value.Integer;
535     }
536     else
537     {
538         Op->Asl.Value.Integer = ACPI_UINT64_MAX;
539     }
540 }
541 
542 
543 /*******************************************************************************
544  *
545  * FUNCTION:    OpnDoBuffer
546  *
547  * PARAMETERS:  Op        - The parent parse node
548  *
549  * RETURN:      None
550  *
551  * DESCRIPTION: Construct the AML operands for the BUFFER ASL keyword. We
552  *              build a single raw byte buffer from the initialization nodes,
553  *              each parse node contains a buffer byte.
554  *
555  ******************************************************************************/
556 
557 static void
558 OpnDoBuffer (
559     ACPI_PARSE_OBJECT       *Op)
560 {
561     ACPI_PARSE_OBJECT       *InitializerOp;
562     ACPI_PARSE_OBJECT       *BufferLengthOp;
563 
564     /* Optional arguments for this opcode with defaults */
565 
566     UINT32                  BufferLength = 0;
567 
568 
569     /* Opcode and package length first */
570     /* Buffer Length is next, followed by the initializer list */
571 
572     BufferLengthOp = Op->Asl.Child;
573     InitializerOp = BufferLengthOp->Asl.Next;
574 
575     /*
576      * If the BufferLength is not an INTEGER or was not specified in the ASL
577      * (DEFAULT_ARG), it is a TermArg that is
578      * evaluated at run-time, and we are therefore finished.
579      */
580     if ((BufferLengthOp->Asl.ParseOpcode != PARSEOP_INTEGER) &&
581         (BufferLengthOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
582     {
583         return;
584     }
585 
586     /*
587      * We want to count the number of items in the initializer list, because if
588      * it is larger than the buffer length, we will define the buffer size
589      * to be the size of the initializer list (as per the ACPI Specification)
590      */
591     switch (InitializerOp->Asl.ParseOpcode)
592     {
593     case PARSEOP_INTEGER:
594     case PARSEOP_BYTECONST:
595     case PARSEOP_WORDCONST:
596     case PARSEOP_DWORDCONST:
597 
598         /* The peer list contains the byte list (if any...) */
599 
600         while (InitializerOp)
601         {
602             /* For buffers, this is a list of raw bytes */
603 
604             InitializerOp->Asl.AmlOpcode      = AML_RAW_DATA_BYTE;
605             InitializerOp->Asl.AmlLength      = 1;
606             InitializerOp->Asl.ParseOpcode    = PARSEOP_RAW_DATA;
607 
608             BufferLength++;
609             InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
610         }
611         break;
612 
613     case PARSEOP_STRING_LITERAL:
614 
615         /*
616          * Only one initializer, the string. Buffer must be big enough to hold
617          * the string plus the null termination byte
618          */
619         BufferLength = strlen (InitializerOp->Asl.Value.String) + 1;
620 
621         InitializerOp->Asl.AmlOpcode      = AML_RAW_DATA_BUFFER;
622         InitializerOp->Asl.AmlLength      = BufferLength;
623         InitializerOp->Asl.ParseOpcode    = PARSEOP_RAW_DATA;
624         break;
625 
626     case PARSEOP_RAW_DATA:
627 
628         /* Buffer nodes are already initialized (e.g. Unicode operator) */
629         return;
630 
631     case PARSEOP_DEFAULT_ARG:
632         break;
633 
634     default:
635 
636         AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, InitializerOp,
637             "Unknown buffer initializer opcode");
638         printf ("Unknown buffer initializer opcode [%s]\n",
639                         UtGetOpName (InitializerOp->Asl.ParseOpcode));
640         return;
641     }
642 
643     /* Check if initializer list is longer than the buffer length */
644 
645     if (BufferLengthOp->Asl.Value.Integer > BufferLength)
646     {
647         BufferLength = (UINT32) BufferLengthOp->Asl.Value.Integer;
648     }
649 
650     if (!BufferLength)
651     {
652         /* No length AND no items -- issue notice */
653 
654         AslError (ASL_REMARK, ASL_MSG_BUFFER_LENGTH, BufferLengthOp, NULL);
655 
656         /* But go ahead and put the buffer length of zero into the AML */
657     }
658 
659     /*
660      * Just set the buffer size node to be the buffer length, regardless
661      * of whether it was previously an integer or a default_arg placeholder
662      */
663     BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
664     BufferLengthOp->Asl.AmlOpcode     = AML_DWORD_OP;
665     BufferLengthOp->Asl.Value.Integer = BufferLength;
666 
667     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
668 
669     /* Remaining nodes are handled via the tree walk */
670 }
671 
672 
673 /*******************************************************************************
674  *
675  * FUNCTION:    OpnDoPackage
676  *
677  * PARAMETERS:  Op        - The parent parse node
678  *
679  * RETURN:      None
680  *
681  * DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword. NOTE:
682  *              can only be called after constants have been folded, to ensure
683  *              that the PackageLength operand has been fully reduced.
684  *
685  ******************************************************************************/
686 
687 void
688 OpnDoPackage (
689     ACPI_PARSE_OBJECT       *Op)
690 {
691     ACPI_PARSE_OBJECT       *InitializerOp;
692     ACPI_PARSE_OBJECT       *PackageLengthOp;
693     UINT32                  PackageLength = 0;
694 
695 
696     /* Opcode and package length first, followed by the initializer list */
697 
698     PackageLengthOp = Op->Asl.Child;
699     InitializerOp = PackageLengthOp->Asl.Next;
700 
701     /* Count the number of items in the initializer list */
702 
703     if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
704     {
705         /* The peer list contains the byte list (if any...) */
706 
707         while (InitializerOp)
708         {
709             PackageLength++;
710             InitializerOp = InitializerOp->Asl.Next;
711         }
712     }
713 
714     /* If package length is a constant, compare to the initializer list */
715 
716     if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
717         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST))
718     {
719         if (PackageLengthOp->Asl.Value.Integer > PackageLength)
720         {
721             /*
722              * Allow package length to be longer than the initializer
723              * list -- but if the length of initializer list is nonzero,
724              * issue a message since this is probably a coding error,
725              * even though technically legal.
726              */
727             if (PackageLength > 0)
728             {
729                 AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT,
730                     PackageLengthOp, NULL);
731             }
732 
733             PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer;
734         }
735         else if (PackageLengthOp->Asl.Value.Integer < PackageLength)
736         {
737             /*
738              * The package length is smaller than the length of the
739              * initializer list. This is an error as per the ACPI spec.
740              */
741             AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG,
742                 PackageLengthOp, NULL);
743         }
744     }
745 
746     if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
747     {
748         /*
749          * This is the case if the PackageLength was left empty - Package()
750          * The package length becomes the length of the initializer list
751          */
752         Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER;
753         Op->Asl.Child->Asl.Value.Integer = PackageLength;
754 
755         /* Set the AML opcode */
756 
757         (void) OpcSetOptimalIntegerSize (Op->Asl.Child);
758     }
759 
760     /* If not a variable-length package, check for a zero package length */
761 
762     if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
763         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST)   ||
764         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_ZERO)         ||
765         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG))
766     {
767         if (!PackageLength)
768         {
769             /* No length AND no initializer list -- issue a remark */
770 
771             AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH,
772                 PackageLengthOp, NULL);
773 
774             /* But go ahead and put the buffer length of zero into the AML */
775         }
776     }
777 
778     /*
779      * If the PackageLength is a constant <= 255, we can change the
780      * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode.
781      */
782     if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
783             (Op->Asl.Child->Asl.Value.Integer <= 255))  ||
784         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) ||
785         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)||
786         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO))
787     {
788         Op->Asl.AmlOpcode = AML_PACKAGE_OP;
789         Op->Asl.ParseOpcode = PARSEOP_PACKAGE;
790 
791         /*
792          * Just set the package size node to be the package length, regardless
793          * of whether it was previously an integer or a default_arg placeholder
794          */
795         PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
796         PackageLengthOp->Asl.AmlLength = 1;
797         PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
798         PackageLengthOp->Asl.Value.Integer = PackageLength;
799     }
800 
801     /* Remaining nodes are handled via the tree walk */
802 }
803 
804 
805 /*******************************************************************************
806  *
807  * FUNCTION:    OpnDoLoadTable
808  *
809  * PARAMETERS:  Op        - The parent parse node
810  *
811  * RETURN:      None
812  *
813  * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword.
814  *
815  ******************************************************************************/
816 
817 static void
818 OpnDoLoadTable (
819     ACPI_PARSE_OBJECT       *Op)
820 {
821     ACPI_PARSE_OBJECT       *Next;
822 
823 
824     /* Opcode is parent node */
825     /* First child is the table signature */
826 
827     Next = Op->Asl.Child;
828 
829     /* Second child is the OEM ID*/
830 
831     Next = Next->Asl.Next;
832 
833     /* Third child is the OEM table ID */
834 
835     Next = Next->Asl.Next;
836 
837     /* Fourth child is the RootPath string */
838 
839     Next = Next->Asl.Next;
840     if (Next->Asl.ParseOpcode == PARSEOP_ZERO)
841     {
842         Next->Asl.ParseOpcode    = PARSEOP_STRING_LITERAL;
843         Next->Asl.Value.String   = "\\";
844         Next->Asl.AmlLength      = 2;
845         OpcGenerateAmlOpcode (Next);
846     }
847 
848 #ifdef ASL_FUTURE_IMPLEMENTATION
849 
850     /* TBD: NOT IMPLEMENTED */
851     /* Fifth child is the [optional] ParameterPathString */
852     /* Sixth child is the [optional] ParameterData */
853 
854     Next = Next->Asl.Next;
855     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
856     {
857         Next->Asl.AmlLength = 1;
858         Next->Asl.ParseOpcode = ZERO;
859         OpcGenerateAmlOpcode (Next);
860     }
861 
862 
863     Next = Next->Asl.Next;
864     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
865     {
866         Next->Asl.AmlLength = 1;
867         Next->Asl.ParseOpcode = ZERO;
868         OpcGenerateAmlOpcode (Next);
869     }
870 #endif
871 }
872 
873 
874 /*******************************************************************************
875  *
876  * FUNCTION:    OpnDoDefinitionBlock
877  *
878  * PARAMETERS:  Op        - The parent parse node
879  *
880  * RETURN:      None
881  *
882  * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword
883  *
884  ******************************************************************************/
885 
886 static void
887 OpnDoDefinitionBlock (
888     ACPI_PARSE_OBJECT       *Op)
889 {
890     ACPI_PARSE_OBJECT       *Child;
891     ACPI_SIZE               Length;
892     UINT32                  i;
893     char                    *Filename;
894 
895 
896     /*
897      * These nodes get stuffed into the table header. They are special
898      * cased when the table is written to the output file.
899      *
900      * Mark all of these nodes as non-usable so they won't get output
901      * as AML opcodes!
902      */
903 
904     /* Get AML filename. Use it if non-null */
905 
906     Child = Op->Asl.Child;
907     if (Child->Asl.Value.Buffer  &&
908         *Child->Asl.Value.Buffer &&
909         (Gbl_UseDefaultAmlFilename))
910     {
911         /*
912          * We will use the AML filename that is embedded in the source file
913          * for the output filename.
914          */
915         Filename = UtStringCacheCalloc (strlen (Gbl_DirectoryPath) +
916             strlen ((char *) Child->Asl.Value.Buffer) + 1);
917 
918         /* Prepend the current directory path */
919 
920         strcpy (Filename, Gbl_DirectoryPath);
921         strcat (Filename, (char *) Child->Asl.Value.Buffer);
922 
923         Gbl_OutputFilenamePrefix = Filename;
924         UtConvertBackslashes (Gbl_OutputFilenamePrefix);
925     }
926     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
927 
928     /* Signature */
929 
930     Child = Child->Asl.Next;
931     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
932     if (Child->Asl.Value.String)
933     {
934         Gbl_TableSignature = Child->Asl.Value.String;
935         if (strlen (Gbl_TableSignature) != ACPI_NAME_SIZE)
936         {
937             AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
938                 "Length is not exactly 4");
939         }
940 
941         for (i = 0; i < ACPI_NAME_SIZE; i++)
942         {
943             if (!isalnum ((int) Gbl_TableSignature[i]))
944             {
945                 AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
946                     "Contains non-alphanumeric characters");
947             }
948         }
949     }
950 
951     /* Revision */
952 
953     Child = Child->Asl.Next;
954     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
955     /*
956      * We used the revision to set the integer width earlier
957      */
958 
959     /* OEMID */
960 
961     Child = Child->Asl.Next;
962     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
963 
964     /* OEM TableID */
965 
966     Child = Child->Asl.Next;
967     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
968     if (Child->Asl.Value.String)
969     {
970         Length = strlen (Child->Asl.Value.String);
971         Gbl_TableId = UtStringCacheCalloc (Length + 1);
972         strcpy (Gbl_TableId, Child->Asl.Value.String);
973 
974         /*
975          * Convert anything non-alphanumeric to an underscore. This
976          * allows us to use the TableID to generate unique C symbols.
977          */
978         for (i = 0; i < Length; i++)
979         {
980             if (!isalnum ((int) Gbl_TableId[i]))
981             {
982                 Gbl_TableId[i] = '_';
983             }
984         }
985     }
986 
987     /* OEM Revision */
988 
989     Child = Child->Asl.Next;
990     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
991 }
992 
993 
994 /*******************************************************************************
995  *
996  * FUNCTION:    UtGetArg
997  *
998  * PARAMETERS:  Op              - Get an argument for this op
999  *              Argn            - Nth argument to get
1000  *
1001  * RETURN:      The argument (as an Op object). NULL if argument does not exist
1002  *
1003  * DESCRIPTION: Get the specified op's argument (peer)
1004  *
1005  ******************************************************************************/
1006 
1007 ACPI_PARSE_OBJECT *
1008 UtGetArg (
1009     ACPI_PARSE_OBJECT       *Op,
1010     UINT32                  Argn)
1011 {
1012     ACPI_PARSE_OBJECT       *Arg = NULL;
1013 
1014 
1015     /* Get the requested argument object */
1016 
1017     Arg = Op->Asl.Child;
1018     while (Arg && Argn)
1019     {
1020         Argn--;
1021         Arg = Arg->Asl.Next;
1022     }
1023 
1024     return (Arg);
1025 }
1026 
1027 
1028 /*******************************************************************************
1029  *
1030  * FUNCTION:    OpnAttachNameToNode
1031  *
1032  * PARAMETERS:  Op        - The parent parse node
1033  *
1034  * RETURN:      None
1035  *
1036  * DESCRIPTION: For the named ASL/AML operators, get the actual name from the
1037  *              argument list and attach it to the parent node so that we
1038  *              can get to it quickly later.
1039  *
1040  ******************************************************************************/
1041 
1042 static void
1043 OpnAttachNameToNode (
1044     ACPI_PARSE_OBJECT       *Op)
1045 {
1046     ACPI_PARSE_OBJECT       *Child = NULL;
1047 
1048 
1049     if (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)
1050     {
1051         Child = UtGetArg (Op, 0);
1052     }
1053     else switch (Op->Asl.AmlOpcode)
1054     {
1055     case AML_DATA_REGION_OP:
1056     case AML_DEVICE_OP:
1057     case AML_EVENT_OP:
1058     case AML_METHOD_OP:
1059     case AML_MUTEX_OP:
1060     case AML_REGION_OP:
1061     case AML_POWER_RES_OP:
1062     case AML_PROCESSOR_OP:
1063     case AML_THERMAL_ZONE_OP:
1064     case AML_NAME_OP:
1065     case AML_SCOPE_OP:
1066 
1067         Child = UtGetArg (Op, 0);
1068         break;
1069 
1070     case AML_ALIAS_OP:
1071 
1072         Child = UtGetArg (Op, 1);
1073         break;
1074 
1075     case AML_CREATE_BIT_FIELD_OP:
1076     case AML_CREATE_BYTE_FIELD_OP:
1077     case AML_CREATE_WORD_FIELD_OP:
1078     case AML_CREATE_DWORD_FIELD_OP:
1079     case AML_CREATE_QWORD_FIELD_OP:
1080 
1081         Child = UtGetArg (Op, 2);
1082         break;
1083 
1084     case AML_CREATE_FIELD_OP:
1085 
1086         Child = UtGetArg (Op, 3);
1087         break;
1088 
1089     case AML_BANK_FIELD_OP:
1090     case AML_INDEX_FIELD_OP:
1091     case AML_FIELD_OP:
1092 
1093         return;
1094 
1095     default:
1096 
1097         return;
1098     }
1099 
1100     if (Child)
1101     {
1102         UtAttachNamepathToOwner (Op, Child);
1103     }
1104 }
1105 
1106 
1107 /*******************************************************************************
1108  *
1109  * FUNCTION:    OpnGenerateAmlOperands
1110  *
1111  * PARAMETERS:  Op        - The parent parse node
1112  *
1113  * RETURN:      None
1114  *
1115  * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more
1116  *              complex AML opcodes require processing of the child nodes
1117  *              (arguments/operands).
1118  *
1119  ******************************************************************************/
1120 
1121 void
1122 OpnGenerateAmlOperands (
1123     ACPI_PARSE_OBJECT       *Op)
1124 {
1125 
1126 
1127     if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)
1128     {
1129         return;
1130     }
1131 
1132     switch (Op->Asl.ParseOpcode)
1133     {
1134     case PARSEOP_DEFINITIONBLOCK:
1135 
1136         OpnDoDefinitionBlock (Op);
1137         break;
1138 
1139     case PARSEOP_METHOD:
1140 
1141         OpnDoMethod (Op);
1142         break;
1143 
1144     case PARSEOP_MUTEX:
1145 
1146         OpnDoMutex (Op);
1147         break;
1148 
1149     case PARSEOP_FIELD:
1150 
1151         OpnDoField (Op);
1152         break;
1153 
1154     case PARSEOP_INDEXFIELD:
1155 
1156         OpnDoIndexField (Op);
1157         break;
1158 
1159     case PARSEOP_BANKFIELD:
1160 
1161         OpnDoBankField (Op);
1162         break;
1163 
1164     case PARSEOP_BUFFER:
1165 
1166         OpnDoBuffer (Op);
1167         break;
1168 
1169     case PARSEOP_LOADTABLE:
1170 
1171         OpnDoLoadTable (Op);
1172         break;
1173 
1174     case PARSEOP_OPERATIONREGION:
1175 
1176         OpnDoRegion (Op);
1177         break;
1178 
1179     case PARSEOP_RESOURCETEMPLATE:
1180 
1181         RsDoResourceTemplate (Op);
1182         break;
1183 
1184     case PARSEOP_NAMESEG:
1185     case PARSEOP_NAMESTRING:
1186     case PARSEOP_METHODCALL:
1187     case PARSEOP_STRING_LITERAL:
1188 
1189         break;
1190 
1191     default:
1192 
1193         break;
1194     }
1195 
1196     /* TBD: move */
1197 
1198     OpnAttachNameToNode (Op);
1199 }
1200