1118611Snjl/******************************************************************************
2118611Snjl *
3207344Sjkim * Module Name: aslresource - Resource template/descriptor utilities
4118611Snjl *
5118611Snjl *****************************************************************************/
6118611Snjl
7217365Sjkim/*
8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp.
9118611Snjl * All rights reserved.
10118611Snjl *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
25118611Snjl *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
29118611Snjl *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
43118611Snjl
44118611Snjl
45151937Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h>
46118611Snjl#include "aslcompiler.y.h"
47193529Sjkim#include <contrib/dev/acpica/include/amlcode.h>
48118611Snjl
49118611Snjl
50118611Snjl#define _COMPONENT          ACPI_COMPILER
51118611Snjl        ACPI_MODULE_NAME    ("aslresource")
52118611Snjl
53118611Snjl
54118611Snjl/*******************************************************************************
55118611Snjl *
56207344Sjkim * FUNCTION:    RsSmallAddressCheck
57207344Sjkim *
58207344Sjkim * PARAMETERS:  Minimum             - Address Min value
59207344Sjkim *              Maximum             - Address Max value
60207344Sjkim *              Length              - Address range value
61207344Sjkim *              Alignment           - Address alignment value
62207344Sjkim *              MinOp               - Original Op for Address Min
63207344Sjkim *              MaxOp               - Original Op for Address Max
64207344Sjkim *              LengthOp            - Original Op for address range
65207344Sjkim *              AlignOp             - Original Op for address alignment. If
66207344Sjkim *                                    NULL, means "zero value for alignment is
67207344Sjkim *                                    OK, and means 64K alignment" (for
68207344Sjkim *                                    Memory24 descriptor)
69213806Sjkim *              Op                  - Parent Op for entire construct
70207344Sjkim *
71207344Sjkim * RETURN:      None. Adds error messages to error log if necessary
72207344Sjkim *
73207344Sjkim * DESCRIPTION: Perform common value checks for "small" address descriptors.
74207344Sjkim *              Currently:
75207344Sjkim *                  Io, Memory24, Memory32
76207344Sjkim *
77207344Sjkim ******************************************************************************/
78207344Sjkim
79207344Sjkimvoid
80207344SjkimRsSmallAddressCheck (
81207344Sjkim    UINT8                   Type,
82207344Sjkim    UINT32                  Minimum,
83207344Sjkim    UINT32                  Maximum,
84207344Sjkim    UINT32                  Length,
85207344Sjkim    UINT32                  Alignment,
86207344Sjkim    ACPI_PARSE_OBJECT       *MinOp,
87207344Sjkim    ACPI_PARSE_OBJECT       *MaxOp,
88207344Sjkim    ACPI_PARSE_OBJECT       *LengthOp,
89213806Sjkim    ACPI_PARSE_OBJECT       *AlignOp,
90213806Sjkim    ACPI_PARSE_OBJECT       *Op)
91207344Sjkim{
92207344Sjkim
93207344Sjkim    if (Gbl_NoResourceChecking)
94207344Sjkim    {
95207344Sjkim        return;
96207344Sjkim    }
97207344Sjkim
98213806Sjkim    /*
99213806Sjkim     * Check for a so-called "null descriptor". These are descriptors that are
100213806Sjkim     * created with most fields set to zero. The intent is that the descriptor
101213806Sjkim     * will be updated/completed at runtime via a BufferField.
102213806Sjkim     *
103213806Sjkim     * If the descriptor does NOT have a resource tag, it cannot be referenced
104213806Sjkim     * by a BufferField and we will flag this as an error. Conversely, if
105213806Sjkim     * the descriptor has a resource tag, we will assume that a BufferField
106213806Sjkim     * will be used to dynamically update it, so no error.
107213806Sjkim     *
108213806Sjkim     * A possible enhancement to this check would be to verify that in fact
109213806Sjkim     * a BufferField is created using the resource tag, and perhaps even
110213806Sjkim     * verify that a Store is performed to the BufferField.
111213806Sjkim     *
112213806Sjkim     * Note: for these descriptors, Alignment is allowed to be zero
113213806Sjkim     */
114213806Sjkim    if (!Minimum && !Maximum && !Length)
115213806Sjkim    {
116213806Sjkim        if (!Op->Asl.ExternalName)
117213806Sjkim        {
118213806Sjkim            /* No resource tag. Descriptor is fixed and is also illegal */
119213806Sjkim
120213806Sjkim            AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL);
121213806Sjkim        }
122213806Sjkim
123213806Sjkim        return;
124213806Sjkim    }
125213806Sjkim
126207344Sjkim    /* Special case for Memory24, values are compressed */
127207344Sjkim
128207344Sjkim    if (Type == ACPI_RESOURCE_NAME_MEMORY24)
129207344Sjkim    {
130207344Sjkim        if (!Alignment) /* Alignment==0 means 64K - no invalid alignment */
131207344Sjkim        {
132207344Sjkim            Alignment = ACPI_UINT16_MAX + 1;
133207344Sjkim        }
134207344Sjkim
135207344Sjkim        Minimum <<= 8;
136207344Sjkim        Maximum <<= 8;
137207344Sjkim        Length *= 256;
138207344Sjkim    }
139207344Sjkim
140207344Sjkim    /* IO descriptor has different definition of min/max, don't check */
141207344Sjkim
142207344Sjkim    if (Type != ACPI_RESOURCE_NAME_IO)
143207344Sjkim    {
144207344Sjkim        /* Basic checks on Min/Max/Length */
145207344Sjkim
146207344Sjkim        if (Minimum > Maximum)
147207344Sjkim        {
148207344Sjkim            AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL);
149207344Sjkim        }
150207344Sjkim        else if (Length > (Maximum - Minimum + 1))
151207344Sjkim        {
152207344Sjkim            AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL);
153207344Sjkim        }
154207344Sjkim    }
155207344Sjkim
156207344Sjkim    /* Alignment of zero is not in ACPI spec, but is used to mean byte acc */
157207344Sjkim
158207344Sjkim    if (!Alignment)
159207344Sjkim    {
160207344Sjkim        Alignment = 1;
161207344Sjkim    }
162207344Sjkim
163207344Sjkim    /* Addresses must be an exact multiple of the alignment value */
164207344Sjkim
165207344Sjkim    if (Minimum % Alignment)
166207344Sjkim    {
167207344Sjkim        AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL);
168207344Sjkim    }
169207344Sjkim    if (Maximum % Alignment)
170207344Sjkim    {
171207344Sjkim        AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, NULL);
172207344Sjkim    }
173207344Sjkim}
174207344Sjkim
175207344Sjkim
176207344Sjkim/*******************************************************************************
177207344Sjkim *
178207344Sjkim * FUNCTION:    RsLargeAddressCheck
179207344Sjkim *
180207344Sjkim * PARAMETERS:  Minimum             - Address Min value
181207344Sjkim *              Maximum             - Address Max value
182207344Sjkim *              Length              - Address range value
183207344Sjkim *              Granularity         - Address granularity value
184207344Sjkim *              Flags               - General flags for address descriptors:
185207344Sjkim *                                    _MIF, _MAF, _DEC
186207344Sjkim *              MinOp               - Original Op for Address Min
187207344Sjkim *              MaxOp               - Original Op for Address Max
188207344Sjkim *              LengthOp            - Original Op for address range
189207344Sjkim *              GranOp              - Original Op for address granularity
190213806Sjkim *              Op                  - Parent Op for entire construct
191207344Sjkim *
192207344Sjkim * RETURN:      None. Adds error messages to error log if necessary
193207344Sjkim *
194207344Sjkim * DESCRIPTION: Perform common value checks for "large" address descriptors.
195207344Sjkim *              Currently:
196207344Sjkim *                  WordIo,     WordBusNumber,  WordSpace
197207344Sjkim *                  DWordIo,    DWordMemory,    DWordSpace
198207344Sjkim *                  QWordIo,    QWordMemory,    QWordSpace
199207344Sjkim *                  ExtendedIo, ExtendedMemory, ExtendedSpace
200207344Sjkim *
201207344Sjkim * _MIF flag set means that the minimum address is fixed and is not relocatable
202207344Sjkim * _MAF flag set means that the maximum address is fixed and is not relocatable
203207344Sjkim * Length of zero means that the record size is variable
204207344Sjkim *
205207344Sjkim * This function implements the LEN/MIF/MAF/MIN/MAX/GRA rules within Table 6-40
206207344Sjkim * of the ACPI 4.0a specification. Added 04/2010.
207207344Sjkim *
208207344Sjkim ******************************************************************************/
209207344Sjkim
210207344Sjkimvoid
211207344SjkimRsLargeAddressCheck (
212207344Sjkim    UINT64                  Minimum,
213207344Sjkim    UINT64                  Maximum,
214207344Sjkim    UINT64                  Length,
215207344Sjkim    UINT64                  Granularity,
216207344Sjkim    UINT8                   Flags,
217207344Sjkim    ACPI_PARSE_OBJECT       *MinOp,
218207344Sjkim    ACPI_PARSE_OBJECT       *MaxOp,
219207344Sjkim    ACPI_PARSE_OBJECT       *LengthOp,
220213806Sjkim    ACPI_PARSE_OBJECT       *GranOp,
221213806Sjkim    ACPI_PARSE_OBJECT       *Op)
222207344Sjkim{
223207344Sjkim
224207344Sjkim    if (Gbl_NoResourceChecking)
225207344Sjkim    {
226207344Sjkim        return;
227207344Sjkim    }
228207344Sjkim
229213806Sjkim    /*
230213806Sjkim     * Check for a so-called "null descriptor". These are descriptors that are
231213806Sjkim     * created with most fields set to zero. The intent is that the descriptor
232213806Sjkim     * will be updated/completed at runtime via a BufferField.
233213806Sjkim     *
234213806Sjkim     * If the descriptor does NOT have a resource tag, it cannot be referenced
235213806Sjkim     * by a BufferField and we will flag this as an error. Conversely, if
236213806Sjkim     * the descriptor has a resource tag, we will assume that a BufferField
237213806Sjkim     * will be used to dynamically update it, so no error.
238213806Sjkim     *
239213806Sjkim     * A possible enhancement to this check would be to verify that in fact
240213806Sjkim     * a BufferField is created using the resource tag, and perhaps even
241213806Sjkim     * verify that a Store is performed to the BufferField.
242213806Sjkim     */
243213806Sjkim    if (!Minimum && !Maximum && !Length && !Granularity)
244213806Sjkim    {
245213806Sjkim        if (!Op->Asl.ExternalName)
246213806Sjkim        {
247213806Sjkim            /* No resource tag. Descriptor is fixed and is also illegal */
248213806Sjkim
249213806Sjkim            AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL);
250213806Sjkim        }
251213806Sjkim
252213806Sjkim        return;
253213806Sjkim    }
254213806Sjkim
255207344Sjkim    /* Basic checks on Min/Max/Length */
256207344Sjkim
257207344Sjkim    if (Minimum > Maximum)
258207344Sjkim    {
259207344Sjkim        AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL);
260207344Sjkim        return;
261207344Sjkim    }
262207344Sjkim    else if (Length > (Maximum - Minimum + 1))
263207344Sjkim    {
264207344Sjkim        AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL);
265207344Sjkim        return;
266207344Sjkim    }
267207344Sjkim
268207344Sjkim    /* If specified (non-zero), ensure granularity is a power-of-two minus one */
269207344Sjkim
270207344Sjkim    if (Granularity)
271207344Sjkim    {
272207344Sjkim        if ((Granularity + 1) &
273207344Sjkim             Granularity)
274207344Sjkim        {
275207344Sjkim            AslError (ASL_ERROR, ASL_MSG_INVALID_GRANULARITY, GranOp, NULL);
276207344Sjkim            return;
277207344Sjkim        }
278207344Sjkim    }
279207344Sjkim
280207344Sjkim    /*
281207344Sjkim     * Check the various combinations of Length, MinFixed, and MaxFixed
282207344Sjkim     */
283207344Sjkim    if (Length)
284207344Sjkim    {
285207344Sjkim        /* Fixed non-zero length */
286207344Sjkim
287207344Sjkim        switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF))
288207344Sjkim        {
289207344Sjkim        case 0:
290207344Sjkim            /*
291207344Sjkim             * Fixed length, variable locations (both _MIN and _MAX).
292207344Sjkim             * Length must be a multiple of granularity
293207344Sjkim             */
294207344Sjkim            if (Granularity & Length)
295207344Sjkim            {
296207344Sjkim                AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, LengthOp, NULL);
297207344Sjkim            }
298207344Sjkim            break;
299207344Sjkim
300207344Sjkim        case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF):
301207344Sjkim
302207344Sjkim            /* Fixed length, fixed location. Granularity must be zero */
303207344Sjkim
304207344Sjkim            if (Granularity != 0)
305207344Sjkim            {
306207344Sjkim                AslError (ASL_ERROR, ASL_MSG_INVALID_GRAN_FIXED, GranOp, NULL);
307207344Sjkim            }
308207344Sjkim
309207344Sjkim            /* Length must be exactly the size of the min/max window */
310207344Sjkim
311207344Sjkim            if (Length != (Maximum - Minimum + 1))
312207344Sjkim            {
313207344Sjkim                AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH_FIXED, LengthOp, NULL);
314207344Sjkim            }
315207344Sjkim            break;
316207344Sjkim
317207344Sjkim        /* All other combinations are invalid */
318207344Sjkim
319207344Sjkim        case ACPI_RESOURCE_FLAG_MIF:
320207344Sjkim        case ACPI_RESOURCE_FLAG_MAF:
321207344Sjkim        default:
322250838Sjkim
323207344Sjkim            AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL);
324207344Sjkim        }
325207344Sjkim    }
326207344Sjkim    else
327207344Sjkim    {
328207344Sjkim        /* Variable length (length==0) */
329207344Sjkim
330207344Sjkim        switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF))
331207344Sjkim        {
332207344Sjkim        case 0:
333207344Sjkim            /*
334207344Sjkim             * Both _MIN and _MAX are variable.
335207344Sjkim             * No additional requirements, just exit
336207344Sjkim             */
337207344Sjkim            break;
338207344Sjkim
339207344Sjkim        case ACPI_RESOURCE_FLAG_MIF:
340207344Sjkim
341207344Sjkim            /* _MIN is fixed. _MIN must be multiple of _GRA */
342207344Sjkim
343207344Sjkim            /*
344207344Sjkim             * The granularity is defined by the ACPI specification to be a
345207344Sjkim             * power-of-two minus one, therefore the granularity is a
346207344Sjkim             * bitmask which can be used to easily validate the addresses.
347207344Sjkim             */
348207344Sjkim            if (Granularity & Minimum)
349207344Sjkim            {
350207344Sjkim                AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL);
351207344Sjkim            }
352207344Sjkim            break;
353207344Sjkim
354207344Sjkim        case ACPI_RESOURCE_FLAG_MAF:
355207344Sjkim
356207344Sjkim            /* _MAX is fixed. (_MAX + 1) must be multiple of _GRA */
357207344Sjkim
358207344Sjkim            if (Granularity & (Maximum + 1))
359207344Sjkim            {
360207344Sjkim                AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, "-1");
361207344Sjkim            }
362207344Sjkim            break;
363207344Sjkim
364207344Sjkim        /* Both MIF/MAF set is invalid if length is zero */
365207344Sjkim
366207344Sjkim        case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF):
367207344Sjkim        default:
368250838Sjkim
369207344Sjkim            AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL);
370207344Sjkim        }
371207344Sjkim    }
372207344Sjkim}
373207344Sjkim
374207344Sjkim
375207344Sjkim/*******************************************************************************
376207344Sjkim *
377207344Sjkim * FUNCTION:    RsGetStringDataLength
378207344Sjkim *
379207344Sjkim * PARAMETERS:  InitializerOp     - Start of a subtree of init nodes
380207344Sjkim *
381207344Sjkim * RETURN:      Valid string length if a string node is found (otherwise 0)
382207344Sjkim *
383207344Sjkim * DESCRIPTION: In a list of peer nodes, find the first one that contains a
384207344Sjkim *              string and return the length of the string.
385207344Sjkim *
386207344Sjkim ******************************************************************************/
387207344Sjkim
388207344SjkimUINT16
389207344SjkimRsGetStringDataLength (
390207344Sjkim    ACPI_PARSE_OBJECT       *InitializerOp)
391207344Sjkim{
392207344Sjkim
393207344Sjkim    while (InitializerOp)
394207344Sjkim    {
395207344Sjkim        if (InitializerOp->Asl.ParseOpcode == PARSEOP_STRING_LITERAL)
396207344Sjkim        {
397207344Sjkim            return ((UINT16) (strlen (InitializerOp->Asl.Value.String) + 1));
398207344Sjkim        }
399207344Sjkim        InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
400207344Sjkim    }
401207344Sjkim
402241973Sjkim    return (0);
403207344Sjkim}
404207344Sjkim
405207344Sjkim
406207344Sjkim/*******************************************************************************
407207344Sjkim *
408118611Snjl * FUNCTION:    RsAllocateResourceNode
409118611Snjl *
410118611Snjl * PARAMETERS:  Size        - Size of node in bytes
411118611Snjl *
412118611Snjl * RETURN:      The allocated node - aborts on allocation failure
413118611Snjl *
414118611Snjl * DESCRIPTION: Allocate a resource description node and the resource
415118611Snjl *              descriptor itself (the nodes are used to link descriptors).
416118611Snjl *
417118611Snjl ******************************************************************************/
418118611Snjl
419118611SnjlASL_RESOURCE_NODE *
420118611SnjlRsAllocateResourceNode (
421118611Snjl    UINT32                  Size)
422118611Snjl{
423118611Snjl    ASL_RESOURCE_NODE       *Rnode;
424118611Snjl
425118611Snjl
426118611Snjl    /* Allocate the node */
427118611Snjl
428118611Snjl    Rnode = UtLocalCalloc (sizeof (ASL_RESOURCE_NODE));
429118611Snjl
430118611Snjl    /* Allocate the resource descriptor itself */
431118611Snjl
432118611Snjl    Rnode->Buffer = UtLocalCalloc (Size);
433118611Snjl    Rnode->BufferLength = Size;
434118611Snjl
435118611Snjl    return (Rnode);
436118611Snjl}
437118611Snjl
438118611Snjl
439118611Snjl/*******************************************************************************
440118611Snjl *
441228110Sjkim * FUNCTION:    RsCreateResourceField
442118611Snjl *
443151937Sjkim * PARAMETERS:  Op              - Resource field node
444118611Snjl *              Name            - Name of the field (Used only to reference
445118611Snjl *                                the field in the ASL, not in the AML)
446118611Snjl *              ByteOffset      - Offset from the field start
447118611Snjl *              BitOffset       - Additional bit offset
448228110Sjkim *              BitLength       - Number of bits in the field
449118611Snjl *
450118611Snjl * RETURN:      None, sets fields within the input node
451118611Snjl *
452118611Snjl * DESCRIPTION: Utility function to generate a named bit field within a
453241973Sjkim *              resource descriptor. Mark a node as 1) a field in a resource
454118611Snjl *              descriptor, and 2) set the value to be a BIT offset
455118611Snjl *
456118611Snjl ******************************************************************************/
457118611Snjl
458118611Snjlvoid
459228110SjkimRsCreateResourceField (
460118611Snjl    ACPI_PARSE_OBJECT       *Op,
461118611Snjl    char                    *Name,
462118611Snjl    UINT32                  ByteOffset,
463228110Sjkim    UINT32                  BitOffset,
464228110Sjkim    UINT32                  BitLength)
465118611Snjl{
466118611Snjl
467228110Sjkim    Op->Asl.ExternalName = Name;
468228110Sjkim    Op->Asl.CompileFlags |= NODE_IS_RESOURCE_FIELD;
469118611Snjl
470118611Snjl
471228110Sjkim    Op->Asl.Value.Tag.BitOffset = (ByteOffset * 8) + BitOffset;
472228110Sjkim    Op->Asl.Value.Tag.BitLength = BitLength;
473118611Snjl}
474118611Snjl
475118611Snjl
476118611Snjl/*******************************************************************************
477118611Snjl *
478118611Snjl * FUNCTION:    RsSetFlagBits
479118611Snjl *
480118611Snjl * PARAMETERS:  *Flags          - Pointer to the flag byte
481151937Sjkim *              Op              - Flag initialization node
482118611Snjl *              Position        - Bit position within the flag byte
483118611Snjl *              Default         - Used if the node is DEFAULT.
484118611Snjl *
485118611Snjl * RETURN:      Sets bits within the *Flags output byte.
486118611Snjl *
487118611Snjl * DESCRIPTION: Set a bit in a cumulative flags word from an initialization
488241973Sjkim *              node. Will use a default value if the node is DEFAULT, meaning
489241973Sjkim *              that no value was specified in the ASL. Used to merge multiple
490118611Snjl *              keywords into a single flags byte.
491118611Snjl *
492118611Snjl ******************************************************************************/
493118611Snjl
494118611Snjlvoid
495118611SnjlRsSetFlagBits (
496118611Snjl    UINT8                   *Flags,
497118611Snjl    ACPI_PARSE_OBJECT       *Op,
498118611Snjl    UINT8                   Position,
499118611Snjl    UINT8                   DefaultBit)
500118611Snjl{
501118611Snjl
502118611Snjl    if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
503118611Snjl    {
504118611Snjl        /* Use the default bit */
505118611Snjl
506118611Snjl        *Flags |= (DefaultBit << Position);
507118611Snjl    }
508118611Snjl    else
509118611Snjl    {
510118611Snjl        /* Use the bit specified in the initialization node */
511118611Snjl
512118611Snjl        *Flags |= (((UINT8) Op->Asl.Value.Integer) << Position);
513118611Snjl    }
514118611Snjl}
515118611Snjl
516118611Snjl
517228110Sjkimvoid
518228110SjkimRsSetFlagBits16 (
519228110Sjkim    UINT16                  *Flags,
520228110Sjkim    ACPI_PARSE_OBJECT       *Op,
521228110Sjkim    UINT8                   Position,
522228110Sjkim    UINT8                   DefaultBit)
523228110Sjkim{
524228110Sjkim
525228110Sjkim    if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
526228110Sjkim    {
527228110Sjkim        /* Use the default bit */
528228110Sjkim
529228110Sjkim        *Flags |= (DefaultBit << Position);
530228110Sjkim    }
531228110Sjkim    else
532228110Sjkim    {
533228110Sjkim        /* Use the bit specified in the initialization node */
534228110Sjkim
535228110Sjkim        *Flags |= (((UINT16) Op->Asl.Value.Integer) << Position);
536228110Sjkim    }
537228110Sjkim}
538228110Sjkim
539228110Sjkim
540118611Snjl/*******************************************************************************
541118611Snjl *
542118611Snjl * FUNCTION:    RsCompleteNodeAndGetNext
543118611Snjl *
544118611Snjl * PARAMETERS:  Op            - Resource node to be completed
545118611Snjl *
546118611Snjl * RETURN:      The next peer to the input node.
547118611Snjl *
548118611Snjl * DESCRIPTION: Mark the current node completed and return the next peer.
549118611Snjl *              The node ParseOpcode is set to DEFAULT_ARG, meaning that
550118611Snjl *              this node is to be ignored from now on.
551118611Snjl *
552118611Snjl ******************************************************************************/
553118611Snjl
554118611SnjlACPI_PARSE_OBJECT *
555118611SnjlRsCompleteNodeAndGetNext (
556118611Snjl    ACPI_PARSE_OBJECT       *Op)
557118611Snjl{
558118611Snjl
559118611Snjl    /* Mark this node unused */
560118611Snjl
561118611Snjl    Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
562118611Snjl
563118611Snjl    /* Move on to the next peer node in the initializer list */
564118611Snjl
565118611Snjl    return (ASL_GET_PEER_NODE (Op));
566118611Snjl}
567118611Snjl
568118611Snjl
569118611Snjl/*******************************************************************************
570118611Snjl *
571151937Sjkim * FUNCTION:    RsCheckListForDuplicates
572151937Sjkim *
573151937Sjkim * PARAMETERS:  Op                  - First op in the initializer list
574151937Sjkim *
575151937Sjkim * RETURN:      None
576151937Sjkim *
577151937Sjkim * DESCRIPTION: Check an initializer list for duplicate values. Emits an error
578151937Sjkim *              if any duplicates are found.
579151937Sjkim *
580151937Sjkim ******************************************************************************/
581151937Sjkim
582151937Sjkimvoid
583151937SjkimRsCheckListForDuplicates (
584151937Sjkim    ACPI_PARSE_OBJECT       *Op)
585151937Sjkim{
586151937Sjkim    ACPI_PARSE_OBJECT       *NextValueOp = Op;
587151937Sjkim    ACPI_PARSE_OBJECT       *NextOp;
588151937Sjkim    UINT32                  Value;
589151937Sjkim
590151937Sjkim
591151937Sjkim    if (!Op)
592151937Sjkim    {
593151937Sjkim        return;
594151937Sjkim    }
595151937Sjkim
596151937Sjkim    /* Search list once for each value in the list */
597151937Sjkim
598151937Sjkim    while (NextValueOp)
599151937Sjkim    {
600151937Sjkim        Value = (UINT32) NextValueOp->Asl.Value.Integer;
601151937Sjkim
602151937Sjkim        /* Compare this value to all remaining values in the list */
603151937Sjkim
604151937Sjkim        NextOp = ASL_GET_PEER_NODE (NextValueOp);
605151937Sjkim        while (NextOp)
606151937Sjkim        {
607151937Sjkim            if (NextOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
608151937Sjkim            {
609151937Sjkim                /* Compare values */
610151937Sjkim
611151937Sjkim                if (Value == (UINT32) NextOp->Asl.Value.Integer)
612151937Sjkim                {
613151937Sjkim                    /* Emit error only once per duplicate node */
614151937Sjkim
615151937Sjkim                    if (!(NextOp->Asl.CompileFlags & NODE_IS_DUPLICATE))
616151937Sjkim                    {
617151937Sjkim                        NextOp->Asl.CompileFlags |= NODE_IS_DUPLICATE;
618151937Sjkim                        AslError (ASL_ERROR, ASL_MSG_DUPLICATE_ITEM,
619151937Sjkim                            NextOp, NULL);
620151937Sjkim                    }
621151937Sjkim                }
622151937Sjkim            }
623151937Sjkim
624151937Sjkim            NextOp = ASL_GET_PEER_NODE (NextOp);
625151937Sjkim        }
626151937Sjkim
627151937Sjkim        NextValueOp = ASL_GET_PEER_NODE (NextValueOp);
628151937Sjkim    }
629151937Sjkim}
630151937Sjkim
631151937Sjkim
632151937Sjkim/*******************************************************************************
633151937Sjkim *
634118611Snjl * FUNCTION:    RsDoOneResourceDescriptor
635118611Snjl *
636118611Snjl * PARAMETERS:  DescriptorTypeOp    - Parent parse node of the descriptor
637118611Snjl *              CurrentByteOffset   - Offset in the resource descriptor
638118611Snjl *                                    buffer.
639118611Snjl *
640118611Snjl * RETURN:      A valid resource node for the descriptor
641118611Snjl *
642118611Snjl * DESCRIPTION: Dispatches the processing of one resource descriptor
643118611Snjl *
644118611Snjl ******************************************************************************/
645118611Snjl
646118611SnjlASL_RESOURCE_NODE *
647118611SnjlRsDoOneResourceDescriptor (
648118611Snjl    ACPI_PARSE_OBJECT       *DescriptorTypeOp,
649118611Snjl    UINT32                  CurrentByteOffset,
650118611Snjl    UINT8                   *State)
651118611Snjl{
652118611Snjl    ASL_RESOURCE_NODE       *Rnode = NULL;
653118611Snjl
654118611Snjl
655167802Sjkim    /* Construct the resource */
656118611Snjl
657118611Snjl    switch (DescriptorTypeOp->Asl.ParseOpcode)
658118611Snjl    {
659118611Snjl    case PARSEOP_DMA:
660250838Sjkim
661151937Sjkim        Rnode = RsDoDmaDescriptor (DescriptorTypeOp,
662151937Sjkim                    CurrentByteOffset);
663118611Snjl        break;
664118611Snjl
665228110Sjkim    case PARSEOP_FIXEDDMA:
666250838Sjkim
667228110Sjkim        Rnode = RsDoFixedDmaDescriptor (DescriptorTypeOp,
668228110Sjkim                    CurrentByteOffset);
669228110Sjkim        break;
670228110Sjkim
671118611Snjl    case PARSEOP_DWORDIO:
672250838Sjkim
673151937Sjkim        Rnode = RsDoDwordIoDescriptor (DescriptorTypeOp,
674151937Sjkim                    CurrentByteOffset);
675118611Snjl        break;
676118611Snjl
677118611Snjl    case PARSEOP_DWORDMEMORY:
678250838Sjkim
679151937Sjkim        Rnode = RsDoDwordMemoryDescriptor (DescriptorTypeOp,
680151937Sjkim                    CurrentByteOffset);
681118611Snjl        break;
682118611Snjl
683151937Sjkim    case PARSEOP_DWORDSPACE:
684250838Sjkim
685151937Sjkim        Rnode = RsDoDwordSpaceDescriptor (DescriptorTypeOp,
686151937Sjkim                    CurrentByteOffset);
687151937Sjkim        break;
688151937Sjkim
689118611Snjl    case PARSEOP_ENDDEPENDENTFN:
690250838Sjkim
691118611Snjl        switch (*State)
692118611Snjl        {
693118611Snjl        case ACPI_RSTATE_NORMAL:
694250838Sjkim
695151937Sjkim            AslError (ASL_ERROR, ASL_MSG_MISSING_STARTDEPENDENT,
696151937Sjkim                DescriptorTypeOp, NULL);
697118611Snjl            break;
698118611Snjl
699118611Snjl        case ACPI_RSTATE_START_DEPENDENT:
700250838Sjkim
701151937Sjkim            AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
702151937Sjkim                DescriptorTypeOp, NULL);
703118611Snjl            break;
704118611Snjl
705118611Snjl        case ACPI_RSTATE_DEPENDENT_LIST:
706118611Snjl        default:
707250838Sjkim
708118611Snjl            break;
709118611Snjl        }
710118611Snjl
711118611Snjl        *State = ACPI_RSTATE_NORMAL;
712151937Sjkim        Rnode = RsDoEndDependentDescriptor (DescriptorTypeOp,
713151937Sjkim                    CurrentByteOffset);
714118611Snjl        break;
715118611Snjl
716167802Sjkim    case PARSEOP_ENDTAG:
717250838Sjkim
718167802Sjkim        Rnode = RsDoEndTagDescriptor (DescriptorTypeOp,
719167802Sjkim                    CurrentByteOffset);
720167802Sjkim        break;
721167802Sjkim
722151937Sjkim    case PARSEOP_EXTENDEDIO:
723250838Sjkim
724151937Sjkim        Rnode = RsDoExtendedIoDescriptor (DescriptorTypeOp,
725151937Sjkim                    CurrentByteOffset);
726151937Sjkim        break;
727151937Sjkim
728151937Sjkim    case PARSEOP_EXTENDEDMEMORY:
729250838Sjkim
730151937Sjkim        Rnode = RsDoExtendedMemoryDescriptor (DescriptorTypeOp,
731151937Sjkim                    CurrentByteOffset);
732151937Sjkim        break;
733151937Sjkim
734151937Sjkim    case PARSEOP_EXTENDEDSPACE:
735250838Sjkim
736151937Sjkim        Rnode = RsDoExtendedSpaceDescriptor (DescriptorTypeOp,
737151937Sjkim                    CurrentByteOffset);
738151937Sjkim        break;
739151937Sjkim
740118611Snjl    case PARSEOP_FIXEDIO:
741250838Sjkim
742151937Sjkim        Rnode = RsDoFixedIoDescriptor (DescriptorTypeOp,
743151937Sjkim                    CurrentByteOffset);
744118611Snjl        break;
745118611Snjl
746118611Snjl    case PARSEOP_INTERRUPT:
747250838Sjkim
748151937Sjkim        Rnode = RsDoInterruptDescriptor (DescriptorTypeOp,
749151937Sjkim                    CurrentByteOffset);
750118611Snjl        break;
751118611Snjl
752118611Snjl    case PARSEOP_IO:
753250838Sjkim
754151937Sjkim        Rnode = RsDoIoDescriptor (DescriptorTypeOp,
755151937Sjkim                    CurrentByteOffset);
756118611Snjl        break;
757118611Snjl
758118611Snjl    case PARSEOP_IRQ:
759250838Sjkim
760151937Sjkim        Rnode = RsDoIrqDescriptor (DescriptorTypeOp,
761151937Sjkim                    CurrentByteOffset);
762118611Snjl        break;
763118611Snjl
764118611Snjl    case PARSEOP_IRQNOFLAGS:
765250838Sjkim
766151937Sjkim        Rnode = RsDoIrqNoFlagsDescriptor (DescriptorTypeOp,
767151937Sjkim                    CurrentByteOffset);
768118611Snjl        break;
769118611Snjl
770118611Snjl    case PARSEOP_MEMORY24:
771250838Sjkim
772151937Sjkim        Rnode = RsDoMemory24Descriptor (DescriptorTypeOp,
773151937Sjkim                    CurrentByteOffset);
774118611Snjl        break;
775118611Snjl
776118611Snjl    case PARSEOP_MEMORY32:
777250838Sjkim
778151937Sjkim        Rnode = RsDoMemory32Descriptor (DescriptorTypeOp,
779151937Sjkim                    CurrentByteOffset);
780118611Snjl        break;
781118611Snjl
782118611Snjl    case PARSEOP_MEMORY32FIXED:
783250838Sjkim
784151937Sjkim        Rnode = RsDoMemory32FixedDescriptor (DescriptorTypeOp,
785151937Sjkim                    CurrentByteOffset);
786118611Snjl        break;
787118611Snjl
788118611Snjl    case PARSEOP_QWORDIO:
789250838Sjkim
790151937Sjkim        Rnode = RsDoQwordIoDescriptor (DescriptorTypeOp,
791151937Sjkim                    CurrentByteOffset);
792118611Snjl        break;
793118611Snjl
794118611Snjl    case PARSEOP_QWORDMEMORY:
795250838Sjkim
796151937Sjkim        Rnode = RsDoQwordMemoryDescriptor (DescriptorTypeOp,
797151937Sjkim                    CurrentByteOffset);
798118611Snjl        break;
799118611Snjl
800151937Sjkim    case PARSEOP_QWORDSPACE:
801250838Sjkim
802151937Sjkim        Rnode = RsDoQwordSpaceDescriptor (DescriptorTypeOp,
803151937Sjkim                    CurrentByteOffset);
804151937Sjkim        break;
805151937Sjkim
806118611Snjl    case PARSEOP_REGISTER:
807250838Sjkim
808151937Sjkim        Rnode = RsDoGeneralRegisterDescriptor (DescriptorTypeOp,
809151937Sjkim                    CurrentByteOffset);
810118611Snjl        break;
811118611Snjl
812118611Snjl    case PARSEOP_STARTDEPENDENTFN:
813250838Sjkim
814118611Snjl        switch (*State)
815118611Snjl        {
816118611Snjl        case ACPI_RSTATE_START_DEPENDENT:
817250838Sjkim
818151937Sjkim            AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
819151937Sjkim                DescriptorTypeOp, NULL);
820118611Snjl            break;
821118611Snjl
822118611Snjl        case ACPI_RSTATE_NORMAL:
823118611Snjl        case ACPI_RSTATE_DEPENDENT_LIST:
824118611Snjl        default:
825250838Sjkim
826118611Snjl            break;
827118611Snjl        }
828118611Snjl
829118611Snjl        *State = ACPI_RSTATE_START_DEPENDENT;
830151937Sjkim        Rnode = RsDoStartDependentDescriptor (DescriptorTypeOp,
831151937Sjkim                    CurrentByteOffset);
832118611Snjl        *State = ACPI_RSTATE_DEPENDENT_LIST;
833118611Snjl        break;
834118611Snjl
835118611Snjl    case PARSEOP_STARTDEPENDENTFN_NOPRI:
836250838Sjkim
837118611Snjl        switch (*State)
838118611Snjl        {
839118611Snjl        case ACPI_RSTATE_START_DEPENDENT:
840250838Sjkim
841151937Sjkim            AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
842151937Sjkim                DescriptorTypeOp, NULL);
843118611Snjl            break;
844118611Snjl
845118611Snjl        case ACPI_RSTATE_NORMAL:
846118611Snjl        case ACPI_RSTATE_DEPENDENT_LIST:
847118611Snjl        default:
848250838Sjkim
849118611Snjl            break;
850118611Snjl        }
851118611Snjl
852118611Snjl        *State = ACPI_RSTATE_START_DEPENDENT;
853151937Sjkim        Rnode = RsDoStartDependentNoPriDescriptor (DescriptorTypeOp,
854151937Sjkim                    CurrentByteOffset);
855118611Snjl        *State = ACPI_RSTATE_DEPENDENT_LIST;
856118611Snjl        break;
857118611Snjl
858118611Snjl    case PARSEOP_VENDORLONG:
859250838Sjkim
860151937Sjkim        Rnode = RsDoVendorLargeDescriptor (DescriptorTypeOp,
861151937Sjkim                    CurrentByteOffset);
862118611Snjl        break;
863118611Snjl
864118611Snjl    case PARSEOP_VENDORSHORT:
865250838Sjkim
866151937Sjkim        Rnode = RsDoVendorSmallDescriptor (DescriptorTypeOp,
867151937Sjkim                    CurrentByteOffset);
868118611Snjl        break;
869118611Snjl
870118611Snjl    case PARSEOP_WORDBUSNUMBER:
871250838Sjkim
872151937Sjkim        Rnode = RsDoWordBusNumberDescriptor (DescriptorTypeOp,
873151937Sjkim                    CurrentByteOffset);
874118611Snjl        break;
875118611Snjl
876118611Snjl    case PARSEOP_WORDIO:
877250838Sjkim
878151937Sjkim        Rnode = RsDoWordIoDescriptor (DescriptorTypeOp,
879151937Sjkim                    CurrentByteOffset);
880118611Snjl        break;
881118611Snjl
882151937Sjkim    case PARSEOP_WORDSPACE:
883250838Sjkim
884151937Sjkim        Rnode = RsDoWordSpaceDescriptor (DescriptorTypeOp,
885151937Sjkim                    CurrentByteOffset);
886151937Sjkim        break;
887151937Sjkim
888228110Sjkim    case PARSEOP_GPIO_INT:
889250838Sjkim
890228110Sjkim        Rnode = RsDoGpioIntDescriptor (DescriptorTypeOp,
891228110Sjkim                    CurrentByteOffset);
892228110Sjkim        break;
893228110Sjkim
894228110Sjkim    case PARSEOP_GPIO_IO:
895250838Sjkim
896228110Sjkim        Rnode = RsDoGpioIoDescriptor (DescriptorTypeOp,
897228110Sjkim                    CurrentByteOffset);
898228110Sjkim        break;
899228110Sjkim
900228110Sjkim    case PARSEOP_I2C_SERIALBUS:
901250838Sjkim
902228110Sjkim        Rnode = RsDoI2cSerialBusDescriptor (DescriptorTypeOp,
903228110Sjkim                    CurrentByteOffset);
904228110Sjkim        break;
905228110Sjkim
906228110Sjkim    case PARSEOP_SPI_SERIALBUS:
907250838Sjkim
908228110Sjkim        Rnode = RsDoSpiSerialBusDescriptor (DescriptorTypeOp,
909228110Sjkim                    CurrentByteOffset);
910228110Sjkim        break;
911228110Sjkim
912228110Sjkim    case PARSEOP_UART_SERIALBUS:
913250838Sjkim
914228110Sjkim        Rnode = RsDoUartSerialBusDescriptor (DescriptorTypeOp,
915228110Sjkim                    CurrentByteOffset);
916228110Sjkim        break;
917228110Sjkim
918118611Snjl    case PARSEOP_DEFAULT_ARG:
919250838Sjkim
920118611Snjl        /* Just ignore any of these, they are used as fillers/placeholders */
921118611Snjl        break;
922118611Snjl
923118611Snjl    default:
924250838Sjkim
925118611Snjl        printf ("Unknown resource descriptor type [%s]\n",
926118611Snjl                    DescriptorTypeOp->Asl.ParseOpName);
927118611Snjl        break;
928118611Snjl    }
929118611Snjl
930118611Snjl    /*
931118611Snjl     * Mark original node as unused, but head of a resource descriptor.
932118611Snjl     * This allows the resource to be installed in the namespace so that
933118611Snjl     * references to the descriptor can be resolved.
934118611Snjl     */
935118611Snjl    DescriptorTypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
936118611Snjl    DescriptorTypeOp->Asl.CompileFlags = NODE_IS_RESOURCE_DESC;
937167802Sjkim    DescriptorTypeOp->Asl.Value.Integer = CurrentByteOffset;
938118611Snjl
939167802Sjkim    if (Rnode)
940167802Sjkim    {
941167802Sjkim        DescriptorTypeOp->Asl.FinalAmlLength = Rnode->BufferLength;
942249112Sjkim        DescriptorTypeOp->Asl.Extra = ((AML_RESOURCE *) Rnode->Buffer)->DescriptorType;
943167802Sjkim    }
944167802Sjkim
945118611Snjl    return (Rnode);
946118611Snjl}
947118611Snjl
948118611Snjl
949118611Snjl/*******************************************************************************
950118611Snjl *
951118611Snjl * FUNCTION:    RsLinkDescriptorChain
952118611Snjl *
953118611Snjl * PARAMETERS:  PreviousRnode       - Pointer to the node that will be previous
954118611Snjl *                                    to the linked node,  At exit, set to the
955118611Snjl *                                    last node in the new chain.
956118611Snjl *              Rnode               - Resource node to link into the list
957118611Snjl *
958118611Snjl * RETURN:      Cumulative buffer byte offset of the new segment of chain
959118611Snjl *
960118611Snjl * DESCRIPTION: Link a descriptor chain at the end of an existing chain.
961118611Snjl *
962118611Snjl ******************************************************************************/
963118611Snjl
964118611SnjlUINT32
965118611SnjlRsLinkDescriptorChain (
966118611Snjl    ASL_RESOURCE_NODE       **PreviousRnode,
967118611Snjl    ASL_RESOURCE_NODE       *Rnode)
968118611Snjl{
969118611Snjl    ASL_RESOURCE_NODE       *LastRnode;
970118611Snjl    UINT32                  CurrentByteOffset;
971118611Snjl
972118611Snjl
973118611Snjl    /* Anything to do? */
974118611Snjl
975118611Snjl    if (!Rnode)
976118611Snjl    {
977241973Sjkim        return (0);
978118611Snjl    }
979118611Snjl
980118611Snjl    /* Point the previous node to the new node */
981118611Snjl
982118611Snjl    (*PreviousRnode)->Next = Rnode;
983118611Snjl    CurrentByteOffset = Rnode->BufferLength;
984118611Snjl
985118611Snjl    /* Walk to the end of the chain headed by Rnode */
986118611Snjl
987118611Snjl    LastRnode = Rnode;
988118611Snjl    while (LastRnode->Next)
989118611Snjl    {
990118611Snjl        LastRnode = LastRnode->Next;
991118611Snjl        CurrentByteOffset += LastRnode->BufferLength;
992118611Snjl    }
993118611Snjl
994118611Snjl    /* Previous node becomes the last node in the chain */
995118611Snjl
996118611Snjl    *PreviousRnode = LastRnode;
997241973Sjkim    return (CurrentByteOffset);
998118611Snjl}
999118611Snjl
1000118611Snjl
1001118611Snjl/*******************************************************************************
1002118611Snjl *
1003118611Snjl * FUNCTION:    RsDoResourceTemplate
1004118611Snjl *
1005118611Snjl * PARAMETERS:  Op        - Parent of a resource template list
1006118611Snjl *
1007241973Sjkim * RETURN:      None. Sets input node to point to a list of AML code
1008118611Snjl *
1009118611Snjl * DESCRIPTION: Merge a list of resource descriptors into a single AML buffer,
1010118611Snjl *              in preparation for output to the AML output file.
1011118611Snjl *
1012118611Snjl ******************************************************************************/
1013118611Snjl
1014118611Snjlvoid
1015118611SnjlRsDoResourceTemplate (
1016118611Snjl    ACPI_PARSE_OBJECT       *Op)
1017118611Snjl{
1018118611Snjl    ACPI_PARSE_OBJECT       *BufferLengthOp;
1019118611Snjl    ACPI_PARSE_OBJECT       *BufferOp;
1020118611Snjl    ACPI_PARSE_OBJECT       *DescriptorTypeOp;
1021118611Snjl    ACPI_PARSE_OBJECT       *LastOp = NULL;
1022118611Snjl    UINT32                  CurrentByteOffset = 0;
1023118611Snjl    ASL_RESOURCE_NODE       HeadRnode;
1024118611Snjl    ASL_RESOURCE_NODE       *PreviousRnode;
1025118611Snjl    ASL_RESOURCE_NODE       *Rnode;
1026118611Snjl    UINT8                   State;
1027118611Snjl
1028118611Snjl
1029167802Sjkim    /* Mark parent as containing a resource template */
1030167802Sjkim
1031167802Sjkim    if (Op->Asl.Parent)
1032167802Sjkim    {
1033167802Sjkim        Op->Asl.Parent->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
1034167802Sjkim    }
1035167802Sjkim
1036118611Snjl    /* ResourceTemplate Opcode is first (Op) */
1037118611Snjl    /* Buffer Length node is first child */
1038118611Snjl
1039118611Snjl    BufferLengthOp = ASL_GET_CHILD_NODE (Op);
1040118611Snjl
1041118611Snjl    /* Buffer Op is first peer */
1042118611Snjl
1043118611Snjl    BufferOp = ASL_GET_PEER_NODE (BufferLengthOp);
1044118611Snjl
1045118611Snjl    /* First Descriptor type is next */
1046118611Snjl
1047118611Snjl    DescriptorTypeOp = ASL_GET_PEER_NODE (BufferOp);
1048118611Snjl
1049167802Sjkim    /*
1050167802Sjkim     * Process all resource descriptors in the list
1051167802Sjkim     * Note: It is assumed that the EndTag node has been automatically
1052167802Sjkim     * inserted at the end of the template by the parser.
1053167802Sjkim     */
1054118611Snjl    State = ACPI_RSTATE_NORMAL;
1055118611Snjl    PreviousRnode = &HeadRnode;
1056118611Snjl    while (DescriptorTypeOp)
1057118611Snjl    {
1058167802Sjkim        DescriptorTypeOp->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
1059151937Sjkim        Rnode = RsDoOneResourceDescriptor (DescriptorTypeOp, CurrentByteOffset,
1060151937Sjkim                    &State);
1061118611Snjl
1062118611Snjl        /*
1063118611Snjl         * Update current byte offset to indicate the number of bytes from the
1064241973Sjkim         * start of the buffer. Buffer can include multiple descriptors, we
1065118611Snjl         * must keep track of the offset of not only each descriptor, but each
1066118611Snjl         * element (field) within each descriptor as well.
1067118611Snjl         */
1068118611Snjl        CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, Rnode);
1069118611Snjl
1070118611Snjl        /* Get the next descriptor in the list */
1071118611Snjl
1072118611Snjl        LastOp = DescriptorTypeOp;
1073118611Snjl        DescriptorTypeOp = ASL_GET_PEER_NODE (DescriptorTypeOp);
1074118611Snjl    }
1075118611Snjl
1076118611Snjl    if (State == ACPI_RSTATE_DEPENDENT_LIST)
1077118611Snjl    {
1078118611Snjl        if (LastOp)
1079118611Snjl        {
1080118611Snjl            LastOp = LastOp->Asl.Parent;
1081118611Snjl        }
1082118611Snjl        AslError (ASL_ERROR, ASL_MSG_MISSING_ENDDEPENDENT, LastOp, NULL);
1083118611Snjl    }
1084118611Snjl
1085118611Snjl    /*
1086118611Snjl     * Transform the nodes into the following
1087118611Snjl     *
1088118611Snjl     * Op           -> AML_BUFFER_OP
1089118611Snjl     * First Child  -> BufferLength
1090118611Snjl     * Second Child -> Descriptor Buffer (raw byte data)
1091118611Snjl     */
1092118611Snjl    Op->Asl.ParseOpcode               = PARSEOP_BUFFER;
1093118611Snjl    Op->Asl.AmlOpcode                 = AML_BUFFER_OP;
1094167802Sjkim    Op->Asl.CompileFlags              = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC;
1095228110Sjkim    UtSetParseOpName (Op);
1096118611Snjl
1097118611Snjl    BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
1098118611Snjl    BufferLengthOp->Asl.Value.Integer = CurrentByteOffset;
1099118611Snjl    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
1100228110Sjkim    UtSetParseOpName (BufferLengthOp);
1101118611Snjl
1102118611Snjl    BufferOp->Asl.ParseOpcode         = PARSEOP_RAW_DATA;
1103118611Snjl    BufferOp->Asl.AmlOpcode           = AML_RAW_DATA_CHAIN;
1104118611Snjl    BufferOp->Asl.AmlOpcodeLength     = 0;
1105118611Snjl    BufferOp->Asl.AmlLength           = CurrentByteOffset;
1106118611Snjl    BufferOp->Asl.Value.Buffer        = (UINT8 *) HeadRnode.Next;
1107167802Sjkim    BufferOp->Asl.CompileFlags       |= NODE_IS_RESOURCE_DATA;
1108228110Sjkim    UtSetParseOpName (BufferOp);
1109118611Snjl
1110118611Snjl    return;
1111118611Snjl}
1112