xref: /freebsd/sys/contrib/dev/acpica/compiler/aslresource.c (revision 48c5129f93c5eb5419c87b08e4677d51513f1dc0)
1 /******************************************************************************
2  *
3  * Module Name: aslresource - Resource template/descriptor utilities
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2012, 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 <contrib/dev/acpica/compiler/aslcompiler.h>
46 #include "aslcompiler.y.h"
47 #include <contrib/dev/acpica/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             AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL);
323         }
324     }
325     else
326     {
327         /* Variable length (length==0) */
328 
329         switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF))
330         {
331         case 0:
332             /*
333              * Both _MIN and _MAX are variable.
334              * No additional requirements, just exit
335              */
336             break;
337 
338         case ACPI_RESOURCE_FLAG_MIF:
339 
340             /* _MIN is fixed. _MIN must be multiple of _GRA */
341 
342             /*
343              * The granularity is defined by the ACPI specification to be a
344              * power-of-two minus one, therefore the granularity is a
345              * bitmask which can be used to easily validate the addresses.
346              */
347             if (Granularity & Minimum)
348             {
349                 AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL);
350             }
351             break;
352 
353         case ACPI_RESOURCE_FLAG_MAF:
354 
355             /* _MAX is fixed. (_MAX + 1) must be multiple of _GRA */
356 
357             if (Granularity & (Maximum + 1))
358             {
359                 AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, "-1");
360             }
361             break;
362 
363         /* Both MIF/MAF set is invalid if length is zero */
364 
365         case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF):
366         default:
367             AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL);
368         }
369     }
370 }
371 
372 
373 /*******************************************************************************
374  *
375  * FUNCTION:    RsGetStringDataLength
376  *
377  * PARAMETERS:  InitializerOp     - Start of a subtree of init nodes
378  *
379  * RETURN:      Valid string length if a string node is found (otherwise 0)
380  *
381  * DESCRIPTION: In a list of peer nodes, find the first one that contains a
382  *              string and return the length of the string.
383  *
384  ******************************************************************************/
385 
386 UINT16
387 RsGetStringDataLength (
388     ACPI_PARSE_OBJECT       *InitializerOp)
389 {
390 
391     while (InitializerOp)
392     {
393         if (InitializerOp->Asl.ParseOpcode == PARSEOP_STRING_LITERAL)
394         {
395             return ((UINT16) (strlen (InitializerOp->Asl.Value.String) + 1));
396         }
397         InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
398     }
399 
400     return (0);
401 }
402 
403 
404 /*******************************************************************************
405  *
406  * FUNCTION:    RsAllocateResourceNode
407  *
408  * PARAMETERS:  Size        - Size of node in bytes
409  *
410  * RETURN:      The allocated node - aborts on allocation failure
411  *
412  * DESCRIPTION: Allocate a resource description node and the resource
413  *              descriptor itself (the nodes are used to link descriptors).
414  *
415  ******************************************************************************/
416 
417 ASL_RESOURCE_NODE *
418 RsAllocateResourceNode (
419     UINT32                  Size)
420 {
421     ASL_RESOURCE_NODE       *Rnode;
422 
423 
424     /* Allocate the node */
425 
426     Rnode = UtLocalCalloc (sizeof (ASL_RESOURCE_NODE));
427 
428     /* Allocate the resource descriptor itself */
429 
430     Rnode->Buffer = UtLocalCalloc (Size);
431     Rnode->BufferLength = Size;
432 
433     return (Rnode);
434 }
435 
436 
437 /*******************************************************************************
438  *
439  * FUNCTION:    RsCreateResourceField
440  *
441  * PARAMETERS:  Op              - Resource field node
442  *              Name            - Name of the field (Used only to reference
443  *                                the field in the ASL, not in the AML)
444  *              ByteOffset      - Offset from the field start
445  *              BitOffset       - Additional bit offset
446  *              BitLength       - Number of bits in the field
447  *
448  * RETURN:      None, sets fields within the input node
449  *
450  * DESCRIPTION: Utility function to generate a named bit field within a
451  *              resource descriptor. Mark a node as 1) a field in a resource
452  *              descriptor, and 2) set the value to be a BIT offset
453  *
454  ******************************************************************************/
455 
456 void
457 RsCreateResourceField (
458     ACPI_PARSE_OBJECT       *Op,
459     char                    *Name,
460     UINT32                  ByteOffset,
461     UINT32                  BitOffset,
462     UINT32                  BitLength)
463 {
464 
465     Op->Asl.ExternalName = Name;
466     Op->Asl.CompileFlags |= NODE_IS_RESOURCE_FIELD;
467 
468 
469     Op->Asl.Value.Tag.BitOffset = (ByteOffset * 8) + BitOffset;
470     Op->Asl.Value.Tag.BitLength = BitLength;
471 }
472 
473 
474 /*******************************************************************************
475  *
476  * FUNCTION:    RsSetFlagBits
477  *
478  * PARAMETERS:  *Flags          - Pointer to the flag byte
479  *              Op              - Flag initialization node
480  *              Position        - Bit position within the flag byte
481  *              Default         - Used if the node is DEFAULT.
482  *
483  * RETURN:      Sets bits within the *Flags output byte.
484  *
485  * DESCRIPTION: Set a bit in a cumulative flags word from an initialization
486  *              node. Will use a default value if the node is DEFAULT, meaning
487  *              that no value was specified in the ASL. Used to merge multiple
488  *              keywords into a single flags byte.
489  *
490  ******************************************************************************/
491 
492 void
493 RsSetFlagBits (
494     UINT8                   *Flags,
495     ACPI_PARSE_OBJECT       *Op,
496     UINT8                   Position,
497     UINT8                   DefaultBit)
498 {
499 
500     if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
501     {
502         /* Use the default bit */
503 
504         *Flags |= (DefaultBit << Position);
505     }
506     else
507     {
508         /* Use the bit specified in the initialization node */
509 
510         *Flags |= (((UINT8) Op->Asl.Value.Integer) << Position);
511     }
512 }
513 
514 
515 void
516 RsSetFlagBits16 (
517     UINT16                  *Flags,
518     ACPI_PARSE_OBJECT       *Op,
519     UINT8                   Position,
520     UINT8                   DefaultBit)
521 {
522 
523     if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
524     {
525         /* Use the default bit */
526 
527         *Flags |= (DefaultBit << Position);
528     }
529     else
530     {
531         /* Use the bit specified in the initialization node */
532 
533         *Flags |= (((UINT16) Op->Asl.Value.Integer) << Position);
534     }
535 }
536 
537 
538 /*******************************************************************************
539  *
540  * FUNCTION:    RsCompleteNodeAndGetNext
541  *
542  * PARAMETERS:  Op            - Resource node to be completed
543  *
544  * RETURN:      The next peer to the input node.
545  *
546  * DESCRIPTION: Mark the current node completed and return the next peer.
547  *              The node ParseOpcode is set to DEFAULT_ARG, meaning that
548  *              this node is to be ignored from now on.
549  *
550  ******************************************************************************/
551 
552 ACPI_PARSE_OBJECT *
553 RsCompleteNodeAndGetNext (
554     ACPI_PARSE_OBJECT       *Op)
555 {
556 
557     /* Mark this node unused */
558 
559     Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
560 
561     /* Move on to the next peer node in the initializer list */
562 
563     return (ASL_GET_PEER_NODE (Op));
564 }
565 
566 
567 /*******************************************************************************
568  *
569  * FUNCTION:    RsCheckListForDuplicates
570  *
571  * PARAMETERS:  Op                  - First op in the initializer list
572  *
573  * RETURN:      None
574  *
575  * DESCRIPTION: Check an initializer list for duplicate values. Emits an error
576  *              if any duplicates are found.
577  *
578  ******************************************************************************/
579 
580 void
581 RsCheckListForDuplicates (
582     ACPI_PARSE_OBJECT       *Op)
583 {
584     ACPI_PARSE_OBJECT       *NextValueOp = Op;
585     ACPI_PARSE_OBJECT       *NextOp;
586     UINT32                  Value;
587 
588 
589     if (!Op)
590     {
591         return;
592     }
593 
594     /* Search list once for each value in the list */
595 
596     while (NextValueOp)
597     {
598         Value = (UINT32) NextValueOp->Asl.Value.Integer;
599 
600         /* Compare this value to all remaining values in the list */
601 
602         NextOp = ASL_GET_PEER_NODE (NextValueOp);
603         while (NextOp)
604         {
605             if (NextOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
606             {
607                 /* Compare values */
608 
609                 if (Value == (UINT32) NextOp->Asl.Value.Integer)
610                 {
611                     /* Emit error only once per duplicate node */
612 
613                     if (!(NextOp->Asl.CompileFlags & NODE_IS_DUPLICATE))
614                     {
615                         NextOp->Asl.CompileFlags |= NODE_IS_DUPLICATE;
616                         AslError (ASL_ERROR, ASL_MSG_DUPLICATE_ITEM,
617                             NextOp, NULL);
618                     }
619                 }
620             }
621 
622             NextOp = ASL_GET_PEER_NODE (NextOp);
623         }
624 
625         NextValueOp = ASL_GET_PEER_NODE (NextValueOp);
626     }
627 }
628 
629 
630 /*******************************************************************************
631  *
632  * FUNCTION:    RsDoOneResourceDescriptor
633  *
634  * PARAMETERS:  DescriptorTypeOp    - Parent parse node of the descriptor
635  *              CurrentByteOffset   - Offset in the resource descriptor
636  *                                    buffer.
637  *
638  * RETURN:      A valid resource node for the descriptor
639  *
640  * DESCRIPTION: Dispatches the processing of one resource descriptor
641  *
642  ******************************************************************************/
643 
644 ASL_RESOURCE_NODE *
645 RsDoOneResourceDescriptor (
646     ACPI_PARSE_OBJECT       *DescriptorTypeOp,
647     UINT32                  CurrentByteOffset,
648     UINT8                   *State)
649 {
650     ASL_RESOURCE_NODE       *Rnode = NULL;
651 
652 
653     /* Construct the resource */
654 
655     switch (DescriptorTypeOp->Asl.ParseOpcode)
656     {
657     case PARSEOP_DMA:
658         Rnode = RsDoDmaDescriptor (DescriptorTypeOp,
659                     CurrentByteOffset);
660         break;
661 
662     case PARSEOP_FIXEDDMA:
663         Rnode = RsDoFixedDmaDescriptor (DescriptorTypeOp,
664                     CurrentByteOffset);
665         break;
666 
667     case PARSEOP_DWORDIO:
668         Rnode = RsDoDwordIoDescriptor (DescriptorTypeOp,
669                     CurrentByteOffset);
670         break;
671 
672     case PARSEOP_DWORDMEMORY:
673         Rnode = RsDoDwordMemoryDescriptor (DescriptorTypeOp,
674                     CurrentByteOffset);
675         break;
676 
677     case PARSEOP_DWORDSPACE:
678         Rnode = RsDoDwordSpaceDescriptor (DescriptorTypeOp,
679                     CurrentByteOffset);
680         break;
681 
682     case PARSEOP_ENDDEPENDENTFN:
683         switch (*State)
684         {
685         case ACPI_RSTATE_NORMAL:
686             AslError (ASL_ERROR, ASL_MSG_MISSING_STARTDEPENDENT,
687                 DescriptorTypeOp, NULL);
688             break;
689 
690         case ACPI_RSTATE_START_DEPENDENT:
691             AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
692                 DescriptorTypeOp, NULL);
693             break;
694 
695         case ACPI_RSTATE_DEPENDENT_LIST:
696         default:
697             break;
698         }
699 
700         *State = ACPI_RSTATE_NORMAL;
701         Rnode = RsDoEndDependentDescriptor (DescriptorTypeOp,
702                     CurrentByteOffset);
703         break;
704 
705     case PARSEOP_ENDTAG:
706         Rnode = RsDoEndTagDescriptor (DescriptorTypeOp,
707                     CurrentByteOffset);
708         break;
709 
710     case PARSEOP_EXTENDEDIO:
711         Rnode = RsDoExtendedIoDescriptor (DescriptorTypeOp,
712                     CurrentByteOffset);
713         break;
714 
715     case PARSEOP_EXTENDEDMEMORY:
716         Rnode = RsDoExtendedMemoryDescriptor (DescriptorTypeOp,
717                     CurrentByteOffset);
718         break;
719 
720     case PARSEOP_EXTENDEDSPACE:
721         Rnode = RsDoExtendedSpaceDescriptor (DescriptorTypeOp,
722                     CurrentByteOffset);
723         break;
724 
725     case PARSEOP_FIXEDIO:
726         Rnode = RsDoFixedIoDescriptor (DescriptorTypeOp,
727                     CurrentByteOffset);
728         break;
729 
730     case PARSEOP_INTERRUPT:
731         Rnode = RsDoInterruptDescriptor (DescriptorTypeOp,
732                     CurrentByteOffset);
733         break;
734 
735     case PARSEOP_IO:
736         Rnode = RsDoIoDescriptor (DescriptorTypeOp,
737                     CurrentByteOffset);
738         break;
739 
740     case PARSEOP_IRQ:
741         Rnode = RsDoIrqDescriptor (DescriptorTypeOp,
742                     CurrentByteOffset);
743         break;
744 
745     case PARSEOP_IRQNOFLAGS:
746         Rnode = RsDoIrqNoFlagsDescriptor (DescriptorTypeOp,
747                     CurrentByteOffset);
748         break;
749 
750     case PARSEOP_MEMORY24:
751         Rnode = RsDoMemory24Descriptor (DescriptorTypeOp,
752                     CurrentByteOffset);
753         break;
754 
755     case PARSEOP_MEMORY32:
756         Rnode = RsDoMemory32Descriptor (DescriptorTypeOp,
757                     CurrentByteOffset);
758         break;
759 
760     case PARSEOP_MEMORY32FIXED:
761         Rnode = RsDoMemory32FixedDescriptor (DescriptorTypeOp,
762                     CurrentByteOffset);
763         break;
764 
765     case PARSEOP_QWORDIO:
766         Rnode = RsDoQwordIoDescriptor (DescriptorTypeOp,
767                     CurrentByteOffset);
768         break;
769 
770     case PARSEOP_QWORDMEMORY:
771         Rnode = RsDoQwordMemoryDescriptor (DescriptorTypeOp,
772                     CurrentByteOffset);
773         break;
774 
775     case PARSEOP_QWORDSPACE:
776         Rnode = RsDoQwordSpaceDescriptor (DescriptorTypeOp,
777                     CurrentByteOffset);
778         break;
779 
780     case PARSEOP_REGISTER:
781         Rnode = RsDoGeneralRegisterDescriptor (DescriptorTypeOp,
782                     CurrentByteOffset);
783         break;
784 
785     case PARSEOP_STARTDEPENDENTFN:
786         switch (*State)
787         {
788         case ACPI_RSTATE_START_DEPENDENT:
789             AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
790                 DescriptorTypeOp, NULL);
791             break;
792 
793         case ACPI_RSTATE_NORMAL:
794         case ACPI_RSTATE_DEPENDENT_LIST:
795         default:
796             break;
797         }
798 
799         *State = ACPI_RSTATE_START_DEPENDENT;
800         Rnode = RsDoStartDependentDescriptor (DescriptorTypeOp,
801                     CurrentByteOffset);
802         *State = ACPI_RSTATE_DEPENDENT_LIST;
803         break;
804 
805     case PARSEOP_STARTDEPENDENTFN_NOPRI:
806         switch (*State)
807         {
808         case ACPI_RSTATE_START_DEPENDENT:
809             AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
810                 DescriptorTypeOp, NULL);
811             break;
812 
813         case ACPI_RSTATE_NORMAL:
814         case ACPI_RSTATE_DEPENDENT_LIST:
815         default:
816             break;
817         }
818 
819         *State = ACPI_RSTATE_START_DEPENDENT;
820         Rnode = RsDoStartDependentNoPriDescriptor (DescriptorTypeOp,
821                     CurrentByteOffset);
822         *State = ACPI_RSTATE_DEPENDENT_LIST;
823         break;
824 
825     case PARSEOP_VENDORLONG:
826         Rnode = RsDoVendorLargeDescriptor (DescriptorTypeOp,
827                     CurrentByteOffset);
828         break;
829 
830     case PARSEOP_VENDORSHORT:
831         Rnode = RsDoVendorSmallDescriptor (DescriptorTypeOp,
832                     CurrentByteOffset);
833         break;
834 
835     case PARSEOP_WORDBUSNUMBER:
836         Rnode = RsDoWordBusNumberDescriptor (DescriptorTypeOp,
837                     CurrentByteOffset);
838         break;
839 
840     case PARSEOP_WORDIO:
841         Rnode = RsDoWordIoDescriptor (DescriptorTypeOp,
842                     CurrentByteOffset);
843         break;
844 
845     case PARSEOP_WORDSPACE:
846         Rnode = RsDoWordSpaceDescriptor (DescriptorTypeOp,
847                     CurrentByteOffset);
848         break;
849 
850     case PARSEOP_GPIO_INT:
851         Rnode = RsDoGpioIntDescriptor (DescriptorTypeOp,
852                     CurrentByteOffset);
853         break;
854 
855     case PARSEOP_GPIO_IO:
856         Rnode = RsDoGpioIoDescriptor (DescriptorTypeOp,
857                     CurrentByteOffset);
858         break;
859 
860     case PARSEOP_I2C_SERIALBUS:
861         Rnode = RsDoI2cSerialBusDescriptor (DescriptorTypeOp,
862                     CurrentByteOffset);
863         break;
864 
865     case PARSEOP_SPI_SERIALBUS:
866         Rnode = RsDoSpiSerialBusDescriptor (DescriptorTypeOp,
867                     CurrentByteOffset);
868         break;
869 
870     case PARSEOP_UART_SERIALBUS:
871         Rnode = RsDoUartSerialBusDescriptor (DescriptorTypeOp,
872                     CurrentByteOffset);
873         break;
874 
875     case PARSEOP_DEFAULT_ARG:
876         /* Just ignore any of these, they are used as fillers/placeholders */
877         break;
878 
879     default:
880         printf ("Unknown resource descriptor type [%s]\n",
881                     DescriptorTypeOp->Asl.ParseOpName);
882         break;
883     }
884 
885     /*
886      * Mark original node as unused, but head of a resource descriptor.
887      * This allows the resource to be installed in the namespace so that
888      * references to the descriptor can be resolved.
889      */
890     DescriptorTypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
891     DescriptorTypeOp->Asl.CompileFlags = NODE_IS_RESOURCE_DESC;
892     DescriptorTypeOp->Asl.Value.Integer = CurrentByteOffset;
893 
894     if (Rnode)
895     {
896         DescriptorTypeOp->Asl.FinalAmlLength = Rnode->BufferLength;
897     }
898 
899     return (Rnode);
900 }
901 
902 
903 /*******************************************************************************
904  *
905  * FUNCTION:    RsLinkDescriptorChain
906  *
907  * PARAMETERS:  PreviousRnode       - Pointer to the node that will be previous
908  *                                    to the linked node,  At exit, set to the
909  *                                    last node in the new chain.
910  *              Rnode               - Resource node to link into the list
911  *
912  * RETURN:      Cumulative buffer byte offset of the new segment of chain
913  *
914  * DESCRIPTION: Link a descriptor chain at the end of an existing chain.
915  *
916  ******************************************************************************/
917 
918 UINT32
919 RsLinkDescriptorChain (
920     ASL_RESOURCE_NODE       **PreviousRnode,
921     ASL_RESOURCE_NODE       *Rnode)
922 {
923     ASL_RESOURCE_NODE       *LastRnode;
924     UINT32                  CurrentByteOffset;
925 
926 
927     /* Anything to do? */
928 
929     if (!Rnode)
930     {
931         return (0);
932     }
933 
934     /* Point the previous node to the new node */
935 
936     (*PreviousRnode)->Next = Rnode;
937     CurrentByteOffset = Rnode->BufferLength;
938 
939     /* Walk to the end of the chain headed by Rnode */
940 
941     LastRnode = Rnode;
942     while (LastRnode->Next)
943     {
944         LastRnode = LastRnode->Next;
945         CurrentByteOffset += LastRnode->BufferLength;
946     }
947 
948     /* Previous node becomes the last node in the chain */
949 
950     *PreviousRnode = LastRnode;
951     return (CurrentByteOffset);
952 }
953 
954 
955 /*******************************************************************************
956  *
957  * FUNCTION:    RsDoResourceTemplate
958  *
959  * PARAMETERS:  Op        - Parent of a resource template list
960  *
961  * RETURN:      None. Sets input node to point to a list of AML code
962  *
963  * DESCRIPTION: Merge a list of resource descriptors into a single AML buffer,
964  *              in preparation for output to the AML output file.
965  *
966  ******************************************************************************/
967 
968 void
969 RsDoResourceTemplate (
970     ACPI_PARSE_OBJECT       *Op)
971 {
972     ACPI_PARSE_OBJECT       *BufferLengthOp;
973     ACPI_PARSE_OBJECT       *BufferOp;
974     ACPI_PARSE_OBJECT       *DescriptorTypeOp;
975     ACPI_PARSE_OBJECT       *LastOp = NULL;
976     UINT32                  CurrentByteOffset = 0;
977     ASL_RESOURCE_NODE       HeadRnode;
978     ASL_RESOURCE_NODE       *PreviousRnode;
979     ASL_RESOURCE_NODE       *Rnode;
980     UINT8                   State;
981 
982 
983     /* Mark parent as containing a resource template */
984 
985     if (Op->Asl.Parent)
986     {
987         Op->Asl.Parent->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
988     }
989 
990     /* ResourceTemplate Opcode is first (Op) */
991     /* Buffer Length node is first child */
992 
993     BufferLengthOp = ASL_GET_CHILD_NODE (Op);
994 
995     /* Buffer Op is first peer */
996 
997     BufferOp = ASL_GET_PEER_NODE (BufferLengthOp);
998 
999     /* First Descriptor type is next */
1000 
1001     DescriptorTypeOp = ASL_GET_PEER_NODE (BufferOp);
1002 
1003     /*
1004      * Process all resource descriptors in the list
1005      * Note: It is assumed that the EndTag node has been automatically
1006      * inserted at the end of the template by the parser.
1007      */
1008     State = ACPI_RSTATE_NORMAL;
1009     PreviousRnode = &HeadRnode;
1010     while (DescriptorTypeOp)
1011     {
1012         DescriptorTypeOp->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
1013         Rnode = RsDoOneResourceDescriptor (DescriptorTypeOp, CurrentByteOffset,
1014                     &State);
1015 
1016         /*
1017          * Update current byte offset to indicate the number of bytes from the
1018          * start of the buffer. Buffer can include multiple descriptors, we
1019          * must keep track of the offset of not only each descriptor, but each
1020          * element (field) within each descriptor as well.
1021          */
1022         CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, Rnode);
1023 
1024         /* Get the next descriptor in the list */
1025 
1026         LastOp = DescriptorTypeOp;
1027         DescriptorTypeOp = ASL_GET_PEER_NODE (DescriptorTypeOp);
1028     }
1029 
1030     if (State == ACPI_RSTATE_DEPENDENT_LIST)
1031     {
1032         if (LastOp)
1033         {
1034             LastOp = LastOp->Asl.Parent;
1035         }
1036         AslError (ASL_ERROR, ASL_MSG_MISSING_ENDDEPENDENT, LastOp, NULL);
1037     }
1038 
1039     /*
1040      * Transform the nodes into the following
1041      *
1042      * Op           -> AML_BUFFER_OP
1043      * First Child  -> BufferLength
1044      * Second Child -> Descriptor Buffer (raw byte data)
1045      */
1046     Op->Asl.ParseOpcode               = PARSEOP_BUFFER;
1047     Op->Asl.AmlOpcode                 = AML_BUFFER_OP;
1048     Op->Asl.CompileFlags              = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC;
1049     UtSetParseOpName (Op);
1050 
1051     BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
1052     BufferLengthOp->Asl.Value.Integer = CurrentByteOffset;
1053     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
1054     UtSetParseOpName (BufferLengthOp);
1055 
1056     BufferOp->Asl.ParseOpcode         = PARSEOP_RAW_DATA;
1057     BufferOp->Asl.AmlOpcode           = AML_RAW_DATA_CHAIN;
1058     BufferOp->Asl.AmlOpcodeLength     = 0;
1059     BufferOp->Asl.AmlLength           = CurrentByteOffset;
1060     BufferOp->Asl.Value.Buffer        = (UINT8 *) HeadRnode.Next;
1061     BufferOp->Asl.CompileFlags       |= NODE_IS_RESOURCE_DATA;
1062     UtSetParseOpName (BufferOp);
1063 
1064     return;
1065 }
1066