xref: /freebsd/sys/contrib/dev/acpica/compiler/asloperands.c (revision 3f0275a0331d5d477f9d8dc5accbba3533ac4cbf)
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_ZERO)         ||
765         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG))
766     {
767         if (!PackageLength)
768         {
769             /* No length AND no initializer list -- issue a remark */
770 
771             AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH,
772                 PackageLengthOp, NULL);
773 
774             /* But go ahead and put the buffer length of zero into the AML */
775         }
776     }
777 
778     /*
779      * If the PackageLength is a constant <= 255, we can change the
780      * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode.
781      */
782     if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
783             (Op->Asl.Child->Asl.Value.Integer <= 255))  ||
784         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) ||
785         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)||
786         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO))
787     {
788         Op->Asl.AmlOpcode = AML_PACKAGE_OP;
789         Op->Asl.ParseOpcode = PARSEOP_PACKAGE;
790 
791         /*
792          * Just set the package size node to be the package length, regardless
793          * of whether it was previously an integer or a default_arg placeholder
794          */
795         PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
796         PackageLengthOp->Asl.AmlLength = 1;
797         PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
798         PackageLengthOp->Asl.Value.Integer = PackageLength;
799     }
800 
801     /* Remaining nodes are handled via the tree walk */
802 }
803 
804 
805 /*******************************************************************************
806  *
807  * FUNCTION:    OpnDoLoadTable
808  *
809  * PARAMETERS:  Op        - The parent parse node
810  *
811  * RETURN:      None
812  *
813  * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword.
814  *
815  ******************************************************************************/
816 
817 static void
818 OpnDoLoadTable (
819     ACPI_PARSE_OBJECT       *Op)
820 {
821     ACPI_PARSE_OBJECT       *Next;
822 
823 
824     /* Opcode is parent node */
825     /* First child is the table signature */
826 
827     Next = Op->Asl.Child;
828 
829     /* Second child is the OEM ID*/
830 
831     Next = Next->Asl.Next;
832 
833     /* Third child is the OEM table ID */
834 
835     Next = Next->Asl.Next;
836 
837     /* Fourth child is the RootPath string */
838 
839     Next = Next->Asl.Next;
840     if (Next->Asl.ParseOpcode == PARSEOP_ZERO)
841     {
842         Next->Asl.ParseOpcode    = PARSEOP_STRING_LITERAL;
843         Next->Asl.Value.String   = "\\";
844         Next->Asl.AmlLength      = 2;
845         OpcGenerateAmlOpcode (Next);
846     }
847 
848 #ifdef ASL_FUTURE_IMPLEMENTATION
849 
850     /* TBD: NOT IMPLEMENTED */
851     /* Fifth child is the [optional] ParameterPathString */
852     /* Sixth child is the [optional] ParameterData */
853 
854     Next = Next->Asl.Next;
855     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
856     {
857         Next->Asl.AmlLength = 1;
858         Next->Asl.ParseOpcode = ZERO;
859         OpcGenerateAmlOpcode (Next);
860     }
861 
862 
863     Next = Next->Asl.Next;
864     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
865     {
866         Next->Asl.AmlLength = 1;
867         Next->Asl.ParseOpcode = ZERO;
868         OpcGenerateAmlOpcode (Next);
869     }
870 #endif
871 }
872 
873 
874 /*******************************************************************************
875  *
876  * FUNCTION:    OpnDoDefinitionBlock
877  *
878  * PARAMETERS:  Op        - The parent parse node
879  *
880  * RETURN:      None
881  *
882  * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword
883  *
884  ******************************************************************************/
885 
886 static void
887 OpnDoDefinitionBlock (
888     ACPI_PARSE_OBJECT       *Op)
889 {
890     ACPI_PARSE_OBJECT       *Child;
891     ACPI_SIZE               Length;
892     UINT32                  i;
893     char                    *Filename;
894 
895 
896     /*
897      * These nodes get stuffed into the table header.  They are special
898      * cased when the table is written to the output file.
899      *
900      * Mark all of these nodes as non-usable so they won't get output
901      * as AML opcodes!
902      */
903 
904     /* Get AML filename. Use it if non-null */
905 
906     Child = Op->Asl.Child;
907     if (Child->Asl.Value.Buffer  &&
908         *Child->Asl.Value.Buffer &&
909         (Gbl_UseDefaultAmlFilename))
910     {
911         /*
912          * We will use the AML filename that is embedded in the source file
913          * for the output filename.
914          */
915         Filename = ACPI_ALLOCATE (strlen (Gbl_DirectoryPath) +
916                     strlen ((char *) Child->Asl.Value.Buffer) + 1);
917 
918         /* Prepend the current directory path */
919 
920         strcpy (Filename, Gbl_DirectoryPath);
921         strcat (Filename, (char *) Child->Asl.Value.Buffer);
922 
923         Gbl_OutputFilenamePrefix = Filename;
924     }
925     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
926 
927     /* Signature */
928 
929     Child = Child->Asl.Next;
930     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
931     if (Child->Asl.Value.String)
932     {
933         Gbl_TableSignature = Child->Asl.Value.String;
934         if (ACPI_STRLEN (Gbl_TableSignature) != 4)
935         {
936             AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
937                 "Length not exactly 4");
938         }
939 
940         for (i = 0; i < 4; i++)
941         {
942             if (!isalnum ((int) Gbl_TableSignature[i]))
943             {
944                 AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
945                     "Contains non-alphanumeric characters");
946             }
947         }
948     }
949 
950     /* Revision */
951 
952     Child = Child->Asl.Next;
953     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
954     /*
955      * We used the revision to set the integer width earlier
956      */
957 
958     /* OEMID */
959 
960     Child = Child->Asl.Next;
961     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
962 
963     /* OEM TableID */
964 
965     Child = Child->Asl.Next;
966     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
967     if (Child->Asl.Value.String)
968     {
969         Length = ACPI_STRLEN (Child->Asl.Value.String);
970         Gbl_TableId = AcpiOsAllocate (Length + 1);
971         ACPI_STRCPY (Gbl_TableId, Child->Asl.Value.String);
972 
973         for (i = 0; i < Length; i++)
974         {
975             if (Gbl_TableId[i] == ' ')
976             {
977                 Gbl_TableId[i] = 0;
978                 break;
979             }
980         }
981     }
982 
983     /* OEM Revision */
984 
985     Child = Child->Asl.Next;
986     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
987 }
988 
989 
990 /*******************************************************************************
991  *
992  * FUNCTION:    UtGetArg
993  *
994  * PARAMETERS:  Op              - Get an argument for this op
995  *              Argn            - Nth argument to get
996  *
997  * RETURN:      The argument (as an Op object).  NULL if argument does not exist
998  *
999  * DESCRIPTION: Get the specified op's argument (peer)
1000  *
1001  ******************************************************************************/
1002 
1003 ACPI_PARSE_OBJECT *
1004 UtGetArg (
1005     ACPI_PARSE_OBJECT       *Op,
1006     UINT32                  Argn)
1007 {
1008     ACPI_PARSE_OBJECT       *Arg = NULL;
1009 
1010 
1011     /* Get the requested argument object */
1012 
1013     Arg = Op->Asl.Child;
1014     while (Arg && Argn)
1015     {
1016         Argn--;
1017         Arg = Arg->Asl.Next;
1018     }
1019 
1020     return (Arg);
1021 }
1022 
1023 
1024 /*******************************************************************************
1025  *
1026  * FUNCTION:    OpnAttachNameToNode
1027  *
1028  * PARAMETERS:  Op        - The parent parse node
1029  *
1030  * RETURN:      None
1031  *
1032  * DESCRIPTION: For the named ASL/AML operators, get the actual name from the
1033  *              argument list and attach it to the parent node so that we
1034  *              can get to it quickly later.
1035  *
1036  ******************************************************************************/
1037 
1038 static void
1039 OpnAttachNameToNode (
1040     ACPI_PARSE_OBJECT       *Op)
1041 {
1042     ACPI_PARSE_OBJECT       *Child = NULL;
1043 
1044 
1045     if (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)
1046     {
1047         Child = UtGetArg (Op, 0);
1048     }
1049     else switch (Op->Asl.AmlOpcode)
1050     {
1051     case AML_DATA_REGION_OP:
1052     case AML_DEVICE_OP:
1053     case AML_EVENT_OP:
1054     case AML_METHOD_OP:
1055     case AML_MUTEX_OP:
1056     case AML_REGION_OP:
1057     case AML_POWER_RES_OP:
1058     case AML_PROCESSOR_OP:
1059     case AML_THERMAL_ZONE_OP:
1060     case AML_NAME_OP:
1061     case AML_SCOPE_OP:
1062 
1063         Child = UtGetArg (Op, 0);
1064         break;
1065 
1066     case AML_ALIAS_OP:
1067 
1068         Child = UtGetArg (Op, 1);
1069         break;
1070 
1071     case AML_CREATE_BIT_FIELD_OP:
1072     case AML_CREATE_BYTE_FIELD_OP:
1073     case AML_CREATE_WORD_FIELD_OP:
1074     case AML_CREATE_DWORD_FIELD_OP:
1075     case AML_CREATE_QWORD_FIELD_OP:
1076 
1077         Child = UtGetArg (Op, 2);
1078         break;
1079 
1080     case AML_CREATE_FIELD_OP:
1081 
1082         Child = UtGetArg (Op, 3);
1083         break;
1084 
1085     case AML_BANK_FIELD_OP:
1086     case AML_INDEX_FIELD_OP:
1087     case AML_FIELD_OP:
1088 
1089         return;
1090 
1091     default:
1092         return;
1093     }
1094 
1095     if (Child)
1096     {
1097         UtAttachNamepathToOwner (Op, Child);
1098     }
1099 }
1100 
1101 
1102 /*******************************************************************************
1103  *
1104  * FUNCTION:    OpnGenerateAmlOperands
1105  *
1106  * PARAMETERS:  Op        - The parent parse node
1107  *
1108  * RETURN:      None
1109  *
1110  * DESCRIPTION: Prepare nodes to be output as AML data and operands.  The more
1111  *              complex AML opcodes require processing of the child nodes
1112  *              (arguments/operands).
1113  *
1114  ******************************************************************************/
1115 
1116 void
1117 OpnGenerateAmlOperands (
1118     ACPI_PARSE_OBJECT       *Op)
1119 {
1120 
1121 
1122     if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)
1123     {
1124         return;
1125     }
1126 
1127     switch (Op->Asl.ParseOpcode)
1128     {
1129     case PARSEOP_DEFINITIONBLOCK:
1130         OpnDoDefinitionBlock (Op);
1131         break;
1132 
1133     case PARSEOP_METHOD:
1134         OpnDoMethod (Op);
1135         break;
1136 
1137     case PARSEOP_MUTEX:
1138         OpnDoMutex (Op);
1139         break;
1140 
1141     case PARSEOP_FIELD:
1142         OpnDoField (Op);
1143         break;
1144 
1145     case PARSEOP_INDEXFIELD:
1146         OpnDoIndexField (Op);
1147         break;
1148 
1149     case PARSEOP_BANKFIELD:
1150         OpnDoBankField (Op);
1151         break;
1152 
1153     case PARSEOP_BUFFER:
1154         OpnDoBuffer (Op);
1155         break;
1156 
1157     case PARSEOP_LOADTABLE:
1158         OpnDoLoadTable (Op);
1159         break;
1160 
1161     case PARSEOP_OPERATIONREGION:
1162         OpnDoRegion (Op);
1163         break;
1164 
1165     case PARSEOP_RESOURCETEMPLATE:
1166         RsDoResourceTemplate (Op);
1167         break;
1168 
1169     case PARSEOP_NAMESEG:
1170     case PARSEOP_NAMESTRING:
1171     case PARSEOP_METHODCALL:
1172     case PARSEOP_STRING_LITERAL:
1173         break;
1174 
1175     default:
1176         break;
1177     }
1178 
1179     /* TBD: move */
1180 
1181     OpnAttachNameToNode (Op);
1182 }
1183 
1184 
1185