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