xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/dttable1.c (revision ccd9df534e375a4366c5b55f23782053c7a98d82)
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