aslresource.c revision 217365
1
2/******************************************************************************
3 *
4 * Module Name: aslresource - Resource template/descriptor utilities
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2011, Intel Corp.
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions, and the following disclaimer,
17 *    without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 *    substantially similar to the "NO WARRANTY" disclaimer below
20 *    ("Disclaimer") and any redistribution must be conditioned upon
21 *    including a substantially similar Disclaimer requirement for further
22 *    binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 *    of any contributors may be used to endorse or promote products derived
25 *    from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <contrib/dev/acpica/compiler/aslcompiler.h>
47#include "aslcompiler.y.h"
48#include <contrib/dev/acpica/include/amlcode.h>
49
50
51#define _COMPONENT          ACPI_COMPILER
52        ACPI_MODULE_NAME    ("aslresource")
53
54
55/*******************************************************************************
56 *
57 * FUNCTION:    RsSmallAddressCheck
58 *
59 * PARAMETERS:  Minimum             - Address Min value
60 *              Maximum             - Address Max value
61 *              Length              - Address range value
62 *              Alignment           - Address alignment value
63 *              MinOp               - Original Op for Address Min
64 *              MaxOp               - Original Op for Address Max
65 *              LengthOp            - Original Op for address range
66 *              AlignOp             - Original Op for address alignment. If
67 *                                    NULL, means "zero value for alignment is
68 *                                    OK, and means 64K alignment" (for
69 *                                    Memory24 descriptor)
70 *              Op                  - Parent Op for entire construct
71 *
72 * RETURN:      None. Adds error messages to error log if necessary
73 *
74 * DESCRIPTION: Perform common value checks for "small" address descriptors.
75 *              Currently:
76 *                  Io, Memory24, Memory32
77 *
78 ******************************************************************************/
79
80void
81RsSmallAddressCheck (
82    UINT8                   Type,
83    UINT32                  Minimum,
84    UINT32                  Maximum,
85    UINT32                  Length,
86    UINT32                  Alignment,
87    ACPI_PARSE_OBJECT       *MinOp,
88    ACPI_PARSE_OBJECT       *MaxOp,
89    ACPI_PARSE_OBJECT       *LengthOp,
90    ACPI_PARSE_OBJECT       *AlignOp,
91    ACPI_PARSE_OBJECT       *Op)
92{
93
94    if (Gbl_NoResourceChecking)
95    {
96        return;
97    }
98
99    /*
100     * Check for a so-called "null descriptor". These are descriptors that are
101     * created with most fields set to zero. The intent is that the descriptor
102     * will be updated/completed at runtime via a BufferField.
103     *
104     * If the descriptor does NOT have a resource tag, it cannot be referenced
105     * by a BufferField and we will flag this as an error. Conversely, if
106     * the descriptor has a resource tag, we will assume that a BufferField
107     * will be used to dynamically update it, so no error.
108     *
109     * A possible enhancement to this check would be to verify that in fact
110     * a BufferField is created using the resource tag, and perhaps even
111     * verify that a Store is performed to the BufferField.
112     *
113     * Note: for these descriptors, Alignment is allowed to be zero
114     */
115    if (!Minimum && !Maximum && !Length)
116    {
117        if (!Op->Asl.ExternalName)
118        {
119            /* No resource tag. Descriptor is fixed and is also illegal */
120
121            AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL);
122        }
123
124        return;
125    }
126
127    /* Special case for Memory24, values are compressed */
128
129    if (Type == ACPI_RESOURCE_NAME_MEMORY24)
130    {
131        if (!Alignment) /* Alignment==0 means 64K - no invalid alignment */
132        {
133            Alignment = ACPI_UINT16_MAX + 1;
134        }
135
136        Minimum <<= 8;
137        Maximum <<= 8;
138        Length *= 256;
139    }
140
141    /* IO descriptor has different definition of min/max, don't check */
142
143    if (Type != ACPI_RESOURCE_NAME_IO)
144    {
145        /* Basic checks on Min/Max/Length */
146
147        if (Minimum > Maximum)
148        {
149            AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL);
150        }
151        else if (Length > (Maximum - Minimum + 1))
152        {
153            AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL);
154        }
155    }
156
157    /* Alignment of zero is not in ACPI spec, but is used to mean byte acc */
158
159    if (!Alignment)
160    {
161        Alignment = 1;
162    }
163
164    /* Addresses must be an exact multiple of the alignment value */
165
166    if (Minimum % Alignment)
167    {
168        AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL);
169    }
170    if (Maximum % Alignment)
171    {
172        AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, NULL);
173    }
174}
175
176
177/*******************************************************************************
178 *
179 * FUNCTION:    RsLargeAddressCheck
180 *
181 * PARAMETERS:  Minimum             - Address Min value
182 *              Maximum             - Address Max value
183 *              Length              - Address range value
184 *              Granularity         - Address granularity value
185 *              Flags               - General flags for address descriptors:
186 *                                    _MIF, _MAF, _DEC
187 *              MinOp               - Original Op for Address Min
188 *              MaxOp               - Original Op for Address Max
189 *              LengthOp            - Original Op for address range
190 *              GranOp              - Original Op for address granularity
191 *              Op                  - Parent Op for entire construct
192 *
193 * RETURN:      None. Adds error messages to error log if necessary
194 *
195 * DESCRIPTION: Perform common value checks for "large" address descriptors.
196 *              Currently:
197 *                  WordIo,     WordBusNumber,  WordSpace
198 *                  DWordIo,    DWordMemory,    DWordSpace
199 *                  QWordIo,    QWordMemory,    QWordSpace
200 *                  ExtendedIo, ExtendedMemory, ExtendedSpace
201 *
202 * _MIF flag set means that the minimum address is fixed and is not relocatable
203 * _MAF flag set means that the maximum address is fixed and is not relocatable
204 * Length of zero means that the record size is variable
205 *
206 * This function implements the LEN/MIF/MAF/MIN/MAX/GRA rules within Table 6-40
207 * of the ACPI 4.0a specification. Added 04/2010.
208 *
209 ******************************************************************************/
210
211void
212RsLargeAddressCheck (
213    UINT64                  Minimum,
214    UINT64                  Maximum,
215    UINT64                  Length,
216    UINT64                  Granularity,
217    UINT8                   Flags,
218    ACPI_PARSE_OBJECT       *MinOp,
219    ACPI_PARSE_OBJECT       *MaxOp,
220    ACPI_PARSE_OBJECT       *LengthOp,
221    ACPI_PARSE_OBJECT       *GranOp,
222    ACPI_PARSE_OBJECT       *Op)
223{
224
225    if (Gbl_NoResourceChecking)
226    {
227        return;
228    }
229
230    /*
231     * Check for a so-called "null descriptor". These are descriptors that are
232     * created with most fields set to zero. The intent is that the descriptor
233     * will be updated/completed at runtime via a BufferField.
234     *
235     * If the descriptor does NOT have a resource tag, it cannot be referenced
236     * by a BufferField and we will flag this as an error. Conversely, if
237     * the descriptor has a resource tag, we will assume that a BufferField
238     * will be used to dynamically update it, so no error.
239     *
240     * A possible enhancement to this check would be to verify that in fact
241     * a BufferField is created using the resource tag, and perhaps even
242     * verify that a Store is performed to the BufferField.
243     */
244    if (!Minimum && !Maximum && !Length && !Granularity)
245    {
246        if (!Op->Asl.ExternalName)
247        {
248            /* No resource tag. Descriptor is fixed and is also illegal */
249
250            AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL);
251        }
252
253        return;
254    }
255
256    /* Basic checks on Min/Max/Length */
257
258    if (Minimum > Maximum)
259    {
260        AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL);
261        return;
262    }
263    else if (Length > (Maximum - Minimum + 1))
264    {
265        AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL);
266        return;
267    }
268
269    /* If specified (non-zero), ensure granularity is a power-of-two minus one */
270
271    if (Granularity)
272    {
273        if ((Granularity + 1) &
274             Granularity)
275        {
276            AslError (ASL_ERROR, ASL_MSG_INVALID_GRANULARITY, GranOp, NULL);
277            return;
278        }
279    }
280
281    /*
282     * Check the various combinations of Length, MinFixed, and MaxFixed
283     */
284    if (Length)
285    {
286        /* Fixed non-zero length */
287
288        switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF))
289        {
290        case 0:
291            /*
292             * Fixed length, variable locations (both _MIN and _MAX).
293             * Length must be a multiple of granularity
294             */
295            if (Granularity & Length)
296            {
297                AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, LengthOp, NULL);
298            }
299            break;
300
301        case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF):
302
303            /* Fixed length, fixed location. Granularity must be zero */
304
305            if (Granularity != 0)
306            {
307                AslError (ASL_ERROR, ASL_MSG_INVALID_GRAN_FIXED, GranOp, NULL);
308            }
309
310            /* Length must be exactly the size of the min/max window */
311
312            if (Length != (Maximum - Minimum + 1))
313            {
314                AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH_FIXED, LengthOp, NULL);
315            }
316            break;
317
318        /* All other combinations are invalid */
319
320        case ACPI_RESOURCE_FLAG_MIF:
321        case ACPI_RESOURCE_FLAG_MAF:
322        default:
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            AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL);
369        }
370    }
371}
372
373
374/*******************************************************************************
375 *
376 * FUNCTION:    RsGetStringDataLength
377 *
378 * PARAMETERS:  InitializerOp     - Start of a subtree of init nodes
379 *
380 * RETURN:      Valid string length if a string node is found (otherwise 0)
381 *
382 * DESCRIPTION: In a list of peer nodes, find the first one that contains a
383 *              string and return the length of the string.
384 *
385 ******************************************************************************/
386
387UINT16
388RsGetStringDataLength (
389    ACPI_PARSE_OBJECT       *InitializerOp)
390{
391
392    while (InitializerOp)
393    {
394        if (InitializerOp->Asl.ParseOpcode == PARSEOP_STRING_LITERAL)
395        {
396            return ((UINT16) (strlen (InitializerOp->Asl.Value.String) + 1));
397        }
398        InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
399    }
400
401    return 0;
402}
403
404
405/*******************************************************************************
406 *
407 * FUNCTION:    RsAllocateResourceNode
408 *
409 * PARAMETERS:  Size        - Size of node in bytes
410 *
411 * RETURN:      The allocated node - aborts on allocation failure
412 *
413 * DESCRIPTION: Allocate a resource description node and the resource
414 *              descriptor itself (the nodes are used to link descriptors).
415 *
416 ******************************************************************************/
417
418ASL_RESOURCE_NODE *
419RsAllocateResourceNode (
420    UINT32                  Size)
421{
422    ASL_RESOURCE_NODE       *Rnode;
423
424
425    /* Allocate the node */
426
427    Rnode = UtLocalCalloc (sizeof (ASL_RESOURCE_NODE));
428
429    /* Allocate the resource descriptor itself */
430
431    Rnode->Buffer = UtLocalCalloc (Size);
432    Rnode->BufferLength = Size;
433
434    return (Rnode);
435}
436
437
438/*******************************************************************************
439 *
440 * FUNCTION:    RsCreateBitField
441 *
442 * PARAMETERS:  Op              - Resource field node
443 *              Name            - Name of the field (Used only to reference
444 *                                the field in the ASL, not in the AML)
445 *              ByteOffset      - Offset from the field start
446 *              BitOffset       - Additional bit offset
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
457RsCreateBitField (
458    ACPI_PARSE_OBJECT       *Op,
459    char                    *Name,
460    UINT32                  ByteOffset,
461    UINT32                  BitOffset)
462{
463
464    Op->Asl.ExternalName      = Name;
465    Op->Asl.Value.Integer     = ((UINT64) ByteOffset * 8) + BitOffset;
466    Op->Asl.CompileFlags     |= (NODE_IS_RESOURCE_FIELD | NODE_IS_BIT_OFFSET);
467}
468
469
470/*******************************************************************************
471 *
472 * FUNCTION:    RsCreateByteField
473 *
474 * PARAMETERS:  Op              - Resource field node
475 *              Name            - Name of the field (Used only to reference
476 *                                the field in the ASL, not in the AML)
477 *              ByteOffset      - Offset from the field start
478 *
479 * RETURN:      None, sets fields within the input node
480 *
481 * DESCRIPTION: Utility function to generate a named byte field within a
482 *              resource descriptor.  Mark a node as 1) a field in a resource
483 *              descriptor, and 2) set the value to be a BYTE offset
484 *
485 ******************************************************************************/
486
487void
488RsCreateByteField (
489    ACPI_PARSE_OBJECT       *Op,
490    char                    *Name,
491    UINT32                  ByteOffset)
492{
493
494    Op->Asl.ExternalName      = Name;
495    Op->Asl.Value.Integer     = ByteOffset;
496    Op->Asl.CompileFlags     |= NODE_IS_RESOURCE_FIELD;
497}
498
499
500/*******************************************************************************
501 *
502 * FUNCTION:    RsSetFlagBits
503 *
504 * PARAMETERS:  *Flags          - Pointer to the flag byte
505 *              Op              - Flag initialization node
506 *              Position        - Bit position within the flag byte
507 *              Default         - Used if the node is DEFAULT.
508 *
509 * RETURN:      Sets bits within the *Flags output byte.
510 *
511 * DESCRIPTION: Set a bit in a cumulative flags word from an initialization
512 *              node.  Will use a default value if the node is DEFAULT, meaning
513 *              that no value was specified in the ASL.  Used to merge multiple
514 *              keywords into a single flags byte.
515 *
516 ******************************************************************************/
517
518void
519RsSetFlagBits (
520    UINT8                   *Flags,
521    ACPI_PARSE_OBJECT       *Op,
522    UINT8                   Position,
523    UINT8                   DefaultBit)
524{
525
526    if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
527    {
528        /* Use the default bit */
529
530        *Flags |= (DefaultBit << Position);
531    }
532    else
533    {
534        /* Use the bit specified in the initialization node */
535
536        *Flags |= (((UINT8) Op->Asl.Value.Integer) << Position);
537    }
538}
539
540
541/*******************************************************************************
542 *
543 * FUNCTION:    RsCompleteNodeAndGetNext
544 *
545 * PARAMETERS:  Op            - Resource node to be completed
546 *
547 * RETURN:      The next peer to the input node.
548 *
549 * DESCRIPTION: Mark the current node completed and return the next peer.
550 *              The node ParseOpcode is set to DEFAULT_ARG, meaning that
551 *              this node is to be ignored from now on.
552 *
553 ******************************************************************************/
554
555ACPI_PARSE_OBJECT *
556RsCompleteNodeAndGetNext (
557    ACPI_PARSE_OBJECT       *Op)
558{
559
560    /* Mark this node unused */
561
562    Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
563
564    /* Move on to the next peer node in the initializer list */
565
566    return (ASL_GET_PEER_NODE (Op));
567}
568
569
570/*******************************************************************************
571 *
572 * FUNCTION:    RsCheckListForDuplicates
573 *
574 * PARAMETERS:  Op                  - First op in the initializer list
575 *
576 * RETURN:      None
577 *
578 * DESCRIPTION: Check an initializer list for duplicate values. Emits an error
579 *              if any duplicates are found.
580 *
581 ******************************************************************************/
582
583void
584RsCheckListForDuplicates (
585    ACPI_PARSE_OBJECT       *Op)
586{
587    ACPI_PARSE_OBJECT       *NextValueOp = Op;
588    ACPI_PARSE_OBJECT       *NextOp;
589    UINT32                  Value;
590
591
592    if (!Op)
593    {
594        return;
595    }
596
597    /* Search list once for each value in the list */
598
599    while (NextValueOp)
600    {
601        Value = (UINT32) NextValueOp->Asl.Value.Integer;
602
603        /* Compare this value to all remaining values in the list */
604
605        NextOp = ASL_GET_PEER_NODE (NextValueOp);
606        while (NextOp)
607        {
608            if (NextOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
609            {
610                /* Compare values */
611
612                if (Value == (UINT32) NextOp->Asl.Value.Integer)
613                {
614                    /* Emit error only once per duplicate node */
615
616                    if (!(NextOp->Asl.CompileFlags & NODE_IS_DUPLICATE))
617                    {
618                        NextOp->Asl.CompileFlags |= NODE_IS_DUPLICATE;
619                        AslError (ASL_ERROR, ASL_MSG_DUPLICATE_ITEM,
620                            NextOp, NULL);
621                    }
622                }
623            }
624
625            NextOp = ASL_GET_PEER_NODE (NextOp);
626        }
627
628        NextValueOp = ASL_GET_PEER_NODE (NextValueOp);
629    }
630}
631
632
633/*******************************************************************************
634 *
635 * FUNCTION:    RsDoOneResourceDescriptor
636 *
637 * PARAMETERS:  DescriptorTypeOp    - Parent parse node of the descriptor
638 *              CurrentByteOffset   - Offset in the resource descriptor
639 *                                    buffer.
640 *
641 * RETURN:      A valid resource node for the descriptor
642 *
643 * DESCRIPTION: Dispatches the processing of one resource descriptor
644 *
645 ******************************************************************************/
646
647ASL_RESOURCE_NODE *
648RsDoOneResourceDescriptor (
649    ACPI_PARSE_OBJECT       *DescriptorTypeOp,
650    UINT32                  CurrentByteOffset,
651    UINT8                   *State)
652{
653    ASL_RESOURCE_NODE       *Rnode = NULL;
654
655
656    /* Construct the resource */
657
658    switch (DescriptorTypeOp->Asl.ParseOpcode)
659    {
660    case PARSEOP_DMA:
661        Rnode = RsDoDmaDescriptor (DescriptorTypeOp,
662                    CurrentByteOffset);
663        break;
664
665    case PARSEOP_DWORDIO:
666        Rnode = RsDoDwordIoDescriptor (DescriptorTypeOp,
667                    CurrentByteOffset);
668        break;
669
670    case PARSEOP_DWORDMEMORY:
671        Rnode = RsDoDwordMemoryDescriptor (DescriptorTypeOp,
672                    CurrentByteOffset);
673        break;
674
675    case PARSEOP_DWORDSPACE:
676        Rnode = RsDoDwordSpaceDescriptor (DescriptorTypeOp,
677                    CurrentByteOffset);
678        break;
679
680    case PARSEOP_ENDDEPENDENTFN:
681        switch (*State)
682        {
683        case ACPI_RSTATE_NORMAL:
684            AslError (ASL_ERROR, ASL_MSG_MISSING_STARTDEPENDENT,
685                DescriptorTypeOp, NULL);
686            break;
687
688        case ACPI_RSTATE_START_DEPENDENT:
689            AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
690                DescriptorTypeOp, NULL);
691            break;
692
693        case ACPI_RSTATE_DEPENDENT_LIST:
694        default:
695            break;
696        }
697
698        *State = ACPI_RSTATE_NORMAL;
699        Rnode = RsDoEndDependentDescriptor (DescriptorTypeOp,
700                    CurrentByteOffset);
701        break;
702
703    case PARSEOP_ENDTAG:
704        Rnode = RsDoEndTagDescriptor (DescriptorTypeOp,
705                    CurrentByteOffset);
706        break;
707
708    case PARSEOP_EXTENDEDIO:
709        Rnode = RsDoExtendedIoDescriptor (DescriptorTypeOp,
710                    CurrentByteOffset);
711        break;
712
713    case PARSEOP_EXTENDEDMEMORY:
714        Rnode = RsDoExtendedMemoryDescriptor (DescriptorTypeOp,
715                    CurrentByteOffset);
716        break;
717
718    case PARSEOP_EXTENDEDSPACE:
719        Rnode = RsDoExtendedSpaceDescriptor (DescriptorTypeOp,
720                    CurrentByteOffset);
721        break;
722
723    case PARSEOP_FIXEDIO:
724        Rnode = RsDoFixedIoDescriptor (DescriptorTypeOp,
725                    CurrentByteOffset);
726        break;
727
728    case PARSEOP_INTERRUPT:
729        Rnode = RsDoInterruptDescriptor (DescriptorTypeOp,
730                    CurrentByteOffset);
731        break;
732
733    case PARSEOP_IO:
734        Rnode = RsDoIoDescriptor (DescriptorTypeOp,
735                    CurrentByteOffset);
736        break;
737
738    case PARSEOP_IRQ:
739        Rnode = RsDoIrqDescriptor (DescriptorTypeOp,
740                    CurrentByteOffset);
741        break;
742
743    case PARSEOP_IRQNOFLAGS:
744        Rnode = RsDoIrqNoFlagsDescriptor (DescriptorTypeOp,
745                    CurrentByteOffset);
746        break;
747
748    case PARSEOP_MEMORY24:
749        Rnode = RsDoMemory24Descriptor (DescriptorTypeOp,
750                    CurrentByteOffset);
751        break;
752
753    case PARSEOP_MEMORY32:
754        Rnode = RsDoMemory32Descriptor (DescriptorTypeOp,
755                    CurrentByteOffset);
756        break;
757
758    case PARSEOP_MEMORY32FIXED:
759        Rnode = RsDoMemory32FixedDescriptor (DescriptorTypeOp,
760                    CurrentByteOffset);
761        break;
762
763    case PARSEOP_QWORDIO:
764        Rnode = RsDoQwordIoDescriptor (DescriptorTypeOp,
765                    CurrentByteOffset);
766        break;
767
768    case PARSEOP_QWORDMEMORY:
769        Rnode = RsDoQwordMemoryDescriptor (DescriptorTypeOp,
770                    CurrentByteOffset);
771        break;
772
773    case PARSEOP_QWORDSPACE:
774        Rnode = RsDoQwordSpaceDescriptor (DescriptorTypeOp,
775                    CurrentByteOffset);
776        break;
777
778    case PARSEOP_REGISTER:
779        Rnode = RsDoGeneralRegisterDescriptor (DescriptorTypeOp,
780                    CurrentByteOffset);
781        break;
782
783    case PARSEOP_STARTDEPENDENTFN:
784        switch (*State)
785        {
786        case ACPI_RSTATE_START_DEPENDENT:
787            AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
788                DescriptorTypeOp, NULL);
789            break;
790
791        case ACPI_RSTATE_NORMAL:
792        case ACPI_RSTATE_DEPENDENT_LIST:
793        default:
794            break;
795        }
796
797        *State = ACPI_RSTATE_START_DEPENDENT;
798        Rnode = RsDoStartDependentDescriptor (DescriptorTypeOp,
799                    CurrentByteOffset);
800        *State = ACPI_RSTATE_DEPENDENT_LIST;
801        break;
802
803    case PARSEOP_STARTDEPENDENTFN_NOPRI:
804        switch (*State)
805        {
806        case ACPI_RSTATE_START_DEPENDENT:
807            AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
808                DescriptorTypeOp, NULL);
809            break;
810
811        case ACPI_RSTATE_NORMAL:
812        case ACPI_RSTATE_DEPENDENT_LIST:
813        default:
814            break;
815        }
816
817        *State = ACPI_RSTATE_START_DEPENDENT;
818        Rnode = RsDoStartDependentNoPriDescriptor (DescriptorTypeOp,
819                    CurrentByteOffset);
820        *State = ACPI_RSTATE_DEPENDENT_LIST;
821        break;
822
823    case PARSEOP_VENDORLONG:
824        Rnode = RsDoVendorLargeDescriptor (DescriptorTypeOp,
825                    CurrentByteOffset);
826        break;
827
828    case PARSEOP_VENDORSHORT:
829        Rnode = RsDoVendorSmallDescriptor (DescriptorTypeOp,
830                    CurrentByteOffset);
831        break;
832
833    case PARSEOP_WORDBUSNUMBER:
834        Rnode = RsDoWordBusNumberDescriptor (DescriptorTypeOp,
835                    CurrentByteOffset);
836        break;
837
838    case PARSEOP_WORDIO:
839        Rnode = RsDoWordIoDescriptor (DescriptorTypeOp,
840                    CurrentByteOffset);
841        break;
842
843    case PARSEOP_WORDSPACE:
844        Rnode = RsDoWordSpaceDescriptor (DescriptorTypeOp,
845                    CurrentByteOffset);
846        break;
847
848    case PARSEOP_DEFAULT_ARG:
849        /* Just ignore any of these, they are used as fillers/placeholders */
850        break;
851
852    default:
853        printf ("Unknown resource descriptor type [%s]\n",
854                    DescriptorTypeOp->Asl.ParseOpName);
855        break;
856    }
857
858    /*
859     * Mark original node as unused, but head of a resource descriptor.
860     * This allows the resource to be installed in the namespace so that
861     * references to the descriptor can be resolved.
862     */
863    DescriptorTypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
864    DescriptorTypeOp->Asl.CompileFlags = NODE_IS_RESOURCE_DESC;
865    DescriptorTypeOp->Asl.Value.Integer = CurrentByteOffset;
866
867    if (Rnode)
868    {
869        DescriptorTypeOp->Asl.FinalAmlLength = Rnode->BufferLength;
870    }
871
872    return (Rnode);
873}
874
875
876/*******************************************************************************
877 *
878 * FUNCTION:    RsLinkDescriptorChain
879 *
880 * PARAMETERS:  PreviousRnode       - Pointer to the node that will be previous
881 *                                    to the linked node,  At exit, set to the
882 *                                    last node in the new chain.
883 *              Rnode               - Resource node to link into the list
884 *
885 * RETURN:      Cumulative buffer byte offset of the new segment of chain
886 *
887 * DESCRIPTION: Link a descriptor chain at the end of an existing chain.
888 *
889 ******************************************************************************/
890
891UINT32
892RsLinkDescriptorChain (
893    ASL_RESOURCE_NODE       **PreviousRnode,
894    ASL_RESOURCE_NODE       *Rnode)
895{
896    ASL_RESOURCE_NODE       *LastRnode;
897    UINT32                  CurrentByteOffset;
898
899
900    /* Anything to do? */
901
902    if (!Rnode)
903    {
904        return 0;
905    }
906
907    /* Point the previous node to the new node */
908
909    (*PreviousRnode)->Next = Rnode;
910    CurrentByteOffset = Rnode->BufferLength;
911
912    /* Walk to the end of the chain headed by Rnode */
913
914    LastRnode = Rnode;
915    while (LastRnode->Next)
916    {
917        LastRnode = LastRnode->Next;
918        CurrentByteOffset += LastRnode->BufferLength;
919    }
920
921    /* Previous node becomes the last node in the chain */
922
923    *PreviousRnode = LastRnode;
924    return CurrentByteOffset;
925}
926
927
928/*******************************************************************************
929 *
930 * FUNCTION:    RsDoResourceTemplate
931 *
932 * PARAMETERS:  Op        - Parent of a resource template list
933 *
934 * RETURN:      None.  Sets input node to point to a list of AML code
935 *
936 * DESCRIPTION: Merge a list of resource descriptors into a single AML buffer,
937 *              in preparation for output to the AML output file.
938 *
939 ******************************************************************************/
940
941void
942RsDoResourceTemplate (
943    ACPI_PARSE_OBJECT       *Op)
944{
945    ACPI_PARSE_OBJECT       *BufferLengthOp;
946    ACPI_PARSE_OBJECT       *BufferOp;
947    ACPI_PARSE_OBJECT       *DescriptorTypeOp;
948    ACPI_PARSE_OBJECT       *LastOp = NULL;
949    UINT32                  CurrentByteOffset = 0;
950    ASL_RESOURCE_NODE       HeadRnode;
951    ASL_RESOURCE_NODE       *PreviousRnode;
952    ASL_RESOURCE_NODE       *Rnode;
953    UINT8                   State;
954
955
956    /* Mark parent as containing a resource template */
957
958    if (Op->Asl.Parent)
959    {
960        Op->Asl.Parent->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
961    }
962
963    /* ResourceTemplate Opcode is first (Op) */
964    /* Buffer Length node is first child */
965
966    BufferLengthOp = ASL_GET_CHILD_NODE (Op);
967
968    /* Buffer Op is first peer */
969
970    BufferOp = ASL_GET_PEER_NODE (BufferLengthOp);
971
972    /* First Descriptor type is next */
973
974    DescriptorTypeOp = ASL_GET_PEER_NODE (BufferOp);
975
976    /*
977     * Process all resource descriptors in the list
978     * Note: It is assumed that the EndTag node has been automatically
979     * inserted at the end of the template by the parser.
980     */
981    State = ACPI_RSTATE_NORMAL;
982    PreviousRnode = &HeadRnode;
983    while (DescriptorTypeOp)
984    {
985        DescriptorTypeOp->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
986        Rnode = RsDoOneResourceDescriptor (DescriptorTypeOp, CurrentByteOffset,
987                    &State);
988
989        /*
990         * Update current byte offset to indicate the number of bytes from the
991         * start of the buffer.  Buffer can include multiple descriptors, we
992         * must keep track of the offset of not only each descriptor, but each
993         * element (field) within each descriptor as well.
994         */
995        CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, Rnode);
996
997        /* Get the next descriptor in the list */
998
999        LastOp = DescriptorTypeOp;
1000        DescriptorTypeOp = ASL_GET_PEER_NODE (DescriptorTypeOp);
1001    }
1002
1003    if (State == ACPI_RSTATE_DEPENDENT_LIST)
1004    {
1005        if (LastOp)
1006        {
1007            LastOp = LastOp->Asl.Parent;
1008        }
1009        AslError (ASL_ERROR, ASL_MSG_MISSING_ENDDEPENDENT, LastOp, NULL);
1010    }
1011
1012    /*
1013     * Transform the nodes into the following
1014     *
1015     * Op           -> AML_BUFFER_OP
1016     * First Child  -> BufferLength
1017     * Second Child -> Descriptor Buffer (raw byte data)
1018     */
1019    Op->Asl.ParseOpcode               = PARSEOP_BUFFER;
1020    Op->Asl.AmlOpcode                 = AML_BUFFER_OP;
1021    Op->Asl.CompileFlags              = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC;
1022
1023    BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
1024    BufferLengthOp->Asl.Value.Integer = CurrentByteOffset;
1025    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
1026
1027    BufferOp->Asl.ParseOpcode         = PARSEOP_RAW_DATA;
1028    BufferOp->Asl.AmlOpcode           = AML_RAW_DATA_CHAIN;
1029    BufferOp->Asl.AmlOpcodeLength     = 0;
1030    BufferOp->Asl.AmlLength           = CurrentByteOffset;
1031    BufferOp->Asl.Value.Buffer        = (UINT8 *) HeadRnode.Next;
1032    BufferOp->Asl.CompileFlags       |= NODE_IS_RESOURCE_DATA;
1033
1034    return;
1035}
1036
1037
1038