xref: /dflybsd-src/sys/contrib/dev/acpica/source/compiler/asloperands.c (revision d638c6eedc81671c3ceddd06ef20463940cb6a43)
1 /******************************************************************************
2  *
3  * Module Name: asloperands - AML operand processing
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2017, 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) && Gbl_OptimizeTrivialParseNodes)
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             if ((NewBitOffset == 0) &&
355                 (Next->Asl.ParseOpcode == PARSEOP_RESERVED_BYTES) &&
356                 Gbl_OptimizeTrivialParseNodes)
357             {
358                 /*
359                  * Unnamed field with a bit length of zero. We can
360                  * safely just ignore this. However, we will not ignore
361                  * a named field of zero length, we don't want to just
362                  * toss out a name.
363                  */
364                 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
365                 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
366                 break;
367             }
368 
369             /* Save the current AccessAs value for error checking later */
370 
371             switch (AccessType)
372             {
373                 case AML_FIELD_ACCESS_ANY:
374                 case AML_FIELD_ACCESS_BYTE:
375                 case AML_FIELD_ACCESS_BUFFER:
376                 default:
377 
378                     MinimumLength = 8;
379                     break;
380 
381                 case AML_FIELD_ACCESS_WORD:
382                     MinimumLength = 16;
383                     break;
384 
385                 case AML_FIELD_ACCESS_DWORD:
386                     MinimumLength = 32;
387                     break;
388 
389                 case AML_FIELD_ACCESS_QWORD:
390                     MinimumLength = 64;
391                     break;
392             }
393 
394             PkgLengthNode->Asl.ExtraValue = MinimumLength;
395             break;
396 
397         default:
398 
399             /* All supported field opcodes must appear above */
400 
401             break;
402         }
403 
404         /* Move on to next entry in the field list */
405 
406         Next = Next->Asl.Next;
407     }
408 }
409 
410 
411 /*******************************************************************************
412  *
413  * FUNCTION:    OpnDoField
414  *
415  * PARAMETERS:  Op        - The parent parse node
416  *
417  * RETURN:      None
418  *
419  * DESCRIPTION: Construct the AML operands for the FIELD ASL keyword
420  *
421  ******************************************************************************/
422 
423 static void
424 OpnDoField (
425     ACPI_PARSE_OBJECT       *Op)
426 {
427     ACPI_PARSE_OBJECT       *Next;
428 
429 
430     /* Opcode is parent node */
431     /* First child is field name */
432 
433     Next = Op->Asl.Child;
434 
435     /* Second child is the AccessType */
436 
437     OpnDoFieldCommon (Op, Next->Asl.Next);
438 }
439 
440 
441 /*******************************************************************************
442  *
443  * FUNCTION:    OpnDoIndexField
444  *
445  * PARAMETERS:  Op        - The parent parse node
446  *
447  * RETURN:      None
448  *
449  * DESCRIPTION: Construct the AML operands for the INDEXFIELD ASL keyword
450  *
451  ******************************************************************************/
452 
453 static void
454 OpnDoIndexField (
455     ACPI_PARSE_OBJECT       *Op)
456 {
457     ACPI_PARSE_OBJECT       *Next;
458 
459 
460     /* Opcode is parent node */
461     /* First child is the index name */
462 
463     Next = Op->Asl.Child;
464 
465     /* Second child is the data name */
466 
467     Next = Next->Asl.Next;
468 
469     /* Third child is the AccessType */
470 
471     OpnDoFieldCommon (Op, Next->Asl.Next);
472 }
473 
474 
475 /*******************************************************************************
476  *
477  * FUNCTION:    OpnDoBankField
478  *
479  * PARAMETERS:  Op        - The parent parse node
480  *
481  * RETURN:      None
482  *
483  * DESCRIPTION: Construct the AML operands for the BANKFIELD ASL keyword
484  *
485  ******************************************************************************/
486 
487 static void
488 OpnDoBankField (
489     ACPI_PARSE_OBJECT       *Op)
490 {
491     ACPI_PARSE_OBJECT       *Next;
492 
493 
494     /* Opcode is parent node */
495     /* First child is the region name */
496 
497     Next = Op->Asl.Child;
498 
499     /* Second child is the bank name */
500 
501     Next = Next->Asl.Next;
502 
503     /* Third child is the bank value */
504 
505     Next = Next->Asl.Next;
506 
507     /* Fourth child is the AccessType */
508 
509     OpnDoFieldCommon (Op, Next->Asl.Next);
510 }
511 
512 
513 /*******************************************************************************
514  *
515  * FUNCTION:    OpnDoRegion
516  *
517  * PARAMETERS:  Op        - The parent parse node
518  *
519  * RETURN:      None
520  *
521  * DESCRIPTION: Tries to get the length of the region. Can only do this at
522  *              compile time if the length is a constant.
523  *
524  ******************************************************************************/
525 
526 static void
527 OpnDoRegion (
528     ACPI_PARSE_OBJECT       *Op)
529 {
530     ACPI_PARSE_OBJECT       *Next;
531 
532 
533     /* Opcode is parent node */
534     /* First child is the region name */
535 
536     Next = Op->Asl.Child;
537 
538     /* Second child is the space ID*/
539 
540     Next = Next->Asl.Next;
541 
542     /* Third child is the region offset */
543 
544     Next = Next->Asl.Next;
545 
546     /* Fourth child is the region length */
547 
548     Next = Next->Asl.Next;
549     if (Next->Asl.ParseOpcode == PARSEOP_INTEGER)
550     {
551         Op->Asl.Value.Integer = Next->Asl.Value.Integer;
552     }
553     else
554     {
555         Op->Asl.Value.Integer = ACPI_UINT64_MAX;
556     }
557 }
558 
559 
560 /*******************************************************************************
561  *
562  * FUNCTION:    OpnDoBuffer
563  *
564  * PARAMETERS:  Op        - The parent parse node
565  *
566  * RETURN:      None
567  *
568  * DESCRIPTION: Construct the AML operands for the BUFFER ASL keyword. We
569  *              build a single raw byte buffer from the initialization nodes,
570  *              each parse node contains a buffer byte.
571  *
572  ******************************************************************************/
573 
574 static void
575 OpnDoBuffer (
576     ACPI_PARSE_OBJECT       *Op)
577 {
578     ACPI_PARSE_OBJECT       *InitializerOp;
579     ACPI_PARSE_OBJECT       *BufferLengthOp;
580 
581     /* Optional arguments for this opcode with defaults */
582 
583     UINT32                  BufferLength = 0;
584 
585 
586     /* Opcode and package length first */
587     /* Buffer Length is next, followed by the initializer list */
588 
589     BufferLengthOp = Op->Asl.Child;
590     InitializerOp = BufferLengthOp->Asl.Next;
591 
592     /*
593      * If the BufferLength is not an INTEGER or was not specified in the ASL
594      * (DEFAULT_ARG), it is a TermArg that is
595      * evaluated at run-time, and we are therefore finished.
596      */
597     if ((BufferLengthOp->Asl.ParseOpcode != PARSEOP_INTEGER) &&
598         (BufferLengthOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
599     {
600         return;
601     }
602 
603     /*
604      * We want to count the number of items in the initializer list, because if
605      * it is larger than the buffer length, we will define the buffer size
606      * to be the size of the initializer list (as per the ACPI Specification)
607      */
608     switch (InitializerOp->Asl.ParseOpcode)
609     {
610     case PARSEOP_INTEGER:
611     case PARSEOP_BYTECONST:
612     case PARSEOP_WORDCONST:
613     case PARSEOP_DWORDCONST:
614 
615         /* The peer list contains the byte list (if any...) */
616 
617         while (InitializerOp)
618         {
619             /* For buffers, this is a list of raw bytes */
620 
621             InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
622             InitializerOp->Asl.AmlLength = 1;
623             InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
624 
625             BufferLength++;
626             InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
627         }
628         break;
629 
630     case PARSEOP_STRING_LITERAL:
631 
632         /*
633          * Only one initializer, the string. Buffer must be big enough to hold
634          * the string plus the null termination byte
635          */
636         BufferLength = strlen (InitializerOp->Asl.Value.String) + 1;
637 
638         InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
639         InitializerOp->Asl.AmlLength = BufferLength;
640         InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
641         break;
642 
643     case PARSEOP_RAW_DATA:
644 
645         /* Buffer nodes are already initialized (e.g. Unicode operator) */
646         return;
647 
648     case PARSEOP_DEFAULT_ARG:
649         break;
650 
651     default:
652 
653         AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, InitializerOp,
654             "Unknown buffer initializer opcode");
655         printf ("Unknown buffer initializer opcode [%s]\n",
656             UtGetOpName (InitializerOp->Asl.ParseOpcode));
657         return;
658     }
659 
660     /* Check if initializer list is longer than the buffer length */
661 
662     if (BufferLengthOp->Asl.Value.Integer > BufferLength)
663     {
664         BufferLength = (UINT32) BufferLengthOp->Asl.Value.Integer;
665     }
666 
667     if (!BufferLength)
668     {
669         /* No length AND no items -- issue notice */
670 
671         AslError (ASL_REMARK, ASL_MSG_BUFFER_LENGTH, BufferLengthOp, NULL);
672 
673         /* But go ahead and put the buffer length of zero into the AML */
674     }
675 
676     /*
677      * Just set the buffer size node to be the buffer length, regardless
678      * of whether it was previously an integer or a default_arg placeholder
679      */
680     BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
681     BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP;
682     BufferLengthOp->Asl.Value.Integer = BufferLength;
683 
684     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
685 
686     /* Remaining nodes are handled via the tree walk */
687 }
688 
689 
690 /*******************************************************************************
691  *
692  * FUNCTION:    OpnDoPackage
693  *
694  * PARAMETERS:  Op        - The parent parse node
695  *
696  * RETURN:      None
697  *
698  * DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword. NOTE:
699  *              can only be called after constants have been folded, to ensure
700  *              that the PackageLength operand has been fully reduced.
701  *
702  ******************************************************************************/
703 
704 void
705 OpnDoPackage (
706     ACPI_PARSE_OBJECT       *Op)
707 {
708     ACPI_PARSE_OBJECT       *InitializerOp;
709     ACPI_PARSE_OBJECT       *PackageLengthOp;
710     UINT32                  PackageLength = 0;
711 
712 
713     /* Opcode and package length first, followed by the initializer list */
714 
715     PackageLengthOp = Op->Asl.Child;
716     InitializerOp = PackageLengthOp->Asl.Next;
717 
718     /* Count the number of items in the initializer list */
719 
720     if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
721     {
722         /* The peer list contains the byte list (if any...) */
723 
724         while (InitializerOp)
725         {
726             PackageLength++;
727             InitializerOp = InitializerOp->Asl.Next;
728         }
729     }
730 
731     /* If package length is a constant, compare to the initializer list */
732 
733     if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
734         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST))
735     {
736         if (PackageLengthOp->Asl.Value.Integer > PackageLength)
737         {
738             /*
739              * Allow package length to be longer than the initializer
740              * list -- but if the length of initializer list is nonzero,
741              * issue a message since this is probably a coding error,
742              * even though technically legal.
743              */
744             if (PackageLength > 0)
745             {
746                 AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT,
747                     PackageLengthOp, NULL);
748             }
749 
750             PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer;
751         }
752         else if (PackageLengthOp->Asl.Value.Integer < PackageLength)
753         {
754             /*
755              * The package length is smaller than the length of the
756              * initializer list. This is an error as per the ACPI spec.
757              */
758             AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG,
759                 PackageLengthOp, NULL);
760         }
761     }
762 
763     if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
764     {
765         /*
766          * This is the case if the PackageLength was left empty - Package()
767          * The package length becomes the length of the initializer list
768          */
769         Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER;
770         Op->Asl.Child->Asl.Value.Integer = PackageLength;
771 
772         /* Set the AML opcode */
773 
774         (void) OpcSetOptimalIntegerSize (Op->Asl.Child);
775     }
776 
777     /* If not a variable-length package, check for a zero package length */
778 
779     if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
780         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST)   ||
781         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_ZERO)         ||
782         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG))
783     {
784         if (!PackageLength)
785         {
786             /* No length AND no initializer list -- issue a remark */
787 
788             AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH,
789                 PackageLengthOp, NULL);
790 
791             /* But go ahead and put the buffer length of zero into the AML */
792         }
793     }
794 
795     /*
796      * If the PackageLength is a constant <= 255, we can change the
797      * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode.
798      */
799     if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
800             (Op->Asl.Child->Asl.Value.Integer <= 255))  ||
801         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) ||
802         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)||
803         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO))
804     {
805         Op->Asl.AmlOpcode = AML_PACKAGE_OP;
806         Op->Asl.ParseOpcode = PARSEOP_PACKAGE;
807 
808         /*
809          * Just set the package size node to be the package length, regardless
810          * of whether it was previously an integer or a default_arg placeholder
811          */
812         PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
813         PackageLengthOp->Asl.AmlLength = 1;
814         PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
815         PackageLengthOp->Asl.Value.Integer = PackageLength;
816     }
817 
818     /* Remaining nodes are handled via the tree walk */
819 }
820 
821 
822 /*******************************************************************************
823  *
824  * FUNCTION:    OpnDoLoadTable
825  *
826  * PARAMETERS:  Op        - The parent parse node
827  *
828  * RETURN:      None
829  *
830  * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword.
831  *
832  ******************************************************************************/
833 
834 static void
835 OpnDoLoadTable (
836     ACPI_PARSE_OBJECT       *Op)
837 {
838     ACPI_PARSE_OBJECT       *Next;
839 
840 
841     /* Opcode is parent node */
842     /* First child is the table signature */
843 
844     Next = Op->Asl.Child;
845 
846     /* Second child is the OEM ID*/
847 
848     Next = Next->Asl.Next;
849 
850     /* Third child is the OEM table ID */
851 
852     Next = Next->Asl.Next;
853 
854     /* Fourth child is the RootPath string */
855 
856     Next = Next->Asl.Next;
857     if (Next->Asl.ParseOpcode == PARSEOP_ZERO)
858     {
859         Next->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
860         Next->Asl.Value.String = "\\";
861         Next->Asl.AmlLength = 2;
862         OpcGenerateAmlOpcode (Next);
863     }
864 
865 #ifdef ASL_FUTURE_IMPLEMENTATION
866 
867     /* TBD: NOT IMPLEMENTED */
868     /* Fifth child is the [optional] ParameterPathString */
869     /* Sixth child is the [optional] ParameterData */
870 
871     Next = Next->Asl.Next;
872     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
873     {
874         Next->Asl.AmlLength = 1;
875         Next->Asl.ParseOpcode = ZERO;
876         OpcGenerateAmlOpcode (Next);
877     }
878 
879 
880     Next = Next->Asl.Next;
881     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
882     {
883         Next->Asl.AmlLength = 1;
884         Next->Asl.ParseOpcode = ZERO;
885         OpcGenerateAmlOpcode (Next);
886     }
887 #endif
888 }
889 
890 
891 /*******************************************************************************
892  *
893  * FUNCTION:    OpnDoDefinitionBlock
894  *
895  * PARAMETERS:  Op        - The parent parse node
896  *
897  * RETURN:      None
898  *
899  * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword
900  *
901  ******************************************************************************/
902 
903 static void
904 OpnDoDefinitionBlock (
905     ACPI_PARSE_OBJECT       *Op)
906 {
907     ACPI_PARSE_OBJECT       *Child;
908     ACPI_SIZE               Length;
909     UINT32                  i;
910     char                    *Filename;
911 
912 
913     /*
914      * These nodes get stuffed into the table header. They are special
915      * cased when the table is written to the output file.
916      *
917      * Mark all of these nodes as non-usable so they won't get output
918      * as AML opcodes!
919      */
920 
921     /* Get AML filename. Use it if non-null */
922 
923     Child = Op->Asl.Child;
924     if (Child->Asl.Value.Buffer  &&
925         *Child->Asl.Value.Buffer &&
926         (Gbl_UseDefaultAmlFilename))
927     {
928         /*
929          * We will use the AML filename that is embedded in the source file
930          * for the output filename.
931          */
932         Filename = UtStringCacheCalloc (strlen (Gbl_DirectoryPath) +
933             strlen ((char *) Child->Asl.Value.Buffer) + 1);
934 
935         /* Prepend the current directory path */
936 
937         strcpy (Filename, Gbl_DirectoryPath);
938         strcat (Filename, (char *) Child->Asl.Value.Buffer);
939 
940         Gbl_OutputFilenamePrefix = Filename;
941         UtConvertBackslashes (Gbl_OutputFilenamePrefix);
942     }
943 
944     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
945 
946     /* Signature */
947 
948     Child = Child->Asl.Next;
949     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
950     if (Child->Asl.Value.String)
951     {
952         Gbl_TableSignature = Child->Asl.Value.String;
953         if (strlen (Gbl_TableSignature) != ACPI_NAME_SIZE)
954         {
955             AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
956                 "Length is not exactly 4");
957         }
958 
959         for (i = 0; i < ACPI_NAME_SIZE; i++)
960         {
961             if (!isalnum ((int) Gbl_TableSignature[i]))
962             {
963                 AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
964                     "Contains non-alphanumeric characters");
965             }
966         }
967     }
968 
969     /* Revision */
970 
971     Child = Child->Asl.Next;
972     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
973     /*
974      * We used the revision to set the integer width earlier
975      */
976 
977     /* OEMID */
978 
979     Child = Child->Asl.Next;
980     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
981 
982     /* OEM TableID */
983 
984     Child = Child->Asl.Next;
985     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
986     if (Child->Asl.Value.String)
987     {
988         Length = strlen (Child->Asl.Value.String);
989         Gbl_TableId = UtStringCacheCalloc (Length + 1);
990         strcpy (Gbl_TableId, Child->Asl.Value.String);
991 
992         /*
993          * Convert anything non-alphanumeric to an underscore. This
994          * allows us to use the TableID to generate unique C symbols.
995          */
996         for (i = 0; i < Length; i++)
997         {
998             if (!isalnum ((int) Gbl_TableId[i]))
999             {
1000                 Gbl_TableId[i] = '_';
1001             }
1002         }
1003     }
1004 
1005     /* OEM Revision */
1006 
1007     Child = Child->Asl.Next;
1008     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1009 }
1010 
1011 
1012 /*******************************************************************************
1013  *
1014  * FUNCTION:    UtGetArg
1015  *
1016  * PARAMETERS:  Op              - Get an argument for this op
1017  *              Argn            - Nth argument to get
1018  *
1019  * RETURN:      The argument (as an Op object). NULL if argument does not exist
1020  *
1021  * DESCRIPTION: Get the specified op's argument (peer)
1022  *
1023  ******************************************************************************/
1024 
1025 ACPI_PARSE_OBJECT *
1026 UtGetArg (
1027     ACPI_PARSE_OBJECT       *Op,
1028     UINT32                  Argn)
1029 {
1030     ACPI_PARSE_OBJECT       *Arg = NULL;
1031 
1032 
1033     /* Get the requested argument object */
1034 
1035     Arg = Op->Asl.Child;
1036     while (Arg && Argn)
1037     {
1038         Argn--;
1039         Arg = Arg->Asl.Next;
1040     }
1041 
1042     return (Arg);
1043 }
1044 
1045 
1046 /*******************************************************************************
1047  *
1048  * FUNCTION:    OpnAttachNameToNode
1049  *
1050  * PARAMETERS:  Op        - The parent parse node
1051  *
1052  * RETURN:      None
1053  *
1054  * DESCRIPTION: For the named ASL/AML operators, get the actual name from the
1055  *              argument list and attach it to the parent node so that we
1056  *              can get to it quickly later.
1057  *
1058  ******************************************************************************/
1059 
1060 static void
1061 OpnAttachNameToNode (
1062     ACPI_PARSE_OBJECT       *Op)
1063 {
1064     ACPI_PARSE_OBJECT       *Child = NULL;
1065 
1066 
1067     switch (Op->Asl.AmlOpcode)
1068     {
1069     case AML_DATA_REGION_OP:
1070     case AML_DEVICE_OP:
1071     case AML_EVENT_OP:
1072     case AML_EXTERNAL_OP:
1073     case AML_METHOD_OP:
1074     case AML_MUTEX_OP:
1075     case AML_REGION_OP:
1076     case AML_POWER_RESOURCE_OP:
1077     case AML_PROCESSOR_OP:
1078     case AML_THERMAL_ZONE_OP:
1079     case AML_NAME_OP:
1080     case AML_SCOPE_OP:
1081 
1082         Child = UtGetArg (Op, 0);
1083         break;
1084 
1085     case AML_ALIAS_OP:
1086 
1087         Child = UtGetArg (Op, 1);
1088         break;
1089 
1090     case AML_CREATE_BIT_FIELD_OP:
1091     case AML_CREATE_BYTE_FIELD_OP:
1092     case AML_CREATE_WORD_FIELD_OP:
1093     case AML_CREATE_DWORD_FIELD_OP:
1094     case AML_CREATE_QWORD_FIELD_OP:
1095 
1096         Child = UtGetArg (Op, 2);
1097         break;
1098 
1099     case AML_CREATE_FIELD_OP:
1100 
1101         Child = UtGetArg (Op, 3);
1102         break;
1103 
1104     case AML_BANK_FIELD_OP:
1105     case AML_INDEX_FIELD_OP:
1106     case AML_FIELD_OP:
1107 
1108         return;
1109 
1110     default:
1111 
1112         return;
1113     }
1114 
1115     if (Child)
1116     {
1117         UtAttachNamepathToOwner (Op, Child);
1118     }
1119 }
1120 
1121 
1122 /*******************************************************************************
1123  *
1124  * FUNCTION:    OpnGenerateAmlOperands
1125  *
1126  * PARAMETERS:  Op        - The parent parse node
1127  *
1128  * RETURN:      None
1129  *
1130  * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more
1131  *              complex AML opcodes require processing of the child nodes
1132  *              (arguments/operands).
1133  *
1134  ******************************************************************************/
1135 
1136 void
1137 OpnGenerateAmlOperands (
1138     ACPI_PARSE_OBJECT       *Op)
1139 {
1140 
1141 
1142     if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)
1143     {
1144         return;
1145     }
1146 
1147     switch (Op->Asl.ParseOpcode)
1148     {
1149     case PARSEOP_DEFINITION_BLOCK:
1150 
1151         OpnDoDefinitionBlock (Op);
1152         break;
1153 
1154     case PARSEOP_METHOD:
1155 
1156         OpnDoMethod (Op);
1157         break;
1158 
1159     case PARSEOP_MUTEX:
1160 
1161         OpnDoMutex (Op);
1162         break;
1163 
1164     case PARSEOP_FIELD:
1165 
1166         OpnDoField (Op);
1167         break;
1168 
1169     case PARSEOP_INDEXFIELD:
1170 
1171         OpnDoIndexField (Op);
1172         break;
1173 
1174     case PARSEOP_BANKFIELD:
1175 
1176         OpnDoBankField (Op);
1177         break;
1178 
1179     case PARSEOP_BUFFER:
1180 
1181         OpnDoBuffer (Op);
1182         break;
1183 
1184     case PARSEOP_LOADTABLE:
1185 
1186         OpnDoLoadTable (Op);
1187         break;
1188 
1189     case PARSEOP_OPERATIONREGION:
1190 
1191         OpnDoRegion (Op);
1192         break;
1193 
1194     case PARSEOP_RESOURCETEMPLATE:
1195 
1196         RsDoResourceTemplate (Op);
1197         break;
1198 
1199     case PARSEOP_NAMESEG:
1200     case PARSEOP_NAMESTRING:
1201     case PARSEOP_METHODCALL:
1202     case PARSEOP_STRING_LITERAL:
1203     default:
1204 
1205         break;
1206     }
1207 
1208     /* TBD: move */
1209 
1210     OpnAttachNameToNode (Op);
1211 }
1212