aslresource.c revision 1.1.1.18 1 /******************************************************************************
2 *
3 * Module Name: aslresource - Resource template/descriptor utilities
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2023, 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 MERCHANTABILITY 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
49 #define _COMPONENT ACPI_COMPILER
50 ACPI_MODULE_NAME ("aslresource")
51
52
53 /*******************************************************************************
54 *
55 * FUNCTION: RsSmallAddressCheck
56 *
57 * PARAMETERS: Minimum - Address Min value
58 * Maximum - Address Max value
59 * Length - Address range value
60 * Alignment - Address alignment value
61 * MinOp - Original Op for Address Min
62 * MaxOp - Original Op for Address Max
63 * LengthOp - Original Op for address range
64 * AlignOp - Original Op for address alignment. If
65 * NULL, means "zero value for alignment is
66 * OK, and means 64K alignment" (for
67 * Memory24 descriptor)
68 * Op - Parent Op for entire construct
69 *
70 * RETURN: None. Adds error messages to error log if necessary
71 *
72 * DESCRIPTION: Perform common value checks for "small" address descriptors.
73 * Currently:
74 * Io, Memory24, Memory32
75 *
76 ******************************************************************************/
77
78 void
79 RsSmallAddressCheck (
80 UINT8 Type,
81 UINT32 Minimum,
82 UINT32 Maximum,
83 UINT32 Length,
84 UINT32 Alignment,
85 ACPI_PARSE_OBJECT *MinOp,
86 ACPI_PARSE_OBJECT *MaxOp,
87 ACPI_PARSE_OBJECT *LengthOp,
88 ACPI_PARSE_OBJECT *AlignOp,
89 ACPI_PARSE_OBJECT *Op)
90 {
91
92 if (AslGbl_NoResourceChecking)
93 {
94 return;
95 }
96
97 /*
98 * Check for a so-called "null descriptor". These are descriptors that are
99 * created with most fields set to zero. The intent is that the descriptor
100 * will be updated/completed at runtime via a BufferField.
101 *
102 * If the descriptor does NOT have a resource tag, it cannot be referenced
103 * by a BufferField and we will flag this as an error. Conversely, if
104 * the descriptor has a resource tag, we will assume that a BufferField
105 * will be used to dynamically update it, so no error.
106 *
107 * A possible enhancement to this check would be to verify that in fact
108 * a BufferField is created using the resource tag, and perhaps even
109 * verify that a Store is performed to the BufferField.
110 *
111 * Note: for these descriptors, Alignment is allowed to be zero
112 */
113 if (!Minimum && !Maximum && !Length)
114 {
115 if (!Op->Asl.ExternalName)
116 {
117 /* No resource tag. Descriptor is fixed and is also illegal */
118
119 AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL);
120 }
121
122 return;
123 }
124
125 /*
126 * Range checks for Memory24 and Memory32.
127 * IO descriptor has different definition of min/max, don't check.
128 */
129 if (Type != ACPI_RESOURCE_NAME_IO)
130 {
131 /* Basic checks on Min/Max/Length */
132
133 if (Minimum > Maximum)
134 {
135 AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL);
136 }
137 else if (Length > (Maximum - Minimum + 1))
138 {
139 AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL);
140 }
141
142 /* Special case for Memory24, min/max values are compressed */
143
144 if (Type == ACPI_RESOURCE_NAME_MEMORY24)
145 {
146 if (!Alignment) /* Alignment==0 means 64K alignment */
147 {
148 Alignment = ACPI_UINT16_MAX + 1;
149 }
150
151 Minimum <<= 8;
152 Maximum <<= 8;
153 }
154 }
155
156 /* Alignment of zero is not in ACPI spec, but is used to mean byte acc */
157
158 if (!Alignment)
159 {
160 Alignment = 1;
161 }
162
163 /* Addresses must be an exact multiple of the alignment value */
164
165 if (Minimum % Alignment)
166 {
167 AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL);
168 }
169 if (Maximum % Alignment)
170 {
171 AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, NULL);
172 }
173 }
174
175
176 /*******************************************************************************
177 *
178 * FUNCTION: RsLargeAddressCheck
179 *
180 * PARAMETERS: Minimum - Address Min value
181 * Maximum - Address Max value
182 * Length - Address range value
183 * Granularity - Address granularity value
184 * Flags - General flags for address descriptors:
185 * _MIF, _MAF, _DEC
186 * MinOp - Original Op for Address Min
187 * MaxOp - Original Op for Address Max
188 * LengthOp - Original Op for address range
189 * GranOp - Original Op for address granularity
190 * Op - Parent Op for entire construct
191 *
192 * RETURN: None. Adds error messages to error log if necessary
193 *
194 * DESCRIPTION: Perform common value checks for "large" address descriptors.
195 * Currently:
196 * WordIo, WordBusNumber, WordSpace
197 * DWordIo, DWordMemory, DWordSpace
198 * QWordIo, QWordMemory, QWordSpace
199 * ExtendedIo, ExtendedMemory, ExtendedSpace
200 *
201 * _MIF flag set means that the minimum address is fixed and is not relocatable
202 * _MAF flag set means that the maximum address is fixed and is not relocatable
203 * Length of zero means that the record size is variable
204 *
205 * This function implements the LEN/MIF/MAF/MIN/MAX/GRA rules within Table 6-40
206 * of the ACPI 4.0a specification. Added 04/2010.
207 *
208 ******************************************************************************/
209
210 void
211 RsLargeAddressCheck (
212 UINT64 Minimum,
213 UINT64 Maximum,
214 UINT64 Length,
215 UINT64 Granularity,
216 UINT8 Flags,
217 ACPI_PARSE_OBJECT *MinOp,
218 ACPI_PARSE_OBJECT *MaxOp,
219 ACPI_PARSE_OBJECT *LengthOp,
220 ACPI_PARSE_OBJECT *GranOp,
221 ACPI_PARSE_OBJECT *Op)
222 {
223
224 if (AslGbl_NoResourceChecking)
225 {
226 return;
227 }
228
229 /*
230 * Check for a so-called "null descriptor". These are descriptors that are
231 * created with most fields set to zero. The intent is that the descriptor
232 * will be updated/completed at runtime via a BufferField.
233 *
234 * If the descriptor does NOT have a resource tag, it cannot be referenced
235 * by a BufferField and we will flag this as an error. Conversely, if
236 * the descriptor has a resource tag, we will assume that a BufferField
237 * will be used to dynamically update it, so no error.
238 *
239 * A possible enhancement to this check would be to verify that in fact
240 * a BufferField is created using the resource tag, and perhaps even
241 * verify that a Store is performed to the BufferField.
242 */
243 if (!Minimum && !Maximum && !Length && !Granularity)
244 {
245 if (!Op->Asl.ExternalName)
246 {
247 /* No resource tag. Descriptor is fixed and is also illegal */
248
249 AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL);
250 }
251
252 return;
253 }
254
255 /* Basic checks on Min/Max/Length */
256
257 if (Minimum > Maximum)
258 {
259 AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL);
260 return;
261 }
262 else if (Length > (Maximum - Minimum + 1))
263 {
264 AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL);
265 return;
266 }
267
268 /* If specified (non-zero), ensure granularity is a power-of-two minus one */
269
270 if (Granularity)
271 {
272 if ((Granularity + 1) &
273 Granularity)
274 {
275 AslError (ASL_ERROR, ASL_MSG_INVALID_GRANULARITY, GranOp, NULL);
276 return;
277 }
278 }
279
280 /*
281 * Check the various combinations of Length, MinFixed, and MaxFixed
282 */
283 if (Length)
284 {
285 /* Fixed non-zero length */
286
287 switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF))
288 {
289 case 0:
290 /*
291 * Fixed length, variable locations (both _MIN and _MAX).
292 * Length must be a multiple of granularity
293 */
294 if (Granularity & Length)
295 {
296 AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, LengthOp, NULL);
297 }
298 break;
299
300 case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF):
301
302 /* Fixed length, fixed location. Granularity must be zero */
303
304 if (Granularity != 0)
305 {
306 AslError (ASL_ERROR, ASL_MSG_INVALID_GRAN_FIXED, GranOp, NULL);
307 }
308
309 /* Length must be exactly the size of the min/max window */
310
311 if (Length != (Maximum - Minimum + 1))
312 {
313 AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH_FIXED, LengthOp, NULL);
314 }
315 break;
316
317 /* All other combinations are invalid */
318
319 case ACPI_RESOURCE_FLAG_MIF:
320 case ACPI_RESOURCE_FLAG_MAF:
321 default:
322
323 AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL);
324 }
325 }
326 else
327 {
328 /* Variable length (length==0) */
329
330 switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF))
331 {
332 case 0:
333 /*
334 * Both _MIN and _MAX are variable.
335 * No additional requirements, just exit
336 */
337 break;
338
339 case ACPI_RESOURCE_FLAG_MIF:
340
341 /* _MIN is fixed. _MIN must be multiple of _GRA */
342
343 /*
344 * The granularity is defined by the ACPI specification to be a
345 * power-of-two minus one, therefore the granularity is a
346 * bitmask which can be used to easily validate the addresses.
347 */
348 if (Granularity & Minimum)
349 {
350 AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL);
351 }
352 break;
353
354 case ACPI_RESOURCE_FLAG_MAF:
355
356 /* _MAX is fixed. (_MAX + 1) must be multiple of _GRA */
357
358 if (Granularity & (Maximum + 1))
359 {
360 AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, "-1");
361 }
362 break;
363
364 /* Both MIF/MAF set is invalid if length is zero */
365
366 case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF):
367 default:
368
369 AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL);
370 }
371 }
372 }
373
374
375 /*******************************************************************************
376 *
377 * FUNCTION: RsGetStringDataLength
378 *
379 * PARAMETERS: InitializerOp - Start of a subtree of init nodes
380 *
381 * RETURN: Valid string length if a string node is found (otherwise 0)
382 *
383 * DESCRIPTION: In a list of peer nodes, find the first one that contains a
384 * string and return the length of the string.
385 *
386 ******************************************************************************/
387
388 UINT16
389 RsGetStringDataLength (
390 ACPI_PARSE_OBJECT *InitializerOp)
391 {
392
393 while (InitializerOp)
394 {
395 if (InitializerOp->Asl.ParseOpcode == PARSEOP_STRING_LITERAL)
396 {
397 return ((UINT16) (strlen (InitializerOp->Asl.Value.String) + 1));
398 }
399
400 InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
401 }
402
403 return (0);
404 }
405
406
407 /*******************************************************************************
408 *
409 * FUNCTION: RsAllocateResourceNode
410 *
411 * PARAMETERS: Size - Size of node in bytes
412 *
413 * RETURN: The allocated node - aborts on allocation failure
414 *
415 * DESCRIPTION: Allocate a resource description node and the resource
416 * descriptor itself (the nodes are used to link descriptors).
417 *
418 ******************************************************************************/
419
420 ASL_RESOURCE_NODE *
421 RsAllocateResourceNode (
422 UINT32 Size)
423 {
424 ASL_RESOURCE_NODE *Rnode;
425
426
427 /* Allocate the node */
428
429 Rnode = UtLocalCalloc (sizeof (ASL_RESOURCE_NODE));
430
431 /* Allocate the resource descriptor itself */
432
433 Rnode->Buffer = UtLocalCalloc (Size);
434 Rnode->BufferLength = Size;
435 return (Rnode);
436 }
437
438
439 /*******************************************************************************
440 *
441 * FUNCTION: RsCreateResourceField
442 *
443 * PARAMETERS: Op - Resource field node
444 * Name - Name of the field (Used only to reference
445 * the field in the ASL, not in the AML)
446 * ByteOffset - Offset from the field start
447 * BitOffset - Additional bit offset
448 * BitLength - Number of bits in the field
449 *
450 * RETURN: None, sets fields within the input node
451 *
452 * DESCRIPTION: Utility function to generate a named bit field within a
453 * resource descriptor. Mark a node as 1) a field in a resource
454 * descriptor, and 2) set the value to be a BIT offset
455 *
456 ******************************************************************************/
457
458 void
459 RsCreateResourceField (
460 ACPI_PARSE_OBJECT *Op,
461 char *Name,
462 UINT32 ByteOffset,
463 UINT32 BitOffset,
464 UINT32 BitLength)
465 {
466
467 Op->Asl.ExternalName = Name;
468 Op->Asl.CompileFlags |= OP_IS_RESOURCE_FIELD;
469
470 Op->Asl.Value.Tag.BitOffset = (ByteOffset * 8) + BitOffset;
471 Op->Asl.Value.Tag.BitLength = BitLength;
472 }
473
474
475 /*******************************************************************************
476 *
477 * FUNCTION: RsSetFlagBits
478 *
479 * PARAMETERS: *Flags - Pointer to the flag byte
480 * Op - Flag initialization node
481 * Position - Bit position within the flag byte
482 * Default - Used if the node is DEFAULT.
483 *
484 * RETURN: Sets bits within the *Flags output byte.
485 *
486 * DESCRIPTION: Set a bit in a cumulative flags word from an initialization
487 * node. Will use a default value if the node is DEFAULT, meaning
488 * that no value was specified in the ASL. Used to merge multiple
489 * keywords into a single flags byte.
490 *
491 ******************************************************************************/
492
493 void
494 RsSetFlagBits (
495 UINT8 *Flags,
496 ACPI_PARSE_OBJECT *Op,
497 UINT8 Position,
498 UINT8 DefaultBit)
499 {
500
501 if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
502 {
503 /* Use the default bit */
504
505 *Flags |= (DefaultBit << Position);
506 }
507 else
508 {
509 /* Use the bit specified in the initialization node */
510
511 *Flags |= (((UINT8) Op->Asl.Value.Integer) << Position);
512 }
513 }
514
515
516 void
517 RsSetFlagBits16 (
518 UINT16 *Flags,
519 ACPI_PARSE_OBJECT *Op,
520 UINT8 Position,
521 UINT8 DefaultBit)
522 {
523
524 if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
525 {
526 /* Use the default bit */
527
528 *Flags |= (DefaultBit << Position);
529 }
530 else
531 {
532 /* Use the bit specified in the initialization node */
533
534 *Flags |= (((UINT16) Op->Asl.Value.Integer) << Position);
535 }
536 }
537
538
539 /*******************************************************************************
540 *
541 * FUNCTION: RsCompleteNodeAndGetNext
542 *
543 * PARAMETERS: Op - Resource node to be completed
544 *
545 * RETURN: The next peer to the input node.
546 *
547 * DESCRIPTION: Mark the current node completed and return the next peer.
548 * The node ParseOpcode is set to DEFAULT_ARG, meaning that
549 * this node is to be ignored from now on.
550 *
551 ******************************************************************************/
552
553 ACPI_PARSE_OBJECT *
554 RsCompleteNodeAndGetNext (
555 ACPI_PARSE_OBJECT *Op)
556 {
557
558 /* Mark this node unused */
559
560 Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
561
562 /* Move on to the next peer node in the initializer list */
563
564 return (ASL_GET_PEER_NODE (Op));
565 }
566
567
568 /*******************************************************************************
569 *
570 * FUNCTION: RsCheckListForDuplicates
571 *
572 * PARAMETERS: Op - First op in the initializer list
573 *
574 * RETURN: None
575 *
576 * DESCRIPTION: Check an initializer list for duplicate values. Emits an error
577 * if any duplicates are found.
578 *
579 ******************************************************************************/
580
581 void
582 RsCheckListForDuplicates (
583 ACPI_PARSE_OBJECT *Op)
584 {
585 ACPI_PARSE_OBJECT *NextValueOp = Op;
586 ACPI_PARSE_OBJECT *NextOp;
587 UINT32 Value;
588
589
590 if (!Op)
591 {
592 return;
593 }
594
595 /* Search list once for each value in the list */
596
597 while (NextValueOp)
598 {
599 Value = (UINT32) NextValueOp->Asl.Value.Integer;
600
601 /* Compare this value to all remaining values in the list */
602
603 NextOp = ASL_GET_PEER_NODE (NextValueOp);
604 while (NextOp)
605 {
606 if (NextOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
607 {
608 /* Compare values */
609
610 if (Value == (UINT32) NextOp->Asl.Value.Integer)
611 {
612 /* Emit error only once per duplicate node */
613
614 if (!(NextOp->Asl.CompileFlags & OP_IS_DUPLICATE))
615 {
616 NextOp->Asl.CompileFlags |= OP_IS_DUPLICATE;
617 AslError (ASL_ERROR, ASL_MSG_DUPLICATE_ITEM,
618 NextOp, NULL);
619 }
620 }
621 }
622
623 NextOp = ASL_GET_PEER_NODE (NextOp);
624 }
625
626 NextValueOp = ASL_GET_PEER_NODE (NextValueOp);
627 }
628 }
629
630
631 /*******************************************************************************
632 *
633 * FUNCTION: RsDoOneResourceDescriptor
634 *
635 * PARAMETERS: DescriptorTypeOp - Parent parse node of the descriptor
636 * CurrentByteOffset - Offset in the resource descriptor
637 * buffer.
638 *
639 * RETURN: A valid resource node for the descriptor
640 *
641 * DESCRIPTION: Dispatches the processing of one resource descriptor
642 *
643 ******************************************************************************/
644
645 ASL_RESOURCE_NODE *
646 RsDoOneResourceDescriptor (
647 ASL_RESOURCE_INFO *Info,
648 UINT8 *State)
649 {
650 ASL_RESOURCE_NODE *Rnode = NULL;
651
652
653 /* Construct the resource */
654
655 switch (Info->DescriptorTypeOp->Asl.ParseOpcode)
656 {
657
658 case PARSEOP_CLOCKINPUT:
659
660 Rnode = RsDoClockInputDescriptor(Info);
661 break;
662
663 case PARSEOP_DMA:
664
665 Rnode = RsDoDmaDescriptor (Info);
666 break;
667
668 case PARSEOP_FIXEDDMA:
669
670 Rnode = RsDoFixedDmaDescriptor (Info);
671 break;
672
673 case PARSEOP_DWORDIO:
674
675 Rnode = RsDoDwordIoDescriptor (Info);
676 break;
677
678 case PARSEOP_DWORDMEMORY:
679
680 Rnode = RsDoDwordMemoryDescriptor (Info);
681 break;
682
683 case PARSEOP_DWORDPCC:
684
685 Rnode = RsDoDwordPccDescriptor (Info);
686 break;
687
688 case PARSEOP_DWORDSPACE:
689
690 Rnode = RsDoDwordSpaceDescriptor (Info);
691 break;
692
693 case PARSEOP_ENDDEPENDENTFN:
694
695 switch (*State)
696 {
697 case ACPI_RSTATE_NORMAL:
698
699 AslError (ASL_ERROR, ASL_MSG_MISSING_STARTDEPENDENT,
700 Info->DescriptorTypeOp, NULL);
701 break;
702
703 case ACPI_RSTATE_START_DEPENDENT:
704
705 AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
706 Info->DescriptorTypeOp, NULL);
707 break;
708
709 case ACPI_RSTATE_DEPENDENT_LIST:
710 default:
711
712 break;
713 }
714
715 *State = ACPI_RSTATE_NORMAL;
716 Rnode = RsDoEndDependentDescriptor (Info);
717 break;
718
719 case PARSEOP_ENDTAG:
720
721 Rnode = RsDoEndTagDescriptor (Info);
722 break;
723
724 case PARSEOP_EXTENDEDIO:
725
726 Rnode = RsDoExtendedIoDescriptor (Info);
727 break;
728
729 case PARSEOP_EXTENDEDMEMORY:
730
731 Rnode = RsDoExtendedMemoryDescriptor (Info);
732 break;
733
734 case PARSEOP_EXTENDEDSPACE:
735
736 Rnode = RsDoExtendedSpaceDescriptor (Info);
737 break;
738
739 case PARSEOP_FIXEDIO:
740
741 Rnode = RsDoFixedIoDescriptor (Info);
742 break;
743
744 case PARSEOP_INTERRUPT:
745
746 Rnode = RsDoInterruptDescriptor (Info);
747 break;
748
749 case PARSEOP_IO:
750
751 Rnode = RsDoIoDescriptor (Info);
752 break;
753
754 case PARSEOP_IRQ:
755
756 Rnode = RsDoIrqDescriptor (Info);
757 break;
758
759 case PARSEOP_IRQNOFLAGS:
760
761 Rnode = RsDoIrqNoFlagsDescriptor (Info);
762 break;
763
764 case PARSEOP_MEMORY24:
765
766 Rnode = RsDoMemory24Descriptor (Info);
767 break;
768
769 case PARSEOP_MEMORY32:
770
771 Rnode = RsDoMemory32Descriptor (Info);
772 break;
773
774 case PARSEOP_MEMORY32FIXED:
775
776 Rnode = RsDoMemory32FixedDescriptor (Info);
777 break;
778
779 case PARSEOP_QWORDIO:
780
781 Rnode = RsDoQwordIoDescriptor (Info);
782 break;
783
784 case PARSEOP_QWORDMEMORY:
785
786 Rnode = RsDoQwordMemoryDescriptor (Info);
787 break;
788
789 case PARSEOP_QWORDPCC:
790
791 Rnode = RsDoQwordPccDescriptor (Info);
792 break;
793
794 case PARSEOP_QWORDSPACE:
795
796 Rnode = RsDoQwordSpaceDescriptor (Info);
797 break;
798
799 case PARSEOP_REGISTER:
800
801 Rnode = RsDoGeneralRegisterDescriptor (Info);
802 break;
803
804 case PARSEOP_STARTDEPENDENTFN:
805
806 switch (*State)
807 {
808 case ACPI_RSTATE_START_DEPENDENT:
809
810 AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
811 Info->DescriptorTypeOp, NULL);
812 break;
813
814 case ACPI_RSTATE_NORMAL:
815 case ACPI_RSTATE_DEPENDENT_LIST:
816 default:
817
818 break;
819 }
820
821 *State = ACPI_RSTATE_START_DEPENDENT;
822 Rnode = RsDoStartDependentDescriptor (Info);
823 *State = ACPI_RSTATE_DEPENDENT_LIST;
824 break;
825
826 case PARSEOP_STARTDEPENDENTFN_NOPRI:
827
828 switch (*State)
829 {
830 case ACPI_RSTATE_START_DEPENDENT:
831
832 AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
833 Info->DescriptorTypeOp, NULL);
834 break;
835
836 case ACPI_RSTATE_NORMAL:
837 case ACPI_RSTATE_DEPENDENT_LIST:
838 default:
839
840 break;
841 }
842
843 *State = ACPI_RSTATE_START_DEPENDENT;
844 Rnode = RsDoStartDependentNoPriDescriptor (Info);
845 *State = ACPI_RSTATE_DEPENDENT_LIST;
846 break;
847
848 case PARSEOP_VENDORLONG:
849
850 Rnode = RsDoVendorLargeDescriptor (Info);
851 break;
852
853 case PARSEOP_VENDORSHORT:
854
855 Rnode = RsDoVendorSmallDescriptor (Info);
856 break;
857
858 case PARSEOP_WORDBUSNUMBER:
859
860 Rnode = RsDoWordBusNumberDescriptor (Info);
861 break;
862
863 case PARSEOP_WORDIO:
864
865 Rnode = RsDoWordIoDescriptor (Info);
866 break;
867
868 case PARSEOP_WORDPCC:
869
870 Rnode = RsDoWordPccDescriptor (Info);
871 break;
872
873 case PARSEOP_WORDSPACE:
874
875 Rnode = RsDoWordSpaceDescriptor (Info);
876 break;
877
878 case PARSEOP_GPIO_INT:
879
880 Rnode = RsDoGpioIntDescriptor (Info);
881 break;
882
883 case PARSEOP_GPIO_IO:
884
885 Rnode = RsDoGpioIoDescriptor (Info);
886 break;
887
888 case PARSEOP_I2C_SERIALBUS:
889 case PARSEOP_I2C_SERIALBUS_V2:
890
891 Rnode = RsDoI2cSerialBusDescriptor (Info);
892 break;
893
894 case PARSEOP_SPI_SERIALBUS:
895 case PARSEOP_SPI_SERIALBUS_V2:
896
897 Rnode = RsDoSpiSerialBusDescriptor (Info);
898 break;
899
900 case PARSEOP_UART_SERIALBUS:
901 case PARSEOP_UART_SERIALBUS_V2:
902
903 Rnode = RsDoUartSerialBusDescriptor (Info);
904 break;
905
906 case PARSEOP_CSI2_SERIALBUS:
907
908 Rnode = RsDoCsi2SerialBusDescriptor (Info);
909 break;
910
911 case PARSEOP_PINCONFIG:
912
913 Rnode = RsDoPinConfigDescriptor (Info);
914 break;
915
916 case PARSEOP_PINFUNCTION:
917
918 Rnode = RsDoPinFunctionDescriptor (Info);
919 break;
920
921 case PARSEOP_PINGROUP:
922
923 Rnode = RsDoPinGroupDescriptor (Info);
924 break;
925
926 case PARSEOP_PINGROUPFUNCTION:
927
928 Rnode = RsDoPinGroupFunctionDescriptor (Info);
929 break;
930
931 case PARSEOP_PINGROUPCONFIG:
932
933 Rnode = RsDoPinGroupConfigDescriptor (Info);
934 break;
935
936 case PARSEOP_DEFAULT_ARG:
937
938 /* Just ignore any of these, they are used as fillers/placeholders */
939 break;
940
941 default:
942
943 printf ("Unknown resource descriptor type [%s]\n",
944 Info->DescriptorTypeOp->Asl.ParseOpName);
945 break;
946 }
947
948 /*
949 * Mark original node as unused, but head of a resource descriptor.
950 * This allows the resource to be installed in the namespace so that
951 * references to the descriptor can be resolved.
952 */
953 Info->DescriptorTypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
954 Info->DescriptorTypeOp->Asl.CompileFlags = OP_IS_RESOURCE_DESC;
955 Info->DescriptorTypeOp->Asl.Value.Integer = Info->CurrentByteOffset;
956
957 if (Rnode)
958 {
959 Info->DescriptorTypeOp->Asl.FinalAmlLength = Rnode->BufferLength;
960 Info->DescriptorTypeOp->Asl.Extra =
961 ((AML_RESOURCE *) Rnode->Buffer)->DescriptorType;
962 }
963
964 return (Rnode);
965 }
966
967
968 /*******************************************************************************
969 *
970 * FUNCTION: RsLinkDescriptorChain
971 *
972 * PARAMETERS: PreviousRnode - Pointer to the node that will be previous
973 * to the linked node, At exit, set to the
974 * last node in the new chain.
975 * Rnode - Resource node to link into the list
976 *
977 * RETURN: Cumulative buffer byte offset of the new segment of chain
978 *
979 * DESCRIPTION: Link a descriptor chain at the end of an existing chain.
980 *
981 ******************************************************************************/
982
983 UINT32
984 RsLinkDescriptorChain (
985 ASL_RESOURCE_NODE **PreviousRnode,
986 ASL_RESOURCE_NODE *Rnode)
987 {
988 ASL_RESOURCE_NODE *LastRnode;
989 UINT32 CurrentByteOffset;
990
991
992 /* Anything to do? */
993
994 if (!Rnode)
995 {
996 return (0);
997 }
998
999 /* Point the previous node to the new node */
1000
1001 (*PreviousRnode)->Next = Rnode;
1002 CurrentByteOffset = Rnode->BufferLength;
1003
1004 /* Walk to the end of the chain headed by Rnode */
1005
1006 LastRnode = Rnode;
1007 while (LastRnode->Next)
1008 {
1009 LastRnode = LastRnode->Next;
1010 CurrentByteOffset += LastRnode->BufferLength;
1011 }
1012
1013 /* Previous node becomes the last node in the chain */
1014
1015 *PreviousRnode = LastRnode;
1016 return (CurrentByteOffset);
1017 }
1018
1019
1020 /*******************************************************************************
1021 *
1022 * FUNCTION: RsDoResourceTemplate
1023 *
1024 * PARAMETERS: Op - Parent of a resource template list
1025 *
1026 * RETURN: None. Sets input node to point to a list of AML code
1027 *
1028 * DESCRIPTION: Merge a list of resource descriptors into a single AML buffer,
1029 * in preparation for output to the AML output file.
1030 *
1031 ******************************************************************************/
1032
1033 void
1034 RsDoResourceTemplate (
1035 ACPI_PARSE_OBJECT *Op)
1036 {
1037 ACPI_PARSE_OBJECT *BufferLengthOp;
1038 ACPI_PARSE_OBJECT *BufferOp;
1039 ACPI_PARSE_OBJECT *DescriptorTypeOp;
1040 ACPI_PARSE_OBJECT *LastOp = NULL;
1041 UINT32 CurrentByteOffset = 0;
1042 ASL_RESOURCE_NODE HeadRnode;
1043 ASL_RESOURCE_NODE *PreviousRnode;
1044 ASL_RESOURCE_NODE *Rnode;
1045 ASL_RESOURCE_INFO Info;
1046 UINT8 State;
1047
1048
1049 /* Mark parent as containing a resource template */
1050
1051 if (Op->Asl.Parent)
1052 {
1053 Op->Asl.Parent->Asl.CompileFlags |= OP_IS_RESOURCE_DESC;
1054 }
1055
1056 /* ResourceTemplate Opcode is first (Op) */
1057 /* Buffer Length node is first child */
1058
1059 BufferLengthOp = ASL_GET_CHILD_NODE (Op);
1060
1061 /* Buffer Op is first peer */
1062
1063 BufferOp = ASL_GET_PEER_NODE (BufferLengthOp);
1064
1065 /* First Descriptor type is next */
1066
1067 DescriptorTypeOp = ASL_GET_PEER_NODE (BufferOp);
1068
1069 /* DEFAULT_ARG indicates null template - ResourceTemplate(){} */
1070
1071 if (DescriptorTypeOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
1072 {
1073 AslError (ASL_WARNING, ASL_MSG_NULL_RESOURCE_TEMPLATE,
1074 DescriptorTypeOp, DescriptorTypeOp->Asl.Value.String);
1075 }
1076
1077 /*
1078 * Process all resource descriptors in the list
1079 * Note: It is assumed that the EndTag node has been automatically
1080 * inserted at the end of the template by the parser.
1081 */
1082 State = ACPI_RSTATE_NORMAL;
1083 PreviousRnode = &HeadRnode;
1084 while (DescriptorTypeOp)
1085 {
1086 /* Save information for optional mapfile */
1087
1088 if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION)
1089 {
1090 Info.MappingOp = Op->Asl.Parent;
1091 }
1092 else
1093 {
1094 Info.MappingOp = DescriptorTypeOp;
1095 }
1096
1097 Info.DescriptorTypeOp = DescriptorTypeOp;
1098 Info.CurrentByteOffset = CurrentByteOffset;
1099
1100 DescriptorTypeOp->Asl.CompileFlags |= OP_IS_RESOURCE_DESC;
1101 Rnode = RsDoOneResourceDescriptor (&Info, &State);
1102
1103 /*
1104 * Update current byte offset to indicate the number of bytes from the
1105 * start of the buffer. Buffer can include multiple descriptors, we
1106 * must keep track of the offset of not only each descriptor, but each
1107 * element (field) within each descriptor as well.
1108 */
1109 CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, Rnode);
1110
1111 /* Get the next descriptor in the list */
1112
1113 LastOp = DescriptorTypeOp;
1114 DescriptorTypeOp = ASL_GET_PEER_NODE (DescriptorTypeOp);
1115 }
1116
1117 if (State == ACPI_RSTATE_DEPENDENT_LIST)
1118 {
1119 if (LastOp)
1120 {
1121 LastOp = LastOp->Asl.Parent;
1122 }
1123 AslError (ASL_ERROR, ASL_MSG_MISSING_ENDDEPENDENT, LastOp, NULL);
1124 }
1125
1126 /*
1127 * Transform the nodes into the following
1128 *
1129 * Op -> AML_BUFFER_OP
1130 * First Child -> BufferLength
1131 * Second Child -> Descriptor Buffer (raw byte data)
1132 */
1133 Op->Asl.ParseOpcode = PARSEOP_BUFFER;
1134 Op->Asl.AmlOpcode = AML_BUFFER_OP;
1135 Op->Asl.CompileFlags = OP_AML_PACKAGE | OP_IS_RESOURCE_DESC;
1136 UtSetParseOpName (Op);
1137
1138 BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
1139 BufferLengthOp->Asl.Value.Integer = CurrentByteOffset;
1140 (void) OpcSetOptimalIntegerSize (BufferLengthOp);
1141 UtSetParseOpName (BufferLengthOp);
1142
1143 BufferOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
1144 BufferOp->Asl.AmlOpcode = AML_RAW_DATA_CHAIN;
1145 BufferOp->Asl.AmlOpcodeLength = 0;
1146 BufferOp->Asl.AmlLength = CurrentByteOffset;
1147 BufferOp->Asl.Value.Buffer = ACPI_CAST_PTR (UINT8, HeadRnode.Next);
1148 BufferOp->Asl.CompileFlags |= OP_IS_RESOURCE_DATA;
1149 UtSetParseOpName (BufferOp);
1150
1151 return;
1152 }
1153