]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/dev/acpica/compiler/asloperands.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / contrib / dev / acpica / compiler / asloperands.c
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