aslresource.c revision 245582
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:
322207344Sjkim            AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL);
323207344Sjkim        }
324207344Sjkim    }
325207344Sjkim    else
326207344Sjkim    {
327207344Sjkim        /* Variable length (length==0) */
328207344Sjkim
329207344Sjkim        switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF))
330207344Sjkim        {
331207344Sjkim        case 0:
332207344Sjkim            /*
333207344Sjkim             * Both _MIN and _MAX are variable.
334207344Sjkim             * No additional requirements, just exit
335207344Sjkim             */
336207344Sjkim            break;
337207344Sjkim
338207344Sjkim        case ACPI_RESOURCE_FLAG_MIF:
339207344Sjkim
340207344Sjkim            /* _MIN is fixed. _MIN must be multiple of _GRA */
341207344Sjkim
342207344Sjkim            /*
343207344Sjkim             * The granularity is defined by the ACPI specification to be a
344207344Sjkim             * power-of-two minus one, therefore the granularity is a
345207344Sjkim             * bitmask which can be used to easily validate the addresses.
346207344Sjkim             */
347207344Sjkim            if (Granularity & Minimum)
348207344Sjkim            {
349207344Sjkim                AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL);
350207344Sjkim            }
351207344Sjkim            break;
352207344Sjkim
353207344Sjkim        case ACPI_RESOURCE_FLAG_MAF:
354207344Sjkim
355207344Sjkim            /* _MAX is fixed. (_MAX + 1) must be multiple of _GRA */
356207344Sjkim
357207344Sjkim            if (Granularity & (Maximum + 1))
358207344Sjkim            {
359207344Sjkim                AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, "-1");
360207344Sjkim            }
361207344Sjkim            break;
362207344Sjkim
363207344Sjkim        /* Both MIF/MAF set is invalid if length is zero */
364207344Sjkim
365207344Sjkim        case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF):
366207344Sjkim        default:
367207344Sjkim            AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL);
368207344Sjkim        }
369207344Sjkim    }
370207344Sjkim}
371207344Sjkim
372207344Sjkim
373207344Sjkim/*******************************************************************************
374207344Sjkim *
375207344Sjkim * FUNCTION:    RsGetStringDataLength
376207344Sjkim *
377207344Sjkim * PARAMETERS:  InitializerOp     - Start of a subtree of init nodes
378207344Sjkim *
379207344Sjkim * RETURN:      Valid string length if a string node is found (otherwise 0)
380207344Sjkim *
381207344Sjkim * DESCRIPTION: In a list of peer nodes, find the first one that contains a
382207344Sjkim *              string and return the length of the string.
383207344Sjkim *
384207344Sjkim ******************************************************************************/
385207344Sjkim
386207344SjkimUINT16
387207344SjkimRsGetStringDataLength (
388207344Sjkim    ACPI_PARSE_OBJECT       *InitializerOp)
389207344Sjkim{
390207344Sjkim
391207344Sjkim    while (InitializerOp)
392207344Sjkim    {
393207344Sjkim        if (InitializerOp->Asl.ParseOpcode == PARSEOP_STRING_LITERAL)
394207344Sjkim        {
395207344Sjkim            return ((UINT16) (strlen (InitializerOp->Asl.Value.String) + 1));
396207344Sjkim        }
397207344Sjkim        InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
398207344Sjkim    }
399207344Sjkim
400241973Sjkim    return (0);
401207344Sjkim}
402207344Sjkim
403207344Sjkim
404207344Sjkim/*******************************************************************************
405207344Sjkim *
406118611Snjl * FUNCTION:    RsAllocateResourceNode
407118611Snjl *
408118611Snjl * PARAMETERS:  Size        - Size of node in bytes
409118611Snjl *
410118611Snjl * RETURN:      The allocated node - aborts on allocation failure
411118611Snjl *
412118611Snjl * DESCRIPTION: Allocate a resource description node and the resource
413118611Snjl *              descriptor itself (the nodes are used to link descriptors).
414118611Snjl *
415118611Snjl ******************************************************************************/
416118611Snjl
417118611SnjlASL_RESOURCE_NODE *
418118611SnjlRsAllocateResourceNode (
419118611Snjl    UINT32                  Size)
420118611Snjl{
421118611Snjl    ASL_RESOURCE_NODE       *Rnode;
422118611Snjl
423118611Snjl
424118611Snjl    /* Allocate the node */
425118611Snjl
426118611Snjl    Rnode = UtLocalCalloc (sizeof (ASL_RESOURCE_NODE));
427118611Snjl
428118611Snjl    /* Allocate the resource descriptor itself */
429118611Snjl
430118611Snjl    Rnode->Buffer = UtLocalCalloc (Size);
431118611Snjl    Rnode->BufferLength = Size;
432118611Snjl
433118611Snjl    return (Rnode);
434118611Snjl}
435118611Snjl
436118611Snjl
437118611Snjl/*******************************************************************************
438118611Snjl *
439228110Sjkim * FUNCTION:    RsCreateResourceField
440118611Snjl *
441151937Sjkim * PARAMETERS:  Op              - Resource field node
442118611Snjl *              Name            - Name of the field (Used only to reference
443118611Snjl *                                the field in the ASL, not in the AML)
444118611Snjl *              ByteOffset      - Offset from the field start
445118611Snjl *              BitOffset       - Additional bit offset
446228110Sjkim *              BitLength       - Number of bits in the field
447118611Snjl *
448118611Snjl * RETURN:      None, sets fields within the input node
449118611Snjl *
450118611Snjl * DESCRIPTION: Utility function to generate a named bit field within a
451241973Sjkim *              resource descriptor. Mark a node as 1) a field in a resource
452118611Snjl *              descriptor, and 2) set the value to be a BIT offset
453118611Snjl *
454118611Snjl ******************************************************************************/
455118611Snjl
456118611Snjlvoid
457228110SjkimRsCreateResourceField (
458118611Snjl    ACPI_PARSE_OBJECT       *Op,
459118611Snjl    char                    *Name,
460118611Snjl    UINT32                  ByteOffset,
461228110Sjkim    UINT32                  BitOffset,
462228110Sjkim    UINT32                  BitLength)
463118611Snjl{
464118611Snjl
465228110Sjkim    Op->Asl.ExternalName = Name;
466228110Sjkim    Op->Asl.CompileFlags |= NODE_IS_RESOURCE_FIELD;
467118611Snjl
468118611Snjl
469228110Sjkim    Op->Asl.Value.Tag.BitOffset = (ByteOffset * 8) + BitOffset;
470228110Sjkim    Op->Asl.Value.Tag.BitLength = BitLength;
471118611Snjl}
472118611Snjl
473118611Snjl
474118611Snjl/*******************************************************************************
475118611Snjl *
476118611Snjl * FUNCTION:    RsSetFlagBits
477118611Snjl *
478118611Snjl * PARAMETERS:  *Flags          - Pointer to the flag byte
479151937Sjkim *              Op              - Flag initialization node
480118611Snjl *              Position        - Bit position within the flag byte
481118611Snjl *              Default         - Used if the node is DEFAULT.
482118611Snjl *
483118611Snjl * RETURN:      Sets bits within the *Flags output byte.
484118611Snjl *
485118611Snjl * DESCRIPTION: Set a bit in a cumulative flags word from an initialization
486241973Sjkim *              node. Will use a default value if the node is DEFAULT, meaning
487241973Sjkim *              that no value was specified in the ASL. Used to merge multiple
488118611Snjl *              keywords into a single flags byte.
489118611Snjl *
490118611Snjl ******************************************************************************/
491118611Snjl
492118611Snjlvoid
493118611SnjlRsSetFlagBits (
494118611Snjl    UINT8                   *Flags,
495118611Snjl    ACPI_PARSE_OBJECT       *Op,
496118611Snjl    UINT8                   Position,
497118611Snjl    UINT8                   DefaultBit)
498118611Snjl{
499118611Snjl
500118611Snjl    if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
501118611Snjl    {
502118611Snjl        /* Use the default bit */
503118611Snjl
504118611Snjl        *Flags |= (DefaultBit << Position);
505118611Snjl    }
506118611Snjl    else
507118611Snjl    {
508118611Snjl        /* Use the bit specified in the initialization node */
509118611Snjl
510118611Snjl        *Flags |= (((UINT8) Op->Asl.Value.Integer) << Position);
511118611Snjl    }
512118611Snjl}
513118611Snjl
514118611Snjl
515228110Sjkimvoid
516228110SjkimRsSetFlagBits16 (
517228110Sjkim    UINT16                  *Flags,
518228110Sjkim    ACPI_PARSE_OBJECT       *Op,
519228110Sjkim    UINT8                   Position,
520228110Sjkim    UINT8                   DefaultBit)
521228110Sjkim{
522228110Sjkim
523228110Sjkim    if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
524228110Sjkim    {
525228110Sjkim        /* Use the default bit */
526228110Sjkim
527228110Sjkim        *Flags |= (DefaultBit << Position);
528228110Sjkim    }
529228110Sjkim    else
530228110Sjkim    {
531228110Sjkim        /* Use the bit specified in the initialization node */
532228110Sjkim
533228110Sjkim        *Flags |= (((UINT16) Op->Asl.Value.Integer) << Position);
534228110Sjkim    }
535228110Sjkim}
536228110Sjkim
537228110Sjkim
538118611Snjl/*******************************************************************************
539118611Snjl *
540118611Snjl * FUNCTION:    RsCompleteNodeAndGetNext
541118611Snjl *
542118611Snjl * PARAMETERS:  Op            - Resource node to be completed
543118611Snjl *
544118611Snjl * RETURN:      The next peer to the input node.
545118611Snjl *
546118611Snjl * DESCRIPTION: Mark the current node completed and return the next peer.
547118611Snjl *              The node ParseOpcode is set to DEFAULT_ARG, meaning that
548118611Snjl *              this node is to be ignored from now on.
549118611Snjl *
550118611Snjl ******************************************************************************/
551118611Snjl
552118611SnjlACPI_PARSE_OBJECT *
553118611SnjlRsCompleteNodeAndGetNext (
554118611Snjl    ACPI_PARSE_OBJECT       *Op)
555118611Snjl{
556118611Snjl
557118611Snjl    /* Mark this node unused */
558118611Snjl
559118611Snjl    Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
560118611Snjl
561118611Snjl    /* Move on to the next peer node in the initializer list */
562118611Snjl
563118611Snjl    return (ASL_GET_PEER_NODE (Op));
564118611Snjl}
565118611Snjl
566118611Snjl
567118611Snjl/*******************************************************************************
568118611Snjl *
569151937Sjkim * FUNCTION:    RsCheckListForDuplicates
570151937Sjkim *
571151937Sjkim * PARAMETERS:  Op                  - First op in the initializer list
572151937Sjkim *
573151937Sjkim * RETURN:      None
574151937Sjkim *
575151937Sjkim * DESCRIPTION: Check an initializer list for duplicate values. Emits an error
576151937Sjkim *              if any duplicates are found.
577151937Sjkim *
578151937Sjkim ******************************************************************************/
579151937Sjkim
580151937Sjkimvoid
581151937SjkimRsCheckListForDuplicates (
582151937Sjkim    ACPI_PARSE_OBJECT       *Op)
583151937Sjkim{
584151937Sjkim    ACPI_PARSE_OBJECT       *NextValueOp = Op;
585151937Sjkim    ACPI_PARSE_OBJECT       *NextOp;
586151937Sjkim    UINT32                  Value;
587151937Sjkim
588151937Sjkim
589151937Sjkim    if (!Op)
590151937Sjkim    {
591151937Sjkim        return;
592151937Sjkim    }
593151937Sjkim
594151937Sjkim    /* Search list once for each value in the list */
595151937Sjkim
596151937Sjkim    while (NextValueOp)
597151937Sjkim    {
598151937Sjkim        Value = (UINT32) NextValueOp->Asl.Value.Integer;
599151937Sjkim
600151937Sjkim        /* Compare this value to all remaining values in the list */
601151937Sjkim
602151937Sjkim        NextOp = ASL_GET_PEER_NODE (NextValueOp);
603151937Sjkim        while (NextOp)
604151937Sjkim        {
605151937Sjkim            if (NextOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
606151937Sjkim            {
607151937Sjkim                /* Compare values */
608151937Sjkim
609151937Sjkim                if (Value == (UINT32) NextOp->Asl.Value.Integer)
610151937Sjkim                {
611151937Sjkim                    /* Emit error only once per duplicate node */
612151937Sjkim
613151937Sjkim                    if (!(NextOp->Asl.CompileFlags & NODE_IS_DUPLICATE))
614151937Sjkim                    {
615151937Sjkim                        NextOp->Asl.CompileFlags |= NODE_IS_DUPLICATE;
616151937Sjkim                        AslError (ASL_ERROR, ASL_MSG_DUPLICATE_ITEM,
617151937Sjkim                            NextOp, NULL);
618151937Sjkim                    }
619151937Sjkim                }
620151937Sjkim            }
621151937Sjkim
622151937Sjkim            NextOp = ASL_GET_PEER_NODE (NextOp);
623151937Sjkim        }
624151937Sjkim
625151937Sjkim        NextValueOp = ASL_GET_PEER_NODE (NextValueOp);
626151937Sjkim    }
627151937Sjkim}
628151937Sjkim
629151937Sjkim
630151937Sjkim/*******************************************************************************
631151937Sjkim *
632118611Snjl * FUNCTION:    RsDoOneResourceDescriptor
633118611Snjl *
634118611Snjl * PARAMETERS:  DescriptorTypeOp    - Parent parse node of the descriptor
635118611Snjl *              CurrentByteOffset   - Offset in the resource descriptor
636118611Snjl *                                    buffer.
637118611Snjl *
638118611Snjl * RETURN:      A valid resource node for the descriptor
639118611Snjl *
640118611Snjl * DESCRIPTION: Dispatches the processing of one resource descriptor
641118611Snjl *
642118611Snjl ******************************************************************************/
643118611Snjl
644118611SnjlASL_RESOURCE_NODE *
645118611SnjlRsDoOneResourceDescriptor (
646118611Snjl    ACPI_PARSE_OBJECT       *DescriptorTypeOp,
647118611Snjl    UINT32                  CurrentByteOffset,
648118611Snjl    UINT8                   *State)
649118611Snjl{
650118611Snjl    ASL_RESOURCE_NODE       *Rnode = NULL;
651118611Snjl
652118611Snjl
653167802Sjkim    /* Construct the resource */
654118611Snjl
655118611Snjl    switch (DescriptorTypeOp->Asl.ParseOpcode)
656118611Snjl    {
657118611Snjl    case PARSEOP_DMA:
658151937Sjkim        Rnode = RsDoDmaDescriptor (DescriptorTypeOp,
659151937Sjkim                    CurrentByteOffset);
660118611Snjl        break;
661118611Snjl
662228110Sjkim    case PARSEOP_FIXEDDMA:
663228110Sjkim        Rnode = RsDoFixedDmaDescriptor (DescriptorTypeOp,
664228110Sjkim                    CurrentByteOffset);
665228110Sjkim        break;
666228110Sjkim
667118611Snjl    case PARSEOP_DWORDIO:
668151937Sjkim        Rnode = RsDoDwordIoDescriptor (DescriptorTypeOp,
669151937Sjkim                    CurrentByteOffset);
670118611Snjl        break;
671118611Snjl
672118611Snjl    case PARSEOP_DWORDMEMORY:
673151937Sjkim        Rnode = RsDoDwordMemoryDescriptor (DescriptorTypeOp,
674151937Sjkim                    CurrentByteOffset);
675118611Snjl        break;
676118611Snjl
677151937Sjkim    case PARSEOP_DWORDSPACE:
678151937Sjkim        Rnode = RsDoDwordSpaceDescriptor (DescriptorTypeOp,
679151937Sjkim                    CurrentByteOffset);
680151937Sjkim        break;
681151937Sjkim
682118611Snjl    case PARSEOP_ENDDEPENDENTFN:
683118611Snjl        switch (*State)
684118611Snjl        {
685118611Snjl        case ACPI_RSTATE_NORMAL:
686151937Sjkim            AslError (ASL_ERROR, ASL_MSG_MISSING_STARTDEPENDENT,
687151937Sjkim                DescriptorTypeOp, NULL);
688118611Snjl            break;
689118611Snjl
690118611Snjl        case ACPI_RSTATE_START_DEPENDENT:
691151937Sjkim            AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
692151937Sjkim                DescriptorTypeOp, NULL);
693118611Snjl            break;
694118611Snjl
695118611Snjl        case ACPI_RSTATE_DEPENDENT_LIST:
696118611Snjl        default:
697118611Snjl            break;
698118611Snjl        }
699118611Snjl
700118611Snjl        *State = ACPI_RSTATE_NORMAL;
701151937Sjkim        Rnode = RsDoEndDependentDescriptor (DescriptorTypeOp,
702151937Sjkim                    CurrentByteOffset);
703118611Snjl        break;
704118611Snjl
705167802Sjkim    case PARSEOP_ENDTAG:
706167802Sjkim        Rnode = RsDoEndTagDescriptor (DescriptorTypeOp,
707167802Sjkim                    CurrentByteOffset);
708167802Sjkim        break;
709167802Sjkim
710151937Sjkim    case PARSEOP_EXTENDEDIO:
711151937Sjkim        Rnode = RsDoExtendedIoDescriptor (DescriptorTypeOp,
712151937Sjkim                    CurrentByteOffset);
713151937Sjkim        break;
714151937Sjkim
715151937Sjkim    case PARSEOP_EXTENDEDMEMORY:
716151937Sjkim        Rnode = RsDoExtendedMemoryDescriptor (DescriptorTypeOp,
717151937Sjkim                    CurrentByteOffset);
718151937Sjkim        break;
719151937Sjkim
720151937Sjkim    case PARSEOP_EXTENDEDSPACE:
721151937Sjkim        Rnode = RsDoExtendedSpaceDescriptor (DescriptorTypeOp,
722151937Sjkim                    CurrentByteOffset);
723151937Sjkim        break;
724151937Sjkim
725118611Snjl    case PARSEOP_FIXEDIO:
726151937Sjkim        Rnode = RsDoFixedIoDescriptor (DescriptorTypeOp,
727151937Sjkim                    CurrentByteOffset);
728118611Snjl        break;
729118611Snjl
730118611Snjl    case PARSEOP_INTERRUPT:
731151937Sjkim        Rnode = RsDoInterruptDescriptor (DescriptorTypeOp,
732151937Sjkim                    CurrentByteOffset);
733118611Snjl        break;
734118611Snjl
735118611Snjl    case PARSEOP_IO:
736151937Sjkim        Rnode = RsDoIoDescriptor (DescriptorTypeOp,
737151937Sjkim                    CurrentByteOffset);
738118611Snjl        break;
739118611Snjl
740118611Snjl    case PARSEOP_IRQ:
741151937Sjkim        Rnode = RsDoIrqDescriptor (DescriptorTypeOp,
742151937Sjkim                    CurrentByteOffset);
743118611Snjl        break;
744118611Snjl
745118611Snjl    case PARSEOP_IRQNOFLAGS:
746151937Sjkim        Rnode = RsDoIrqNoFlagsDescriptor (DescriptorTypeOp,
747151937Sjkim                    CurrentByteOffset);
748118611Snjl        break;
749118611Snjl
750118611Snjl    case PARSEOP_MEMORY24:
751151937Sjkim        Rnode = RsDoMemory24Descriptor (DescriptorTypeOp,
752151937Sjkim                    CurrentByteOffset);
753118611Snjl        break;
754118611Snjl
755118611Snjl    case PARSEOP_MEMORY32:
756151937Sjkim        Rnode = RsDoMemory32Descriptor (DescriptorTypeOp,
757151937Sjkim                    CurrentByteOffset);
758118611Snjl        break;
759118611Snjl
760118611Snjl    case PARSEOP_MEMORY32FIXED:
761151937Sjkim        Rnode = RsDoMemory32FixedDescriptor (DescriptorTypeOp,
762151937Sjkim                    CurrentByteOffset);
763118611Snjl        break;
764118611Snjl
765118611Snjl    case PARSEOP_QWORDIO:
766151937Sjkim        Rnode = RsDoQwordIoDescriptor (DescriptorTypeOp,
767151937Sjkim                    CurrentByteOffset);
768118611Snjl        break;
769118611Snjl
770118611Snjl    case PARSEOP_QWORDMEMORY:
771151937Sjkim        Rnode = RsDoQwordMemoryDescriptor (DescriptorTypeOp,
772151937Sjkim                    CurrentByteOffset);
773118611Snjl        break;
774118611Snjl
775151937Sjkim    case PARSEOP_QWORDSPACE:
776151937Sjkim        Rnode = RsDoQwordSpaceDescriptor (DescriptorTypeOp,
777151937Sjkim                    CurrentByteOffset);
778151937Sjkim        break;
779151937Sjkim
780118611Snjl    case PARSEOP_REGISTER:
781151937Sjkim        Rnode = RsDoGeneralRegisterDescriptor (DescriptorTypeOp,
782151937Sjkim                    CurrentByteOffset);
783118611Snjl        break;
784118611Snjl
785118611Snjl    case PARSEOP_STARTDEPENDENTFN:
786118611Snjl        switch (*State)
787118611Snjl        {
788118611Snjl        case ACPI_RSTATE_START_DEPENDENT:
789151937Sjkim            AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
790151937Sjkim                DescriptorTypeOp, NULL);
791118611Snjl            break;
792118611Snjl
793118611Snjl        case ACPI_RSTATE_NORMAL:
794118611Snjl        case ACPI_RSTATE_DEPENDENT_LIST:
795118611Snjl        default:
796118611Snjl            break;
797118611Snjl        }
798118611Snjl
799118611Snjl        *State = ACPI_RSTATE_START_DEPENDENT;
800151937Sjkim        Rnode = RsDoStartDependentDescriptor (DescriptorTypeOp,
801151937Sjkim                    CurrentByteOffset);
802118611Snjl        *State = ACPI_RSTATE_DEPENDENT_LIST;
803118611Snjl        break;
804118611Snjl
805118611Snjl    case PARSEOP_STARTDEPENDENTFN_NOPRI:
806118611Snjl        switch (*State)
807118611Snjl        {
808118611Snjl        case ACPI_RSTATE_START_DEPENDENT:
809151937Sjkim            AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
810151937Sjkim                DescriptorTypeOp, NULL);
811118611Snjl            break;
812118611Snjl
813118611Snjl        case ACPI_RSTATE_NORMAL:
814118611Snjl        case ACPI_RSTATE_DEPENDENT_LIST:
815118611Snjl        default:
816118611Snjl            break;
817118611Snjl        }
818118611Snjl
819118611Snjl        *State = ACPI_RSTATE_START_DEPENDENT;
820151937Sjkim        Rnode = RsDoStartDependentNoPriDescriptor (DescriptorTypeOp,
821151937Sjkim                    CurrentByteOffset);
822118611Snjl        *State = ACPI_RSTATE_DEPENDENT_LIST;
823118611Snjl        break;
824118611Snjl
825118611Snjl    case PARSEOP_VENDORLONG:
826151937Sjkim        Rnode = RsDoVendorLargeDescriptor (DescriptorTypeOp,
827151937Sjkim                    CurrentByteOffset);
828118611Snjl        break;
829118611Snjl
830118611Snjl    case PARSEOP_VENDORSHORT:
831151937Sjkim        Rnode = RsDoVendorSmallDescriptor (DescriptorTypeOp,
832151937Sjkim                    CurrentByteOffset);
833118611Snjl        break;
834118611Snjl
835118611Snjl    case PARSEOP_WORDBUSNUMBER:
836151937Sjkim        Rnode = RsDoWordBusNumberDescriptor (DescriptorTypeOp,
837151937Sjkim                    CurrentByteOffset);
838118611Snjl        break;
839118611Snjl
840118611Snjl    case PARSEOP_WORDIO:
841151937Sjkim        Rnode = RsDoWordIoDescriptor (DescriptorTypeOp,
842151937Sjkim                    CurrentByteOffset);
843118611Snjl        break;
844118611Snjl
845151937Sjkim    case PARSEOP_WORDSPACE:
846151937Sjkim        Rnode = RsDoWordSpaceDescriptor (DescriptorTypeOp,
847151937Sjkim                    CurrentByteOffset);
848151937Sjkim        break;
849151937Sjkim
850228110Sjkim    case PARSEOP_GPIO_INT:
851228110Sjkim        Rnode = RsDoGpioIntDescriptor (DescriptorTypeOp,
852228110Sjkim                    CurrentByteOffset);
853228110Sjkim        break;
854228110Sjkim
855228110Sjkim    case PARSEOP_GPIO_IO:
856228110Sjkim        Rnode = RsDoGpioIoDescriptor (DescriptorTypeOp,
857228110Sjkim                    CurrentByteOffset);
858228110Sjkim        break;
859228110Sjkim
860228110Sjkim    case PARSEOP_I2C_SERIALBUS:
861228110Sjkim        Rnode = RsDoI2cSerialBusDescriptor (DescriptorTypeOp,
862228110Sjkim                    CurrentByteOffset);
863228110Sjkim        break;
864228110Sjkim
865228110Sjkim    case PARSEOP_SPI_SERIALBUS:
866228110Sjkim        Rnode = RsDoSpiSerialBusDescriptor (DescriptorTypeOp,
867228110Sjkim                    CurrentByteOffset);
868228110Sjkim        break;
869228110Sjkim
870228110Sjkim    case PARSEOP_UART_SERIALBUS:
871228110Sjkim        Rnode = RsDoUartSerialBusDescriptor (DescriptorTypeOp,
872228110Sjkim                    CurrentByteOffset);
873228110Sjkim        break;
874228110Sjkim
875118611Snjl    case PARSEOP_DEFAULT_ARG:
876118611Snjl        /* Just ignore any of these, they are used as fillers/placeholders */
877118611Snjl        break;
878118611Snjl
879118611Snjl    default:
880118611Snjl        printf ("Unknown resource descriptor type [%s]\n",
881118611Snjl                    DescriptorTypeOp->Asl.ParseOpName);
882118611Snjl        break;
883118611Snjl    }
884118611Snjl
885118611Snjl    /*
886118611Snjl     * Mark original node as unused, but head of a resource descriptor.
887118611Snjl     * This allows the resource to be installed in the namespace so that
888118611Snjl     * references to the descriptor can be resolved.
889118611Snjl     */
890118611Snjl    DescriptorTypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
891118611Snjl    DescriptorTypeOp->Asl.CompileFlags = NODE_IS_RESOURCE_DESC;
892167802Sjkim    DescriptorTypeOp->Asl.Value.Integer = CurrentByteOffset;
893118611Snjl
894167802Sjkim    if (Rnode)
895167802Sjkim    {
896167802Sjkim        DescriptorTypeOp->Asl.FinalAmlLength = Rnode->BufferLength;
897167802Sjkim    }
898167802Sjkim
899118611Snjl    return (Rnode);
900118611Snjl}
901118611Snjl
902118611Snjl
903118611Snjl/*******************************************************************************
904118611Snjl *
905118611Snjl * FUNCTION:    RsLinkDescriptorChain
906118611Snjl *
907118611Snjl * PARAMETERS:  PreviousRnode       - Pointer to the node that will be previous
908118611Snjl *                                    to the linked node,  At exit, set to the
909118611Snjl *                                    last node in the new chain.
910118611Snjl *              Rnode               - Resource node to link into the list
911118611Snjl *
912118611Snjl * RETURN:      Cumulative buffer byte offset of the new segment of chain
913118611Snjl *
914118611Snjl * DESCRIPTION: Link a descriptor chain at the end of an existing chain.
915118611Snjl *
916118611Snjl ******************************************************************************/
917118611Snjl
918118611SnjlUINT32
919118611SnjlRsLinkDescriptorChain (
920118611Snjl    ASL_RESOURCE_NODE       **PreviousRnode,
921118611Snjl    ASL_RESOURCE_NODE       *Rnode)
922118611Snjl{
923118611Snjl    ASL_RESOURCE_NODE       *LastRnode;
924118611Snjl    UINT32                  CurrentByteOffset;
925118611Snjl
926118611Snjl
927118611Snjl    /* Anything to do? */
928118611Snjl
929118611Snjl    if (!Rnode)
930118611Snjl    {
931241973Sjkim        return (0);
932118611Snjl    }
933118611Snjl
934118611Snjl    /* Point the previous node to the new node */
935118611Snjl
936118611Snjl    (*PreviousRnode)->Next = Rnode;
937118611Snjl    CurrentByteOffset = Rnode->BufferLength;
938118611Snjl
939118611Snjl    /* Walk to the end of the chain headed by Rnode */
940118611Snjl
941118611Snjl    LastRnode = Rnode;
942118611Snjl    while (LastRnode->Next)
943118611Snjl    {
944118611Snjl        LastRnode = LastRnode->Next;
945118611Snjl        CurrentByteOffset += LastRnode->BufferLength;
946118611Snjl    }
947118611Snjl
948118611Snjl    /* Previous node becomes the last node in the chain */
949118611Snjl
950118611Snjl    *PreviousRnode = LastRnode;
951241973Sjkim    return (CurrentByteOffset);
952118611Snjl}
953118611Snjl
954118611Snjl
955118611Snjl/*******************************************************************************
956118611Snjl *
957118611Snjl * FUNCTION:    RsDoResourceTemplate
958118611Snjl *
959118611Snjl * PARAMETERS:  Op        - Parent of a resource template list
960118611Snjl *
961241973Sjkim * RETURN:      None. Sets input node to point to a list of AML code
962118611Snjl *
963118611Snjl * DESCRIPTION: Merge a list of resource descriptors into a single AML buffer,
964118611Snjl *              in preparation for output to the AML output file.
965118611Snjl *
966118611Snjl ******************************************************************************/
967118611Snjl
968118611Snjlvoid
969118611SnjlRsDoResourceTemplate (
970118611Snjl    ACPI_PARSE_OBJECT       *Op)
971118611Snjl{
972118611Snjl    ACPI_PARSE_OBJECT       *BufferLengthOp;
973118611Snjl    ACPI_PARSE_OBJECT       *BufferOp;
974118611Snjl    ACPI_PARSE_OBJECT       *DescriptorTypeOp;
975118611Snjl    ACPI_PARSE_OBJECT       *LastOp = NULL;
976118611Snjl    UINT32                  CurrentByteOffset = 0;
977118611Snjl    ASL_RESOURCE_NODE       HeadRnode;
978118611Snjl    ASL_RESOURCE_NODE       *PreviousRnode;
979118611Snjl    ASL_RESOURCE_NODE       *Rnode;
980118611Snjl    UINT8                   State;
981118611Snjl
982118611Snjl
983167802Sjkim    /* Mark parent as containing a resource template */
984167802Sjkim
985167802Sjkim    if (Op->Asl.Parent)
986167802Sjkim    {
987167802Sjkim        Op->Asl.Parent->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
988167802Sjkim    }
989167802Sjkim
990118611Snjl    /* ResourceTemplate Opcode is first (Op) */
991118611Snjl    /* Buffer Length node is first child */
992118611Snjl
993118611Snjl    BufferLengthOp = ASL_GET_CHILD_NODE (Op);
994118611Snjl
995118611Snjl    /* Buffer Op is first peer */
996118611Snjl
997118611Snjl    BufferOp = ASL_GET_PEER_NODE (BufferLengthOp);
998118611Snjl
999118611Snjl    /* First Descriptor type is next */
1000118611Snjl
1001118611Snjl    DescriptorTypeOp = ASL_GET_PEER_NODE (BufferOp);
1002118611Snjl
1003167802Sjkim    /*
1004167802Sjkim     * Process all resource descriptors in the list
1005167802Sjkim     * Note: It is assumed that the EndTag node has been automatically
1006167802Sjkim     * inserted at the end of the template by the parser.
1007167802Sjkim     */
1008118611Snjl    State = ACPI_RSTATE_NORMAL;
1009118611Snjl    PreviousRnode = &HeadRnode;
1010118611Snjl    while (DescriptorTypeOp)
1011118611Snjl    {
1012167802Sjkim        DescriptorTypeOp->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
1013151937Sjkim        Rnode = RsDoOneResourceDescriptor (DescriptorTypeOp, CurrentByteOffset,
1014151937Sjkim                    &State);
1015118611Snjl
1016118611Snjl        /*
1017118611Snjl         * Update current byte offset to indicate the number of bytes from the
1018241973Sjkim         * start of the buffer. Buffer can include multiple descriptors, we
1019118611Snjl         * must keep track of the offset of not only each descriptor, but each
1020118611Snjl         * element (field) within each descriptor as well.
1021118611Snjl         */
1022118611Snjl        CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, Rnode);
1023118611Snjl
1024118611Snjl        /* Get the next descriptor in the list */
1025118611Snjl
1026118611Snjl        LastOp = DescriptorTypeOp;
1027118611Snjl        DescriptorTypeOp = ASL_GET_PEER_NODE (DescriptorTypeOp);
1028118611Snjl    }
1029118611Snjl
1030118611Snjl    if (State == ACPI_RSTATE_DEPENDENT_LIST)
1031118611Snjl    {
1032118611Snjl        if (LastOp)
1033118611Snjl        {
1034118611Snjl            LastOp = LastOp->Asl.Parent;
1035118611Snjl        }
1036118611Snjl        AslError (ASL_ERROR, ASL_MSG_MISSING_ENDDEPENDENT, LastOp, NULL);
1037118611Snjl    }
1038118611Snjl
1039118611Snjl    /*
1040118611Snjl     * Transform the nodes into the following
1041118611Snjl     *
1042118611Snjl     * Op           -> AML_BUFFER_OP
1043118611Snjl     * First Child  -> BufferLength
1044118611Snjl     * Second Child -> Descriptor Buffer (raw byte data)
1045118611Snjl     */
1046118611Snjl    Op->Asl.ParseOpcode               = PARSEOP_BUFFER;
1047118611Snjl    Op->Asl.AmlOpcode                 = AML_BUFFER_OP;
1048167802Sjkim    Op->Asl.CompileFlags              = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC;
1049228110Sjkim    UtSetParseOpName (Op);
1050118611Snjl
1051118611Snjl    BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
1052118611Snjl    BufferLengthOp->Asl.Value.Integer = CurrentByteOffset;
1053118611Snjl    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
1054228110Sjkim    UtSetParseOpName (BufferLengthOp);
1055118611Snjl
1056118611Snjl    BufferOp->Asl.ParseOpcode         = PARSEOP_RAW_DATA;
1057118611Snjl    BufferOp->Asl.AmlOpcode           = AML_RAW_DATA_CHAIN;
1058118611Snjl    BufferOp->Asl.AmlOpcodeLength     = 0;
1059118611Snjl    BufferOp->Asl.AmlLength           = CurrentByteOffset;
1060118611Snjl    BufferOp->Asl.Value.Buffer        = (UINT8 *) HeadRnode.Next;
1061167802Sjkim    BufferOp->Asl.CompileFlags       |= NODE_IS_RESOURCE_DATA;
1062228110Sjkim    UtSetParseOpName (BufferOp);
1063118611Snjl
1064118611Snjl    return;
1065118611Snjl}
1066