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