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