aslresource.c revision 306536
1/******************************************************************************
2 *
3 * Module Name: aslresource - Resource template/descriptor utilities
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2016, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <contrib/dev/acpica/compiler/aslcompiler.h>
45#include "aslcompiler.y.h"
46#include <contrib/dev/acpica/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
78void
79RsSmallAddressCheck (
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 (Gbl_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
210void
211RsLargeAddressCheck (
212    UINT64                  Minimum,
213    UINT64                  Maximum,
214    UINT64                  Length,
215    UINT64                  Granularity,
216    UINT8                   Flags,
217    ACPI_PARSE_OBJECT       *MinOp,
218    ACPI_PARSE_OBJECT       *MaxOp,
219    ACPI_PARSE_OBJECT       *LengthOp,
220    ACPI_PARSE_OBJECT       *GranOp,
221    ACPI_PARSE_OBJECT       *Op)
222{
223
224    if (Gbl_NoResourceChecking)
225    {
226        return;
227    }
228
229    /*
230     * Check for a so-called "null descriptor". These are descriptors that are
231     * created with most fields set to zero. The intent is that the descriptor
232     * will be updated/completed at runtime via a BufferField.
233     *
234     * If the descriptor does NOT have a resource tag, it cannot be referenced
235     * by a BufferField and we will flag this as an error. Conversely, if
236     * the descriptor has a resource tag, we will assume that a BufferField
237     * will be used to dynamically update it, so no error.
238     *
239     * A possible enhancement to this check would be to verify that in fact
240     * a BufferField is created using the resource tag, and perhaps even
241     * verify that a Store is performed to the BufferField.
242     */
243    if (!Minimum && !Maximum && !Length && !Granularity)
244    {
245        if (!Op->Asl.ExternalName)
246        {
247            /* No resource tag. Descriptor is fixed and is also illegal */
248
249            AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL);
250        }
251
252        return;
253    }
254
255    /* Basic checks on Min/Max/Length */
256
257    if (Minimum > Maximum)
258    {
259        AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL);
260        return;
261    }
262    else if (Length > (Maximum - Minimum + 1))
263    {
264        AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL);
265        return;
266    }
267
268    /* If specified (non-zero), ensure granularity is a power-of-two minus one */
269
270    if (Granularity)
271    {
272        if ((Granularity + 1) &
273             Granularity)
274        {
275            AslError (ASL_ERROR, ASL_MSG_INVALID_GRANULARITY, GranOp, NULL);
276            return;
277        }
278    }
279
280    /*
281     * Check the various combinations of Length, MinFixed, and MaxFixed
282     */
283    if (Length)
284    {
285        /* Fixed non-zero length */
286
287        switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF))
288        {
289        case 0:
290            /*
291             * Fixed length, variable locations (both _MIN and _MAX).
292             * Length must be a multiple of granularity
293             */
294            if (Granularity & Length)
295            {
296                AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, LengthOp, NULL);
297            }
298            break;
299
300        case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF):
301
302            /* Fixed length, fixed location. Granularity must be zero */
303
304            if (Granularity != 0)
305            {
306                AslError (ASL_ERROR, ASL_MSG_INVALID_GRAN_FIXED, GranOp, NULL);
307            }
308
309            /* Length must be exactly the size of the min/max window */
310
311            if (Length != (Maximum - Minimum + 1))
312            {
313                AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH_FIXED, LengthOp, NULL);
314            }
315            break;
316
317        /* All other combinations are invalid */
318
319        case ACPI_RESOURCE_FLAG_MIF:
320        case ACPI_RESOURCE_FLAG_MAF:
321        default:
322
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
388UINT16
389RsGetStringDataLength (
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
420ASL_RESOURCE_NODE *
421RsAllocateResourceNode (
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
458void
459RsCreateResourceField (
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 |= NODE_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
493void
494RsSetFlagBits (
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
516void
517RsSetFlagBits16 (
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
553ACPI_PARSE_OBJECT *
554RsCompleteNodeAndGetNext (
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
581void
582RsCheckListForDuplicates (
583    ACPI_PARSE_OBJECT       *Op)
584{
585    ACPI_PARSE_OBJECT       *NextValueOp = Op;
586    ACPI_PARSE_OBJECT       *NextOp;
587    UINT32                  Value;
588
589
590    if (!Op)
591    {
592        return;
593    }
594
595    /* Search list once for each value in the list */
596
597    while (NextValueOp)
598    {
599        Value = (UINT32) NextValueOp->Asl.Value.Integer;
600
601        /* Compare this value to all remaining values in the list */
602
603        NextOp = ASL_GET_PEER_NODE (NextValueOp);
604        while (NextOp)
605        {
606            if (NextOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
607            {
608                /* Compare values */
609
610                if (Value == (UINT32) NextOp->Asl.Value.Integer)
611                {
612                    /* Emit error only once per duplicate node */
613
614                    if (!(NextOp->Asl.CompileFlags & NODE_IS_DUPLICATE))
615                    {
616                        NextOp->Asl.CompileFlags |= NODE_IS_DUPLICATE;
617                        AslError (ASL_ERROR, ASL_MSG_DUPLICATE_ITEM,
618                            NextOp, NULL);
619                    }
620                }
621            }
622
623            NextOp = ASL_GET_PEER_NODE (NextOp);
624        }
625
626        NextValueOp = ASL_GET_PEER_NODE (NextValueOp);
627    }
628}
629
630
631/*******************************************************************************
632 *
633 * FUNCTION:    RsDoOneResourceDescriptor
634 *
635 * PARAMETERS:  DescriptorTypeOp    - Parent parse node of the descriptor
636 *              CurrentByteOffset   - Offset in the resource descriptor
637 *                                    buffer.
638 *
639 * RETURN:      A valid resource node for the descriptor
640 *
641 * DESCRIPTION: Dispatches the processing of one resource descriptor
642 *
643 ******************************************************************************/
644
645ASL_RESOURCE_NODE *
646RsDoOneResourceDescriptor (
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    case PARSEOP_DMA:
658
659        Rnode = RsDoDmaDescriptor (Info);
660        break;
661
662    case PARSEOP_FIXEDDMA:
663
664        Rnode = RsDoFixedDmaDescriptor (Info);
665        break;
666
667    case PARSEOP_DWORDIO:
668
669        Rnode = RsDoDwordIoDescriptor (Info);
670        break;
671
672    case PARSEOP_DWORDMEMORY:
673
674        Rnode = RsDoDwordMemoryDescriptor (Info);
675        break;
676
677    case PARSEOP_DWORDSPACE:
678
679        Rnode = RsDoDwordSpaceDescriptor (Info);
680        break;
681
682    case PARSEOP_ENDDEPENDENTFN:
683
684        switch (*State)
685        {
686        case ACPI_RSTATE_NORMAL:
687
688            AslError (ASL_ERROR, ASL_MSG_MISSING_STARTDEPENDENT,
689                Info->DescriptorTypeOp, NULL);
690            break;
691
692        case ACPI_RSTATE_START_DEPENDENT:
693
694            AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
695                Info->DescriptorTypeOp, NULL);
696            break;
697
698        case ACPI_RSTATE_DEPENDENT_LIST:
699        default:
700
701            break;
702        }
703
704        *State = ACPI_RSTATE_NORMAL;
705        Rnode = RsDoEndDependentDescriptor (Info);
706        break;
707
708    case PARSEOP_ENDTAG:
709
710        Rnode = RsDoEndTagDescriptor (Info);
711        break;
712
713    case PARSEOP_EXTENDEDIO:
714
715        Rnode = RsDoExtendedIoDescriptor (Info);
716        break;
717
718    case PARSEOP_EXTENDEDMEMORY:
719
720        Rnode = RsDoExtendedMemoryDescriptor (Info);
721        break;
722
723    case PARSEOP_EXTENDEDSPACE:
724
725        Rnode = RsDoExtendedSpaceDescriptor (Info);
726        break;
727
728    case PARSEOP_FIXEDIO:
729
730        Rnode = RsDoFixedIoDescriptor (Info);
731        break;
732
733    case PARSEOP_INTERRUPT:
734
735        Rnode = RsDoInterruptDescriptor (Info);
736        break;
737
738    case PARSEOP_IO:
739
740        Rnode = RsDoIoDescriptor (Info);
741        break;
742
743    case PARSEOP_IRQ:
744
745        Rnode = RsDoIrqDescriptor (Info);
746        break;
747
748    case PARSEOP_IRQNOFLAGS:
749
750        Rnode = RsDoIrqNoFlagsDescriptor (Info);
751        break;
752
753    case PARSEOP_MEMORY24:
754
755        Rnode = RsDoMemory24Descriptor (Info);
756        break;
757
758    case PARSEOP_MEMORY32:
759
760        Rnode = RsDoMemory32Descriptor (Info);
761        break;
762
763    case PARSEOP_MEMORY32FIXED:
764
765        Rnode = RsDoMemory32FixedDescriptor (Info);
766        break;
767
768    case PARSEOP_QWORDIO:
769
770        Rnode = RsDoQwordIoDescriptor (Info);
771        break;
772
773    case PARSEOP_QWORDMEMORY:
774
775        Rnode = RsDoQwordMemoryDescriptor (Info);
776        break;
777
778    case PARSEOP_QWORDSPACE:
779
780        Rnode = RsDoQwordSpaceDescriptor (Info);
781        break;
782
783    case PARSEOP_REGISTER:
784
785        Rnode = RsDoGeneralRegisterDescriptor (Info);
786        break;
787
788    case PARSEOP_STARTDEPENDENTFN:
789
790        switch (*State)
791        {
792        case ACPI_RSTATE_START_DEPENDENT:
793
794            AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
795                Info->DescriptorTypeOp, NULL);
796            break;
797
798        case ACPI_RSTATE_NORMAL:
799        case ACPI_RSTATE_DEPENDENT_LIST:
800        default:
801
802            break;
803        }
804
805        *State = ACPI_RSTATE_START_DEPENDENT;
806        Rnode = RsDoStartDependentDescriptor (Info);
807        *State = ACPI_RSTATE_DEPENDENT_LIST;
808        break;
809
810    case PARSEOP_STARTDEPENDENTFN_NOPRI:
811
812        switch (*State)
813        {
814        case ACPI_RSTATE_START_DEPENDENT:
815
816            AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
817                Info->DescriptorTypeOp, NULL);
818            break;
819
820        case ACPI_RSTATE_NORMAL:
821        case ACPI_RSTATE_DEPENDENT_LIST:
822        default:
823
824            break;
825        }
826
827        *State = ACPI_RSTATE_START_DEPENDENT;
828        Rnode = RsDoStartDependentNoPriDescriptor (Info);
829        *State = ACPI_RSTATE_DEPENDENT_LIST;
830        break;
831
832    case PARSEOP_VENDORLONG:
833
834        Rnode = RsDoVendorLargeDescriptor (Info);
835        break;
836
837    case PARSEOP_VENDORSHORT:
838
839        Rnode = RsDoVendorSmallDescriptor (Info);
840        break;
841
842    case PARSEOP_WORDBUSNUMBER:
843
844        Rnode = RsDoWordBusNumberDescriptor (Info);
845        break;
846
847    case PARSEOP_WORDIO:
848
849        Rnode = RsDoWordIoDescriptor (Info);
850        break;
851
852    case PARSEOP_WORDSPACE:
853
854        Rnode = RsDoWordSpaceDescriptor (Info);
855        break;
856
857    case PARSEOP_GPIO_INT:
858
859        Rnode = RsDoGpioIntDescriptor (Info);
860        break;
861
862    case PARSEOP_GPIO_IO:
863
864        Rnode = RsDoGpioIoDescriptor (Info);
865        break;
866
867    case PARSEOP_I2C_SERIALBUS:
868    case PARSEOP_I2C_SERIALBUS_V2:
869
870        Rnode = RsDoI2cSerialBusDescriptor (Info);
871        break;
872
873    case PARSEOP_SPI_SERIALBUS:
874    case PARSEOP_SPI_SERIALBUS_V2:
875
876        Rnode = RsDoSpiSerialBusDescriptor (Info);
877        break;
878
879    case PARSEOP_UART_SERIALBUS:
880    case PARSEOP_UART_SERIALBUS_V2:
881
882        Rnode = RsDoUartSerialBusDescriptor (Info);
883        break;
884
885    case PARSEOP_DEFAULT_ARG:
886
887        /* Just ignore any of these, they are used as fillers/placeholders */
888        break;
889
890    default:
891
892        printf ("Unknown resource descriptor type [%s]\n",
893            Info->DescriptorTypeOp->Asl.ParseOpName);
894        break;
895    }
896
897    /*
898     * Mark original node as unused, but head of a resource descriptor.
899     * This allows the resource to be installed in the namespace so that
900     * references to the descriptor can be resolved.
901     */
902    Info->DescriptorTypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
903    Info->DescriptorTypeOp->Asl.CompileFlags = NODE_IS_RESOURCE_DESC;
904    Info->DescriptorTypeOp->Asl.Value.Integer = Info->CurrentByteOffset;
905
906    if (Rnode)
907    {
908        Info->DescriptorTypeOp->Asl.FinalAmlLength = Rnode->BufferLength;
909        Info->DescriptorTypeOp->Asl.Extra =
910            ((AML_RESOURCE *) Rnode->Buffer)->DescriptorType;
911    }
912
913    return (Rnode);
914}
915
916
917/*******************************************************************************
918 *
919 * FUNCTION:    RsLinkDescriptorChain
920 *
921 * PARAMETERS:  PreviousRnode       - Pointer to the node that will be previous
922 *                                    to the linked node,  At exit, set to the
923 *                                    last node in the new chain.
924 *              Rnode               - Resource node to link into the list
925 *
926 * RETURN:      Cumulative buffer byte offset of the new segment of chain
927 *
928 * DESCRIPTION: Link a descriptor chain at the end of an existing chain.
929 *
930 ******************************************************************************/
931
932UINT32
933RsLinkDescriptorChain (
934    ASL_RESOURCE_NODE       **PreviousRnode,
935    ASL_RESOURCE_NODE       *Rnode)
936{
937    ASL_RESOURCE_NODE       *LastRnode;
938    UINT32                  CurrentByteOffset;
939
940
941    /* Anything to do? */
942
943    if (!Rnode)
944    {
945        return (0);
946    }
947
948    /* Point the previous node to the new node */
949
950    (*PreviousRnode)->Next = Rnode;
951    CurrentByteOffset = Rnode->BufferLength;
952
953    /* Walk to the end of the chain headed by Rnode */
954
955    LastRnode = Rnode;
956    while (LastRnode->Next)
957    {
958        LastRnode = LastRnode->Next;
959        CurrentByteOffset += LastRnode->BufferLength;
960    }
961
962    /* Previous node becomes the last node in the chain */
963
964    *PreviousRnode = LastRnode;
965    return (CurrentByteOffset);
966}
967
968
969/*******************************************************************************
970 *
971 * FUNCTION:    RsDoResourceTemplate
972 *
973 * PARAMETERS:  Op        - Parent of a resource template list
974 *
975 * RETURN:      None. Sets input node to point to a list of AML code
976 *
977 * DESCRIPTION: Merge a list of resource descriptors into a single AML buffer,
978 *              in preparation for output to the AML output file.
979 *
980 ******************************************************************************/
981
982void
983RsDoResourceTemplate (
984    ACPI_PARSE_OBJECT       *Op)
985{
986    ACPI_PARSE_OBJECT       *BufferLengthOp;
987    ACPI_PARSE_OBJECT       *BufferOp;
988    ACPI_PARSE_OBJECT       *DescriptorTypeOp;
989    ACPI_PARSE_OBJECT       *LastOp = NULL;
990    UINT32                  CurrentByteOffset = 0;
991    ASL_RESOURCE_NODE       HeadRnode;
992    ASL_RESOURCE_NODE       *PreviousRnode;
993    ASL_RESOURCE_NODE       *Rnode;
994    ASL_RESOURCE_INFO       Info;
995    UINT8                   State;
996
997
998    /* Mark parent as containing a resource template */
999
1000    if (Op->Asl.Parent)
1001    {
1002        Op->Asl.Parent->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
1003    }
1004
1005    /* ResourceTemplate Opcode is first (Op) */
1006    /* Buffer Length node is first child */
1007
1008    BufferLengthOp = ASL_GET_CHILD_NODE (Op);
1009
1010    /* Buffer Op is first peer */
1011
1012    BufferOp = ASL_GET_PEER_NODE (BufferLengthOp);
1013
1014    /* First Descriptor type is next */
1015
1016    DescriptorTypeOp = ASL_GET_PEER_NODE (BufferOp);
1017
1018    /*
1019     * Process all resource descriptors in the list
1020     * Note: It is assumed that the EndTag node has been automatically
1021     * inserted at the end of the template by the parser.
1022     */
1023    State = ACPI_RSTATE_NORMAL;
1024    PreviousRnode = &HeadRnode;
1025    while (DescriptorTypeOp)
1026    {
1027        /* Save information for optional mapfile */
1028
1029        if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION)
1030        {
1031            Info.MappingOp = Op->Asl.Parent;
1032        }
1033        else
1034        {
1035            Info.MappingOp = DescriptorTypeOp;
1036        }
1037
1038        Info.DescriptorTypeOp = DescriptorTypeOp;
1039        Info.CurrentByteOffset = CurrentByteOffset;
1040
1041        DescriptorTypeOp->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
1042        Rnode = RsDoOneResourceDescriptor (&Info, &State);
1043
1044        /*
1045         * Update current byte offset to indicate the number of bytes from the
1046         * start of the buffer. Buffer can include multiple descriptors, we
1047         * must keep track of the offset of not only each descriptor, but each
1048         * element (field) within each descriptor as well.
1049         */
1050        CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, Rnode);
1051
1052        /* Get the next descriptor in the list */
1053
1054        LastOp = DescriptorTypeOp;
1055        DescriptorTypeOp = ASL_GET_PEER_NODE (DescriptorTypeOp);
1056    }
1057
1058    if (State == ACPI_RSTATE_DEPENDENT_LIST)
1059    {
1060        if (LastOp)
1061        {
1062            LastOp = LastOp->Asl.Parent;
1063        }
1064        AslError (ASL_ERROR, ASL_MSG_MISSING_ENDDEPENDENT, LastOp, NULL);
1065    }
1066
1067    /*
1068     * Transform the nodes into the following
1069     *
1070     * Op           -> AML_BUFFER_OP
1071     * First Child  -> BufferLength
1072     * Second Child -> Descriptor Buffer (raw byte data)
1073     */
1074    Op->Asl.ParseOpcode               = PARSEOP_BUFFER;
1075    Op->Asl.AmlOpcode                 = AML_BUFFER_OP;
1076    Op->Asl.CompileFlags              = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC;
1077    UtSetParseOpName (Op);
1078
1079    BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
1080    BufferLengthOp->Asl.Value.Integer = CurrentByteOffset;
1081    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
1082    UtSetParseOpName (BufferLengthOp);
1083
1084    BufferOp->Asl.ParseOpcode         = PARSEOP_RAW_DATA;
1085    BufferOp->Asl.AmlOpcode           = AML_RAW_DATA_CHAIN;
1086    BufferOp->Asl.AmlOpcodeLength     = 0;
1087    BufferOp->Asl.AmlLength           = CurrentByteOffset;
1088    BufferOp->Asl.Value.Buffer        = (UINT8 *) HeadRnode.Next;
1089    BufferOp->Asl.CompileFlags       |= NODE_IS_RESOURCE_DATA;
1090    UtSetParseOpName (BufferOp);
1091
1092    return;
1093}
1094