dttable1.c revision 1.1.1.14 1 /******************************************************************************
2 *
3 * Module Name: dttable1.c - handling for specific ACPI tables
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2022, 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 /* Compile all complex data tables, signatures starting with A-I */
45
46 #include "aslcompiler.h"
47
48 #define _COMPONENT DT_COMPILER
49 ACPI_MODULE_NAME ("dttable1")
50
51
52 static ACPI_DMTABLE_INFO TableInfoAsfAddress[] =
53 {
54 {ACPI_DMT_BUFFER, 0, "Addresses", 0},
55 {ACPI_DMT_EXIT, 0, NULL, 0}
56 };
57
58 static ACPI_DMTABLE_INFO TableInfoDmarPciPath[] =
59 {
60 {ACPI_DMT_PCI_PATH, 0, "PCI Path", 0},
61 {ACPI_DMT_EXIT, 0, NULL, 0}
62 };
63
64
65 /******************************************************************************
66 *
67 * FUNCTION: DtCompileAest
68 *
69 * PARAMETERS: List - Current field list pointer
70 *
71 * RETURN: Status
72 *
73 * DESCRIPTION: Compile AEST.
74 *
75 * NOTE: Assumes the following table structure:
76 * For all AEST Error Nodes:
77 * 1) An AEST Error Node, followed immediately by:
78 * 2) Any node-specific data
79 * 3) An Interface Structure (one)
80 * 4) A list (array) of Interrupt Structures, the count as specified
81 * in the NodeInterruptCount field of the Error Node header.
82 *
83 * AEST - ARM Error Source table. Conforms to:
84 * ACPI for the Armv8 RAS Extensions 1.1 Platform Design Document Sep 2020
85 *
86 *****************************************************************************/
87
88 ACPI_STATUS
89 DtCompileAest (
90 void **List)
91 {
92 ACPI_AEST_HEADER *ErrorNodeHeader;
93 ACPI_AEST_PROCESSOR *AestProcessor;
94 DT_SUBTABLE *Subtable;
95 DT_SUBTABLE *ParentTable;
96 ACPI_DMTABLE_INFO *InfoTable;
97 ACPI_STATUS Status;
98 UINT32 i;
99 UINT32 Offset;
100 DT_FIELD **PFieldList = (DT_FIELD **) List;
101
102
103 while (*PFieldList)
104 {
105 /* Compile the common error node header */
106
107 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAestHdr,
108 &Subtable);
109 if (ACPI_FAILURE (Status))
110 {
111 return (Status);
112 }
113
114 ParentTable = DtPeekSubtable ();
115 DtInsertSubtable (ParentTable, Subtable);
116
117 /* Everything past the error node header will be a subtable */
118
119 DtPushSubtable (Subtable);
120
121 /*
122 * Compile the node-specific structure (Based on the error
123 * node header Type field)
124 */
125 ErrorNodeHeader = ACPI_CAST_PTR (ACPI_AEST_HEADER, Subtable->Buffer);
126
127 /* Point past the common error node header */
128
129 Offset = sizeof (ACPI_AEST_HEADER);
130 ErrorNodeHeader->NodeSpecificOffset = Offset;
131
132 /* Decode the error node type */
133
134 switch (ErrorNodeHeader->Type)
135 {
136 case ACPI_AEST_PROCESSOR_ERROR_NODE:
137
138 InfoTable = AcpiDmTableInfoAestProcError;
139 break;
140
141 case ACPI_AEST_MEMORY_ERROR_NODE:
142
143 InfoTable = AcpiDmTableInfoAestMemError;
144 break;
145
146 case ACPI_AEST_SMMU_ERROR_NODE:
147
148 InfoTable = AcpiDmTableInfoAestSmmuError;
149 break;
150
151 case ACPI_AEST_VENDOR_ERROR_NODE:
152
153 InfoTable = AcpiDmTableInfoAestVendorError;
154 break;
155
156 case ACPI_AEST_GIC_ERROR_NODE:
157
158 InfoTable = AcpiDmTableInfoAestGicError;
159 break;
160
161 /* Error case below */
162 default:
163 AcpiOsPrintf ("Unknown AEST Subtable Type: %X\n",
164 ErrorNodeHeader->Type);
165 return (AE_ERROR);
166 }
167
168 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
169 if (ACPI_FAILURE (Status))
170 {
171 return (Status);
172 }
173
174 /* Point past the node-specific structure */
175
176 Offset += Subtable->Length;
177 ErrorNodeHeader->NodeInterfaceOffset = Offset;
178
179 ParentTable = DtPeekSubtable ();
180 DtInsertSubtable (ParentTable, Subtable);
181
182 /* Compile any additional node-specific substructures */
183
184 if (ErrorNodeHeader->Type == ACPI_AEST_PROCESSOR_ERROR_NODE)
185 {
186 /*
187 * Special handling for PROCESSOR_ERROR_NODE subtables
188 * (to handle the Resource Substructure via the ResourceType
189 * field).
190 */
191 AestProcessor = ACPI_CAST_PTR (ACPI_AEST_PROCESSOR,
192 Subtable->Buffer);
193
194 switch (AestProcessor->ResourceType)
195 {
196 case ACPI_AEST_CACHE_RESOURCE:
197
198 InfoTable = AcpiDmTableInfoAestCacheRsrc;
199 break;
200
201 case ACPI_AEST_TLB_RESOURCE:
202
203 InfoTable = AcpiDmTableInfoAestTlbRsrc;
204 break;
205
206 case ACPI_AEST_GENERIC_RESOURCE:
207
208 InfoTable = AcpiDmTableInfoAestGenRsrc;
209 AcpiOsPrintf ("Generic Resource Type (%X) is not supported at this time\n",
210 AestProcessor->ResourceType);
211 return (AE_ERROR);
212
213 /* Error case below */
214 default:
215 AcpiOsPrintf ("Unknown AEST Processor Resource Type: %X\n",
216 AestProcessor->ResourceType);
217 return (AE_ERROR);
218 }
219
220 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
221 if (ACPI_FAILURE (Status))
222 {
223 return (Status);
224 }
225
226 /* Point past the resource substructure subtable */
227
228 Offset += Subtable->Length;
229 ErrorNodeHeader->NodeInterfaceOffset = Offset;
230
231 ParentTable = DtPeekSubtable ();
232 DtInsertSubtable (ParentTable, Subtable);
233 }
234
235 /* Compile the (required) node interface structure */
236
237 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAestXface,
238 &Subtable);
239 if (ACPI_FAILURE (Status))
240 {
241 return (Status);
242 }
243
244 ErrorNodeHeader->NodeInterruptOffset = 0;
245 ParentTable = DtPeekSubtable ();
246 DtInsertSubtable (ParentTable, Subtable);
247
248 /* Compile each of the node interrupt structures */
249
250 if (ErrorNodeHeader->NodeInterruptCount)
251 {
252 /* Point to the first interrupt structure */
253
254 Offset += Subtable->Length;
255 ErrorNodeHeader->NodeInterruptOffset = Offset;
256 }
257
258 /* Compile each of the interrupt structures */
259
260 for (i = 0; i < ErrorNodeHeader->NodeInterruptCount; i++)
261 {
262 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAestXrupt,
263 &Subtable);
264 if (ACPI_FAILURE (Status))
265 {
266 return (Status);
267 }
268
269 ParentTable = DtPeekSubtable ();
270 DtInsertSubtable (ParentTable, Subtable);
271 }
272
273 /* Prepare for the next AEST Error node */
274
275 DtPopSubtable ();
276 }
277
278 return (AE_OK);
279 }
280
281
282 /******************************************************************************
283 *
284 * FUNCTION: DtCompileApmt
285 *
286 * PARAMETERS: List - Current field list pointer
287 *
288 * RETURN: Status
289 *
290 * DESCRIPTION: Compile APMT.
291 *
292 *****************************************************************************/
293
294 ACPI_STATUS
295 DtCompileApmt (
296 void **List)
297 {
298 ACPI_STATUS Status;
299 ACPI_TABLE_HEADER *Header;
300 ACPI_APMT_NODE *ApmtNode;
301 ACPI_APMT_NODE *PeerApmtNode;
302 DT_SUBTABLE *Subtable;
303 DT_SUBTABLE *PeerSubtable;
304 DT_SUBTABLE *ParentTable;
305 DT_FIELD **PFieldList = (DT_FIELD**)List;
306 DT_FIELD *SubtableStart;
307 UINT32 CurLength;
308 char MsgBuffer[64] = "";
309
310 ParentTable = DtPeekSubtable();
311
312 Header = ACPI_CAST_PTR(ACPI_TABLE_HEADER, ParentTable->Buffer);
313
314 CurLength = sizeof(ACPI_TABLE_HEADER);
315
316 /* Walk the parse tree */
317
318 while (*PFieldList)
319 {
320 /* APMT Node Subtable */
321
322 SubtableStart = *PFieldList;
323
324 Status = DtCompileTable(PFieldList, AcpiDmTableInfoApmtNode, &Subtable);
325
326 if (ACPI_FAILURE(Status))
327 {
328 return (Status);
329 }
330
331 ApmtNode = ACPI_CAST_PTR(ACPI_APMT_NODE, Subtable->Buffer);
332
333 if (ApmtNode->Length != sizeof(ACPI_APMT_NODE))
334 {
335 DtFatal(ASL_MSG_INVALID_LENGTH, SubtableStart, "APMT");
336 return (AE_ERROR);
337 }
338
339 if (ApmtNode->Type >= ACPI_APMT_NODE_TYPE_COUNT)
340 {
341 snprintf(MsgBuffer, 64, "Node Type : 0x%X", ApmtNode->Type);
342 DtFatal(ASL_MSG_INVALID_TYPE, SubtableStart, MsgBuffer);
343 return (AE_ERROR);
344 }
345
346 PeerSubtable = DtGetNextSubtable(ParentTable, NULL);
347
348 /* Validate the node id needs to be unique. */
349 while(PeerSubtable)
350 {
351 PeerApmtNode = ACPI_CAST_PTR(ACPI_APMT_NODE, PeerSubtable->Buffer);
352 if (PeerApmtNode->Id == ApmtNode->Id)
353 {
354 snprintf(MsgBuffer, 64, "Node Id : 0x%X existed", ApmtNode->Id);
355 DtFatal(ASL_MSG_DUPLICATE_ITEM, SubtableStart, MsgBuffer);
356 return (AE_ERROR);
357 }
358
359 PeerSubtable = DtGetNextSubtable(ParentTable, PeerSubtable);
360 }
361
362 CurLength += ApmtNode->Length;
363
364 DtInsertSubtable(ParentTable, Subtable);
365 }
366
367 if (Header->Length != CurLength)
368 {
369 snprintf(MsgBuffer, 64, " - APMT Length : %u (expected: %u)",
370 Header->Length, CurLength);
371 DtFatal(ASL_MSG_INVALID_LENGTH, NULL, MsgBuffer);
372 return (AE_ERROR);
373 }
374
375 return (AE_OK);
376 }
377
378 /******************************************************************************
379 *
380 * FUNCTION: DtCompileAsf
381 *
382 * PARAMETERS: List - Current field list pointer
383 *
384 * RETURN: Status
385 *
386 * DESCRIPTION: Compile ASF!.
387 *
388 *****************************************************************************/
389
390 ACPI_STATUS
391 DtCompileAsf (
392 void **List)
393 {
394 ACPI_ASF_INFO *AsfTable;
395 DT_SUBTABLE *Subtable;
396 DT_SUBTABLE *ParentTable;
397 ACPI_DMTABLE_INFO *InfoTable;
398 ACPI_DMTABLE_INFO *DataInfoTable = NULL;
399 UINT32 DataCount = 0;
400 ACPI_STATUS Status;
401 UINT32 i;
402 DT_FIELD **PFieldList = (DT_FIELD **) List;
403 DT_FIELD *SubtableStart;
404
405
406 while (*PFieldList)
407 {
408 SubtableStart = *PFieldList;
409 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAsfHdr,
410 &Subtable);
411 if (ACPI_FAILURE (Status))
412 {
413 return (Status);
414 }
415
416 ParentTable = DtPeekSubtable ();
417 DtInsertSubtable (ParentTable, Subtable);
418 DtPushSubtable (Subtable);
419
420 AsfTable = ACPI_CAST_PTR (ACPI_ASF_INFO, Subtable->Buffer);
421
422 switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */
423 {
424 case ACPI_ASF_TYPE_INFO:
425
426 InfoTable = AcpiDmTableInfoAsf0;
427 break;
428
429 case ACPI_ASF_TYPE_ALERT:
430
431 InfoTable = AcpiDmTableInfoAsf1;
432 break;
433
434 case ACPI_ASF_TYPE_CONTROL:
435
436 InfoTable = AcpiDmTableInfoAsf2;
437 break;
438
439 case ACPI_ASF_TYPE_BOOT:
440
441 InfoTable = AcpiDmTableInfoAsf3;
442 break;
443
444 case ACPI_ASF_TYPE_ADDRESS:
445
446 InfoTable = AcpiDmTableInfoAsf4;
447 break;
448
449 default:
450
451 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!");
452 return (AE_ERROR);
453 }
454
455 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
456 if (ACPI_FAILURE (Status))
457 {
458 return (Status);
459 }
460
461 ParentTable = DtPeekSubtable ();
462 DtInsertSubtable (ParentTable, Subtable);
463
464 switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */
465 {
466 case ACPI_ASF_TYPE_INFO:
467
468 DataInfoTable = NULL;
469 break;
470
471 case ACPI_ASF_TYPE_ALERT:
472
473 DataInfoTable = AcpiDmTableInfoAsf1a;
474 DataCount = ACPI_CAST_PTR (ACPI_ASF_ALERT,
475 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
476 sizeof (ACPI_ASF_HEADER)))->Alerts;
477 break;
478
479 case ACPI_ASF_TYPE_CONTROL:
480
481 DataInfoTable = AcpiDmTableInfoAsf2a;
482 DataCount = ACPI_CAST_PTR (ACPI_ASF_REMOTE,
483 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
484 sizeof (ACPI_ASF_HEADER)))->Controls;
485 break;
486
487 case ACPI_ASF_TYPE_BOOT:
488
489 DataInfoTable = NULL;
490 break;
491
492 case ACPI_ASF_TYPE_ADDRESS:
493
494 DataInfoTable = TableInfoAsfAddress;
495 DataCount = ACPI_CAST_PTR (ACPI_ASF_ADDRESS,
496 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
497 sizeof (ACPI_ASF_HEADER)))->Devices;
498 break;
499
500 default:
501
502 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!");
503 return (AE_ERROR);
504 }
505
506 if (DataInfoTable)
507 {
508 switch (AsfTable->Header.Type & 0x7F)
509 {
510 case ACPI_ASF_TYPE_ADDRESS:
511
512 while (DataCount > 0)
513 {
514 Status = DtCompileTable (PFieldList, DataInfoTable,
515 &Subtable);
516 if (ACPI_FAILURE (Status))
517 {
518 return (Status);
519 }
520
521 DtInsertSubtable (ParentTable, Subtable);
522 DataCount = DataCount - Subtable->Length;
523 }
524 break;
525
526 default:
527
528 for (i = 0; i < DataCount; i++)
529 {
530 Status = DtCompileTable (PFieldList, DataInfoTable,
531 &Subtable);
532 if (ACPI_FAILURE (Status))
533 {
534 return (Status);
535 }
536
537 DtInsertSubtable (ParentTable, Subtable);
538 }
539 break;
540 }
541 }
542
543 DtPopSubtable ();
544 }
545
546 return (AE_OK);
547 }
548
549
550 /******************************************************************************
551 *
552 * FUNCTION: DtCompileCedt
553 *
554 * PARAMETERS: List - Current field list pointer
555 *
556 * RETURN: Status
557 *
558 * DESCRIPTION: Compile CEDT.
559 *
560 *****************************************************************************/
561
562 ACPI_STATUS
563 DtCompileCedt (
564 void **List)
565 {
566 ACPI_STATUS Status;
567 DT_SUBTABLE *Subtable;
568 DT_SUBTABLE *ParentTable;
569 DT_FIELD **PFieldList = (DT_FIELD **) List;
570 ACPI_CEDT_HEADER *CedtHeader;
571 DT_FIELD *SubtableStart;
572
573
574 /* Walk the parse tree */
575
576 while (*PFieldList)
577 {
578 /* if CFMWS and has more than one target, then set to zero later */
579
580 int InsertFlag = 1;
581 SubtableStart = *PFieldList;
582
583 /* CEDT Header */
584
585 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedtHdr,
586 &Subtable);
587 if (ACPI_FAILURE (Status))
588 {
589 return (Status);
590 }
591
592 ParentTable = DtPeekSubtable ();
593 DtInsertSubtable (ParentTable, Subtable);
594 DtPushSubtable (Subtable);
595
596 CedtHeader = ACPI_CAST_PTR (ACPI_CEDT_HEADER, Subtable->Buffer);
597
598 switch (CedtHeader->Type)
599 {
600 case ACPI_CEDT_TYPE_CHBS:
601 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt0, &Subtable);
602 if (ACPI_FAILURE (Status))
603 {
604 return (Status);
605 }
606 break;
607 case ACPI_CEDT_TYPE_CFMWS: {
608 unsigned char *dump;
609 unsigned int idx, offset, max = 0;
610
611 /* Compile table with first "Interleave target" */
612
613 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt1, &Subtable);
614 if (ACPI_FAILURE (Status))
615 {
616 return (Status);
617 }
618
619 /* Look in buffer for the number of targets */
620 offset = (unsigned int) ACPI_OFFSET (ACPI_CEDT_CFMWS, InterleaveWays);
621 dump = (unsigned char *) Subtable->Buffer - 4; /* place at beginning of cedt1 */
622 max = 0x01 << dump[offset]; /* 2^max, so 0=1, 1=2, 2=4, 3=8. 8 is MAX */
623 if (max > 8) max=1; /* Error in encoding Interleaving Ways. */
624 if (max == 1) /* if only one target, then break here. */
625 break; /* break if only one target. */
626
627 /* We need to add more interleave targets, so write the current Subtable. */
628
629 ParentTable = DtPeekSubtable ();
630 DtInsertSubtable (ParentTable, Subtable); /* Insert AcpiDmTableInfoCedt1 table so we can put in */
631 DtPushSubtable (Subtable); /* the targets > the first. */
632
633 /* Now, find out all interleave targets beyond the first. */
634
635 for (idx = 1; idx < max; idx++) {
636 ParentTable = DtPeekSubtable ();
637
638 if (*PFieldList)
639 {
640 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt1_te, &Subtable);
641 if (ACPI_FAILURE (Status))
642 {
643 return (Status);
644 }
645 if (Subtable)
646 {
647 DtInsertSubtable (ParentTable, Subtable); /* got a target, so insert table. */
648 InsertFlag = 0;
649 }
650 }
651 }
652
653 DtPopSubtable ();
654 ParentTable = DtPeekSubtable ();
655 break;
656 }
657
658 default:
659 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "CEDT");
660 return (AE_ERROR);
661 }
662
663 ParentTable = DtPeekSubtable ();
664 if (InsertFlag == 1) {
665 DtInsertSubtable (ParentTable, Subtable);
666 }
667 DtPopSubtable ();
668 }
669
670 return (AE_OK);
671 }
672
673
674 /******************************************************************************
675 *
676 * FUNCTION: DtCompileCpep
677 *
678 * PARAMETERS: List - Current field list pointer
679 *
680 * RETURN: Status
681 *
682 * DESCRIPTION: Compile CPEP.
683 *
684 *****************************************************************************/
685
686 ACPI_STATUS
687 DtCompileCpep (
688 void **List)
689 {
690 ACPI_STATUS Status;
691
692
693 Status = DtCompileTwoSubtables (List,
694 AcpiDmTableInfoCpep, AcpiDmTableInfoCpep0);
695 return (Status);
696 }
697
698
699 /******************************************************************************
700 *
701 * FUNCTION: DtCompileCsrt
702 *
703 * PARAMETERS: List - Current field list pointer
704 *
705 * RETURN: Status
706 *
707 * DESCRIPTION: Compile CSRT.
708 *
709 *****************************************************************************/
710
711 ACPI_STATUS
712 DtCompileCsrt (
713 void **List)
714 {
715 ACPI_STATUS Status = AE_OK;
716 DT_SUBTABLE *Subtable;
717 DT_SUBTABLE *ParentTable;
718 DT_FIELD **PFieldList = (DT_FIELD **) List;
719 UINT32 DescriptorCount;
720 UINT32 GroupLength;
721
722
723 /* Subtables (Resource Groups) */
724
725 ParentTable = DtPeekSubtable ();
726 while (*PFieldList)
727 {
728 /* Resource group subtable */
729
730 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt0,
731 &Subtable);
732 if (ACPI_FAILURE (Status))
733 {
734 return (Status);
735 }
736
737 /* Compute the number of resource descriptors */
738
739 GroupLength =
740 (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
741 Subtable->Buffer))->Length -
742 (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
743 Subtable->Buffer))->SharedInfoLength -
744 sizeof (ACPI_CSRT_GROUP);
745
746 DescriptorCount = (GroupLength /
747 sizeof (ACPI_CSRT_DESCRIPTOR));
748
749 DtInsertSubtable (ParentTable, Subtable);
750 DtPushSubtable (Subtable);
751 ParentTable = DtPeekSubtable ();
752
753 /* Shared info subtable (One per resource group) */
754
755 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt1,
756 &Subtable);
757 if (ACPI_FAILURE (Status))
758 {
759 return (Status);
760 }
761
762 DtInsertSubtable (ParentTable, Subtable);
763
764 /* Sub-Subtables (Resource Descriptors) */
765
766 while (*PFieldList && DescriptorCount)
767 {
768
769 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2,
770 &Subtable);
771 if (ACPI_FAILURE (Status))
772 {
773 return (Status);
774 }
775
776 DtInsertSubtable (ParentTable, Subtable);
777
778 DtPushSubtable (Subtable);
779 ParentTable = DtPeekSubtable ();
780 if (*PFieldList)
781 {
782 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2a,
783 &Subtable);
784 if (ACPI_FAILURE (Status))
785 {
786 return (Status);
787 }
788 if (Subtable)
789 {
790 DtInsertSubtable (ParentTable, Subtable);
791 }
792 }
793
794 DtPopSubtable ();
795 ParentTable = DtPeekSubtable ();
796 DescriptorCount--;
797 }
798
799 DtPopSubtable ();
800 ParentTable = DtPeekSubtable ();
801 }
802
803 return (Status);
804 }
805
806
807 /******************************************************************************
808 *
809 * FUNCTION: DtCompileDbg2
810 *
811 * PARAMETERS: List - Current field list pointer
812 *
813 * RETURN: Status
814 *
815 * DESCRIPTION: Compile DBG2.
816 *
817 *****************************************************************************/
818
819 ACPI_STATUS
820 DtCompileDbg2 (
821 void **List)
822 {
823 ACPI_STATUS Status;
824 DT_SUBTABLE *Subtable;
825 DT_SUBTABLE *ParentTable;
826 DT_FIELD **PFieldList = (DT_FIELD **) List;
827 UINT32 SubtableCount;
828 ACPI_DBG2_HEADER *Dbg2Header;
829 ACPI_DBG2_DEVICE *DeviceInfo;
830 UINT16 CurrentOffset;
831 UINT32 i;
832
833
834 /* Main table */
835
836 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2, &Subtable);
837 if (ACPI_FAILURE (Status))
838 {
839 return (Status);
840 }
841
842 ParentTable = DtPeekSubtable ();
843 DtInsertSubtable (ParentTable, Subtable);
844
845 /* Main table fields */
846
847 Dbg2Header = ACPI_CAST_PTR (ACPI_DBG2_HEADER, Subtable->Buffer);
848 Dbg2Header->InfoOffset = sizeof (ACPI_TABLE_HEADER) + ACPI_PTR_DIFF (
849 ACPI_ADD_PTR (UINT8, Dbg2Header, sizeof (ACPI_DBG2_HEADER)), Dbg2Header);
850
851 SubtableCount = Dbg2Header->InfoCount;
852 DtPushSubtable (Subtable);
853
854 /* Process all Device Information subtables (Count = InfoCount) */
855
856 while (*PFieldList && SubtableCount)
857 {
858 /* Subtable: Debug Device Information */
859
860 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Device,
861 &Subtable);
862 if (ACPI_FAILURE (Status))
863 {
864 return (Status);
865 }
866
867 DeviceInfo = ACPI_CAST_PTR (ACPI_DBG2_DEVICE, Subtable->Buffer);
868 CurrentOffset = (UINT16) sizeof (ACPI_DBG2_DEVICE);
869
870 ParentTable = DtPeekSubtable ();
871 DtInsertSubtable (ParentTable, Subtable);
872 DtPushSubtable (Subtable);
873
874 ParentTable = DtPeekSubtable ();
875
876 /* BaseAddressRegister GAS array (Required, size is RegisterCount) */
877
878 DeviceInfo->BaseAddressOffset = CurrentOffset;
879 for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++)
880 {
881 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Addr,
882 &Subtable);
883 if (ACPI_FAILURE (Status))
884 {
885 return (Status);
886 }
887
888 CurrentOffset += (UINT16) sizeof (ACPI_GENERIC_ADDRESS);
889 DtInsertSubtable (ParentTable, Subtable);
890 }
891
892 /* AddressSize array (Required, size = RegisterCount) */
893
894 DeviceInfo->AddressSizeOffset = CurrentOffset;
895 for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++)
896 {
897 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Size,
898 &Subtable);
899 if (ACPI_FAILURE (Status))
900 {
901 return (Status);
902 }
903
904 CurrentOffset += (UINT16) sizeof (UINT32);
905 DtInsertSubtable (ParentTable, Subtable);
906 }
907
908 /* NamespaceString device identifier (Required, size = NamePathLength) */
909
910 DeviceInfo->NamepathOffset = CurrentOffset;
911 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Name,
912 &Subtable);
913 if (ACPI_FAILURE (Status))
914 {
915 return (Status);
916 }
917
918 /* Update the device info header */
919
920 DeviceInfo->NamepathLength = (UINT16) Subtable->Length;
921 CurrentOffset += (UINT16) DeviceInfo->NamepathLength;
922 DtInsertSubtable (ParentTable, Subtable);
923
924 /* OemData - Variable-length data (Optional, size = OemDataLength) */
925
926 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2OemData,
927 &Subtable);
928 if (Status == AE_END_OF_TABLE)
929 {
930 /* optional field was not found and we're at the end of the file */
931
932 goto subtableDone;
933 }
934 else if (ACPI_FAILURE (Status))
935 {
936 return (Status);
937 }
938
939 /* Update the device info header (zeros if no OEM data present) */
940
941 DeviceInfo->OemDataOffset = 0;
942 DeviceInfo->OemDataLength = 0;
943
944 /* Optional subtable (OemData) */
945
946 if (Subtable && Subtable->Length)
947 {
948 DeviceInfo->OemDataOffset = CurrentOffset;
949 DeviceInfo->OemDataLength = (UINT16) Subtable->Length;
950
951 DtInsertSubtable (ParentTable, Subtable);
952 }
953 subtableDone:
954 SubtableCount--;
955 DtPopSubtable (); /* Get next Device Information subtable */
956 }
957
958 DtPopSubtable ();
959 return (AE_OK);
960 }
961
962
963 /******************************************************************************
964 *
965 * FUNCTION: DtCompileDmar
966 *
967 * PARAMETERS: List - Current field list pointer
968 *
969 * RETURN: Status
970 *
971 * DESCRIPTION: Compile DMAR.
972 *
973 *****************************************************************************/
974
975 ACPI_STATUS
976 DtCompileDmar (
977 void **List)
978 {
979 ACPI_STATUS Status;
980 DT_SUBTABLE *Subtable;
981 DT_SUBTABLE *ParentTable;
982 DT_FIELD **PFieldList = (DT_FIELD **) List;
983 DT_FIELD *SubtableStart;
984 ACPI_DMTABLE_INFO *InfoTable;
985 ACPI_DMAR_HEADER *DmarHeader;
986 ACPI_DMAR_DEVICE_SCOPE *DmarDeviceScope;
987 UINT32 DeviceScopeLength;
988 UINT32 PciPathLength;
989
990
991 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmar, &Subtable);
992 if (ACPI_FAILURE (Status))
993 {
994 return (Status);
995 }
996
997 ParentTable = DtPeekSubtable ();
998 DtInsertSubtable (ParentTable, Subtable);
999 DtPushSubtable (Subtable);
1000
1001 while (*PFieldList)
1002 {
1003 /* DMAR Header */
1004
1005 SubtableStart = *PFieldList;
1006 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarHdr,
1007 &Subtable);
1008 if (ACPI_FAILURE (Status))
1009 {
1010 return (Status);
1011 }
1012
1013 ParentTable = DtPeekSubtable ();
1014 DtInsertSubtable (ParentTable, Subtable);
1015 DtPushSubtable (Subtable);
1016
1017 DmarHeader = ACPI_CAST_PTR (ACPI_DMAR_HEADER, Subtable->Buffer);
1018
1019 switch (DmarHeader->Type)
1020 {
1021 case ACPI_DMAR_TYPE_HARDWARE_UNIT:
1022
1023 InfoTable = AcpiDmTableInfoDmar0;
1024 break;
1025
1026 case ACPI_DMAR_TYPE_RESERVED_MEMORY:
1027
1028 InfoTable = AcpiDmTableInfoDmar1;
1029 break;
1030
1031 case ACPI_DMAR_TYPE_ROOT_ATS:
1032
1033 InfoTable = AcpiDmTableInfoDmar2;
1034 break;
1035
1036 case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
1037
1038 InfoTable = AcpiDmTableInfoDmar3;
1039 break;
1040
1041 case ACPI_DMAR_TYPE_NAMESPACE:
1042
1043 InfoTable = AcpiDmTableInfoDmar4;
1044 break;
1045
1046 case ACPI_DMAR_TYPE_SATC:
1047
1048 InfoTable = AcpiDmTableInfoDmar5;
1049 break;
1050
1051 default:
1052
1053 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "DMAR");
1054 return (AE_ERROR);
1055 }
1056
1057 /* DMAR Subtable */
1058
1059 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1060 if (ACPI_FAILURE (Status))
1061 {
1062 return (Status);
1063 }
1064
1065 ParentTable = DtPeekSubtable ();
1066 DtInsertSubtable (ParentTable, Subtable);
1067
1068 /*
1069 * Optional Device Scope subtables
1070 */
1071 if ((DmarHeader->Type == ACPI_DMAR_TYPE_HARDWARE_AFFINITY) ||
1072 (DmarHeader->Type == ACPI_DMAR_TYPE_NAMESPACE))
1073 {
1074 /* These types do not support device scopes */
1075
1076 DtPopSubtable ();
1077 continue;
1078 }
1079
1080 DtPushSubtable (Subtable);
1081 DeviceScopeLength = DmarHeader->Length - Subtable->Length -
1082 ParentTable->Length;
1083 while (DeviceScopeLength)
1084 {
1085 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarScope,
1086 &Subtable);
1087 if (Status == AE_NOT_FOUND)
1088 {
1089 break;
1090 }
1091
1092 ParentTable = DtPeekSubtable ();
1093 DtInsertSubtable (ParentTable, Subtable);
1094 DtPushSubtable (Subtable);
1095
1096 DmarDeviceScope = ACPI_CAST_PTR (ACPI_DMAR_DEVICE_SCOPE, Subtable->Buffer);
1097
1098 /* Optional PCI Paths */
1099
1100 PciPathLength = DmarDeviceScope->Length - Subtable->Length;
1101 while (PciPathLength)
1102 {
1103 Status = DtCompileTable (PFieldList, TableInfoDmarPciPath,
1104 &Subtable);
1105 if (Status == AE_NOT_FOUND)
1106 {
1107 DtPopSubtable ();
1108 break;
1109 }
1110
1111 ParentTable = DtPeekSubtable ();
1112 DtInsertSubtable (ParentTable, Subtable);
1113 PciPathLength -= Subtable->Length;
1114 }
1115
1116 DtPopSubtable ();
1117 DeviceScopeLength -= DmarDeviceScope->Length;
1118 }
1119
1120 DtPopSubtable ();
1121 DtPopSubtable ();
1122 }
1123
1124 return (AE_OK);
1125 }
1126
1127
1128 /******************************************************************************
1129 *
1130 * FUNCTION: DtCompileDrtm
1131 *
1132 * PARAMETERS: List - Current field list pointer
1133 *
1134 * RETURN: Status
1135 *
1136 * DESCRIPTION: Compile DRTM.
1137 *
1138 *****************************************************************************/
1139
1140 ACPI_STATUS
1141 DtCompileDrtm (
1142 void **List)
1143 {
1144 ACPI_STATUS Status;
1145 DT_SUBTABLE *Subtable;
1146 DT_SUBTABLE *ParentTable;
1147 DT_FIELD **PFieldList = (DT_FIELD **) List;
1148 UINT32 Count;
1149 /* ACPI_TABLE_DRTM *Drtm; */
1150 ACPI_DRTM_VTABLE_LIST *DrtmVtl;
1151 ACPI_DRTM_RESOURCE_LIST *DrtmRl;
1152 /* ACPI_DRTM_DPS_ID *DrtmDps; */
1153
1154
1155 ParentTable = DtPeekSubtable ();
1156
1157 /* Compile DRTM header */
1158
1159 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm,
1160 &Subtable);
1161 if (ACPI_FAILURE (Status))
1162 {
1163 return (Status);
1164 }
1165 DtInsertSubtable (ParentTable, Subtable);
1166
1167 /*
1168 * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
1169 * should be taken to avoid accessing ACPI_TABLE_HADER fields.
1170 */
1171 #if 0
1172 Drtm = ACPI_SUB_PTR (ACPI_TABLE_DRTM,
1173 Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
1174 #endif
1175 /* Compile VTL */
1176
1177 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0,
1178 &Subtable);
1179 if (ACPI_FAILURE (Status))
1180 {
1181 return (Status);
1182 }
1183
1184 DtInsertSubtable (ParentTable, Subtable);
1185 DrtmVtl = ACPI_CAST_PTR (ACPI_DRTM_VTABLE_LIST, Subtable->Buffer);
1186
1187 DtPushSubtable (Subtable);
1188 ParentTable = DtPeekSubtable ();
1189 Count = 0;
1190
1191 while (*PFieldList)
1192 {
1193 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0a,
1194 &Subtable);
1195 if (ACPI_FAILURE (Status))
1196 {
1197 return (Status);
1198 }
1199 if (!Subtable)
1200 {
1201 break;
1202 }
1203 DtInsertSubtable (ParentTable, Subtable);
1204 Count++;
1205 }
1206
1207 DrtmVtl->ValidatedTableCount = Count;
1208 DtPopSubtable ();
1209 ParentTable = DtPeekSubtable ();
1210
1211 /* Compile RL */
1212
1213 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1,
1214 &Subtable);
1215 if (ACPI_FAILURE (Status))
1216 {
1217 return (Status);
1218 }
1219
1220 DtInsertSubtable (ParentTable, Subtable);
1221 DrtmRl = ACPI_CAST_PTR (ACPI_DRTM_RESOURCE_LIST, Subtable->Buffer);
1222
1223 DtPushSubtable (Subtable);
1224 ParentTable = DtPeekSubtable ();
1225 Count = 0;
1226
1227 while (*PFieldList)
1228 {
1229 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1a,
1230 &Subtable);
1231 if (ACPI_FAILURE (Status))
1232 {
1233 return (Status);
1234 }
1235
1236 if (!Subtable)
1237 {
1238 break;
1239 }
1240
1241 DtInsertSubtable (ParentTable, Subtable);
1242 Count++;
1243 }
1244
1245 DrtmRl->ResourceCount = Count;
1246 DtPopSubtable ();
1247 ParentTable = DtPeekSubtable ();
1248
1249 /* Compile DPS */
1250
1251 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm2,
1252 &Subtable);
1253 if (ACPI_FAILURE (Status))
1254 {
1255 return (Status);
1256 }
1257 DtInsertSubtable (ParentTable, Subtable);
1258 /* DrtmDps = ACPI_CAST_PTR (ACPI_DRTM_DPS_ID, Subtable->Buffer);*/
1259
1260
1261 return (AE_OK);
1262 }
1263
1264
1265 /******************************************************************************
1266 *
1267 * FUNCTION: DtCompileEinj
1268 *
1269 * PARAMETERS: List - Current field list pointer
1270 *
1271 * RETURN: Status
1272 *
1273 * DESCRIPTION: Compile EINJ.
1274 *
1275 *****************************************************************************/
1276
1277 ACPI_STATUS
1278 DtCompileEinj (
1279 void **List)
1280 {
1281 ACPI_STATUS Status;
1282
1283
1284 Status = DtCompileTwoSubtables (List,
1285 AcpiDmTableInfoEinj, AcpiDmTableInfoEinj0);
1286 return (Status);
1287 }
1288
1289
1290 /******************************************************************************
1291 *
1292 * FUNCTION: DtCompileErst
1293 *
1294 * PARAMETERS: List - Current field list pointer
1295 *
1296 * RETURN: Status
1297 *
1298 * DESCRIPTION: Compile ERST.
1299 *
1300 *****************************************************************************/
1301
1302 ACPI_STATUS
1303 DtCompileErst (
1304 void **List)
1305 {
1306 ACPI_STATUS Status;
1307
1308
1309 Status = DtCompileTwoSubtables (List,
1310 AcpiDmTableInfoErst, AcpiDmTableInfoEinj0);
1311 return (Status);
1312 }
1313
1314
1315 /******************************************************************************
1316 *
1317 * FUNCTION: DtCompileGtdt
1318 *
1319 * PARAMETERS: List - Current field list pointer
1320 *
1321 * RETURN: Status
1322 *
1323 * DESCRIPTION: Compile GTDT.
1324 *
1325 *****************************************************************************/
1326
1327 ACPI_STATUS
1328 DtCompileGtdt (
1329 void **List)
1330 {
1331 ACPI_STATUS Status;
1332 DT_SUBTABLE *Subtable;
1333 DT_SUBTABLE *ParentTable;
1334 DT_FIELD **PFieldList = (DT_FIELD **) List;
1335 DT_FIELD *SubtableStart;
1336 ACPI_SUBTABLE_HEADER *GtdtHeader;
1337 ACPI_DMTABLE_INFO *InfoTable;
1338 UINT32 GtCount;
1339 ACPI_TABLE_HEADER *Header;
1340
1341
1342 ParentTable = DtPeekSubtable ();
1343
1344 Header = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer);
1345
1346 /* Compile the main table */
1347
1348 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt,
1349 &Subtable);
1350 if (ACPI_FAILURE (Status))
1351 {
1352 return (Status);
1353 }
1354
1355 /* GTDT revision 3 later contains 2 extra fields before subtables */
1356
1357 if (Header->Revision > 2)
1358 {
1359 ParentTable = DtPeekSubtable ();
1360 DtInsertSubtable (ParentTable, Subtable);
1361
1362 Status = DtCompileTable (PFieldList,
1363 AcpiDmTableInfoGtdtEl2, &Subtable);
1364 if (ACPI_FAILURE (Status))
1365 {
1366 return (Status);
1367 }
1368 }
1369
1370 ParentTable = DtPeekSubtable ();
1371 DtInsertSubtable (ParentTable, Subtable);
1372
1373 while (*PFieldList)
1374 {
1375 SubtableStart = *PFieldList;
1376 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdtHdr,
1377 &Subtable);
1378 if (ACPI_FAILURE (Status))
1379 {
1380 return (Status);
1381 }
1382
1383 ParentTable = DtPeekSubtable ();
1384 DtInsertSubtable (ParentTable, Subtable);
1385 DtPushSubtable (Subtable);
1386
1387 GtdtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer);
1388
1389 switch (GtdtHeader->Type)
1390 {
1391 case ACPI_GTDT_TYPE_TIMER_BLOCK:
1392
1393 InfoTable = AcpiDmTableInfoGtdt0;
1394 break;
1395
1396 case ACPI_GTDT_TYPE_WATCHDOG:
1397
1398 InfoTable = AcpiDmTableInfoGtdt1;
1399 break;
1400
1401 default:
1402
1403 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "GTDT");
1404 return (AE_ERROR);
1405 }
1406
1407 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1408 if (ACPI_FAILURE (Status))
1409 {
1410 return (Status);
1411 }
1412
1413 ParentTable = DtPeekSubtable ();
1414 DtInsertSubtable (ParentTable, Subtable);
1415
1416 /*
1417 * Additional GT block subtable data
1418 */
1419
1420 switch (GtdtHeader->Type)
1421 {
1422 case ACPI_GTDT_TYPE_TIMER_BLOCK:
1423
1424 DtPushSubtable (Subtable);
1425 ParentTable = DtPeekSubtable ();
1426
1427 GtCount = (ACPI_CAST_PTR (ACPI_GTDT_TIMER_BLOCK,
1428 Subtable->Buffer - sizeof(ACPI_GTDT_HEADER)))->TimerCount;
1429
1430 while (GtCount)
1431 {
1432 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt0a,
1433 &Subtable);
1434 if (ACPI_FAILURE (Status))
1435 {
1436 return (Status);
1437 }
1438
1439 DtInsertSubtable (ParentTable, Subtable);
1440 GtCount--;
1441 }
1442
1443 DtPopSubtable ();
1444 break;
1445
1446 default:
1447
1448 break;
1449 }
1450
1451 DtPopSubtable ();
1452 }
1453
1454 return (AE_OK);
1455 }
1456
1457
1458 /******************************************************************************
1459 *
1460 * FUNCTION: DtCompileFpdt
1461 *
1462 * PARAMETERS: List - Current field list pointer
1463 *
1464 * RETURN: Status
1465 *
1466 * DESCRIPTION: Compile FPDT.
1467 *
1468 *****************************************************************************/
1469
1470 ACPI_STATUS
1471 DtCompileFpdt (
1472 void **List)
1473 {
1474 ACPI_STATUS Status;
1475 ACPI_FPDT_HEADER *FpdtHeader;
1476 DT_SUBTABLE *Subtable;
1477 DT_SUBTABLE *ParentTable;
1478 ACPI_DMTABLE_INFO *InfoTable;
1479 DT_FIELD **PFieldList = (DT_FIELD **) List;
1480 DT_FIELD *SubtableStart;
1481
1482
1483 while (*PFieldList)
1484 {
1485 SubtableStart = *PFieldList;
1486 Status = DtCompileTable (PFieldList, AcpiDmTableInfoFpdtHdr,
1487 &Subtable);
1488 if (ACPI_FAILURE (Status))
1489 {
1490 return (Status);
1491 }
1492
1493 ParentTable = DtPeekSubtable ();
1494 DtInsertSubtable (ParentTable, Subtable);
1495 DtPushSubtable (Subtable);
1496
1497 FpdtHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer);
1498
1499 switch (FpdtHeader->Type)
1500 {
1501 case ACPI_FPDT_TYPE_BOOT:
1502
1503 InfoTable = AcpiDmTableInfoFpdt0;
1504 break;
1505
1506 case ACPI_FPDT_TYPE_S3PERF:
1507
1508 InfoTable = AcpiDmTableInfoFpdt1;
1509 break;
1510
1511 default:
1512
1513 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "FPDT");
1514 return (AE_ERROR);
1515 break;
1516 }
1517
1518 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1519 if (ACPI_FAILURE (Status))
1520 {
1521 return (Status);
1522 }
1523
1524 ParentTable = DtPeekSubtable ();
1525 DtInsertSubtable (ParentTable, Subtable);
1526 DtPopSubtable ();
1527 }
1528
1529 return (AE_OK);
1530 }
1531
1532
1533 /******************************************************************************
1534 *
1535 * FUNCTION: DtCompileHest
1536 *
1537 * PARAMETERS: List - Current field list pointer
1538 *
1539 * RETURN: Status
1540 *
1541 * DESCRIPTION: Compile HEST.
1542 *
1543 *****************************************************************************/
1544
1545 ACPI_STATUS
1546 DtCompileHest (
1547 void **List)
1548 {
1549 ACPI_STATUS Status;
1550 DT_SUBTABLE *Subtable;
1551 DT_SUBTABLE *ParentTable;
1552 DT_FIELD **PFieldList = (DT_FIELD **) List;
1553 DT_FIELD *SubtableStart;
1554 ACPI_DMTABLE_INFO *InfoTable;
1555 UINT16 Type;
1556 UINT32 BankCount;
1557
1558
1559 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHest,
1560 &Subtable);
1561 if (ACPI_FAILURE (Status))
1562 {
1563 return (Status);
1564 }
1565
1566 ParentTable = DtPeekSubtable ();
1567 DtInsertSubtable (ParentTable, Subtable);
1568
1569 while (*PFieldList)
1570 {
1571 /* Get subtable type */
1572
1573 SubtableStart = *PFieldList;
1574 DtCompileInteger ((UINT8 *) &Type, *PFieldList, 2, 0);
1575
1576 switch (Type)
1577 {
1578 case ACPI_HEST_TYPE_IA32_CHECK:
1579
1580 InfoTable = AcpiDmTableInfoHest0;
1581 break;
1582
1583 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
1584
1585 InfoTable = AcpiDmTableInfoHest1;
1586 break;
1587
1588 case ACPI_HEST_TYPE_IA32_NMI:
1589
1590 InfoTable = AcpiDmTableInfoHest2;
1591 break;
1592
1593 case ACPI_HEST_TYPE_AER_ROOT_PORT:
1594
1595 InfoTable = AcpiDmTableInfoHest6;
1596 break;
1597
1598 case ACPI_HEST_TYPE_AER_ENDPOINT:
1599
1600 InfoTable = AcpiDmTableInfoHest7;
1601 break;
1602
1603 case ACPI_HEST_TYPE_AER_BRIDGE:
1604
1605 InfoTable = AcpiDmTableInfoHest8;
1606 break;
1607
1608 case ACPI_HEST_TYPE_GENERIC_ERROR:
1609
1610 InfoTable = AcpiDmTableInfoHest9;
1611 break;
1612
1613 case ACPI_HEST_TYPE_GENERIC_ERROR_V2:
1614
1615 InfoTable = AcpiDmTableInfoHest10;
1616 break;
1617
1618 case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
1619
1620 InfoTable = AcpiDmTableInfoHest11;
1621 break;
1622
1623 default:
1624
1625 /* Cannot continue on unknown type */
1626
1627 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HEST");
1628 return (AE_ERROR);
1629 }
1630
1631 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1632 if (ACPI_FAILURE (Status))
1633 {
1634 return (Status);
1635 }
1636
1637 DtInsertSubtable (ParentTable, Subtable);
1638
1639 /*
1640 * Additional subtable data - IA32 Error Bank(s)
1641 */
1642 BankCount = 0;
1643 switch (Type)
1644 {
1645 case ACPI_HEST_TYPE_IA32_CHECK:
1646
1647 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK,
1648 Subtable->Buffer))->NumHardwareBanks;
1649 break;
1650
1651 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
1652
1653 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED,
1654 Subtable->Buffer))->NumHardwareBanks;
1655 break;
1656
1657 case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
1658
1659 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_DEFERRED_CHECK,
1660 Subtable->Buffer))->NumHardwareBanks;
1661 break;
1662
1663 default:
1664
1665 break;
1666 }
1667
1668 while (BankCount)
1669 {
1670 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHestBank,
1671 &Subtable);
1672 if (ACPI_FAILURE (Status))
1673 {
1674 return (Status);
1675 }
1676
1677 DtInsertSubtable (ParentTable, Subtable);
1678 BankCount--;
1679 }
1680 }
1681
1682 return (AE_OK);
1683 }
1684
1685
1686 /******************************************************************************
1687 *
1688 * FUNCTION: DtCompileHmat
1689 *
1690 * PARAMETERS: List - Current field list pointer
1691 *
1692 * RETURN: Status
1693 *
1694 * DESCRIPTION: Compile HMAT.
1695 *
1696 *****************************************************************************/
1697
1698 ACPI_STATUS
1699 DtCompileHmat (
1700 void **List)
1701 {
1702 ACPI_STATUS Status;
1703 DT_SUBTABLE *Subtable;
1704 DT_SUBTABLE *ParentTable;
1705 DT_FIELD **PFieldList = (DT_FIELD **) List;
1706 DT_FIELD *SubtableStart;
1707 DT_FIELD *EntryStart;
1708 ACPI_HMAT_STRUCTURE *HmatStruct;
1709 ACPI_HMAT_LOCALITY *HmatLocality;
1710 ACPI_HMAT_CACHE *HmatCache;
1711 ACPI_DMTABLE_INFO *InfoTable;
1712 UINT32 IntPDNumber;
1713 UINT32 TgtPDNumber;
1714 UINT64 EntryNumber;
1715 UINT16 SMBIOSHandleNumber;
1716
1717
1718 ParentTable = DtPeekSubtable ();
1719
1720 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmat,
1721 &Subtable);
1722 if (ACPI_FAILURE (Status))
1723 {
1724 return (Status);
1725 }
1726 DtInsertSubtable (ParentTable, Subtable);
1727
1728 while (*PFieldList)
1729 {
1730 /* Compile HMAT structure header */
1731
1732 SubtableStart = *PFieldList;
1733 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmatHdr,
1734 &Subtable);
1735 if (ACPI_FAILURE (Status))
1736 {
1737 return (Status);
1738 }
1739 DtInsertSubtable (ParentTable, Subtable);
1740
1741 HmatStruct = ACPI_CAST_PTR (ACPI_HMAT_STRUCTURE, Subtable->Buffer);
1742 HmatStruct->Length = Subtable->Length;
1743
1744 /* Compile HMAT structure body */
1745
1746 switch (HmatStruct->Type)
1747 {
1748 case ACPI_HMAT_TYPE_ADDRESS_RANGE:
1749
1750 InfoTable = AcpiDmTableInfoHmat0;
1751 break;
1752
1753 case ACPI_HMAT_TYPE_LOCALITY:
1754
1755 InfoTable = AcpiDmTableInfoHmat1;
1756 break;
1757
1758 case ACPI_HMAT_TYPE_CACHE:
1759
1760 InfoTable = AcpiDmTableInfoHmat2;
1761 break;
1762
1763 default:
1764
1765 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HMAT");
1766 return (AE_ERROR);
1767 }
1768
1769 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1770 if (ACPI_FAILURE (Status))
1771 {
1772 return (Status);
1773 }
1774 DtInsertSubtable (ParentTable, Subtable);
1775 HmatStruct->Length += Subtable->Length;
1776
1777 /* Compile HMAT structure additionals */
1778
1779 switch (HmatStruct->Type)
1780 {
1781 case ACPI_HMAT_TYPE_LOCALITY:
1782
1783 HmatLocality = ACPI_SUB_PTR (ACPI_HMAT_LOCALITY,
1784 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
1785
1786 /* Compile initiator proximity domain list */
1787
1788 IntPDNumber = 0;
1789 while (*PFieldList)
1790 {
1791 Status = DtCompileTable (PFieldList,
1792 AcpiDmTableInfoHmat1a, &Subtable);
1793 if (ACPI_FAILURE (Status))
1794 {
1795 return (Status);
1796 }
1797 if (!Subtable)
1798 {
1799 break;
1800 }
1801 DtInsertSubtable (ParentTable, Subtable);
1802 HmatStruct->Length += Subtable->Length;
1803 IntPDNumber++;
1804 }
1805 HmatLocality->NumberOfInitiatorPDs = IntPDNumber;
1806
1807 /* Compile target proximity domain list */
1808
1809 TgtPDNumber = 0;
1810 while (*PFieldList)
1811 {
1812 Status = DtCompileTable (PFieldList,
1813 AcpiDmTableInfoHmat1b, &Subtable);
1814 if (ACPI_FAILURE (Status))
1815 {
1816 return (Status);
1817 }
1818 if (!Subtable)
1819 {
1820 break;
1821 }
1822 DtInsertSubtable (ParentTable, Subtable);
1823 HmatStruct->Length += Subtable->Length;
1824 TgtPDNumber++;
1825 }
1826 HmatLocality->NumberOfTargetPDs = TgtPDNumber;
1827
1828 /* Save start of the entries for reporting errors */
1829
1830 EntryStart = *PFieldList;
1831
1832 /* Compile latency/bandwidth entries */
1833
1834 EntryNumber = 0;
1835 while (*PFieldList)
1836 {
1837 Status = DtCompileTable (PFieldList,
1838 AcpiDmTableInfoHmat1c, &Subtable);
1839 if (ACPI_FAILURE (Status))
1840 {
1841 return (Status);
1842 }
1843 if (!Subtable)
1844 {
1845 break;
1846 }
1847 DtInsertSubtable (ParentTable, Subtable);
1848 HmatStruct->Length += Subtable->Length;
1849 EntryNumber++;
1850 }
1851
1852 /* Validate number of entries */
1853
1854 if (EntryNumber !=
1855 ((UINT64)IntPDNumber * (UINT64)TgtPDNumber))
1856 {
1857 DtFatal (ASL_MSG_INVALID_EXPRESSION, EntryStart, "HMAT");
1858 return (AE_ERROR);
1859 }
1860 break;
1861
1862 case ACPI_HMAT_TYPE_CACHE:
1863
1864 /* Compile SMBIOS handles */
1865
1866 HmatCache = ACPI_SUB_PTR (ACPI_HMAT_CACHE,
1867 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
1868 SMBIOSHandleNumber = 0;
1869 while (*PFieldList)
1870 {
1871 Status = DtCompileTable (PFieldList,
1872 AcpiDmTableInfoHmat2a, &Subtable);
1873 if (ACPI_FAILURE (Status))
1874 {
1875 return (Status);
1876 }
1877 if (!Subtable)
1878 {
1879 break;
1880 }
1881 DtInsertSubtable (ParentTable, Subtable);
1882 HmatStruct->Length += Subtable->Length;
1883 SMBIOSHandleNumber++;
1884 }
1885 HmatCache->NumberOfSMBIOSHandles = SMBIOSHandleNumber;
1886 break;
1887
1888 default:
1889
1890 break;
1891 }
1892 }
1893
1894 return (AE_OK);
1895 }
1896
1897
1898 /******************************************************************************
1899 *
1900 * FUNCTION: DtCompileIort
1901 *
1902 * PARAMETERS: List - Current field list pointer
1903 *
1904 * RETURN: Status
1905 *
1906 * DESCRIPTION: Compile IORT.
1907 *
1908 *****************************************************************************/
1909
1910 ACPI_STATUS
1911 DtCompileIort (
1912 void **List)
1913 {
1914 ACPI_STATUS Status;
1915 DT_SUBTABLE *Subtable;
1916 DT_SUBTABLE *ParentTable;
1917 DT_FIELD **PFieldList = (DT_FIELD **) List;
1918 DT_FIELD *SubtableStart;
1919 ACPI_TABLE_HEADER *Table;
1920 ACPI_TABLE_IORT *Iort;
1921 ACPI_IORT_NODE *IortNode;
1922 ACPI_IORT_ITS_GROUP *IortItsGroup;
1923 ACPI_IORT_SMMU *IortSmmu;
1924 ACPI_IORT_RMR *IortRmr;
1925 UINT32 NodeNumber;
1926 UINT32 NodeLength;
1927 UINT32 IdMappingNumber;
1928 UINT32 ItsNumber;
1929 UINT32 ContextIrptNumber;
1930 UINT32 PmuIrptNumber;
1931 UINT32 PaddingLength;
1932 UINT8 Revision;
1933 UINT32 RmrCount;
1934
1935
1936 ParentTable = DtPeekSubtable ();
1937
1938 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort,
1939 &Subtable);
1940 if (ACPI_FAILURE (Status))
1941 {
1942 return (Status);
1943 }
1944 DtInsertSubtable (ParentTable, Subtable);
1945
1946 Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer);
1947 Revision = Table->Revision;
1948
1949 /* IORT Revisions E, E.a & E.c have known issues and are not supported */
1950
1951 if (Revision == 1 || Revision == 2 || Revision == 4)
1952 {
1953 DtError (ASL_ERROR, ASL_MSG_UNSUPPORTED, NULL, "IORT table revision");
1954 return (AE_ERROR);
1955 }
1956
1957 /*
1958 * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
1959 * should be taken to avoid accessing ACPI_TABLE_HEADER fields.
1960 */
1961 Iort = ACPI_SUB_PTR (ACPI_TABLE_IORT,
1962 Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
1963
1964 /*
1965 * OptionalPadding - Variable-length data
1966 * (Optional, size = OffsetToNodes - sizeof (ACPI_TABLE_IORT))
1967 * Optionally allows the generic data types to be used for filling
1968 * this field.
1969 */
1970 Iort->NodeOffset = sizeof (ACPI_TABLE_IORT);
1971 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortPad,
1972 &Subtable);
1973 if (ACPI_FAILURE (Status))
1974 {
1975 return (Status);
1976 }
1977 if (Subtable)
1978 {
1979 DtInsertSubtable (ParentTable, Subtable);
1980 Iort->NodeOffset += Subtable->Length;
1981 }
1982 else
1983 {
1984 Status = DtCompileGeneric (ACPI_CAST_PTR (void *, PFieldList),
1985 AcpiDmTableInfoIortHdr[0].Name, &PaddingLength);
1986 if (ACPI_FAILURE (Status))
1987 {
1988 return (Status);
1989 }
1990 Iort->NodeOffset += PaddingLength;
1991 }
1992
1993 NodeNumber = 0;
1994 while (*PFieldList)
1995 {
1996 SubtableStart = *PFieldList;
1997 if (Revision == 0)
1998 {
1999 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr,
2000 &Subtable);
2001 }
2002 else if (Revision >= 3)
2003 {
2004 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr3,
2005 &Subtable);
2006 }
2007
2008 if (ACPI_FAILURE (Status))
2009 {
2010 return (Status);
2011 }
2012
2013 DtInsertSubtable (ParentTable, Subtable);
2014 IortNode = ACPI_CAST_PTR (ACPI_IORT_NODE, Subtable->Buffer);
2015 NodeLength = ACPI_OFFSET (ACPI_IORT_NODE, NodeData);
2016
2017 DtPushSubtable (Subtable);
2018 ParentTable = DtPeekSubtable ();
2019
2020 switch (IortNode->Type)
2021 {
2022 case ACPI_IORT_NODE_ITS_GROUP:
2023
2024 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0,
2025 &Subtable);
2026 if (ACPI_FAILURE (Status))
2027 {
2028 return (Status);
2029 }
2030
2031 DtInsertSubtable (ParentTable, Subtable);
2032 IortItsGroup = ACPI_CAST_PTR (ACPI_IORT_ITS_GROUP, Subtable->Buffer);
2033 NodeLength += Subtable->Length;
2034
2035 ItsNumber = 0;
2036 while (*PFieldList)
2037 {
2038 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0a,
2039 &Subtable);
2040 if (ACPI_FAILURE (Status))
2041 {
2042 return (Status);
2043 }
2044 if (!Subtable)
2045 {
2046 break;
2047 }
2048
2049 DtInsertSubtable (ParentTable, Subtable);
2050 NodeLength += Subtable->Length;
2051 ItsNumber++;
2052 }
2053
2054 IortItsGroup->ItsCount = ItsNumber;
2055 break;
2056
2057 case ACPI_IORT_NODE_NAMED_COMPONENT:
2058
2059 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1,
2060 &Subtable);
2061 if (ACPI_FAILURE (Status))
2062 {
2063 return (Status);
2064 }
2065
2066 DtInsertSubtable (ParentTable, Subtable);
2067 NodeLength += Subtable->Length;
2068
2069 /*
2070 * Padding - Variable-length data
2071 * Optionally allows the offset of the ID mappings to be used
2072 * for filling this field.
2073 */
2074 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1a,
2075 &Subtable);
2076 if (ACPI_FAILURE (Status))
2077 {
2078 return (Status);
2079 }
2080
2081 if (Subtable)
2082 {
2083 DtInsertSubtable (ParentTable, Subtable);
2084 NodeLength += Subtable->Length;
2085 }
2086 else
2087 {
2088 if (NodeLength > IortNode->MappingOffset)
2089 {
2090 return (AE_BAD_DATA);
2091 }
2092
2093 if (NodeLength < IortNode->MappingOffset)
2094 {
2095 Status = DtCompilePadding (
2096 IortNode->MappingOffset - NodeLength,
2097 &Subtable);
2098 if (ACPI_FAILURE (Status))
2099 {
2100 return (Status);
2101 }
2102
2103 DtInsertSubtable (ParentTable, Subtable);
2104 NodeLength = IortNode->MappingOffset;
2105 }
2106 }
2107 break;
2108
2109 case ACPI_IORT_NODE_PCI_ROOT_COMPLEX:
2110
2111 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort2,
2112 &Subtable);
2113 if (ACPI_FAILURE (Status))
2114 {
2115 return (Status);
2116 }
2117
2118 DtInsertSubtable (ParentTable, Subtable);
2119 NodeLength += Subtable->Length;
2120 break;
2121
2122 case ACPI_IORT_NODE_SMMU:
2123
2124 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3,
2125 &Subtable);
2126 if (ACPI_FAILURE (Status))
2127 {
2128 return (Status);
2129 }
2130
2131 DtInsertSubtable (ParentTable, Subtable);
2132 IortSmmu = ACPI_CAST_PTR (ACPI_IORT_SMMU, Subtable->Buffer);
2133 NodeLength += Subtable->Length;
2134
2135 /* Compile global interrupt array */
2136
2137 IortSmmu->GlobalInterruptOffset = NodeLength;
2138 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3a,
2139 &Subtable);
2140 if (ACPI_FAILURE (Status))
2141 {
2142 return (Status);
2143 }
2144
2145 DtInsertSubtable (ParentTable, Subtable);
2146 NodeLength += Subtable->Length;
2147
2148 /* Compile context interrupt array */
2149
2150 ContextIrptNumber = 0;
2151 IortSmmu->ContextInterruptOffset = NodeLength;
2152 while (*PFieldList)
2153 {
2154 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3b,
2155 &Subtable);
2156 if (ACPI_FAILURE (Status))
2157 {
2158 return (Status);
2159 }
2160
2161 if (!Subtable)
2162 {
2163 break;
2164 }
2165
2166 DtInsertSubtable (ParentTable, Subtable);
2167 NodeLength += Subtable->Length;
2168 ContextIrptNumber++;
2169 }
2170
2171 IortSmmu->ContextInterruptCount = ContextIrptNumber;
2172
2173 /* Compile PMU interrupt array */
2174
2175 PmuIrptNumber = 0;
2176 IortSmmu->PmuInterruptOffset = NodeLength;
2177 while (*PFieldList)
2178 {
2179 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3c,
2180 &Subtable);
2181 if (ACPI_FAILURE (Status))
2182 {
2183 return (Status);
2184 }
2185
2186 if (!Subtable)
2187 {
2188 break;
2189 }
2190
2191 DtInsertSubtable (ParentTable, Subtable);
2192 NodeLength += Subtable->Length;
2193 PmuIrptNumber++;
2194 }
2195
2196 IortSmmu->PmuInterruptCount = PmuIrptNumber;
2197 break;
2198
2199 case ACPI_IORT_NODE_SMMU_V3:
2200
2201 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort4,
2202 &Subtable);
2203 if (ACPI_FAILURE (Status))
2204 {
2205 return (Status);
2206 }
2207
2208 DtInsertSubtable (ParentTable, Subtable);
2209 NodeLength += Subtable->Length;
2210 break;
2211
2212 case ACPI_IORT_NODE_PMCG:
2213
2214 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort5,
2215 &Subtable);
2216 if (ACPI_FAILURE (Status))
2217 {
2218 return (Status);
2219 }
2220
2221 DtInsertSubtable (ParentTable, Subtable);
2222 NodeLength += Subtable->Length;
2223 break;
2224
2225 case ACPI_IORT_NODE_RMR:
2226
2227 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6,
2228 &Subtable);
2229 if (ACPI_FAILURE (Status))
2230 {
2231 return (Status);
2232 }
2233
2234 DtInsertSubtable (ParentTable, Subtable);
2235 IortRmr = ACPI_CAST_PTR (ACPI_IORT_RMR, Subtable->Buffer);
2236 NodeLength += Subtable->Length;
2237
2238 /* Compile RMR Descriptors */
2239
2240 RmrCount = 0;
2241 IortRmr->RmrOffset = NodeLength;
2242 while (*PFieldList)
2243 {
2244 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6a,
2245 &Subtable);
2246 if (ACPI_FAILURE (Status))
2247 {
2248 return (Status);
2249 }
2250
2251 if (!Subtable)
2252 {
2253 break;
2254 }
2255
2256 DtInsertSubtable (ParentTable, Subtable);
2257 NodeLength += sizeof (ACPI_IORT_RMR_DESC);
2258 RmrCount++;
2259 }
2260
2261 IortRmr->RmrCount = RmrCount;
2262 break;
2263
2264 default:
2265
2266 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IORT");
2267 return (AE_ERROR);
2268 }
2269
2270 /* Compile Array of ID mappings */
2271
2272 IortNode->MappingOffset = NodeLength;
2273 IdMappingNumber = 0;
2274 while (*PFieldList)
2275 {
2276 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortMap,
2277 &Subtable);
2278 if (ACPI_FAILURE (Status))
2279 {
2280 return (Status);
2281 }
2282
2283 if (!Subtable)
2284 {
2285 break;
2286 }
2287
2288 DtInsertSubtable (ParentTable, Subtable);
2289 NodeLength += sizeof (ACPI_IORT_ID_MAPPING);
2290 IdMappingNumber++;
2291 }
2292
2293 IortNode->MappingCount = IdMappingNumber;
2294 if (!IdMappingNumber)
2295 {
2296 IortNode->MappingOffset = 0;
2297 }
2298
2299 /*
2300 * Node length can be determined by DT_LENGTH option
2301 * IortNode->Length = NodeLength;
2302 */
2303 DtPopSubtable ();
2304 ParentTable = DtPeekSubtable ();
2305 NodeNumber++;
2306 }
2307
2308 Iort->NodeCount = NodeNumber;
2309 return (AE_OK);
2310 }
2311
2312
2313 /******************************************************************************
2314 *
2315 * FUNCTION: DtCompileIvrs
2316 *
2317 * PARAMETERS: List - Current field list pointer
2318 *
2319 * RETURN: Status
2320 *
2321 * DESCRIPTION: Compile IVRS. Notes:
2322 * The IVRS is essentially a flat table, with the following
2323 * structure:
2324 * <Main ACPI Table Header>
2325 * <Main subtable - virtualization info>
2326 * <IVHD>
2327 * <Device Entries>
2328 * ...
2329 * <IVHD>
2330 * <Device Entries>
2331 * <IVMD>
2332 * ...
2333 *
2334 *****************************************************************************/
2335
2336 ACPI_STATUS
2337 DtCompileIvrs (
2338 void **List)
2339 {
2340 ACPI_STATUS Status;
2341 DT_SUBTABLE *Subtable;
2342 DT_SUBTABLE *ParentTable;
2343 DT_SUBTABLE *MainSubtable;
2344 DT_FIELD **PFieldList = (DT_FIELD **) List;
2345 DT_FIELD *SubtableStart;
2346 ACPI_DMTABLE_INFO *InfoTable = NULL;
2347 UINT8 SubtableType;
2348 UINT8 Temp64[16];
2349 UINT8 Temp8;
2350
2351
2352 /* Main table */
2353
2354 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrs,
2355 &Subtable);
2356 if (ACPI_FAILURE (Status))
2357 {
2358 return (Status);
2359 }
2360
2361 ParentTable = DtPeekSubtable ();
2362 DtInsertSubtable (ParentTable, Subtable);
2363 DtPushSubtable (Subtable);
2364
2365 /* Save a pointer to the main subtable */
2366
2367 MainSubtable = Subtable;
2368
2369 while (*PFieldList)
2370 {
2371 SubtableStart = *PFieldList;
2372
2373 /* Compile the SubtableType integer */
2374
2375 DtCompileInteger (&SubtableType, *PFieldList, 1, 0);
2376
2377 switch (SubtableType)
2378 {
2379
2380 /* Type 10h, IVHD (I/O Virtualization Hardware Definition) */
2381
2382 case ACPI_IVRS_TYPE_HARDWARE1:
2383
2384 InfoTable = AcpiDmTableInfoIvrsHware1;
2385 break;
2386
2387 /* Types 11h, 40h, IVHD (I/O Virtualization Hardware Definition) */
2388
2389 case ACPI_IVRS_TYPE_HARDWARE2:
2390 case ACPI_IVRS_TYPE_HARDWARE3:
2391
2392 InfoTable = AcpiDmTableInfoIvrsHware23;
2393 break;
2394
2395 /* Types 20h, 21h, 22h, IVMD (I/O Virtualization Memory Definition Block) */
2396
2397 case ACPI_IVRS_TYPE_MEMORY1:
2398 case ACPI_IVRS_TYPE_MEMORY2:
2399 case ACPI_IVRS_TYPE_MEMORY3:
2400
2401 InfoTable = AcpiDmTableInfoIvrsMemory;
2402 break;
2403
2404 /* 4-byte device entries */
2405
2406 case ACPI_IVRS_TYPE_PAD4:
2407 case ACPI_IVRS_TYPE_ALL:
2408 case ACPI_IVRS_TYPE_SELECT:
2409 case ACPI_IVRS_TYPE_START:
2410 case ACPI_IVRS_TYPE_END:
2411
2412 InfoTable = AcpiDmTableInfoIvrs4;
2413 break;
2414
2415 /* 8-byte device entries, type A */
2416
2417 case ACPI_IVRS_TYPE_ALIAS_SELECT:
2418 case ACPI_IVRS_TYPE_ALIAS_START:
2419
2420 InfoTable = AcpiDmTableInfoIvrs8a;
2421 break;
2422
2423 /* 8-byte device entries, type B */
2424
2425 case ACPI_IVRS_TYPE_EXT_SELECT:
2426 case ACPI_IVRS_TYPE_EXT_START:
2427
2428 InfoTable = AcpiDmTableInfoIvrs8b;
2429 break;
2430
2431 /* 8-byte device entries, type C */
2432
2433 case ACPI_IVRS_TYPE_SPECIAL:
2434
2435 InfoTable = AcpiDmTableInfoIvrs8c;
2436 break;
2437
2438 /* Variable device entries, type F0h */
2439
2440 case ACPI_IVRS_TYPE_HID:
2441
2442 InfoTable = AcpiDmTableInfoIvrsHid;
2443 break;
2444
2445 default:
2446
2447 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart,
2448 "IVRS Device Entry");
2449 return (AE_ERROR);
2450 }
2451
2452 /* Compile the InfoTable from above */
2453
2454 Status = DtCompileTable (PFieldList, InfoTable,
2455 &Subtable);
2456 if (ACPI_FAILURE (Status))
2457 {
2458 return (Status);
2459 }
2460
2461 ParentTable = DtPeekSubtable ();
2462 if (SubtableType != ACPI_IVRS_TYPE_HARDWARE1 &&
2463 SubtableType != ACPI_IVRS_TYPE_HARDWARE2 &&
2464 SubtableType != ACPI_IVRS_TYPE_HARDWARE3 &&
2465 SubtableType != ACPI_IVRS_TYPE_HID &&
2466 SubtableType != ACPI_IVRS_TYPE_MEMORY1 &&
2467 SubtableType != ACPI_IVRS_TYPE_MEMORY2 &&
2468 SubtableType != ACPI_IVRS_TYPE_MEMORY3)
2469 {
2470 if (ParentTable)
2471 DtInsertSubtable (ParentTable, Subtable);
2472 }
2473
2474 switch (SubtableType)
2475 {
2476 case ACPI_IVRS_TYPE_HARDWARE1:
2477 case ACPI_IVRS_TYPE_HARDWARE2:
2478 case ACPI_IVRS_TYPE_HARDWARE3:
2479 case ACPI_IVRS_TYPE_MEMORY1:
2480 case ACPI_IVRS_TYPE_MEMORY2:
2481 case ACPI_IVRS_TYPE_MEMORY3:
2482
2483 /* Insert these IVHDs/IVMDs at the root subtable */
2484
2485 DtInsertSubtable (MainSubtable, Subtable);
2486 DtPushSubtable (Subtable);
2487 ParentTable = MainSubtable;
2488 break;
2489
2490 case ACPI_IVRS_TYPE_HID:
2491
2492 /* Special handling for the HID named device entry (0xF0) */
2493
2494 if (ParentTable)
2495 {
2496 DtInsertSubtable (ParentTable, Subtable);
2497 }
2498
2499 /*
2500 * Process the HID value. First, get the HID value as a string.
2501 */
2502 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0);
2503
2504 /*
2505 * Determine if the HID is an integer or a string.
2506 * An integer is defined to be 32 bits, with the upper 32 bits
2507 * set to zero. (from the ACPI Spec): "The HID can be a 32-bit
2508 * integer or a character string. If an integer, the lower
2509 * 4 bytes of the field contain the integer and the upper
2510 * 4 bytes are padded with 0".
2511 */
2512 if (UtIsIdInteger ((UINT8 *) &Temp64))
2513 {
2514 /* Compile the HID value as an integer */
2515
2516 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0);
2517
2518 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidInteger,
2519 &Subtable);
2520 if (ACPI_FAILURE (Status))
2521 {
2522 return (Status);
2523 }
2524 }
2525 else
2526 {
2527 /* Compile the HID value as a string */
2528
2529 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidString,
2530 &Subtable);
2531 if (ACPI_FAILURE (Status))
2532 {
2533 return (Status);
2534 }
2535 }
2536
2537 DtInsertSubtable (ParentTable, Subtable);
2538
2539 /*
2540 * Process the CID value. First, get the CID value as a string.
2541 */
2542 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0);
2543
2544 if (UtIsIdInteger ((UINT8 *) &Temp64))
2545 {
2546 /* Compile the CID value as an integer */
2547
2548 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0);
2549
2550 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidInteger,
2551 &Subtable);
2552 if (ACPI_FAILURE (Status))
2553 {
2554 return (Status);
2555 }
2556 }
2557 else
2558 {
2559 /* Compile the CID value as a string */
2560
2561 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidString,
2562 &Subtable);
2563 if (ACPI_FAILURE (Status))
2564 {
2565 return (Status);
2566 }
2567 }
2568
2569 DtInsertSubtable (ParentTable, Subtable);
2570
2571 /*
2572 * Process the UID value. First, get and decode the "UID Format" field (Integer).
2573 */
2574 if (!*PFieldList)
2575 {
2576 return (AE_OK);
2577 }
2578
2579 DtCompileOneField (&Temp8, *PFieldList, 1, DT_FIELD_TYPE_INTEGER, 0);
2580
2581 switch (Temp8)
2582 {
2583 case ACPI_IVRS_UID_NOT_PRESENT:
2584 break;
2585
2586 case ACPI_IVRS_UID_IS_INTEGER:
2587
2588 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidInteger,
2589 &Subtable);
2590 if (ACPI_FAILURE (Status))
2591 {
2592 return (Status);
2593 }
2594 DtInsertSubtable (ParentTable, Subtable);
2595 break;
2596
2597 case ACPI_IVRS_UID_IS_STRING:
2598
2599 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidString,
2600 &Subtable);
2601 if (ACPI_FAILURE (Status))
2602 {
2603 return (Status);
2604 }
2605 DtInsertSubtable (ParentTable, Subtable);
2606 break;
2607
2608 default:
2609
2610 DtFatal (ASL_MSG_UNKNOWN_FORMAT, SubtableStart,
2611 "IVRS Device Entry");
2612 return (AE_ERROR);
2613 }
2614
2615 default:
2616
2617 /* All other subtable types come through here */
2618 break;
2619 }
2620 }
2621
2622 return (AE_OK);
2623 }
2624