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
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        InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
400    }
401
402    return (0);
403}
404
405
406/*******************************************************************************
407 *
408 * FUNCTION:    RsAllocateResourceNode
409 *
410 * PARAMETERS:  Size        - Size of node in bytes
411 *
412 * RETURN:      The allocated node - aborts on allocation failure
413 *
414 * DESCRIPTION: Allocate a resource description node and the resource
415 *              descriptor itself (the nodes are used to link descriptors).
416 *
417 ******************************************************************************/
418
419ASL_RESOURCE_NODE *
420RsAllocateResourceNode (
421    UINT32                  Size)
422{
423    ASL_RESOURCE_NODE       *Rnode;
424
425
426    /* Allocate the node */
427
428    Rnode = UtLocalCalloc (sizeof (ASL_RESOURCE_NODE));
429
430    /* Allocate the resource descriptor itself */
431
432    Rnode->Buffer = UtLocalCalloc (Size);
433    Rnode->BufferLength = Size;
434
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
471    Op->Asl.Value.Tag.BitOffset = (ByteOffset * 8) + BitOffset;
472    Op->Asl.Value.Tag.BitLength = BitLength;
473}
474
475
476/*******************************************************************************
477 *
478 * FUNCTION:    RsSetFlagBits
479 *
480 * PARAMETERS:  *Flags          - Pointer to the flag byte
481 *              Op              - Flag initialization node
482 *              Position        - Bit position within the flag byte
483 *              Default         - Used if the node is DEFAULT.
484 *
485 * RETURN:      Sets bits within the *Flags output byte.
486 *
487 * DESCRIPTION: Set a bit in a cumulative flags word from an initialization
488 *              node. Will use a default value if the node is DEFAULT, meaning
489 *              that no value was specified in the ASL. Used to merge multiple
490 *              keywords into a single flags byte.
491 *
492 ******************************************************************************/
493
494void
495RsSetFlagBits (
496    UINT8                   *Flags,
497    ACPI_PARSE_OBJECT       *Op,
498    UINT8                   Position,
499    UINT8                   DefaultBit)
500{
501
502    if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
503    {
504        /* Use the default bit */
505
506        *Flags |= (DefaultBit << Position);
507    }
508    else
509    {
510        /* Use the bit specified in the initialization node */
511
512        *Flags |= (((UINT8) Op->Asl.Value.Integer) << Position);
513    }
514}
515
516
517void
518RsSetFlagBits16 (
519    UINT16                  *Flags,
520    ACPI_PARSE_OBJECT       *Op,
521    UINT8                   Position,
522    UINT8                   DefaultBit)
523{
524
525    if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
526    {
527        /* Use the default bit */
528
529        *Flags |= (DefaultBit << Position);
530    }
531    else
532    {
533        /* Use the bit specified in the initialization node */
534
535        *Flags |= (((UINT16) Op->Asl.Value.Integer) << Position);
536    }
537}
538
539
540/*******************************************************************************
541 *
542 * FUNCTION:    RsCompleteNodeAndGetNext
543 *
544 * PARAMETERS:  Op            - Resource node to be completed
545 *
546 * RETURN:      The next peer to the input node.
547 *
548 * DESCRIPTION: Mark the current node completed and return the next peer.
549 *              The node ParseOpcode is set to DEFAULT_ARG, meaning that
550 *              this node is to be ignored from now on.
551 *
552 ******************************************************************************/
553
554ACPI_PARSE_OBJECT *
555RsCompleteNodeAndGetNext (
556    ACPI_PARSE_OBJECT       *Op)
557{
558
559    /* Mark this node unused */
560
561    Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
562
563    /* Move on to the next peer node in the initializer list */
564
565    return (ASL_GET_PEER_NODE (Op));
566}
567
568
569/*******************************************************************************
570 *
571 * FUNCTION:    RsCheckListForDuplicates
572 *
573 * PARAMETERS:  Op                  - First op in the initializer list
574 *
575 * RETURN:      None
576 *
577 * DESCRIPTION: Check an initializer list for duplicate values. Emits an error
578 *              if any duplicates are found.
579 *
580 ******************************************************************************/
581
582void
583RsCheckListForDuplicates (
584    ACPI_PARSE_OBJECT       *Op)
585{
586    ACPI_PARSE_OBJECT       *NextValueOp = Op;
587    ACPI_PARSE_OBJECT       *NextOp;
588    UINT32                  Value;
589
590
591    if (!Op)
592    {
593        return;
594    }
595
596    /* Search list once for each value in the list */
597
598    while (NextValueOp)
599    {
600        Value = (UINT32) NextValueOp->Asl.Value.Integer;
601
602        /* Compare this value to all remaining values in the list */
603
604        NextOp = ASL_GET_PEER_NODE (NextValueOp);
605        while (NextOp)
606        {
607            if (NextOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
608            {
609                /* Compare values */
610
611                if (Value == (UINT32) NextOp->Asl.Value.Integer)
612                {
613                    /* Emit error only once per duplicate node */
614
615                    if (!(NextOp->Asl.CompileFlags & NODE_IS_DUPLICATE))
616                    {
617                        NextOp->Asl.CompileFlags |= NODE_IS_DUPLICATE;
618                        AslError (ASL_ERROR, ASL_MSG_DUPLICATE_ITEM,
619                            NextOp, NULL);
620                    }
621                }
622            }
623
624            NextOp = ASL_GET_PEER_NODE (NextOp);
625        }
626
627        NextValueOp = ASL_GET_PEER_NODE (NextValueOp);
628    }
629}
630
631
632/*******************************************************************************
633 *
634 * FUNCTION:    RsDoOneResourceDescriptor
635 *
636 * PARAMETERS:  DescriptorTypeOp    - Parent parse node of the descriptor
637 *              CurrentByteOffset   - Offset in the resource descriptor
638 *                                    buffer.
639 *
640 * RETURN:      A valid resource node for the descriptor
641 *
642 * DESCRIPTION: Dispatches the processing of one resource descriptor
643 *
644 ******************************************************************************/
645
646ASL_RESOURCE_NODE *
647RsDoOneResourceDescriptor (
648    ACPI_PARSE_OBJECT       *DescriptorTypeOp,
649    UINT32                  CurrentByteOffset,
650    UINT8                   *State)
651{
652    ASL_RESOURCE_NODE       *Rnode = NULL;
653
654
655    /* Construct the resource */
656
657    switch (DescriptorTypeOp->Asl.ParseOpcode)
658    {
659    case PARSEOP_DMA:
660
661        Rnode = RsDoDmaDescriptor (DescriptorTypeOp,
662                    CurrentByteOffset);
663        break;
664
665    case PARSEOP_FIXEDDMA:
666
667        Rnode = RsDoFixedDmaDescriptor (DescriptorTypeOp,
668                    CurrentByteOffset);
669        break;
670
671    case PARSEOP_DWORDIO:
672
673        Rnode = RsDoDwordIoDescriptor (DescriptorTypeOp,
674                    CurrentByteOffset);
675        break;
676
677    case PARSEOP_DWORDMEMORY:
678
679        Rnode = RsDoDwordMemoryDescriptor (DescriptorTypeOp,
680                    CurrentByteOffset);
681        break;
682
683    case PARSEOP_DWORDSPACE:
684
685        Rnode = RsDoDwordSpaceDescriptor (DescriptorTypeOp,
686                    CurrentByteOffset);
687        break;
688
689    case PARSEOP_ENDDEPENDENTFN:
690
691        switch (*State)
692        {
693        case ACPI_RSTATE_NORMAL:
694
695            AslError (ASL_ERROR, ASL_MSG_MISSING_STARTDEPENDENT,
696                DescriptorTypeOp, NULL);
697            break;
698
699        case ACPI_RSTATE_START_DEPENDENT:
700
701            AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
702                DescriptorTypeOp, NULL);
703            break;
704
705        case ACPI_RSTATE_DEPENDENT_LIST:
706        default:
707
708            break;
709        }
710
711        *State = ACPI_RSTATE_NORMAL;
712        Rnode = RsDoEndDependentDescriptor (DescriptorTypeOp,
713                    CurrentByteOffset);
714        break;
715
716    case PARSEOP_ENDTAG:
717
718        Rnode = RsDoEndTagDescriptor (DescriptorTypeOp,
719                    CurrentByteOffset);
720        break;
721
722    case PARSEOP_EXTENDEDIO:
723
724        Rnode = RsDoExtendedIoDescriptor (DescriptorTypeOp,
725                    CurrentByteOffset);
726        break;
727
728    case PARSEOP_EXTENDEDMEMORY:
729
730        Rnode = RsDoExtendedMemoryDescriptor (DescriptorTypeOp,
731                    CurrentByteOffset);
732        break;
733
734    case PARSEOP_EXTENDEDSPACE:
735
736        Rnode = RsDoExtendedSpaceDescriptor (DescriptorTypeOp,
737                    CurrentByteOffset);
738        break;
739
740    case PARSEOP_FIXEDIO:
741
742        Rnode = RsDoFixedIoDescriptor (DescriptorTypeOp,
743                    CurrentByteOffset);
744        break;
745
746    case PARSEOP_INTERRUPT:
747
748        Rnode = RsDoInterruptDescriptor (DescriptorTypeOp,
749                    CurrentByteOffset);
750        break;
751
752    case PARSEOP_IO:
753
754        Rnode = RsDoIoDescriptor (DescriptorTypeOp,
755                    CurrentByteOffset);
756        break;
757
758    case PARSEOP_IRQ:
759
760        Rnode = RsDoIrqDescriptor (DescriptorTypeOp,
761                    CurrentByteOffset);
762        break;
763
764    case PARSEOP_IRQNOFLAGS:
765
766        Rnode = RsDoIrqNoFlagsDescriptor (DescriptorTypeOp,
767                    CurrentByteOffset);
768        break;
769
770    case PARSEOP_MEMORY24:
771
772        Rnode = RsDoMemory24Descriptor (DescriptorTypeOp,
773                    CurrentByteOffset);
774        break;
775
776    case PARSEOP_MEMORY32:
777
778        Rnode = RsDoMemory32Descriptor (DescriptorTypeOp,
779                    CurrentByteOffset);
780        break;
781
782    case PARSEOP_MEMORY32FIXED:
783
784        Rnode = RsDoMemory32FixedDescriptor (DescriptorTypeOp,
785                    CurrentByteOffset);
786        break;
787
788    case PARSEOP_QWORDIO:
789
790        Rnode = RsDoQwordIoDescriptor (DescriptorTypeOp,
791                    CurrentByteOffset);
792        break;
793
794    case PARSEOP_QWORDMEMORY:
795
796        Rnode = RsDoQwordMemoryDescriptor (DescriptorTypeOp,
797                    CurrentByteOffset);
798        break;
799
800    case PARSEOP_QWORDSPACE:
801
802        Rnode = RsDoQwordSpaceDescriptor (DescriptorTypeOp,
803                    CurrentByteOffset);
804        break;
805
806    case PARSEOP_REGISTER:
807
808        Rnode = RsDoGeneralRegisterDescriptor (DescriptorTypeOp,
809                    CurrentByteOffset);
810        break;
811
812    case PARSEOP_STARTDEPENDENTFN:
813
814        switch (*State)
815        {
816        case ACPI_RSTATE_START_DEPENDENT:
817
818            AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
819                DescriptorTypeOp, NULL);
820            break;
821
822        case ACPI_RSTATE_NORMAL:
823        case ACPI_RSTATE_DEPENDENT_LIST:
824        default:
825
826            break;
827        }
828
829        *State = ACPI_RSTATE_START_DEPENDENT;
830        Rnode = RsDoStartDependentDescriptor (DescriptorTypeOp,
831                    CurrentByteOffset);
832        *State = ACPI_RSTATE_DEPENDENT_LIST;
833        break;
834
835    case PARSEOP_STARTDEPENDENTFN_NOPRI:
836
837        switch (*State)
838        {
839        case ACPI_RSTATE_START_DEPENDENT:
840
841            AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
842                DescriptorTypeOp, NULL);
843            break;
844
845        case ACPI_RSTATE_NORMAL:
846        case ACPI_RSTATE_DEPENDENT_LIST:
847        default:
848
849            break;
850        }
851
852        *State = ACPI_RSTATE_START_DEPENDENT;
853        Rnode = RsDoStartDependentNoPriDescriptor (DescriptorTypeOp,
854                    CurrentByteOffset);
855        *State = ACPI_RSTATE_DEPENDENT_LIST;
856        break;
857
858    case PARSEOP_VENDORLONG:
859
860        Rnode = RsDoVendorLargeDescriptor (DescriptorTypeOp,
861                    CurrentByteOffset);
862        break;
863
864    case PARSEOP_VENDORSHORT:
865
866        Rnode = RsDoVendorSmallDescriptor (DescriptorTypeOp,
867                    CurrentByteOffset);
868        break;
869
870    case PARSEOP_WORDBUSNUMBER:
871
872        Rnode = RsDoWordBusNumberDescriptor (DescriptorTypeOp,
873                    CurrentByteOffset);
874        break;
875
876    case PARSEOP_WORDIO:
877
878        Rnode = RsDoWordIoDescriptor (DescriptorTypeOp,
879                    CurrentByteOffset);
880        break;
881
882    case PARSEOP_WORDSPACE:
883
884        Rnode = RsDoWordSpaceDescriptor (DescriptorTypeOp,
885                    CurrentByteOffset);
886        break;
887
888    case PARSEOP_GPIO_INT:
889
890        Rnode = RsDoGpioIntDescriptor (DescriptorTypeOp,
891                    CurrentByteOffset);
892        break;
893
894    case PARSEOP_GPIO_IO:
895
896        Rnode = RsDoGpioIoDescriptor (DescriptorTypeOp,
897                    CurrentByteOffset);
898        break;
899
900    case PARSEOP_I2C_SERIALBUS:
901
902        Rnode = RsDoI2cSerialBusDescriptor (DescriptorTypeOp,
903                    CurrentByteOffset);
904        break;
905
906    case PARSEOP_SPI_SERIALBUS:
907
908        Rnode = RsDoSpiSerialBusDescriptor (DescriptorTypeOp,
909                    CurrentByteOffset);
910        break;
911
912    case PARSEOP_UART_SERIALBUS:
913
914        Rnode = RsDoUartSerialBusDescriptor (DescriptorTypeOp,
915                    CurrentByteOffset);
916        break;
917
918    case PARSEOP_DEFAULT_ARG:
919
920        /* Just ignore any of these, they are used as fillers/placeholders */
921        break;
922
923    default:
924
925        printf ("Unknown resource descriptor type [%s]\n",
926                    DescriptorTypeOp->Asl.ParseOpName);
927        break;
928    }
929
930    /*
931     * Mark original node as unused, but head of a resource descriptor.
932     * This allows the resource to be installed in the namespace so that
933     * references to the descriptor can be resolved.
934     */
935    DescriptorTypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
936    DescriptorTypeOp->Asl.CompileFlags = NODE_IS_RESOURCE_DESC;
937    DescriptorTypeOp->Asl.Value.Integer = CurrentByteOffset;
938
939    if (Rnode)
940    {
941        DescriptorTypeOp->Asl.FinalAmlLength = Rnode->BufferLength;
942        DescriptorTypeOp->Asl.Extra = ((AML_RESOURCE *) Rnode->Buffer)->DescriptorType;
943    }
944
945    return (Rnode);
946}
947
948
949/*******************************************************************************
950 *
951 * FUNCTION:    RsLinkDescriptorChain
952 *
953 * PARAMETERS:  PreviousRnode       - Pointer to the node that will be previous
954 *                                    to the linked node,  At exit, set to the
955 *                                    last node in the new chain.
956 *              Rnode               - Resource node to link into the list
957 *
958 * RETURN:      Cumulative buffer byte offset of the new segment of chain
959 *
960 * DESCRIPTION: Link a descriptor chain at the end of an existing chain.
961 *
962 ******************************************************************************/
963
964UINT32
965RsLinkDescriptorChain (
966    ASL_RESOURCE_NODE       **PreviousRnode,
967    ASL_RESOURCE_NODE       *Rnode)
968{
969    ASL_RESOURCE_NODE       *LastRnode;
970    UINT32                  CurrentByteOffset;
971
972
973    /* Anything to do? */
974
975    if (!Rnode)
976    {
977        return (0);
978    }
979
980    /* Point the previous node to the new node */
981
982    (*PreviousRnode)->Next = Rnode;
983    CurrentByteOffset = Rnode->BufferLength;
984
985    /* Walk to the end of the chain headed by Rnode */
986
987    LastRnode = Rnode;
988    while (LastRnode->Next)
989    {
990        LastRnode = LastRnode->Next;
991        CurrentByteOffset += LastRnode->BufferLength;
992    }
993
994    /* Previous node becomes the last node in the chain */
995
996    *PreviousRnode = LastRnode;
997    return (CurrentByteOffset);
998}
999
1000
1001/*******************************************************************************
1002 *
1003 * FUNCTION:    RsDoResourceTemplate
1004 *
1005 * PARAMETERS:  Op        - Parent of a resource template list
1006 *
1007 * RETURN:      None. Sets input node to point to a list of AML code
1008 *
1009 * DESCRIPTION: Merge a list of resource descriptors into a single AML buffer,
1010 *              in preparation for output to the AML output file.
1011 *
1012 ******************************************************************************/
1013
1014void
1015RsDoResourceTemplate (
1016    ACPI_PARSE_OBJECT       *Op)
1017{
1018    ACPI_PARSE_OBJECT       *BufferLengthOp;
1019    ACPI_PARSE_OBJECT       *BufferOp;
1020    ACPI_PARSE_OBJECT       *DescriptorTypeOp;
1021    ACPI_PARSE_OBJECT       *LastOp = NULL;
1022    UINT32                  CurrentByteOffset = 0;
1023    ASL_RESOURCE_NODE       HeadRnode;
1024    ASL_RESOURCE_NODE       *PreviousRnode;
1025    ASL_RESOURCE_NODE       *Rnode;
1026    UINT8                   State;
1027
1028
1029    /* Mark parent as containing a resource template */
1030
1031    if (Op->Asl.Parent)
1032    {
1033        Op->Asl.Parent->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
1034    }
1035
1036    /* ResourceTemplate Opcode is first (Op) */
1037    /* Buffer Length node is first child */
1038
1039    BufferLengthOp = ASL_GET_CHILD_NODE (Op);
1040
1041    /* Buffer Op is first peer */
1042
1043    BufferOp = ASL_GET_PEER_NODE (BufferLengthOp);
1044
1045    /* First Descriptor type is next */
1046
1047    DescriptorTypeOp = ASL_GET_PEER_NODE (BufferOp);
1048
1049    /*
1050     * Process all resource descriptors in the list
1051     * Note: It is assumed that the EndTag node has been automatically
1052     * inserted at the end of the template by the parser.
1053     */
1054    State = ACPI_RSTATE_NORMAL;
1055    PreviousRnode = &HeadRnode;
1056    while (DescriptorTypeOp)
1057    {
1058        DescriptorTypeOp->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
1059        Rnode = RsDoOneResourceDescriptor (DescriptorTypeOp, CurrentByteOffset,
1060                    &State);
1061
1062        /*
1063         * Update current byte offset to indicate the number of bytes from the
1064         * start of the buffer. Buffer can include multiple descriptors, we
1065         * must keep track of the offset of not only each descriptor, but each
1066         * element (field) within each descriptor as well.
1067         */
1068        CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, Rnode);
1069
1070        /* Get the next descriptor in the list */
1071
1072        LastOp = DescriptorTypeOp;
1073        DescriptorTypeOp = ASL_GET_PEER_NODE (DescriptorTypeOp);
1074    }
1075
1076    if (State == ACPI_RSTATE_DEPENDENT_LIST)
1077    {
1078        if (LastOp)
1079        {
1080            LastOp = LastOp->Asl.Parent;
1081        }
1082        AslError (ASL_ERROR, ASL_MSG_MISSING_ENDDEPENDENT, LastOp, NULL);
1083    }
1084
1085    /*
1086     * Transform the nodes into the following
1087     *
1088     * Op           -> AML_BUFFER_OP
1089     * First Child  -> BufferLength
1090     * Second Child -> Descriptor Buffer (raw byte data)
1091     */
1092    Op->Asl.ParseOpcode               = PARSEOP_BUFFER;
1093    Op->Asl.AmlOpcode                 = AML_BUFFER_OP;
1094    Op->Asl.CompileFlags              = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC;
1095    UtSetParseOpName (Op);
1096
1097    BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
1098    BufferLengthOp->Asl.Value.Integer = CurrentByteOffset;
1099    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
1100    UtSetParseOpName (BufferLengthOp);
1101
1102    BufferOp->Asl.ParseOpcode         = PARSEOP_RAW_DATA;
1103    BufferOp->Asl.AmlOpcode           = AML_RAW_DATA_CHAIN;
1104    BufferOp->Asl.AmlOpcodeLength     = 0;
1105    BufferOp->Asl.AmlLength           = CurrentByteOffset;
1106    BufferOp->Asl.Value.Buffer        = (UINT8 *) HeadRnode.Next;
1107    BufferOp->Asl.CompileFlags       |= NODE_IS_RESOURCE_DATA;
1108    UtSetParseOpName (BufferOp);
1109
1110    return;
1111}
1112