xref: /freebsd/sys/contrib/dev/acpica/compiler/aslresource.c (revision 5956d97f4b3204318ceb6aa9c77bd0bc6ea87a41)
1 /******************************************************************************
2  *
3  * Module Name: aslresource - Resource template/descriptor utilities
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2022, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************
115  *
116  * Alternatively, you may choose to be licensed under the terms of the
117  * following license:
118  *
119  * Redistribution and use in source and binary forms, with or without
120  * modification, are permitted provided that the following conditions
121  * are met:
122  * 1. Redistributions of source code must retain the above copyright
123  *    notice, this list of conditions, and the following disclaimer,
124  *    without modification.
125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126  *    substantially similar to the "NO WARRANTY" disclaimer below
127  *    ("Disclaimer") and any redistribution must be conditioned upon
128  *    including a substantially similar Disclaimer requirement for further
129  *    binary redistribution.
130  * 3. Neither the names of the above-listed copyright holders nor the names
131  *    of any contributors may be used to endorse or promote products derived
132  *    from this software without specific prior written permission.
133  *
134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145  *
146  * Alternatively, you may choose to be licensed under the terms of the
147  * GNU General Public License ("GPL") version 2 as published by the Free
148  * Software Foundation.
149  *
150  *****************************************************************************/
151 
152 #include <contrib/dev/acpica/compiler/aslcompiler.h>
153 #include "aslcompiler.y.h"
154 #include <contrib/dev/acpica/include/amlcode.h>
155 
156 
157 #define _COMPONENT          ACPI_COMPILER
158         ACPI_MODULE_NAME    ("aslresource")
159 
160 
161 /*******************************************************************************
162  *
163  * FUNCTION:    RsSmallAddressCheck
164  *
165  * PARAMETERS:  Minimum             - Address Min value
166  *              Maximum             - Address Max value
167  *              Length              - Address range value
168  *              Alignment           - Address alignment value
169  *              MinOp               - Original Op for Address Min
170  *              MaxOp               - Original Op for Address Max
171  *              LengthOp            - Original Op for address range
172  *              AlignOp             - Original Op for address alignment. If
173  *                                    NULL, means "zero value for alignment is
174  *                                    OK, and means 64K alignment" (for
175  *                                    Memory24 descriptor)
176  *              Op                  - Parent Op for entire construct
177  *
178  * RETURN:      None. Adds error messages to error log if necessary
179  *
180  * DESCRIPTION: Perform common value checks for "small" address descriptors.
181  *              Currently:
182  *                  Io, Memory24, Memory32
183  *
184  ******************************************************************************/
185 
186 void
187 RsSmallAddressCheck (
188     UINT8                   Type,
189     UINT32                  Minimum,
190     UINT32                  Maximum,
191     UINT32                  Length,
192     UINT32                  Alignment,
193     ACPI_PARSE_OBJECT       *MinOp,
194     ACPI_PARSE_OBJECT       *MaxOp,
195     ACPI_PARSE_OBJECT       *LengthOp,
196     ACPI_PARSE_OBJECT       *AlignOp,
197     ACPI_PARSE_OBJECT       *Op)
198 {
199 
200     if (AslGbl_NoResourceChecking)
201     {
202         return;
203     }
204 
205     /*
206      * Check for a so-called "null descriptor". These are descriptors that are
207      * created with most fields set to zero. The intent is that the descriptor
208      * will be updated/completed at runtime via a BufferField.
209      *
210      * If the descriptor does NOT have a resource tag, it cannot be referenced
211      * by a BufferField and we will flag this as an error. Conversely, if
212      * the descriptor has a resource tag, we will assume that a BufferField
213      * will be used to dynamically update it, so no error.
214      *
215      * A possible enhancement to this check would be to verify that in fact
216      * a BufferField is created using the resource tag, and perhaps even
217      * verify that a Store is performed to the BufferField.
218      *
219      * Note: for these descriptors, Alignment is allowed to be zero
220      */
221     if (!Minimum && !Maximum && !Length)
222     {
223         if (!Op->Asl.ExternalName)
224         {
225             /* No resource tag. Descriptor is fixed and is also illegal */
226 
227             AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL);
228         }
229 
230         return;
231     }
232 
233     /*
234      * Range checks for Memory24 and Memory32.
235      * IO descriptor has different definition of min/max, don't check.
236      */
237     if (Type != ACPI_RESOURCE_NAME_IO)
238     {
239         /* Basic checks on Min/Max/Length */
240 
241         if (Minimum > Maximum)
242         {
243             AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL);
244         }
245         else if (Length > (Maximum - Minimum + 1))
246         {
247             AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL);
248         }
249 
250         /* Special case for Memory24, min/max values are compressed */
251 
252         if (Type == ACPI_RESOURCE_NAME_MEMORY24)
253         {
254             if (!Alignment) /* Alignment==0 means 64K alignment */
255             {
256                 Alignment = ACPI_UINT16_MAX + 1;
257             }
258 
259             Minimum <<= 8;
260             Maximum <<= 8;
261         }
262     }
263 
264     /* Alignment of zero is not in ACPI spec, but is used to mean byte acc */
265 
266     if (!Alignment)
267     {
268         Alignment = 1;
269     }
270 
271     /* Addresses must be an exact multiple of the alignment value */
272 
273     if (Minimum % Alignment)
274     {
275         AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL);
276     }
277     if (Maximum % Alignment)
278     {
279         AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, NULL);
280     }
281 }
282 
283 
284 /*******************************************************************************
285  *
286  * FUNCTION:    RsLargeAddressCheck
287  *
288  * PARAMETERS:  Minimum             - Address Min value
289  *              Maximum             - Address Max value
290  *              Length              - Address range value
291  *              Granularity         - Address granularity value
292  *              Flags               - General flags for address descriptors:
293  *                                    _MIF, _MAF, _DEC
294  *              MinOp               - Original Op for Address Min
295  *              MaxOp               - Original Op for Address Max
296  *              LengthOp            - Original Op for address range
297  *              GranOp              - Original Op for address granularity
298  *              Op                  - Parent Op for entire construct
299  *
300  * RETURN:      None. Adds error messages to error log if necessary
301  *
302  * DESCRIPTION: Perform common value checks for "large" address descriptors.
303  *              Currently:
304  *                  WordIo,     WordBusNumber,  WordSpace
305  *                  DWordIo,    DWordMemory,    DWordSpace
306  *                  QWordIo,    QWordMemory,    QWordSpace
307  *                  ExtendedIo, ExtendedMemory, ExtendedSpace
308  *
309  * _MIF flag set means that the minimum address is fixed and is not relocatable
310  * _MAF flag set means that the maximum address is fixed and is not relocatable
311  * Length of zero means that the record size is variable
312  *
313  * This function implements the LEN/MIF/MAF/MIN/MAX/GRA rules within Table 6-40
314  * of the ACPI 4.0a specification. Added 04/2010.
315  *
316  ******************************************************************************/
317 
318 void
319 RsLargeAddressCheck (
320     UINT64                  Minimum,
321     UINT64                  Maximum,
322     UINT64                  Length,
323     UINT64                  Granularity,
324     UINT8                   Flags,
325     ACPI_PARSE_OBJECT       *MinOp,
326     ACPI_PARSE_OBJECT       *MaxOp,
327     ACPI_PARSE_OBJECT       *LengthOp,
328     ACPI_PARSE_OBJECT       *GranOp,
329     ACPI_PARSE_OBJECT       *Op)
330 {
331 
332     if (AslGbl_NoResourceChecking)
333     {
334         return;
335     }
336 
337     /*
338      * Check for a so-called "null descriptor". These are descriptors that are
339      * created with most fields set to zero. The intent is that the descriptor
340      * will be updated/completed at runtime via a BufferField.
341      *
342      * If the descriptor does NOT have a resource tag, it cannot be referenced
343      * by a BufferField and we will flag this as an error. Conversely, if
344      * the descriptor has a resource tag, we will assume that a BufferField
345      * will be used to dynamically update it, so no error.
346      *
347      * A possible enhancement to this check would be to verify that in fact
348      * a BufferField is created using the resource tag, and perhaps even
349      * verify that a Store is performed to the BufferField.
350      */
351     if (!Minimum && !Maximum && !Length && !Granularity)
352     {
353         if (!Op->Asl.ExternalName)
354         {
355             /* No resource tag. Descriptor is fixed and is also illegal */
356 
357             AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL);
358         }
359 
360         return;
361     }
362 
363     /* Basic checks on Min/Max/Length */
364 
365     if (Minimum > Maximum)
366     {
367         AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL);
368         return;
369     }
370     else if (Length > (Maximum - Minimum + 1))
371     {
372         AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL);
373         return;
374     }
375 
376     /* If specified (non-zero), ensure granularity is a power-of-two minus one */
377 
378     if (Granularity)
379     {
380         if ((Granularity + 1) &
381              Granularity)
382         {
383             AslError (ASL_ERROR, ASL_MSG_INVALID_GRANULARITY, GranOp, NULL);
384             return;
385         }
386     }
387 
388     /*
389      * Check the various combinations of Length, MinFixed, and MaxFixed
390      */
391     if (Length)
392     {
393         /* Fixed non-zero length */
394 
395         switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF))
396         {
397         case 0:
398             /*
399              * Fixed length, variable locations (both _MIN and _MAX).
400              * Length must be a multiple of granularity
401              */
402             if (Granularity & Length)
403             {
404                 AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, LengthOp, NULL);
405             }
406             break;
407 
408         case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF):
409 
410             /* Fixed length, fixed location. Granularity must be zero */
411 
412             if (Granularity != 0)
413             {
414                 AslError (ASL_ERROR, ASL_MSG_INVALID_GRAN_FIXED, GranOp, NULL);
415             }
416 
417             /* Length must be exactly the size of the min/max window */
418 
419             if (Length != (Maximum - Minimum + 1))
420             {
421                 AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH_FIXED, LengthOp, NULL);
422             }
423             break;
424 
425         /* All other combinations are invalid */
426 
427         case ACPI_RESOURCE_FLAG_MIF:
428         case ACPI_RESOURCE_FLAG_MAF:
429         default:
430 
431             AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL);
432         }
433     }
434     else
435     {
436         /* Variable length (length==0) */
437 
438         switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF))
439         {
440         case 0:
441             /*
442              * Both _MIN and _MAX are variable.
443              * No additional requirements, just exit
444              */
445             break;
446 
447         case ACPI_RESOURCE_FLAG_MIF:
448 
449             /* _MIN is fixed. _MIN must be multiple of _GRA */
450 
451             /*
452              * The granularity is defined by the ACPI specification to be a
453              * power-of-two minus one, therefore the granularity is a
454              * bitmask which can be used to easily validate the addresses.
455              */
456             if (Granularity & Minimum)
457             {
458                 AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL);
459             }
460             break;
461 
462         case ACPI_RESOURCE_FLAG_MAF:
463 
464             /* _MAX is fixed. (_MAX + 1) must be multiple of _GRA */
465 
466             if (Granularity & (Maximum + 1))
467             {
468                 AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, "-1");
469             }
470             break;
471 
472         /* Both MIF/MAF set is invalid if length is zero */
473 
474         case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF):
475         default:
476 
477             AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL);
478         }
479     }
480 }
481 
482 
483 /*******************************************************************************
484  *
485  * FUNCTION:    RsGetStringDataLength
486  *
487  * PARAMETERS:  InitializerOp     - Start of a subtree of init nodes
488  *
489  * RETURN:      Valid string length if a string node is found (otherwise 0)
490  *
491  * DESCRIPTION: In a list of peer nodes, find the first one that contains a
492  *              string and return the length of the string.
493  *
494  ******************************************************************************/
495 
496 UINT16
497 RsGetStringDataLength (
498     ACPI_PARSE_OBJECT       *InitializerOp)
499 {
500 
501     while (InitializerOp)
502     {
503         if (InitializerOp->Asl.ParseOpcode == PARSEOP_STRING_LITERAL)
504         {
505             return ((UINT16) (strlen (InitializerOp->Asl.Value.String) + 1));
506         }
507 
508         InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
509     }
510 
511     return (0);
512 }
513 
514 
515 /*******************************************************************************
516  *
517  * FUNCTION:    RsAllocateResourceNode
518  *
519  * PARAMETERS:  Size        - Size of node in bytes
520  *
521  * RETURN:      The allocated node - aborts on allocation failure
522  *
523  * DESCRIPTION: Allocate a resource description node and the resource
524  *              descriptor itself (the nodes are used to link descriptors).
525  *
526  ******************************************************************************/
527 
528 ASL_RESOURCE_NODE *
529 RsAllocateResourceNode (
530     UINT32                  Size)
531 {
532     ASL_RESOURCE_NODE       *Rnode;
533 
534 
535     /* Allocate the node */
536 
537     Rnode = UtLocalCalloc (sizeof (ASL_RESOURCE_NODE));
538 
539     /* Allocate the resource descriptor itself */
540 
541     Rnode->Buffer = UtLocalCalloc (Size);
542     Rnode->BufferLength = Size;
543     return (Rnode);
544 }
545 
546 
547 /*******************************************************************************
548  *
549  * FUNCTION:    RsCreateResourceField
550  *
551  * PARAMETERS:  Op              - Resource field node
552  *              Name            - Name of the field (Used only to reference
553  *                                the field in the ASL, not in the AML)
554  *              ByteOffset      - Offset from the field start
555  *              BitOffset       - Additional bit offset
556  *              BitLength       - Number of bits in the field
557  *
558  * RETURN:      None, sets fields within the input node
559  *
560  * DESCRIPTION: Utility function to generate a named bit field within a
561  *              resource descriptor. Mark a node as 1) a field in a resource
562  *              descriptor, and 2) set the value to be a BIT offset
563  *
564  ******************************************************************************/
565 
566 void
567 RsCreateResourceField (
568     ACPI_PARSE_OBJECT       *Op,
569     char                    *Name,
570     UINT32                  ByteOffset,
571     UINT32                  BitOffset,
572     UINT32                  BitLength)
573 {
574 
575     Op->Asl.ExternalName = Name;
576     Op->Asl.CompileFlags |= OP_IS_RESOURCE_FIELD;
577 
578     Op->Asl.Value.Tag.BitOffset = (ByteOffset * 8) + BitOffset;
579     Op->Asl.Value.Tag.BitLength = BitLength;
580 }
581 
582 
583 /*******************************************************************************
584  *
585  * FUNCTION:    RsSetFlagBits
586  *
587  * PARAMETERS:  *Flags          - Pointer to the flag byte
588  *              Op              - Flag initialization node
589  *              Position        - Bit position within the flag byte
590  *              Default         - Used if the node is DEFAULT.
591  *
592  * RETURN:      Sets bits within the *Flags output byte.
593  *
594  * DESCRIPTION: Set a bit in a cumulative flags word from an initialization
595  *              node. Will use a default value if the node is DEFAULT, meaning
596  *              that no value was specified in the ASL. Used to merge multiple
597  *              keywords into a single flags byte.
598  *
599  ******************************************************************************/
600 
601 void
602 RsSetFlagBits (
603     UINT8                   *Flags,
604     ACPI_PARSE_OBJECT       *Op,
605     UINT8                   Position,
606     UINT8                   DefaultBit)
607 {
608 
609     if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
610     {
611         /* Use the default bit */
612 
613         *Flags |= (DefaultBit << Position);
614     }
615     else
616     {
617         /* Use the bit specified in the initialization node */
618 
619         *Flags |= (((UINT8) Op->Asl.Value.Integer) << Position);
620     }
621 }
622 
623 
624 void
625 RsSetFlagBits16 (
626     UINT16                  *Flags,
627     ACPI_PARSE_OBJECT       *Op,
628     UINT8                   Position,
629     UINT8                   DefaultBit)
630 {
631 
632     if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
633     {
634         /* Use the default bit */
635 
636         *Flags |= (DefaultBit << Position);
637     }
638     else
639     {
640         /* Use the bit specified in the initialization node */
641 
642         *Flags |= (((UINT16) Op->Asl.Value.Integer) << Position);
643     }
644 }
645 
646 
647 /*******************************************************************************
648  *
649  * FUNCTION:    RsCompleteNodeAndGetNext
650  *
651  * PARAMETERS:  Op            - Resource node to be completed
652  *
653  * RETURN:      The next peer to the input node.
654  *
655  * DESCRIPTION: Mark the current node completed and return the next peer.
656  *              The node ParseOpcode is set to DEFAULT_ARG, meaning that
657  *              this node is to be ignored from now on.
658  *
659  ******************************************************************************/
660 
661 ACPI_PARSE_OBJECT *
662 RsCompleteNodeAndGetNext (
663     ACPI_PARSE_OBJECT       *Op)
664 {
665 
666     /* Mark this node unused */
667 
668     Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
669 
670     /* Move on to the next peer node in the initializer list */
671 
672     return (ASL_GET_PEER_NODE (Op));
673 }
674 
675 
676 /*******************************************************************************
677  *
678  * FUNCTION:    RsCheckListForDuplicates
679  *
680  * PARAMETERS:  Op                  - First op in the initializer list
681  *
682  * RETURN:      None
683  *
684  * DESCRIPTION: Check an initializer list for duplicate values. Emits an error
685  *              if any duplicates are found.
686  *
687  ******************************************************************************/
688 
689 void
690 RsCheckListForDuplicates (
691     ACPI_PARSE_OBJECT       *Op)
692 {
693     ACPI_PARSE_OBJECT       *NextValueOp = Op;
694     ACPI_PARSE_OBJECT       *NextOp;
695     UINT32                  Value;
696 
697 
698     if (!Op)
699     {
700         return;
701     }
702 
703     /* Search list once for each value in the list */
704 
705     while (NextValueOp)
706     {
707         Value = (UINT32) NextValueOp->Asl.Value.Integer;
708 
709         /* Compare this value to all remaining values in the list */
710 
711         NextOp = ASL_GET_PEER_NODE (NextValueOp);
712         while (NextOp)
713         {
714             if (NextOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
715             {
716                 /* Compare values */
717 
718                 if (Value == (UINT32) NextOp->Asl.Value.Integer)
719                 {
720                     /* Emit error only once per duplicate node */
721 
722                     if (!(NextOp->Asl.CompileFlags & OP_IS_DUPLICATE))
723                     {
724                         NextOp->Asl.CompileFlags |= OP_IS_DUPLICATE;
725                         AslError (ASL_ERROR, ASL_MSG_DUPLICATE_ITEM,
726                             NextOp, NULL);
727                     }
728                 }
729             }
730 
731             NextOp = ASL_GET_PEER_NODE (NextOp);
732         }
733 
734         NextValueOp = ASL_GET_PEER_NODE (NextValueOp);
735     }
736 }
737 
738 
739 /*******************************************************************************
740  *
741  * FUNCTION:    RsDoOneResourceDescriptor
742  *
743  * PARAMETERS:  DescriptorTypeOp    - Parent parse node of the descriptor
744  *              CurrentByteOffset   - Offset in the resource descriptor
745  *                                    buffer.
746  *
747  * RETURN:      A valid resource node for the descriptor
748  *
749  * DESCRIPTION: Dispatches the processing of one resource descriptor
750  *
751  ******************************************************************************/
752 
753 ASL_RESOURCE_NODE *
754 RsDoOneResourceDescriptor (
755     ASL_RESOURCE_INFO       *Info,
756     UINT8                   *State)
757 {
758     ASL_RESOURCE_NODE       *Rnode = NULL;
759 
760 
761     /* Construct the resource */
762 
763     switch (Info->DescriptorTypeOp->Asl.ParseOpcode)
764     {
765     case PARSEOP_DMA:
766 
767         Rnode = RsDoDmaDescriptor (Info);
768         break;
769 
770     case PARSEOP_FIXEDDMA:
771 
772         Rnode = RsDoFixedDmaDescriptor (Info);
773         break;
774 
775     case PARSEOP_DWORDIO:
776 
777         Rnode = RsDoDwordIoDescriptor (Info);
778         break;
779 
780     case PARSEOP_DWORDMEMORY:
781 
782         Rnode = RsDoDwordMemoryDescriptor (Info);
783         break;
784 
785     case PARSEOP_DWORDSPACE:
786 
787         Rnode = RsDoDwordSpaceDescriptor (Info);
788         break;
789 
790     case PARSEOP_ENDDEPENDENTFN:
791 
792         switch (*State)
793         {
794         case ACPI_RSTATE_NORMAL:
795 
796             AslError (ASL_ERROR, ASL_MSG_MISSING_STARTDEPENDENT,
797                 Info->DescriptorTypeOp, NULL);
798             break;
799 
800         case ACPI_RSTATE_START_DEPENDENT:
801 
802             AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
803                 Info->DescriptorTypeOp, NULL);
804             break;
805 
806         case ACPI_RSTATE_DEPENDENT_LIST:
807         default:
808 
809             break;
810         }
811 
812         *State = ACPI_RSTATE_NORMAL;
813         Rnode = RsDoEndDependentDescriptor (Info);
814         break;
815 
816     case PARSEOP_ENDTAG:
817 
818         Rnode = RsDoEndTagDescriptor (Info);
819         break;
820 
821     case PARSEOP_EXTENDEDIO:
822 
823         Rnode = RsDoExtendedIoDescriptor (Info);
824         break;
825 
826     case PARSEOP_EXTENDEDMEMORY:
827 
828         Rnode = RsDoExtendedMemoryDescriptor (Info);
829         break;
830 
831     case PARSEOP_EXTENDEDSPACE:
832 
833         Rnode = RsDoExtendedSpaceDescriptor (Info);
834         break;
835 
836     case PARSEOP_FIXEDIO:
837 
838         Rnode = RsDoFixedIoDescriptor (Info);
839         break;
840 
841     case PARSEOP_INTERRUPT:
842 
843         Rnode = RsDoInterruptDescriptor (Info);
844         break;
845 
846     case PARSEOP_IO:
847 
848         Rnode = RsDoIoDescriptor (Info);
849         break;
850 
851     case PARSEOP_IRQ:
852 
853         Rnode = RsDoIrqDescriptor (Info);
854         break;
855 
856     case PARSEOP_IRQNOFLAGS:
857 
858         Rnode = RsDoIrqNoFlagsDescriptor (Info);
859         break;
860 
861     case PARSEOP_MEMORY24:
862 
863         Rnode = RsDoMemory24Descriptor (Info);
864         break;
865 
866     case PARSEOP_MEMORY32:
867 
868         Rnode = RsDoMemory32Descriptor (Info);
869         break;
870 
871     case PARSEOP_MEMORY32FIXED:
872 
873         Rnode = RsDoMemory32FixedDescriptor (Info);
874         break;
875 
876     case PARSEOP_QWORDIO:
877 
878         Rnode = RsDoQwordIoDescriptor (Info);
879         break;
880 
881     case PARSEOP_QWORDMEMORY:
882 
883         Rnode = RsDoQwordMemoryDescriptor (Info);
884         break;
885 
886     case PARSEOP_QWORDSPACE:
887 
888         Rnode = RsDoQwordSpaceDescriptor (Info);
889         break;
890 
891     case PARSEOP_REGISTER:
892 
893         Rnode = RsDoGeneralRegisterDescriptor (Info);
894         break;
895 
896     case PARSEOP_STARTDEPENDENTFN:
897 
898         switch (*State)
899         {
900         case ACPI_RSTATE_START_DEPENDENT:
901 
902             AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
903                 Info->DescriptorTypeOp, NULL);
904             break;
905 
906         case ACPI_RSTATE_NORMAL:
907         case ACPI_RSTATE_DEPENDENT_LIST:
908         default:
909 
910             break;
911         }
912 
913         *State = ACPI_RSTATE_START_DEPENDENT;
914         Rnode = RsDoStartDependentDescriptor (Info);
915         *State = ACPI_RSTATE_DEPENDENT_LIST;
916         break;
917 
918     case PARSEOP_STARTDEPENDENTFN_NOPRI:
919 
920         switch (*State)
921         {
922         case ACPI_RSTATE_START_DEPENDENT:
923 
924             AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
925                 Info->DescriptorTypeOp, NULL);
926             break;
927 
928         case ACPI_RSTATE_NORMAL:
929         case ACPI_RSTATE_DEPENDENT_LIST:
930         default:
931 
932             break;
933         }
934 
935         *State = ACPI_RSTATE_START_DEPENDENT;
936         Rnode = RsDoStartDependentNoPriDescriptor (Info);
937         *State = ACPI_RSTATE_DEPENDENT_LIST;
938         break;
939 
940     case PARSEOP_VENDORLONG:
941 
942         Rnode = RsDoVendorLargeDescriptor (Info);
943         break;
944 
945     case PARSEOP_VENDORSHORT:
946 
947         Rnode = RsDoVendorSmallDescriptor (Info);
948         break;
949 
950     case PARSEOP_WORDBUSNUMBER:
951 
952         Rnode = RsDoWordBusNumberDescriptor (Info);
953         break;
954 
955     case PARSEOP_WORDIO:
956 
957         Rnode = RsDoWordIoDescriptor (Info);
958         break;
959 
960     case PARSEOP_WORDSPACE:
961 
962         Rnode = RsDoWordSpaceDescriptor (Info);
963         break;
964 
965     case PARSEOP_GPIO_INT:
966 
967         Rnode = RsDoGpioIntDescriptor (Info);
968         break;
969 
970     case PARSEOP_GPIO_IO:
971 
972         Rnode = RsDoGpioIoDescriptor (Info);
973         break;
974 
975     case PARSEOP_I2C_SERIALBUS:
976     case PARSEOP_I2C_SERIALBUS_V2:
977 
978         Rnode = RsDoI2cSerialBusDescriptor (Info);
979         break;
980 
981     case PARSEOP_SPI_SERIALBUS:
982     case PARSEOP_SPI_SERIALBUS_V2:
983 
984         Rnode = RsDoSpiSerialBusDescriptor (Info);
985         break;
986 
987     case PARSEOP_UART_SERIALBUS:
988     case PARSEOP_UART_SERIALBUS_V2:
989 
990         Rnode = RsDoUartSerialBusDescriptor (Info);
991         break;
992 
993     case PARSEOP_CSI2_SERIALBUS:
994 
995         Rnode = RsDoCsi2SerialBusDescriptor (Info);
996         break;
997 
998     case PARSEOP_PINCONFIG:
999 
1000         Rnode = RsDoPinConfigDescriptor (Info);
1001         break;
1002 
1003     case PARSEOP_PINFUNCTION:
1004 
1005         Rnode = RsDoPinFunctionDescriptor (Info);
1006         break;
1007 
1008     case PARSEOP_PINGROUP:
1009 
1010         Rnode = RsDoPinGroupDescriptor (Info);
1011         break;
1012 
1013     case PARSEOP_PINGROUPFUNCTION:
1014 
1015         Rnode = RsDoPinGroupFunctionDescriptor (Info);
1016         break;
1017 
1018     case PARSEOP_PINGROUPCONFIG:
1019 
1020         Rnode = RsDoPinGroupConfigDescriptor (Info);
1021         break;
1022 
1023     case PARSEOP_DEFAULT_ARG:
1024 
1025         /* Just ignore any of these, they are used as fillers/placeholders */
1026         break;
1027 
1028     default:
1029 
1030         printf ("Unknown resource descriptor type [%s]\n",
1031             Info->DescriptorTypeOp->Asl.ParseOpName);
1032         break;
1033     }
1034 
1035     /*
1036      * Mark original node as unused, but head of a resource descriptor.
1037      * This allows the resource to be installed in the namespace so that
1038      * references to the descriptor can be resolved.
1039      */
1040     Info->DescriptorTypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1041     Info->DescriptorTypeOp->Asl.CompileFlags = OP_IS_RESOURCE_DESC;
1042     Info->DescriptorTypeOp->Asl.Value.Integer = Info->CurrentByteOffset;
1043 
1044     if (Rnode)
1045     {
1046         Info->DescriptorTypeOp->Asl.FinalAmlLength = Rnode->BufferLength;
1047         Info->DescriptorTypeOp->Asl.Extra =
1048             ((AML_RESOURCE *) Rnode->Buffer)->DescriptorType;
1049     }
1050 
1051     return (Rnode);
1052 }
1053 
1054 
1055 /*******************************************************************************
1056  *
1057  * FUNCTION:    RsLinkDescriptorChain
1058  *
1059  * PARAMETERS:  PreviousRnode       - Pointer to the node that will be previous
1060  *                                    to the linked node,  At exit, set to the
1061  *                                    last node in the new chain.
1062  *              Rnode               - Resource node to link into the list
1063  *
1064  * RETURN:      Cumulative buffer byte offset of the new segment of chain
1065  *
1066  * DESCRIPTION: Link a descriptor chain at the end of an existing chain.
1067  *
1068  ******************************************************************************/
1069 
1070 UINT32
1071 RsLinkDescriptorChain (
1072     ASL_RESOURCE_NODE       **PreviousRnode,
1073     ASL_RESOURCE_NODE       *Rnode)
1074 {
1075     ASL_RESOURCE_NODE       *LastRnode;
1076     UINT32                  CurrentByteOffset;
1077 
1078 
1079     /* Anything to do? */
1080 
1081     if (!Rnode)
1082     {
1083         return (0);
1084     }
1085 
1086     /* Point the previous node to the new node */
1087 
1088     (*PreviousRnode)->Next = Rnode;
1089     CurrentByteOffset = Rnode->BufferLength;
1090 
1091     /* Walk to the end of the chain headed by Rnode */
1092 
1093     LastRnode = Rnode;
1094     while (LastRnode->Next)
1095     {
1096         LastRnode = LastRnode->Next;
1097         CurrentByteOffset += LastRnode->BufferLength;
1098     }
1099 
1100     /* Previous node becomes the last node in the chain */
1101 
1102     *PreviousRnode = LastRnode;
1103     return (CurrentByteOffset);
1104 }
1105 
1106 
1107 /*******************************************************************************
1108  *
1109  * FUNCTION:    RsDoResourceTemplate
1110  *
1111  * PARAMETERS:  Op        - Parent of a resource template list
1112  *
1113  * RETURN:      None. Sets input node to point to a list of AML code
1114  *
1115  * DESCRIPTION: Merge a list of resource descriptors into a single AML buffer,
1116  *              in preparation for output to the AML output file.
1117  *
1118  ******************************************************************************/
1119 
1120 void
1121 RsDoResourceTemplate (
1122     ACPI_PARSE_OBJECT       *Op)
1123 {
1124     ACPI_PARSE_OBJECT       *BufferLengthOp;
1125     ACPI_PARSE_OBJECT       *BufferOp;
1126     ACPI_PARSE_OBJECT       *DescriptorTypeOp;
1127     ACPI_PARSE_OBJECT       *LastOp = NULL;
1128     UINT32                  CurrentByteOffset = 0;
1129     ASL_RESOURCE_NODE       HeadRnode;
1130     ASL_RESOURCE_NODE       *PreviousRnode;
1131     ASL_RESOURCE_NODE       *Rnode;
1132     ASL_RESOURCE_INFO       Info;
1133     UINT8                   State;
1134 
1135 
1136     /* Mark parent as containing a resource template */
1137 
1138     if (Op->Asl.Parent)
1139     {
1140         Op->Asl.Parent->Asl.CompileFlags |= OP_IS_RESOURCE_DESC;
1141     }
1142 
1143     /* ResourceTemplate Opcode is first (Op) */
1144     /* Buffer Length node is first child */
1145 
1146     BufferLengthOp = ASL_GET_CHILD_NODE (Op);
1147 
1148     /* Buffer Op is first peer */
1149 
1150     BufferOp = ASL_GET_PEER_NODE (BufferLengthOp);
1151 
1152     /* First Descriptor type is next */
1153 
1154     DescriptorTypeOp = ASL_GET_PEER_NODE (BufferOp);
1155 
1156     /* DEFAULT_ARG indicates null template - ResourceTemplate(){} */
1157 
1158     if (DescriptorTypeOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
1159     {
1160         AslError (ASL_WARNING, ASL_MSG_NULL_RESOURCE_TEMPLATE,
1161             DescriptorTypeOp, DescriptorTypeOp->Asl.Value.String);
1162     }
1163 
1164     /*
1165      * Process all resource descriptors in the list
1166      * Note: It is assumed that the EndTag node has been automatically
1167      * inserted at the end of the template by the parser.
1168      */
1169     State = ACPI_RSTATE_NORMAL;
1170     PreviousRnode = &HeadRnode;
1171     while (DescriptorTypeOp)
1172     {
1173         /* Save information for optional mapfile */
1174 
1175         if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION)
1176         {
1177             Info.MappingOp = Op->Asl.Parent;
1178         }
1179         else
1180         {
1181             Info.MappingOp = DescriptorTypeOp;
1182         }
1183 
1184         Info.DescriptorTypeOp = DescriptorTypeOp;
1185         Info.CurrentByteOffset = CurrentByteOffset;
1186 
1187         DescriptorTypeOp->Asl.CompileFlags |= OP_IS_RESOURCE_DESC;
1188         Rnode = RsDoOneResourceDescriptor (&Info, &State);
1189 
1190         /*
1191          * Update current byte offset to indicate the number of bytes from the
1192          * start of the buffer. Buffer can include multiple descriptors, we
1193          * must keep track of the offset of not only each descriptor, but each
1194          * element (field) within each descriptor as well.
1195          */
1196         CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, Rnode);
1197 
1198         /* Get the next descriptor in the list */
1199 
1200         LastOp = DescriptorTypeOp;
1201         DescriptorTypeOp = ASL_GET_PEER_NODE (DescriptorTypeOp);
1202     }
1203 
1204     if (State == ACPI_RSTATE_DEPENDENT_LIST)
1205     {
1206         if (LastOp)
1207         {
1208             LastOp = LastOp->Asl.Parent;
1209         }
1210         AslError (ASL_ERROR, ASL_MSG_MISSING_ENDDEPENDENT, LastOp, NULL);
1211     }
1212 
1213     /*
1214      * Transform the nodes into the following
1215      *
1216      * Op           -> AML_BUFFER_OP
1217      * First Child  -> BufferLength
1218      * Second Child -> Descriptor Buffer (raw byte data)
1219      */
1220     Op->Asl.ParseOpcode               = PARSEOP_BUFFER;
1221     Op->Asl.AmlOpcode                 = AML_BUFFER_OP;
1222     Op->Asl.CompileFlags              = OP_AML_PACKAGE | OP_IS_RESOURCE_DESC;
1223     UtSetParseOpName (Op);
1224 
1225     BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
1226     BufferLengthOp->Asl.Value.Integer = CurrentByteOffset;
1227     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
1228     UtSetParseOpName (BufferLengthOp);
1229 
1230     BufferOp->Asl.ParseOpcode         = PARSEOP_RAW_DATA;
1231     BufferOp->Asl.AmlOpcode           = AML_RAW_DATA_CHAIN;
1232     BufferOp->Asl.AmlOpcodeLength     = 0;
1233     BufferOp->Asl.AmlLength           = CurrentByteOffset;
1234     BufferOp->Asl.Value.Buffer        = ACPI_CAST_PTR (UINT8,  HeadRnode.Next);
1235     BufferOp->Asl.CompileFlags       |= OP_IS_RESOURCE_DATA;
1236     UtSetParseOpName (BufferOp);
1237 
1238     return;
1239 }
1240