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