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