xref: /freebsd/sys/contrib/dev/acpica/compiler/asloperands.c (revision fba7fc7e34e95963b681b882698b951b35d1ba48)
1 
2 /******************************************************************************
3  *
4  * Module Name: asloperands - AML operand processing
5  *              $Revision: 1.57 $
6  *
7  *****************************************************************************/
8 
9 /******************************************************************************
10  *
11  * 1. Copyright Notice
12  *
13  * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp.
14  * All rights reserved.
15  *
16  * 2. License
17  *
18  * 2.1. This is your license from Intel Corp. under its intellectual property
19  * rights.  You may have additional license terms from the party that provided
20  * you this software, covering your right to use that party's intellectual
21  * property rights.
22  *
23  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
24  * copy of the source code appearing in this file ("Covered Code") an
25  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
26  * base code distributed originally by Intel ("Original Intel Code") to copy,
27  * make derivatives, distribute, use and display any portion of the Covered
28  * Code in any form, with the right to sublicense such rights; and
29  *
30  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
31  * license (with the right to sublicense), under only those claims of Intel
32  * patents that are infringed by the Original Intel Code, to make, use, sell,
33  * offer to sell, and import the Covered Code and derivative works thereof
34  * solely to the minimum extent necessary to exercise the above copyright
35  * license, and in no event shall the patent license extend to any additions
36  * to or modifications of the Original Intel Code.  No other license or right
37  * is granted directly or by implication, estoppel or otherwise;
38  *
39  * The above copyright and patent license is granted only if the following
40  * conditions are met:
41  *
42  * 3. Conditions
43  *
44  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
45  * Redistribution of source code of any substantial portion of the Covered
46  * Code or modification with rights to further distribute source must include
47  * the above Copyright Notice, the above License, this list of Conditions,
48  * and the following Disclaimer and Export Compliance provision.  In addition,
49  * Licensee must cause all Covered Code to which Licensee contributes to
50  * contain a file documenting the changes Licensee made to create that Covered
51  * Code and the date of any change.  Licensee must include in that file the
52  * documentation of any changes made by any predecessor Licensee.  Licensee
53  * must include a prominent statement that the modification is derived,
54  * directly or indirectly, from Original Intel Code.
55  *
56  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
57  * Redistribution of source code of any substantial portion of the Covered
58  * Code or modification without rights to further distribute source must
59  * include the following Disclaimer and Export Compliance provision in the
60  * documentation and/or other materials provided with distribution.  In
61  * addition, Licensee may not authorize further sublicense of source of any
62  * portion of the Covered Code, and must include terms to the effect that the
63  * license from Licensee to its licensee is limited to the intellectual
64  * property embodied in the software Licensee provides to its licensee, and
65  * not to intellectual property embodied in modifications its licensee may
66  * make.
67  *
68  * 3.3. Redistribution of Executable. Redistribution in executable form of any
69  * substantial portion of the Covered Code or modification must reproduce the
70  * above Copyright Notice, and the following Disclaimer and Export Compliance
71  * provision in the documentation and/or other materials provided with the
72  * distribution.
73  *
74  * 3.4. Intel retains all right, title, and interest in and to the Original
75  * Intel Code.
76  *
77  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
78  * Intel shall be used in advertising or otherwise to promote the sale, use or
79  * other dealings in products derived from or relating to the Covered Code
80  * without prior written authorization from Intel.
81  *
82  * 4. Disclaimer and Export Compliance
83  *
84  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
85  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
86  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
87  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
88  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
89  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
90  * PARTICULAR PURPOSE.
91  *
92  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
93  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
94  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
95  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
96  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
97  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
98  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
99  * LIMITED REMEDY.
100  *
101  * 4.3. Licensee shall not export, either directly or indirectly, any of this
102  * software or system incorporating such software without first obtaining any
103  * required license or other approval from the U. S. Department of Commerce or
104  * any other agency or department of the United States Government.  In the
105  * event Licensee exports any such software from the United States or
106  * re-exports any such software from a foreign destination, Licensee shall
107  * ensure that the distribution and export/re-export of the software is in
108  * compliance with all laws, regulations, orders, or other restrictions of the
109  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
110  * any of its subsidiaries will export/re-export any technical data, process,
111  * software, or service, directly or indirectly, to any country for which the
112  * United States government or any agency thereof requires an export license,
113  * other governmental approval, or letter of assurance, without first obtaining
114  * such license, approval or letter.
115  *
116  *****************************************************************************/
117 
118 
119 #include <contrib/dev/acpica/compiler/aslcompiler.h>
120 #include "aslcompiler.y.h"
121 #include <contrib/dev/acpica/amlcode.h>
122 
123 #define _COMPONENT          ACPI_COMPILER
124         ACPI_MODULE_NAME    ("asloperands")
125 
126 /* Local prototypes */
127 
128 static void
129 OpnDoField (
130     ACPI_PARSE_OBJECT       *Op);
131 
132 static void
133 OpnDoBankField (
134     ACPI_PARSE_OBJECT       *Op);
135 
136 static void
137 OpnDoBuffer (
138     ACPI_PARSE_OBJECT       *Op);
139 
140 static void
141 OpnDoDefinitionBlock (
142     ACPI_PARSE_OBJECT       *Op);
143 
144 static void
145 OpnDoFieldCommon (
146     ACPI_PARSE_OBJECT       *FieldOp,
147     ACPI_PARSE_OBJECT       *Op);
148 
149 static void
150 OpnDoIndexField (
151     ACPI_PARSE_OBJECT       *Op);
152 
153 static void
154 OpnDoLoadTable (
155     ACPI_PARSE_OBJECT       *Op);
156 
157 static void
158 OpnDoMethod (
159     ACPI_PARSE_OBJECT       *Op);
160 
161 static void
162 OpnDoMutex (
163     ACPI_PARSE_OBJECT       *Op);
164 
165 static void
166 OpnDoRegion (
167     ACPI_PARSE_OBJECT       *Op);
168 
169 static void
170 OpnAttachNameToNode (
171     ACPI_PARSE_OBJECT       *Op);
172 
173 
174 /*******************************************************************************
175  *
176  * FUNCTION:    OpnDoMutex
177  *
178  * PARAMETERS:  Op        - The parent parse node
179  *
180  * RETURN:      None
181  *
182  * DESCRIPTION: Construct the operands for the MUTEX ASL keyword.
183  *
184  ******************************************************************************/
185 
186 static void
187 OpnDoMutex (
188     ACPI_PARSE_OBJECT       *Op)
189 {
190     ACPI_PARSE_OBJECT       *Next;
191 
192 
193     Next = Op->Asl.Child;
194     Next = Next->Asl.Next;
195 
196     if (Next->Asl.Value.Integer > 15)
197     {
198         AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
199     }
200     return;
201 }
202 
203 
204 /*******************************************************************************
205  *
206  * FUNCTION:    OpnDoMethod
207  *
208  * PARAMETERS:  Op        - The parent parse node
209  *
210  * RETURN:      None
211  *
212  * DESCRIPTION: Construct the operands for the METHOD ASL keyword.
213  *
214  ******************************************************************************/
215 
216 static void
217 OpnDoMethod (
218     ACPI_PARSE_OBJECT       *Op)
219 {
220     ACPI_PARSE_OBJECT       *Next;
221 
222     /* Optional arguments for this opcode with defaults */
223 
224     UINT8                   NumArgs = 0;
225     UINT8                   Serialized = 0;
226     UINT8                   Concurrency = 0;
227     UINT8                   MethodFlags;
228 
229 
230     /* Opcode and package length first */
231     /* Method name */
232 
233     Next = Op->Asl.Child;
234 
235     /* Num args */
236 
237     Next = Next->Asl.Next;
238     if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
239     {
240         NumArgs = (UINT8) Next->Asl.Value.Integer;
241         Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
242     }
243 
244     /* Serialized Flag */
245 
246     Next = Next->Asl.Next;
247     if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
248     {
249         Serialized = (UINT8) Next->Asl.Value.Integer;
250         Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
251     }
252 
253     /* Concurrency value (valid values are 0-15) */
254 
255     Next = Next->Asl.Next;
256     if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
257     {
258         if (Next->Asl.Value.Integer > 15)
259         {
260             AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
261         }
262         Concurrency = (UINT8) Next->Asl.Value.Integer;
263     }
264 
265     /* Put the bits in their proper places */
266 
267     MethodFlags = (UINT8) ((NumArgs & 0x7) |
268                           ((Serialized & 0x1) << 3) |
269                           ((Concurrency & 0xF) << 4));
270 
271     /* Use the last node for the combined flags byte */
272 
273     Next->Asl.Value.Integer = MethodFlags;
274     Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
275     Next->Asl.AmlLength = 1;
276     Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
277 
278     /* Save the arg count in the first node */
279 
280     Op->Asl.Extra = NumArgs;
281 }
282 
283 
284 /*******************************************************************************
285  *
286  * FUNCTION:    OpnDoFieldCommon
287  *
288  * PARAMETERS:  FieldOp       - Node for an ASL field
289  *              Op            - The parent parse node
290  *
291  * RETURN:      None
292  *
293  * DESCRIPTION: Construct the AML operands for the various field keywords,
294  *              FIELD, BANKFIELD, INDEXFIELD
295  *
296  ******************************************************************************/
297 
298 static void
299 OpnDoFieldCommon (
300     ACPI_PARSE_OBJECT       *FieldOp,
301     ACPI_PARSE_OBJECT       *Op)
302 {
303     ACPI_PARSE_OBJECT       *Next;
304     ACPI_PARSE_OBJECT       *PkgLengthNode;
305     UINT32                  CurrentBitOffset;
306     UINT32                  NewBitOffset;
307     UINT8                   AccessType;
308     UINT8                   LockRule;
309     UINT8                   UpdateRule;
310     UINT8                   FieldFlags;
311     UINT32                  MinimumLength;
312 
313 
314     /* AccessType -- not optional, so no need to check for DEFAULT_ARG */
315 
316     AccessType = (UINT8) Op->Asl.Value.Integer;
317     Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
318 
319     /* Set the access type in the parent (field) node for use later */
320 
321     FieldOp->Asl.Value.Integer = AccessType;
322 
323     /* LockRule -- not optional, so no need to check for DEFAULT_ARG */
324 
325     Next = Op->Asl.Next;
326     LockRule = (UINT8) Next->Asl.Value.Integer;
327     Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
328 
329     /* UpdateRule -- not optional, so no need to check for DEFAULT_ARG */
330 
331     Next = Next->Asl.Next;
332     UpdateRule = (UINT8) Next->Asl.Value.Integer;
333 
334     /*
335      * Generate the flags byte.  The various fields are already
336      * in the right bit position via translation from the
337      * keywords by the parser.
338      */
339     FieldFlags = (UINT8) (AccessType | LockRule | UpdateRule);
340 
341     /* Use the previous node to be the FieldFlags node */
342 
343     /* Set the node to RAW_DATA */
344 
345     Next->Asl.Value.Integer = FieldFlags;
346     Next->Asl.AmlOpcode     = AML_RAW_DATA_BYTE;
347     Next->Asl.AmlLength     = 1;
348     Next->Asl.ParseOpcode   = PARSEOP_RAW_DATA;
349 
350     /* Process the FieldUnitList */
351 
352     Next = Next->Asl.Next;
353     CurrentBitOffset = 0;
354 
355     while (Next)
356     {
357         /* Save the offset of this field unit */
358 
359         Next->Asl.ExtraValue = CurrentBitOffset;
360 
361         switch (Next->Asl.ParseOpcode)
362         {
363         case PARSEOP_ACCESSAS:
364 
365             PkgLengthNode = Next->Asl.Child;
366             AccessType = (UINT8) PkgLengthNode->Asl.Value.Integer;
367 
368             /* Nothing additional to do */
369             break;
370 
371 
372         case PARSEOP_OFFSET:
373 
374             /* New offset into the field */
375 
376             PkgLengthNode = Next->Asl.Child;
377             NewBitOffset = ((UINT32) PkgLengthNode->Asl.Value.Integer) * 8;
378 
379             /*
380              * Examine the specified offset in relation to the
381              * current offset counter.
382              */
383             if (NewBitOffset < CurrentBitOffset)
384             {
385                 /*
386                  * Not allowed to specify a backwards offset!
387                  * Issue error and ignore this node.
388                  */
389                 AslError (ASL_ERROR, ASL_MSG_BACKWARDS_OFFSET, PkgLengthNode,
390                     NULL);
391                 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
392                 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
393             }
394             else if (NewBitOffset == CurrentBitOffset)
395             {
396                 /*
397                  * Offset is redundant; we don't need to output an
398                  * offset opcode.  Just set these nodes to default
399                  */
400                 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
401                 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
402             }
403             else
404             {
405                 /*
406                  * Valid new offset - set the value to be inserted into the AML
407                  * and update the offset counter.
408                  */
409                 PkgLengthNode->Asl.Value.Integer =
410                     NewBitOffset - CurrentBitOffset;
411                 CurrentBitOffset = NewBitOffset;
412             }
413             break;
414 
415 
416         case PARSEOP_NAMESEG:
417         case PARSEOP_RESERVED_BYTES:
418 
419             /* Named or reserved field entry */
420 
421             PkgLengthNode     = Next->Asl.Child;
422             NewBitOffset      = (UINT32) PkgLengthNode->Asl.Value.Integer;
423             CurrentBitOffset += NewBitOffset;
424 
425             /* Save the current AccessAs value for error checking later */
426 
427             switch (AccessType)
428             {
429                 case AML_FIELD_ACCESS_ANY:
430                 case AML_FIELD_ACCESS_BYTE:
431                 case AML_FIELD_ACCESS_BUFFER:
432                 default:
433                     MinimumLength = 8;
434                     break;
435 
436                 case AML_FIELD_ACCESS_WORD:
437                     MinimumLength = 16;
438                     break;
439 
440                 case AML_FIELD_ACCESS_DWORD:
441                     MinimumLength = 32;
442                     break;
443 
444                 case AML_FIELD_ACCESS_QWORD:
445                     MinimumLength = 64;
446                     break;
447             }
448 
449             PkgLengthNode->Asl.ExtraValue = MinimumLength;
450             break;
451 
452         default:
453             /* All supported field opcodes must appear above */
454             break;
455         }
456 
457         /* Move on to next entry in the field list */
458 
459         Next = Next->Asl.Next;
460     }
461 }
462 
463 
464 /*******************************************************************************
465  *
466  * FUNCTION:    OpnDoField
467  *
468  * PARAMETERS:  Op        - The parent parse node
469  *
470  * RETURN:      None
471  *
472  * DESCRIPTION: Construct the AML operands for the FIELD ASL keyword
473  *
474  ******************************************************************************/
475 
476 static void
477 OpnDoField (
478     ACPI_PARSE_OBJECT       *Op)
479 {
480     ACPI_PARSE_OBJECT       *Next;
481 
482 
483     /* Opcode is parent node */
484     /* First child is field name */
485 
486     Next = Op->Asl.Child;
487 
488     /* Second child is the AccessType */
489 
490     OpnDoFieldCommon (Op, Next->Asl.Next);
491 }
492 
493 
494 /*******************************************************************************
495  *
496  * FUNCTION:    OpnDoIndexField
497  *
498  * PARAMETERS:  Op        - The parent parse node
499  *
500  * RETURN:      None
501  *
502  * DESCRIPTION: Construct the AML operands for the INDEXFIELD ASL keyword
503  *
504  ******************************************************************************/
505 
506 static void
507 OpnDoIndexField (
508     ACPI_PARSE_OBJECT       *Op)
509 {
510     ACPI_PARSE_OBJECT       *Next;
511 
512 
513     /* Opcode is parent node */
514     /* First child is the index name */
515 
516     Next = Op->Asl.Child;
517 
518     /* Second child is the data name */
519 
520     Next = Next->Asl.Next;
521 
522     /* Third child is the AccessType */
523 
524     OpnDoFieldCommon (Op, Next->Asl.Next);
525 }
526 
527 
528 /*******************************************************************************
529  *
530  * FUNCTION:    OpnDoBankField
531  *
532  * PARAMETERS:  Op        - The parent parse node
533  *
534  * RETURN:      None
535  *
536  * DESCRIPTION: Construct the AML operands for the BANKFIELD ASL keyword
537  *
538  ******************************************************************************/
539 
540 static void
541 OpnDoBankField (
542     ACPI_PARSE_OBJECT       *Op)
543 {
544     ACPI_PARSE_OBJECT       *Next;
545 
546 
547     /* Opcode is parent node */
548     /* First child is the region name */
549 
550     Next = Op->Asl.Child;
551 
552     /* Second child is the bank name */
553 
554     Next = Next->Asl.Next;
555 
556     /* Third child is the bank value */
557 
558     Next = Next->Asl.Next;
559 
560     /* Fourth child is the AccessType */
561 
562     OpnDoFieldCommon (Op, Next->Asl.Next);
563 }
564 
565 
566 /*******************************************************************************
567  *
568  * FUNCTION:    OpnDoRegion
569  *
570  * PARAMETERS:  Op        - The parent parse node
571  *
572  * RETURN:      None
573  *
574  * DESCRIPTION: Tries to get the length of the region.  Can only do this at
575  *              compile time if the length is a constant.
576  *
577  ******************************************************************************/
578 
579 static void
580 OpnDoRegion (
581     ACPI_PARSE_OBJECT       *Op)
582 {
583     ACPI_PARSE_OBJECT       *Next;
584 
585 
586     /* Opcode is parent node */
587     /* First child is the region name */
588 
589     Next = Op->Asl.Child;
590 
591     /* Second child is the space ID*/
592 
593     Next = Next->Asl.Next;
594 
595     /* Third child is the region offset */
596 
597     Next = Next->Asl.Next;
598 
599     /* Fourth child is the region length */
600 
601     Next = Next->Asl.Next;
602     if (Next->Asl.ParseOpcode == PARSEOP_INTEGER)
603     {
604         Op->Asl.Value.Integer = Next->Asl.Value.Integer;
605     }
606     else
607     {
608         Op->Asl.Value.Integer = ACPI_INTEGER_MAX;
609     }
610 }
611 
612 
613 /*******************************************************************************
614  *
615  * FUNCTION:    OpnDoBuffer
616  *
617  * PARAMETERS:  Op        - The parent parse node
618  *
619  * RETURN:      None
620  *
621  * DESCRIPTION: Construct the AML operands for the BUFFER ASL keyword.  We
622  *              build a single raw byte buffer from the initialization nodes,
623  *              each parse node contains a buffer byte.
624  *
625  ******************************************************************************/
626 
627 static void
628 OpnDoBuffer (
629     ACPI_PARSE_OBJECT       *Op)
630 {
631     ACPI_PARSE_OBJECT       *InitializerOp;
632     ACPI_PARSE_OBJECT       *BufferLengthOp;
633 
634     /* Optional arguments for this opcode with defaults */
635 
636     UINT32                  BufferLength = 0;
637 
638 
639     /* Opcode and package length first */
640     /* Buffer Length is next, followed by the initializer list */
641 
642     BufferLengthOp = Op->Asl.Child;
643     InitializerOp = BufferLengthOp->Asl.Next;
644 
645     /*
646      * If the BufferLength is not an INTEGER or was not specified in the ASL
647      * (DEFAULT_ARG), it is a TermArg that is
648      * evaluated at run-time, and we are therefore finished.
649      */
650     if ((BufferLengthOp->Asl.ParseOpcode != PARSEOP_INTEGER) &&
651         (BufferLengthOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
652     {
653         return;
654     }
655 
656     /*
657      * We want to count the number of items in the initializer list, because if
658      * it is larger than the buffer length, we will define the buffer size
659      * to be the size of the initializer list (as per the ACPI Specification)
660      */
661     switch (InitializerOp->Asl.ParseOpcode)
662     {
663     case PARSEOP_INTEGER:
664     case PARSEOP_BYTECONST:
665     case PARSEOP_WORDCONST:
666     case PARSEOP_DWORDCONST:
667 
668         /* The peer list contains the byte list (if any...) */
669 
670         while (InitializerOp)
671         {
672             /* For buffers, this is a list of raw bytes */
673 
674             InitializerOp->Asl.AmlOpcode      = AML_RAW_DATA_BYTE;
675             InitializerOp->Asl.AmlLength      = 1;
676             InitializerOp->Asl.ParseOpcode    = PARSEOP_RAW_DATA;
677 
678             BufferLength++;
679             InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
680         }
681         break;
682 
683 
684     case PARSEOP_STRING_LITERAL:
685 
686         /*
687          * Only one initializer, the string.  Buffer must be big enough to hold
688          * the string plus the null termination byte
689          */
690         BufferLength = strlen (InitializerOp->Asl.Value.String) + 1;
691 
692         InitializerOp->Asl.AmlOpcode      = AML_RAW_DATA_BUFFER;
693         InitializerOp->Asl.AmlLength      = BufferLength;
694         InitializerOp->Asl.ParseOpcode    = PARSEOP_RAW_DATA;
695         break;
696 
697 
698     case PARSEOP_RAW_DATA:
699 
700         /* Buffer nodes are already initialized (e.g. Unicode operator) */
701         return;
702 
703 
704     case PARSEOP_DEFAULT_ARG:
705         break;
706 
707 
708     default:
709         AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, InitializerOp,
710             "Unknown buffer initializer opcode");
711         printf ("Unknown buffer initializer opcode [%s]\n",
712                         UtGetOpName (InitializerOp->Asl.ParseOpcode));
713         return;
714     }
715 
716     /* Check if initializer list is longer than the buffer length */
717 
718     if (BufferLengthOp->Asl.Value.Integer > BufferLength)
719     {
720         BufferLength = (UINT32) BufferLengthOp->Asl.Value.Integer;
721     }
722 
723     if (!BufferLength)
724     {
725         /* No length AND no items -- issue notice */
726 
727         AslError (ASL_REMARK, ASL_MSG_BUFFER_LENGTH, BufferLengthOp, NULL);
728 
729         /* But go ahead and put the buffer length of zero into the AML */
730     }
731 
732     /*
733      * Just set the buffer size node to be the buffer length, regardless
734      * of whether it was previously an integer or a default_arg placeholder
735      */
736     BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
737     BufferLengthOp->Asl.AmlOpcode     = AML_DWORD_OP;
738     BufferLengthOp->Asl.Value.Integer = BufferLength;
739 
740     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
741 
742     /* Remaining nodes are handled via the tree walk */
743 }
744 
745 
746 /*******************************************************************************
747  *
748  * FUNCTION:    OpnDoPackage
749  *
750  * PARAMETERS:  Op        - The parent parse node
751  *
752  * RETURN:      None
753  *
754  * DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword.  NOTE:
755  *              can only be called after constants have been folded, to ensure
756  *              that the PackageLength operand has been fully reduced.
757  *
758  ******************************************************************************/
759 
760 void
761 OpnDoPackage (
762     ACPI_PARSE_OBJECT       *Op)
763 {
764     ACPI_PARSE_OBJECT       *InitializerOp;
765     ACPI_PARSE_OBJECT       *PackageLengthOp;
766     UINT32                  PackageLength = 0;
767 
768 
769     /* Opcode and package length first, followed by the initializer list */
770 
771     PackageLengthOp = Op->Asl.Child;
772     InitializerOp = PackageLengthOp->Asl.Next;
773 
774     /* Count the number of items in the initializer list */
775 
776     if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
777     {
778         /* The peer list contains the byte list (if any...) */
779 
780         while (InitializerOp)
781         {
782             PackageLength++;
783             InitializerOp = InitializerOp->Asl.Next;
784         }
785     }
786 
787     /* If package length is a constant, compare to the initializer list */
788 
789     if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
790         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST))
791     {
792         if (PackageLengthOp->Asl.Value.Integer >= PackageLength)
793         {
794             /* Allow package to be longer than the initializer list */
795 
796             PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer;
797         }
798         else
799         {
800             /*
801              * Initializer list is longer than the package length. This
802              * is an error as per the ACPI spec.
803              */
804             AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH,
805                 PackageLengthOp->Asl.Next, NULL);
806         }
807     }
808 
809     if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
810     {
811         /*
812          * This is the case if the PackageLength was left empty - Package()
813          * The package length becomes the length of the initializer list
814          */
815         Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER;
816         Op->Asl.Child->Asl.Value.Integer = PackageLength;
817 
818         /* Set the AML opcode */
819 
820         (void) OpcSetOptimalIntegerSize (Op->Asl.Child);
821     }
822 
823     /* If not a variable-length package, check for a zero package length */
824 
825     if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
826         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST)   ||
827         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG))
828     {
829         if (!PackageLength)
830         {
831             /* No length AND no initializer list -- issue a remark */
832 
833             AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH,
834                 PackageLengthOp, NULL);
835 
836             /* But go ahead and put the buffer length of zero into the AML */
837         }
838     }
839 
840     /*
841      * If the PackageLength is a constant <= 255, we can change the
842      * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode.
843      */
844     if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
845         (Op->Asl.Child->Asl.Value.Integer <= 255))
846     {
847         Op->Asl.AmlOpcode = AML_PACKAGE_OP;
848         Op->Asl.ParseOpcode = PARSEOP_PACKAGE;
849 
850         /*
851          * Just set the package size node to be the package length, regardless
852          * of whether it was previously an integer or a default_arg placeholder
853          */
854         PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
855         PackageLengthOp->Asl.AmlLength = 1;
856         PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
857         PackageLengthOp->Asl.Value.Integer = PackageLength;
858     }
859 
860     /* Remaining nodes are handled via the tree walk */
861 }
862 
863 
864 /*******************************************************************************
865  *
866  * FUNCTION:    OpnDoLoadTable
867  *
868  * PARAMETERS:  Op        - The parent parse node
869  *
870  * RETURN:      None
871  *
872  * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword.
873  *
874  ******************************************************************************/
875 
876 static void
877 OpnDoLoadTable (
878     ACPI_PARSE_OBJECT       *Op)
879 {
880     ACPI_PARSE_OBJECT       *Next;
881 
882 
883     /* Opcode is parent node */
884     /* First child is the table signature */
885 
886     Next = Op->Asl.Child;
887 
888     /* Second child is the OEM ID*/
889 
890     Next = Next->Asl.Next;
891 
892     /* Third child is the OEM table ID */
893 
894     Next = Next->Asl.Next;
895 
896     /* Fourth child is the RootPath string */
897 
898     Next = Next->Asl.Next;
899     if (Next->Asl.ParseOpcode == PARSEOP_ZERO)
900     {
901         Next->Asl.ParseOpcode    = PARSEOP_STRING_LITERAL;
902         Next->Asl.Value.String   = "\\";
903         Next->Asl.AmlLength      = 2;
904         OpcGenerateAmlOpcode (Next);
905     }
906 
907 #ifdef ASL_FUTURE_IMPLEMENTATION
908 
909     /* TBD: NOT IMPLEMENTED */
910     /* Fifth child is the [optional] ParameterPathString */
911     /* Sixth child is the [optional] ParameterData */
912 
913     Next = Next->Asl.Next;
914     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
915     {
916         Next->Asl.AmlLength = 1;
917         Next->Asl.ParseOpcode = ZERO;
918         OpcGenerateAmlOpcode (Next);
919     }
920 
921 
922     Next = Next->Asl.Next;
923     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
924     {
925         Next->Asl.AmlLength = 1;
926         Next->Asl.ParseOpcode = ZERO;
927         OpcGenerateAmlOpcode (Next);
928     }
929 #endif
930 }
931 
932 
933 /*******************************************************************************
934  *
935  * FUNCTION:    OpnDoDefinitionBlock
936  *
937  * PARAMETERS:  Op        - The parent parse node
938  *
939  * RETURN:      None
940  *
941  * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword
942  *
943  ******************************************************************************/
944 
945 static void
946 OpnDoDefinitionBlock (
947     ACPI_PARSE_OBJECT       *Op)
948 {
949     ACPI_PARSE_OBJECT       *Child;
950     ACPI_SIZE               Length;
951     ACPI_NATIVE_UINT        i;
952 
953 
954     /*
955      * These nodes get stuffed into the table header.  They are special
956      * cased when the table is written to the output file.
957      *
958      * Mark all of these nodes as non-usable so they won't get output
959      * as AML opcodes!
960      */
961 
962     /* AML filename */
963 
964     Child = Op->Asl.Child;
965     if ((Child->Asl.Value.Buffer) && (Gbl_UseDefaultAmlFilename))
966     {
967         Gbl_OutputFilenamePrefix = (char *) Child->Asl.Value.Buffer;
968     }
969     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
970 
971     /* Signature */
972 
973     Child = Child->Asl.Next;
974     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
975     if (Child->Asl.Value.String)
976     {
977         Gbl_TableSignature = Child->Asl.Value.String;
978         if (ACPI_STRLEN (Gbl_TableSignature) != 4)
979         {
980             AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
981                 "Length not exactly 4");
982         }
983 
984         for (i = 0; i < 4; i++)
985         {
986             if (!isalnum (Gbl_TableSignature[i]))
987             {
988                 AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
989                     "Contains non-alphanumeric characters");
990             }
991         }
992     }
993 
994     /* Revision */
995 
996     Child = Child->Asl.Next;
997     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
998 
999     /* Use the revision to set the integer width */
1000 
1001     AcpiUtSetIntegerWidth ((UINT8) Child->Asl.Value.Integer);
1002 
1003     /* OEMID */
1004 
1005     Child = Child->Asl.Next;
1006     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1007 
1008     /* OEM TableID */
1009 
1010     Child = Child->Asl.Next;
1011     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1012     if (Child->Asl.Value.String)
1013     {
1014         Length = ACPI_STRLEN (Child->Asl.Value.String);
1015         Gbl_TableId = AcpiOsAllocate (Length + 1);
1016         ACPI_STRCPY (Gbl_TableId, Child->Asl.Value.String);
1017 
1018         for (i = 0; i < Length; i++)
1019         {
1020             if (Gbl_TableId[i] == ' ')
1021             {
1022                 Gbl_TableId[i] = 0;
1023                 break;
1024             }
1025         }
1026     }
1027 
1028     /* OEM Revision */
1029 
1030     Child = Child->Asl.Next;
1031     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1032 }
1033 
1034 
1035 /*******************************************************************************
1036  *
1037  * FUNCTION:    UtGetArg
1038  *
1039  * PARAMETERS:  Op              - Get an argument for this op
1040  *              Argn            - Nth argument to get
1041  *
1042  * RETURN:      The argument (as an Op object).  NULL if argument does not exist
1043  *
1044  * DESCRIPTION: Get the specified op's argument (peer)
1045  *
1046  ******************************************************************************/
1047 
1048 ACPI_PARSE_OBJECT *
1049 UtGetArg (
1050     ACPI_PARSE_OBJECT       *Op,
1051     UINT32                  Argn)
1052 {
1053     ACPI_PARSE_OBJECT       *Arg = NULL;
1054 
1055 
1056     /* Get the requested argument object */
1057 
1058     Arg = Op->Asl.Child;
1059     while (Arg && Argn)
1060     {
1061         Argn--;
1062         Arg = Arg->Asl.Next;
1063     }
1064 
1065     return (Arg);
1066 }
1067 
1068 
1069 /*******************************************************************************
1070  *
1071  * FUNCTION:    OpnAttachNameToNode
1072  *
1073  * PARAMETERS:  Op        - The parent parse node
1074  *
1075  * RETURN:      None
1076  *
1077  * DESCRIPTION: For the named ASL/AML operators, get the actual name from the
1078  *              argument list and attach it to the parent node so that we
1079  *              can get to it quickly later.
1080  *
1081  ******************************************************************************/
1082 
1083 static void
1084 OpnAttachNameToNode (
1085     ACPI_PARSE_OBJECT       *Op)
1086 {
1087     ACPI_PARSE_OBJECT       *Child = NULL;
1088 
1089 
1090     if (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)
1091     {
1092         Child = UtGetArg (Op, 0);
1093     }
1094     else switch (Op->Asl.AmlOpcode)
1095     {
1096     case AML_DATA_REGION_OP:
1097     case AML_DEVICE_OP:
1098     case AML_EVENT_OP:
1099     case AML_METHOD_OP:
1100     case AML_MUTEX_OP:
1101     case AML_REGION_OP:
1102     case AML_POWER_RES_OP:
1103     case AML_PROCESSOR_OP:
1104     case AML_THERMAL_ZONE_OP:
1105     case AML_NAME_OP:
1106     case AML_SCOPE_OP:
1107 
1108         Child = UtGetArg (Op, 0);
1109         break;
1110 
1111     case AML_ALIAS_OP:
1112 
1113         Child = UtGetArg (Op, 1);
1114         break;
1115 
1116     case AML_CREATE_BIT_FIELD_OP:
1117     case AML_CREATE_BYTE_FIELD_OP:
1118     case AML_CREATE_WORD_FIELD_OP:
1119     case AML_CREATE_DWORD_FIELD_OP:
1120     case AML_CREATE_QWORD_FIELD_OP:
1121 
1122         Child = UtGetArg (Op, 2);
1123         break;
1124 
1125     case AML_CREATE_FIELD_OP:
1126 
1127         Child = UtGetArg (Op, 3);
1128         break;
1129 
1130     case AML_BANK_FIELD_OP:
1131     case AML_INDEX_FIELD_OP:
1132     case AML_FIELD_OP:
1133 
1134         return;
1135 
1136     default:
1137         return;
1138     }
1139 
1140     if (Child)
1141     {
1142         UtAttachNamepathToOwner (Op, Child);
1143     }
1144 }
1145 
1146 
1147 /*******************************************************************************
1148  *
1149  * FUNCTION:    OpnGenerateAmlOperands
1150  *
1151  * PARAMETERS:  Op        - The parent parse node
1152  *
1153  * RETURN:      None
1154  *
1155  * DESCRIPTION: Prepare nodes to be output as AML data and operands.  The more
1156  *              complex AML opcodes require processing of the child nodes
1157  *              (arguments/operands).
1158  *
1159  ******************************************************************************/
1160 
1161 void
1162 OpnGenerateAmlOperands (
1163     ACPI_PARSE_OBJECT       *Op)
1164 {
1165 
1166 
1167     if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)
1168     {
1169         return;
1170     }
1171 
1172     switch (Op->Asl.ParseOpcode)
1173     {
1174     case PARSEOP_DEFINITIONBLOCK:
1175         OpnDoDefinitionBlock (Op);
1176         break;
1177 
1178     case PARSEOP_METHOD:
1179         OpnDoMethod (Op);
1180         break;
1181 
1182     case PARSEOP_MUTEX:
1183         OpnDoMutex (Op);
1184         break;
1185 
1186     case PARSEOP_FIELD:
1187         OpnDoField (Op);
1188         break;
1189 
1190     case PARSEOP_INDEXFIELD:
1191         OpnDoIndexField (Op);
1192         break;
1193 
1194     case PARSEOP_BANKFIELD:
1195         OpnDoBankField (Op);
1196         break;
1197 
1198     case PARSEOP_BUFFER:
1199         OpnDoBuffer (Op);
1200         break;
1201 
1202     case PARSEOP_LOADTABLE:
1203         OpnDoLoadTable (Op);
1204         break;
1205 
1206     case PARSEOP_OPERATIONREGION:
1207         OpnDoRegion (Op);
1208         break;
1209 
1210     case PARSEOP_RESOURCETEMPLATE:
1211         RsDoResourceTemplate (Op);
1212         break;
1213 
1214     case PARSEOP_NAMESEG:
1215     case PARSEOP_NAMESTRING:
1216     case PARSEOP_METHODCALL:
1217     case PARSEOP_STRING_LITERAL:
1218         break;
1219 
1220     default:
1221         break;
1222     }
1223 
1224     /* TBD: move */
1225 
1226     OpnAttachNameToNode (Op);
1227 }
1228 
1229 
1230