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