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 - 2023, 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 "aslcompiler.h"
153 #include "aslcompiler.y.h"
154 #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
RsSmallAddressCheck(UINT8 Type,UINT32 Minimum,UINT32 Maximum,UINT32 Length,UINT32 Alignment,ACPI_PARSE_OBJECT * MinOp,ACPI_PARSE_OBJECT * MaxOp,ACPI_PARSE_OBJECT * LengthOp,ACPI_PARSE_OBJECT * AlignOp,ACPI_PARSE_OBJECT * Op)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
RsLargeAddressCheck(UINT64 Minimum,UINT64 Maximum,UINT64 Length,UINT64 Granularity,UINT8 Flags,ACPI_PARSE_OBJECT * MinOp,ACPI_PARSE_OBJECT * MaxOp,ACPI_PARSE_OBJECT * LengthOp,ACPI_PARSE_OBJECT * GranOp,ACPI_PARSE_OBJECT * Op)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
RsGetStringDataLength(ACPI_PARSE_OBJECT * InitializerOp)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 *
RsAllocateResourceNode(UINT32 Size)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
RsCreateResourceField(ACPI_PARSE_OBJECT * Op,char * Name,UINT32 ByteOffset,UINT32 BitOffset,UINT32 BitLength)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
RsSetFlagBits(UINT8 * Flags,ACPI_PARSE_OBJECT * Op,UINT8 Position,UINT8 DefaultBit)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
RsSetFlagBits16(UINT16 * Flags,ACPI_PARSE_OBJECT * Op,UINT8 Position,UINT8 DefaultBit)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 *
RsCompleteNodeAndGetNext(ACPI_PARSE_OBJECT * Op)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
RsCheckListForDuplicates(ACPI_PARSE_OBJECT * Op)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 *
RsDoOneResourceDescriptor(ASL_RESOURCE_INFO * Info,UINT8 * State)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 
766     case PARSEOP_CLOCKINPUT:
767 
768         Rnode = RsDoClockInputDescriptor(Info);
769         break;
770 
771     case PARSEOP_DMA:
772 
773         Rnode = RsDoDmaDescriptor (Info);
774         break;
775 
776     case PARSEOP_FIXEDDMA:
777 
778         Rnode = RsDoFixedDmaDescriptor (Info);
779         break;
780 
781     case PARSEOP_DWORDIO:
782 
783         Rnode = RsDoDwordIoDescriptor (Info);
784         break;
785 
786     case PARSEOP_DWORDMEMORY:
787 
788         Rnode = RsDoDwordMemoryDescriptor (Info);
789         break;
790 
791     case PARSEOP_DWORDSPACE:
792 
793         Rnode = RsDoDwordSpaceDescriptor (Info);
794         break;
795 
796     case PARSEOP_ENDDEPENDENTFN:
797 
798         switch (*State)
799         {
800         case ACPI_RSTATE_NORMAL:
801 
802             AslError (ASL_ERROR, ASL_MSG_MISSING_STARTDEPENDENT,
803                 Info->DescriptorTypeOp, NULL);
804             break;
805 
806         case ACPI_RSTATE_START_DEPENDENT:
807 
808             AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
809                 Info->DescriptorTypeOp, NULL);
810             break;
811 
812         case ACPI_RSTATE_DEPENDENT_LIST:
813         default:
814 
815             break;
816         }
817 
818         *State = ACPI_RSTATE_NORMAL;
819         Rnode = RsDoEndDependentDescriptor (Info);
820         break;
821 
822     case PARSEOP_ENDTAG:
823 
824         Rnode = RsDoEndTagDescriptor (Info);
825         break;
826 
827     case PARSEOP_EXTENDEDIO:
828 
829         Rnode = RsDoExtendedIoDescriptor (Info);
830         break;
831 
832     case PARSEOP_EXTENDEDMEMORY:
833 
834         Rnode = RsDoExtendedMemoryDescriptor (Info);
835         break;
836 
837     case PARSEOP_EXTENDEDSPACE:
838 
839         Rnode = RsDoExtendedSpaceDescriptor (Info);
840         break;
841 
842     case PARSEOP_FIXEDIO:
843 
844         Rnode = RsDoFixedIoDescriptor (Info);
845         break;
846 
847     case PARSEOP_INTERRUPT:
848 
849         Rnode = RsDoInterruptDescriptor (Info);
850         break;
851 
852     case PARSEOP_IO:
853 
854         Rnode = RsDoIoDescriptor (Info);
855         break;
856 
857     case PARSEOP_IRQ:
858 
859         Rnode = RsDoIrqDescriptor (Info);
860         break;
861 
862     case PARSEOP_IRQNOFLAGS:
863 
864         Rnode = RsDoIrqNoFlagsDescriptor (Info);
865         break;
866 
867     case PARSEOP_MEMORY24:
868 
869         Rnode = RsDoMemory24Descriptor (Info);
870         break;
871 
872     case PARSEOP_MEMORY32:
873 
874         Rnode = RsDoMemory32Descriptor (Info);
875         break;
876 
877     case PARSEOP_MEMORY32FIXED:
878 
879         Rnode = RsDoMemory32FixedDescriptor (Info);
880         break;
881 
882     case PARSEOP_QWORDIO:
883 
884         Rnode = RsDoQwordIoDescriptor (Info);
885         break;
886 
887     case PARSEOP_QWORDMEMORY:
888 
889         Rnode = RsDoQwordMemoryDescriptor (Info);
890         break;
891 
892     case PARSEOP_QWORDSPACE:
893 
894         Rnode = RsDoQwordSpaceDescriptor (Info);
895         break;
896 
897     case PARSEOP_REGISTER:
898 
899         Rnode = RsDoGeneralRegisterDescriptor (Info);
900         break;
901 
902     case PARSEOP_STARTDEPENDENTFN:
903 
904         switch (*State)
905         {
906         case ACPI_RSTATE_START_DEPENDENT:
907 
908             AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
909                 Info->DescriptorTypeOp, NULL);
910             break;
911 
912         case ACPI_RSTATE_NORMAL:
913         case ACPI_RSTATE_DEPENDENT_LIST:
914         default:
915 
916             break;
917         }
918 
919         *State = ACPI_RSTATE_START_DEPENDENT;
920         Rnode = RsDoStartDependentDescriptor (Info);
921         *State = ACPI_RSTATE_DEPENDENT_LIST;
922         break;
923 
924     case PARSEOP_STARTDEPENDENTFN_NOPRI:
925 
926         switch (*State)
927         {
928         case ACPI_RSTATE_START_DEPENDENT:
929 
930             AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
931                 Info->DescriptorTypeOp, NULL);
932             break;
933 
934         case ACPI_RSTATE_NORMAL:
935         case ACPI_RSTATE_DEPENDENT_LIST:
936         default:
937 
938             break;
939         }
940 
941         *State = ACPI_RSTATE_START_DEPENDENT;
942         Rnode = RsDoStartDependentNoPriDescriptor (Info);
943         *State = ACPI_RSTATE_DEPENDENT_LIST;
944         break;
945 
946     case PARSEOP_VENDORLONG:
947 
948         Rnode = RsDoVendorLargeDescriptor (Info);
949         break;
950 
951     case PARSEOP_VENDORSHORT:
952 
953         Rnode = RsDoVendorSmallDescriptor (Info);
954         break;
955 
956     case PARSEOP_WORDBUSNUMBER:
957 
958         Rnode = RsDoWordBusNumberDescriptor (Info);
959         break;
960 
961     case PARSEOP_WORDIO:
962 
963         Rnode = RsDoWordIoDescriptor (Info);
964         break;
965 
966     case PARSEOP_WORDSPACE:
967 
968         Rnode = RsDoWordSpaceDescriptor (Info);
969         break;
970 
971     case PARSEOP_GPIO_INT:
972 
973         Rnode = RsDoGpioIntDescriptor (Info);
974         break;
975 
976     case PARSEOP_GPIO_IO:
977 
978         Rnode = RsDoGpioIoDescriptor (Info);
979         break;
980 
981     case PARSEOP_I2C_SERIALBUS:
982     case PARSEOP_I2C_SERIALBUS_V2:
983 
984         Rnode = RsDoI2cSerialBusDescriptor (Info);
985         break;
986 
987     case PARSEOP_SPI_SERIALBUS:
988     case PARSEOP_SPI_SERIALBUS_V2:
989 
990         Rnode = RsDoSpiSerialBusDescriptor (Info);
991         break;
992 
993     case PARSEOP_UART_SERIALBUS:
994     case PARSEOP_UART_SERIALBUS_V2:
995 
996         Rnode = RsDoUartSerialBusDescriptor (Info);
997         break;
998 
999     case PARSEOP_CSI2_SERIALBUS:
1000 
1001         Rnode = RsDoCsi2SerialBusDescriptor (Info);
1002         break;
1003 
1004     case PARSEOP_PINCONFIG:
1005 
1006         Rnode = RsDoPinConfigDescriptor (Info);
1007         break;
1008 
1009     case PARSEOP_PINFUNCTION:
1010 
1011         Rnode = RsDoPinFunctionDescriptor (Info);
1012         break;
1013 
1014     case PARSEOP_PINGROUP:
1015 
1016         Rnode = RsDoPinGroupDescriptor (Info);
1017         break;
1018 
1019     case PARSEOP_PINGROUPFUNCTION:
1020 
1021         Rnode = RsDoPinGroupFunctionDescriptor (Info);
1022         break;
1023 
1024     case PARSEOP_PINGROUPCONFIG:
1025 
1026         Rnode = RsDoPinGroupConfigDescriptor (Info);
1027         break;
1028 
1029     case PARSEOP_DEFAULT_ARG:
1030 
1031         /* Just ignore any of these, they are used as fillers/placeholders */
1032         break;
1033 
1034     default:
1035 
1036         printf ("Unknown resource descriptor type [%s]\n",
1037             Info->DescriptorTypeOp->Asl.ParseOpName);
1038         break;
1039     }
1040 
1041     /*
1042      * Mark original node as unused, but head of a resource descriptor.
1043      * This allows the resource to be installed in the namespace so that
1044      * references to the descriptor can be resolved.
1045      */
1046     Info->DescriptorTypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1047     Info->DescriptorTypeOp->Asl.CompileFlags = OP_IS_RESOURCE_DESC;
1048     Info->DescriptorTypeOp->Asl.Value.Integer = Info->CurrentByteOffset;
1049 
1050     if (Rnode)
1051     {
1052         Info->DescriptorTypeOp->Asl.FinalAmlLength = Rnode->BufferLength;
1053         Info->DescriptorTypeOp->Asl.Extra =
1054             ((AML_RESOURCE *) Rnode->Buffer)->DescriptorType;
1055     }
1056 
1057     return (Rnode);
1058 }
1059 
1060 
1061 /*******************************************************************************
1062  *
1063  * FUNCTION:    RsLinkDescriptorChain
1064  *
1065  * PARAMETERS:  PreviousRnode       - Pointer to the node that will be previous
1066  *                                    to the linked node,  At exit, set to the
1067  *                                    last node in the new chain.
1068  *              Rnode               - Resource node to link into the list
1069  *
1070  * RETURN:      Cumulative buffer byte offset of the new segment of chain
1071  *
1072  * DESCRIPTION: Link a descriptor chain at the end of an existing chain.
1073  *
1074  ******************************************************************************/
1075 
1076 UINT32
RsLinkDescriptorChain(ASL_RESOURCE_NODE ** PreviousRnode,ASL_RESOURCE_NODE * Rnode)1077 RsLinkDescriptorChain (
1078     ASL_RESOURCE_NODE       **PreviousRnode,
1079     ASL_RESOURCE_NODE       *Rnode)
1080 {
1081     ASL_RESOURCE_NODE       *LastRnode;
1082     UINT32                  CurrentByteOffset;
1083 
1084 
1085     /* Anything to do? */
1086 
1087     if (!Rnode)
1088     {
1089         return (0);
1090     }
1091 
1092     /* Point the previous node to the new node */
1093 
1094     (*PreviousRnode)->Next = Rnode;
1095     CurrentByteOffset = Rnode->BufferLength;
1096 
1097     /* Walk to the end of the chain headed by Rnode */
1098 
1099     LastRnode = Rnode;
1100     while (LastRnode->Next)
1101     {
1102         LastRnode = LastRnode->Next;
1103         CurrentByteOffset += LastRnode->BufferLength;
1104     }
1105 
1106     /* Previous node becomes the last node in the chain */
1107 
1108     *PreviousRnode = LastRnode;
1109     return (CurrentByteOffset);
1110 }
1111 
1112 
1113 /*******************************************************************************
1114  *
1115  * FUNCTION:    RsDoResourceTemplate
1116  *
1117  * PARAMETERS:  Op        - Parent of a resource template list
1118  *
1119  * RETURN:      None. Sets input node to point to a list of AML code
1120  *
1121  * DESCRIPTION: Merge a list of resource descriptors into a single AML buffer,
1122  *              in preparation for output to the AML output file.
1123  *
1124  ******************************************************************************/
1125 
1126 void
RsDoResourceTemplate(ACPI_PARSE_OBJECT * Op)1127 RsDoResourceTemplate (
1128     ACPI_PARSE_OBJECT       *Op)
1129 {
1130     ACPI_PARSE_OBJECT       *BufferLengthOp;
1131     ACPI_PARSE_OBJECT       *BufferOp;
1132     ACPI_PARSE_OBJECT       *DescriptorTypeOp;
1133     ACPI_PARSE_OBJECT       *LastOp = NULL;
1134     UINT32                  CurrentByteOffset = 0;
1135     ASL_RESOURCE_NODE       HeadRnode;
1136     ASL_RESOURCE_NODE       *PreviousRnode;
1137     ASL_RESOURCE_NODE       *Rnode;
1138     ASL_RESOURCE_INFO       Info;
1139     UINT8                   State;
1140 
1141 
1142     /* Mark parent as containing a resource template */
1143 
1144     if (Op->Asl.Parent)
1145     {
1146         Op->Asl.Parent->Asl.CompileFlags |= OP_IS_RESOURCE_DESC;
1147     }
1148 
1149     /* ResourceTemplate Opcode is first (Op) */
1150     /* Buffer Length node is first child */
1151 
1152     BufferLengthOp = ASL_GET_CHILD_NODE (Op);
1153 
1154     /* Buffer Op is first peer */
1155 
1156     BufferOp = ASL_GET_PEER_NODE (BufferLengthOp);
1157 
1158     /* First Descriptor type is next */
1159 
1160     DescriptorTypeOp = ASL_GET_PEER_NODE (BufferOp);
1161 
1162     /* DEFAULT_ARG indicates null template - ResourceTemplate(){} */
1163 
1164     if (DescriptorTypeOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
1165     {
1166         AslError (ASL_WARNING, ASL_MSG_NULL_RESOURCE_TEMPLATE,
1167             DescriptorTypeOp, DescriptorTypeOp->Asl.Value.String);
1168     }
1169 
1170     /*
1171      * Process all resource descriptors in the list
1172      * Note: It is assumed that the EndTag node has been automatically
1173      * inserted at the end of the template by the parser.
1174      */
1175     State = ACPI_RSTATE_NORMAL;
1176     PreviousRnode = &HeadRnode;
1177     while (DescriptorTypeOp)
1178     {
1179         /* Save information for optional mapfile */
1180 
1181         if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION)
1182         {
1183             Info.MappingOp = Op->Asl.Parent;
1184         }
1185         else
1186         {
1187             Info.MappingOp = DescriptorTypeOp;
1188         }
1189 
1190         Info.DescriptorTypeOp = DescriptorTypeOp;
1191         Info.CurrentByteOffset = CurrentByteOffset;
1192 
1193         DescriptorTypeOp->Asl.CompileFlags |= OP_IS_RESOURCE_DESC;
1194         Rnode = RsDoOneResourceDescriptor (&Info, &State);
1195 
1196         /*
1197          * Update current byte offset to indicate the number of bytes from the
1198          * start of the buffer. Buffer can include multiple descriptors, we
1199          * must keep track of the offset of not only each descriptor, but each
1200          * element (field) within each descriptor as well.
1201          */
1202         CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, Rnode);
1203 
1204         /* Get the next descriptor in the list */
1205 
1206         LastOp = DescriptorTypeOp;
1207         DescriptorTypeOp = ASL_GET_PEER_NODE (DescriptorTypeOp);
1208     }
1209 
1210     if (State == ACPI_RSTATE_DEPENDENT_LIST)
1211     {
1212         if (LastOp)
1213         {
1214             LastOp = LastOp->Asl.Parent;
1215         }
1216         AslError (ASL_ERROR, ASL_MSG_MISSING_ENDDEPENDENT, LastOp, NULL);
1217     }
1218 
1219     /*
1220      * Transform the nodes into the following
1221      *
1222      * Op           -> AML_BUFFER_OP
1223      * First Child  -> BufferLength
1224      * Second Child -> Descriptor Buffer (raw byte data)
1225      */
1226     Op->Asl.ParseOpcode               = PARSEOP_BUFFER;
1227     Op->Asl.AmlOpcode                 = AML_BUFFER_OP;
1228     Op->Asl.CompileFlags              = OP_AML_PACKAGE | OP_IS_RESOURCE_DESC;
1229     UtSetParseOpName (Op);
1230 
1231     BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
1232     BufferLengthOp->Asl.Value.Integer = CurrentByteOffset;
1233     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
1234     UtSetParseOpName (BufferLengthOp);
1235 
1236     BufferOp->Asl.ParseOpcode         = PARSEOP_RAW_DATA;
1237     BufferOp->Asl.AmlOpcode           = AML_RAW_DATA_CHAIN;
1238     BufferOp->Asl.AmlOpcodeLength     = 0;
1239     BufferOp->Asl.AmlLength           = CurrentByteOffset;
1240     BufferOp->Asl.Value.Buffer        = ACPI_CAST_PTR (UINT8,  HeadRnode.Next);
1241     BufferOp->Asl.CompileFlags       |= OP_IS_RESOURCE_DATA;
1242     UtSetParseOpName (BufferOp);
1243 
1244     return;
1245 }
1246