aslresource.c revision 249112
1/******************************************************************************
2 *
3 * Module Name: aslresource - Resource template/descriptor utilities
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2013, 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
45#include <contrib/dev/acpica/compiler/aslcompiler.h>
46#include "aslcompiler.y.h"
47#include <contrib/dev/acpica/include/amlcode.h>
48
49
50#define _COMPONENT          ACPI_COMPILER
51        ACPI_MODULE_NAME    ("aslresource")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION:    RsSmallAddressCheck
57 *
58 * PARAMETERS:  Minimum             - Address Min value
59 *              Maximum             - Address Max value
60 *              Length              - Address range value
61 *              Alignment           - Address alignment value
62 *              MinOp               - Original Op for Address Min
63 *              MaxOp               - Original Op for Address Max
64 *              LengthOp            - Original Op for address range
65 *              AlignOp             - Original Op for address alignment. If
66 *                                    NULL, means "zero value for alignment is
67 *                                    OK, and means 64K alignment" (for
68 *                                    Memory24 descriptor)
69 *              Op                  - Parent Op for entire construct
70 *
71 * RETURN:      None. Adds error messages to error log if necessary
72 *
73 * DESCRIPTION: Perform common value checks for "small" address descriptors.
74 *              Currently:
75 *                  Io, Memory24, Memory32
76 *
77 ******************************************************************************/
78
79void
80RsSmallAddressCheck (
81    UINT8                   Type,
82    UINT32                  Minimum,
83    UINT32                  Maximum,
84    UINT32                  Length,
85    UINT32                  Alignment,
86    ACPI_PARSE_OBJECT       *MinOp,
87    ACPI_PARSE_OBJECT       *MaxOp,
88    ACPI_PARSE_OBJECT       *LengthOp,
89    ACPI_PARSE_OBJECT       *AlignOp,
90    ACPI_PARSE_OBJECT       *Op)
91{
92
93    if (Gbl_NoResourceChecking)
94    {
95        return;
96    }
97
98    /*
99     * Check for a so-called "null descriptor". These are descriptors that are
100     * created with most fields set to zero. The intent is that the descriptor
101     * will be updated/completed at runtime via a BufferField.
102     *
103     * If the descriptor does NOT have a resource tag, it cannot be referenced
104     * by a BufferField and we will flag this as an error. Conversely, if
105     * the descriptor has a resource tag, we will assume that a BufferField
106     * will be used to dynamically update it, so no error.
107     *
108     * A possible enhancement to this check would be to verify that in fact
109     * a BufferField is created using the resource tag, and perhaps even
110     * verify that a Store is performed to the BufferField.
111     *
112     * Note: for these descriptors, Alignment is allowed to be zero
113     */
114    if (!Minimum && !Maximum && !Length)
115    {
116        if (!Op->Asl.ExternalName)
117        {
118            /* No resource tag. Descriptor is fixed and is also illegal */
119
120            AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL);
121        }
122
123        return;
124    }
125
126    /* Special case for Memory24, values are compressed */
127
128    if (Type == ACPI_RESOURCE_NAME_MEMORY24)
129    {
130        if (!Alignment) /* Alignment==0 means 64K - no invalid alignment */
131        {
132            Alignment = ACPI_UINT16_MAX + 1;
133        }
134
135        Minimum <<= 8;
136        Maximum <<= 8;
137        Length *= 256;
138    }
139
140    /* IO descriptor has different definition of min/max, don't check */
141
142    if (Type != ACPI_RESOURCE_NAME_IO)
143    {
144        /* Basic checks on Min/Max/Length */
145
146        if (Minimum > Maximum)
147        {
148            AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL);
149        }
150        else if (Length > (Maximum - Minimum + 1))
151        {
152            AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL);
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            AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL);
323        }
324    }
325    else
326    {
327        /* Variable length (length==0) */
328
329        switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF))
330        {
331        case 0:
332            /*
333             * Both _MIN and _MAX are variable.
334             * No additional requirements, just exit
335             */
336            break;
337
338        case ACPI_RESOURCE_FLAG_MIF:
339
340            /* _MIN is fixed. _MIN must be multiple of _GRA */
341
342            /*
343             * The granularity is defined by the ACPI specification to be a
344             * power-of-two minus one, therefore the granularity is a
345             * bitmask which can be used to easily validate the addresses.
346             */
347            if (Granularity & Minimum)
348            {
349                AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL);
350            }
351            break;
352
353        case ACPI_RESOURCE_FLAG_MAF:
354
355            /* _MAX is fixed. (_MAX + 1) must be multiple of _GRA */
356
357            if (Granularity & (Maximum + 1))
358            {
359                AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, "-1");
360            }
361            break;
362
363        /* Both MIF/MAF set is invalid if length is zero */
364
365        case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF):
366        default:
367            AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL);
368        }
369    }
370}
371
372
373/*******************************************************************************
374 *
375 * FUNCTION:    RsGetStringDataLength
376 *
377 * PARAMETERS:  InitializerOp     - Start of a subtree of init nodes
378 *
379 * RETURN:      Valid string length if a string node is found (otherwise 0)
380 *
381 * DESCRIPTION: In a list of peer nodes, find the first one that contains a
382 *              string and return the length of the string.
383 *
384 ******************************************************************************/
385
386UINT16
387RsGetStringDataLength (
388    ACPI_PARSE_OBJECT       *InitializerOp)
389{
390
391    while (InitializerOp)
392    {
393        if (InitializerOp->Asl.ParseOpcode == PARSEOP_STRING_LITERAL)
394        {
395            return ((UINT16) (strlen (InitializerOp->Asl.Value.String) + 1));
396        }
397        InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
398    }
399
400    return (0);
401}
402
403
404/*******************************************************************************
405 *
406 * FUNCTION:    RsAllocateResourceNode
407 *
408 * PARAMETERS:  Size        - Size of node in bytes
409 *
410 * RETURN:      The allocated node - aborts on allocation failure
411 *
412 * DESCRIPTION: Allocate a resource description node and the resource
413 *              descriptor itself (the nodes are used to link descriptors).
414 *
415 ******************************************************************************/
416
417ASL_RESOURCE_NODE *
418RsAllocateResourceNode (
419    UINT32                  Size)
420{
421    ASL_RESOURCE_NODE       *Rnode;
422
423
424    /* Allocate the node */
425
426    Rnode = UtLocalCalloc (sizeof (ASL_RESOURCE_NODE));
427
428    /* Allocate the resource descriptor itself */
429
430    Rnode->Buffer = UtLocalCalloc (Size);
431    Rnode->BufferLength = Size;
432
433    return (Rnode);
434}
435
436
437/*******************************************************************************
438 *
439 * FUNCTION:    RsCreateResourceField
440 *
441 * PARAMETERS:  Op              - Resource field node
442 *              Name            - Name of the field (Used only to reference
443 *                                the field in the ASL, not in the AML)
444 *              ByteOffset      - Offset from the field start
445 *              BitOffset       - Additional bit offset
446 *              BitLength       - Number of bits in the field
447 *
448 * RETURN:      None, sets fields within the input node
449 *
450 * DESCRIPTION: Utility function to generate a named bit field within a
451 *              resource descriptor. Mark a node as 1) a field in a resource
452 *              descriptor, and 2) set the value to be a BIT offset
453 *
454 ******************************************************************************/
455
456void
457RsCreateResourceField (
458    ACPI_PARSE_OBJECT       *Op,
459    char                    *Name,
460    UINT32                  ByteOffset,
461    UINT32                  BitOffset,
462    UINT32                  BitLength)
463{
464
465    Op->Asl.ExternalName = Name;
466    Op->Asl.CompileFlags |= NODE_IS_RESOURCE_FIELD;
467
468
469    Op->Asl.Value.Tag.BitOffset = (ByteOffset * 8) + BitOffset;
470    Op->Asl.Value.Tag.BitLength = BitLength;
471}
472
473
474/*******************************************************************************
475 *
476 * FUNCTION:    RsSetFlagBits
477 *
478 * PARAMETERS:  *Flags          - Pointer to the flag byte
479 *              Op              - Flag initialization node
480 *              Position        - Bit position within the flag byte
481 *              Default         - Used if the node is DEFAULT.
482 *
483 * RETURN:      Sets bits within the *Flags output byte.
484 *
485 * DESCRIPTION: Set a bit in a cumulative flags word from an initialization
486 *              node. Will use a default value if the node is DEFAULT, meaning
487 *              that no value was specified in the ASL. Used to merge multiple
488 *              keywords into a single flags byte.
489 *
490 ******************************************************************************/
491
492void
493RsSetFlagBits (
494    UINT8                   *Flags,
495    ACPI_PARSE_OBJECT       *Op,
496    UINT8                   Position,
497    UINT8                   DefaultBit)
498{
499
500    if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
501    {
502        /* Use the default bit */
503
504        *Flags |= (DefaultBit << Position);
505    }
506    else
507    {
508        /* Use the bit specified in the initialization node */
509
510        *Flags |= (((UINT8) Op->Asl.Value.Integer) << Position);
511    }
512}
513
514
515void
516RsSetFlagBits16 (
517    UINT16                  *Flags,
518    ACPI_PARSE_OBJECT       *Op,
519    UINT8                   Position,
520    UINT8                   DefaultBit)
521{
522
523    if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
524    {
525        /* Use the default bit */
526
527        *Flags |= (DefaultBit << Position);
528    }
529    else
530    {
531        /* Use the bit specified in the initialization node */
532
533        *Flags |= (((UINT16) Op->Asl.Value.Integer) << Position);
534    }
535}
536
537
538/*******************************************************************************
539 *
540 * FUNCTION:    RsCompleteNodeAndGetNext
541 *
542 * PARAMETERS:  Op            - Resource node to be completed
543 *
544 * RETURN:      The next peer to the input node.
545 *
546 * DESCRIPTION: Mark the current node completed and return the next peer.
547 *              The node ParseOpcode is set to DEFAULT_ARG, meaning that
548 *              this node is to be ignored from now on.
549 *
550 ******************************************************************************/
551
552ACPI_PARSE_OBJECT *
553RsCompleteNodeAndGetNext (
554    ACPI_PARSE_OBJECT       *Op)
555{
556
557    /* Mark this node unused */
558
559    Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
560
561    /* Move on to the next peer node in the initializer list */
562
563    return (ASL_GET_PEER_NODE (Op));
564}
565
566
567/*******************************************************************************
568 *
569 * FUNCTION:    RsCheckListForDuplicates
570 *
571 * PARAMETERS:  Op                  - First op in the initializer list
572 *
573 * RETURN:      None
574 *
575 * DESCRIPTION: Check an initializer list for duplicate values. Emits an error
576 *              if any duplicates are found.
577 *
578 ******************************************************************************/
579
580void
581RsCheckListForDuplicates (
582    ACPI_PARSE_OBJECT       *Op)
583{
584    ACPI_PARSE_OBJECT       *NextValueOp = Op;
585    ACPI_PARSE_OBJECT       *NextOp;
586    UINT32                  Value;
587
588
589    if (!Op)
590    {
591        return;
592    }
593
594    /* Search list once for each value in the list */
595
596    while (NextValueOp)
597    {
598        Value = (UINT32) NextValueOp->Asl.Value.Integer;
599
600        /* Compare this value to all remaining values in the list */
601
602        NextOp = ASL_GET_PEER_NODE (NextValueOp);
603        while (NextOp)
604        {
605            if (NextOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
606            {
607                /* Compare values */
608
609                if (Value == (UINT32) NextOp->Asl.Value.Integer)
610                {
611                    /* Emit error only once per duplicate node */
612
613                    if (!(NextOp->Asl.CompileFlags & NODE_IS_DUPLICATE))
614                    {
615                        NextOp->Asl.CompileFlags |= NODE_IS_DUPLICATE;
616                        AslError (ASL_ERROR, ASL_MSG_DUPLICATE_ITEM,
617                            NextOp, NULL);
618                    }
619                }
620            }
621
622            NextOp = ASL_GET_PEER_NODE (NextOp);
623        }
624
625        NextValueOp = ASL_GET_PEER_NODE (NextValueOp);
626    }
627}
628
629
630/*******************************************************************************
631 *
632 * FUNCTION:    RsDoOneResourceDescriptor
633 *
634 * PARAMETERS:  DescriptorTypeOp    - Parent parse node of the descriptor
635 *              CurrentByteOffset   - Offset in the resource descriptor
636 *                                    buffer.
637 *
638 * RETURN:      A valid resource node for the descriptor
639 *
640 * DESCRIPTION: Dispatches the processing of one resource descriptor
641 *
642 ******************************************************************************/
643
644ASL_RESOURCE_NODE *
645RsDoOneResourceDescriptor (
646    ACPI_PARSE_OBJECT       *DescriptorTypeOp,
647    UINT32                  CurrentByteOffset,
648    UINT8                   *State)
649{
650    ASL_RESOURCE_NODE       *Rnode = NULL;
651
652
653    /* Construct the resource */
654
655    switch (DescriptorTypeOp->Asl.ParseOpcode)
656    {
657    case PARSEOP_DMA:
658        Rnode = RsDoDmaDescriptor (DescriptorTypeOp,
659                    CurrentByteOffset);
660        break;
661
662    case PARSEOP_FIXEDDMA:
663        Rnode = RsDoFixedDmaDescriptor (DescriptorTypeOp,
664                    CurrentByteOffset);
665        break;
666
667    case PARSEOP_DWORDIO:
668        Rnode = RsDoDwordIoDescriptor (DescriptorTypeOp,
669                    CurrentByteOffset);
670        break;
671
672    case PARSEOP_DWORDMEMORY:
673        Rnode = RsDoDwordMemoryDescriptor (DescriptorTypeOp,
674                    CurrentByteOffset);
675        break;
676
677    case PARSEOP_DWORDSPACE:
678        Rnode = RsDoDwordSpaceDescriptor (DescriptorTypeOp,
679                    CurrentByteOffset);
680        break;
681
682    case PARSEOP_ENDDEPENDENTFN:
683        switch (*State)
684        {
685        case ACPI_RSTATE_NORMAL:
686            AslError (ASL_ERROR, ASL_MSG_MISSING_STARTDEPENDENT,
687                DescriptorTypeOp, NULL);
688            break;
689
690        case ACPI_RSTATE_START_DEPENDENT:
691            AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
692                DescriptorTypeOp, NULL);
693            break;
694
695        case ACPI_RSTATE_DEPENDENT_LIST:
696        default:
697            break;
698        }
699
700        *State = ACPI_RSTATE_NORMAL;
701        Rnode = RsDoEndDependentDescriptor (DescriptorTypeOp,
702                    CurrentByteOffset);
703        break;
704
705    case PARSEOP_ENDTAG:
706        Rnode = RsDoEndTagDescriptor (DescriptorTypeOp,
707                    CurrentByteOffset);
708        break;
709
710    case PARSEOP_EXTENDEDIO:
711        Rnode = RsDoExtendedIoDescriptor (DescriptorTypeOp,
712                    CurrentByteOffset);
713        break;
714
715    case PARSEOP_EXTENDEDMEMORY:
716        Rnode = RsDoExtendedMemoryDescriptor (DescriptorTypeOp,
717                    CurrentByteOffset);
718        break;
719
720    case PARSEOP_EXTENDEDSPACE:
721        Rnode = RsDoExtendedSpaceDescriptor (DescriptorTypeOp,
722                    CurrentByteOffset);
723        break;
724
725    case PARSEOP_FIXEDIO:
726        Rnode = RsDoFixedIoDescriptor (DescriptorTypeOp,
727                    CurrentByteOffset);
728        break;
729
730    case PARSEOP_INTERRUPT:
731        Rnode = RsDoInterruptDescriptor (DescriptorTypeOp,
732                    CurrentByteOffset);
733        break;
734
735    case PARSEOP_IO:
736        Rnode = RsDoIoDescriptor (DescriptorTypeOp,
737                    CurrentByteOffset);
738        break;
739
740    case PARSEOP_IRQ:
741        Rnode = RsDoIrqDescriptor (DescriptorTypeOp,
742                    CurrentByteOffset);
743        break;
744
745    case PARSEOP_IRQNOFLAGS:
746        Rnode = RsDoIrqNoFlagsDescriptor (DescriptorTypeOp,
747                    CurrentByteOffset);
748        break;
749
750    case PARSEOP_MEMORY24:
751        Rnode = RsDoMemory24Descriptor (DescriptorTypeOp,
752                    CurrentByteOffset);
753        break;
754
755    case PARSEOP_MEMORY32:
756        Rnode = RsDoMemory32Descriptor (DescriptorTypeOp,
757                    CurrentByteOffset);
758        break;
759
760    case PARSEOP_MEMORY32FIXED:
761        Rnode = RsDoMemory32FixedDescriptor (DescriptorTypeOp,
762                    CurrentByteOffset);
763        break;
764
765    case PARSEOP_QWORDIO:
766        Rnode = RsDoQwordIoDescriptor (DescriptorTypeOp,
767                    CurrentByteOffset);
768        break;
769
770    case PARSEOP_QWORDMEMORY:
771        Rnode = RsDoQwordMemoryDescriptor (DescriptorTypeOp,
772                    CurrentByteOffset);
773        break;
774
775    case PARSEOP_QWORDSPACE:
776        Rnode = RsDoQwordSpaceDescriptor (DescriptorTypeOp,
777                    CurrentByteOffset);
778        break;
779
780    case PARSEOP_REGISTER:
781        Rnode = RsDoGeneralRegisterDescriptor (DescriptorTypeOp,
782                    CurrentByteOffset);
783        break;
784
785    case PARSEOP_STARTDEPENDENTFN:
786        switch (*State)
787        {
788        case ACPI_RSTATE_START_DEPENDENT:
789            AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
790                DescriptorTypeOp, NULL);
791            break;
792
793        case ACPI_RSTATE_NORMAL:
794        case ACPI_RSTATE_DEPENDENT_LIST:
795        default:
796            break;
797        }
798
799        *State = ACPI_RSTATE_START_DEPENDENT;
800        Rnode = RsDoStartDependentDescriptor (DescriptorTypeOp,
801                    CurrentByteOffset);
802        *State = ACPI_RSTATE_DEPENDENT_LIST;
803        break;
804
805    case PARSEOP_STARTDEPENDENTFN_NOPRI:
806        switch (*State)
807        {
808        case ACPI_RSTATE_START_DEPENDENT:
809            AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
810                DescriptorTypeOp, NULL);
811            break;
812
813        case ACPI_RSTATE_NORMAL:
814        case ACPI_RSTATE_DEPENDENT_LIST:
815        default:
816            break;
817        }
818
819        *State = ACPI_RSTATE_START_DEPENDENT;
820        Rnode = RsDoStartDependentNoPriDescriptor (DescriptorTypeOp,
821                    CurrentByteOffset);
822        *State = ACPI_RSTATE_DEPENDENT_LIST;
823        break;
824
825    case PARSEOP_VENDORLONG:
826        Rnode = RsDoVendorLargeDescriptor (DescriptorTypeOp,
827                    CurrentByteOffset);
828        break;
829
830    case PARSEOP_VENDORSHORT:
831        Rnode = RsDoVendorSmallDescriptor (DescriptorTypeOp,
832                    CurrentByteOffset);
833        break;
834
835    case PARSEOP_WORDBUSNUMBER:
836        Rnode = RsDoWordBusNumberDescriptor (DescriptorTypeOp,
837                    CurrentByteOffset);
838        break;
839
840    case PARSEOP_WORDIO:
841        Rnode = RsDoWordIoDescriptor (DescriptorTypeOp,
842                    CurrentByteOffset);
843        break;
844
845    case PARSEOP_WORDSPACE:
846        Rnode = RsDoWordSpaceDescriptor (DescriptorTypeOp,
847                    CurrentByteOffset);
848        break;
849
850    case PARSEOP_GPIO_INT:
851        Rnode = RsDoGpioIntDescriptor (DescriptorTypeOp,
852                    CurrentByteOffset);
853        break;
854
855    case PARSEOP_GPIO_IO:
856        Rnode = RsDoGpioIoDescriptor (DescriptorTypeOp,
857                    CurrentByteOffset);
858        break;
859
860    case PARSEOP_I2C_SERIALBUS:
861        Rnode = RsDoI2cSerialBusDescriptor (DescriptorTypeOp,
862                    CurrentByteOffset);
863        break;
864
865    case PARSEOP_SPI_SERIALBUS:
866        Rnode = RsDoSpiSerialBusDescriptor (DescriptorTypeOp,
867                    CurrentByteOffset);
868        break;
869
870    case PARSEOP_UART_SERIALBUS:
871        Rnode = RsDoUartSerialBusDescriptor (DescriptorTypeOp,
872                    CurrentByteOffset);
873        break;
874
875    case PARSEOP_DEFAULT_ARG:
876        /* Just ignore any of these, they are used as fillers/placeholders */
877        break;
878
879    default:
880        printf ("Unknown resource descriptor type [%s]\n",
881                    DescriptorTypeOp->Asl.ParseOpName);
882        break;
883    }
884
885    /*
886     * Mark original node as unused, but head of a resource descriptor.
887     * This allows the resource to be installed in the namespace so that
888     * references to the descriptor can be resolved.
889     */
890    DescriptorTypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
891    DescriptorTypeOp->Asl.CompileFlags = NODE_IS_RESOURCE_DESC;
892    DescriptorTypeOp->Asl.Value.Integer = CurrentByteOffset;
893
894    if (Rnode)
895    {
896        DescriptorTypeOp->Asl.FinalAmlLength = Rnode->BufferLength;
897        DescriptorTypeOp->Asl.Extra = ((AML_RESOURCE *) Rnode->Buffer)->DescriptorType;
898    }
899
900    return (Rnode);
901}
902
903
904/*******************************************************************************
905 *
906 * FUNCTION:    RsLinkDescriptorChain
907 *
908 * PARAMETERS:  PreviousRnode       - Pointer to the node that will be previous
909 *                                    to the linked node,  At exit, set to the
910 *                                    last node in the new chain.
911 *              Rnode               - Resource node to link into the list
912 *
913 * RETURN:      Cumulative buffer byte offset of the new segment of chain
914 *
915 * DESCRIPTION: Link a descriptor chain at the end of an existing chain.
916 *
917 ******************************************************************************/
918
919UINT32
920RsLinkDescriptorChain (
921    ASL_RESOURCE_NODE       **PreviousRnode,
922    ASL_RESOURCE_NODE       *Rnode)
923{
924    ASL_RESOURCE_NODE       *LastRnode;
925    UINT32                  CurrentByteOffset;
926
927
928    /* Anything to do? */
929
930    if (!Rnode)
931    {
932        return (0);
933    }
934
935    /* Point the previous node to the new node */
936
937    (*PreviousRnode)->Next = Rnode;
938    CurrentByteOffset = Rnode->BufferLength;
939
940    /* Walk to the end of the chain headed by Rnode */
941
942    LastRnode = Rnode;
943    while (LastRnode->Next)
944    {
945        LastRnode = LastRnode->Next;
946        CurrentByteOffset += LastRnode->BufferLength;
947    }
948
949    /* Previous node becomes the last node in the chain */
950
951    *PreviousRnode = LastRnode;
952    return (CurrentByteOffset);
953}
954
955
956/*******************************************************************************
957 *
958 * FUNCTION:    RsDoResourceTemplate
959 *
960 * PARAMETERS:  Op        - Parent of a resource template list
961 *
962 * RETURN:      None. Sets input node to point to a list of AML code
963 *
964 * DESCRIPTION: Merge a list of resource descriptors into a single AML buffer,
965 *              in preparation for output to the AML output file.
966 *
967 ******************************************************************************/
968
969void
970RsDoResourceTemplate (
971    ACPI_PARSE_OBJECT       *Op)
972{
973    ACPI_PARSE_OBJECT       *BufferLengthOp;
974    ACPI_PARSE_OBJECT       *BufferOp;
975    ACPI_PARSE_OBJECT       *DescriptorTypeOp;
976    ACPI_PARSE_OBJECT       *LastOp = NULL;
977    UINT32                  CurrentByteOffset = 0;
978    ASL_RESOURCE_NODE       HeadRnode;
979    ASL_RESOURCE_NODE       *PreviousRnode;
980    ASL_RESOURCE_NODE       *Rnode;
981    UINT8                   State;
982
983
984    /* Mark parent as containing a resource template */
985
986    if (Op->Asl.Parent)
987    {
988        Op->Asl.Parent->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
989    }
990
991    /* ResourceTemplate Opcode is first (Op) */
992    /* Buffer Length node is first child */
993
994    BufferLengthOp = ASL_GET_CHILD_NODE (Op);
995
996    /* Buffer Op is first peer */
997
998    BufferOp = ASL_GET_PEER_NODE (BufferLengthOp);
999
1000    /* First Descriptor type is next */
1001
1002    DescriptorTypeOp = ASL_GET_PEER_NODE (BufferOp);
1003
1004    /*
1005     * Process all resource descriptors in the list
1006     * Note: It is assumed that the EndTag node has been automatically
1007     * inserted at the end of the template by the parser.
1008     */
1009    State = ACPI_RSTATE_NORMAL;
1010    PreviousRnode = &HeadRnode;
1011    while (DescriptorTypeOp)
1012    {
1013        DescriptorTypeOp->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
1014        Rnode = RsDoOneResourceDescriptor (DescriptorTypeOp, CurrentByteOffset,
1015                    &State);
1016
1017        /*
1018         * Update current byte offset to indicate the number of bytes from the
1019         * start of the buffer. Buffer can include multiple descriptors, we
1020         * must keep track of the offset of not only each descriptor, but each
1021         * element (field) within each descriptor as well.
1022         */
1023        CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, Rnode);
1024
1025        /* Get the next descriptor in the list */
1026
1027        LastOp = DescriptorTypeOp;
1028        DescriptorTypeOp = ASL_GET_PEER_NODE (DescriptorTypeOp);
1029    }
1030
1031    if (State == ACPI_RSTATE_DEPENDENT_LIST)
1032    {
1033        if (LastOp)
1034        {
1035            LastOp = LastOp->Asl.Parent;
1036        }
1037        AslError (ASL_ERROR, ASL_MSG_MISSING_ENDDEPENDENT, LastOp, NULL);
1038    }
1039
1040    /*
1041     * Transform the nodes into the following
1042     *
1043     * Op           -> AML_BUFFER_OP
1044     * First Child  -> BufferLength
1045     * Second Child -> Descriptor Buffer (raw byte data)
1046     */
1047    Op->Asl.ParseOpcode               = PARSEOP_BUFFER;
1048    Op->Asl.AmlOpcode                 = AML_BUFFER_OP;
1049    Op->Asl.CompileFlags              = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC;
1050    UtSetParseOpName (Op);
1051
1052    BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
1053    BufferLengthOp->Asl.Value.Integer = CurrentByteOffset;
1054    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
1055    UtSetParseOpName (BufferLengthOp);
1056
1057    BufferOp->Asl.ParseOpcode         = PARSEOP_RAW_DATA;
1058    BufferOp->Asl.AmlOpcode           = AML_RAW_DATA_CHAIN;
1059    BufferOp->Asl.AmlOpcodeLength     = 0;
1060    BufferOp->Asl.AmlLength           = CurrentByteOffset;
1061    BufferOp->Asl.Value.Buffer        = (UINT8 *) HeadRnode.Next;
1062    BufferOp->Asl.CompileFlags       |= NODE_IS_RESOURCE_DATA;
1063    UtSetParseOpName (BufferOp);
1064
1065    return;
1066}
1067