1 /******************************************************************************
2  *
3  * Module Name: aslresource - Resource template/descriptor utilities
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2014, 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 
45 #include "aslcompiler.h"
46 #include "aslcompiler.y.h"
47 #include "amlcode.h"
48 
49 
50 #define _COMPONENT          ACPI_COMPILER
51         ACPI_MODULE_NAME    ("aslresource")
52 
53 
54 /*******************************************************************************
55  *
56  * FUNCTION:    RsSmallAddressCheck
57  *
58  * PARAMETERS:  Minimum             - Address Min value
59  *              Maximum             - Address Max value
60  *              Length              - Address range value
61  *              Alignment           - Address alignment value
62  *              MinOp               - Original Op for Address Min
63  *              MaxOp               - Original Op for Address Max
64  *              LengthOp            - Original Op for address range
65  *              AlignOp             - Original Op for address alignment. If
66  *                                    NULL, means "zero value for alignment is
67  *                                    OK, and means 64K alignment" (for
68  *                                    Memory24 descriptor)
69  *              Op                  - Parent Op for entire construct
70  *
71  * RETURN:      None. Adds error messages to error log if necessary
72  *
73  * DESCRIPTION: Perform common value checks for "small" address descriptors.
74  *              Currently:
75  *                  Io, Memory24, Memory32
76  *
77  ******************************************************************************/
78 
79 void
80 RsSmallAddressCheck (
81     UINT8                   Type,
82     UINT32                  Minimum,
83     UINT32                  Maximum,
84     UINT32                  Length,
85     UINT32                  Alignment,
86     ACPI_PARSE_OBJECT       *MinOp,
87     ACPI_PARSE_OBJECT       *MaxOp,
88     ACPI_PARSE_OBJECT       *LengthOp,
89     ACPI_PARSE_OBJECT       *AlignOp,
90     ACPI_PARSE_OBJECT       *Op)
91 {
92 
93     if (Gbl_NoResourceChecking)
94     {
95         return;
96     }
97 
98     /*
99      * Check for a so-called "null descriptor". These are descriptors that are
100      * created with most fields set to zero. The intent is that the descriptor
101      * will be updated/completed at runtime via a BufferField.
102      *
103      * If the descriptor does NOT have a resource tag, it cannot be referenced
104      * by a BufferField and we will flag this as an error. Conversely, if
105      * the descriptor has a resource tag, we will assume that a BufferField
106      * will be used to dynamically update it, so no error.
107      *
108      * A possible enhancement to this check would be to verify that in fact
109      * a BufferField is created using the resource tag, and perhaps even
110      * verify that a Store is performed to the BufferField.
111      *
112      * Note: for these descriptors, Alignment is allowed to be zero
113      */
114     if (!Minimum && !Maximum && !Length)
115     {
116         if (!Op->Asl.ExternalName)
117         {
118             /* No resource tag. Descriptor is fixed and is also illegal */
119 
120             AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL);
121         }
122 
123         return;
124     }
125 
126     /* Special case for Memory24, values are compressed */
127 
128     if (Type == ACPI_RESOURCE_NAME_MEMORY24)
129     {
130         if (!Alignment) /* Alignment==0 means 64K - no invalid alignment */
131         {
132             Alignment = ACPI_UINT16_MAX + 1;
133         }
134 
135         Minimum <<= 8;
136         Maximum <<= 8;
137         Length *= 256;
138     }
139 
140     /* IO descriptor has different definition of min/max, don't check */
141 
142     if (Type != ACPI_RESOURCE_NAME_IO)
143     {
144         /* Basic checks on Min/Max/Length */
145 
146         if (Minimum > Maximum)
147         {
148             AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL);
149         }
150         else if (Length > (Maximum - Minimum + 1))
151         {
152             AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL);
153         }
154     }
155 
156     /* Alignment of zero is not in ACPI spec, but is used to mean byte acc */
157 
158     if (!Alignment)
159     {
160         Alignment = 1;
161     }
162 
163     /* Addresses must be an exact multiple of the alignment value */
164 
165     if (Minimum % Alignment)
166     {
167         AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL);
168     }
169     if (Maximum % Alignment)
170     {
171         AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, NULL);
172     }
173 }
174 
175 
176 /*******************************************************************************
177  *
178  * FUNCTION:    RsLargeAddressCheck
179  *
180  * PARAMETERS:  Minimum             - Address Min value
181  *              Maximum             - Address Max value
182  *              Length              - Address range value
183  *              Granularity         - Address granularity value
184  *              Flags               - General flags for address descriptors:
185  *                                    _MIF, _MAF, _DEC
186  *              MinOp               - Original Op for Address Min
187  *              MaxOp               - Original Op for Address Max
188  *              LengthOp            - Original Op for address range
189  *              GranOp              - Original Op for address granularity
190  *              Op                  - Parent Op for entire construct
191  *
192  * RETURN:      None. Adds error messages to error log if necessary
193  *
194  * DESCRIPTION: Perform common value checks for "large" address descriptors.
195  *              Currently:
196  *                  WordIo,     WordBusNumber,  WordSpace
197  *                  DWordIo,    DWordMemory,    DWordSpace
198  *                  QWordIo,    QWordMemory,    QWordSpace
199  *                  ExtendedIo, ExtendedMemory, ExtendedSpace
200  *
201  * _MIF flag set means that the minimum address is fixed and is not relocatable
202  * _MAF flag set means that the maximum address is fixed and is not relocatable
203  * Length of zero means that the record size is variable
204  *
205  * This function implements the LEN/MIF/MAF/MIN/MAX/GRA rules within Table 6-40
206  * of the ACPI 4.0a specification. Added 04/2010.
207  *
208  ******************************************************************************/
209 
210 void
211 RsLargeAddressCheck (
212     UINT64                  Minimum,
213     UINT64                  Maximum,
214     UINT64                  Length,
215     UINT64                  Granularity,
216     UINT8                   Flags,
217     ACPI_PARSE_OBJECT       *MinOp,
218     ACPI_PARSE_OBJECT       *MaxOp,
219     ACPI_PARSE_OBJECT       *LengthOp,
220     ACPI_PARSE_OBJECT       *GranOp,
221     ACPI_PARSE_OBJECT       *Op)
222 {
223 
224     if (Gbl_NoResourceChecking)
225     {
226         return;
227     }
228 
229     /*
230      * Check for a so-called "null descriptor". These are descriptors that are
231      * created with most fields set to zero. The intent is that the descriptor
232      * will be updated/completed at runtime via a BufferField.
233      *
234      * If the descriptor does NOT have a resource tag, it cannot be referenced
235      * by a BufferField and we will flag this as an error. Conversely, if
236      * the descriptor has a resource tag, we will assume that a BufferField
237      * will be used to dynamically update it, so no error.
238      *
239      * A possible enhancement to this check would be to verify that in fact
240      * a BufferField is created using the resource tag, and perhaps even
241      * verify that a Store is performed to the BufferField.
242      */
243     if (!Minimum && !Maximum && !Length && !Granularity)
244     {
245         if (!Op->Asl.ExternalName)
246         {
247             /* No resource tag. Descriptor is fixed and is also illegal */
248 
249             AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL);
250         }
251 
252         return;
253     }
254 
255     /* Basic checks on Min/Max/Length */
256 
257     if (Minimum > Maximum)
258     {
259         AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL);
260         return;
261     }
262     else if (Length > (Maximum - Minimum + 1))
263     {
264         AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL);
265         return;
266     }
267 
268     /* If specified (non-zero), ensure granularity is a power-of-two minus one */
269 
270     if (Granularity)
271     {
272         if ((Granularity + 1) &
273              Granularity)
274         {
275             AslError (ASL_ERROR, ASL_MSG_INVALID_GRANULARITY, GranOp, NULL);
276             return;
277         }
278     }
279 
280     /*
281      * Check the various combinations of Length, MinFixed, and MaxFixed
282      */
283     if (Length)
284     {
285         /* Fixed non-zero length */
286 
287         switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF))
288         {
289         case 0:
290             /*
291              * Fixed length, variable locations (both _MIN and _MAX).
292              * Length must be a multiple of granularity
293              */
294             if (Granularity & Length)
295             {
296                 AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, LengthOp, NULL);
297             }
298             break;
299 
300         case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF):
301 
302             /* Fixed length, fixed location. Granularity must be zero */
303 
304             if (Granularity != 0)
305             {
306                 AslError (ASL_ERROR, ASL_MSG_INVALID_GRAN_FIXED, GranOp, NULL);
307             }
308 
309             /* Length must be exactly the size of the min/max window */
310 
311             if (Length != (Maximum - Minimum + 1))
312             {
313                 AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH_FIXED, LengthOp, NULL);
314             }
315             break;
316 
317         /* All other combinations are invalid */
318 
319         case ACPI_RESOURCE_FLAG_MIF:
320         case ACPI_RESOURCE_FLAG_MAF:
321         default:
322 
323             AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL);
324         }
325     }
326     else
327     {
328         /* Variable length (length==0) */
329 
330         switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF))
331         {
332         case 0:
333             /*
334              * Both _MIN and _MAX are variable.
335              * No additional requirements, just exit
336              */
337             break;
338 
339         case ACPI_RESOURCE_FLAG_MIF:
340 
341             /* _MIN is fixed. _MIN must be multiple of _GRA */
342 
343             /*
344              * The granularity is defined by the ACPI specification to be a
345              * power-of-two minus one, therefore the granularity is a
346              * bitmask which can be used to easily validate the addresses.
347              */
348             if (Granularity & Minimum)
349             {
350                 AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL);
351             }
352             break;
353 
354         case ACPI_RESOURCE_FLAG_MAF:
355 
356             /* _MAX is fixed. (_MAX + 1) must be multiple of _GRA */
357 
358             if (Granularity & (Maximum + 1))
359             {
360                 AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, "-1");
361             }
362             break;
363 
364         /* Both MIF/MAF set is invalid if length is zero */
365 
366         case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF):
367         default:
368 
369             AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL);
370         }
371     }
372 }
373 
374 
375 /*******************************************************************************
376  *
377  * FUNCTION:    RsGetStringDataLength
378  *
379  * PARAMETERS:  InitializerOp     - Start of a subtree of init nodes
380  *
381  * RETURN:      Valid string length if a string node is found (otherwise 0)
382  *
383  * DESCRIPTION: In a list of peer nodes, find the first one that contains a
384  *              string and return the length of the string.
385  *
386  ******************************************************************************/
387 
388 UINT16
389 RsGetStringDataLength (
390     ACPI_PARSE_OBJECT       *InitializerOp)
391 {
392 
393     while (InitializerOp)
394     {
395         if (InitializerOp->Asl.ParseOpcode == PARSEOP_STRING_LITERAL)
396         {
397             return ((UINT16) (strlen (InitializerOp->Asl.Value.String) + 1));
398         }
399         InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
400     }
401 
402     return (0);
403 }
404 
405 
406 /*******************************************************************************
407  *
408  * FUNCTION:    RsAllocateResourceNode
409  *
410  * PARAMETERS:  Size        - Size of node in bytes
411  *
412  * RETURN:      The allocated node - aborts on allocation failure
413  *
414  * DESCRIPTION: Allocate a resource description node and the resource
415  *              descriptor itself (the nodes are used to link descriptors).
416  *
417  ******************************************************************************/
418 
419 ASL_RESOURCE_NODE *
420 RsAllocateResourceNode (
421     UINT32                  Size)
422 {
423     ASL_RESOURCE_NODE       *Rnode;
424 
425 
426     /* Allocate the node */
427 
428     Rnode = UtLocalCalloc (sizeof (ASL_RESOURCE_NODE));
429 
430     /* Allocate the resource descriptor itself */
431 
432     Rnode->Buffer = UtLocalCalloc (Size);
433     Rnode->BufferLength = Size;
434 
435     return (Rnode);
436 }
437 
438 
439 /*******************************************************************************
440  *
441  * FUNCTION:    RsCreateResourceField
442  *
443  * PARAMETERS:  Op              - Resource field node
444  *              Name            - Name of the field (Used only to reference
445  *                                the field in the ASL, not in the AML)
446  *              ByteOffset      - Offset from the field start
447  *              BitOffset       - Additional bit offset
448  *              BitLength       - Number of bits in the field
449  *
450  * RETURN:      None, sets fields within the input node
451  *
452  * DESCRIPTION: Utility function to generate a named bit field within a
453  *              resource descriptor. Mark a node as 1) a field in a resource
454  *              descriptor, and 2) set the value to be a BIT offset
455  *
456  ******************************************************************************/
457 
458 void
459 RsCreateResourceField (
460     ACPI_PARSE_OBJECT       *Op,
461     char                    *Name,
462     UINT32                  ByteOffset,
463     UINT32                  BitOffset,
464     UINT32                  BitLength)
465 {
466 
467     Op->Asl.ExternalName = Name;
468     Op->Asl.CompileFlags |= NODE_IS_RESOURCE_FIELD;
469 
470 
471     Op->Asl.Value.Tag.BitOffset = (ByteOffset * 8) + BitOffset;
472     Op->Asl.Value.Tag.BitLength = BitLength;
473 }
474 
475 
476 /*******************************************************************************
477  *
478  * FUNCTION:    RsSetFlagBits
479  *
480  * PARAMETERS:  *Flags          - Pointer to the flag byte
481  *              Op              - Flag initialization node
482  *              Position        - Bit position within the flag byte
483  *              Default         - Used if the node is DEFAULT.
484  *
485  * RETURN:      Sets bits within the *Flags output byte.
486  *
487  * DESCRIPTION: Set a bit in a cumulative flags word from an initialization
488  *              node. Will use a default value if the node is DEFAULT, meaning
489  *              that no value was specified in the ASL. Used to merge multiple
490  *              keywords into a single flags byte.
491  *
492  ******************************************************************************/
493 
494 void
495 RsSetFlagBits (
496     UINT8                   *Flags,
497     ACPI_PARSE_OBJECT       *Op,
498     UINT8                   Position,
499     UINT8                   DefaultBit)
500 {
501 
502     if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
503     {
504         /* Use the default bit */
505 
506         *Flags |= (DefaultBit << Position);
507     }
508     else
509     {
510         /* Use the bit specified in the initialization node */
511 
512         *Flags |= (((UINT8) Op->Asl.Value.Integer) << Position);
513     }
514 }
515 
516 
517 void
518 RsSetFlagBits16 (
519     UINT16                  *Flags,
520     ACPI_PARSE_OBJECT       *Op,
521     UINT8                   Position,
522     UINT8                   DefaultBit)
523 {
524 
525     if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
526     {
527         /* Use the default bit */
528 
529         *Flags |= (DefaultBit << Position);
530     }
531     else
532     {
533         /* Use the bit specified in the initialization node */
534 
535         *Flags |= (((UINT16) Op->Asl.Value.Integer) << Position);
536     }
537 }
538 
539 
540 /*******************************************************************************
541  *
542  * FUNCTION:    RsCompleteNodeAndGetNext
543  *
544  * PARAMETERS:  Op            - Resource node to be completed
545  *
546  * RETURN:      The next peer to the input node.
547  *
548  * DESCRIPTION: Mark the current node completed and return the next peer.
549  *              The node ParseOpcode is set to DEFAULT_ARG, meaning that
550  *              this node is to be ignored from now on.
551  *
552  ******************************************************************************/
553 
554 ACPI_PARSE_OBJECT *
555 RsCompleteNodeAndGetNext (
556     ACPI_PARSE_OBJECT       *Op)
557 {
558 
559     /* Mark this node unused */
560 
561     Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
562 
563     /* Move on to the next peer node in the initializer list */
564 
565     return (ASL_GET_PEER_NODE (Op));
566 }
567 
568 
569 /*******************************************************************************
570  *
571  * FUNCTION:    RsCheckListForDuplicates
572  *
573  * PARAMETERS:  Op                  - First op in the initializer list
574  *
575  * RETURN:      None
576  *
577  * DESCRIPTION: Check an initializer list for duplicate values. Emits an error
578  *              if any duplicates are found.
579  *
580  ******************************************************************************/
581 
582 void
583 RsCheckListForDuplicates (
584     ACPI_PARSE_OBJECT       *Op)
585 {
586     ACPI_PARSE_OBJECT       *NextValueOp = Op;
587     ACPI_PARSE_OBJECT       *NextOp;
588     UINT32                  Value;
589 
590 
591     if (!Op)
592     {
593         return;
594     }
595 
596     /* Search list once for each value in the list */
597 
598     while (NextValueOp)
599     {
600         Value = (UINT32) NextValueOp->Asl.Value.Integer;
601 
602         /* Compare this value to all remaining values in the list */
603 
604         NextOp = ASL_GET_PEER_NODE (NextValueOp);
605         while (NextOp)
606         {
607             if (NextOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
608             {
609                 /* Compare values */
610 
611                 if (Value == (UINT32) NextOp->Asl.Value.Integer)
612                 {
613                     /* Emit error only once per duplicate node */
614 
615                     if (!(NextOp->Asl.CompileFlags & NODE_IS_DUPLICATE))
616                     {
617                         NextOp->Asl.CompileFlags |= NODE_IS_DUPLICATE;
618                         AslError (ASL_ERROR, ASL_MSG_DUPLICATE_ITEM,
619                             NextOp, NULL);
620                     }
621                 }
622             }
623 
624             NextOp = ASL_GET_PEER_NODE (NextOp);
625         }
626 
627         NextValueOp = ASL_GET_PEER_NODE (NextValueOp);
628     }
629 }
630 
631 
632 /*******************************************************************************
633  *
634  * FUNCTION:    RsDoOneResourceDescriptor
635  *
636  * PARAMETERS:  DescriptorTypeOp    - Parent parse node of the descriptor
637  *              CurrentByteOffset   - Offset in the resource descriptor
638  *                                    buffer.
639  *
640  * RETURN:      A valid resource node for the descriptor
641  *
642  * DESCRIPTION: Dispatches the processing of one resource descriptor
643  *
644  ******************************************************************************/
645 
646 ASL_RESOURCE_NODE *
647 RsDoOneResourceDescriptor (
648     ACPI_PARSE_OBJECT       *DescriptorTypeOp,
649     UINT32                  CurrentByteOffset,
650     UINT8                   *State)
651 {
652     ASL_RESOURCE_NODE       *Rnode = NULL;
653 
654 
655     /* Construct the resource */
656 
657     switch (DescriptorTypeOp->Asl.ParseOpcode)
658     {
659     case PARSEOP_DMA:
660 
661         Rnode = RsDoDmaDescriptor (DescriptorTypeOp,
662                     CurrentByteOffset);
663         break;
664 
665     case PARSEOP_FIXEDDMA:
666 
667         Rnode = RsDoFixedDmaDescriptor (DescriptorTypeOp,
668                     CurrentByteOffset);
669         break;
670 
671     case PARSEOP_DWORDIO:
672 
673         Rnode = RsDoDwordIoDescriptor (DescriptorTypeOp,
674                     CurrentByteOffset);
675         break;
676 
677     case PARSEOP_DWORDMEMORY:
678 
679         Rnode = RsDoDwordMemoryDescriptor (DescriptorTypeOp,
680                     CurrentByteOffset);
681         break;
682 
683     case PARSEOP_DWORDSPACE:
684 
685         Rnode = RsDoDwordSpaceDescriptor (DescriptorTypeOp,
686                     CurrentByteOffset);
687         break;
688 
689     case PARSEOP_ENDDEPENDENTFN:
690 
691         switch (*State)
692         {
693         case ACPI_RSTATE_NORMAL:
694 
695             AslError (ASL_ERROR, ASL_MSG_MISSING_STARTDEPENDENT,
696                 DescriptorTypeOp, NULL);
697             break;
698 
699         case ACPI_RSTATE_START_DEPENDENT:
700 
701             AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
702                 DescriptorTypeOp, NULL);
703             break;
704 
705         case ACPI_RSTATE_DEPENDENT_LIST:
706         default:
707 
708             break;
709         }
710 
711         *State = ACPI_RSTATE_NORMAL;
712         Rnode = RsDoEndDependentDescriptor (DescriptorTypeOp,
713                     CurrentByteOffset);
714         break;
715 
716     case PARSEOP_ENDTAG:
717 
718         Rnode = RsDoEndTagDescriptor (DescriptorTypeOp,
719                     CurrentByteOffset);
720         break;
721 
722     case PARSEOP_EXTENDEDIO:
723 
724         Rnode = RsDoExtendedIoDescriptor (DescriptorTypeOp,
725                     CurrentByteOffset);
726         break;
727 
728     case PARSEOP_EXTENDEDMEMORY:
729 
730         Rnode = RsDoExtendedMemoryDescriptor (DescriptorTypeOp,
731                     CurrentByteOffset);
732         break;
733 
734     case PARSEOP_EXTENDEDSPACE:
735 
736         Rnode = RsDoExtendedSpaceDescriptor (DescriptorTypeOp,
737                     CurrentByteOffset);
738         break;
739 
740     case PARSEOP_FIXEDIO:
741 
742         Rnode = RsDoFixedIoDescriptor (DescriptorTypeOp,
743                     CurrentByteOffset);
744         break;
745 
746     case PARSEOP_INTERRUPT:
747 
748         Rnode = RsDoInterruptDescriptor (DescriptorTypeOp,
749                     CurrentByteOffset);
750         break;
751 
752     case PARSEOP_IO:
753 
754         Rnode = RsDoIoDescriptor (DescriptorTypeOp,
755                     CurrentByteOffset);
756         break;
757 
758     case PARSEOP_IRQ:
759 
760         Rnode = RsDoIrqDescriptor (DescriptorTypeOp,
761                     CurrentByteOffset);
762         break;
763 
764     case PARSEOP_IRQNOFLAGS:
765 
766         Rnode = RsDoIrqNoFlagsDescriptor (DescriptorTypeOp,
767                     CurrentByteOffset);
768         break;
769 
770     case PARSEOP_MEMORY24:
771 
772         Rnode = RsDoMemory24Descriptor (DescriptorTypeOp,
773                     CurrentByteOffset);
774         break;
775 
776     case PARSEOP_MEMORY32:
777 
778         Rnode = RsDoMemory32Descriptor (DescriptorTypeOp,
779                     CurrentByteOffset);
780         break;
781 
782     case PARSEOP_MEMORY32FIXED:
783 
784         Rnode = RsDoMemory32FixedDescriptor (DescriptorTypeOp,
785                     CurrentByteOffset);
786         break;
787 
788     case PARSEOP_QWORDIO:
789 
790         Rnode = RsDoQwordIoDescriptor (DescriptorTypeOp,
791                     CurrentByteOffset);
792         break;
793 
794     case PARSEOP_QWORDMEMORY:
795 
796         Rnode = RsDoQwordMemoryDescriptor (DescriptorTypeOp,
797                     CurrentByteOffset);
798         break;
799 
800     case PARSEOP_QWORDSPACE:
801 
802         Rnode = RsDoQwordSpaceDescriptor (DescriptorTypeOp,
803                     CurrentByteOffset);
804         break;
805 
806     case PARSEOP_REGISTER:
807 
808         Rnode = RsDoGeneralRegisterDescriptor (DescriptorTypeOp,
809                     CurrentByteOffset);
810         break;
811 
812     case PARSEOP_STARTDEPENDENTFN:
813 
814         switch (*State)
815         {
816         case ACPI_RSTATE_START_DEPENDENT:
817 
818             AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
819                 DescriptorTypeOp, NULL);
820             break;
821 
822         case ACPI_RSTATE_NORMAL:
823         case ACPI_RSTATE_DEPENDENT_LIST:
824         default:
825 
826             break;
827         }
828 
829         *State = ACPI_RSTATE_START_DEPENDENT;
830         Rnode = RsDoStartDependentDescriptor (DescriptorTypeOp,
831                     CurrentByteOffset);
832         *State = ACPI_RSTATE_DEPENDENT_LIST;
833         break;
834 
835     case PARSEOP_STARTDEPENDENTFN_NOPRI:
836 
837         switch (*State)
838         {
839         case ACPI_RSTATE_START_DEPENDENT:
840 
841             AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
842                 DescriptorTypeOp, NULL);
843             break;
844 
845         case ACPI_RSTATE_NORMAL:
846         case ACPI_RSTATE_DEPENDENT_LIST:
847         default:
848 
849             break;
850         }
851 
852         *State = ACPI_RSTATE_START_DEPENDENT;
853         Rnode = RsDoStartDependentNoPriDescriptor (DescriptorTypeOp,
854                     CurrentByteOffset);
855         *State = ACPI_RSTATE_DEPENDENT_LIST;
856         break;
857 
858     case PARSEOP_VENDORLONG:
859 
860         Rnode = RsDoVendorLargeDescriptor (DescriptorTypeOp,
861                     CurrentByteOffset);
862         break;
863 
864     case PARSEOP_VENDORSHORT:
865 
866         Rnode = RsDoVendorSmallDescriptor (DescriptorTypeOp,
867                     CurrentByteOffset);
868         break;
869 
870     case PARSEOP_WORDBUSNUMBER:
871 
872         Rnode = RsDoWordBusNumberDescriptor (DescriptorTypeOp,
873                     CurrentByteOffset);
874         break;
875 
876     case PARSEOP_WORDIO:
877 
878         Rnode = RsDoWordIoDescriptor (DescriptorTypeOp,
879                     CurrentByteOffset);
880         break;
881 
882     case PARSEOP_WORDSPACE:
883 
884         Rnode = RsDoWordSpaceDescriptor (DescriptorTypeOp,
885                     CurrentByteOffset);
886         break;
887 
888     case PARSEOP_GPIO_INT:
889 
890         Rnode = RsDoGpioIntDescriptor (DescriptorTypeOp,
891                     CurrentByteOffset);
892         break;
893 
894     case PARSEOP_GPIO_IO:
895 
896         Rnode = RsDoGpioIoDescriptor (DescriptorTypeOp,
897                     CurrentByteOffset);
898         break;
899 
900     case PARSEOP_I2C_SERIALBUS:
901 
902         Rnode = RsDoI2cSerialBusDescriptor (DescriptorTypeOp,
903                     CurrentByteOffset);
904         break;
905 
906     case PARSEOP_SPI_SERIALBUS:
907 
908         Rnode = RsDoSpiSerialBusDescriptor (DescriptorTypeOp,
909                     CurrentByteOffset);
910         break;
911 
912     case PARSEOP_UART_SERIALBUS:
913 
914         Rnode = RsDoUartSerialBusDescriptor (DescriptorTypeOp,
915                     CurrentByteOffset);
916         break;
917 
918     case PARSEOP_DEFAULT_ARG:
919 
920         /* Just ignore any of these, they are used as fillers/placeholders */
921         break;
922 
923     default:
924 
925         printf ("Unknown resource descriptor type [%s]\n",
926                     DescriptorTypeOp->Asl.ParseOpName);
927         break;
928     }
929 
930     /*
931      * Mark original node as unused, but head of a resource descriptor.
932      * This allows the resource to be installed in the namespace so that
933      * references to the descriptor can be resolved.
934      */
935     DescriptorTypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
936     DescriptorTypeOp->Asl.CompileFlags = NODE_IS_RESOURCE_DESC;
937     DescriptorTypeOp->Asl.Value.Integer = CurrentByteOffset;
938 
939     if (Rnode)
940     {
941         DescriptorTypeOp->Asl.FinalAmlLength = Rnode->BufferLength;
942         DescriptorTypeOp->Asl.Extra = ((AML_RESOURCE *) Rnode->Buffer)->DescriptorType;
943     }
944 
945     return (Rnode);
946 }
947 
948 
949 /*******************************************************************************
950  *
951  * FUNCTION:    RsLinkDescriptorChain
952  *
953  * PARAMETERS:  PreviousRnode       - Pointer to the node that will be previous
954  *                                    to the linked node,  At exit, set to the
955  *                                    last node in the new chain.
956  *              Rnode               - Resource node to link into the list
957  *
958  * RETURN:      Cumulative buffer byte offset of the new segment of chain
959  *
960  * DESCRIPTION: Link a descriptor chain at the end of an existing chain.
961  *
962  ******************************************************************************/
963 
964 UINT32
965 RsLinkDescriptorChain (
966     ASL_RESOURCE_NODE       **PreviousRnode,
967     ASL_RESOURCE_NODE       *Rnode)
968 {
969     ASL_RESOURCE_NODE       *LastRnode;
970     UINT32                  CurrentByteOffset;
971 
972 
973     /* Anything to do? */
974 
975     if (!Rnode)
976     {
977         return (0);
978     }
979 
980     /* Point the previous node to the new node */
981 
982     (*PreviousRnode)->Next = Rnode;
983     CurrentByteOffset = Rnode->BufferLength;
984 
985     /* Walk to the end of the chain headed by Rnode */
986 
987     LastRnode = Rnode;
988     while (LastRnode->Next)
989     {
990         LastRnode = LastRnode->Next;
991         CurrentByteOffset += LastRnode->BufferLength;
992     }
993 
994     /* Previous node becomes the last node in the chain */
995 
996     *PreviousRnode = LastRnode;
997     return (CurrentByteOffset);
998 }
999 
1000 
1001 /*******************************************************************************
1002  *
1003  * FUNCTION:    RsDoResourceTemplate
1004  *
1005  * PARAMETERS:  Op        - Parent of a resource template list
1006  *
1007  * RETURN:      None. Sets input node to point to a list of AML code
1008  *
1009  * DESCRIPTION: Merge a list of resource descriptors into a single AML buffer,
1010  *              in preparation for output to the AML output file.
1011  *
1012  ******************************************************************************/
1013 
1014 void
1015 RsDoResourceTemplate (
1016     ACPI_PARSE_OBJECT       *Op)
1017 {
1018     ACPI_PARSE_OBJECT       *BufferLengthOp;
1019     ACPI_PARSE_OBJECT       *BufferOp;
1020     ACPI_PARSE_OBJECT       *DescriptorTypeOp;
1021     ACPI_PARSE_OBJECT       *LastOp = NULL;
1022     UINT32                  CurrentByteOffset = 0;
1023     ASL_RESOURCE_NODE       HeadRnode;
1024     ASL_RESOURCE_NODE       *PreviousRnode;
1025     ASL_RESOURCE_NODE       *Rnode;
1026     UINT8                   State;
1027 
1028 
1029     /* Mark parent as containing a resource template */
1030 
1031     if (Op->Asl.Parent)
1032     {
1033         Op->Asl.Parent->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
1034     }
1035 
1036     /* ResourceTemplate Opcode is first (Op) */
1037     /* Buffer Length node is first child */
1038 
1039     BufferLengthOp = ASL_GET_CHILD_NODE (Op);
1040 
1041     /* Buffer Op is first peer */
1042 
1043     BufferOp = ASL_GET_PEER_NODE (BufferLengthOp);
1044 
1045     /* First Descriptor type is next */
1046 
1047     DescriptorTypeOp = ASL_GET_PEER_NODE (BufferOp);
1048 
1049     /*
1050      * Process all resource descriptors in the list
1051      * Note: It is assumed that the EndTag node has been automatically
1052      * inserted at the end of the template by the parser.
1053      */
1054     State = ACPI_RSTATE_NORMAL;
1055     PreviousRnode = &HeadRnode;
1056     while (DescriptorTypeOp)
1057     {
1058         DescriptorTypeOp->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
1059         Rnode = RsDoOneResourceDescriptor (DescriptorTypeOp, CurrentByteOffset,
1060                     &State);
1061 
1062         /*
1063          * Update current byte offset to indicate the number of bytes from the
1064          * start of the buffer. Buffer can include multiple descriptors, we
1065          * must keep track of the offset of not only each descriptor, but each
1066          * element (field) within each descriptor as well.
1067          */
1068         CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, Rnode);
1069 
1070         /* Get the next descriptor in the list */
1071 
1072         LastOp = DescriptorTypeOp;
1073         DescriptorTypeOp = ASL_GET_PEER_NODE (DescriptorTypeOp);
1074     }
1075 
1076     if (State == ACPI_RSTATE_DEPENDENT_LIST)
1077     {
1078         if (LastOp)
1079         {
1080             LastOp = LastOp->Asl.Parent;
1081         }
1082         AslError (ASL_ERROR, ASL_MSG_MISSING_ENDDEPENDENT, LastOp, NULL);
1083     }
1084 
1085     /*
1086      * Transform the nodes into the following
1087      *
1088      * Op           -> AML_BUFFER_OP
1089      * First Child  -> BufferLength
1090      * Second Child -> Descriptor Buffer (raw byte data)
1091      */
1092     Op->Asl.ParseOpcode               = PARSEOP_BUFFER;
1093     Op->Asl.AmlOpcode                 = AML_BUFFER_OP;
1094     Op->Asl.CompileFlags              = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC;
1095     UtSetParseOpName (Op);
1096 
1097     BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
1098     BufferLengthOp->Asl.Value.Integer = CurrentByteOffset;
1099     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
1100     UtSetParseOpName (BufferLengthOp);
1101 
1102     BufferOp->Asl.ParseOpcode         = PARSEOP_RAW_DATA;
1103     BufferOp->Asl.AmlOpcode           = AML_RAW_DATA_CHAIN;
1104     BufferOp->Asl.AmlOpcodeLength     = 0;
1105     BufferOp->Asl.AmlLength           = CurrentByteOffset;
1106     BufferOp->Asl.Value.Buffer        = (UINT8 *) HeadRnode.Next;
1107     BufferOp->Asl.CompileFlags       |= NODE_IS_RESOURCE_DATA;
1108     UtSetParseOpName (BufferOp);
1109 
1110     return;
1111 }
1112