xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/dttable1.c (revision 154bfe8e089c1a0a4e9ed8414f08d3da90949162)
1 /******************************************************************************
2  *
3  * Module Name: dttable1.c - handling for specific ACPI tables
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2020, 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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
491         if (Status == AE_END_OF_TABLE)
492         {
493             /* optional field was not found and we're at the end of the file */
494 
495             goto subtableDone;
496         }
497         else if (ACPI_FAILURE (Status))
498         {
499             return (Status);
500         }
501 
502         /* Update the device info header (zeros if no OEM data present) */
503 
504         DeviceInfo->OemDataOffset = 0;
505         DeviceInfo->OemDataLength = 0;
506 
507         /* Optional subtable (OemData) */
508 
509         if (Subtable && Subtable->Length)
510         {
511             DeviceInfo->OemDataOffset = CurrentOffset;
512             DeviceInfo->OemDataLength = (UINT16) Subtable->Length;
513 
514             DtInsertSubtable (ParentTable, Subtable);
515         }
516 subtableDone:
517         SubtableCount--;
518         DtPopSubtable (); /* Get next Device Information subtable */
519     }
520 
521     DtPopSubtable ();
522     return (AE_OK);
523 }
524 
525 
526 /******************************************************************************
527  *
528  * FUNCTION:    DtCompileDmar
529  *
530  * PARAMETERS:  List                - Current field list pointer
531  *
532  * RETURN:      Status
533  *
534  * DESCRIPTION: Compile DMAR.
535  *
536  *****************************************************************************/
537 
538 ACPI_STATUS
539 DtCompileDmar (
540     void                    **List)
541 {
542     ACPI_STATUS             Status;
543     DT_SUBTABLE             *Subtable;
544     DT_SUBTABLE             *ParentTable;
545     DT_FIELD                **PFieldList = (DT_FIELD **) List;
546     DT_FIELD                *SubtableStart;
547     ACPI_DMTABLE_INFO       *InfoTable;
548     ACPI_DMAR_HEADER        *DmarHeader;
549     ACPI_DMAR_DEVICE_SCOPE  *DmarDeviceScope;
550     UINT32                  DeviceScopeLength;
551     UINT32                  PciPathLength;
552 
553 
554     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmar, &Subtable);
555     if (ACPI_FAILURE (Status))
556     {
557         return (Status);
558     }
559 
560     ParentTable = DtPeekSubtable ();
561     DtInsertSubtable (ParentTable, Subtable);
562     DtPushSubtable (Subtable);
563 
564     while (*PFieldList)
565     {
566         /* DMAR Header */
567 
568         SubtableStart = *PFieldList;
569         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarHdr,
570             &Subtable);
571         if (ACPI_FAILURE (Status))
572         {
573             return (Status);
574         }
575 
576         ParentTable = DtPeekSubtable ();
577         DtInsertSubtable (ParentTable, Subtable);
578         DtPushSubtable (Subtable);
579 
580         DmarHeader = ACPI_CAST_PTR (ACPI_DMAR_HEADER, Subtable->Buffer);
581 
582         switch (DmarHeader->Type)
583         {
584         case ACPI_DMAR_TYPE_HARDWARE_UNIT:
585 
586             InfoTable = AcpiDmTableInfoDmar0;
587             break;
588 
589         case ACPI_DMAR_TYPE_RESERVED_MEMORY:
590 
591             InfoTable = AcpiDmTableInfoDmar1;
592             break;
593 
594         case ACPI_DMAR_TYPE_ROOT_ATS:
595 
596             InfoTable = AcpiDmTableInfoDmar2;
597             break;
598 
599         case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
600 
601             InfoTable = AcpiDmTableInfoDmar3;
602             break;
603 
604         case ACPI_DMAR_TYPE_NAMESPACE:
605 
606             InfoTable = AcpiDmTableInfoDmar4;
607             break;
608 
609         default:
610 
611             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "DMAR");
612             return (AE_ERROR);
613         }
614 
615         /* DMAR Subtable */
616 
617         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
618         if (ACPI_FAILURE (Status))
619         {
620             return (Status);
621         }
622 
623         ParentTable = DtPeekSubtable ();
624         DtInsertSubtable (ParentTable, Subtable);
625 
626         /*
627          * Optional Device Scope subtables
628          */
629         if ((DmarHeader->Type == ACPI_DMAR_TYPE_HARDWARE_AFFINITY) ||
630             (DmarHeader->Type == ACPI_DMAR_TYPE_NAMESPACE))
631         {
632             /* These types do not support device scopes */
633 
634             DtPopSubtable ();
635             continue;
636         }
637 
638         DtPushSubtable (Subtable);
639         DeviceScopeLength = DmarHeader->Length - Subtable->Length -
640             ParentTable->Length;
641         while (DeviceScopeLength)
642         {
643             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarScope,
644                 &Subtable);
645             if (Status == AE_NOT_FOUND)
646             {
647                 break;
648             }
649 
650             ParentTable = DtPeekSubtable ();
651             DtInsertSubtable (ParentTable, Subtable);
652             DtPushSubtable (Subtable);
653 
654             DmarDeviceScope = ACPI_CAST_PTR (ACPI_DMAR_DEVICE_SCOPE, Subtable->Buffer);
655 
656             /* Optional PCI Paths */
657 
658             PciPathLength = DmarDeviceScope->Length - Subtable->Length;
659             while (PciPathLength)
660             {
661                 Status = DtCompileTable (PFieldList, TableInfoDmarPciPath,
662                     &Subtable);
663                 if (Status == AE_NOT_FOUND)
664                 {
665                     DtPopSubtable ();
666                     break;
667                 }
668 
669                 ParentTable = DtPeekSubtable ();
670                 DtInsertSubtable (ParentTable, Subtable);
671                 PciPathLength -= Subtable->Length;
672             }
673 
674             DtPopSubtable ();
675             DeviceScopeLength -= DmarDeviceScope->Length;
676         }
677 
678         DtPopSubtable ();
679         DtPopSubtable ();
680     }
681 
682     return (AE_OK);
683 }
684 
685 
686 /******************************************************************************
687  *
688  * FUNCTION:    DtCompileDrtm
689  *
690  * PARAMETERS:  List                - Current field list pointer
691  *
692  * RETURN:      Status
693  *
694  * DESCRIPTION: Compile DRTM.
695  *
696  *****************************************************************************/
697 
698 ACPI_STATUS
699 DtCompileDrtm (
700     void                    **List)
701 {
702     ACPI_STATUS             Status;
703     DT_SUBTABLE             *Subtable;
704     DT_SUBTABLE             *ParentTable;
705     DT_FIELD                **PFieldList = (DT_FIELD **) List;
706     UINT32                  Count;
707     /* ACPI_TABLE_DRTM         *Drtm; */
708     ACPI_DRTM_VTABLE_LIST   *DrtmVtl;
709     ACPI_DRTM_RESOURCE_LIST *DrtmRl;
710     /* ACPI_DRTM_DPS_ID        *DrtmDps; */
711 
712 
713     ParentTable = DtPeekSubtable ();
714 
715     /* Compile DRTM header */
716 
717     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm,
718         &Subtable);
719     if (ACPI_FAILURE (Status))
720     {
721         return (Status);
722     }
723     DtInsertSubtable (ParentTable, Subtable);
724 
725     /*
726      * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
727      * should be taken to avoid accessing ACPI_TABLE_HADER fields.
728      */
729 #if 0
730     Drtm = ACPI_SUB_PTR (ACPI_TABLE_DRTM,
731         Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
732 #endif
733     /* Compile VTL */
734 
735     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0,
736         &Subtable);
737     if (ACPI_FAILURE (Status))
738     {
739         return (Status);
740     }
741 
742     DtInsertSubtable (ParentTable, Subtable);
743     DrtmVtl = ACPI_CAST_PTR (ACPI_DRTM_VTABLE_LIST, Subtable->Buffer);
744 
745     DtPushSubtable (Subtable);
746     ParentTable = DtPeekSubtable ();
747     Count = 0;
748 
749     while (*PFieldList)
750     {
751         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0a,
752             &Subtable);
753         if (ACPI_FAILURE (Status))
754         {
755             return (Status);
756         }
757         if (!Subtable)
758         {
759             break;
760         }
761         DtInsertSubtable (ParentTable, Subtable);
762         Count++;
763     }
764 
765     DrtmVtl->ValidatedTableCount = Count;
766     DtPopSubtable ();
767     ParentTable = DtPeekSubtable ();
768 
769     /* Compile RL */
770 
771     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1,
772         &Subtable);
773     if (ACPI_FAILURE (Status))
774     {
775         return (Status);
776     }
777 
778     DtInsertSubtable (ParentTable, Subtable);
779     DrtmRl = ACPI_CAST_PTR (ACPI_DRTM_RESOURCE_LIST, Subtable->Buffer);
780 
781     DtPushSubtable (Subtable);
782     ParentTable = DtPeekSubtable ();
783     Count = 0;
784 
785     while (*PFieldList)
786     {
787         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1a,
788             &Subtable);
789         if (ACPI_FAILURE (Status))
790         {
791             return (Status);
792         }
793 
794         if (!Subtable)
795         {
796             break;
797         }
798 
799         DtInsertSubtable (ParentTable, Subtable);
800         Count++;
801     }
802 
803     DrtmRl->ResourceCount = Count;
804     DtPopSubtable ();
805     ParentTable = DtPeekSubtable ();
806 
807     /* Compile DPS */
808 
809     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm2,
810         &Subtable);
811     if (ACPI_FAILURE (Status))
812     {
813         return (Status);
814     }
815     DtInsertSubtable (ParentTable, Subtable);
816     /* DrtmDps = ACPI_CAST_PTR (ACPI_DRTM_DPS_ID, Subtable->Buffer);*/
817 
818 
819     return (AE_OK);
820 }
821 
822 
823 /******************************************************************************
824  *
825  * FUNCTION:    DtCompileEinj
826  *
827  * PARAMETERS:  List                - Current field list pointer
828  *
829  * RETURN:      Status
830  *
831  * DESCRIPTION: Compile EINJ.
832  *
833  *****************************************************************************/
834 
835 ACPI_STATUS
836 DtCompileEinj (
837     void                    **List)
838 {
839     ACPI_STATUS             Status;
840 
841 
842     Status = DtCompileTwoSubtables (List,
843         AcpiDmTableInfoEinj, AcpiDmTableInfoEinj0);
844     return (Status);
845 }
846 
847 
848 /******************************************************************************
849  *
850  * FUNCTION:    DtCompileErst
851  *
852  * PARAMETERS:  List                - Current field list pointer
853  *
854  * RETURN:      Status
855  *
856  * DESCRIPTION: Compile ERST.
857  *
858  *****************************************************************************/
859 
860 ACPI_STATUS
861 DtCompileErst (
862     void                    **List)
863 {
864     ACPI_STATUS             Status;
865 
866 
867     Status = DtCompileTwoSubtables (List,
868         AcpiDmTableInfoErst, AcpiDmTableInfoEinj0);
869     return (Status);
870 }
871 
872 
873 /******************************************************************************
874  *
875  * FUNCTION:    DtCompileGtdt
876  *
877  * PARAMETERS:  List                - Current field list pointer
878  *
879  * RETURN:      Status
880  *
881  * DESCRIPTION: Compile GTDT.
882  *
883  *****************************************************************************/
884 
885 ACPI_STATUS
886 DtCompileGtdt (
887     void                    **List)
888 {
889     ACPI_STATUS             Status;
890     DT_SUBTABLE             *Subtable;
891     DT_SUBTABLE             *ParentTable;
892     DT_FIELD                **PFieldList = (DT_FIELD **) List;
893     DT_FIELD                *SubtableStart;
894     ACPI_SUBTABLE_HEADER    *GtdtHeader;
895     ACPI_DMTABLE_INFO       *InfoTable;
896     UINT32                  GtCount;
897     ACPI_TABLE_HEADER       *Header;
898 
899 
900     ParentTable = DtPeekSubtable ();
901 
902     Header = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer);
903 
904     /* Compile the main table */
905 
906     Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt,
907         &Subtable);
908     if (ACPI_FAILURE (Status))
909     {
910         return (Status);
911     }
912 
913     /* GTDT revision 3 later contains 2 extra fields before subtables */
914 
915     if (Header->Revision > 2)
916     {
917         ParentTable = DtPeekSubtable ();
918         DtInsertSubtable (ParentTable, Subtable);
919 
920         Status = DtCompileTable (PFieldList,
921             AcpiDmTableInfoGtdtEl2, &Subtable);
922         if (ACPI_FAILURE (Status))
923         {
924             return (Status);
925         }
926     }
927 
928     ParentTable = DtPeekSubtable ();
929     DtInsertSubtable (ParentTable, Subtable);
930 
931     while (*PFieldList)
932     {
933         SubtableStart = *PFieldList;
934         Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdtHdr,
935             &Subtable);
936         if (ACPI_FAILURE (Status))
937         {
938             return (Status);
939         }
940 
941         ParentTable = DtPeekSubtable ();
942         DtInsertSubtable (ParentTable, Subtable);
943         DtPushSubtable (Subtable);
944 
945         GtdtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer);
946 
947         switch (GtdtHeader->Type)
948         {
949         case ACPI_GTDT_TYPE_TIMER_BLOCK:
950 
951             InfoTable = AcpiDmTableInfoGtdt0;
952             break;
953 
954         case ACPI_GTDT_TYPE_WATCHDOG:
955 
956             InfoTable = AcpiDmTableInfoGtdt1;
957             break;
958 
959         default:
960 
961             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "GTDT");
962             return (AE_ERROR);
963         }
964 
965         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
966         if (ACPI_FAILURE (Status))
967         {
968             return (Status);
969         }
970 
971         ParentTable = DtPeekSubtable ();
972         DtInsertSubtable (ParentTable, Subtable);
973 
974         /*
975          * Additional GT block subtable data
976          */
977 
978         switch (GtdtHeader->Type)
979         {
980         case ACPI_GTDT_TYPE_TIMER_BLOCK:
981 
982             DtPushSubtable (Subtable);
983             ParentTable = DtPeekSubtable ();
984 
985             GtCount = (ACPI_CAST_PTR (ACPI_GTDT_TIMER_BLOCK,
986                 Subtable->Buffer - sizeof(ACPI_GTDT_HEADER)))->TimerCount;
987 
988             while (GtCount)
989             {
990                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt0a,
991                     &Subtable);
992                 if (ACPI_FAILURE (Status))
993                 {
994                     return (Status);
995                 }
996 
997                 DtInsertSubtable (ParentTable, Subtable);
998                 GtCount--;
999             }
1000 
1001             DtPopSubtable ();
1002             break;
1003 
1004         default:
1005 
1006             break;
1007         }
1008 
1009         DtPopSubtable ();
1010     }
1011 
1012     return (AE_OK);
1013 }
1014 
1015 
1016 /******************************************************************************
1017  *
1018  * FUNCTION:    DtCompileFpdt
1019  *
1020  * PARAMETERS:  List                - Current field list pointer
1021  *
1022  * RETURN:      Status
1023  *
1024  * DESCRIPTION: Compile FPDT.
1025  *
1026  *****************************************************************************/
1027 
1028 ACPI_STATUS
1029 DtCompileFpdt (
1030     void                    **List)
1031 {
1032     ACPI_STATUS             Status;
1033     ACPI_FPDT_HEADER        *FpdtHeader;
1034     DT_SUBTABLE             *Subtable;
1035     DT_SUBTABLE             *ParentTable;
1036     ACPI_DMTABLE_INFO       *InfoTable;
1037     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1038     DT_FIELD                *SubtableStart;
1039 
1040 
1041     while (*PFieldList)
1042     {
1043         SubtableStart = *PFieldList;
1044         Status = DtCompileTable (PFieldList, AcpiDmTableInfoFpdtHdr,
1045             &Subtable);
1046         if (ACPI_FAILURE (Status))
1047         {
1048             return (Status);
1049         }
1050 
1051         ParentTable = DtPeekSubtable ();
1052         DtInsertSubtable (ParentTable, Subtable);
1053         DtPushSubtable (Subtable);
1054 
1055         FpdtHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer);
1056 
1057         switch (FpdtHeader->Type)
1058         {
1059         case ACPI_FPDT_TYPE_BOOT:
1060 
1061             InfoTable = AcpiDmTableInfoFpdt0;
1062             break;
1063 
1064         case ACPI_FPDT_TYPE_S3PERF:
1065 
1066             InfoTable = AcpiDmTableInfoFpdt1;
1067             break;
1068 
1069         default:
1070 
1071             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "FPDT");
1072             return (AE_ERROR);
1073             break;
1074         }
1075 
1076         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1077         if (ACPI_FAILURE (Status))
1078         {
1079             return (Status);
1080         }
1081 
1082         ParentTable = DtPeekSubtable ();
1083         DtInsertSubtable (ParentTable, Subtable);
1084         DtPopSubtable ();
1085     }
1086 
1087     return (AE_OK);
1088 }
1089 
1090 
1091 /******************************************************************************
1092  *
1093  * FUNCTION:    DtCompileHest
1094  *
1095  * PARAMETERS:  List                - Current field list pointer
1096  *
1097  * RETURN:      Status
1098  *
1099  * DESCRIPTION: Compile HEST.
1100  *
1101  *****************************************************************************/
1102 
1103 ACPI_STATUS
1104 DtCompileHest (
1105     void                    **List)
1106 {
1107     ACPI_STATUS             Status;
1108     DT_SUBTABLE             *Subtable;
1109     DT_SUBTABLE             *ParentTable;
1110     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1111     DT_FIELD                *SubtableStart;
1112     ACPI_DMTABLE_INFO       *InfoTable;
1113     UINT16                  Type;
1114     UINT32                  BankCount;
1115 
1116 
1117     Status = DtCompileTable (PFieldList, AcpiDmTableInfoHest,
1118         &Subtable);
1119     if (ACPI_FAILURE (Status))
1120     {
1121         return (Status);
1122     }
1123 
1124     ParentTable = DtPeekSubtable ();
1125     DtInsertSubtable (ParentTable, Subtable);
1126 
1127     while (*PFieldList)
1128     {
1129         /* Get subtable type */
1130 
1131         SubtableStart = *PFieldList;
1132         DtCompileInteger ((UINT8 *) &Type, *PFieldList, 2, 0);
1133 
1134         switch (Type)
1135         {
1136         case ACPI_HEST_TYPE_IA32_CHECK:
1137 
1138             InfoTable = AcpiDmTableInfoHest0;
1139             break;
1140 
1141         case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
1142 
1143             InfoTable = AcpiDmTableInfoHest1;
1144             break;
1145 
1146         case ACPI_HEST_TYPE_IA32_NMI:
1147 
1148             InfoTable = AcpiDmTableInfoHest2;
1149             break;
1150 
1151         case ACPI_HEST_TYPE_AER_ROOT_PORT:
1152 
1153             InfoTable = AcpiDmTableInfoHest6;
1154             break;
1155 
1156         case ACPI_HEST_TYPE_AER_ENDPOINT:
1157 
1158             InfoTable = AcpiDmTableInfoHest7;
1159             break;
1160 
1161         case ACPI_HEST_TYPE_AER_BRIDGE:
1162 
1163             InfoTable = AcpiDmTableInfoHest8;
1164             break;
1165 
1166         case ACPI_HEST_TYPE_GENERIC_ERROR:
1167 
1168             InfoTable = AcpiDmTableInfoHest9;
1169             break;
1170 
1171         case ACPI_HEST_TYPE_GENERIC_ERROR_V2:
1172 
1173             InfoTable = AcpiDmTableInfoHest10;
1174             break;
1175 
1176         case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
1177 
1178             InfoTable = AcpiDmTableInfoHest11;
1179             break;
1180 
1181         default:
1182 
1183             /* Cannot continue on unknown type */
1184 
1185             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HEST");
1186             return (AE_ERROR);
1187         }
1188 
1189         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1190         if (ACPI_FAILURE (Status))
1191         {
1192             return (Status);
1193         }
1194 
1195         DtInsertSubtable (ParentTable, Subtable);
1196 
1197         /*
1198          * Additional subtable data - IA32 Error Bank(s)
1199          */
1200         BankCount = 0;
1201         switch (Type)
1202         {
1203         case ACPI_HEST_TYPE_IA32_CHECK:
1204 
1205             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK,
1206                 Subtable->Buffer))->NumHardwareBanks;
1207             break;
1208 
1209         case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
1210 
1211             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED,
1212                 Subtable->Buffer))->NumHardwareBanks;
1213             break;
1214 
1215         case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
1216 
1217             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_DEFERRED_CHECK,
1218                 Subtable->Buffer))->NumHardwareBanks;
1219             break;
1220 
1221         default:
1222 
1223             break;
1224         }
1225 
1226         while (BankCount)
1227         {
1228             Status = DtCompileTable (PFieldList, AcpiDmTableInfoHestBank,
1229                 &Subtable);
1230             if (ACPI_FAILURE (Status))
1231             {
1232                 return (Status);
1233             }
1234 
1235             DtInsertSubtable (ParentTable, Subtable);
1236             BankCount--;
1237         }
1238     }
1239 
1240     return (AE_OK);
1241 }
1242 
1243 
1244 /******************************************************************************
1245  *
1246  * FUNCTION:    DtCompileHmat
1247  *
1248  * PARAMETERS:  List                - Current field list pointer
1249  *
1250  * RETURN:      Status
1251  *
1252  * DESCRIPTION: Compile HMAT.
1253  *
1254  *****************************************************************************/
1255 
1256 ACPI_STATUS
1257 DtCompileHmat (
1258     void                    **List)
1259 {
1260     ACPI_STATUS             Status;
1261     DT_SUBTABLE             *Subtable;
1262     DT_SUBTABLE             *ParentTable;
1263     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1264     DT_FIELD                *SubtableStart;
1265     DT_FIELD                *EntryStart;
1266     ACPI_HMAT_STRUCTURE     *HmatStruct;
1267     ACPI_HMAT_LOCALITY      *HmatLocality;
1268     ACPI_HMAT_CACHE         *HmatCache;
1269     ACPI_DMTABLE_INFO       *InfoTable;
1270     UINT32                  IntPDNumber;
1271     UINT32                  TgtPDNumber;
1272     UINT64                  EntryNumber;
1273     UINT16                  SMBIOSHandleNumber;
1274 
1275 
1276     ParentTable = DtPeekSubtable ();
1277 
1278     Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmat,
1279         &Subtable);
1280     if (ACPI_FAILURE (Status))
1281     {
1282         return (Status);
1283     }
1284     DtInsertSubtable (ParentTable, Subtable);
1285 
1286     while (*PFieldList)
1287     {
1288         /* Compile HMAT structure header */
1289 
1290         SubtableStart = *PFieldList;
1291         Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmatHdr,
1292             &Subtable);
1293         if (ACPI_FAILURE (Status))
1294         {
1295             return (Status);
1296         }
1297         DtInsertSubtable (ParentTable, Subtable);
1298 
1299         HmatStruct = ACPI_CAST_PTR (ACPI_HMAT_STRUCTURE, Subtable->Buffer);
1300         HmatStruct->Length = Subtable->Length;
1301 
1302         /* Compile HMAT structure body */
1303 
1304         switch (HmatStruct->Type)
1305         {
1306         case ACPI_HMAT_TYPE_ADDRESS_RANGE:
1307 
1308             InfoTable = AcpiDmTableInfoHmat0;
1309             break;
1310 
1311         case ACPI_HMAT_TYPE_LOCALITY:
1312 
1313             InfoTable = AcpiDmTableInfoHmat1;
1314             break;
1315 
1316         case ACPI_HMAT_TYPE_CACHE:
1317 
1318             InfoTable = AcpiDmTableInfoHmat2;
1319             break;
1320 
1321         default:
1322 
1323             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HMAT");
1324             return (AE_ERROR);
1325         }
1326 
1327         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1328         if (ACPI_FAILURE (Status))
1329         {
1330             return (Status);
1331         }
1332         DtInsertSubtable (ParentTable, Subtable);
1333         HmatStruct->Length += Subtable->Length;
1334 
1335         /* Compile HMAT structure additionals */
1336 
1337         switch (HmatStruct->Type)
1338         {
1339         case ACPI_HMAT_TYPE_LOCALITY:
1340 
1341             HmatLocality = ACPI_SUB_PTR (ACPI_HMAT_LOCALITY,
1342                 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
1343 
1344             /* Compile initiator proximity domain list */
1345 
1346             IntPDNumber = 0;
1347             while (*PFieldList)
1348             {
1349                 Status = DtCompileTable (PFieldList,
1350                     AcpiDmTableInfoHmat1a, &Subtable);
1351                 if (ACPI_FAILURE (Status))
1352                 {
1353                     return (Status);
1354                 }
1355                 if (!Subtable)
1356                 {
1357                     break;
1358                 }
1359                 DtInsertSubtable (ParentTable, Subtable);
1360                 HmatStruct->Length += Subtable->Length;
1361                 IntPDNumber++;
1362             }
1363             HmatLocality->NumberOfInitiatorPDs = IntPDNumber;
1364 
1365             /* Compile target proximity domain list */
1366 
1367             TgtPDNumber = 0;
1368             while (*PFieldList)
1369             {
1370                 Status = DtCompileTable (PFieldList,
1371                     AcpiDmTableInfoHmat1b, &Subtable);
1372                 if (ACPI_FAILURE (Status))
1373                 {
1374                     return (Status);
1375                 }
1376                 if (!Subtable)
1377                 {
1378                     break;
1379                 }
1380                 DtInsertSubtable (ParentTable, Subtable);
1381                 HmatStruct->Length += Subtable->Length;
1382                 TgtPDNumber++;
1383             }
1384             HmatLocality->NumberOfTargetPDs = TgtPDNumber;
1385 
1386             /* Save start of the entries for reporting errors */
1387 
1388             EntryStart = *PFieldList;
1389 
1390             /* Compile latency/bandwidth entries */
1391 
1392             EntryNumber = 0;
1393             while (*PFieldList)
1394             {
1395                 Status = DtCompileTable (PFieldList,
1396                     AcpiDmTableInfoHmat1c, &Subtable);
1397                 if (ACPI_FAILURE (Status))
1398                 {
1399                     return (Status);
1400                 }
1401                 if (!Subtable)
1402                 {
1403                     break;
1404                 }
1405                 DtInsertSubtable (ParentTable, Subtable);
1406                 HmatStruct->Length += Subtable->Length;
1407                 EntryNumber++;
1408             }
1409 
1410             /* Validate number of entries */
1411 
1412             if (EntryNumber !=
1413                 ((UINT64)IntPDNumber * (UINT64)TgtPDNumber))
1414             {
1415                 DtFatal (ASL_MSG_INVALID_EXPRESSION, EntryStart, "HMAT");
1416                 return (AE_ERROR);
1417             }
1418             break;
1419 
1420         case ACPI_HMAT_TYPE_CACHE:
1421 
1422             /* Compile SMBIOS handles */
1423 
1424             HmatCache = ACPI_SUB_PTR (ACPI_HMAT_CACHE,
1425                 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
1426             SMBIOSHandleNumber = 0;
1427             while (*PFieldList)
1428             {
1429                 Status = DtCompileTable (PFieldList,
1430                     AcpiDmTableInfoHmat2a, &Subtable);
1431                 if (ACPI_FAILURE (Status))
1432                 {
1433                     return (Status);
1434                 }
1435                 if (!Subtable)
1436                 {
1437                     break;
1438                 }
1439                 DtInsertSubtable (ParentTable, Subtable);
1440                 HmatStruct->Length += Subtable->Length;
1441                 SMBIOSHandleNumber++;
1442             }
1443             HmatCache->NumberOfSMBIOSHandles = SMBIOSHandleNumber;
1444             break;
1445 
1446         default:
1447 
1448             break;
1449         }
1450     }
1451 
1452     return (AE_OK);
1453 }
1454 
1455 
1456 /******************************************************************************
1457  *
1458  * FUNCTION:    DtCompileIort
1459  *
1460  * PARAMETERS:  List                - Current field list pointer
1461  *
1462  * RETURN:      Status
1463  *
1464  * DESCRIPTION: Compile IORT.
1465  *
1466  *****************************************************************************/
1467 
1468 ACPI_STATUS
1469 DtCompileIort (
1470     void                    **List)
1471 {
1472     ACPI_STATUS             Status;
1473     DT_SUBTABLE             *Subtable;
1474     DT_SUBTABLE             *ParentTable;
1475     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1476     DT_FIELD                *SubtableStart;
1477     ACPI_TABLE_IORT         *Iort;
1478     ACPI_IORT_NODE          *IortNode;
1479     ACPI_IORT_ITS_GROUP     *IortItsGroup;
1480     ACPI_IORT_SMMU          *IortSmmu;
1481     UINT32                  NodeNumber;
1482     UINT32                  NodeLength;
1483     UINT32                  IdMappingNumber;
1484     UINT32                  ItsNumber;
1485     UINT32                  ContextIrptNumber;
1486     UINT32                  PmuIrptNumber;
1487     UINT32                  PaddingLength;
1488 
1489 
1490     ParentTable = DtPeekSubtable ();
1491 
1492     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort,
1493         &Subtable);
1494     if (ACPI_FAILURE (Status))
1495     {
1496         return (Status);
1497     }
1498     DtInsertSubtable (ParentTable, Subtable);
1499 
1500     /*
1501      * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
1502      * should be taken to avoid accessing ACPI_TABLE_HEADER fields.
1503      */
1504     Iort = ACPI_SUB_PTR (ACPI_TABLE_IORT,
1505         Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
1506 
1507     /*
1508      * OptionalPadding - Variable-length data
1509      * (Optional, size = OffsetToNodes - sizeof (ACPI_TABLE_IORT))
1510      * Optionally allows the generic data types to be used for filling
1511      * this field.
1512      */
1513     Iort->NodeOffset = sizeof (ACPI_TABLE_IORT);
1514     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortPad,
1515         &Subtable);
1516     if (ACPI_FAILURE (Status))
1517     {
1518         return (Status);
1519     }
1520     if (Subtable)
1521     {
1522         DtInsertSubtable (ParentTable, Subtable);
1523         Iort->NodeOffset += Subtable->Length;
1524     }
1525     else
1526     {
1527         Status = DtCompileGeneric (ACPI_CAST_PTR (void *, PFieldList),
1528             AcpiDmTableInfoIortHdr[0].Name, &PaddingLength);
1529         if (ACPI_FAILURE (Status))
1530         {
1531             return (Status);
1532         }
1533         Iort->NodeOffset += PaddingLength;
1534     }
1535 
1536     NodeNumber = 0;
1537     while (*PFieldList)
1538     {
1539         SubtableStart = *PFieldList;
1540         Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr,
1541             &Subtable);
1542         if (ACPI_FAILURE (Status))
1543         {
1544             return (Status);
1545         }
1546 
1547         DtInsertSubtable (ParentTable, Subtable);
1548         IortNode = ACPI_CAST_PTR (ACPI_IORT_NODE, Subtable->Buffer);
1549         NodeLength = ACPI_OFFSET (ACPI_IORT_NODE, NodeData);
1550 
1551         DtPushSubtable (Subtable);
1552         ParentTable = DtPeekSubtable ();
1553 
1554         switch (IortNode->Type)
1555         {
1556         case ACPI_IORT_NODE_ITS_GROUP:
1557 
1558             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0,
1559                 &Subtable);
1560             if (ACPI_FAILURE (Status))
1561             {
1562                 return (Status);
1563             }
1564 
1565             DtInsertSubtable (ParentTable, Subtable);
1566             IortItsGroup = ACPI_CAST_PTR (ACPI_IORT_ITS_GROUP, Subtable->Buffer);
1567             NodeLength += Subtable->Length;
1568 
1569             ItsNumber = 0;
1570             while (*PFieldList)
1571             {
1572                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0a,
1573                     &Subtable);
1574                 if (ACPI_FAILURE (Status))
1575                 {
1576                     return (Status);
1577                 }
1578                 if (!Subtable)
1579                 {
1580                     break;
1581                 }
1582 
1583                 DtInsertSubtable (ParentTable, Subtable);
1584                 NodeLength += Subtable->Length;
1585                 ItsNumber++;
1586             }
1587 
1588             IortItsGroup->ItsCount = ItsNumber;
1589             break;
1590 
1591         case ACPI_IORT_NODE_NAMED_COMPONENT:
1592 
1593             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1,
1594                 &Subtable);
1595             if (ACPI_FAILURE (Status))
1596             {
1597                 return (Status);
1598             }
1599 
1600             DtInsertSubtable (ParentTable, Subtable);
1601             NodeLength += Subtable->Length;
1602 
1603             /*
1604              * Padding - Variable-length data
1605              * Optionally allows the offset of the ID mappings to be used
1606              * for filling this field.
1607              */
1608             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1a,
1609                 &Subtable);
1610             if (ACPI_FAILURE (Status))
1611             {
1612                 return (Status);
1613             }
1614 
1615             if (Subtable)
1616             {
1617                 DtInsertSubtable (ParentTable, Subtable);
1618                 NodeLength += Subtable->Length;
1619             }
1620             else
1621             {
1622                 if (NodeLength > IortNode->MappingOffset)
1623                 {
1624                     return (AE_BAD_DATA);
1625                 }
1626 
1627                 if (NodeLength < IortNode->MappingOffset)
1628                 {
1629                     Status = DtCompilePadding (
1630                         IortNode->MappingOffset - NodeLength,
1631                         &Subtable);
1632                     if (ACPI_FAILURE (Status))
1633                     {
1634                         return (Status);
1635                     }
1636 
1637                     DtInsertSubtable (ParentTable, Subtable);
1638                     NodeLength = IortNode->MappingOffset;
1639                 }
1640             }
1641             break;
1642 
1643         case ACPI_IORT_NODE_PCI_ROOT_COMPLEX:
1644 
1645             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort2,
1646                 &Subtable);
1647             if (ACPI_FAILURE (Status))
1648             {
1649                 return (Status);
1650             }
1651 
1652             DtInsertSubtable (ParentTable, Subtable);
1653             NodeLength += Subtable->Length;
1654             break;
1655 
1656         case ACPI_IORT_NODE_SMMU:
1657 
1658             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3,
1659                 &Subtable);
1660             if (ACPI_FAILURE (Status))
1661             {
1662                 return (Status);
1663             }
1664 
1665             DtInsertSubtable (ParentTable, Subtable);
1666             IortSmmu = ACPI_CAST_PTR (ACPI_IORT_SMMU, Subtable->Buffer);
1667             NodeLength += Subtable->Length;
1668 
1669             /* Compile global interrupt array */
1670 
1671             IortSmmu->GlobalInterruptOffset = NodeLength;
1672             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3a,
1673                 &Subtable);
1674             if (ACPI_FAILURE (Status))
1675             {
1676                 return (Status);
1677             }
1678 
1679             DtInsertSubtable (ParentTable, Subtable);
1680             NodeLength += Subtable->Length;
1681 
1682             /* Compile context interrupt array */
1683 
1684             ContextIrptNumber = 0;
1685             IortSmmu->ContextInterruptOffset = NodeLength;
1686             while (*PFieldList)
1687             {
1688                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3b,
1689                     &Subtable);
1690                 if (ACPI_FAILURE (Status))
1691                 {
1692                     return (Status);
1693                 }
1694 
1695                 if (!Subtable)
1696                 {
1697                     break;
1698                 }
1699 
1700                 DtInsertSubtable (ParentTable, Subtable);
1701                 NodeLength += Subtable->Length;
1702                 ContextIrptNumber++;
1703             }
1704 
1705             IortSmmu->ContextInterruptCount = ContextIrptNumber;
1706 
1707             /* Compile PMU interrupt array */
1708 
1709             PmuIrptNumber = 0;
1710             IortSmmu->PmuInterruptOffset = NodeLength;
1711             while (*PFieldList)
1712             {
1713                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3c,
1714                     &Subtable);
1715                 if (ACPI_FAILURE (Status))
1716                 {
1717                     return (Status);
1718                 }
1719 
1720                 if (!Subtable)
1721                 {
1722                     break;
1723                 }
1724 
1725                 DtInsertSubtable (ParentTable, Subtable);
1726                 NodeLength += Subtable->Length;
1727                 PmuIrptNumber++;
1728             }
1729 
1730             IortSmmu->PmuInterruptCount = PmuIrptNumber;
1731             break;
1732 
1733         case ACPI_IORT_NODE_SMMU_V3:
1734 
1735             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort4,
1736                 &Subtable);
1737             if (ACPI_FAILURE (Status))
1738             {
1739                 return (Status);
1740             }
1741 
1742             DtInsertSubtable (ParentTable, Subtable);
1743             NodeLength += Subtable->Length;
1744             break;
1745 
1746         case ACPI_IORT_NODE_PMCG:
1747 
1748             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort5,
1749                 &Subtable);
1750             if (ACPI_FAILURE (Status))
1751             {
1752                 return (Status);
1753             }
1754 
1755             DtInsertSubtable (ParentTable, Subtable);
1756             NodeLength += Subtable->Length;
1757             break;
1758 
1759         default:
1760 
1761             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IORT");
1762             return (AE_ERROR);
1763         }
1764 
1765         /* Compile Array of ID mappings */
1766 
1767         IortNode->MappingOffset = NodeLength;
1768         IdMappingNumber = 0;
1769         while (*PFieldList)
1770         {
1771             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortMap,
1772                 &Subtable);
1773             if (ACPI_FAILURE (Status))
1774             {
1775                 return (Status);
1776             }
1777 
1778             if (!Subtable)
1779             {
1780                 break;
1781             }
1782 
1783             DtInsertSubtable (ParentTable, Subtable);
1784             NodeLength += sizeof (ACPI_IORT_ID_MAPPING);
1785             IdMappingNumber++;
1786         }
1787 
1788         IortNode->MappingCount = IdMappingNumber;
1789         if (!IdMappingNumber)
1790         {
1791             IortNode->MappingOffset = 0;
1792         }
1793 
1794         /*
1795          * Node length can be determined by DT_LENGTH option
1796          * IortNode->Length = NodeLength;
1797          */
1798         DtPopSubtable ();
1799         ParentTable = DtPeekSubtable ();
1800         NodeNumber++;
1801     }
1802 
1803     Iort->NodeCount = NodeNumber;
1804     return (AE_OK);
1805 }
1806 
1807 
1808 /******************************************************************************
1809  *
1810  * FUNCTION:    DtCompileIvrs
1811  *
1812  * PARAMETERS:  List                - Current field list pointer
1813  *
1814  * RETURN:      Status
1815  *
1816  * DESCRIPTION: Compile IVRS.
1817  *
1818  *****************************************************************************/
1819 
1820 ACPI_STATUS
1821 DtCompileIvrs (
1822     void                    **List)
1823 {
1824     ACPI_STATUS             Status;
1825     DT_SUBTABLE             *Subtable;
1826     DT_SUBTABLE             *ParentTable;
1827     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1828     DT_FIELD                *SubtableStart;
1829     ACPI_DMTABLE_INFO       *InfoTable;
1830     ACPI_IVRS_HEADER        *IvrsHeader;
1831     UINT8                   EntryType;
1832 
1833 
1834     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrs,
1835         &Subtable);
1836     if (ACPI_FAILURE (Status))
1837     {
1838         return (Status);
1839     }
1840 
1841     ParentTable = DtPeekSubtable ();
1842     DtInsertSubtable (ParentTable, Subtable);
1843 
1844     while (*PFieldList)
1845     {
1846         SubtableStart = *PFieldList;
1847         Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHdr,
1848             &Subtable);
1849         if (ACPI_FAILURE (Status))
1850         {
1851             return (Status);
1852         }
1853 
1854         ParentTable = DtPeekSubtable ();
1855         DtInsertSubtable (ParentTable, Subtable);
1856         DtPushSubtable (Subtable);
1857 
1858         IvrsHeader = ACPI_CAST_PTR (ACPI_IVRS_HEADER, Subtable->Buffer);
1859 
1860         switch (IvrsHeader->Type)
1861         {
1862         case ACPI_IVRS_TYPE_HARDWARE1:
1863 
1864             InfoTable = AcpiDmTableInfoIvrs0;
1865             break;
1866 
1867         case ACPI_IVRS_TYPE_HARDWARE2:
1868 
1869             InfoTable = AcpiDmTableInfoIvrs01;
1870             break;
1871 
1872         case ACPI_IVRS_TYPE_MEMORY1:
1873         case ACPI_IVRS_TYPE_MEMORY2:
1874         case ACPI_IVRS_TYPE_MEMORY3:
1875 
1876             InfoTable = AcpiDmTableInfoIvrs1;
1877             break;
1878 
1879         default:
1880 
1881             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IVRS");
1882             return (AE_ERROR);
1883         }
1884 
1885         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1886         if (ACPI_FAILURE (Status))
1887         {
1888             return (Status);
1889         }
1890 
1891         ParentTable = DtPeekSubtable ();
1892         DtInsertSubtable (ParentTable, Subtable);
1893 
1894         if (IvrsHeader->Type == ACPI_IVRS_TYPE_HARDWARE1 ||
1895             IvrsHeader->Type == ACPI_IVRS_TYPE_HARDWARE2)
1896         {
1897             while (*PFieldList &&
1898                 !strcmp ((*PFieldList)->Name, "Entry Type"))
1899             {
1900                 SubtableStart = *PFieldList;
1901                 DtCompileInteger (&EntryType, *PFieldList, 1, 0);
1902 
1903                 switch (EntryType)
1904                 {
1905                 /* 4-byte device entries */
1906 
1907                 case ACPI_IVRS_TYPE_PAD4:
1908                 case ACPI_IVRS_TYPE_ALL:
1909                 case ACPI_IVRS_TYPE_SELECT:
1910                 case ACPI_IVRS_TYPE_START:
1911                 case ACPI_IVRS_TYPE_END:
1912 
1913                     InfoTable = AcpiDmTableInfoIvrs4;
1914                     break;
1915 
1916                 /* 8-byte entries, type A */
1917 
1918                 case ACPI_IVRS_TYPE_ALIAS_SELECT:
1919                 case ACPI_IVRS_TYPE_ALIAS_START:
1920 
1921                     InfoTable = AcpiDmTableInfoIvrs8a;
1922                     break;
1923 
1924                 /* 8-byte entries, type B */
1925 
1926                 case ACPI_IVRS_TYPE_PAD8:
1927                 case ACPI_IVRS_TYPE_EXT_SELECT:
1928                 case ACPI_IVRS_TYPE_EXT_START:
1929 
1930                     InfoTable = AcpiDmTableInfoIvrs8b;
1931                     break;
1932 
1933                 /* 8-byte entries, type C */
1934 
1935                 case ACPI_IVRS_TYPE_SPECIAL:
1936 
1937                     InfoTable = AcpiDmTableInfoIvrs8c;
1938                     break;
1939 
1940                 default:
1941 
1942                     DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart,
1943                         "IVRS Device Entry");
1944                     return (AE_ERROR);
1945                 }
1946 
1947                 Status = DtCompileTable (PFieldList, InfoTable,
1948                     &Subtable);
1949                 if (ACPI_FAILURE (Status))
1950                 {
1951                     return (Status);
1952                 }
1953 
1954                 DtInsertSubtable (ParentTable, Subtable);
1955             }
1956         }
1957 
1958         DtPopSubtable ();
1959     }
1960 
1961     return (AE_OK);
1962 }
1963