xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/dttable1.c (revision 796c32c94f6e154afc9de0f63da35c91bb739b45)
1 /******************************************************************************
2  *
3  * Module Name: dttable1.c - handling for specific ACPI tables
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2017, 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 MERCHANTIBILITY 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:    DtCompileAsf
68  *
69  * PARAMETERS:  List                - Current field list pointer
70  *
71  * RETURN:      Status
72  *
73  * DESCRIPTION: Compile ASF!.
74  *
75  *****************************************************************************/
76 
77 ACPI_STATUS
78 DtCompileAsf (
79     void                    **List)
80 {
81     ACPI_ASF_INFO           *AsfTable;
82     DT_SUBTABLE             *Subtable;
83     DT_SUBTABLE             *ParentTable;
84     ACPI_DMTABLE_INFO       *InfoTable;
85     ACPI_DMTABLE_INFO       *DataInfoTable = NULL;
86     UINT32                  DataCount = 0;
87     ACPI_STATUS             Status;
88     UINT32                  i;
89     DT_FIELD                **PFieldList = (DT_FIELD **) List;
90     DT_FIELD                *SubtableStart;
91 
92 
93     while (*PFieldList)
94     {
95         SubtableStart = *PFieldList;
96         Status = DtCompileTable (PFieldList, AcpiDmTableInfoAsfHdr,
97             &Subtable, TRUE);
98         if (ACPI_FAILURE (Status))
99         {
100             return (Status);
101         }
102 
103         ParentTable = DtPeekSubtable ();
104         DtInsertSubtable (ParentTable, Subtable);
105         DtPushSubtable (Subtable);
106 
107         AsfTable = ACPI_CAST_PTR (ACPI_ASF_INFO, Subtable->Buffer);
108 
109         switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */
110         {
111         case ACPI_ASF_TYPE_INFO:
112 
113             InfoTable = AcpiDmTableInfoAsf0;
114             break;
115 
116         case ACPI_ASF_TYPE_ALERT:
117 
118             InfoTable = AcpiDmTableInfoAsf1;
119             break;
120 
121         case ACPI_ASF_TYPE_CONTROL:
122 
123             InfoTable = AcpiDmTableInfoAsf2;
124             break;
125 
126         case ACPI_ASF_TYPE_BOOT:
127 
128             InfoTable = AcpiDmTableInfoAsf3;
129             break;
130 
131         case ACPI_ASF_TYPE_ADDRESS:
132 
133             InfoTable = AcpiDmTableInfoAsf4;
134             break;
135 
136         default:
137 
138             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!");
139             return (AE_ERROR);
140         }
141 
142         Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
143         if (ACPI_FAILURE (Status))
144         {
145             return (Status);
146         }
147 
148         ParentTable = DtPeekSubtable ();
149         DtInsertSubtable (ParentTable, Subtable);
150 
151         switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */
152         {
153         case ACPI_ASF_TYPE_INFO:
154 
155             DataInfoTable = NULL;
156             break;
157 
158         case ACPI_ASF_TYPE_ALERT:
159 
160             DataInfoTable = AcpiDmTableInfoAsf1a;
161             DataCount = ACPI_CAST_PTR (ACPI_ASF_ALERT,
162                 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
163                     sizeof (ACPI_ASF_HEADER)))->Alerts;
164             break;
165 
166         case ACPI_ASF_TYPE_CONTROL:
167 
168             DataInfoTable = AcpiDmTableInfoAsf2a;
169             DataCount = ACPI_CAST_PTR (ACPI_ASF_REMOTE,
170                 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
171                     sizeof (ACPI_ASF_HEADER)))->Controls;
172             break;
173 
174         case ACPI_ASF_TYPE_BOOT:
175 
176             DataInfoTable = NULL;
177             break;
178 
179         case ACPI_ASF_TYPE_ADDRESS:
180 
181             DataInfoTable = TableInfoAsfAddress;
182             DataCount = ACPI_CAST_PTR (ACPI_ASF_ADDRESS,
183                 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
184                     sizeof (ACPI_ASF_HEADER)))->Devices;
185             break;
186 
187         default:
188 
189             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!");
190             return (AE_ERROR);
191         }
192 
193         if (DataInfoTable)
194         {
195             switch (AsfTable->Header.Type & 0x7F)
196             {
197             case ACPI_ASF_TYPE_ADDRESS:
198 
199                 while (DataCount > 0)
200                 {
201                     Status = DtCompileTable (PFieldList, DataInfoTable,
202                         &Subtable, TRUE);
203                     if (ACPI_FAILURE (Status))
204                     {
205                         return (Status);
206                     }
207 
208                     DtInsertSubtable (ParentTable, Subtable);
209                     DataCount = DataCount - Subtable->Length;
210                 }
211                 break;
212 
213             default:
214 
215                 for (i = 0; i < DataCount; i++)
216                 {
217                     Status = DtCompileTable (PFieldList, DataInfoTable,
218                         &Subtable, TRUE);
219                     if (ACPI_FAILURE (Status))
220                     {
221                         return (Status);
222                     }
223 
224                     DtInsertSubtable (ParentTable, Subtable);
225                 }
226                 break;
227             }
228         }
229 
230         DtPopSubtable ();
231     }
232 
233     return (AE_OK);
234 }
235 
236 
237 /******************************************************************************
238  *
239  * FUNCTION:    DtCompileCpep
240  *
241  * PARAMETERS:  List                - Current field list pointer
242  *
243  * RETURN:      Status
244  *
245  * DESCRIPTION: Compile CPEP.
246  *
247  *****************************************************************************/
248 
249 ACPI_STATUS
250 DtCompileCpep (
251     void                    **List)
252 {
253     ACPI_STATUS             Status;
254 
255 
256     Status = DtCompileTwoSubtables (List,
257         AcpiDmTableInfoCpep, AcpiDmTableInfoCpep0);
258     return (Status);
259 }
260 
261 
262 /******************************************************************************
263  *
264  * FUNCTION:    DtCompileCsrt
265  *
266  * PARAMETERS:  List                - Current field list pointer
267  *
268  * RETURN:      Status
269  *
270  * DESCRIPTION: Compile CSRT.
271  *
272  *****************************************************************************/
273 
274 ACPI_STATUS
275 DtCompileCsrt (
276     void                    **List)
277 {
278     ACPI_STATUS             Status = AE_OK;
279     DT_SUBTABLE             *Subtable;
280     DT_SUBTABLE             *ParentTable;
281     DT_FIELD                **PFieldList = (DT_FIELD **) List;
282     UINT32                  DescriptorCount;
283     UINT32                  GroupLength;
284 
285 
286     /* Subtables (Resource Groups) */
287 
288     ParentTable = DtPeekSubtable ();
289     while (*PFieldList)
290     {
291         /* Resource group subtable */
292 
293         Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt0,
294             &Subtable, TRUE);
295         if (ACPI_FAILURE (Status))
296         {
297             return (Status);
298         }
299 
300         /* Compute the number of resource descriptors */
301 
302         GroupLength =
303             (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
304                 Subtable->Buffer))->Length -
305             (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
306                 Subtable->Buffer))->SharedInfoLength -
307             sizeof (ACPI_CSRT_GROUP);
308 
309         DescriptorCount = (GroupLength  /
310             sizeof (ACPI_CSRT_DESCRIPTOR));
311 
312         DtInsertSubtable (ParentTable, Subtable);
313         DtPushSubtable (Subtable);
314         ParentTable = DtPeekSubtable ();
315 
316         /* Shared info subtable (One per resource group) */
317 
318         Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt1,
319             &Subtable, TRUE);
320         if (ACPI_FAILURE (Status))
321         {
322             return (Status);
323         }
324 
325         DtInsertSubtable (ParentTable, Subtable);
326 
327         /* Sub-Subtables (Resource Descriptors) */
328 
329         while (*PFieldList && DescriptorCount)
330         {
331 
332             Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2,
333                 &Subtable, TRUE);
334             if (ACPI_FAILURE (Status))
335             {
336                 return (Status);
337             }
338 
339             DtInsertSubtable (ParentTable, Subtable);
340 
341             DtPushSubtable (Subtable);
342             ParentTable = DtPeekSubtable ();
343             if (*PFieldList)
344             {
345                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2a,
346                     &Subtable, TRUE);
347                 if (ACPI_FAILURE (Status))
348                 {
349                     return (Status);
350                 }
351                 if (Subtable)
352                 {
353                     DtInsertSubtable (ParentTable, Subtable);
354                 }
355             }
356 
357             DtPopSubtable ();
358             ParentTable = DtPeekSubtable ();
359             DescriptorCount--;
360         }
361 
362         DtPopSubtable ();
363         ParentTable = DtPeekSubtable ();
364     }
365 
366     return (Status);
367 }
368 
369 
370 /******************************************************************************
371  *
372  * FUNCTION:    DtCompileDbg2
373  *
374  * PARAMETERS:  List                - Current field list pointer
375  *
376  * RETURN:      Status
377  *
378  * DESCRIPTION: Compile DBG2.
379  *
380  *****************************************************************************/
381 
382 ACPI_STATUS
383 DtCompileDbg2 (
384     void                    **List)
385 {
386     ACPI_STATUS             Status;
387     DT_SUBTABLE             *Subtable;
388     DT_SUBTABLE             *ParentTable;
389     DT_FIELD                **PFieldList = (DT_FIELD **) List;
390     UINT32                  SubtableCount;
391     ACPI_DBG2_HEADER        *Dbg2Header;
392     ACPI_DBG2_DEVICE        *DeviceInfo;
393     UINT16                  CurrentOffset;
394     UINT32                  i;
395 
396 
397     /* Main table */
398 
399     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2, &Subtable, TRUE);
400     if (ACPI_FAILURE (Status))
401     {
402         return (Status);
403     }
404 
405     ParentTable = DtPeekSubtable ();
406     DtInsertSubtable (ParentTable, Subtable);
407 
408     /* Main table fields */
409 
410     Dbg2Header = ACPI_CAST_PTR (ACPI_DBG2_HEADER, Subtable->Buffer);
411     Dbg2Header->InfoOffset = sizeof (ACPI_TABLE_HEADER) + ACPI_PTR_DIFF (
412         ACPI_ADD_PTR (UINT8, Dbg2Header, sizeof (ACPI_DBG2_HEADER)), Dbg2Header);
413 
414     SubtableCount = Dbg2Header->InfoCount;
415     DtPushSubtable (Subtable);
416 
417     /* Process all Device Information subtables (Count = InfoCount) */
418 
419     while (*PFieldList && SubtableCount)
420     {
421         /* Subtable: Debug Device Information */
422 
423         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Device,
424             &Subtable, TRUE);
425         if (ACPI_FAILURE (Status))
426         {
427             return (Status);
428         }
429 
430         DeviceInfo = ACPI_CAST_PTR (ACPI_DBG2_DEVICE, Subtable->Buffer);
431         CurrentOffset = (UINT16) sizeof (ACPI_DBG2_DEVICE);
432 
433         ParentTable = DtPeekSubtable ();
434         DtInsertSubtable (ParentTable, Subtable);
435         DtPushSubtable (Subtable);
436 
437         ParentTable = DtPeekSubtable ();
438 
439         /* BaseAddressRegister GAS array (Required, size is RegisterCount) */
440 
441         DeviceInfo->BaseAddressOffset = CurrentOffset;
442         for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++)
443         {
444             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Addr,
445                 &Subtable, TRUE);
446             if (ACPI_FAILURE (Status))
447             {
448                 return (Status);
449             }
450 
451             CurrentOffset += (UINT16) sizeof (ACPI_GENERIC_ADDRESS);
452             DtInsertSubtable (ParentTable, Subtable);
453         }
454 
455         /* AddressSize array (Required, size = RegisterCount) */
456 
457         DeviceInfo->AddressSizeOffset = CurrentOffset;
458         for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++)
459         {
460             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Size,
461                 &Subtable, TRUE);
462             if (ACPI_FAILURE (Status))
463             {
464                 return (Status);
465             }
466 
467             CurrentOffset += (UINT16) sizeof (UINT32);
468             DtInsertSubtable (ParentTable, Subtable);
469         }
470 
471         /* NamespaceString device identifier (Required, size = NamePathLength) */
472 
473         DeviceInfo->NamepathOffset = CurrentOffset;
474         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Name,
475             &Subtable, TRUE);
476         if (ACPI_FAILURE (Status))
477         {
478             return (Status);
479         }
480 
481         /* Update the device info header */
482 
483         DeviceInfo->NamepathLength = (UINT16) Subtable->Length;
484         CurrentOffset += (UINT16) DeviceInfo->NamepathLength;
485         DtInsertSubtable (ParentTable, Subtable);
486 
487         /* OemData - Variable-length data (Optional, size = OemDataLength) */
488 
489         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2OemData,
490             &Subtable, TRUE);
491         if (ACPI_FAILURE (Status))
492         {
493             return (Status);
494         }
495 
496         /* Update the device info header (zeros if no OEM data present) */
497 
498         DeviceInfo->OemDataOffset = 0;
499         DeviceInfo->OemDataLength = 0;
500 
501         /* Optional subtable (OemData) */
502 
503         if (Subtable && Subtable->Length)
504         {
505             DeviceInfo->OemDataOffset = CurrentOffset;
506             DeviceInfo->OemDataLength = (UINT16) Subtable->Length;
507 
508             DtInsertSubtable (ParentTable, Subtable);
509         }
510 
511         SubtableCount--;
512         DtPopSubtable (); /* Get next Device Information subtable */
513     }
514 
515     DtPopSubtable ();
516     return (AE_OK);
517 }
518 
519 
520 /******************************************************************************
521  *
522  * FUNCTION:    DtCompileDmar
523  *
524  * PARAMETERS:  List                - Current field list pointer
525  *
526  * RETURN:      Status
527  *
528  * DESCRIPTION: Compile DMAR.
529  *
530  *****************************************************************************/
531 
532 ACPI_STATUS
533 DtCompileDmar (
534     void                    **List)
535 {
536     ACPI_STATUS             Status;
537     DT_SUBTABLE             *Subtable;
538     DT_SUBTABLE             *ParentTable;
539     DT_FIELD                **PFieldList = (DT_FIELD **) List;
540     DT_FIELD                *SubtableStart;
541     ACPI_DMTABLE_INFO       *InfoTable;
542     ACPI_DMAR_HEADER        *DmarHeader;
543     ACPI_DMAR_DEVICE_SCOPE  *DmarDeviceScope;
544     UINT32                  DeviceScopeLength;
545     UINT32                  PciPathLength;
546 
547 
548     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmar, &Subtable, TRUE);
549     if (ACPI_FAILURE (Status))
550     {
551         return (Status);
552     }
553 
554     ParentTable = DtPeekSubtable ();
555     DtInsertSubtable (ParentTable, Subtable);
556     DtPushSubtable (Subtable);
557 
558     while (*PFieldList)
559     {
560         /* DMAR Header */
561 
562         SubtableStart = *PFieldList;
563         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarHdr,
564             &Subtable, TRUE);
565         if (ACPI_FAILURE (Status))
566         {
567             return (Status);
568         }
569 
570         ParentTable = DtPeekSubtable ();
571         DtInsertSubtable (ParentTable, Subtable);
572         DtPushSubtable (Subtable);
573 
574         DmarHeader = ACPI_CAST_PTR (ACPI_DMAR_HEADER, Subtable->Buffer);
575 
576         switch (DmarHeader->Type)
577         {
578         case ACPI_DMAR_TYPE_HARDWARE_UNIT:
579 
580             InfoTable = AcpiDmTableInfoDmar0;
581             break;
582 
583         case ACPI_DMAR_TYPE_RESERVED_MEMORY:
584 
585             InfoTable = AcpiDmTableInfoDmar1;
586             break;
587 
588         case ACPI_DMAR_TYPE_ROOT_ATS:
589 
590             InfoTable = AcpiDmTableInfoDmar2;
591             break;
592 
593         case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
594 
595             InfoTable = AcpiDmTableInfoDmar3;
596             break;
597 
598         case ACPI_DMAR_TYPE_NAMESPACE:
599 
600             InfoTable = AcpiDmTableInfoDmar4;
601             break;
602 
603         default:
604 
605             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "DMAR");
606             return (AE_ERROR);
607         }
608 
609         /* DMAR Subtable */
610 
611         Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
612         if (ACPI_FAILURE (Status))
613         {
614             return (Status);
615         }
616 
617         ParentTable = DtPeekSubtable ();
618         DtInsertSubtable (ParentTable, Subtable);
619 
620         /*
621          * Optional Device Scope subtables
622          */
623         if ((DmarHeader->Type == ACPI_DMAR_TYPE_HARDWARE_AFFINITY) ||
624             (DmarHeader->Type == ACPI_DMAR_TYPE_NAMESPACE))
625         {
626             /* These types do not support device scopes */
627 
628             DtPopSubtable ();
629             continue;
630         }
631 
632         DtPushSubtable (Subtable);
633         DeviceScopeLength = DmarHeader->Length - Subtable->Length -
634             ParentTable->Length;
635         while (DeviceScopeLength)
636         {
637             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarScope,
638                 &Subtable, FALSE);
639             if (Status == AE_NOT_FOUND)
640             {
641                 break;
642             }
643 
644             ParentTable = DtPeekSubtable ();
645             DtInsertSubtable (ParentTable, Subtable);
646             DtPushSubtable (Subtable);
647 
648             DmarDeviceScope = ACPI_CAST_PTR (ACPI_DMAR_DEVICE_SCOPE, Subtable->Buffer);
649 
650             /* Optional PCI Paths */
651 
652             PciPathLength = DmarDeviceScope->Length - Subtable->Length;
653             while (PciPathLength)
654             {
655                 Status = DtCompileTable (PFieldList, TableInfoDmarPciPath,
656                     &Subtable, FALSE);
657                 if (Status == AE_NOT_FOUND)
658                 {
659                     DtPopSubtable ();
660                     break;
661                 }
662 
663                 ParentTable = DtPeekSubtable ();
664                 DtInsertSubtable (ParentTable, Subtable);
665                 PciPathLength -= Subtable->Length;
666             }
667 
668             DtPopSubtable ();
669             DeviceScopeLength -= DmarDeviceScope->Length;
670         }
671 
672         DtPopSubtable ();
673         DtPopSubtable ();
674     }
675 
676     return (AE_OK);
677 }
678 
679 
680 /******************************************************************************
681  *
682  * FUNCTION:    DtCompileDrtm
683  *
684  * PARAMETERS:  List                - Current field list pointer
685  *
686  * RETURN:      Status
687  *
688  * DESCRIPTION: Compile DRTM.
689  *
690  *****************************************************************************/
691 
692 ACPI_STATUS
693 DtCompileDrtm (
694     void                    **List)
695 {
696     ACPI_STATUS             Status;
697     DT_SUBTABLE             *Subtable;
698     DT_SUBTABLE             *ParentTable;
699     DT_FIELD                **PFieldList = (DT_FIELD **) List;
700     UINT32                  Count;
701     /* ACPI_TABLE_DRTM         *Drtm; */
702     ACPI_DRTM_VTABLE_LIST   *DrtmVtl;
703     ACPI_DRTM_RESOURCE_LIST *DrtmRl;
704     /* ACPI_DRTM_DPS_ID        *DrtmDps; */
705 
706 
707     ParentTable = DtPeekSubtable ();
708 
709     /* Compile DRTM header */
710 
711     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm,
712         &Subtable, TRUE);
713     if (ACPI_FAILURE (Status))
714     {
715         return (Status);
716     }
717     DtInsertSubtable (ParentTable, Subtable);
718 
719     /*
720      * Using ACPI_SUB_PTR, We needn't define a seperate structure. Care
721      * should be taken to avoid accessing ACPI_TABLE_HADER fields.
722      */
723 #if 0
724     Drtm = ACPI_SUB_PTR (ACPI_TABLE_DRTM,
725         Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
726 #endif
727     /* Compile VTL */
728 
729     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0,
730         &Subtable, TRUE);
731     if (ACPI_FAILURE (Status))
732     {
733         return (Status);
734     }
735 
736     DtInsertSubtable (ParentTable, Subtable);
737     DrtmVtl = ACPI_CAST_PTR (ACPI_DRTM_VTABLE_LIST, Subtable->Buffer);
738 
739     DtPushSubtable (Subtable);
740     ParentTable = DtPeekSubtable ();
741     Count = 0;
742 
743     while (*PFieldList)
744     {
745         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0a,
746             &Subtable, TRUE);
747         if (ACPI_FAILURE (Status))
748         {
749             return (Status);
750         }
751         if (!Subtable)
752         {
753             break;
754         }
755         DtInsertSubtable (ParentTable, Subtable);
756         Count++;
757     }
758 
759     DrtmVtl->ValidatedTableCount = Count;
760     DtPopSubtable ();
761     ParentTable = DtPeekSubtable ();
762 
763     /* Compile RL */
764 
765     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1,
766         &Subtable, TRUE);
767     if (ACPI_FAILURE (Status))
768     {
769         return (Status);
770     }
771 
772     DtInsertSubtable (ParentTable, Subtable);
773     DrtmRl = ACPI_CAST_PTR (ACPI_DRTM_RESOURCE_LIST, Subtable->Buffer);
774 
775     DtPushSubtable (Subtable);
776     ParentTable = DtPeekSubtable ();
777     Count = 0;
778 
779     while (*PFieldList)
780     {
781         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1a,
782             &Subtable, TRUE);
783         if (ACPI_FAILURE (Status))
784         {
785             return (Status);
786         }
787 
788         if (!Subtable)
789         {
790             break;
791         }
792 
793         DtInsertSubtable (ParentTable, Subtable);
794         Count++;
795     }
796 
797     DrtmRl->ResourceCount = Count;
798     DtPopSubtable ();
799     ParentTable = DtPeekSubtable ();
800 
801     /* Compile DPS */
802 
803     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm2,
804         &Subtable, TRUE);
805     if (ACPI_FAILURE (Status))
806     {
807         return (Status);
808     }
809     DtInsertSubtable (ParentTable, Subtable);
810     /* DrtmDps = ACPI_CAST_PTR (ACPI_DRTM_DPS_ID, Subtable->Buffer);*/
811 
812 
813     return (AE_OK);
814 }
815 
816 
817 /******************************************************************************
818  *
819  * FUNCTION:    DtCompileEinj
820  *
821  * PARAMETERS:  List                - Current field list pointer
822  *
823  * RETURN:      Status
824  *
825  * DESCRIPTION: Compile EINJ.
826  *
827  *****************************************************************************/
828 
829 ACPI_STATUS
830 DtCompileEinj (
831     void                    **List)
832 {
833     ACPI_STATUS             Status;
834 
835 
836     Status = DtCompileTwoSubtables (List,
837         AcpiDmTableInfoEinj, AcpiDmTableInfoEinj0);
838     return (Status);
839 }
840 
841 
842 /******************************************************************************
843  *
844  * FUNCTION:    DtCompileErst
845  *
846  * PARAMETERS:  List                - Current field list pointer
847  *
848  * RETURN:      Status
849  *
850  * DESCRIPTION: Compile ERST.
851  *
852  *****************************************************************************/
853 
854 ACPI_STATUS
855 DtCompileErst (
856     void                    **List)
857 {
858     ACPI_STATUS             Status;
859 
860 
861     Status = DtCompileTwoSubtables (List,
862         AcpiDmTableInfoErst, AcpiDmTableInfoEinj0);
863     return (Status);
864 }
865 
866 
867 /******************************************************************************
868  *
869  * FUNCTION:    DtCompileGtdt
870  *
871  * PARAMETERS:  List                - Current field list pointer
872  *
873  * RETURN:      Status
874  *
875  * DESCRIPTION: Compile GTDT.
876  *
877  *****************************************************************************/
878 
879 ACPI_STATUS
880 DtCompileGtdt (
881     void                    **List)
882 {
883     ACPI_STATUS             Status;
884     DT_SUBTABLE             *Subtable;
885     DT_SUBTABLE             *ParentTable;
886     DT_FIELD                **PFieldList = (DT_FIELD **) List;
887     DT_FIELD                *SubtableStart;
888     ACPI_SUBTABLE_HEADER    *GtdtHeader;
889     ACPI_DMTABLE_INFO       *InfoTable;
890     UINT32                  GtCount;
891 
892 
893     Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt,
894         &Subtable, TRUE);
895     if (ACPI_FAILURE (Status))
896     {
897         return (Status);
898     }
899 
900     ParentTable = DtPeekSubtable ();
901     DtInsertSubtable (ParentTable, Subtable);
902 
903     while (*PFieldList)
904     {
905         SubtableStart = *PFieldList;
906         Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdtHdr,
907             &Subtable, TRUE);
908         if (ACPI_FAILURE (Status))
909         {
910             return (Status);
911         }
912 
913         ParentTable = DtPeekSubtable ();
914         DtInsertSubtable (ParentTable, Subtable);
915         DtPushSubtable (Subtable);
916 
917         GtdtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer);
918 
919         switch (GtdtHeader->Type)
920         {
921         case ACPI_GTDT_TYPE_TIMER_BLOCK:
922 
923             InfoTable = AcpiDmTableInfoGtdt0;
924             break;
925 
926         case ACPI_GTDT_TYPE_WATCHDOG:
927 
928             InfoTable = AcpiDmTableInfoGtdt1;
929             break;
930 
931         default:
932 
933             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "GTDT");
934             return (AE_ERROR);
935         }
936 
937         Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
938         if (ACPI_FAILURE (Status))
939         {
940             return (Status);
941         }
942 
943         ParentTable = DtPeekSubtable ();
944         DtInsertSubtable (ParentTable, Subtable);
945 
946         /*
947          * Additional GT block subtable data
948          */
949 
950         switch (GtdtHeader->Type)
951         {
952         case ACPI_GTDT_TYPE_TIMER_BLOCK:
953 
954             DtPushSubtable (Subtable);
955             ParentTable = DtPeekSubtable ();
956 
957             GtCount = (ACPI_CAST_PTR (ACPI_GTDT_TIMER_BLOCK,
958                 Subtable->Buffer - sizeof(ACPI_GTDT_HEADER)))->TimerCount;
959 
960             while (GtCount)
961             {
962                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt0a,
963                     &Subtable, TRUE);
964                 if (ACPI_FAILURE (Status))
965                 {
966                     return (Status);
967                 }
968 
969                 DtInsertSubtable (ParentTable, Subtable);
970                 GtCount--;
971             }
972 
973             DtPopSubtable ();
974             break;
975 
976         default:
977 
978             break;
979         }
980 
981         DtPopSubtable ();
982     }
983 
984     return (AE_OK);
985 }
986 
987 
988 /******************************************************************************
989  *
990  * FUNCTION:    DtCompileFpdt
991  *
992  * PARAMETERS:  List                - Current field list pointer
993  *
994  * RETURN:      Status
995  *
996  * DESCRIPTION: Compile FPDT.
997  *
998  *****************************************************************************/
999 
1000 ACPI_STATUS
1001 DtCompileFpdt (
1002     void                    **List)
1003 {
1004     ACPI_STATUS             Status;
1005     ACPI_FPDT_HEADER        *FpdtHeader;
1006     DT_SUBTABLE             *Subtable;
1007     DT_SUBTABLE             *ParentTable;
1008     ACPI_DMTABLE_INFO       *InfoTable;
1009     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1010     DT_FIELD                *SubtableStart;
1011 
1012 
1013     while (*PFieldList)
1014     {
1015         SubtableStart = *PFieldList;
1016         Status = DtCompileTable (PFieldList, AcpiDmTableInfoFpdtHdr,
1017             &Subtable, TRUE);
1018         if (ACPI_FAILURE (Status))
1019         {
1020             return (Status);
1021         }
1022 
1023         ParentTable = DtPeekSubtable ();
1024         DtInsertSubtable (ParentTable, Subtable);
1025         DtPushSubtable (Subtable);
1026 
1027         FpdtHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer);
1028 
1029         switch (FpdtHeader->Type)
1030         {
1031         case ACPI_FPDT_TYPE_BOOT:
1032 
1033             InfoTable = AcpiDmTableInfoFpdt0;
1034             break;
1035 
1036         case ACPI_FPDT_TYPE_S3PERF:
1037 
1038             InfoTable = AcpiDmTableInfoFpdt1;
1039             break;
1040 
1041         default:
1042 
1043             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "FPDT");
1044             return (AE_ERROR);
1045             break;
1046         }
1047 
1048         Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
1049         if (ACPI_FAILURE (Status))
1050         {
1051             return (Status);
1052         }
1053 
1054         ParentTable = DtPeekSubtable ();
1055         DtInsertSubtable (ParentTable, Subtable);
1056         DtPopSubtable ();
1057     }
1058 
1059     return (AE_OK);
1060 }
1061 
1062 
1063 /******************************************************************************
1064  *
1065  * FUNCTION:    DtCompileHest
1066  *
1067  * PARAMETERS:  List                - Current field list pointer
1068  *
1069  * RETURN:      Status
1070  *
1071  * DESCRIPTION: Compile HEST.
1072  *
1073  *****************************************************************************/
1074 
1075 ACPI_STATUS
1076 DtCompileHest (
1077     void                    **List)
1078 {
1079     ACPI_STATUS             Status;
1080     DT_SUBTABLE             *Subtable;
1081     DT_SUBTABLE             *ParentTable;
1082     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1083     DT_FIELD                *SubtableStart;
1084     ACPI_DMTABLE_INFO       *InfoTable;
1085     UINT16                  Type;
1086     UINT32                  BankCount;
1087 
1088 
1089     Status = DtCompileTable (PFieldList, AcpiDmTableInfoHest,
1090         &Subtable, TRUE);
1091     if (ACPI_FAILURE (Status))
1092     {
1093         return (Status);
1094     }
1095 
1096     ParentTable = DtPeekSubtable ();
1097     DtInsertSubtable (ParentTable, Subtable);
1098 
1099     while (*PFieldList)
1100     {
1101         /* Get subtable type */
1102 
1103         SubtableStart = *PFieldList;
1104         DtCompileInteger ((UINT8 *) &Type, *PFieldList, 2, 0);
1105 
1106         switch (Type)
1107         {
1108         case ACPI_HEST_TYPE_IA32_CHECK:
1109 
1110             InfoTable = AcpiDmTableInfoHest0;
1111             break;
1112 
1113         case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
1114 
1115             InfoTable = AcpiDmTableInfoHest1;
1116             break;
1117 
1118         case ACPI_HEST_TYPE_IA32_NMI:
1119 
1120             InfoTable = AcpiDmTableInfoHest2;
1121             break;
1122 
1123         case ACPI_HEST_TYPE_AER_ROOT_PORT:
1124 
1125             InfoTable = AcpiDmTableInfoHest6;
1126             break;
1127 
1128         case ACPI_HEST_TYPE_AER_ENDPOINT:
1129 
1130             InfoTable = AcpiDmTableInfoHest7;
1131             break;
1132 
1133         case ACPI_HEST_TYPE_AER_BRIDGE:
1134 
1135             InfoTable = AcpiDmTableInfoHest8;
1136             break;
1137 
1138         case ACPI_HEST_TYPE_GENERIC_ERROR:
1139 
1140             InfoTable = AcpiDmTableInfoHest9;
1141             break;
1142 
1143         case ACPI_HEST_TYPE_GENERIC_ERROR_V2:
1144 
1145             InfoTable = AcpiDmTableInfoHest10;
1146             break;
1147 
1148         case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
1149 
1150             InfoTable = AcpiDmTableInfoHest11;
1151             break;
1152 
1153         default:
1154 
1155             /* Cannot continue on unknown type */
1156 
1157             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HEST");
1158             return (AE_ERROR);
1159         }
1160 
1161         Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
1162         if (ACPI_FAILURE (Status))
1163         {
1164             return (Status);
1165         }
1166 
1167         DtInsertSubtable (ParentTable, Subtable);
1168 
1169         /*
1170          * Additional subtable data - IA32 Error Bank(s)
1171          */
1172         BankCount = 0;
1173         switch (Type)
1174         {
1175         case ACPI_HEST_TYPE_IA32_CHECK:
1176 
1177             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK,
1178                 Subtable->Buffer))->NumHardwareBanks;
1179             break;
1180 
1181         case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
1182 
1183             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED,
1184                 Subtable->Buffer))->NumHardwareBanks;
1185             break;
1186 
1187         case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
1188 
1189             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_DEFERRED_CHECK,
1190                 Subtable->Buffer))->NumHardwareBanks;
1191             break;
1192 
1193         default:
1194 
1195             break;
1196         }
1197 
1198         while (BankCount)
1199         {
1200             Status = DtCompileTable (PFieldList, AcpiDmTableInfoHestBank,
1201                 &Subtable, TRUE);
1202             if (ACPI_FAILURE (Status))
1203             {
1204                 return (Status);
1205             }
1206 
1207             DtInsertSubtable (ParentTable, Subtable);
1208             BankCount--;
1209         }
1210     }
1211 
1212     return (AE_OK);
1213 }
1214 
1215 
1216 /******************************************************************************
1217  *
1218  * FUNCTION:    DtCompileHmat
1219  *
1220  * PARAMETERS:  List                - Current field list pointer
1221  *
1222  * RETURN:      Status
1223  *
1224  * DESCRIPTION: Compile HMAT.
1225  *
1226  *****************************************************************************/
1227 
1228 ACPI_STATUS
1229 DtCompileHmat (
1230     void                    **List)
1231 {
1232     ACPI_STATUS             Status;
1233     DT_SUBTABLE             *Subtable;
1234     DT_SUBTABLE             *ParentTable;
1235     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1236     DT_FIELD                *SubtableStart;
1237     DT_FIELD                *EntryStart;
1238     ACPI_HMAT_STRUCTURE     *HmatStruct;
1239     ACPI_HMAT_LOCALITY      *HmatLocality;
1240     ACPI_HMAT_CACHE         *HmatCache;
1241     ACPI_DMTABLE_INFO       *InfoTable;
1242     UINT32                  IntPDNumber;
1243     UINT32                  TgtPDNumber;
1244     UINT64                  EntryNumber;
1245     UINT16                  SMBIOSHandleNumber;
1246 
1247 
1248     ParentTable = DtPeekSubtable ();
1249 
1250     Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmat,
1251         &Subtable, TRUE);
1252     if (ACPI_FAILURE (Status))
1253     {
1254         return (Status);
1255     }
1256     DtInsertSubtable (ParentTable, Subtable);
1257 
1258     while (*PFieldList)
1259     {
1260         /* Compile HMAT structure header */
1261 
1262         SubtableStart = *PFieldList;
1263         Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmatHdr,
1264             &Subtable, TRUE);
1265         if (ACPI_FAILURE (Status))
1266         {
1267             return (Status);
1268         }
1269         DtInsertSubtable (ParentTable, Subtable);
1270 
1271         HmatStruct = ACPI_CAST_PTR (ACPI_HMAT_STRUCTURE, Subtable->Buffer);
1272         HmatStruct->Length = Subtable->Length;
1273 
1274         /* Compile HMAT structure body */
1275 
1276         switch (HmatStruct->Type)
1277         {
1278         case ACPI_HMAT_TYPE_ADDRESS_RANGE:
1279 
1280             InfoTable = AcpiDmTableInfoHmat0;
1281             break;
1282 
1283         case ACPI_HMAT_TYPE_LOCALITY:
1284 
1285             InfoTable = AcpiDmTableInfoHmat1;
1286             break;
1287 
1288         case ACPI_HMAT_TYPE_CACHE:
1289 
1290             InfoTable = AcpiDmTableInfoHmat2;
1291             break;
1292 
1293         default:
1294 
1295             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HMAT");
1296             return (AE_ERROR);
1297         }
1298 
1299         Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
1300         if (ACPI_FAILURE (Status))
1301         {
1302             return (Status);
1303         }
1304         DtInsertSubtable (ParentTable, Subtable);
1305         HmatStruct->Length += Subtable->Length;
1306 
1307         /* Compile HMAT structure additionals */
1308 
1309         switch (HmatStruct->Type)
1310         {
1311         case ACPI_HMAT_TYPE_LOCALITY:
1312 
1313             HmatLocality = ACPI_SUB_PTR (ACPI_HMAT_LOCALITY,
1314                 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
1315 
1316             /* Compile initiator proximity domain list */
1317 
1318             IntPDNumber = 0;
1319             while (*PFieldList)
1320             {
1321                 Status = DtCompileTable (PFieldList,
1322                     AcpiDmTableInfoHmat1a, &Subtable, TRUE);
1323                 if (ACPI_FAILURE (Status))
1324                 {
1325                     return (Status);
1326                 }
1327                 if (!Subtable)
1328                 {
1329                     break;
1330                 }
1331                 DtInsertSubtable (ParentTable, Subtable);
1332                 HmatStruct->Length += Subtable->Length;
1333                 IntPDNumber++;
1334             }
1335             HmatLocality->NumberOfInitiatorPDs = IntPDNumber;
1336 
1337             /* Compile target proximity domain list */
1338 
1339             TgtPDNumber = 0;
1340             while (*PFieldList)
1341             {
1342                 Status = DtCompileTable (PFieldList,
1343                     AcpiDmTableInfoHmat1b, &Subtable, TRUE);
1344                 if (ACPI_FAILURE (Status))
1345                 {
1346                     return (Status);
1347                 }
1348                 if (!Subtable)
1349                 {
1350                     break;
1351                 }
1352                 DtInsertSubtable (ParentTable, Subtable);
1353                 HmatStruct->Length += Subtable->Length;
1354                 TgtPDNumber++;
1355             }
1356             HmatLocality->NumberOfTargetPDs = TgtPDNumber;
1357 
1358             /* Save start of the entries for reporting errors */
1359 
1360             EntryStart = *PFieldList;
1361 
1362             /* Compile latency/bandwidth entries */
1363 
1364             EntryNumber = 0;
1365             while (*PFieldList)
1366             {
1367                 Status = DtCompileTable (PFieldList,
1368                     AcpiDmTableInfoHmat1c, &Subtable, TRUE);
1369                 if (ACPI_FAILURE (Status))
1370                 {
1371                     return (Status);
1372                 }
1373                 if (!Subtable)
1374                 {
1375                     break;
1376                 }
1377                 DtInsertSubtable (ParentTable, Subtable);
1378                 HmatStruct->Length += Subtable->Length;
1379                 EntryNumber++;
1380             }
1381 
1382             /* Validate number of entries */
1383 
1384             if (EntryNumber !=
1385                 ((UINT64)IntPDNumber * (UINT64)TgtPDNumber))
1386             {
1387                 DtFatal (ASL_MSG_INVALID_EXPRESSION, EntryStart, "HMAT");
1388                 return (AE_ERROR);
1389             }
1390             break;
1391 
1392         case ACPI_HMAT_TYPE_CACHE:
1393 
1394             /* Compile SMBIOS handles */
1395 
1396             HmatCache = ACPI_SUB_PTR (ACPI_HMAT_CACHE,
1397                 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
1398             SMBIOSHandleNumber = 0;
1399             while (*PFieldList)
1400             {
1401                 Status = DtCompileTable (PFieldList,
1402                     AcpiDmTableInfoHmat2a, &Subtable, TRUE);
1403                 if (ACPI_FAILURE (Status))
1404                 {
1405                     return (Status);
1406                 }
1407                 if (!Subtable)
1408                 {
1409                     break;
1410                 }
1411                 DtInsertSubtable (ParentTable, Subtable);
1412                 HmatStruct->Length += Subtable->Length;
1413                 SMBIOSHandleNumber++;
1414             }
1415             HmatCache->NumberOfSMBIOSHandles = SMBIOSHandleNumber;
1416             break;
1417 
1418         default:
1419 
1420             break;
1421         }
1422     }
1423 
1424     return (AE_OK);
1425 }
1426 
1427 
1428 /******************************************************************************
1429  *
1430  * FUNCTION:    DtCompileIort
1431  *
1432  * PARAMETERS:  List                - Current field list pointer
1433  *
1434  * RETURN:      Status
1435  *
1436  * DESCRIPTION: Compile IORT.
1437  *
1438  *****************************************************************************/
1439 
1440 ACPI_STATUS
1441 DtCompileIort (
1442     void                    **List)
1443 {
1444     ACPI_STATUS             Status;
1445     DT_SUBTABLE             *Subtable;
1446     DT_SUBTABLE             *ParentTable;
1447     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1448     DT_FIELD                *SubtableStart;
1449     ACPI_TABLE_IORT         *Iort;
1450     ACPI_IORT_NODE          *IortNode;
1451     ACPI_IORT_ITS_GROUP     *IortItsGroup;
1452     ACPI_IORT_SMMU          *IortSmmu;
1453     UINT32                  NodeNumber;
1454     UINT32                  NodeLength;
1455     UINT32                  IdMappingNumber;
1456     UINT32                  ItsNumber;
1457     UINT32                  ContextIrptNumber;
1458     UINT32                  PmuIrptNumber;
1459     UINT32                  PaddingLength;
1460 
1461 
1462     ParentTable = DtPeekSubtable ();
1463 
1464     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort,
1465         &Subtable, TRUE);
1466     if (ACPI_FAILURE (Status))
1467     {
1468         return (Status);
1469     }
1470     DtInsertSubtable (ParentTable, Subtable);
1471 
1472     /*
1473      * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
1474      * should be taken to avoid accessing ACPI_TABLE_HEADER fields.
1475      */
1476     Iort = ACPI_SUB_PTR (ACPI_TABLE_IORT,
1477         Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
1478 
1479     /*
1480      * OptionalPadding - Variable-length data
1481      * (Optional, size = OffsetToNodes - sizeof (ACPI_TABLE_IORT))
1482      * Optionally allows the generic data types to be used for filling
1483      * this field.
1484      */
1485     Iort->NodeOffset = sizeof (ACPI_TABLE_IORT);
1486     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortPad,
1487         &Subtable, TRUE);
1488     if (ACPI_FAILURE (Status))
1489     {
1490         return (Status);
1491     }
1492     if (Subtable)
1493     {
1494         DtInsertSubtable (ParentTable, Subtable);
1495         Iort->NodeOffset += Subtable->Length;
1496     }
1497     else
1498     {
1499         Status = DtCompileGeneric (ACPI_CAST_PTR (void *, PFieldList),
1500             AcpiDmTableInfoIortHdr[0].Name, &PaddingLength);
1501         if (ACPI_FAILURE (Status))
1502         {
1503             return (Status);
1504         }
1505         Iort->NodeOffset += PaddingLength;
1506     }
1507 
1508     NodeNumber = 0;
1509     while (*PFieldList)
1510     {
1511         SubtableStart = *PFieldList;
1512         Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr,
1513             &Subtable, TRUE);
1514         if (ACPI_FAILURE (Status))
1515         {
1516             return (Status);
1517         }
1518 
1519         DtInsertSubtable (ParentTable, Subtable);
1520         IortNode = ACPI_CAST_PTR (ACPI_IORT_NODE, Subtable->Buffer);
1521         NodeLength = ACPI_OFFSET (ACPI_IORT_NODE, NodeData);
1522 
1523         DtPushSubtable (Subtable);
1524         ParentTable = DtPeekSubtable ();
1525 
1526         switch (IortNode->Type)
1527         {
1528         case ACPI_IORT_NODE_ITS_GROUP:
1529 
1530             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0,
1531                 &Subtable, TRUE);
1532             if (ACPI_FAILURE (Status))
1533             {
1534                 return (Status);
1535             }
1536 
1537             DtInsertSubtable (ParentTable, Subtable);
1538             IortItsGroup = ACPI_CAST_PTR (ACPI_IORT_ITS_GROUP, Subtable->Buffer);
1539             NodeLength += Subtable->Length;
1540 
1541             ItsNumber = 0;
1542             while (*PFieldList)
1543             {
1544                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0a,
1545                     &Subtable, TRUE);
1546                 if (ACPI_FAILURE (Status))
1547                 {
1548                     return (Status);
1549                 }
1550                 if (!Subtable)
1551                 {
1552                     break;
1553                 }
1554 
1555                 DtInsertSubtable (ParentTable, Subtable);
1556                 NodeLength += Subtable->Length;
1557                 ItsNumber++;
1558             }
1559 
1560             IortItsGroup->ItsCount = ItsNumber;
1561             break;
1562 
1563         case ACPI_IORT_NODE_NAMED_COMPONENT:
1564 
1565             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1,
1566                 &Subtable, TRUE);
1567             if (ACPI_FAILURE (Status))
1568             {
1569                 return (Status);
1570             }
1571 
1572             DtInsertSubtable (ParentTable, Subtable);
1573             NodeLength += Subtable->Length;
1574 
1575             /*
1576              * Padding - Variable-length data
1577              * Optionally allows the offset of the ID mappings to be used
1578              * for filling this field.
1579              */
1580             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1a,
1581                 &Subtable, TRUE);
1582             if (ACPI_FAILURE (Status))
1583             {
1584                 return (Status);
1585             }
1586 
1587             if (Subtable)
1588             {
1589                 DtInsertSubtable (ParentTable, Subtable);
1590                 NodeLength += Subtable->Length;
1591             }
1592             else
1593             {
1594                 if (NodeLength > IortNode->MappingOffset)
1595                 {
1596                     return (AE_BAD_DATA);
1597                 }
1598 
1599                 if (NodeLength < IortNode->MappingOffset)
1600                 {
1601                     Status = DtCompilePadding (
1602                         IortNode->MappingOffset - NodeLength,
1603                         &Subtable);
1604                     if (ACPI_FAILURE (Status))
1605                     {
1606                         return (Status);
1607                     }
1608 
1609                     DtInsertSubtable (ParentTable, Subtable);
1610                     NodeLength = IortNode->MappingOffset;
1611                 }
1612             }
1613             break;
1614 
1615         case ACPI_IORT_NODE_PCI_ROOT_COMPLEX:
1616 
1617             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort2,
1618                 &Subtable, TRUE);
1619             if (ACPI_FAILURE (Status))
1620             {
1621                 return (Status);
1622             }
1623 
1624             DtInsertSubtable (ParentTable, Subtable);
1625             NodeLength += Subtable->Length;
1626             break;
1627 
1628         case ACPI_IORT_NODE_SMMU:
1629 
1630             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3,
1631                 &Subtable, TRUE);
1632             if (ACPI_FAILURE (Status))
1633             {
1634                 return (Status);
1635             }
1636 
1637             DtInsertSubtable (ParentTable, Subtable);
1638             IortSmmu = ACPI_CAST_PTR (ACPI_IORT_SMMU, Subtable->Buffer);
1639             NodeLength += Subtable->Length;
1640 
1641             /* Compile global interrupt array */
1642 
1643             IortSmmu->GlobalInterruptOffset = NodeLength;
1644             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3a,
1645                 &Subtable, TRUE);
1646             if (ACPI_FAILURE (Status))
1647             {
1648                 return (Status);
1649             }
1650 
1651             DtInsertSubtable (ParentTable, Subtable);
1652             NodeLength += Subtable->Length;
1653 
1654             /* Compile context interrupt array */
1655 
1656             ContextIrptNumber = 0;
1657             IortSmmu->ContextInterruptOffset = NodeLength;
1658             while (*PFieldList)
1659             {
1660                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3b,
1661                     &Subtable, TRUE);
1662                 if (ACPI_FAILURE (Status))
1663                 {
1664                     return (Status);
1665                 }
1666 
1667                 if (!Subtable)
1668                 {
1669                     break;
1670                 }
1671 
1672                 DtInsertSubtable (ParentTable, Subtable);
1673                 NodeLength += Subtable->Length;
1674                 ContextIrptNumber++;
1675             }
1676 
1677             IortSmmu->ContextInterruptCount = ContextIrptNumber;
1678 
1679             /* Compile PMU interrupt array */
1680 
1681             PmuIrptNumber = 0;
1682             IortSmmu->PmuInterruptOffset = NodeLength;
1683             while (*PFieldList)
1684             {
1685                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3c,
1686                     &Subtable, TRUE);
1687                 if (ACPI_FAILURE (Status))
1688                 {
1689                     return (Status);
1690                 }
1691 
1692                 if (!Subtable)
1693                 {
1694                     break;
1695                 }
1696 
1697                 DtInsertSubtable (ParentTable, Subtable);
1698                 NodeLength += Subtable->Length;
1699                 PmuIrptNumber++;
1700             }
1701 
1702             IortSmmu->PmuInterruptCount = PmuIrptNumber;
1703             break;
1704 
1705         case ACPI_IORT_NODE_SMMU_V3:
1706 
1707             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort4,
1708                 &Subtable, TRUE);
1709             if (ACPI_FAILURE (Status))
1710             {
1711                 return (Status);
1712             }
1713 
1714             DtInsertSubtable (ParentTable, Subtable);
1715             NodeLength += Subtable->Length;
1716             break;
1717 
1718         default:
1719 
1720             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IORT");
1721             return (AE_ERROR);
1722         }
1723 
1724         /* Compile Array of ID mappings */
1725 
1726         IortNode->MappingOffset = NodeLength;
1727         IdMappingNumber = 0;
1728         while (*PFieldList)
1729         {
1730             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortMap,
1731                 &Subtable, TRUE);
1732             if (ACPI_FAILURE (Status))
1733             {
1734                 return (Status);
1735             }
1736 
1737             if (!Subtable)
1738             {
1739                 break;
1740             }
1741 
1742             DtInsertSubtable (ParentTable, Subtable);
1743             NodeLength += sizeof (ACPI_IORT_ID_MAPPING);
1744             IdMappingNumber++;
1745         }
1746 
1747         IortNode->MappingCount = IdMappingNumber;
1748         if (!IdMappingNumber)
1749         {
1750             IortNode->MappingOffset = 0;
1751         }
1752 
1753         /*
1754          * Node length can be determined by DT_LENGTH option
1755          * IortNode->Length = NodeLength;
1756          */
1757         DtPopSubtable ();
1758         ParentTable = DtPeekSubtable ();
1759         NodeNumber++;
1760     }
1761 
1762     Iort->NodeCount = NodeNumber;
1763     return (AE_OK);
1764 }
1765 
1766 
1767 /******************************************************************************
1768  *
1769  * FUNCTION:    DtCompileIvrs
1770  *
1771  * PARAMETERS:  List                - Current field list pointer
1772  *
1773  * RETURN:      Status
1774  *
1775  * DESCRIPTION: Compile IVRS.
1776  *
1777  *****************************************************************************/
1778 
1779 ACPI_STATUS
1780 DtCompileIvrs (
1781     void                    **List)
1782 {
1783     ACPI_STATUS             Status;
1784     DT_SUBTABLE             *Subtable;
1785     DT_SUBTABLE             *ParentTable;
1786     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1787     DT_FIELD                *SubtableStart;
1788     ACPI_DMTABLE_INFO       *InfoTable;
1789     ACPI_IVRS_HEADER        *IvrsHeader;
1790     UINT8                   EntryType;
1791 
1792 
1793     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrs,
1794         &Subtable, TRUE);
1795     if (ACPI_FAILURE (Status))
1796     {
1797         return (Status);
1798     }
1799 
1800     ParentTable = DtPeekSubtable ();
1801     DtInsertSubtable (ParentTable, Subtable);
1802 
1803     while (*PFieldList)
1804     {
1805         SubtableStart = *PFieldList;
1806         Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHdr,
1807             &Subtable, TRUE);
1808         if (ACPI_FAILURE (Status))
1809         {
1810             return (Status);
1811         }
1812 
1813         ParentTable = DtPeekSubtable ();
1814         DtInsertSubtable (ParentTable, Subtable);
1815         DtPushSubtable (Subtable);
1816 
1817         IvrsHeader = ACPI_CAST_PTR (ACPI_IVRS_HEADER, Subtable->Buffer);
1818 
1819         switch (IvrsHeader->Type)
1820         {
1821         case ACPI_IVRS_TYPE_HARDWARE:
1822 
1823             InfoTable = AcpiDmTableInfoIvrs0;
1824             break;
1825 
1826         case ACPI_IVRS_TYPE_MEMORY1:
1827         case ACPI_IVRS_TYPE_MEMORY2:
1828         case ACPI_IVRS_TYPE_MEMORY3:
1829 
1830             InfoTable = AcpiDmTableInfoIvrs1;
1831             break;
1832 
1833         default:
1834 
1835             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IVRS");
1836             return (AE_ERROR);
1837         }
1838 
1839         Status = DtCompileTable (PFieldList, InfoTable, &Subtable, TRUE);
1840         if (ACPI_FAILURE (Status))
1841         {
1842             return (Status);
1843         }
1844 
1845         ParentTable = DtPeekSubtable ();
1846         DtInsertSubtable (ParentTable, Subtable);
1847 
1848         if (IvrsHeader->Type == ACPI_IVRS_TYPE_HARDWARE)
1849         {
1850             while (*PFieldList &&
1851                 !strcmp ((*PFieldList)->Name, "Entry Type"))
1852             {
1853                 SubtableStart = *PFieldList;
1854                 DtCompileInteger (&EntryType, *PFieldList, 1, 0);
1855 
1856                 switch (EntryType)
1857                 {
1858                 /* 4-byte device entries */
1859 
1860                 case ACPI_IVRS_TYPE_PAD4:
1861                 case ACPI_IVRS_TYPE_ALL:
1862                 case ACPI_IVRS_TYPE_SELECT:
1863                 case ACPI_IVRS_TYPE_START:
1864                 case ACPI_IVRS_TYPE_END:
1865 
1866                     InfoTable = AcpiDmTableInfoIvrs4;
1867                     break;
1868 
1869                 /* 8-byte entries, type A */
1870 
1871                 case ACPI_IVRS_TYPE_ALIAS_SELECT:
1872                 case ACPI_IVRS_TYPE_ALIAS_START:
1873 
1874                     InfoTable = AcpiDmTableInfoIvrs8a;
1875                     break;
1876 
1877                 /* 8-byte entries, type B */
1878 
1879                 case ACPI_IVRS_TYPE_PAD8:
1880                 case ACPI_IVRS_TYPE_EXT_SELECT:
1881                 case ACPI_IVRS_TYPE_EXT_START:
1882 
1883                     InfoTable = AcpiDmTableInfoIvrs8b;
1884                     break;
1885 
1886                 /* 8-byte entries, type C */
1887 
1888                 case ACPI_IVRS_TYPE_SPECIAL:
1889 
1890                     InfoTable = AcpiDmTableInfoIvrs8c;
1891                     break;
1892 
1893                 default:
1894 
1895                     DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart,
1896                         "IVRS Device Entry");
1897                     return (AE_ERROR);
1898                 }
1899 
1900                 Status = DtCompileTable (PFieldList, InfoTable,
1901                     &Subtable, TRUE);
1902                 if (ACPI_FAILURE (Status))
1903                 {
1904                     return (Status);
1905                 }
1906 
1907                 DtInsertSubtable (ParentTable, Subtable);
1908             }
1909         }
1910 
1911         DtPopSubtable ();
1912     }
1913 
1914     return (AE_OK);
1915 }
1916