1 /*******************************************************************************
3 * Module Name: rsmisc - Miscellaneous resource descriptors
5 ******************************************************************************/
8 * Copyright (C) 2000 - 2016, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
48 #define _COMPONENT ACPI_RESOURCES
49 ACPI_MODULE_NAME ("rsmisc")
52 #define INIT_RESOURCE_TYPE(i) i->ResourceOffset
53 #define INIT_RESOURCE_LENGTH(i) i->AmlOffset
54 #define INIT_TABLE_LENGTH(i) i->Value
56 #define COMPARE_OPCODE(i) i->ResourceOffset
57 #define COMPARE_TARGET(i) i->AmlOffset
58 #define COMPARE_VALUE(i) i->Value
61 /*******************************************************************************
63 * FUNCTION: AcpiRsConvertAmlToResource
65 * PARAMETERS: Resource - Pointer to the resource descriptor
66 * Aml - Where the AML descriptor is returned
67 * Info - Pointer to appropriate conversion table
71 * DESCRIPTION: Convert an external AML resource descriptor to the corresponding
72 * internal resource descriptor
74 ******************************************************************************/
77 AcpiRsConvertAmlToResource (
78 ACPI_RESOURCE *Resource,
80 ACPI_RSCONVERT_INFO *Info)
82 ACPI_RS_LENGTH AmlResourceLength;
87 UINT8 FlagsMode = FALSE;
92 ACPI_FUNCTION_TRACE (RsConvertAmlToResource);
97 return_ACPI_STATUS (AE_BAD_PARAMETER);
100 if (((ACPI_SIZE) Resource) & 0x3)
102 /* Each internal resource struct is expected to be 32-bit aligned */
104 ACPI_WARNING ((AE_INFO,
105 "Misaligned resource pointer (get): %p Type 0x%2.2X Length %u",
106 Resource, Resource->Type, Resource->Length));
109 /* Extract the resource Length field (does not include header length) */
111 AmlResourceLength = AcpiUtGetResourceLength (Aml);
114 * First table entry must be ACPI_RSC_INITxxx and must contain the
115 * table length (# of table entries)
117 Count = INIT_TABLE_LENGTH (Info);
121 * Source is the external AML byte stream buffer,
122 * destination is the internal resource descriptor
124 Source = ACPI_ADD_PTR (void, Aml, Info->AmlOffset);
125 Destination = ACPI_ADD_PTR (void, Resource, Info->ResourceOffset);
127 switch (Info->Opcode)
129 case ACPI_RSC_INITGET:
131 * Get the resource type and the initial (minimum) length
133 memset (Resource, 0, INIT_RESOURCE_LENGTH (Info));
134 Resource->Type = INIT_RESOURCE_TYPE (Info);
135 Resource->Length = INIT_RESOURCE_LENGTH (Info);
138 case ACPI_RSC_INITSET:
141 case ACPI_RSC_FLAGINIT:
146 case ACPI_RSC_1BITFLAG:
148 * Mask and shift the flag bit
150 ACPI_SET8 (Destination,
151 ((ACPI_GET8 (Source) >> Info->Value) & 0x01));
154 case ACPI_RSC_2BITFLAG:
156 * Mask and shift the flag bits
158 ACPI_SET8 (Destination,
159 ((ACPI_GET8 (Source) >> Info->Value) & 0x03));
162 case ACPI_RSC_3BITFLAG:
164 * Mask and shift the flag bits
166 ACPI_SET8 (Destination,
167 ((ACPI_GET8 (Source) >> Info->Value) & 0x07));
172 ItemCount = ACPI_GET8 (Source);
173 ACPI_SET8 (Destination, ItemCount);
175 Resource->Length = Resource->Length +
176 (Info->Value * (ItemCount - 1));
179 case ACPI_RSC_COUNT16:
181 ItemCount = AmlResourceLength;
182 ACPI_SET16 (Destination, ItemCount);
184 Resource->Length = Resource->Length +
185 (Info->Value * (ItemCount - 1));
188 case ACPI_RSC_COUNT_GPIO_PIN:
190 Target = ACPI_ADD_PTR (void, Aml, Info->Value);
191 ItemCount = ACPI_GET16 (Target) - ACPI_GET16 (Source);
193 Resource->Length = Resource->Length + ItemCount;
194 ItemCount = ItemCount / 2;
195 ACPI_SET16 (Destination, ItemCount);
198 case ACPI_RSC_COUNT_GPIO_VEN:
200 ItemCount = ACPI_GET8 (Source);
201 ACPI_SET8 (Destination, ItemCount);
203 Resource->Length = Resource->Length + (Info->Value * ItemCount);
206 case ACPI_RSC_COUNT_GPIO_RES:
208 * Vendor data is optional (length/offset may both be zero)
209 * Examine vendor data length field first
211 Target = ACPI_ADD_PTR (void, Aml, (Info->Value + 2));
212 if (ACPI_GET16 (Target))
214 /* Use vendor offset to get resource source length */
216 Target = ACPI_ADD_PTR (void, Aml, Info->Value);
217 ItemCount = ACPI_GET16 (Target) - ACPI_GET16 (Source);
221 /* No vendor data to worry about */
223 ItemCount = Aml->LargeHeader.ResourceLength +
224 sizeof (AML_RESOURCE_LARGE_HEADER) -
228 Resource->Length = Resource->Length + ItemCount;
229 ACPI_SET16 (Destination, ItemCount);
232 case ACPI_RSC_COUNT_SERIAL_VEN:
234 ItemCount = ACPI_GET16 (Source) - Info->Value;
236 Resource->Length = Resource->Length + ItemCount;
237 ACPI_SET16 (Destination, ItemCount);
240 case ACPI_RSC_COUNT_SERIAL_RES:
242 ItemCount = (AmlResourceLength +
243 sizeof (AML_RESOURCE_LARGE_HEADER)) -
244 ACPI_GET16 (Source) - Info->Value;
246 Resource->Length = Resource->Length + ItemCount;
247 ACPI_SET16 (Destination, ItemCount);
250 case ACPI_RSC_LENGTH:
252 Resource->Length = Resource->Length + Info->Value;
256 case ACPI_RSC_MOVE16:
257 case ACPI_RSC_MOVE32:
258 case ACPI_RSC_MOVE64:
260 * Raw data move. Use the Info value field unless ItemCount has
261 * been previously initialized via a COUNT opcode
265 ItemCount = Info->Value;
267 AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
270 case ACPI_RSC_MOVE_GPIO_PIN:
272 /* Generate and set the PIN data pointer */
274 Target = (char *) ACPI_ADD_PTR (void, Resource,
275 (Resource->Length - ItemCount * 2));
276 *(UINT16 **) Destination = ACPI_CAST_PTR (UINT16, Target);
278 /* Copy the PIN data */
280 Source = ACPI_ADD_PTR (void, Aml, ACPI_GET16 (Source));
281 AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode);
284 case ACPI_RSC_MOVE_GPIO_RES:
286 /* Generate and set the ResourceSource string pointer */
288 Target = (char *) ACPI_ADD_PTR (void, Resource,
289 (Resource->Length - ItemCount));
290 *(UINT8 **) Destination = ACPI_CAST_PTR (UINT8, Target);
292 /* Copy the ResourceSource string */
294 Source = ACPI_ADD_PTR (void, Aml, ACPI_GET16 (Source));
295 AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode);
298 case ACPI_RSC_MOVE_SERIAL_VEN:
300 /* Generate and set the Vendor Data pointer */
302 Target = (char *) ACPI_ADD_PTR (void, Resource,
303 (Resource->Length - ItemCount));
304 *(UINT8 **) Destination = ACPI_CAST_PTR (UINT8, Target);
306 /* Copy the Vendor Data */
308 Source = ACPI_ADD_PTR (void, Aml, Info->Value);
309 AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode);
312 case ACPI_RSC_MOVE_SERIAL_RES:
314 /* Generate and set the ResourceSource string pointer */
316 Target = (char *) ACPI_ADD_PTR (void, Resource,
317 (Resource->Length - ItemCount));
318 *(UINT8 **) Destination = ACPI_CAST_PTR (UINT8, Target);
320 /* Copy the ResourceSource string */
322 Source = ACPI_ADD_PTR (
323 void, Aml, (ACPI_GET16 (Source) + Info->Value));
324 AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode);
329 memset (Destination, Info->AmlOffset, Info->Value);
334 Target = ACPI_ADD_PTR (char, Resource, Info->Value);
335 memcpy (Destination, Source, ACPI_GET16 (Target));
338 case ACPI_RSC_ADDRESS:
340 * Common handler for address descriptor flags
342 if (!AcpiRsGetAddressCommon (Resource, Aml))
344 return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
348 case ACPI_RSC_SOURCE:
350 * Optional ResourceSource (Index and String)
353 AcpiRsGetResourceSource (AmlResourceLength, Info->Value,
354 Destination, Aml, NULL);
357 case ACPI_RSC_SOURCEX:
359 * Optional ResourceSource (Index and String). This is the more
360 * complicated case used by the Interrupt() macro
362 Target = ACPI_ADD_PTR (char, Resource,
363 Info->AmlOffset + (ItemCount * 4));
366 AcpiRsGetResourceSource (AmlResourceLength, (ACPI_RS_LENGTH)
367 (((ItemCount - 1) * sizeof (UINT32)) + Info->Value),
368 Destination, Aml, Target);
371 case ACPI_RSC_BITMASK:
373 * 8-bit encoded bitmask (DMA macro)
375 ItemCount = AcpiRsDecodeBitmask (ACPI_GET8 (Source), Destination);
378 Resource->Length += (ItemCount - 1);
381 Target = ACPI_ADD_PTR (char, Resource, Info->Value);
382 ACPI_SET8 (Target, ItemCount);
385 case ACPI_RSC_BITMASK16:
387 * 16-bit encoded bitmask (IRQ macro)
389 ACPI_MOVE_16_TO_16 (&Temp16, Source);
391 ItemCount = AcpiRsDecodeBitmask (Temp16, Destination);
394 Resource->Length += (ItemCount - 1);
397 Target = ACPI_ADD_PTR (char, Resource, Info->Value);
398 ACPI_SET8 (Target, ItemCount);
401 case ACPI_RSC_EXIT_NE:
403 * Control - Exit conversion if not equal
405 switch (Info->ResourceOffset)
407 case ACPI_RSC_COMPARE_AML_LENGTH:
409 if (AmlResourceLength != Info->Value)
415 case ACPI_RSC_COMPARE_VALUE:
417 if (ACPI_GET8 (Source) != Info->Value)
425 ACPI_ERROR ((AE_INFO, "Invalid conversion sub-opcode"));
426 return_ACPI_STATUS (AE_BAD_PARAMETER);
432 ACPI_ERROR ((AE_INFO, "Invalid conversion opcode"));
433 return_ACPI_STATUS (AE_BAD_PARAMETER);
443 /* Round the resource struct length up to the next boundary (32 or 64) */
445 Resource->Length = (UINT32)
446 ACPI_ROUND_UP_TO_NATIVE_WORD (Resource->Length);
448 return_ACPI_STATUS (AE_OK);
452 /*******************************************************************************
454 * FUNCTION: AcpiRsConvertResourceToAml
456 * PARAMETERS: Resource - Pointer to the resource descriptor
457 * Aml - Where the AML descriptor is returned
458 * Info - Pointer to appropriate conversion table
462 * DESCRIPTION: Convert an internal resource descriptor to the corresponding
463 * external AML resource descriptor.
465 ******************************************************************************/
468 AcpiRsConvertResourceToAml (
469 ACPI_RESOURCE *Resource,
471 ACPI_RSCONVERT_INFO *Info)
476 ACPI_RSDESC_SIZE AmlLength = 0;
479 UINT16 ItemCount = 0;
482 ACPI_FUNCTION_TRACE (RsConvertResourceToAml);
487 return_ACPI_STATUS (AE_BAD_PARAMETER);
491 * First table entry must be ACPI_RSC_INITxxx and must contain the
492 * table length (# of table entries)
494 Count = INIT_TABLE_LENGTH (Info);
499 * Source is the internal resource descriptor,
500 * destination is the external AML byte stream buffer
502 Source = ACPI_ADD_PTR (void, Resource, Info->ResourceOffset);
503 Destination = ACPI_ADD_PTR (void, Aml, Info->AmlOffset);
505 switch (Info->Opcode)
507 case ACPI_RSC_INITSET:
509 memset (Aml, 0, INIT_RESOURCE_LENGTH (Info));
510 AmlLength = INIT_RESOURCE_LENGTH (Info);
511 AcpiRsSetResourceHeader (
512 INIT_RESOURCE_TYPE (Info), AmlLength, Aml);
515 case ACPI_RSC_INITGET:
518 case ACPI_RSC_FLAGINIT:
520 * Clear the flag byte
522 ACPI_SET8 (Destination, 0);
525 case ACPI_RSC_1BITFLAG:
527 * Mask and shift the flag bit
529 ACPI_SET_BIT (*ACPI_CAST8 (Destination), (UINT8)
530 ((ACPI_GET8 (Source) & 0x01) << Info->Value));
533 case ACPI_RSC_2BITFLAG:
535 * Mask and shift the flag bits
537 ACPI_SET_BIT (*ACPI_CAST8 (Destination), (UINT8)
538 ((ACPI_GET8 (Source) & 0x03) << Info->Value));
541 case ACPI_RSC_3BITFLAG:
543 * Mask and shift the flag bits
545 ACPI_SET_BIT (*ACPI_CAST8 (Destination), (UINT8)
546 ((ACPI_GET8 (Source) & 0x07) << Info->Value));
551 ItemCount = ACPI_GET8 (Source);
552 ACPI_SET8 (Destination, ItemCount);
555 (AmlLength + (Info->Value * (ItemCount - 1)));
558 case ACPI_RSC_COUNT16:
560 ItemCount = ACPI_GET16 (Source);
561 AmlLength = (UINT16) (AmlLength + ItemCount);
562 AcpiRsSetResourceLength (AmlLength, Aml);
565 case ACPI_RSC_COUNT_GPIO_PIN:
567 ItemCount = ACPI_GET16 (Source);
568 ACPI_SET16 (Destination, AmlLength);
570 AmlLength = (UINT16) (AmlLength + ItemCount * 2);
571 Target = ACPI_ADD_PTR (void, Aml, Info->Value);
572 ACPI_SET16 (Target, AmlLength);
573 AcpiRsSetResourceLength (AmlLength, Aml);
576 case ACPI_RSC_COUNT_GPIO_VEN:
578 ItemCount = ACPI_GET16 (Source);
579 ACPI_SET16 (Destination, ItemCount);
581 AmlLength = (UINT16) (
582 AmlLength + (Info->Value * ItemCount));
583 AcpiRsSetResourceLength (AmlLength, Aml);
586 case ACPI_RSC_COUNT_GPIO_RES:
588 /* Set resource source string length */
590 ItemCount = ACPI_GET16 (Source);
591 ACPI_SET16 (Destination, AmlLength);
593 /* Compute offset for the Vendor Data */
595 AmlLength = (UINT16) (AmlLength + ItemCount);
596 Target = ACPI_ADD_PTR (void, Aml, Info->Value);
598 /* Set vendor offset only if there is vendor data */
600 if (Resource->Data.Gpio.VendorLength)
602 ACPI_SET16 (Target, AmlLength);
605 AcpiRsSetResourceLength (AmlLength, Aml);
608 case ACPI_RSC_COUNT_SERIAL_VEN:
610 ItemCount = ACPI_GET16 (Source);
611 ACPI_SET16 (Destination, ItemCount + Info->Value);
612 AmlLength = (UINT16) (AmlLength + ItemCount);
613 AcpiRsSetResourceLength (AmlLength, Aml);
616 case ACPI_RSC_COUNT_SERIAL_RES:
618 ItemCount = ACPI_GET16 (Source);
619 AmlLength = (UINT16) (AmlLength + ItemCount);
620 AcpiRsSetResourceLength (AmlLength, Aml);
623 case ACPI_RSC_LENGTH:
625 AcpiRsSetResourceLength (Info->Value, Aml);
629 case ACPI_RSC_MOVE16:
630 case ACPI_RSC_MOVE32:
631 case ACPI_RSC_MOVE64:
635 ItemCount = Info->Value;
637 AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
640 case ACPI_RSC_MOVE_GPIO_PIN:
642 Destination = (char *) ACPI_ADD_PTR (void, Aml,
643 ACPI_GET16 (Destination));
644 Source = * (UINT16 **) Source;
645 AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
648 case ACPI_RSC_MOVE_GPIO_RES:
650 /* Used for both ResourceSource string and VendorData */
652 Destination = (char *) ACPI_ADD_PTR (void, Aml,
653 ACPI_GET16 (Destination));
654 Source = * (UINT8 **) Source;
655 AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
658 case ACPI_RSC_MOVE_SERIAL_VEN:
660 Destination = (char *) ACPI_ADD_PTR (void, Aml,
661 (AmlLength - ItemCount));
662 Source = * (UINT8 **) Source;
663 AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
666 case ACPI_RSC_MOVE_SERIAL_RES:
668 Destination = (char *) ACPI_ADD_PTR (void, Aml,
669 (AmlLength - ItemCount));
670 Source = * (UINT8 **) Source;
671 AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
674 case ACPI_RSC_ADDRESS:
676 /* Set the Resource Type, General Flags, and Type-Specific Flags */
678 AcpiRsSetAddressCommon (Aml, Resource);
681 case ACPI_RSC_SOURCEX:
683 * Optional ResourceSource (Index and String)
685 AmlLength = AcpiRsSetResourceSource (
686 Aml, (ACPI_RS_LENGTH) AmlLength, Source);
687 AcpiRsSetResourceLength (AmlLength, Aml);
690 case ACPI_RSC_SOURCE:
692 * Optional ResourceSource (Index and String). This is the more
693 * complicated case used by the Interrupt() macro
695 AmlLength = AcpiRsSetResourceSource (Aml, Info->Value, Source);
696 AcpiRsSetResourceLength (AmlLength, Aml);
699 case ACPI_RSC_BITMASK:
701 * 8-bit encoded bitmask (DMA macro)
703 ACPI_SET8 (Destination,
704 AcpiRsEncodeBitmask (Source,
705 *ACPI_ADD_PTR (UINT8, Resource, Info->Value)));
708 case ACPI_RSC_BITMASK16:
710 * 16-bit encoded bitmask (IRQ macro)
712 Temp16 = AcpiRsEncodeBitmask (
713 Source, *ACPI_ADD_PTR (UINT8, Resource, Info->Value));
714 ACPI_MOVE_16_TO_16 (Destination, &Temp16);
717 case ACPI_RSC_EXIT_LE:
719 * Control - Exit conversion if less than or equal
721 if (ItemCount <= Info->Value)
727 case ACPI_RSC_EXIT_NE:
729 * Control - Exit conversion if not equal
731 switch (COMPARE_OPCODE (Info))
733 case ACPI_RSC_COMPARE_VALUE:
735 if (*ACPI_ADD_PTR (UINT8, Resource,
736 COMPARE_TARGET (Info)) != COMPARE_VALUE (Info))
744 ACPI_ERROR ((AE_INFO, "Invalid conversion sub-opcode"));
745 return_ACPI_STATUS (AE_BAD_PARAMETER);
749 case ACPI_RSC_EXIT_EQ:
751 * Control - Exit conversion if equal
753 if (*ACPI_ADD_PTR (UINT8, Resource,
754 COMPARE_TARGET (Info)) == COMPARE_VALUE (Info))
762 ACPI_ERROR ((AE_INFO, "Invalid conversion opcode"));
763 return_ACPI_STATUS (AE_BAD_PARAMETER);
771 return_ACPI_STATUS (AE_OK);
776 /* Previous resource validations */
778 if (Aml->ExtAddress64.RevisionID !=
779 AML_RESOURCE_EXTENDED_ADDRESS_REVISION)
781 return_ACPI_STATUS (AE_SUPPORT);
784 if (Resource->Data.StartDpf.PerformanceRobustness >= 3)
786 return_ACPI_STATUS (AE_AML_BAD_RESOURCE_VALUE);
789 if (((Aml->Irq.Flags & 0x09) == 0x00) ||
790 ((Aml->Irq.Flags & 0x09) == 0x09))
793 * Only [ActiveHigh, EdgeSensitive] or [ActiveLow, LevelSensitive]
794 * polarity/trigger interrupts are allowed (ACPI spec, section
795 * "IRQ Format"), so 0x00 and 0x09 are illegal.
797 ACPI_ERROR ((AE_INFO,
798 "Invalid interrupt polarity/trigger in resource list, 0x%X",
800 return_ACPI_STATUS (AE_BAD_DATA);
803 Resource->Data.ExtendedIrq.InterruptCount = Temp8;
806 /* Must have at least one IRQ */
808 return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
811 if (Resource->Data.Dma.Transfer == 0x03)
813 ACPI_ERROR ((AE_INFO,
814 "Invalid DMA.Transfer preference (3)"));
815 return_ACPI_STATUS (AE_BAD_DATA);