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