1 /******************************************************************************
2  *
3  * Module Name: aslrestype2 - Miscellaneous Large resource descriptors
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, 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.AddressSpaceId == ACPI_ADR_SPACE_PLATFORM_COMM)
131             {
132                 break;
133             }
134 
135             if (Descriptor->GenericReg.AccessSize > AML_FIELD_ACCESS_QWORD)
136             {
137                 AslError (ASL_ERROR, ASL_MSG_INVALID_ACCESS_SIZE,
138                     InitializerOp, NULL);
139             }
140             break;
141 
142         case 5: /* ResourceTag (ACPI 3.0b) */
143 
144             UtAttachNamepathToOwner (Info->DescriptorTypeOp, InitializerOp);
145             break;
146 
147         default:
148 
149             AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
150             break;
151         }
152 
153         InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
154     }
155 
156     return (Rnode);
157 }
158 
159 
160 /*******************************************************************************
161  *
162  * FUNCTION:    RsDoInterruptDescriptor
163  *
164  * PARAMETERS:  Info                - Parse Op and resource template offset
165  *
166  * RETURN:      Completed resource node
167  *
168  * DESCRIPTION: Construct a long "Interrupt" descriptor
169  *
170  ******************************************************************************/
171 
172 ASL_RESOURCE_NODE *
173 RsDoInterruptDescriptor (
174     ASL_RESOURCE_INFO       *Info)
175 {
176     AML_RESOURCE            *Descriptor;
177     AML_RESOURCE            *Rover = NULL;
178     ACPI_PARSE_OBJECT       *InitializerOp;
179     ASL_RESOURCE_NODE       *Rnode;
180     UINT16                  StringLength = 0;
181     UINT32                  OptionIndex = 0;
182     UINT32                  CurrentByteOffset;
183     UINT32                  i;
184     BOOLEAN                 HasResSourceIndex = FALSE;
185     UINT8                   ResSourceIndex = 0;
186     UINT8                   *ResSourceString = NULL;
187 
188 
189     InitializerOp = Info->DescriptorTypeOp->Asl.Child;
190     CurrentByteOffset = Info->CurrentByteOffset;
191     StringLength = RsGetStringDataLength (InitializerOp);
192 
193     /* Count the interrupt numbers */
194 
195     for (i = 0; InitializerOp; i++)
196     {
197         InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
198 
199         if (i <= 6)
200         {
201             if (i == 3 &&
202                 InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
203             {
204                 /*
205                  * ResourceSourceIndex was specified, always make room for
206                  * it, even if the ResourceSource was omitted.
207                  */
208                 OptionIndex++;
209             }
210 
211             continue;
212         }
213 
214         OptionIndex += 4;
215     }
216 
217     InitializerOp = Info->DescriptorTypeOp->Asl.Child;
218     Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_EXTENDED_IRQ) +
219         1 + OptionIndex + StringLength);
220 
221     Descriptor = Rnode->Buffer;
222     Descriptor->ExtendedIrq.DescriptorType = ACPI_RESOURCE_NAME_EXTENDED_IRQ;
223 
224     /*
225      * Initial descriptor length -- may be enlarged if there are
226      * optional fields present
227      */
228     Descriptor->ExtendedIrq.ResourceLength  = 2;  /* Flags and table length byte */
229     Descriptor->ExtendedIrq.InterruptCount  = 0;
230 
231     Rover = ACPI_CAST_PTR (AML_RESOURCE,
232         (&(Descriptor->ExtendedIrq.Interrupts[0])));
233 
234     /* Process all child initialization nodes */
235 
236     for (i = 0; InitializerOp; i++)
237     {
238         switch (i)
239         {
240         case 0: /* Resource Usage (Default: consumer (1) */
241 
242             RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 0, 1);
243             break;
244 
245         case 1: /* Interrupt Type (or Mode - edge/level) */
246 
247             RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 1, 0);
248             RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTTYPE,
249                 CurrentByteOffset + ASL_RESDESC_OFFSET (ExtendedIrq.Flags), 1);
250             break;
251 
252         case 2: /* Interrupt Level (or Polarity - Active high/low) */
253 
254             RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 2, 0);
255             RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTLEVEL,
256                 CurrentByteOffset + ASL_RESDESC_OFFSET (ExtendedIrq.Flags), 2);
257             break;
258 
259         case 3: /* Share Type - Default: exclusive (0) */
260 
261             RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 3, 0);
262             RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTSHARE,
263                 CurrentByteOffset + ASL_RESDESC_OFFSET (ExtendedIrq.Flags), 3);
264             break;
265 
266         case 4: /* ResSourceIndex [Optional Field - BYTE] */
267 
268             if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
269             {
270                 HasResSourceIndex = TRUE;
271                 ResSourceIndex = (UINT8) InitializerOp->Asl.Value.Integer;
272             }
273             break;
274 
275         case 5: /* ResSource [Optional Field - STRING] */
276 
277             if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
278                 (InitializerOp->Asl.Value.String))
279             {
280                 if (StringLength)
281                 {
282                     ResSourceString = (UINT8 *) InitializerOp->Asl.Value.String;
283                 }
284 
285                 /* ResourceSourceIndex must also be valid */
286 
287                 if (!HasResSourceIndex)
288                 {
289                     AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
290                         InitializerOp, NULL);
291                 }
292             }
293 
294 #if 0
295             /*
296              * Not a valid ResourceSource, ResourceSourceIndex must also
297              * be invalid
298              */
299             else if (HasResSourceIndex)
300             {
301                 AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
302                     InitializerOp, NULL);
303             }
304 #endif
305             break;
306 
307         case 6: /* ResourceTag */
308 
309             UtAttachNamepathToOwner (Info->DescriptorTypeOp, InitializerOp);
310             break;
311 
312         default:
313             /*
314              * Interrupt Numbers come through here, repeatedly
315              */
316 
317             /* Maximum 255 interrupts allowed for this descriptor */
318 
319             if (Descriptor->ExtendedIrq.InterruptCount == 255)
320             {
321                 AslError (ASL_ERROR, ASL_MSG_EX_INTERRUPT_LIST,
322                     InitializerOp, NULL);
323                 return (Rnode);
324             }
325 
326             /* Each interrupt number must be a 32-bit value */
327 
328             if (InitializerOp->Asl.Value.Integer > ACPI_UINT32_MAX)
329             {
330                 AslError (ASL_ERROR, ASL_MSG_EX_INTERRUPT_NUMBER,
331                     InitializerOp, NULL);
332             }
333 
334             /* Save the integer and move pointer to the next one */
335 
336             Rover->DwordItem = (UINT32) InitializerOp->Asl.Value.Integer;
337             Rover = ACPI_ADD_PTR (AML_RESOURCE, &(Rover->DwordItem), 4);
338             Descriptor->ExtendedIrq.InterruptCount++;
339             Descriptor->ExtendedIrq.ResourceLength += 4;
340 
341             /* Case 7: First interrupt number in list */
342 
343             if (i == 7)
344             {
345                 if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
346                 {
347                     /* Must be at least one interrupt */
348 
349                     AslError (ASL_ERROR, ASL_MSG_EX_INTERRUPT_LIST_MIN,
350                         InitializerOp, NULL);
351                 }
352 
353                 /* Check now for duplicates in list */
354 
355                 RsCheckListForDuplicates (InitializerOp);
356 
357                 /* Create a named field at the start of the list */
358 
359                 RsCreateDwordField (InitializerOp, ACPI_RESTAG_INTERRUPT,
360                     CurrentByteOffset +
361                     ASL_RESDESC_OFFSET (ExtendedIrq.Interrupts[0]));
362             }
363         }
364 
365         InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
366     }
367 
368 
369     /* Add optional ResSourceIndex if present */
370 
371     if (HasResSourceIndex)
372     {
373         Rover->ByteItem = ResSourceIndex;
374         Rover = ACPI_ADD_PTR (AML_RESOURCE, &(Rover->ByteItem), 1);
375         Descriptor->ExtendedIrq.ResourceLength += 1;
376     }
377 
378     /* Add optional ResSource string if present */
379 
380     if (StringLength && ResSourceString)
381     {
382 
383         strcpy ((char *) Rover, (char *) ResSourceString);
384         Rover = ACPI_ADD_PTR (
385                     AML_RESOURCE, &(Rover->ByteItem), StringLength);
386 
387         Descriptor->ExtendedIrq.ResourceLength = (UINT16)
388             (Descriptor->ExtendedIrq.ResourceLength + StringLength);
389     }
390 
391     Rnode->BufferLength =
392         (ASL_RESDESC_OFFSET (ExtendedIrq.Interrupts[0]) -
393         ASL_RESDESC_OFFSET (ExtendedIrq.DescriptorType))
394         + OptionIndex + StringLength;
395     return (Rnode);
396 }
397 
398 
399 /*******************************************************************************
400  *
401  * FUNCTION:    RsDoVendorLargeDescriptor
402  *
403  * PARAMETERS:  Info                - Parse Op and resource template offset
404  *
405  * RETURN:      Completed resource node
406  *
407  * DESCRIPTION: Construct a long "VendorLong" descriptor
408  *
409  ******************************************************************************/
410 
411 ASL_RESOURCE_NODE *
412 RsDoVendorLargeDescriptor (
413     ASL_RESOURCE_INFO       *Info)
414 {
415     AML_RESOURCE            *Descriptor;
416     ACPI_PARSE_OBJECT       *InitializerOp;
417     ASL_RESOURCE_NODE       *Rnode;
418     UINT8                   *VendorData;
419     UINT32                  i;
420 
421 
422     /* Count the number of data bytes */
423 
424     InitializerOp = Info->DescriptorTypeOp->Asl.Child;
425     InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
426 
427     for (i = 0; InitializerOp; i++)
428     {
429         if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
430         {
431             break;
432         }
433         InitializerOp = InitializerOp->Asl.Next;
434     }
435 
436     InitializerOp = Info->DescriptorTypeOp->Asl.Child;
437     InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
438     Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_VENDOR_LARGE) + i);
439 
440     Descriptor = Rnode->Buffer;
441     Descriptor->VendorLarge.DescriptorType = ACPI_RESOURCE_NAME_VENDOR_LARGE;
442     Descriptor->VendorLarge.ResourceLength = (UINT16) i;
443 
444     /* Point to end-of-descriptor for vendor data */
445 
446     VendorData = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_LARGE_HEADER);
447 
448     /* Process all child initialization nodes */
449 
450     for (i = 0; InitializerOp; i++)
451     {
452         if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
453         {
454             break;
455         }
456 
457         VendorData[i] = (UINT8) InitializerOp->Asl.Value.Integer;
458         InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
459     }
460 
461     return (Rnode);
462 }
463