xref: /freebsd/sys/contrib/dev/acpica/compiler/asloperands.c (revision 89498fdf4174b08bb67d684d14886539aff698b4)
1 
2 /******************************************************************************
3  *
4  * Module Name: asloperands - AML operand processing
5  *
6  *****************************************************************************/
7 
8 /*
9  * Copyright (C) 2000 - 2012, Intel Corp.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44 
45 
46 #include <contrib/dev/acpica/compiler/aslcompiler.h>
47 #include "aslcompiler.y.h"
48 #include <contrib/dev/acpica/include/amlcode.h>
49 
50 #define _COMPONENT          ACPI_COMPILER
51         ACPI_MODULE_NAME    ("asloperands")
52 
53 /* Local prototypes */
54 
55 static void
56 OpnDoField (
57     ACPI_PARSE_OBJECT       *Op);
58 
59 static void
60 OpnDoBankField (
61     ACPI_PARSE_OBJECT       *Op);
62 
63 static void
64 OpnDoBuffer (
65     ACPI_PARSE_OBJECT       *Op);
66 
67 static void
68 OpnDoDefinitionBlock (
69     ACPI_PARSE_OBJECT       *Op);
70 
71 static void
72 OpnDoFieldCommon (
73     ACPI_PARSE_OBJECT       *FieldOp,
74     ACPI_PARSE_OBJECT       *Op);
75 
76 static void
77 OpnDoIndexField (
78     ACPI_PARSE_OBJECT       *Op);
79 
80 static void
81 OpnDoLoadTable (
82     ACPI_PARSE_OBJECT       *Op);
83 
84 static void
85 OpnDoMethod (
86     ACPI_PARSE_OBJECT       *Op);
87 
88 static void
89 OpnDoMutex (
90     ACPI_PARSE_OBJECT       *Op);
91 
92 static void
93 OpnDoRegion (
94     ACPI_PARSE_OBJECT       *Op);
95 
96 static void
97 OpnAttachNameToNode (
98     ACPI_PARSE_OBJECT       *Op);
99 
100 
101 /*******************************************************************************
102  *
103  * FUNCTION:    OpnDoMutex
104  *
105  * PARAMETERS:  Op        - The parent parse node
106  *
107  * RETURN:      None
108  *
109  * DESCRIPTION: Construct the operands for the MUTEX ASL keyword.
110  *
111  ******************************************************************************/
112 
113 static void
114 OpnDoMutex (
115     ACPI_PARSE_OBJECT       *Op)
116 {
117     ACPI_PARSE_OBJECT       *Next;
118 
119 
120     Next = Op->Asl.Child;
121     Next = Next->Asl.Next;
122 
123     if (Next->Asl.Value.Integer > 15)
124     {
125         AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
126     }
127     return;
128 }
129 
130 
131 /*******************************************************************************
132  *
133  * FUNCTION:    OpnDoMethod
134  *
135  * PARAMETERS:  Op        - The parent parse node
136  *
137  * RETURN:      None
138  *
139  * DESCRIPTION: Construct the operands for the METHOD ASL keyword.
140  *
141  ******************************************************************************/
142 
143 static void
144 OpnDoMethod (
145     ACPI_PARSE_OBJECT       *Op)
146 {
147     ACPI_PARSE_OBJECT       *Next;
148 
149     /* Optional arguments for this opcode with defaults */
150 
151     UINT8                   NumArgs = 0;
152     UINT8                   Serialized = 0;
153     UINT8                   Concurrency = 0;
154     UINT8                   MethodFlags;
155 
156 
157     /* Opcode and package length first */
158     /* Method name */
159 
160     Next = Op->Asl.Child;
161 
162     /* Num args */
163 
164     Next = Next->Asl.Next;
165     if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
166     {
167         NumArgs = (UINT8) Next->Asl.Value.Integer;
168         Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
169     }
170 
171     /* Serialized Flag */
172 
173     Next = Next->Asl.Next;
174     if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
175     {
176         Serialized = (UINT8) Next->Asl.Value.Integer;
177         Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
178     }
179 
180     /* Concurrency value (valid values are 0-15) */
181 
182     Next = Next->Asl.Next;
183     if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
184     {
185         /* This is a ByteConstExpr, so eval the constant now */
186 
187         OpcAmlConstantWalk (Next, 0, NULL);
188 
189         if (Next->Asl.Value.Integer > 15)
190         {
191             AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
192         }
193         Concurrency = (UINT8) Next->Asl.Value.Integer;
194     }
195 
196     /* Put the bits in their proper places */
197 
198     MethodFlags = (UINT8) ((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 
303         case PARSEOP_OFFSET:
304 
305             /* New offset into the field */
306 
307             PkgLengthNode = Next->Asl.Child;
308             NewBitOffset = ((UINT32) PkgLengthNode->Asl.Value.Integer) * 8;
309 
310             /*
311              * Examine the specified offset in relation to the
312              * current offset counter.
313              */
314             if (NewBitOffset < CurrentBitOffset)
315             {
316                 /*
317                  * Not allowed to specify a backwards offset!
318                  * Issue error and ignore this node.
319                  */
320                 AslError (ASL_ERROR, ASL_MSG_BACKWARDS_OFFSET, PkgLengthNode,
321                     NULL);
322                 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
323                 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
324             }
325             else if (NewBitOffset == CurrentBitOffset)
326             {
327                 /*
328                  * Offset is redundant; we don't need to output an
329                  * offset opcode.  Just set these nodes to default
330                  */
331                 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
332                 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
333             }
334             else
335             {
336                 /*
337                  * Valid new offset - set the value to be inserted into the AML
338                  * and update the offset counter.
339                  */
340                 PkgLengthNode->Asl.Value.Integer =
341                     NewBitOffset - CurrentBitOffset;
342                 CurrentBitOffset = NewBitOffset;
343             }
344             break;
345 
346 
347         case PARSEOP_NAMESEG:
348         case PARSEOP_RESERVED_BYTES:
349 
350             /* Named or reserved field entry */
351 
352             PkgLengthNode     = Next->Asl.Child;
353             NewBitOffset      = (UINT32) PkgLengthNode->Asl.Value.Integer;
354             CurrentBitOffset += NewBitOffset;
355 
356             /* Save the current AccessAs value for error checking later */
357 
358             switch (AccessType)
359             {
360                 case AML_FIELD_ACCESS_ANY:
361                 case AML_FIELD_ACCESS_BYTE:
362                 case AML_FIELD_ACCESS_BUFFER:
363                 default:
364                     MinimumLength = 8;
365                     break;
366 
367                 case AML_FIELD_ACCESS_WORD:
368                     MinimumLength = 16;
369                     break;
370 
371                 case AML_FIELD_ACCESS_DWORD:
372                     MinimumLength = 32;
373                     break;
374 
375                 case AML_FIELD_ACCESS_QWORD:
376                     MinimumLength = 64;
377                     break;
378             }
379 
380             PkgLengthNode->Asl.ExtraValue = MinimumLength;
381             break;
382 
383         default:
384             /* All supported field opcodes must appear above */
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 
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 
629     case PARSEOP_RAW_DATA:
630 
631         /* Buffer nodes are already initialized (e.g. Unicode operator) */
632         return;
633 
634 
635     case PARSEOP_DEFAULT_ARG:
636         break;
637 
638 
639     default:
640         AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, InitializerOp,
641             "Unknown buffer initializer opcode");
642         printf ("Unknown buffer initializer opcode [%s]\n",
643                         UtGetOpName (InitializerOp->Asl.ParseOpcode));
644         return;
645     }
646 
647     /* Check if initializer list is longer than the buffer length */
648 
649     if (BufferLengthOp->Asl.Value.Integer > BufferLength)
650     {
651         BufferLength = (UINT32) BufferLengthOp->Asl.Value.Integer;
652     }
653 
654     if (!BufferLength)
655     {
656         /* No length AND no items -- issue notice */
657 
658         AslError (ASL_REMARK, ASL_MSG_BUFFER_LENGTH, BufferLengthOp, NULL);
659 
660         /* But go ahead and put the buffer length of zero into the AML */
661     }
662 
663     /*
664      * Just set the buffer size node to be the buffer length, regardless
665      * of whether it was previously an integer or a default_arg placeholder
666      */
667     BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
668     BufferLengthOp->Asl.AmlOpcode     = AML_DWORD_OP;
669     BufferLengthOp->Asl.Value.Integer = BufferLength;
670 
671     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
672 
673     /* Remaining nodes are handled via the tree walk */
674 }
675 
676 
677 /*******************************************************************************
678  *
679  * FUNCTION:    OpnDoPackage
680  *
681  * PARAMETERS:  Op        - The parent parse node
682  *
683  * RETURN:      None
684  *
685  * DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword.  NOTE:
686  *              can only be called after constants have been folded, to ensure
687  *              that the PackageLength operand has been fully reduced.
688  *
689  ******************************************************************************/
690 
691 void
692 OpnDoPackage (
693     ACPI_PARSE_OBJECT       *Op)
694 {
695     ACPI_PARSE_OBJECT       *InitializerOp;
696     ACPI_PARSE_OBJECT       *PackageLengthOp;
697     UINT32                  PackageLength = 0;
698 
699 
700     /* Opcode and package length first, followed by the initializer list */
701 
702     PackageLengthOp = Op->Asl.Child;
703     InitializerOp = PackageLengthOp->Asl.Next;
704 
705     /* Count the number of items in the initializer list */
706 
707     if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
708     {
709         /* The peer list contains the byte list (if any...) */
710 
711         while (InitializerOp)
712         {
713             PackageLength++;
714             InitializerOp = InitializerOp->Asl.Next;
715         }
716     }
717 
718     /* If package length is a constant, compare to the initializer list */
719 
720     if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
721         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST))
722     {
723         if (PackageLengthOp->Asl.Value.Integer > PackageLength)
724         {
725             /*
726              * Allow package length to be longer than the initializer
727              * list -- but if the length of initializer list is nonzero,
728              * issue a message since this is probably a coding error,
729              * even though technically legal.
730              */
731             if (PackageLength > 0)
732             {
733                 AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT,
734                     PackageLengthOp, NULL);
735             }
736 
737             PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer;
738         }
739         else if (PackageLengthOp->Asl.Value.Integer < PackageLength)
740         {
741             /*
742              * The package length is smaller than the length of the
743              * initializer list. This is an error as per the ACPI spec.
744              */
745             AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG,
746                 PackageLengthOp, NULL);
747         }
748     }
749 
750     if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
751     {
752         /*
753          * This is the case if the PackageLength was left empty - Package()
754          * The package length becomes the length of the initializer list
755          */
756         Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER;
757         Op->Asl.Child->Asl.Value.Integer = PackageLength;
758 
759         /* Set the AML opcode */
760 
761         (void) OpcSetOptimalIntegerSize (Op->Asl.Child);
762     }
763 
764     /* If not a variable-length package, check for a zero package length */
765 
766     if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
767         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST)   ||
768         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_ZERO)         ||
769         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG))
770     {
771         if (!PackageLength)
772         {
773             /* No length AND no initializer list -- issue a remark */
774 
775             AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH,
776                 PackageLengthOp, NULL);
777 
778             /* But go ahead and put the buffer length of zero into the AML */
779         }
780     }
781 
782     /*
783      * If the PackageLength is a constant <= 255, we can change the
784      * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode.
785      */
786     if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
787             (Op->Asl.Child->Asl.Value.Integer <= 255))  ||
788         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) ||
789         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)||
790         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO))
791     {
792         Op->Asl.AmlOpcode = AML_PACKAGE_OP;
793         Op->Asl.ParseOpcode = PARSEOP_PACKAGE;
794 
795         /*
796          * Just set the package size node to be the package length, regardless
797          * of whether it was previously an integer or a default_arg placeholder
798          */
799         PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
800         PackageLengthOp->Asl.AmlLength = 1;
801         PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
802         PackageLengthOp->Asl.Value.Integer = PackageLength;
803     }
804 
805     /* Remaining nodes are handled via the tree walk */
806 }
807 
808 
809 /*******************************************************************************
810  *
811  * FUNCTION:    OpnDoLoadTable
812  *
813  * PARAMETERS:  Op        - The parent parse node
814  *
815  * RETURN:      None
816  *
817  * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword.
818  *
819  ******************************************************************************/
820 
821 static void
822 OpnDoLoadTable (
823     ACPI_PARSE_OBJECT       *Op)
824 {
825     ACPI_PARSE_OBJECT       *Next;
826 
827 
828     /* Opcode is parent node */
829     /* First child is the table signature */
830 
831     Next = Op->Asl.Child;
832 
833     /* Second child is the OEM ID*/
834 
835     Next = Next->Asl.Next;
836 
837     /* Third child is the OEM table ID */
838 
839     Next = Next->Asl.Next;
840 
841     /* Fourth child is the RootPath string */
842 
843     Next = Next->Asl.Next;
844     if (Next->Asl.ParseOpcode == PARSEOP_ZERO)
845     {
846         Next->Asl.ParseOpcode    = PARSEOP_STRING_LITERAL;
847         Next->Asl.Value.String   = "\\";
848         Next->Asl.AmlLength      = 2;
849         OpcGenerateAmlOpcode (Next);
850     }
851 
852 #ifdef ASL_FUTURE_IMPLEMENTATION
853 
854     /* TBD: NOT IMPLEMENTED */
855     /* Fifth child is the [optional] ParameterPathString */
856     /* Sixth child is the [optional] ParameterData */
857 
858     Next = Next->Asl.Next;
859     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
860     {
861         Next->Asl.AmlLength = 1;
862         Next->Asl.ParseOpcode = ZERO;
863         OpcGenerateAmlOpcode (Next);
864     }
865 
866 
867     Next = Next->Asl.Next;
868     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
869     {
870         Next->Asl.AmlLength = 1;
871         Next->Asl.ParseOpcode = ZERO;
872         OpcGenerateAmlOpcode (Next);
873     }
874 #endif
875 }
876 
877 
878 /*******************************************************************************
879  *
880  * FUNCTION:    OpnDoDefinitionBlock
881  *
882  * PARAMETERS:  Op        - The parent parse node
883  *
884  * RETURN:      None
885  *
886  * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword
887  *
888  ******************************************************************************/
889 
890 static void
891 OpnDoDefinitionBlock (
892     ACPI_PARSE_OBJECT       *Op)
893 {
894     ACPI_PARSE_OBJECT       *Child;
895     ACPI_SIZE               Length;
896     UINT32                  i;
897     char                    *Filename;
898 
899 
900     /*
901      * These nodes get stuffed into the table header.  They are special
902      * cased when the table is written to the output file.
903      *
904      * Mark all of these nodes as non-usable so they won't get output
905      * as AML opcodes!
906      */
907 
908     /* Get AML filename. Use it if non-null */
909 
910     Child = Op->Asl.Child;
911     if (Child->Asl.Value.Buffer  &&
912         *Child->Asl.Value.Buffer &&
913         (Gbl_UseDefaultAmlFilename))
914     {
915         /*
916          * We will use the AML filename that is embedded in the source file
917          * for the output filename.
918          */
919         Filename = ACPI_ALLOCATE (strlen (Gbl_DirectoryPath) +
920                     strlen ((char *) Child->Asl.Value.Buffer) + 1);
921 
922         /* Prepend the current directory path */
923 
924         strcpy (Filename, Gbl_DirectoryPath);
925         strcat (Filename, (char *) Child->Asl.Value.Buffer);
926 
927         Gbl_OutputFilenamePrefix = Filename;
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 (ACPI_STRLEN (Gbl_TableSignature) != 4)
939         {
940             AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
941                 "Length not exactly 4");
942         }
943 
944         for (i = 0; i < 4; 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 = ACPI_STRLEN (Child->Asl.Value.String);
974         Gbl_TableId = AcpiOsAllocate (Length + 1);
975         ACPI_STRCPY (Gbl_TableId, Child->Asl.Value.String);
976 
977         for (i = 0; i < Length; i++)
978         {
979             if (Gbl_TableId[i] == ' ')
980             {
981                 Gbl_TableId[i] = 0;
982                 break;
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         return;
1097     }
1098 
1099     if (Child)
1100     {
1101         UtAttachNamepathToOwner (Op, Child);
1102     }
1103 }
1104 
1105 
1106 /*******************************************************************************
1107  *
1108  * FUNCTION:    OpnGenerateAmlOperands
1109  *
1110  * PARAMETERS:  Op        - The parent parse node
1111  *
1112  * RETURN:      None
1113  *
1114  * DESCRIPTION: Prepare nodes to be output as AML data and operands.  The more
1115  *              complex AML opcodes require processing of the child nodes
1116  *              (arguments/operands).
1117  *
1118  ******************************************************************************/
1119 
1120 void
1121 OpnGenerateAmlOperands (
1122     ACPI_PARSE_OBJECT       *Op)
1123 {
1124 
1125 
1126     if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)
1127     {
1128         return;
1129     }
1130 
1131     switch (Op->Asl.ParseOpcode)
1132     {
1133     case PARSEOP_DEFINITIONBLOCK:
1134         OpnDoDefinitionBlock (Op);
1135         break;
1136 
1137     case PARSEOP_METHOD:
1138         OpnDoMethod (Op);
1139         break;
1140 
1141     case PARSEOP_MUTEX:
1142         OpnDoMutex (Op);
1143         break;
1144 
1145     case PARSEOP_FIELD:
1146         OpnDoField (Op);
1147         break;
1148 
1149     case PARSEOP_INDEXFIELD:
1150         OpnDoIndexField (Op);
1151         break;
1152 
1153     case PARSEOP_BANKFIELD:
1154         OpnDoBankField (Op);
1155         break;
1156 
1157     case PARSEOP_BUFFER:
1158         OpnDoBuffer (Op);
1159         break;
1160 
1161     case PARSEOP_LOADTABLE:
1162         OpnDoLoadTable (Op);
1163         break;
1164 
1165     case PARSEOP_OPERATIONREGION:
1166         OpnDoRegion (Op);
1167         break;
1168 
1169     case PARSEOP_RESOURCETEMPLATE:
1170         RsDoResourceTemplate (Op);
1171         break;
1172 
1173     case PARSEOP_NAMESEG:
1174     case PARSEOP_NAMESTRING:
1175     case PARSEOP_METHODCALL:
1176     case PARSEOP_STRING_LITERAL:
1177         break;
1178 
1179     default:
1180         break;
1181     }
1182 
1183     /* TBD: move */
1184 
1185     OpnAttachNameToNode (Op);
1186 }
1187 
1188 
1189