1 /******************************************************************************
2  *
3  * Module Name: aslrestype2 - Miscellaneous Large resource descriptors
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2014, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "aslcompiler.h"
45 #include "aslcompiler.y.h"
46 #include "amlcode.h"
47 
48 #define _COMPONENT          ACPI_COMPILER
49         ACPI_MODULE_NAME    ("aslrestype2")
50 
51 /*
52  * This module contains miscellaneous large resource descriptors:
53  *
54  * Register
55  * Interrupt
56  * VendorLong
57  */
58 
59 /*******************************************************************************
60  *
61  * FUNCTION:    RsDoGeneralRegisterDescriptor
62  *
63  * PARAMETERS:  Info                - Parse Op and resource template offset
64  *
65  * RETURN:      Completed resource node
66  *
67  * DESCRIPTION: Construct a long "Register" descriptor
68  *
69  ******************************************************************************/
70 
71 ASL_RESOURCE_NODE *
72 RsDoGeneralRegisterDescriptor (
73     ASL_RESOURCE_INFO       *Info)
74 {
75     AML_RESOURCE            *Descriptor;
76     ACPI_PARSE_OBJECT       *InitializerOp;
77     ASL_RESOURCE_NODE       *Rnode;
78     UINT32                  CurrentByteOffset;
79     UINT32                  i;
80 
81 
82     InitializerOp = Info->DescriptorTypeOp->Asl.Child;
83     CurrentByteOffset = Info->CurrentByteOffset;
84     Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_GENERIC_REGISTER));
85 
86     Descriptor = Rnode->Buffer;
87     Descriptor->GenericReg.DescriptorType = ACPI_RESOURCE_NAME_GENERIC_REGISTER;
88     Descriptor->GenericReg.ResourceLength = 12;
89 
90     /* Process all child initialization nodes */
91 
92     for (i = 0; InitializerOp; i++)
93     {
94         switch (i)
95         {
96         case 0: /* Address space */
97 
98             Descriptor->GenericReg.AddressSpaceId = (UINT8) InitializerOp->Asl.Value.Integer;
99             RsCreateByteField (InitializerOp, ACPI_RESTAG_ADDRESSSPACE,
100                 CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.AddressSpaceId));
101            break;
102 
103         case 1: /* Register Bit Width */
104 
105             Descriptor->GenericReg.BitWidth = (UINT8) InitializerOp->Asl.Value.Integer;
106             RsCreateByteField (InitializerOp, ACPI_RESTAG_REGISTERBITWIDTH,
107                 CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.BitWidth));
108             break;
109 
110         case 2: /* Register Bit Offset */
111 
112             Descriptor->GenericReg.BitOffset = (UINT8) InitializerOp->Asl.Value.Integer;
113             RsCreateByteField (InitializerOp, ACPI_RESTAG_REGISTERBITOFFSET,
114                 CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.BitOffset));
115             break;
116 
117         case 3: /* Register Address */
118 
119             Descriptor->GenericReg.Address = InitializerOp->Asl.Value.Integer;
120             RsCreateQwordField (InitializerOp, ACPI_RESTAG_ADDRESS,
121                 CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.Address));
122             break;
123 
124         case 4: /* Access Size (ACPI 3.0) */
125 
126             Descriptor->GenericReg.AccessSize = (UINT8) InitializerOp->Asl.Value.Integer;
127             RsCreateByteField (InitializerOp, ACPI_RESTAG_ACCESSSIZE,
128                 CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.AccessSize));
129 
130             if (Descriptor->GenericReg.AccessSize > AML_FIELD_ACCESS_QWORD)
131             {
132                 AslError (ASL_ERROR, ASL_MSG_INVALID_ACCESS_SIZE,
133                     InitializerOp, NULL);
134             }
135             break;
136 
137         case 5: /* ResourceTag (ACPI 3.0b) */
138 
139             UtAttachNamepathToOwner (Info->DescriptorTypeOp, InitializerOp);
140             break;
141 
142         default:
143 
144             AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
145             break;
146         }
147 
148         InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
149     }
150     return (Rnode);
151 }
152 
153 
154 /*******************************************************************************
155  *
156  * FUNCTION:    RsDoInterruptDescriptor
157  *
158  * PARAMETERS:  Info                - Parse Op and resource template offset
159  *
160  * RETURN:      Completed resource node
161  *
162  * DESCRIPTION: Construct a long "Interrupt" descriptor
163  *
164  ******************************************************************************/
165 
166 ASL_RESOURCE_NODE *
167 RsDoInterruptDescriptor (
168     ASL_RESOURCE_INFO       *Info)
169 {
170     AML_RESOURCE            *Descriptor;
171     AML_RESOURCE            *Rover = NULL;
172     ACPI_PARSE_OBJECT       *InitializerOp;
173     ASL_RESOURCE_NODE       *Rnode;
174     UINT16                  StringLength = 0;
175     UINT32                  OptionIndex = 0;
176     UINT32                  CurrentByteOffset;
177     UINT32                  i;
178     BOOLEAN                 HasResSourceIndex = FALSE;
179     UINT8                   ResSourceIndex = 0;
180     UINT8                   *ResSourceString = NULL;
181 
182 
183     InitializerOp = Info->DescriptorTypeOp->Asl.Child;
184     CurrentByteOffset = Info->CurrentByteOffset;
185     StringLength = RsGetStringDataLength (InitializerOp);
186 
187     /* Count the interrupt numbers */
188 
189     for (i = 0; InitializerOp; i++)
190     {
191         InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
192 
193         if (i <= 6)
194         {
195             if (i == 3 &&
196                 InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
197             {
198                 /*
199                  * ResourceSourceIndex was specified, always make room for
200                  * it, even if the ResourceSource was omitted.
201                  */
202                 OptionIndex++;
203             }
204 
205             continue;
206         }
207 
208         OptionIndex += 4;
209     }
210 
211     InitializerOp = Info->DescriptorTypeOp->Asl.Child;
212     Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_EXTENDED_IRQ) +
213         1 + OptionIndex + StringLength);
214 
215     Descriptor = Rnode->Buffer;
216     Descriptor->ExtendedIrq.DescriptorType  = ACPI_RESOURCE_NAME_EXTENDED_IRQ;
217 
218     /*
219      * Initial descriptor length -- may be enlarged if there are
220      * optional fields present
221      */
222     Descriptor->ExtendedIrq.ResourceLength  = 2;  /* Flags and table length byte */
223     Descriptor->ExtendedIrq.InterruptCount  = 0;
224 
225     Rover = ACPI_CAST_PTR (AML_RESOURCE,
226                 (&(Descriptor->ExtendedIrq.Interrupts[0])));
227 
228     /* Process all child initialization nodes */
229 
230     for (i = 0; InitializerOp; i++)
231     {
232         switch (i)
233         {
234         case 0: /* Resource Usage (Default: consumer (1) */
235 
236             RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 0, 1);
237             break;
238 
239         case 1: /* Interrupt Type (or Mode - edge/level) */
240 
241             RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 1, 0);
242             RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTTYPE,
243                 CurrentByteOffset + ASL_RESDESC_OFFSET (ExtendedIrq.Flags), 1);
244             break;
245 
246         case 2: /* Interrupt Level (or Polarity - Active high/low) */
247 
248             RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 2, 0);
249             RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTLEVEL,
250                 CurrentByteOffset + ASL_RESDESC_OFFSET (ExtendedIrq.Flags), 2);
251             break;
252 
253         case 3: /* Share Type - Default: exclusive (0) */
254 
255             RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 3, 0);
256             RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTSHARE,
257                 CurrentByteOffset + ASL_RESDESC_OFFSET (ExtendedIrq.Flags), 3);
258             break;
259 
260         case 4: /* ResSourceIndex [Optional Field - BYTE] */
261 
262             if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
263             {
264                 HasResSourceIndex = TRUE;
265                 ResSourceIndex = (UINT8) InitializerOp->Asl.Value.Integer;
266             }
267             break;
268 
269         case 5: /* ResSource [Optional Field - STRING] */
270 
271             if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
272                 (InitializerOp->Asl.Value.String))
273             {
274                 if (StringLength)
275                 {
276                     ResSourceString = (UINT8 *) InitializerOp->Asl.Value.String;
277                 }
278 
279                 /* ResourceSourceIndex must also be valid */
280 
281                 if (!HasResSourceIndex)
282                 {
283                     AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
284                         InitializerOp, NULL);
285                 }
286             }
287 
288 #if 0
289             /*
290              * Not a valid ResourceSource, ResourceSourceIndex must also
291              * be invalid
292              */
293             else if (HasResSourceIndex)
294             {
295                 AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
296                     InitializerOp, NULL);
297             }
298 #endif
299             break;
300 
301         case 6: /* ResourceTag */
302 
303             UtAttachNamepathToOwner (Info->DescriptorTypeOp, InitializerOp);
304             break;
305 
306         default:
307             /*
308              * Interrupt Numbers come through here, repeatedly
309              */
310 
311             /* Maximum 255 interrupts allowed for this descriptor */
312 
313             if (Descriptor->ExtendedIrq.InterruptCount == 255)
314             {
315                 AslError (ASL_ERROR, ASL_MSG_EX_INTERRUPT_LIST,
316                     InitializerOp, NULL);
317                 return (Rnode);
318             }
319 
320             /* Each interrupt number must be a 32-bit value */
321 
322             if (InitializerOp->Asl.Value.Integer > ACPI_UINT32_MAX)
323             {
324                 AslError (ASL_ERROR, ASL_MSG_EX_INTERRUPT_NUMBER,
325                     InitializerOp, NULL);
326             }
327 
328             /* Save the integer and move pointer to the next one */
329 
330             Rover->DwordItem = (UINT32) InitializerOp->Asl.Value.Integer;
331             Rover = ACPI_ADD_PTR (AML_RESOURCE, &(Rover->DwordItem), 4);
332             Descriptor->ExtendedIrq.InterruptCount++;
333             Descriptor->ExtendedIrq.ResourceLength += 4;
334 
335             /* Case 7: First interrupt number in list */
336 
337             if (i == 7)
338             {
339                 if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
340                 {
341                     /* Must be at least one interrupt */
342 
343                     AslError (ASL_ERROR, ASL_MSG_EX_INTERRUPT_LIST_MIN,
344                         InitializerOp, NULL);
345                 }
346 
347                 /* Check now for duplicates in list */
348 
349                 RsCheckListForDuplicates (InitializerOp);
350 
351                 /* Create a named field at the start of the list */
352 
353                 RsCreateDwordField (InitializerOp, ACPI_RESTAG_INTERRUPT,
354                     CurrentByteOffset +
355                     ASL_RESDESC_OFFSET (ExtendedIrq.Interrupts[0]));
356             }
357         }
358 
359         InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
360     }
361 
362 
363     /* Add optional ResSourceIndex if present */
364 
365     if (HasResSourceIndex)
366     {
367         Rover->ByteItem = ResSourceIndex;
368         Rover = ACPI_ADD_PTR (AML_RESOURCE, &(Rover->ByteItem), 1);
369         Descriptor->ExtendedIrq.ResourceLength += 1;
370     }
371 
372     /* Add optional ResSource string if present */
373 
374     if (StringLength && ResSourceString)
375     {
376 
377         strcpy ((char *) Rover, (char *) ResSourceString);
378         Rover = ACPI_ADD_PTR (
379                     AML_RESOURCE, &(Rover->ByteItem), StringLength);
380 
381         Descriptor->ExtendedIrq.ResourceLength = (UINT16)
382             (Descriptor->ExtendedIrq.ResourceLength + StringLength);
383     }
384 
385     Rnode->BufferLength = (ASL_RESDESC_OFFSET (ExtendedIrq.Interrupts[0]) -
386                            ASL_RESDESC_OFFSET (ExtendedIrq.DescriptorType))
387                            + OptionIndex + StringLength;
388     return (Rnode);
389 }
390 
391 
392 /*******************************************************************************
393  *
394  * FUNCTION:    RsDoVendorLargeDescriptor
395  *
396  * PARAMETERS:  Info                - Parse Op and resource template offset
397  *
398  * RETURN:      Completed resource node
399  *
400  * DESCRIPTION: Construct a long "VendorLong" descriptor
401  *
402  ******************************************************************************/
403 
404 ASL_RESOURCE_NODE *
405 RsDoVendorLargeDescriptor (
406     ASL_RESOURCE_INFO       *Info)
407 {
408     AML_RESOURCE            *Descriptor;
409     ACPI_PARSE_OBJECT       *InitializerOp;
410     ASL_RESOURCE_NODE       *Rnode;
411     UINT8                   *VendorData;
412     UINT32                  i;
413 
414 
415     /* Count the number of data bytes */
416 
417     InitializerOp = Info->DescriptorTypeOp->Asl.Child;
418     InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
419 
420     for (i = 0; InitializerOp; i++)
421     {
422         if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
423         {
424             break;
425         }
426         InitializerOp = InitializerOp->Asl.Next;
427     }
428 
429     InitializerOp = Info->DescriptorTypeOp->Asl.Child;
430     InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
431     Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_VENDOR_LARGE) + i);
432 
433     Descriptor = Rnode->Buffer;
434     Descriptor->VendorLarge.DescriptorType  = ACPI_RESOURCE_NAME_VENDOR_LARGE;
435     Descriptor->VendorLarge.ResourceLength = (UINT16) i;
436 
437     /* Point to end-of-descriptor for vendor data */
438 
439     VendorData = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_LARGE_HEADER);
440 
441     /* Process all child initialization nodes */
442 
443     for (i = 0; InitializerOp; i++)
444     {
445         if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
446         {
447             break;
448         }
449 
450         VendorData[i] = (UINT8) InitializerOp->Asl.Value.Integer;
451         InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
452     }
453 
454     return (Rnode);
455 }
456