xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/aslresource.c (revision c7960b37466ae0fd417c32e6acbb4b956ac7a121)
1 /******************************************************************************
2  *
3  * Module Name: aslresource - Resource template/descriptor utilities
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2023, 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 MERCHANTABILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "aslcompiler.h"
45 #include "aslcompiler.y.h"
46 #include "amlcode.h"
47 
48 
49 #define _COMPONENT          ACPI_COMPILER
50         ACPI_MODULE_NAME    ("aslresource")
51 
52 
53 /*******************************************************************************
54  *
55  * FUNCTION:    RsSmallAddressCheck
56  *
57  * PARAMETERS:  Minimum             - Address Min value
58  *              Maximum             - Address Max value
59  *              Length              - Address range value
60  *              Alignment           - Address alignment value
61  *              MinOp               - Original Op for Address Min
62  *              MaxOp               - Original Op for Address Max
63  *              LengthOp            - Original Op for address range
64  *              AlignOp             - Original Op for address alignment. If
65  *                                    NULL, means "zero value for alignment is
66  *                                    OK, and means 64K alignment" (for
67  *                                    Memory24 descriptor)
68  *              Op                  - Parent Op for entire construct
69  *
70  * RETURN:      None. Adds error messages to error log if necessary
71  *
72  * DESCRIPTION: Perform common value checks for "small" address descriptors.
73  *              Currently:
74  *                  Io, Memory24, Memory32
75  *
76  ******************************************************************************/
77 
78 void
79 RsSmallAddressCheck (
80     UINT8                   Type,
81     UINT32                  Minimum,
82     UINT32                  Maximum,
83     UINT32                  Length,
84     UINT32                  Alignment,
85     ACPI_PARSE_OBJECT       *MinOp,
86     ACPI_PARSE_OBJECT       *MaxOp,
87     ACPI_PARSE_OBJECT       *LengthOp,
88     ACPI_PARSE_OBJECT       *AlignOp,
89     ACPI_PARSE_OBJECT       *Op)
90 {
91 
92     if (AslGbl_NoResourceChecking)
93     {
94         return;
95     }
96 
97     /*
98      * Check for a so-called "null descriptor". These are descriptors that are
99      * created with most fields set to zero. The intent is that the descriptor
100      * will be updated/completed at runtime via a BufferField.
101      *
102      * If the descriptor does NOT have a resource tag, it cannot be referenced
103      * by a BufferField and we will flag this as an error. Conversely, if
104      * the descriptor has a resource tag, we will assume that a BufferField
105      * will be used to dynamically update it, so no error.
106      *
107      * A possible enhancement to this check would be to verify that in fact
108      * a BufferField is created using the resource tag, and perhaps even
109      * verify that a Store is performed to the BufferField.
110      *
111      * Note: for these descriptors, Alignment is allowed to be zero
112      */
113     if (!Minimum && !Maximum && !Length)
114     {
115         if (!Op->Asl.ExternalName)
116         {
117             /* No resource tag. Descriptor is fixed and is also illegal */
118 
119             AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL);
120         }
121 
122         return;
123     }
124 
125     /*
126      * Range checks for Memory24 and Memory32.
127      * IO descriptor has different definition of min/max, don't check.
128      */
129     if (Type != ACPI_RESOURCE_NAME_IO)
130     {
131         /* Basic checks on Min/Max/Length */
132 
133         if (Minimum > Maximum)
134         {
135             AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL);
136         }
137         else if (Length > (Maximum - Minimum + 1))
138         {
139             AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL);
140         }
141 
142         /* Special case for Memory24, min/max values are compressed */
143 
144         if (Type == ACPI_RESOURCE_NAME_MEMORY24)
145         {
146             if (!Alignment) /* Alignment==0 means 64K alignment */
147             {
148                 Alignment = ACPI_UINT16_MAX + 1;
149             }
150 
151             Minimum <<= 8;
152             Maximum <<= 8;
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 (AslGbl_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 
400         InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
401     }
402 
403     return (0);
404 }
405 
406 
407 /*******************************************************************************
408  *
409  * FUNCTION:    RsAllocateResourceNode
410  *
411  * PARAMETERS:  Size        - Size of node in bytes
412  *
413  * RETURN:      The allocated node - aborts on allocation failure
414  *
415  * DESCRIPTION: Allocate a resource description node and the resource
416  *              descriptor itself (the nodes are used to link descriptors).
417  *
418  ******************************************************************************/
419 
420 ASL_RESOURCE_NODE *
421 RsAllocateResourceNode (
422     UINT32                  Size)
423 {
424     ASL_RESOURCE_NODE       *Rnode;
425 
426 
427     /* Allocate the node */
428 
429     Rnode = UtLocalCalloc (sizeof (ASL_RESOURCE_NODE));
430 
431     /* Allocate the resource descriptor itself */
432 
433     Rnode->Buffer = UtLocalCalloc (Size);
434     Rnode->BufferLength = Size;
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 |= OP_IS_RESOURCE_FIELD;
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 & OP_IS_DUPLICATE))
615                     {
616                         NextOp->Asl.CompileFlags |= OP_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     ASL_RESOURCE_INFO       *Info,
648     UINT8                   *State)
649 {
650     ASL_RESOURCE_NODE       *Rnode = NULL;
651 
652 
653     /* Construct the resource */
654 
655     switch (Info->DescriptorTypeOp->Asl.ParseOpcode)
656     {
657 
658     case PARSEOP_CLOCKINPUT:
659 
660         Rnode = RsDoClockInputDescriptor(Info);
661         break;
662 
663     case PARSEOP_DMA:
664 
665         Rnode = RsDoDmaDescriptor (Info);
666         break;
667 
668     case PARSEOP_FIXEDDMA:
669 
670         Rnode = RsDoFixedDmaDescriptor (Info);
671         break;
672 
673     case PARSEOP_DWORDIO:
674 
675         Rnode = RsDoDwordIoDescriptor (Info);
676         break;
677 
678     case PARSEOP_DWORDMEMORY:
679 
680         Rnode = RsDoDwordMemoryDescriptor (Info);
681         break;
682 
683     case PARSEOP_DWORDPCC:
684 
685         Rnode = RsDoDwordPccDescriptor (Info);
686         break;
687 
688     case PARSEOP_DWORDSPACE:
689 
690         Rnode = RsDoDwordSpaceDescriptor (Info);
691         break;
692 
693     case PARSEOP_ENDDEPENDENTFN:
694 
695         switch (*State)
696         {
697         case ACPI_RSTATE_NORMAL:
698 
699             AslError (ASL_ERROR, ASL_MSG_MISSING_STARTDEPENDENT,
700                 Info->DescriptorTypeOp, NULL);
701             break;
702 
703         case ACPI_RSTATE_START_DEPENDENT:
704 
705             AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
706                 Info->DescriptorTypeOp, NULL);
707             break;
708 
709         case ACPI_RSTATE_DEPENDENT_LIST:
710         default:
711 
712             break;
713         }
714 
715         *State = ACPI_RSTATE_NORMAL;
716         Rnode = RsDoEndDependentDescriptor (Info);
717         break;
718 
719     case PARSEOP_ENDTAG:
720 
721         Rnode = RsDoEndTagDescriptor (Info);
722         break;
723 
724     case PARSEOP_EXTENDEDIO:
725 
726         Rnode = RsDoExtendedIoDescriptor (Info);
727         break;
728 
729     case PARSEOP_EXTENDEDMEMORY:
730 
731         Rnode = RsDoExtendedMemoryDescriptor (Info);
732         break;
733 
734     case PARSEOP_EXTENDEDSPACE:
735 
736         Rnode = RsDoExtendedSpaceDescriptor (Info);
737         break;
738 
739     case PARSEOP_FIXEDIO:
740 
741         Rnode = RsDoFixedIoDescriptor (Info);
742         break;
743 
744     case PARSEOP_INTERRUPT:
745 
746         Rnode = RsDoInterruptDescriptor (Info);
747         break;
748 
749     case PARSEOP_IO:
750 
751         Rnode = RsDoIoDescriptor (Info);
752         break;
753 
754     case PARSEOP_IRQ:
755 
756         Rnode = RsDoIrqDescriptor (Info);
757         break;
758 
759     case PARSEOP_IRQNOFLAGS:
760 
761         Rnode = RsDoIrqNoFlagsDescriptor (Info);
762         break;
763 
764     case PARSEOP_MEMORY24:
765 
766         Rnode = RsDoMemory24Descriptor (Info);
767         break;
768 
769     case PARSEOP_MEMORY32:
770 
771         Rnode = RsDoMemory32Descriptor (Info);
772         break;
773 
774     case PARSEOP_MEMORY32FIXED:
775 
776         Rnode = RsDoMemory32FixedDescriptor (Info);
777         break;
778 
779     case PARSEOP_QWORDIO:
780 
781         Rnode = RsDoQwordIoDescriptor (Info);
782         break;
783 
784     case PARSEOP_QWORDMEMORY:
785 
786         Rnode = RsDoQwordMemoryDescriptor (Info);
787         break;
788 
789     case PARSEOP_QWORDPCC:
790 
791         Rnode = RsDoQwordPccDescriptor (Info);
792         break;
793 
794     case PARSEOP_QWORDSPACE:
795 
796         Rnode = RsDoQwordSpaceDescriptor (Info);
797         break;
798 
799     case PARSEOP_REGISTER:
800 
801         Rnode = RsDoGeneralRegisterDescriptor (Info);
802         break;
803 
804     case PARSEOP_STARTDEPENDENTFN:
805 
806         switch (*State)
807         {
808         case ACPI_RSTATE_START_DEPENDENT:
809 
810             AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
811                 Info->DescriptorTypeOp, NULL);
812             break;
813 
814         case ACPI_RSTATE_NORMAL:
815         case ACPI_RSTATE_DEPENDENT_LIST:
816         default:
817 
818             break;
819         }
820 
821         *State = ACPI_RSTATE_START_DEPENDENT;
822         Rnode = RsDoStartDependentDescriptor (Info);
823         *State = ACPI_RSTATE_DEPENDENT_LIST;
824         break;
825 
826     case PARSEOP_STARTDEPENDENTFN_NOPRI:
827 
828         switch (*State)
829         {
830         case ACPI_RSTATE_START_DEPENDENT:
831 
832             AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
833                 Info->DescriptorTypeOp, NULL);
834             break;
835 
836         case ACPI_RSTATE_NORMAL:
837         case ACPI_RSTATE_DEPENDENT_LIST:
838         default:
839 
840             break;
841         }
842 
843         *State = ACPI_RSTATE_START_DEPENDENT;
844         Rnode = RsDoStartDependentNoPriDescriptor (Info);
845         *State = ACPI_RSTATE_DEPENDENT_LIST;
846         break;
847 
848     case PARSEOP_VENDORLONG:
849 
850         Rnode = RsDoVendorLargeDescriptor (Info);
851         break;
852 
853     case PARSEOP_VENDORSHORT:
854 
855         Rnode = RsDoVendorSmallDescriptor (Info);
856         break;
857 
858     case PARSEOP_WORDBUSNUMBER:
859 
860         Rnode = RsDoWordBusNumberDescriptor (Info);
861         break;
862 
863     case PARSEOP_WORDIO:
864 
865         Rnode = RsDoWordIoDescriptor (Info);
866         break;
867 
868     case PARSEOP_WORDPCC:
869 
870         Rnode = RsDoWordPccDescriptor (Info);
871         break;
872 
873     case PARSEOP_WORDSPACE:
874 
875         Rnode = RsDoWordSpaceDescriptor (Info);
876         break;
877 
878     case PARSEOP_GPIO_INT:
879 
880         Rnode = RsDoGpioIntDescriptor (Info);
881         break;
882 
883     case PARSEOP_GPIO_IO:
884 
885         Rnode = RsDoGpioIoDescriptor (Info);
886         break;
887 
888     case PARSEOP_I2C_SERIALBUS:
889     case PARSEOP_I2C_SERIALBUS_V2:
890 
891         Rnode = RsDoI2cSerialBusDescriptor (Info);
892         break;
893 
894     case PARSEOP_SPI_SERIALBUS:
895     case PARSEOP_SPI_SERIALBUS_V2:
896 
897         Rnode = RsDoSpiSerialBusDescriptor (Info);
898         break;
899 
900     case PARSEOP_UART_SERIALBUS:
901     case PARSEOP_UART_SERIALBUS_V2:
902 
903         Rnode = RsDoUartSerialBusDescriptor (Info);
904         break;
905 
906     case PARSEOP_CSI2_SERIALBUS:
907 
908         Rnode = RsDoCsi2SerialBusDescriptor (Info);
909         break;
910 
911     case PARSEOP_PINCONFIG:
912 
913         Rnode = RsDoPinConfigDescriptor (Info);
914         break;
915 
916     case PARSEOP_PINFUNCTION:
917 
918         Rnode = RsDoPinFunctionDescriptor (Info);
919         break;
920 
921     case PARSEOP_PINGROUP:
922 
923         Rnode = RsDoPinGroupDescriptor (Info);
924         break;
925 
926     case PARSEOP_PINGROUPFUNCTION:
927 
928         Rnode = RsDoPinGroupFunctionDescriptor (Info);
929         break;
930 
931     case PARSEOP_PINGROUPCONFIG:
932 
933         Rnode = RsDoPinGroupConfigDescriptor (Info);
934         break;
935 
936     case PARSEOP_DEFAULT_ARG:
937 
938         /* Just ignore any of these, they are used as fillers/placeholders */
939         break;
940 
941     default:
942 
943         printf ("Unknown resource descriptor type [%s]\n",
944             Info->DescriptorTypeOp->Asl.ParseOpName);
945         break;
946     }
947 
948     /*
949      * Mark original node as unused, but head of a resource descriptor.
950      * This allows the resource to be installed in the namespace so that
951      * references to the descriptor can be resolved.
952      */
953     Info->DescriptorTypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
954     Info->DescriptorTypeOp->Asl.CompileFlags = OP_IS_RESOURCE_DESC;
955     Info->DescriptorTypeOp->Asl.Value.Integer = Info->CurrentByteOffset;
956 
957     if (Rnode)
958     {
959         Info->DescriptorTypeOp->Asl.FinalAmlLength = Rnode->BufferLength;
960         Info->DescriptorTypeOp->Asl.Extra =
961             ((AML_RESOURCE *) Rnode->Buffer)->DescriptorType;
962     }
963 
964     return (Rnode);
965 }
966 
967 
968 /*******************************************************************************
969  *
970  * FUNCTION:    RsLinkDescriptorChain
971  *
972  * PARAMETERS:  PreviousRnode       - Pointer to the node that will be previous
973  *                                    to the linked node,  At exit, set to the
974  *                                    last node in the new chain.
975  *              Rnode               - Resource node to link into the list
976  *
977  * RETURN:      Cumulative buffer byte offset of the new segment of chain
978  *
979  * DESCRIPTION: Link a descriptor chain at the end of an existing chain.
980  *
981  ******************************************************************************/
982 
983 UINT32
984 RsLinkDescriptorChain (
985     ASL_RESOURCE_NODE       **PreviousRnode,
986     ASL_RESOURCE_NODE       *Rnode)
987 {
988     ASL_RESOURCE_NODE       *LastRnode;
989     UINT32                  CurrentByteOffset;
990 
991 
992     /* Anything to do? */
993 
994     if (!Rnode)
995     {
996         return (0);
997     }
998 
999     /* Point the previous node to the new node */
1000 
1001     (*PreviousRnode)->Next = Rnode;
1002     CurrentByteOffset = Rnode->BufferLength;
1003 
1004     /* Walk to the end of the chain headed by Rnode */
1005 
1006     LastRnode = Rnode;
1007     while (LastRnode->Next)
1008     {
1009         LastRnode = LastRnode->Next;
1010         CurrentByteOffset += LastRnode->BufferLength;
1011     }
1012 
1013     /* Previous node becomes the last node in the chain */
1014 
1015     *PreviousRnode = LastRnode;
1016     return (CurrentByteOffset);
1017 }
1018 
1019 
1020 /*******************************************************************************
1021  *
1022  * FUNCTION:    RsDoResourceTemplate
1023  *
1024  * PARAMETERS:  Op        - Parent of a resource template list
1025  *
1026  * RETURN:      None. Sets input node to point to a list of AML code
1027  *
1028  * DESCRIPTION: Merge a list of resource descriptors into a single AML buffer,
1029  *              in preparation for output to the AML output file.
1030  *
1031  ******************************************************************************/
1032 
1033 void
1034 RsDoResourceTemplate (
1035     ACPI_PARSE_OBJECT       *Op)
1036 {
1037     ACPI_PARSE_OBJECT       *BufferLengthOp;
1038     ACPI_PARSE_OBJECT       *BufferOp;
1039     ACPI_PARSE_OBJECT       *DescriptorTypeOp;
1040     ACPI_PARSE_OBJECT       *LastOp = NULL;
1041     UINT32                  CurrentByteOffset = 0;
1042     ASL_RESOURCE_NODE       HeadRnode;
1043     ASL_RESOURCE_NODE       *PreviousRnode;
1044     ASL_RESOURCE_NODE       *Rnode;
1045     ASL_RESOURCE_INFO       Info;
1046     UINT8                   State;
1047 
1048 
1049     /* Mark parent as containing a resource template */
1050 
1051     if (Op->Asl.Parent)
1052     {
1053         Op->Asl.Parent->Asl.CompileFlags |= OP_IS_RESOURCE_DESC;
1054     }
1055 
1056     /* ResourceTemplate Opcode is first (Op) */
1057     /* Buffer Length node is first child */
1058 
1059     BufferLengthOp = ASL_GET_CHILD_NODE (Op);
1060 
1061     /* Buffer Op is first peer */
1062 
1063     BufferOp = ASL_GET_PEER_NODE (BufferLengthOp);
1064 
1065     /* First Descriptor type is next */
1066 
1067     DescriptorTypeOp = ASL_GET_PEER_NODE (BufferOp);
1068 
1069     /* DEFAULT_ARG indicates null template - ResourceTemplate(){} */
1070 
1071     if (DescriptorTypeOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
1072     {
1073         AslError (ASL_WARNING, ASL_MSG_NULL_RESOURCE_TEMPLATE,
1074             DescriptorTypeOp, DescriptorTypeOp->Asl.Value.String);
1075     }
1076 
1077     /*
1078      * Process all resource descriptors in the list
1079      * Note: It is assumed that the EndTag node has been automatically
1080      * inserted at the end of the template by the parser.
1081      */
1082     State = ACPI_RSTATE_NORMAL;
1083     PreviousRnode = &HeadRnode;
1084     while (DescriptorTypeOp)
1085     {
1086         /* Save information for optional mapfile */
1087 
1088         if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION)
1089         {
1090             Info.MappingOp = Op->Asl.Parent;
1091         }
1092         else
1093         {
1094             Info.MappingOp = DescriptorTypeOp;
1095         }
1096 
1097         Info.DescriptorTypeOp = DescriptorTypeOp;
1098         Info.CurrentByteOffset = CurrentByteOffset;
1099 
1100         DescriptorTypeOp->Asl.CompileFlags |= OP_IS_RESOURCE_DESC;
1101         Rnode = RsDoOneResourceDescriptor (&Info, &State);
1102 
1103         /*
1104          * Update current byte offset to indicate the number of bytes from the
1105          * start of the buffer. Buffer can include multiple descriptors, we
1106          * must keep track of the offset of not only each descriptor, but each
1107          * element (field) within each descriptor as well.
1108          */
1109         CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, Rnode);
1110 
1111         /* Get the next descriptor in the list */
1112 
1113         LastOp = DescriptorTypeOp;
1114         DescriptorTypeOp = ASL_GET_PEER_NODE (DescriptorTypeOp);
1115     }
1116 
1117     if (State == ACPI_RSTATE_DEPENDENT_LIST)
1118     {
1119         if (LastOp)
1120         {
1121             LastOp = LastOp->Asl.Parent;
1122         }
1123         AslError (ASL_ERROR, ASL_MSG_MISSING_ENDDEPENDENT, LastOp, NULL);
1124     }
1125 
1126     /*
1127      * Transform the nodes into the following
1128      *
1129      * Op           -> AML_BUFFER_OP
1130      * First Child  -> BufferLength
1131      * Second Child -> Descriptor Buffer (raw byte data)
1132      */
1133     Op->Asl.ParseOpcode               = PARSEOP_BUFFER;
1134     Op->Asl.AmlOpcode                 = AML_BUFFER_OP;
1135     Op->Asl.CompileFlags              = OP_AML_PACKAGE | OP_IS_RESOURCE_DESC;
1136     UtSetParseOpName (Op);
1137 
1138     BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
1139     BufferLengthOp->Asl.Value.Integer = CurrentByteOffset;
1140     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
1141     UtSetParseOpName (BufferLengthOp);
1142 
1143     BufferOp->Asl.ParseOpcode         = PARSEOP_RAW_DATA;
1144     BufferOp->Asl.AmlOpcode           = AML_RAW_DATA_CHAIN;
1145     BufferOp->Asl.AmlOpcodeLength     = 0;
1146     BufferOp->Asl.AmlLength           = CurrentByteOffset;
1147     BufferOp->Asl.Value.Buffer        = ACPI_CAST_PTR (UINT8,  HeadRnode.Next);
1148     BufferOp->Asl.CompileFlags       |= OP_IS_RESOURCE_DATA;
1149     UtSetParseOpName (BufferOp);
1150 
1151     return;
1152 }
1153