dttable1.c revision 1.1.1.16 1 /******************************************************************************
2 *
3 * Module Name: dttable1.c - handling for specific ACPI tables
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 /* 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 * FUNCTION: DtCompileAspt
552 *
553 * PARAMETERS: List - Current field list pointer
554 *
555 * RETURN: Status
556 *
557 * DESCRIPTION: Compile ASPT.
558 *
559 *****************************************************************************/
560
561 ACPI_STATUS
562 DtCompileAspt (
563 void **List)
564 {
565 ACPI_ASPT_HEADER *AsptTable;
566 DT_SUBTABLE *Subtable;
567 DT_SUBTABLE *ParentTable;
568 ACPI_DMTABLE_INFO *InfoTable;
569 ACPI_STATUS Status;
570 DT_FIELD **PFieldList = (DT_FIELD **) List;
571 DT_FIELD *SubtableStart;
572
573 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAspt, &Subtable);
574 if (ACPI_FAILURE (Status))
575 {
576 return (Status);
577 }
578
579 ParentTable = DtPeekSubtable ();
580 DtInsertSubtable (ParentTable, Subtable);
581
582 while (*PFieldList)
583 {
584 SubtableStart = *PFieldList;
585 Status = DtCompileTable (PFieldList, AcpiDmTableInfoAsptHdr,
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 AsptTable = ACPI_CAST_PTR (ACPI_ASPT_HEADER, Subtable->Buffer);
597
598 switch (AsptTable->Type) /* Mask off top bit */
599 {
600 case ACPI_ASPT_TYPE_GLOBAL_REGS:
601
602 InfoTable = AcpiDmTableInfoAspt0;
603 break;
604
605 case ACPI_ASPT_TYPE_SEV_MBOX_REGS:
606
607 InfoTable = AcpiDmTableInfoAspt1;
608 break;
609
610 case ACPI_ASPT_TYPE_ACPI_MBOX_REGS:
611
612 InfoTable = AcpiDmTableInfoAspt2;
613 break;
614
615 default:
616
617 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASPT");
618 return (AE_ERROR);
619 }
620
621 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
622 if (ACPI_FAILURE (Status))
623 {
624 return (Status);
625 }
626 ParentTable = DtPeekSubtable ();
627 DtInsertSubtable (ParentTable, Subtable);
628 DtPopSubtable ();
629 }
630
631 return (AE_OK);
632 }
633
634
635 /******************************************************************************
636 *
637 * FUNCTION: DtCompileCdat
638 *
639 * PARAMETERS: List - Current field list pointer
640 *
641 * RETURN: Status
642 *
643 * DESCRIPTION: Compile CDAT.
644 *
645 *****************************************************************************/
646
647 ACPI_STATUS
648 DtCompileCdat (
649 void **List)
650 {
651 ACPI_STATUS Status = AE_OK;
652 DT_SUBTABLE *Subtable;
653 DT_SUBTABLE *ParentTable;
654 DT_FIELD **PFieldList = (DT_FIELD **) List;
655 ACPI_CDAT_HEADER *CdatHeader;
656 ACPI_DMTABLE_INFO *InfoTable = NULL;
657 DT_FIELD *SubtableStart;
658
659
660 /* Walk the parse tree.
661 *
662 * Note: Main table consists of only the CDAT table header
663 * (This is not the standard ACPI table header, however)--
664 * Followed by some number of subtables.
665 */
666 while (*PFieldList)
667 {
668 SubtableStart = *PFieldList;
669
670 /* Compile the expected CDAT Subtable header */
671
672 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCdatHeader,
673 &Subtable);
674 if (ACPI_FAILURE (Status))
675 {
676 return (Status);
677 }
678
679 ParentTable = DtPeekSubtable ();
680 DtInsertSubtable (ParentTable, Subtable);
681 DtPushSubtable (Subtable);
682
683 CdatHeader = ACPI_CAST_PTR (ACPI_CDAT_HEADER, Subtable->Buffer);
684
685 /* Decode the subtable by type */
686
687 switch (CdatHeader->Type)
688 {
689 case ACPI_CDAT_TYPE_DSMAS:
690 InfoTable = AcpiDmTableInfoCdat0;
691 break;
692
693 case ACPI_CDAT_TYPE_DSLBIS:
694 InfoTable = AcpiDmTableInfoCdat1;
695 break;
696
697 case ACPI_CDAT_TYPE_DSMSCIS:
698 InfoTable = AcpiDmTableInfoCdat2;
699 break;
700
701 case ACPI_CDAT_TYPE_DSIS:
702 InfoTable = AcpiDmTableInfoCdat3;
703 break;
704
705 case ACPI_CDAT_TYPE_DSEMTS:
706 InfoTable = AcpiDmTableInfoCdat4;
707 break;
708
709 case ACPI_CDAT_TYPE_SSLBIS:
710 InfoTable = AcpiDmTableInfoCdat5;
711 break;
712
713 default:
714 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "CDAT");
715 }
716
717 /* Compile the CDAT subtable */
718
719 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
720 if (ACPI_FAILURE (Status))
721 {
722 return (Status);
723 }
724
725 ParentTable = DtPeekSubtable ();
726 DtInsertSubtable (ParentTable, Subtable);
727
728 switch (CdatHeader->Type)
729 {
730 /* Multiple entries supported for this type */
731
732 case ACPI_CDAT_TYPE_SSLBIS:
733
734 /*
735 * Check for multiple SSLBEs
736 */
737 while (*PFieldList && !AcpiUtStricmp ((*PFieldList)->Name, "Port X ID"))
738 {
739 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCdatEntries, &Subtable);
740 if (ACPI_FAILURE (Status))
741 {
742 return (Status);
743 }
744 ParentTable = DtPeekSubtable ();
745 DtInsertSubtable (ParentTable, Subtable);
746 }
747 break;
748
749 default:
750 break;
751 }
752
753 /* Pop off the CDAT Subtable header subtree */
754
755 DtPopSubtable ();
756 }
757
758 return (AE_OK);
759 }
760
761
762 /******************************************************************************
763 *
764 * FUNCTION: DtCompileCedt
765 *
766 * PARAMETERS: List - Current field list pointer
767 *
768 * RETURN: Status
769 *
770 * DESCRIPTION: Compile CEDT.
771 *
772 *****************************************************************************/
773
774 ACPI_STATUS
775 DtCompileCedt (
776 void **List)
777 {
778 ACPI_STATUS Status;
779 DT_SUBTABLE *Subtable;
780 DT_SUBTABLE *ParentTable;
781 DT_FIELD **PFieldList = (DT_FIELD **) List;
782 ACPI_CEDT_HEADER *CedtHeader;
783 DT_FIELD *SubtableStart;
784
785
786 /* Walk the parse tree */
787
788 while (*PFieldList)
789 {
790 /* if CFMWS and has more than one target, then set to zero later */
791
792 int InsertFlag = 1;
793 SubtableStart = *PFieldList;
794
795 /* CEDT Header */
796
797 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedtHdr,
798 &Subtable);
799 if (ACPI_FAILURE (Status))
800 {
801 return (Status);
802 }
803
804 ParentTable = DtPeekSubtable ();
805 DtInsertSubtable (ParentTable, Subtable);
806 DtPushSubtable (Subtable);
807
808 CedtHeader = ACPI_CAST_PTR (ACPI_CEDT_HEADER, Subtable->Buffer);
809
810 switch (CedtHeader->Type)
811 {
812 case ACPI_CEDT_TYPE_CHBS:
813 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt0, &Subtable);
814 if (ACPI_FAILURE (Status))
815 {
816 return (Status);
817 }
818 break;
819 case ACPI_CEDT_TYPE_CFMWS: {
820 unsigned char *dump;
821 unsigned int idx, offset, max = 0;
822
823 /* Compile table with first "Interleave target" */
824
825 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt1, &Subtable);
826 if (ACPI_FAILURE (Status))
827 {
828 return (Status);
829 }
830
831 /* Look in buffer for the number of targets */
832 offset = (unsigned int) ACPI_OFFSET (ACPI_CEDT_CFMWS, InterleaveWays);
833 dump = (unsigned char *) Subtable->Buffer - 4; /* place at beginning of cedt1 */
834 max = 0x01 << dump[offset]; /* 2^max, so 0=1, 1=2, 2=4, 3=8. 8 is MAX */
835 if (max > 8) max=1; /* Error in encoding Interleaving Ways. */
836 if (max == 1) /* if only one target, then break here. */
837 break; /* break if only one target. */
838
839 /* We need to add more interleave targets, so write the current Subtable. */
840
841 ParentTable = DtPeekSubtable ();
842 DtInsertSubtable (ParentTable, Subtable); /* Insert AcpiDmTableInfoCedt1 table so we can put in */
843 DtPushSubtable (Subtable); /* the targets > the first. */
844
845 /* Now, find out all interleave targets beyond the first. */
846
847 for (idx = 1; idx < max; idx++) {
848 ParentTable = DtPeekSubtable ();
849
850 if (*PFieldList)
851 {
852 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt1_te, &Subtable);
853 if (ACPI_FAILURE (Status))
854 {
855 return (Status);
856 }
857 if (Subtable)
858 {
859 DtInsertSubtable (ParentTable, Subtable); /* got a target, so insert table. */
860 InsertFlag = 0;
861 }
862 }
863 }
864
865 DtPopSubtable ();
866 ParentTable = DtPeekSubtable ();
867 break;
868 }
869
870 default:
871 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "CEDT");
872 return (AE_ERROR);
873 }
874
875 ParentTable = DtPeekSubtable ();
876 if (InsertFlag == 1) {
877 DtInsertSubtable (ParentTable, Subtable);
878 }
879 DtPopSubtable ();
880 }
881
882 return (AE_OK);
883 }
884
885
886 /******************************************************************************
887 *
888 * FUNCTION: DtCompileCpep
889 *
890 * PARAMETERS: List - Current field list pointer
891 *
892 * RETURN: Status
893 *
894 * DESCRIPTION: Compile CPEP.
895 *
896 *****************************************************************************/
897
898 ACPI_STATUS
899 DtCompileCpep (
900 void **List)
901 {
902 ACPI_STATUS Status;
903
904
905 Status = DtCompileTwoSubtables (List,
906 AcpiDmTableInfoCpep, AcpiDmTableInfoCpep0);
907 return (Status);
908 }
909
910
911 /******************************************************************************
912 *
913 * FUNCTION: DtCompileCsrt
914 *
915 * PARAMETERS: List - Current field list pointer
916 *
917 * RETURN: Status
918 *
919 * DESCRIPTION: Compile CSRT.
920 *
921 *****************************************************************************/
922
923 ACPI_STATUS
924 DtCompileCsrt (
925 void **List)
926 {
927 ACPI_STATUS Status = AE_OK;
928 DT_SUBTABLE *Subtable;
929 DT_SUBTABLE *ParentTable;
930 DT_FIELD **PFieldList = (DT_FIELD **) List;
931 UINT32 DescriptorCount;
932 UINT32 GroupLength;
933
934
935 /* Subtables (Resource Groups) */
936
937 ParentTable = DtPeekSubtable ();
938 while (*PFieldList)
939 {
940 /* Resource group subtable */
941
942 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt0,
943 &Subtable);
944 if (ACPI_FAILURE (Status))
945 {
946 return (Status);
947 }
948
949 /* Compute the number of resource descriptors */
950
951 GroupLength =
952 (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
953 Subtable->Buffer))->Length -
954 (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
955 Subtable->Buffer))->SharedInfoLength -
956 sizeof (ACPI_CSRT_GROUP);
957
958 DescriptorCount = (GroupLength /
959 sizeof (ACPI_CSRT_DESCRIPTOR));
960
961 DtInsertSubtable (ParentTable, Subtable);
962 DtPushSubtable (Subtable);
963 ParentTable = DtPeekSubtable ();
964
965 /* Shared info subtable (One per resource group) */
966
967 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt1,
968 &Subtable);
969 if (ACPI_FAILURE (Status))
970 {
971 return (Status);
972 }
973
974 DtInsertSubtable (ParentTable, Subtable);
975
976 /* Sub-Subtables (Resource Descriptors) */
977
978 while (*PFieldList && DescriptorCount)
979 {
980
981 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2,
982 &Subtable);
983 if (ACPI_FAILURE (Status))
984 {
985 return (Status);
986 }
987
988 DtInsertSubtable (ParentTable, Subtable);
989
990 DtPushSubtable (Subtable);
991 ParentTable = DtPeekSubtable ();
992 if (*PFieldList)
993 {
994 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2a,
995 &Subtable);
996 if (ACPI_FAILURE (Status))
997 {
998 return (Status);
999 }
1000 if (Subtable)
1001 {
1002 DtInsertSubtable (ParentTable, Subtable);
1003 }
1004 }
1005
1006 DtPopSubtable ();
1007 ParentTable = DtPeekSubtable ();
1008 DescriptorCount--;
1009 }
1010
1011 DtPopSubtable ();
1012 ParentTable = DtPeekSubtable ();
1013 }
1014
1015 return (Status);
1016 }
1017
1018
1019 /******************************************************************************
1020 *
1021 * FUNCTION: DtCompileDbg2
1022 *
1023 * PARAMETERS: List - Current field list pointer
1024 *
1025 * RETURN: Status
1026 *
1027 * DESCRIPTION: Compile DBG2.
1028 *
1029 *****************************************************************************/
1030
1031 ACPI_STATUS
1032 DtCompileDbg2 (
1033 void **List)
1034 {
1035 ACPI_STATUS Status;
1036 DT_SUBTABLE *Subtable;
1037 DT_SUBTABLE *ParentTable;
1038 DT_FIELD **PFieldList = (DT_FIELD **) List;
1039 UINT32 SubtableCount;
1040 ACPI_DBG2_HEADER *Dbg2Header;
1041 ACPI_DBG2_DEVICE *DeviceInfo;
1042 UINT16 CurrentOffset;
1043 UINT32 i;
1044
1045
1046 /* Main table */
1047
1048 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2, &Subtable);
1049 if (ACPI_FAILURE (Status))
1050 {
1051 return (Status);
1052 }
1053
1054 ParentTable = DtPeekSubtable ();
1055 DtInsertSubtable (ParentTable, Subtable);
1056
1057 /* Main table fields */
1058
1059 Dbg2Header = ACPI_CAST_PTR (ACPI_DBG2_HEADER, Subtable->Buffer);
1060 Dbg2Header->InfoOffset = sizeof (ACPI_TABLE_HEADER) + ACPI_PTR_DIFF (
1061 ACPI_ADD_PTR (UINT8, Dbg2Header, sizeof (ACPI_DBG2_HEADER)), Dbg2Header);
1062
1063 SubtableCount = Dbg2Header->InfoCount;
1064 DtPushSubtable (Subtable);
1065
1066 /* Process all Device Information subtables (Count = InfoCount) */
1067
1068 while (*PFieldList && SubtableCount)
1069 {
1070 /* Subtable: Debug Device Information */
1071
1072 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Device,
1073 &Subtable);
1074 if (ACPI_FAILURE (Status))
1075 {
1076 return (Status);
1077 }
1078
1079 DeviceInfo = ACPI_CAST_PTR (ACPI_DBG2_DEVICE, Subtable->Buffer);
1080 CurrentOffset = (UINT16) sizeof (ACPI_DBG2_DEVICE);
1081
1082 ParentTable = DtPeekSubtable ();
1083 DtInsertSubtable (ParentTable, Subtable);
1084 DtPushSubtable (Subtable);
1085
1086 ParentTable = DtPeekSubtable ();
1087
1088 /* BaseAddressRegister GAS array (Required, size is RegisterCount) */
1089
1090 DeviceInfo->BaseAddressOffset = CurrentOffset;
1091 for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++)
1092 {
1093 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Addr,
1094 &Subtable);
1095 if (ACPI_FAILURE (Status))
1096 {
1097 return (Status);
1098 }
1099
1100 CurrentOffset += (UINT16) sizeof (ACPI_GENERIC_ADDRESS);
1101 DtInsertSubtable (ParentTable, Subtable);
1102 }
1103
1104 /* AddressSize array (Required, size = RegisterCount) */
1105
1106 DeviceInfo->AddressSizeOffset = CurrentOffset;
1107 for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++)
1108 {
1109 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Size,
1110 &Subtable);
1111 if (ACPI_FAILURE (Status))
1112 {
1113 return (Status);
1114 }
1115
1116 CurrentOffset += (UINT16) sizeof (UINT32);
1117 DtInsertSubtable (ParentTable, Subtable);
1118 }
1119
1120 /* NamespaceString device identifier (Required, size = NamePathLength) */
1121
1122 DeviceInfo->NamepathOffset = CurrentOffset;
1123 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Name,
1124 &Subtable);
1125 if (ACPI_FAILURE (Status))
1126 {
1127 return (Status);
1128 }
1129
1130 /* Update the device info header */
1131
1132 DeviceInfo->NamepathLength = (UINT16) Subtable->Length;
1133 CurrentOffset += (UINT16) DeviceInfo->NamepathLength;
1134 DtInsertSubtable (ParentTable, Subtable);
1135
1136 /* OemData - Variable-length data (Optional, size = OemDataLength) */
1137
1138 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2OemData,
1139 &Subtable);
1140 if (Status == AE_END_OF_TABLE)
1141 {
1142 /* optional field was not found and we're at the end of the file */
1143
1144 goto subtableDone;
1145 }
1146 else if (ACPI_FAILURE (Status))
1147 {
1148 return (Status);
1149 }
1150
1151 /* Update the device info header (zeros if no OEM data present) */
1152
1153 DeviceInfo->OemDataOffset = 0;
1154 DeviceInfo->OemDataLength = 0;
1155
1156 /* Optional subtable (OemData) */
1157
1158 if (Subtable && Subtable->Length)
1159 {
1160 DeviceInfo->OemDataOffset = CurrentOffset;
1161 DeviceInfo->OemDataLength = (UINT16) Subtable->Length;
1162
1163 DtInsertSubtable (ParentTable, Subtable);
1164 }
1165 subtableDone:
1166 SubtableCount--;
1167 DtPopSubtable (); /* Get next Device Information subtable */
1168 }
1169
1170 DtPopSubtable ();
1171 return (AE_OK);
1172 }
1173
1174
1175 /******************************************************************************
1176 *
1177 * FUNCTION: DtCompileDmar
1178 *
1179 * PARAMETERS: List - Current field list pointer
1180 *
1181 * RETURN: Status
1182 *
1183 * DESCRIPTION: Compile DMAR.
1184 *
1185 *****************************************************************************/
1186
1187 ACPI_STATUS
1188 DtCompileDmar (
1189 void **List)
1190 {
1191 ACPI_STATUS Status;
1192 DT_SUBTABLE *Subtable;
1193 DT_SUBTABLE *ParentTable;
1194 DT_FIELD **PFieldList = (DT_FIELD **) List;
1195 DT_FIELD *SubtableStart;
1196 ACPI_DMTABLE_INFO *InfoTable;
1197 ACPI_DMAR_HEADER *DmarHeader;
1198 ACPI_DMAR_DEVICE_SCOPE *DmarDeviceScope;
1199 UINT32 DeviceScopeLength;
1200 UINT32 PciPathLength;
1201
1202
1203 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmar, &Subtable);
1204 if (ACPI_FAILURE (Status))
1205 {
1206 return (Status);
1207 }
1208
1209 ParentTable = DtPeekSubtable ();
1210 DtInsertSubtable (ParentTable, Subtable);
1211 DtPushSubtable (Subtable);
1212
1213 while (*PFieldList)
1214 {
1215 /* DMAR Header */
1216
1217 SubtableStart = *PFieldList;
1218 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarHdr,
1219 &Subtable);
1220 if (ACPI_FAILURE (Status))
1221 {
1222 return (Status);
1223 }
1224
1225 ParentTable = DtPeekSubtable ();
1226 DtInsertSubtable (ParentTable, Subtable);
1227 DtPushSubtable (Subtable);
1228
1229 DmarHeader = ACPI_CAST_PTR (ACPI_DMAR_HEADER, Subtable->Buffer);
1230
1231 switch (DmarHeader->Type)
1232 {
1233 case ACPI_DMAR_TYPE_HARDWARE_UNIT:
1234
1235 InfoTable = AcpiDmTableInfoDmar0;
1236 break;
1237
1238 case ACPI_DMAR_TYPE_RESERVED_MEMORY:
1239
1240 InfoTable = AcpiDmTableInfoDmar1;
1241 break;
1242
1243 case ACPI_DMAR_TYPE_ROOT_ATS:
1244
1245 InfoTable = AcpiDmTableInfoDmar2;
1246 break;
1247
1248 case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
1249
1250 InfoTable = AcpiDmTableInfoDmar3;
1251 break;
1252
1253 case ACPI_DMAR_TYPE_NAMESPACE:
1254
1255 InfoTable = AcpiDmTableInfoDmar4;
1256 break;
1257
1258 case ACPI_DMAR_TYPE_SATC:
1259
1260 InfoTable = AcpiDmTableInfoDmar5;
1261 break;
1262
1263 default:
1264
1265 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "DMAR");
1266 return (AE_ERROR);
1267 }
1268
1269 /* DMAR Subtable */
1270
1271 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1272 if (ACPI_FAILURE (Status))
1273 {
1274 return (Status);
1275 }
1276
1277 ParentTable = DtPeekSubtable ();
1278 DtInsertSubtable (ParentTable, Subtable);
1279
1280 /*
1281 * Optional Device Scope subtables
1282 */
1283 if ((DmarHeader->Type == ACPI_DMAR_TYPE_HARDWARE_AFFINITY) ||
1284 (DmarHeader->Type == ACPI_DMAR_TYPE_NAMESPACE))
1285 {
1286 /* These types do not support device scopes */
1287
1288 DtPopSubtable ();
1289 continue;
1290 }
1291
1292 DtPushSubtable (Subtable);
1293 DeviceScopeLength = DmarHeader->Length - Subtable->Length -
1294 ParentTable->Length;
1295 while (DeviceScopeLength)
1296 {
1297 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarScope,
1298 &Subtable);
1299 if (Status == AE_NOT_FOUND)
1300 {
1301 break;
1302 }
1303
1304 ParentTable = DtPeekSubtable ();
1305 DtInsertSubtable (ParentTable, Subtable);
1306 DtPushSubtable (Subtable);
1307
1308 DmarDeviceScope = ACPI_CAST_PTR (ACPI_DMAR_DEVICE_SCOPE, Subtable->Buffer);
1309
1310 /* Optional PCI Paths */
1311
1312 PciPathLength = DmarDeviceScope->Length - Subtable->Length;
1313 while (PciPathLength)
1314 {
1315 Status = DtCompileTable (PFieldList, TableInfoDmarPciPath,
1316 &Subtable);
1317 if (Status == AE_NOT_FOUND)
1318 {
1319 DtPopSubtable ();
1320 break;
1321 }
1322
1323 ParentTable = DtPeekSubtable ();
1324 DtInsertSubtable (ParentTable, Subtable);
1325 PciPathLength -= Subtable->Length;
1326 }
1327
1328 DtPopSubtable ();
1329 DeviceScopeLength -= DmarDeviceScope->Length;
1330 }
1331
1332 DtPopSubtable ();
1333 DtPopSubtable ();
1334 }
1335
1336 return (AE_OK);
1337 }
1338
1339
1340 /******************************************************************************
1341 *
1342 * FUNCTION: DtCompileDrtm
1343 *
1344 * PARAMETERS: List - Current field list pointer
1345 *
1346 * RETURN: Status
1347 *
1348 * DESCRIPTION: Compile DRTM.
1349 *
1350 *****************************************************************************/
1351
1352 ACPI_STATUS
1353 DtCompileDrtm (
1354 void **List)
1355 {
1356 ACPI_STATUS Status;
1357 DT_SUBTABLE *Subtable;
1358 DT_SUBTABLE *ParentTable;
1359 DT_FIELD **PFieldList = (DT_FIELD **) List;
1360 UINT32 Count;
1361 /* ACPI_TABLE_DRTM *Drtm; */
1362 ACPI_DRTM_VTABLE_LIST *DrtmVtl;
1363 ACPI_DRTM_RESOURCE_LIST *DrtmRl;
1364 /* ACPI_DRTM_DPS_ID *DrtmDps; */
1365
1366
1367 ParentTable = DtPeekSubtable ();
1368
1369 /* Compile DRTM header */
1370
1371 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm,
1372 &Subtable);
1373 if (ACPI_FAILURE (Status))
1374 {
1375 return (Status);
1376 }
1377 DtInsertSubtable (ParentTable, Subtable);
1378
1379 /*
1380 * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
1381 * should be taken to avoid accessing ACPI_TABLE_HADER fields.
1382 */
1383 #if 0
1384 Drtm = ACPI_SUB_PTR (ACPI_TABLE_DRTM,
1385 Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
1386 #endif
1387 /* Compile VTL */
1388
1389 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0,
1390 &Subtable);
1391 if (ACPI_FAILURE (Status))
1392 {
1393 return (Status);
1394 }
1395
1396 DtInsertSubtable (ParentTable, Subtable);
1397 DrtmVtl = ACPI_CAST_PTR (ACPI_DRTM_VTABLE_LIST, Subtable->Buffer);
1398
1399 DtPushSubtable (Subtable);
1400 ParentTable = DtPeekSubtable ();
1401 Count = 0;
1402
1403 while (*PFieldList)
1404 {
1405 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0a,
1406 &Subtable);
1407 if (ACPI_FAILURE (Status))
1408 {
1409 return (Status);
1410 }
1411 if (!Subtable)
1412 {
1413 break;
1414 }
1415 DtInsertSubtable (ParentTable, Subtable);
1416 Count++;
1417 }
1418
1419 DrtmVtl->ValidatedTableCount = Count;
1420 DtPopSubtable ();
1421 ParentTable = DtPeekSubtable ();
1422
1423 /* Compile RL */
1424
1425 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1,
1426 &Subtable);
1427 if (ACPI_FAILURE (Status))
1428 {
1429 return (Status);
1430 }
1431
1432 DtInsertSubtable (ParentTable, Subtable);
1433 DrtmRl = ACPI_CAST_PTR (ACPI_DRTM_RESOURCE_LIST, Subtable->Buffer);
1434
1435 DtPushSubtable (Subtable);
1436 ParentTable = DtPeekSubtable ();
1437 Count = 0;
1438
1439 while (*PFieldList)
1440 {
1441 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1a,
1442 &Subtable);
1443 if (ACPI_FAILURE (Status))
1444 {
1445 return (Status);
1446 }
1447
1448 if (!Subtable)
1449 {
1450 break;
1451 }
1452
1453 DtInsertSubtable (ParentTable, Subtable);
1454 Count++;
1455 }
1456
1457 DrtmRl->ResourceCount = Count;
1458 DtPopSubtable ();
1459 ParentTable = DtPeekSubtable ();
1460
1461 /* Compile DPS */
1462
1463 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm2,
1464 &Subtable);
1465 if (ACPI_FAILURE (Status))
1466 {
1467 return (Status);
1468 }
1469 DtInsertSubtable (ParentTable, Subtable);
1470 /* DrtmDps = ACPI_CAST_PTR (ACPI_DRTM_DPS_ID, Subtable->Buffer);*/
1471
1472
1473 return (AE_OK);
1474 }
1475
1476
1477 /******************************************************************************
1478 *
1479 * FUNCTION: DtCompileEinj
1480 *
1481 * PARAMETERS: List - Current field list pointer
1482 *
1483 * RETURN: Status
1484 *
1485 * DESCRIPTION: Compile EINJ.
1486 *
1487 *****************************************************************************/
1488
1489 ACPI_STATUS
1490 DtCompileEinj (
1491 void **List)
1492 {
1493 ACPI_STATUS Status;
1494
1495
1496 Status = DtCompileTwoSubtables (List,
1497 AcpiDmTableInfoEinj, AcpiDmTableInfoEinj0);
1498 return (Status);
1499 }
1500
1501
1502 /******************************************************************************
1503 *
1504 * FUNCTION: DtCompileErst
1505 *
1506 * PARAMETERS: List - Current field list pointer
1507 *
1508 * RETURN: Status
1509 *
1510 * DESCRIPTION: Compile ERST.
1511 *
1512 *****************************************************************************/
1513
1514 ACPI_STATUS
1515 DtCompileErst (
1516 void **List)
1517 {
1518 ACPI_STATUS Status;
1519
1520
1521 Status = DtCompileTwoSubtables (List,
1522 AcpiDmTableInfoErst, AcpiDmTableInfoEinj0);
1523 return (Status);
1524 }
1525
1526
1527 /******************************************************************************
1528 *
1529 * FUNCTION: DtCompileGtdt
1530 *
1531 * PARAMETERS: List - Current field list pointer
1532 *
1533 * RETURN: Status
1534 *
1535 * DESCRIPTION: Compile GTDT.
1536 *
1537 *****************************************************************************/
1538
1539 ACPI_STATUS
1540 DtCompileGtdt (
1541 void **List)
1542 {
1543 ACPI_STATUS Status;
1544 DT_SUBTABLE *Subtable;
1545 DT_SUBTABLE *ParentTable;
1546 DT_FIELD **PFieldList = (DT_FIELD **) List;
1547 DT_FIELD *SubtableStart;
1548 ACPI_SUBTABLE_HEADER *GtdtHeader;
1549 ACPI_DMTABLE_INFO *InfoTable;
1550 UINT32 GtCount;
1551 ACPI_TABLE_HEADER *Header;
1552
1553
1554 ParentTable = DtPeekSubtable ();
1555
1556 Header = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer);
1557
1558 /* Compile the main table */
1559
1560 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt,
1561 &Subtable);
1562 if (ACPI_FAILURE (Status))
1563 {
1564 return (Status);
1565 }
1566
1567 /* GTDT revision 3 later contains 2 extra fields before subtables */
1568
1569 if (Header->Revision > 2)
1570 {
1571 ParentTable = DtPeekSubtable ();
1572 DtInsertSubtable (ParentTable, Subtable);
1573
1574 Status = DtCompileTable (PFieldList,
1575 AcpiDmTableInfoGtdtEl2, &Subtable);
1576 if (ACPI_FAILURE (Status))
1577 {
1578 return (Status);
1579 }
1580 }
1581
1582 ParentTable = DtPeekSubtable ();
1583 DtInsertSubtable (ParentTable, Subtable);
1584
1585 while (*PFieldList)
1586 {
1587 SubtableStart = *PFieldList;
1588 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdtHdr,
1589 &Subtable);
1590 if (ACPI_FAILURE (Status))
1591 {
1592 return (Status);
1593 }
1594
1595 ParentTable = DtPeekSubtable ();
1596 DtInsertSubtable (ParentTable, Subtable);
1597 DtPushSubtable (Subtable);
1598
1599 GtdtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer);
1600
1601 switch (GtdtHeader->Type)
1602 {
1603 case ACPI_GTDT_TYPE_TIMER_BLOCK:
1604
1605 InfoTable = AcpiDmTableInfoGtdt0;
1606 break;
1607
1608 case ACPI_GTDT_TYPE_WATCHDOG:
1609
1610 InfoTable = AcpiDmTableInfoGtdt1;
1611 break;
1612
1613 default:
1614
1615 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "GTDT");
1616 return (AE_ERROR);
1617 }
1618
1619 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1620 if (ACPI_FAILURE (Status))
1621 {
1622 return (Status);
1623 }
1624
1625 ParentTable = DtPeekSubtable ();
1626 DtInsertSubtable (ParentTable, Subtable);
1627
1628 /*
1629 * Additional GT block subtable data
1630 */
1631
1632 switch (GtdtHeader->Type)
1633 {
1634 case ACPI_GTDT_TYPE_TIMER_BLOCK:
1635
1636 DtPushSubtable (Subtable);
1637 ParentTable = DtPeekSubtable ();
1638
1639 GtCount = (ACPI_CAST_PTR (ACPI_GTDT_TIMER_BLOCK,
1640 Subtable->Buffer - sizeof(ACPI_GTDT_HEADER)))->TimerCount;
1641
1642 while (GtCount)
1643 {
1644 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt0a,
1645 &Subtable);
1646 if (ACPI_FAILURE (Status))
1647 {
1648 return (Status);
1649 }
1650
1651 DtInsertSubtable (ParentTable, Subtable);
1652 GtCount--;
1653 }
1654
1655 DtPopSubtable ();
1656 break;
1657
1658 default:
1659
1660 break;
1661 }
1662
1663 DtPopSubtable ();
1664 }
1665
1666 return (AE_OK);
1667 }
1668
1669
1670 /******************************************************************************
1671 *
1672 * FUNCTION: DtCompileFpdt
1673 *
1674 * PARAMETERS: List - Current field list pointer
1675 *
1676 * RETURN: Status
1677 *
1678 * DESCRIPTION: Compile FPDT.
1679 *
1680 *****************************************************************************/
1681
1682 ACPI_STATUS
1683 DtCompileFpdt (
1684 void **List)
1685 {
1686 ACPI_STATUS Status;
1687 ACPI_FPDT_HEADER *FpdtHeader;
1688 DT_SUBTABLE *Subtable;
1689 DT_SUBTABLE *ParentTable;
1690 ACPI_DMTABLE_INFO *InfoTable;
1691 DT_FIELD **PFieldList = (DT_FIELD **) List;
1692 DT_FIELD *SubtableStart;
1693
1694
1695 while (*PFieldList)
1696 {
1697 SubtableStart = *PFieldList;
1698 Status = DtCompileTable (PFieldList, AcpiDmTableInfoFpdtHdr,
1699 &Subtable);
1700 if (ACPI_FAILURE (Status))
1701 {
1702 return (Status);
1703 }
1704
1705 ParentTable = DtPeekSubtable ();
1706 DtInsertSubtable (ParentTable, Subtable);
1707 DtPushSubtable (Subtable);
1708
1709 FpdtHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer);
1710
1711 switch (FpdtHeader->Type)
1712 {
1713 case ACPI_FPDT_TYPE_BOOT:
1714
1715 InfoTable = AcpiDmTableInfoFpdt0;
1716 break;
1717
1718 case ACPI_FPDT_TYPE_S3PERF:
1719
1720 InfoTable = AcpiDmTableInfoFpdt1;
1721 break;
1722
1723 default:
1724
1725 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "FPDT");
1726 return (AE_ERROR);
1727 break;
1728 }
1729
1730 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1731 if (ACPI_FAILURE (Status))
1732 {
1733 return (Status);
1734 }
1735
1736 ParentTable = DtPeekSubtable ();
1737 DtInsertSubtable (ParentTable, Subtable);
1738 DtPopSubtable ();
1739 }
1740
1741 return (AE_OK);
1742 }
1743
1744
1745 /******************************************************************************
1746 *
1747 * FUNCTION: DtCompileHest
1748 *
1749 * PARAMETERS: List - Current field list pointer
1750 *
1751 * RETURN: Status
1752 *
1753 * DESCRIPTION: Compile HEST.
1754 *
1755 *****************************************************************************/
1756
1757 ACPI_STATUS
1758 DtCompileHest (
1759 void **List)
1760 {
1761 ACPI_STATUS Status;
1762 DT_SUBTABLE *Subtable;
1763 DT_SUBTABLE *ParentTable;
1764 DT_FIELD **PFieldList = (DT_FIELD **) List;
1765 DT_FIELD *SubtableStart;
1766 ACPI_DMTABLE_INFO *InfoTable;
1767 UINT16 Type;
1768 UINT32 BankCount;
1769
1770
1771 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHest,
1772 &Subtable);
1773 if (ACPI_FAILURE (Status))
1774 {
1775 return (Status);
1776 }
1777
1778 ParentTable = DtPeekSubtable ();
1779 DtInsertSubtable (ParentTable, Subtable);
1780
1781 while (*PFieldList)
1782 {
1783 /* Get subtable type */
1784
1785 SubtableStart = *PFieldList;
1786 DtCompileInteger ((UINT8 *) &Type, *PFieldList, 2, 0);
1787
1788 switch (Type)
1789 {
1790 case ACPI_HEST_TYPE_IA32_CHECK:
1791
1792 InfoTable = AcpiDmTableInfoHest0;
1793 break;
1794
1795 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
1796
1797 InfoTable = AcpiDmTableInfoHest1;
1798 break;
1799
1800 case ACPI_HEST_TYPE_IA32_NMI:
1801
1802 InfoTable = AcpiDmTableInfoHest2;
1803 break;
1804
1805 case ACPI_HEST_TYPE_AER_ROOT_PORT:
1806
1807 InfoTable = AcpiDmTableInfoHest6;
1808 break;
1809
1810 case ACPI_HEST_TYPE_AER_ENDPOINT:
1811
1812 InfoTable = AcpiDmTableInfoHest7;
1813 break;
1814
1815 case ACPI_HEST_TYPE_AER_BRIDGE:
1816
1817 InfoTable = AcpiDmTableInfoHest8;
1818 break;
1819
1820 case ACPI_HEST_TYPE_GENERIC_ERROR:
1821
1822 InfoTable = AcpiDmTableInfoHest9;
1823 break;
1824
1825 case ACPI_HEST_TYPE_GENERIC_ERROR_V2:
1826
1827 InfoTable = AcpiDmTableInfoHest10;
1828 break;
1829
1830 case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
1831
1832 InfoTable = AcpiDmTableInfoHest11;
1833 break;
1834
1835 default:
1836
1837 /* Cannot continue on unknown type */
1838
1839 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HEST");
1840 return (AE_ERROR);
1841 }
1842
1843 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1844 if (ACPI_FAILURE (Status))
1845 {
1846 return (Status);
1847 }
1848
1849 DtInsertSubtable (ParentTable, Subtable);
1850
1851 /*
1852 * Additional subtable data - IA32 Error Bank(s)
1853 */
1854 BankCount = 0;
1855 switch (Type)
1856 {
1857 case ACPI_HEST_TYPE_IA32_CHECK:
1858
1859 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK,
1860 Subtable->Buffer))->NumHardwareBanks;
1861 break;
1862
1863 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
1864
1865 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED,
1866 Subtable->Buffer))->NumHardwareBanks;
1867 break;
1868
1869 case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
1870
1871 BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_DEFERRED_CHECK,
1872 Subtable->Buffer))->NumHardwareBanks;
1873 break;
1874
1875 default:
1876
1877 break;
1878 }
1879
1880 while (BankCount)
1881 {
1882 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHestBank,
1883 &Subtable);
1884 if (ACPI_FAILURE (Status))
1885 {
1886 return (Status);
1887 }
1888
1889 DtInsertSubtable (ParentTable, Subtable);
1890 BankCount--;
1891 }
1892 }
1893
1894 return (AE_OK);
1895 }
1896
1897
1898 /******************************************************************************
1899 *
1900 * FUNCTION: DtCompileHmat
1901 *
1902 * PARAMETERS: List - Current field list pointer
1903 *
1904 * RETURN: Status
1905 *
1906 * DESCRIPTION: Compile HMAT.
1907 *
1908 *****************************************************************************/
1909
1910 ACPI_STATUS
1911 DtCompileHmat (
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 DT_FIELD *EntryStart;
1920 ACPI_HMAT_STRUCTURE *HmatStruct;
1921 ACPI_HMAT_LOCALITY *HmatLocality;
1922 ACPI_HMAT_CACHE *HmatCache;
1923 ACPI_DMTABLE_INFO *InfoTable;
1924 UINT32 IntPDNumber;
1925 UINT32 TgtPDNumber;
1926 UINT64 EntryNumber;
1927 UINT16 SMBIOSHandleNumber;
1928
1929
1930 ParentTable = DtPeekSubtable ();
1931
1932 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmat,
1933 &Subtable);
1934 if (ACPI_FAILURE (Status))
1935 {
1936 return (Status);
1937 }
1938 DtInsertSubtable (ParentTable, Subtable);
1939
1940 while (*PFieldList)
1941 {
1942 /* Compile HMAT structure header */
1943
1944 SubtableStart = *PFieldList;
1945 Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmatHdr,
1946 &Subtable);
1947 if (ACPI_FAILURE (Status))
1948 {
1949 return (Status);
1950 }
1951 DtInsertSubtable (ParentTable, Subtable);
1952
1953 HmatStruct = ACPI_CAST_PTR (ACPI_HMAT_STRUCTURE, Subtable->Buffer);
1954 HmatStruct->Length = Subtable->Length;
1955
1956 /* Compile HMAT structure body */
1957
1958 switch (HmatStruct->Type)
1959 {
1960 case ACPI_HMAT_TYPE_ADDRESS_RANGE:
1961
1962 InfoTable = AcpiDmTableInfoHmat0;
1963 break;
1964
1965 case ACPI_HMAT_TYPE_LOCALITY:
1966
1967 InfoTable = AcpiDmTableInfoHmat1;
1968 break;
1969
1970 case ACPI_HMAT_TYPE_CACHE:
1971
1972 InfoTable = AcpiDmTableInfoHmat2;
1973 break;
1974
1975 default:
1976
1977 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HMAT");
1978 return (AE_ERROR);
1979 }
1980
1981 Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1982 if (ACPI_FAILURE (Status))
1983 {
1984 return (Status);
1985 }
1986 DtInsertSubtable (ParentTable, Subtable);
1987 HmatStruct->Length += Subtable->Length;
1988
1989 /* Compile HMAT structure additional */
1990
1991 switch (HmatStruct->Type)
1992 {
1993 case ACPI_HMAT_TYPE_LOCALITY:
1994
1995 HmatLocality = ACPI_SUB_PTR (ACPI_HMAT_LOCALITY,
1996 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
1997
1998 /* Compile initiator proximity domain list */
1999
2000 IntPDNumber = 0;
2001 while (*PFieldList)
2002 {
2003 Status = DtCompileTable (PFieldList,
2004 AcpiDmTableInfoHmat1a, &Subtable);
2005 if (ACPI_FAILURE (Status))
2006 {
2007 return (Status);
2008 }
2009 if (!Subtable)
2010 {
2011 break;
2012 }
2013 DtInsertSubtable (ParentTable, Subtable);
2014 HmatStruct->Length += Subtable->Length;
2015 IntPDNumber++;
2016 }
2017 HmatLocality->NumberOfInitiatorPDs = IntPDNumber;
2018
2019 /* Compile target proximity domain list */
2020
2021 TgtPDNumber = 0;
2022 while (*PFieldList)
2023 {
2024 Status = DtCompileTable (PFieldList,
2025 AcpiDmTableInfoHmat1b, &Subtable);
2026 if (ACPI_FAILURE (Status))
2027 {
2028 return (Status);
2029 }
2030 if (!Subtable)
2031 {
2032 break;
2033 }
2034 DtInsertSubtable (ParentTable, Subtable);
2035 HmatStruct->Length += Subtable->Length;
2036 TgtPDNumber++;
2037 }
2038 HmatLocality->NumberOfTargetPDs = TgtPDNumber;
2039
2040 /* Save start of the entries for reporting errors */
2041
2042 EntryStart = *PFieldList;
2043
2044 /* Compile latency/bandwidth entries */
2045
2046 EntryNumber = 0;
2047 while (*PFieldList)
2048 {
2049 Status = DtCompileTable (PFieldList,
2050 AcpiDmTableInfoHmat1c, &Subtable);
2051 if (ACPI_FAILURE (Status))
2052 {
2053 return (Status);
2054 }
2055 if (!Subtable)
2056 {
2057 break;
2058 }
2059 DtInsertSubtable (ParentTable, Subtable);
2060 HmatStruct->Length += Subtable->Length;
2061 EntryNumber++;
2062 }
2063
2064 /* Validate number of entries */
2065
2066 if (EntryNumber !=
2067 ((UINT64)IntPDNumber * (UINT64)TgtPDNumber))
2068 {
2069 DtFatal (ASL_MSG_INVALID_EXPRESSION, EntryStart, "HMAT");
2070 return (AE_ERROR);
2071 }
2072 break;
2073
2074 case ACPI_HMAT_TYPE_CACHE:
2075
2076 /* Compile SMBIOS handles */
2077
2078 HmatCache = ACPI_SUB_PTR (ACPI_HMAT_CACHE,
2079 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
2080 SMBIOSHandleNumber = 0;
2081 while (*PFieldList)
2082 {
2083 Status = DtCompileTable (PFieldList,
2084 AcpiDmTableInfoHmat2a, &Subtable);
2085 if (ACPI_FAILURE (Status))
2086 {
2087 return (Status);
2088 }
2089 if (!Subtable)
2090 {
2091 break;
2092 }
2093 DtInsertSubtable (ParentTable, Subtable);
2094 HmatStruct->Length += Subtable->Length;
2095 SMBIOSHandleNumber++;
2096 }
2097 HmatCache->NumberOfSMBIOSHandles = SMBIOSHandleNumber;
2098 break;
2099
2100 default:
2101
2102 break;
2103 }
2104 }
2105
2106 return (AE_OK);
2107 }
2108
2109
2110 /******************************************************************************
2111 *
2112 * FUNCTION: DtCompileIort
2113 *
2114 * PARAMETERS: List - Current field list pointer
2115 *
2116 * RETURN: Status
2117 *
2118 * DESCRIPTION: Compile IORT.
2119 *
2120 *****************************************************************************/
2121
2122 ACPI_STATUS
2123 DtCompileIort (
2124 void **List)
2125 {
2126 ACPI_STATUS Status;
2127 DT_SUBTABLE *Subtable;
2128 DT_SUBTABLE *ParentTable;
2129 DT_FIELD **PFieldList = (DT_FIELD **) List;
2130 DT_FIELD *SubtableStart;
2131 ACPI_TABLE_HEADER *Table;
2132 ACPI_TABLE_IORT *Iort;
2133 ACPI_IORT_NODE *IortNode;
2134 ACPI_IORT_ITS_GROUP *IortItsGroup;
2135 ACPI_IORT_SMMU *IortSmmu;
2136 ACPI_IORT_RMR *IortRmr;
2137 UINT32 NodeNumber;
2138 UINT32 NodeLength;
2139 UINT32 IdMappingNumber;
2140 UINT32 ItsNumber;
2141 UINT32 ContextIrptNumber;
2142 UINT32 PmuIrptNumber;
2143 UINT32 PaddingLength;
2144 UINT8 Revision;
2145 UINT32 RmrCount;
2146
2147
2148 ParentTable = DtPeekSubtable ();
2149
2150 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort,
2151 &Subtable);
2152 if (ACPI_FAILURE (Status))
2153 {
2154 return (Status);
2155 }
2156 DtInsertSubtable (ParentTable, Subtable);
2157
2158 Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer);
2159 Revision = Table->Revision;
2160
2161 /* IORT Revisions E, E.a & E.c have known issues and are not supported */
2162
2163 if (Revision == 1 || Revision == 2 || Revision == 4)
2164 {
2165 DtError (ASL_ERROR, ASL_MSG_UNSUPPORTED, NULL, "IORT table revision");
2166 return (AE_ERROR);
2167 }
2168
2169 /*
2170 * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
2171 * should be taken to avoid accessing ACPI_TABLE_HEADER fields.
2172 */
2173 Iort = ACPI_SUB_PTR (ACPI_TABLE_IORT,
2174 Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
2175
2176 /*
2177 * OptionalPadding - Variable-length data
2178 * (Optional, size = OffsetToNodes - sizeof (ACPI_TABLE_IORT))
2179 * Optionally allows the generic data types to be used for filling
2180 * this field.
2181 */
2182 Iort->NodeOffset = sizeof (ACPI_TABLE_IORT);
2183 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortPad,
2184 &Subtable);
2185 if (ACPI_FAILURE (Status))
2186 {
2187 return (Status);
2188 }
2189 if (Subtable)
2190 {
2191 DtInsertSubtable (ParentTable, Subtable);
2192 Iort->NodeOffset += Subtable->Length;
2193 }
2194 else
2195 {
2196 Status = DtCompileGeneric (ACPI_CAST_PTR (void *, PFieldList),
2197 AcpiDmTableInfoIortHdr[0].Name, &PaddingLength);
2198 if (ACPI_FAILURE (Status))
2199 {
2200 return (Status);
2201 }
2202 Iort->NodeOffset += PaddingLength;
2203 }
2204
2205 NodeNumber = 0;
2206 while (*PFieldList)
2207 {
2208 SubtableStart = *PFieldList;
2209 if (Revision == 0)
2210 {
2211 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr,
2212 &Subtable);
2213 }
2214 else if (Revision >= 3)
2215 {
2216 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr3,
2217 &Subtable);
2218 }
2219
2220 if (ACPI_FAILURE (Status))
2221 {
2222 return (Status);
2223 }
2224
2225 DtInsertSubtable (ParentTable, Subtable);
2226 IortNode = ACPI_CAST_PTR (ACPI_IORT_NODE, Subtable->Buffer);
2227 NodeLength = ACPI_OFFSET (ACPI_IORT_NODE, NodeData);
2228
2229 DtPushSubtable (Subtable);
2230 ParentTable = DtPeekSubtable ();
2231
2232 switch (IortNode->Type)
2233 {
2234 case ACPI_IORT_NODE_ITS_GROUP:
2235
2236 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0,
2237 &Subtable);
2238 if (ACPI_FAILURE (Status))
2239 {
2240 return (Status);
2241 }
2242
2243 DtInsertSubtable (ParentTable, Subtable);
2244 IortItsGroup = ACPI_CAST_PTR (ACPI_IORT_ITS_GROUP, Subtable->Buffer);
2245 NodeLength += Subtable->Length;
2246
2247 ItsNumber = 0;
2248 while (*PFieldList)
2249 {
2250 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0a,
2251 &Subtable);
2252 if (ACPI_FAILURE (Status))
2253 {
2254 return (Status);
2255 }
2256 if (!Subtable)
2257 {
2258 break;
2259 }
2260
2261 DtInsertSubtable (ParentTable, Subtable);
2262 NodeLength += Subtable->Length;
2263 ItsNumber++;
2264 }
2265
2266 IortItsGroup->ItsCount = ItsNumber;
2267 break;
2268
2269 case ACPI_IORT_NODE_NAMED_COMPONENT:
2270
2271 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1,
2272 &Subtable);
2273 if (ACPI_FAILURE (Status))
2274 {
2275 return (Status);
2276 }
2277
2278 DtInsertSubtable (ParentTable, Subtable);
2279 NodeLength += Subtable->Length;
2280
2281 /*
2282 * Padding - Variable-length data
2283 * Optionally allows the offset of the ID mappings to be used
2284 * for filling this field.
2285 */
2286 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1a,
2287 &Subtable);
2288 if (ACPI_FAILURE (Status))
2289 {
2290 return (Status);
2291 }
2292
2293 if (Subtable)
2294 {
2295 DtInsertSubtable (ParentTable, Subtable);
2296 NodeLength += Subtable->Length;
2297 }
2298 else
2299 {
2300 if (NodeLength > IortNode->MappingOffset)
2301 {
2302 return (AE_BAD_DATA);
2303 }
2304
2305 if (NodeLength < IortNode->MappingOffset)
2306 {
2307 Status = DtCompilePadding (
2308 IortNode->MappingOffset - NodeLength,
2309 &Subtable);
2310 if (ACPI_FAILURE (Status))
2311 {
2312 return (Status);
2313 }
2314
2315 DtInsertSubtable (ParentTable, Subtable);
2316 NodeLength = IortNode->MappingOffset;
2317 }
2318 }
2319 break;
2320
2321 case ACPI_IORT_NODE_PCI_ROOT_COMPLEX:
2322
2323 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort2,
2324 &Subtable);
2325 if (ACPI_FAILURE (Status))
2326 {
2327 return (Status);
2328 }
2329
2330 DtInsertSubtable (ParentTable, Subtable);
2331 NodeLength += Subtable->Length;
2332 break;
2333
2334 case ACPI_IORT_NODE_SMMU:
2335
2336 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3,
2337 &Subtable);
2338 if (ACPI_FAILURE (Status))
2339 {
2340 return (Status);
2341 }
2342
2343 DtInsertSubtable (ParentTable, Subtable);
2344 IortSmmu = ACPI_CAST_PTR (ACPI_IORT_SMMU, Subtable->Buffer);
2345 NodeLength += Subtable->Length;
2346
2347 /* Compile global interrupt array */
2348
2349 IortSmmu->GlobalInterruptOffset = NodeLength;
2350 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3a,
2351 &Subtable);
2352 if (ACPI_FAILURE (Status))
2353 {
2354 return (Status);
2355 }
2356
2357 DtInsertSubtable (ParentTable, Subtable);
2358 NodeLength += Subtable->Length;
2359
2360 /* Compile context interrupt array */
2361
2362 ContextIrptNumber = 0;
2363 IortSmmu->ContextInterruptOffset = NodeLength;
2364 while (*PFieldList)
2365 {
2366 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3b,
2367 &Subtable);
2368 if (ACPI_FAILURE (Status))
2369 {
2370 return (Status);
2371 }
2372
2373 if (!Subtable)
2374 {
2375 break;
2376 }
2377
2378 DtInsertSubtable (ParentTable, Subtable);
2379 NodeLength += Subtable->Length;
2380 ContextIrptNumber++;
2381 }
2382
2383 IortSmmu->ContextInterruptCount = ContextIrptNumber;
2384
2385 /* Compile PMU interrupt array */
2386
2387 PmuIrptNumber = 0;
2388 IortSmmu->PmuInterruptOffset = NodeLength;
2389 while (*PFieldList)
2390 {
2391 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3c,
2392 &Subtable);
2393 if (ACPI_FAILURE (Status))
2394 {
2395 return (Status);
2396 }
2397
2398 if (!Subtable)
2399 {
2400 break;
2401 }
2402
2403 DtInsertSubtable (ParentTable, Subtable);
2404 NodeLength += Subtable->Length;
2405 PmuIrptNumber++;
2406 }
2407
2408 IortSmmu->PmuInterruptCount = PmuIrptNumber;
2409 break;
2410
2411 case ACPI_IORT_NODE_SMMU_V3:
2412
2413 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort4,
2414 &Subtable);
2415 if (ACPI_FAILURE (Status))
2416 {
2417 return (Status);
2418 }
2419
2420 DtInsertSubtable (ParentTable, Subtable);
2421 NodeLength += Subtable->Length;
2422 break;
2423
2424 case ACPI_IORT_NODE_PMCG:
2425
2426 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort5,
2427 &Subtable);
2428 if (ACPI_FAILURE (Status))
2429 {
2430 return (Status);
2431 }
2432
2433 DtInsertSubtable (ParentTable, Subtable);
2434 NodeLength += Subtable->Length;
2435 break;
2436
2437 case ACPI_IORT_NODE_RMR:
2438
2439 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6,
2440 &Subtable);
2441 if (ACPI_FAILURE (Status))
2442 {
2443 return (Status);
2444 }
2445
2446 DtInsertSubtable (ParentTable, Subtable);
2447 IortRmr = ACPI_CAST_PTR (ACPI_IORT_RMR, Subtable->Buffer);
2448 NodeLength += Subtable->Length;
2449
2450 /* Compile RMR Descriptors */
2451
2452 RmrCount = 0;
2453 IortRmr->RmrOffset = NodeLength;
2454 while (*PFieldList)
2455 {
2456 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6a,
2457 &Subtable);
2458 if (ACPI_FAILURE (Status))
2459 {
2460 return (Status);
2461 }
2462
2463 if (!Subtable)
2464 {
2465 break;
2466 }
2467
2468 DtInsertSubtable (ParentTable, Subtable);
2469 NodeLength += sizeof (ACPI_IORT_RMR_DESC);
2470 RmrCount++;
2471 }
2472
2473 IortRmr->RmrCount = RmrCount;
2474 break;
2475
2476 default:
2477
2478 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IORT");
2479 return (AE_ERROR);
2480 }
2481
2482 /* Compile Array of ID mappings */
2483
2484 IortNode->MappingOffset = NodeLength;
2485 IdMappingNumber = 0;
2486 while (*PFieldList)
2487 {
2488 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortMap,
2489 &Subtable);
2490 if (ACPI_FAILURE (Status))
2491 {
2492 return (Status);
2493 }
2494
2495 if (!Subtable)
2496 {
2497 break;
2498 }
2499
2500 DtInsertSubtable (ParentTable, Subtable);
2501 NodeLength += sizeof (ACPI_IORT_ID_MAPPING);
2502 IdMappingNumber++;
2503 }
2504
2505 IortNode->MappingCount = IdMappingNumber;
2506 if (!IdMappingNumber)
2507 {
2508 IortNode->MappingOffset = 0;
2509 }
2510
2511 /*
2512 * Node length can be determined by DT_LENGTH option
2513 * IortNode->Length = NodeLength;
2514 */
2515 DtPopSubtable ();
2516 ParentTable = DtPeekSubtable ();
2517 NodeNumber++;
2518 }
2519
2520 Iort->NodeCount = NodeNumber;
2521 return (AE_OK);
2522 }
2523
2524
2525 /******************************************************************************
2526 *
2527 * FUNCTION: DtCompileIvrs
2528 *
2529 * PARAMETERS: List - Current field list pointer
2530 *
2531 * RETURN: Status
2532 *
2533 * DESCRIPTION: Compile IVRS. Notes:
2534 * The IVRS is essentially a flat table, with the following
2535 * structure:
2536 * <Main ACPI Table Header>
2537 * <Main subtable - virtualization info>
2538 * <IVHD>
2539 * <Device Entries>
2540 * ...
2541 * <IVHD>
2542 * <Device Entries>
2543 * <IVMD>
2544 * ...
2545 *
2546 *****************************************************************************/
2547
2548 ACPI_STATUS
2549 DtCompileIvrs (
2550 void **List)
2551 {
2552 ACPI_STATUS Status;
2553 DT_SUBTABLE *Subtable;
2554 DT_SUBTABLE *ParentTable;
2555 DT_SUBTABLE *MainSubtable;
2556 DT_FIELD **PFieldList = (DT_FIELD **) List;
2557 DT_FIELD *SubtableStart;
2558 ACPI_DMTABLE_INFO *InfoTable = NULL;
2559 UINT8 SubtableType;
2560 UINT8 Temp64[16];
2561 UINT8 Temp8;
2562
2563
2564 /* Main table */
2565
2566 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrs,
2567 &Subtable);
2568 if (ACPI_FAILURE (Status))
2569 {
2570 return (Status);
2571 }
2572
2573 ParentTable = DtPeekSubtable ();
2574 DtInsertSubtable (ParentTable, Subtable);
2575 DtPushSubtable (Subtable);
2576
2577 /* Save a pointer to the main subtable */
2578
2579 MainSubtable = Subtable;
2580
2581 while (*PFieldList)
2582 {
2583 SubtableStart = *PFieldList;
2584
2585 /* Compile the SubtableType integer */
2586
2587 DtCompileInteger (&SubtableType, *PFieldList, 1, 0);
2588
2589 switch (SubtableType)
2590 {
2591
2592 /* Type 10h, IVHD (I/O Virtualization Hardware Definition) */
2593
2594 case ACPI_IVRS_TYPE_HARDWARE1:
2595
2596 InfoTable = AcpiDmTableInfoIvrsHware1;
2597 break;
2598
2599 /* Types 11h, 40h, IVHD (I/O Virtualization Hardware Definition) */
2600
2601 case ACPI_IVRS_TYPE_HARDWARE2:
2602 case ACPI_IVRS_TYPE_HARDWARE3:
2603
2604 InfoTable = AcpiDmTableInfoIvrsHware23;
2605 break;
2606
2607 /* Types 20h, 21h, 22h, IVMD (I/O Virtualization Memory Definition Block) */
2608
2609 case ACPI_IVRS_TYPE_MEMORY1:
2610 case ACPI_IVRS_TYPE_MEMORY2:
2611 case ACPI_IVRS_TYPE_MEMORY3:
2612
2613 InfoTable = AcpiDmTableInfoIvrsMemory;
2614 break;
2615
2616 /* 4-byte device entries */
2617
2618 case ACPI_IVRS_TYPE_PAD4:
2619 case ACPI_IVRS_TYPE_ALL:
2620 case ACPI_IVRS_TYPE_SELECT:
2621 case ACPI_IVRS_TYPE_START:
2622 case ACPI_IVRS_TYPE_END:
2623
2624 InfoTable = AcpiDmTableInfoIvrs4;
2625 break;
2626
2627 /* 8-byte device entries, type A */
2628
2629 case ACPI_IVRS_TYPE_ALIAS_SELECT:
2630 case ACPI_IVRS_TYPE_ALIAS_START:
2631
2632 InfoTable = AcpiDmTableInfoIvrs8a;
2633 break;
2634
2635 /* 8-byte device entries, type B */
2636
2637 case ACPI_IVRS_TYPE_EXT_SELECT:
2638 case ACPI_IVRS_TYPE_EXT_START:
2639
2640 InfoTable = AcpiDmTableInfoIvrs8b;
2641 break;
2642
2643 /* 8-byte device entries, type C */
2644
2645 case ACPI_IVRS_TYPE_SPECIAL:
2646
2647 InfoTable = AcpiDmTableInfoIvrs8c;
2648 break;
2649
2650 /* Variable device entries, type F0h */
2651
2652 case ACPI_IVRS_TYPE_HID:
2653
2654 InfoTable = AcpiDmTableInfoIvrsHid;
2655 break;
2656
2657 default:
2658
2659 DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart,
2660 "IVRS Device Entry");
2661 return (AE_ERROR);
2662 }
2663
2664 /* Compile the InfoTable from above */
2665
2666 Status = DtCompileTable (PFieldList, InfoTable,
2667 &Subtable);
2668 if (ACPI_FAILURE (Status))
2669 {
2670 return (Status);
2671 }
2672
2673 ParentTable = DtPeekSubtable ();
2674 if (SubtableType != ACPI_IVRS_TYPE_HARDWARE1 &&
2675 SubtableType != ACPI_IVRS_TYPE_HARDWARE2 &&
2676 SubtableType != ACPI_IVRS_TYPE_HARDWARE3 &&
2677 SubtableType != ACPI_IVRS_TYPE_HID &&
2678 SubtableType != ACPI_IVRS_TYPE_MEMORY1 &&
2679 SubtableType != ACPI_IVRS_TYPE_MEMORY2 &&
2680 SubtableType != ACPI_IVRS_TYPE_MEMORY3)
2681 {
2682 if (ParentTable)
2683 DtInsertSubtable (ParentTable, Subtable);
2684 }
2685
2686 switch (SubtableType)
2687 {
2688 case ACPI_IVRS_TYPE_HARDWARE1:
2689 case ACPI_IVRS_TYPE_HARDWARE2:
2690 case ACPI_IVRS_TYPE_HARDWARE3:
2691 case ACPI_IVRS_TYPE_MEMORY1:
2692 case ACPI_IVRS_TYPE_MEMORY2:
2693 case ACPI_IVRS_TYPE_MEMORY3:
2694
2695 /* Insert these IVHDs/IVMDs at the root subtable */
2696
2697 DtInsertSubtable (MainSubtable, Subtable);
2698 DtPushSubtable (Subtable);
2699 break;
2700
2701 case ACPI_IVRS_TYPE_HID:
2702
2703 /* Special handling for the HID named device entry (0xF0) */
2704
2705 if (ParentTable)
2706 {
2707 DtInsertSubtable (ParentTable, Subtable);
2708 }
2709
2710 /*
2711 * Process the HID value. First, get the HID value as a string.
2712 */
2713 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0);
2714
2715 /*
2716 * Determine if the HID is an integer or a string.
2717 * An integer is defined to be 32 bits, with the upper 32 bits
2718 * set to zero. (from the ACPI Spec): "The HID can be a 32-bit
2719 * integer or a character string. If an integer, the lower
2720 * 4 bytes of the field contain the integer and the upper
2721 * 4 bytes are padded with 0".
2722 */
2723 if (UtIsIdInteger ((UINT8 *) &Temp64))
2724 {
2725 /* Compile the HID value as an integer */
2726
2727 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0);
2728
2729 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidInteger,
2730 &Subtable);
2731 if (ACPI_FAILURE (Status))
2732 {
2733 return (Status);
2734 }
2735 }
2736 else
2737 {
2738 /* Compile the HID value as a string */
2739
2740 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidString,
2741 &Subtable);
2742 if (ACPI_FAILURE (Status))
2743 {
2744 return (Status);
2745 }
2746 }
2747
2748 DtInsertSubtable (ParentTable, Subtable);
2749
2750 /*
2751 * Process the CID value. First, get the CID value as a string.
2752 */
2753 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0);
2754
2755 if (UtIsIdInteger ((UINT8 *) &Temp64))
2756 {
2757 /* Compile the CID value as an integer */
2758
2759 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0);
2760
2761 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidInteger,
2762 &Subtable);
2763 if (ACPI_FAILURE (Status))
2764 {
2765 return (Status);
2766 }
2767 }
2768 else
2769 {
2770 /* Compile the CID value as a string */
2771
2772 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidString,
2773 &Subtable);
2774 if (ACPI_FAILURE (Status))
2775 {
2776 return (Status);
2777 }
2778 }
2779
2780 DtInsertSubtable (ParentTable, Subtable);
2781
2782 /*
2783 * Process the UID value. First, get and decode the "UID Format" field (Integer).
2784 */
2785 if (!*PFieldList)
2786 {
2787 return (AE_OK);
2788 }
2789
2790 DtCompileOneField (&Temp8, *PFieldList, 1, DT_FIELD_TYPE_INTEGER, 0);
2791
2792 switch (Temp8)
2793 {
2794 case ACPI_IVRS_UID_NOT_PRESENT:
2795 break;
2796
2797 case ACPI_IVRS_UID_IS_INTEGER:
2798
2799 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidInteger,
2800 &Subtable);
2801 if (ACPI_FAILURE (Status))
2802 {
2803 return (Status);
2804 }
2805 DtInsertSubtable (ParentTable, Subtable);
2806 break;
2807
2808 case ACPI_IVRS_UID_IS_STRING:
2809
2810 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidString,
2811 &Subtable);
2812 if (ACPI_FAILURE (Status))
2813 {
2814 return (Status);
2815 }
2816 DtInsertSubtable (ParentTable, Subtable);
2817 break;
2818
2819 default:
2820
2821 DtFatal (ASL_MSG_UNKNOWN_FORMAT, SubtableStart,
2822 "IVRS Device Entry");
2823 return (AE_ERROR);
2824 }
2825
2826 default:
2827
2828 /* All other subtable types come through here */
2829 break;
2830 }
2831 }
2832
2833 return (AE_OK);
2834 }
2835