xref: /freebsd/sys/contrib/dev/acpica/compiler/asloperands.c (revision 884a2a699669ec61e2366e3e358342dbc94be24a)
1 
2 /******************************************************************************
3  *
4  * Module Name: asloperands - AML operand processing
5  *
6  *****************************************************************************/
7 
8 /*
9  * Copyright (C) 2000 - 2011, 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         if (Next->Asl.Value.Integer > 15)
186         {
187             AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
188         }
189         Concurrency = (UINT8) Next->Asl.Value.Integer;
190     }
191 
192     /* Put the bits in their proper places */
193 
194     MethodFlags = (UINT8) ((NumArgs & 0x7) |
195                           ((Serialized & 0x1) << 3) |
196                           ((Concurrency & 0xF) << 4));
197 
198     /* Use the last node for the combined flags byte */
199 
200     Next->Asl.Value.Integer = MethodFlags;
201     Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
202     Next->Asl.AmlLength = 1;
203     Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
204 
205     /* Save the arg count in the first node */
206 
207     Op->Asl.Extra = NumArgs;
208 }
209 
210 
211 /*******************************************************************************
212  *
213  * FUNCTION:    OpnDoFieldCommon
214  *
215  * PARAMETERS:  FieldOp       - Node for an ASL field
216  *              Op            - The parent parse node
217  *
218  * RETURN:      None
219  *
220  * DESCRIPTION: Construct the AML operands for the various field keywords,
221  *              FIELD, BANKFIELD, INDEXFIELD
222  *
223  ******************************************************************************/
224 
225 static void
226 OpnDoFieldCommon (
227     ACPI_PARSE_OBJECT       *FieldOp,
228     ACPI_PARSE_OBJECT       *Op)
229 {
230     ACPI_PARSE_OBJECT       *Next;
231     ACPI_PARSE_OBJECT       *PkgLengthNode;
232     UINT32                  CurrentBitOffset;
233     UINT32                  NewBitOffset;
234     UINT8                   AccessType;
235     UINT8                   LockRule;
236     UINT8                   UpdateRule;
237     UINT8                   FieldFlags;
238     UINT32                  MinimumLength;
239 
240 
241     /* AccessType -- not optional, so no need to check for DEFAULT_ARG */
242 
243     AccessType = (UINT8) Op->Asl.Value.Integer;
244     Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
245 
246     /* Set the access type in the parent (field) node for use later */
247 
248     FieldOp->Asl.Value.Integer = AccessType;
249 
250     /* LockRule -- not optional, so no need to check for DEFAULT_ARG */
251 
252     Next = Op->Asl.Next;
253     LockRule = (UINT8) Next->Asl.Value.Integer;
254     Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
255 
256     /* UpdateRule -- not optional, so no need to check for DEFAULT_ARG */
257 
258     Next = Next->Asl.Next;
259     UpdateRule = (UINT8) Next->Asl.Value.Integer;
260 
261     /*
262      * Generate the flags byte.  The various fields are already
263      * in the right bit position via translation from the
264      * keywords by the parser.
265      */
266     FieldFlags = (UINT8) (AccessType | LockRule | UpdateRule);
267 
268     /* Use the previous node to be the FieldFlags node */
269 
270     /* Set the node to RAW_DATA */
271 
272     Next->Asl.Value.Integer = FieldFlags;
273     Next->Asl.AmlOpcode     = AML_RAW_DATA_BYTE;
274     Next->Asl.AmlLength     = 1;
275     Next->Asl.ParseOpcode   = PARSEOP_RAW_DATA;
276 
277     /* Process the FieldUnitList */
278 
279     Next = Next->Asl.Next;
280     CurrentBitOffset = 0;
281 
282     while (Next)
283     {
284         /* Save the offset of this field unit */
285 
286         Next->Asl.ExtraValue = CurrentBitOffset;
287 
288         switch (Next->Asl.ParseOpcode)
289         {
290         case PARSEOP_ACCESSAS:
291 
292             PkgLengthNode = Next->Asl.Child;
293             AccessType = (UINT8) PkgLengthNode->Asl.Value.Integer;
294 
295             /* Nothing additional to do */
296             break;
297 
298 
299         case PARSEOP_OFFSET:
300 
301             /* New offset into the field */
302 
303             PkgLengthNode = Next->Asl.Child;
304             NewBitOffset = ((UINT32) PkgLengthNode->Asl.Value.Integer) * 8;
305 
306             /*
307              * Examine the specified offset in relation to the
308              * current offset counter.
309              */
310             if (NewBitOffset < CurrentBitOffset)
311             {
312                 /*
313                  * Not allowed to specify a backwards offset!
314                  * Issue error and ignore this node.
315                  */
316                 AslError (ASL_ERROR, ASL_MSG_BACKWARDS_OFFSET, PkgLengthNode,
317                     NULL);
318                 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
319                 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
320             }
321             else if (NewBitOffset == CurrentBitOffset)
322             {
323                 /*
324                  * Offset is redundant; we don't need to output an
325                  * offset opcode.  Just set these nodes to default
326                  */
327                 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
328                 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
329             }
330             else
331             {
332                 /*
333                  * Valid new offset - set the value to be inserted into the AML
334                  * and update the offset counter.
335                  */
336                 PkgLengthNode->Asl.Value.Integer =
337                     NewBitOffset - CurrentBitOffset;
338                 CurrentBitOffset = NewBitOffset;
339             }
340             break;
341 
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                     MinimumLength = 8;
361                     break;
362 
363                 case AML_FIELD_ACCESS_WORD:
364                     MinimumLength = 16;
365                     break;
366 
367                 case AML_FIELD_ACCESS_DWORD:
368                     MinimumLength = 32;
369                     break;
370 
371                 case AML_FIELD_ACCESS_QWORD:
372                     MinimumLength = 64;
373                     break;
374             }
375 
376             PkgLengthNode->Asl.ExtraValue = MinimumLength;
377             break;
378 
379         default:
380             /* All supported field opcodes must appear above */
381             break;
382         }
383 
384         /* Move on to next entry in the field list */
385 
386         Next = Next->Asl.Next;
387     }
388 }
389 
390 
391 /*******************************************************************************
392  *
393  * FUNCTION:    OpnDoField
394  *
395  * PARAMETERS:  Op        - The parent parse node
396  *
397  * RETURN:      None
398  *
399  * DESCRIPTION: Construct the AML operands for the FIELD ASL keyword
400  *
401  ******************************************************************************/
402 
403 static void
404 OpnDoField (
405     ACPI_PARSE_OBJECT       *Op)
406 {
407     ACPI_PARSE_OBJECT       *Next;
408 
409 
410     /* Opcode is parent node */
411     /* First child is field name */
412 
413     Next = Op->Asl.Child;
414 
415     /* Second child is the AccessType */
416 
417     OpnDoFieldCommon (Op, Next->Asl.Next);
418 }
419 
420 
421 /*******************************************************************************
422  *
423  * FUNCTION:    OpnDoIndexField
424  *
425  * PARAMETERS:  Op        - The parent parse node
426  *
427  * RETURN:      None
428  *
429  * DESCRIPTION: Construct the AML operands for the INDEXFIELD ASL keyword
430  *
431  ******************************************************************************/
432 
433 static void
434 OpnDoIndexField (
435     ACPI_PARSE_OBJECT       *Op)
436 {
437     ACPI_PARSE_OBJECT       *Next;
438 
439 
440     /* Opcode is parent node */
441     /* First child is the index name */
442 
443     Next = Op->Asl.Child;
444 
445     /* Second child is the data name */
446 
447     Next = Next->Asl.Next;
448 
449     /* Third child is the AccessType */
450 
451     OpnDoFieldCommon (Op, Next->Asl.Next);
452 }
453 
454 
455 /*******************************************************************************
456  *
457  * FUNCTION:    OpnDoBankField
458  *
459  * PARAMETERS:  Op        - The parent parse node
460  *
461  * RETURN:      None
462  *
463  * DESCRIPTION: Construct the AML operands for the BANKFIELD ASL keyword
464  *
465  ******************************************************************************/
466 
467 static void
468 OpnDoBankField (
469     ACPI_PARSE_OBJECT       *Op)
470 {
471     ACPI_PARSE_OBJECT       *Next;
472 
473 
474     /* Opcode is parent node */
475     /* First child is the region name */
476 
477     Next = Op->Asl.Child;
478 
479     /* Second child is the bank name */
480 
481     Next = Next->Asl.Next;
482 
483     /* Third child is the bank value */
484 
485     Next = Next->Asl.Next;
486 
487     /* Fourth child is the AccessType */
488 
489     OpnDoFieldCommon (Op, Next->Asl.Next);
490 }
491 
492 
493 /*******************************************************************************
494  *
495  * FUNCTION:    OpnDoRegion
496  *
497  * PARAMETERS:  Op        - The parent parse node
498  *
499  * RETURN:      None
500  *
501  * DESCRIPTION: Tries to get the length of the region.  Can only do this at
502  *              compile time if the length is a constant.
503  *
504  ******************************************************************************/
505 
506 static void
507 OpnDoRegion (
508     ACPI_PARSE_OBJECT       *Op)
509 {
510     ACPI_PARSE_OBJECT       *Next;
511 
512 
513     /* Opcode is parent node */
514     /* First child is the region name */
515 
516     Next = Op->Asl.Child;
517 
518     /* Second child is the space ID*/
519 
520     Next = Next->Asl.Next;
521 
522     /* Third child is the region offset */
523 
524     Next = Next->Asl.Next;
525 
526     /* Fourth child is the region length */
527 
528     Next = Next->Asl.Next;
529     if (Next->Asl.ParseOpcode == PARSEOP_INTEGER)
530     {
531         Op->Asl.Value.Integer = Next->Asl.Value.Integer;
532     }
533     else
534     {
535         Op->Asl.Value.Integer = ACPI_UINT64_MAX;
536     }
537 }
538 
539 
540 /*******************************************************************************
541  *
542  * FUNCTION:    OpnDoBuffer
543  *
544  * PARAMETERS:  Op        - The parent parse node
545  *
546  * RETURN:      None
547  *
548  * DESCRIPTION: Construct the AML operands for the BUFFER ASL keyword.  We
549  *              build a single raw byte buffer from the initialization nodes,
550  *              each parse node contains a buffer byte.
551  *
552  ******************************************************************************/
553 
554 static void
555 OpnDoBuffer (
556     ACPI_PARSE_OBJECT       *Op)
557 {
558     ACPI_PARSE_OBJECT       *InitializerOp;
559     ACPI_PARSE_OBJECT       *BufferLengthOp;
560 
561     /* Optional arguments for this opcode with defaults */
562 
563     UINT32                  BufferLength = 0;
564 
565 
566     /* Opcode and package length first */
567     /* Buffer Length is next, followed by the initializer list */
568 
569     BufferLengthOp = Op->Asl.Child;
570     InitializerOp = BufferLengthOp->Asl.Next;
571 
572     /*
573      * If the BufferLength is not an INTEGER or was not specified in the ASL
574      * (DEFAULT_ARG), it is a TermArg that is
575      * evaluated at run-time, and we are therefore finished.
576      */
577     if ((BufferLengthOp->Asl.ParseOpcode != PARSEOP_INTEGER) &&
578         (BufferLengthOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
579     {
580         return;
581     }
582 
583     /*
584      * We want to count the number of items in the initializer list, because if
585      * it is larger than the buffer length, we will define the buffer size
586      * to be the size of the initializer list (as per the ACPI Specification)
587      */
588     switch (InitializerOp->Asl.ParseOpcode)
589     {
590     case PARSEOP_INTEGER:
591     case PARSEOP_BYTECONST:
592     case PARSEOP_WORDCONST:
593     case PARSEOP_DWORDCONST:
594 
595         /* The peer list contains the byte list (if any...) */
596 
597         while (InitializerOp)
598         {
599             /* For buffers, this is a list of raw bytes */
600 
601             InitializerOp->Asl.AmlOpcode      = AML_RAW_DATA_BYTE;
602             InitializerOp->Asl.AmlLength      = 1;
603             InitializerOp->Asl.ParseOpcode    = PARSEOP_RAW_DATA;
604 
605             BufferLength++;
606             InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
607         }
608         break;
609 
610 
611     case PARSEOP_STRING_LITERAL:
612 
613         /*
614          * Only one initializer, the string.  Buffer must be big enough to hold
615          * the string plus the null termination byte
616          */
617         BufferLength = strlen (InitializerOp->Asl.Value.String) + 1;
618 
619         InitializerOp->Asl.AmlOpcode      = AML_RAW_DATA_BUFFER;
620         InitializerOp->Asl.AmlLength      = BufferLength;
621         InitializerOp->Asl.ParseOpcode    = PARSEOP_RAW_DATA;
622         break;
623 
624 
625     case PARSEOP_RAW_DATA:
626 
627         /* Buffer nodes are already initialized (e.g. Unicode operator) */
628         return;
629 
630 
631     case PARSEOP_DEFAULT_ARG:
632         break;
633 
634 
635     default:
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_DEFAULT_ARG))
765     {
766         if (!PackageLength)
767         {
768             /* No length AND no initializer list -- issue a remark */
769 
770             AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH,
771                 PackageLengthOp, NULL);
772 
773             /* But go ahead and put the buffer length of zero into the AML */
774         }
775     }
776 
777     /*
778      * If the PackageLength is a constant <= 255, we can change the
779      * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode.
780      */
781     if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
782         (Op->Asl.Child->Asl.Value.Integer <= 255))
783     {
784         Op->Asl.AmlOpcode = AML_PACKAGE_OP;
785         Op->Asl.ParseOpcode = PARSEOP_PACKAGE;
786 
787         /*
788          * Just set the package size node to be the package length, regardless
789          * of whether it was previously an integer or a default_arg placeholder
790          */
791         PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
792         PackageLengthOp->Asl.AmlLength = 1;
793         PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
794         PackageLengthOp->Asl.Value.Integer = PackageLength;
795     }
796 
797     /* Remaining nodes are handled via the tree walk */
798 }
799 
800 
801 /*******************************************************************************
802  *
803  * FUNCTION:    OpnDoLoadTable
804  *
805  * PARAMETERS:  Op        - The parent parse node
806  *
807  * RETURN:      None
808  *
809  * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword.
810  *
811  ******************************************************************************/
812 
813 static void
814 OpnDoLoadTable (
815     ACPI_PARSE_OBJECT       *Op)
816 {
817     ACPI_PARSE_OBJECT       *Next;
818 
819 
820     /* Opcode is parent node */
821     /* First child is the table signature */
822 
823     Next = Op->Asl.Child;
824 
825     /* Second child is the OEM ID*/
826 
827     Next = Next->Asl.Next;
828 
829     /* Third child is the OEM table ID */
830 
831     Next = Next->Asl.Next;
832 
833     /* Fourth child is the RootPath string */
834 
835     Next = Next->Asl.Next;
836     if (Next->Asl.ParseOpcode == PARSEOP_ZERO)
837     {
838         Next->Asl.ParseOpcode    = PARSEOP_STRING_LITERAL;
839         Next->Asl.Value.String   = "\\";
840         Next->Asl.AmlLength      = 2;
841         OpcGenerateAmlOpcode (Next);
842     }
843 
844 #ifdef ASL_FUTURE_IMPLEMENTATION
845 
846     /* TBD: NOT IMPLEMENTED */
847     /* Fifth child is the [optional] ParameterPathString */
848     /* Sixth child is the [optional] ParameterData */
849 
850     Next = Next->Asl.Next;
851     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
852     {
853         Next->Asl.AmlLength = 1;
854         Next->Asl.ParseOpcode = ZERO;
855         OpcGenerateAmlOpcode (Next);
856     }
857 
858 
859     Next = Next->Asl.Next;
860     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
861     {
862         Next->Asl.AmlLength = 1;
863         Next->Asl.ParseOpcode = ZERO;
864         OpcGenerateAmlOpcode (Next);
865     }
866 #endif
867 }
868 
869 
870 /*******************************************************************************
871  *
872  * FUNCTION:    OpnDoDefinitionBlock
873  *
874  * PARAMETERS:  Op        - The parent parse node
875  *
876  * RETURN:      None
877  *
878  * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword
879  *
880  ******************************************************************************/
881 
882 static void
883 OpnDoDefinitionBlock (
884     ACPI_PARSE_OBJECT       *Op)
885 {
886     ACPI_PARSE_OBJECT       *Child;
887     ACPI_SIZE               Length;
888     UINT32                  i;
889     char                    *Filename;
890 
891 
892     /*
893      * These nodes get stuffed into the table header.  They are special
894      * cased when the table is written to the output file.
895      *
896      * Mark all of these nodes as non-usable so they won't get output
897      * as AML opcodes!
898      */
899 
900     /* Get AML filename. Use it if non-null */
901 
902     Child = Op->Asl.Child;
903     if (Child->Asl.Value.Buffer  &&
904         *Child->Asl.Value.Buffer &&
905         (Gbl_UseDefaultAmlFilename))
906     {
907         /*
908          * We will use the AML filename that is embedded in the source file
909          * for the output filename.
910          */
911         Filename = ACPI_ALLOCATE (strlen (Gbl_DirectoryPath) +
912                     strlen ((char *) Child->Asl.Value.Buffer) + 1);
913 
914         /* Prepend the current directory path */
915 
916         strcpy (Filename, Gbl_DirectoryPath);
917         strcat (Filename, (char *) Child->Asl.Value.Buffer);
918 
919         Gbl_OutputFilenamePrefix = Filename;
920     }
921     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
922 
923     /* Signature */
924 
925     Child = Child->Asl.Next;
926     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
927     if (Child->Asl.Value.String)
928     {
929         Gbl_TableSignature = Child->Asl.Value.String;
930         if (ACPI_STRLEN (Gbl_TableSignature) != 4)
931         {
932             AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
933                 "Length not exactly 4");
934         }
935 
936         for (i = 0; i < 4; i++)
937         {
938             if (!isalnum ((int) Gbl_TableSignature[i]))
939             {
940                 AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
941                     "Contains non-alphanumeric characters");
942             }
943         }
944     }
945 
946     /* Revision */
947 
948     Child = Child->Asl.Next;
949     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
950     /*
951      * We used the revision to set the integer width earlier
952      */
953 
954     /* OEMID */
955 
956     Child = Child->Asl.Next;
957     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
958 
959     /* OEM TableID */
960 
961     Child = Child->Asl.Next;
962     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
963     if (Child->Asl.Value.String)
964     {
965         Length = ACPI_STRLEN (Child->Asl.Value.String);
966         Gbl_TableId = AcpiOsAllocate (Length + 1);
967         ACPI_STRCPY (Gbl_TableId, Child->Asl.Value.String);
968 
969         for (i = 0; i < Length; i++)
970         {
971             if (Gbl_TableId[i] == ' ')
972             {
973                 Gbl_TableId[i] = 0;
974                 break;
975             }
976         }
977     }
978 
979     /* OEM Revision */
980 
981     Child = Child->Asl.Next;
982     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
983 }
984 
985 
986 /*******************************************************************************
987  *
988  * FUNCTION:    UtGetArg
989  *
990  * PARAMETERS:  Op              - Get an argument for this op
991  *              Argn            - Nth argument to get
992  *
993  * RETURN:      The argument (as an Op object).  NULL if argument does not exist
994  *
995  * DESCRIPTION: Get the specified op's argument (peer)
996  *
997  ******************************************************************************/
998 
999 ACPI_PARSE_OBJECT *
1000 UtGetArg (
1001     ACPI_PARSE_OBJECT       *Op,
1002     UINT32                  Argn)
1003 {
1004     ACPI_PARSE_OBJECT       *Arg = NULL;
1005 
1006 
1007     /* Get the requested argument object */
1008 
1009     Arg = Op->Asl.Child;
1010     while (Arg && Argn)
1011     {
1012         Argn--;
1013         Arg = Arg->Asl.Next;
1014     }
1015 
1016     return (Arg);
1017 }
1018 
1019 
1020 /*******************************************************************************
1021  *
1022  * FUNCTION:    OpnAttachNameToNode
1023  *
1024  * PARAMETERS:  Op        - The parent parse node
1025  *
1026  * RETURN:      None
1027  *
1028  * DESCRIPTION: For the named ASL/AML operators, get the actual name from the
1029  *              argument list and attach it to the parent node so that we
1030  *              can get to it quickly later.
1031  *
1032  ******************************************************************************/
1033 
1034 static void
1035 OpnAttachNameToNode (
1036     ACPI_PARSE_OBJECT       *Op)
1037 {
1038     ACPI_PARSE_OBJECT       *Child = NULL;
1039 
1040 
1041     if (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)
1042     {
1043         Child = UtGetArg (Op, 0);
1044     }
1045     else switch (Op->Asl.AmlOpcode)
1046     {
1047     case AML_DATA_REGION_OP:
1048     case AML_DEVICE_OP:
1049     case AML_EVENT_OP:
1050     case AML_METHOD_OP:
1051     case AML_MUTEX_OP:
1052     case AML_REGION_OP:
1053     case AML_POWER_RES_OP:
1054     case AML_PROCESSOR_OP:
1055     case AML_THERMAL_ZONE_OP:
1056     case AML_NAME_OP:
1057     case AML_SCOPE_OP:
1058 
1059         Child = UtGetArg (Op, 0);
1060         break;
1061 
1062     case AML_ALIAS_OP:
1063 
1064         Child = UtGetArg (Op, 1);
1065         break;
1066 
1067     case AML_CREATE_BIT_FIELD_OP:
1068     case AML_CREATE_BYTE_FIELD_OP:
1069     case AML_CREATE_WORD_FIELD_OP:
1070     case AML_CREATE_DWORD_FIELD_OP:
1071     case AML_CREATE_QWORD_FIELD_OP:
1072 
1073         Child = UtGetArg (Op, 2);
1074         break;
1075 
1076     case AML_CREATE_FIELD_OP:
1077 
1078         Child = UtGetArg (Op, 3);
1079         break;
1080 
1081     case AML_BANK_FIELD_OP:
1082     case AML_INDEX_FIELD_OP:
1083     case AML_FIELD_OP:
1084 
1085         return;
1086 
1087     default:
1088         return;
1089     }
1090 
1091     if (Child)
1092     {
1093         UtAttachNamepathToOwner (Op, Child);
1094     }
1095 }
1096 
1097 
1098 /*******************************************************************************
1099  *
1100  * FUNCTION:    OpnGenerateAmlOperands
1101  *
1102  * PARAMETERS:  Op        - The parent parse node
1103  *
1104  * RETURN:      None
1105  *
1106  * DESCRIPTION: Prepare nodes to be output as AML data and operands.  The more
1107  *              complex AML opcodes require processing of the child nodes
1108  *              (arguments/operands).
1109  *
1110  ******************************************************************************/
1111 
1112 void
1113 OpnGenerateAmlOperands (
1114     ACPI_PARSE_OBJECT       *Op)
1115 {
1116 
1117 
1118     if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)
1119     {
1120         return;
1121     }
1122 
1123     switch (Op->Asl.ParseOpcode)
1124     {
1125     case PARSEOP_DEFINITIONBLOCK:
1126         OpnDoDefinitionBlock (Op);
1127         break;
1128 
1129     case PARSEOP_METHOD:
1130         OpnDoMethod (Op);
1131         break;
1132 
1133     case PARSEOP_MUTEX:
1134         OpnDoMutex (Op);
1135         break;
1136 
1137     case PARSEOP_FIELD:
1138         OpnDoField (Op);
1139         break;
1140 
1141     case PARSEOP_INDEXFIELD:
1142         OpnDoIndexField (Op);
1143         break;
1144 
1145     case PARSEOP_BANKFIELD:
1146         OpnDoBankField (Op);
1147         break;
1148 
1149     case PARSEOP_BUFFER:
1150         OpnDoBuffer (Op);
1151         break;
1152 
1153     case PARSEOP_LOADTABLE:
1154         OpnDoLoadTable (Op);
1155         break;
1156 
1157     case PARSEOP_OPERATIONREGION:
1158         OpnDoRegion (Op);
1159         break;
1160 
1161     case PARSEOP_RESOURCETEMPLATE:
1162         RsDoResourceTemplate (Op);
1163         break;
1164 
1165     case PARSEOP_NAMESEG:
1166     case PARSEOP_NAMESTRING:
1167     case PARSEOP_METHODCALL:
1168     case PARSEOP_STRING_LITERAL:
1169         break;
1170 
1171     default:
1172         break;
1173     }
1174 
1175     /* TBD: move */
1176 
1177     OpnAttachNameToNode (Op);
1178 }
1179 
1180 
1181