xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/dttable1.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /******************************************************************************
2  *
3  * Module Name: dttable1.c - handling for specific ACPI tables
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2018, 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 seperate 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 
898 
899     Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt,
900         &Subtable);
901     if (ACPI_FAILURE (Status))
902     {
903         return (Status);
904     }
905 
906     ParentTable = DtPeekSubtable ();
907     DtInsertSubtable (ParentTable, Subtable);
908 
909     while (*PFieldList)
910     {
911         SubtableStart = *PFieldList;
912         Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdtHdr,
913             &Subtable);
914         if (ACPI_FAILURE (Status))
915         {
916             return (Status);
917         }
918 
919         ParentTable = DtPeekSubtable ();
920         DtInsertSubtable (ParentTable, Subtable);
921         DtPushSubtable (Subtable);
922 
923         GtdtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer);
924 
925         switch (GtdtHeader->Type)
926         {
927         case ACPI_GTDT_TYPE_TIMER_BLOCK:
928 
929             InfoTable = AcpiDmTableInfoGtdt0;
930             break;
931 
932         case ACPI_GTDT_TYPE_WATCHDOG:
933 
934             InfoTable = AcpiDmTableInfoGtdt1;
935             break;
936 
937         default:
938 
939             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "GTDT");
940             return (AE_ERROR);
941         }
942 
943         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
944         if (ACPI_FAILURE (Status))
945         {
946             return (Status);
947         }
948 
949         ParentTable = DtPeekSubtable ();
950         DtInsertSubtable (ParentTable, Subtable);
951 
952         /*
953          * Additional GT block subtable data
954          */
955 
956         switch (GtdtHeader->Type)
957         {
958         case ACPI_GTDT_TYPE_TIMER_BLOCK:
959 
960             DtPushSubtable (Subtable);
961             ParentTable = DtPeekSubtable ();
962 
963             GtCount = (ACPI_CAST_PTR (ACPI_GTDT_TIMER_BLOCK,
964                 Subtable->Buffer - sizeof(ACPI_GTDT_HEADER)))->TimerCount;
965 
966             while (GtCount)
967             {
968                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt0a,
969                     &Subtable);
970                 if (ACPI_FAILURE (Status))
971                 {
972                     return (Status);
973                 }
974 
975                 DtInsertSubtable (ParentTable, Subtable);
976                 GtCount--;
977             }
978 
979             DtPopSubtable ();
980             break;
981 
982         default:
983 
984             break;
985         }
986 
987         DtPopSubtable ();
988     }
989 
990     return (AE_OK);
991 }
992 
993 
994 /******************************************************************************
995  *
996  * FUNCTION:    DtCompileFpdt
997  *
998  * PARAMETERS:  List                - Current field list pointer
999  *
1000  * RETURN:      Status
1001  *
1002  * DESCRIPTION: Compile FPDT.
1003  *
1004  *****************************************************************************/
1005 
1006 ACPI_STATUS
1007 DtCompileFpdt (
1008     void                    **List)
1009 {
1010     ACPI_STATUS             Status;
1011     ACPI_FPDT_HEADER        *FpdtHeader;
1012     DT_SUBTABLE             *Subtable;
1013     DT_SUBTABLE             *ParentTable;
1014     ACPI_DMTABLE_INFO       *InfoTable;
1015     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1016     DT_FIELD                *SubtableStart;
1017 
1018 
1019     while (*PFieldList)
1020     {
1021         SubtableStart = *PFieldList;
1022         Status = DtCompileTable (PFieldList, AcpiDmTableInfoFpdtHdr,
1023             &Subtable);
1024         if (ACPI_FAILURE (Status))
1025         {
1026             return (Status);
1027         }
1028 
1029         ParentTable = DtPeekSubtable ();
1030         DtInsertSubtable (ParentTable, Subtable);
1031         DtPushSubtable (Subtable);
1032 
1033         FpdtHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer);
1034 
1035         switch (FpdtHeader->Type)
1036         {
1037         case ACPI_FPDT_TYPE_BOOT:
1038 
1039             InfoTable = AcpiDmTableInfoFpdt0;
1040             break;
1041 
1042         case ACPI_FPDT_TYPE_S3PERF:
1043 
1044             InfoTable = AcpiDmTableInfoFpdt1;
1045             break;
1046 
1047         default:
1048 
1049             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "FPDT");
1050             return (AE_ERROR);
1051             break;
1052         }
1053 
1054         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1055         if (ACPI_FAILURE (Status))
1056         {
1057             return (Status);
1058         }
1059 
1060         ParentTable = DtPeekSubtable ();
1061         DtInsertSubtable (ParentTable, Subtable);
1062         DtPopSubtable ();
1063     }
1064 
1065     return (AE_OK);
1066 }
1067 
1068 
1069 /******************************************************************************
1070  *
1071  * FUNCTION:    DtCompileHest
1072  *
1073  * PARAMETERS:  List                - Current field list pointer
1074  *
1075  * RETURN:      Status
1076  *
1077  * DESCRIPTION: Compile HEST.
1078  *
1079  *****************************************************************************/
1080 
1081 ACPI_STATUS
1082 DtCompileHest (
1083     void                    **List)
1084 {
1085     ACPI_STATUS             Status;
1086     DT_SUBTABLE             *Subtable;
1087     DT_SUBTABLE             *ParentTable;
1088     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1089     DT_FIELD                *SubtableStart;
1090     ACPI_DMTABLE_INFO       *InfoTable;
1091     UINT16                  Type;
1092     UINT32                  BankCount;
1093 
1094 
1095     Status = DtCompileTable (PFieldList, AcpiDmTableInfoHest,
1096         &Subtable);
1097     if (ACPI_FAILURE (Status))
1098     {
1099         return (Status);
1100     }
1101 
1102     ParentTable = DtPeekSubtable ();
1103     DtInsertSubtable (ParentTable, Subtable);
1104 
1105     while (*PFieldList)
1106     {
1107         /* Get subtable type */
1108 
1109         SubtableStart = *PFieldList;
1110         DtCompileInteger ((UINT8 *) &Type, *PFieldList, 2, 0);
1111 
1112         switch (Type)
1113         {
1114         case ACPI_HEST_TYPE_IA32_CHECK:
1115 
1116             InfoTable = AcpiDmTableInfoHest0;
1117             break;
1118 
1119         case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
1120 
1121             InfoTable = AcpiDmTableInfoHest1;
1122             break;
1123 
1124         case ACPI_HEST_TYPE_IA32_NMI:
1125 
1126             InfoTable = AcpiDmTableInfoHest2;
1127             break;
1128 
1129         case ACPI_HEST_TYPE_AER_ROOT_PORT:
1130 
1131             InfoTable = AcpiDmTableInfoHest6;
1132             break;
1133 
1134         case ACPI_HEST_TYPE_AER_ENDPOINT:
1135 
1136             InfoTable = AcpiDmTableInfoHest7;
1137             break;
1138 
1139         case ACPI_HEST_TYPE_AER_BRIDGE:
1140 
1141             InfoTable = AcpiDmTableInfoHest8;
1142             break;
1143 
1144         case ACPI_HEST_TYPE_GENERIC_ERROR:
1145 
1146             InfoTable = AcpiDmTableInfoHest9;
1147             break;
1148 
1149         case ACPI_HEST_TYPE_GENERIC_ERROR_V2:
1150 
1151             InfoTable = AcpiDmTableInfoHest10;
1152             break;
1153 
1154         case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
1155 
1156             InfoTable = AcpiDmTableInfoHest11;
1157             break;
1158 
1159         default:
1160 
1161             /* Cannot continue on unknown type */
1162 
1163             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HEST");
1164             return (AE_ERROR);
1165         }
1166 
1167         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1168         if (ACPI_FAILURE (Status))
1169         {
1170             return (Status);
1171         }
1172 
1173         DtInsertSubtable (ParentTable, Subtable);
1174 
1175         /*
1176          * Additional subtable data - IA32 Error Bank(s)
1177          */
1178         BankCount = 0;
1179         switch (Type)
1180         {
1181         case ACPI_HEST_TYPE_IA32_CHECK:
1182 
1183             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK,
1184                 Subtable->Buffer))->NumHardwareBanks;
1185             break;
1186 
1187         case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
1188 
1189             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED,
1190                 Subtable->Buffer))->NumHardwareBanks;
1191             break;
1192 
1193         case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
1194 
1195             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_DEFERRED_CHECK,
1196                 Subtable->Buffer))->NumHardwareBanks;
1197             break;
1198 
1199         default:
1200 
1201             break;
1202         }
1203 
1204         while (BankCount)
1205         {
1206             Status = DtCompileTable (PFieldList, AcpiDmTableInfoHestBank,
1207                 &Subtable);
1208             if (ACPI_FAILURE (Status))
1209             {
1210                 return (Status);
1211             }
1212 
1213             DtInsertSubtable (ParentTable, Subtable);
1214             BankCount--;
1215         }
1216     }
1217 
1218     return (AE_OK);
1219 }
1220 
1221 
1222 /******************************************************************************
1223  *
1224  * FUNCTION:    DtCompileHmat
1225  *
1226  * PARAMETERS:  List                - Current field list pointer
1227  *
1228  * RETURN:      Status
1229  *
1230  * DESCRIPTION: Compile HMAT.
1231  *
1232  *****************************************************************************/
1233 
1234 ACPI_STATUS
1235 DtCompileHmat (
1236     void                    **List)
1237 {
1238     ACPI_STATUS             Status;
1239     DT_SUBTABLE             *Subtable;
1240     DT_SUBTABLE             *ParentTable;
1241     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1242     DT_FIELD                *SubtableStart;
1243     DT_FIELD                *EntryStart;
1244     ACPI_HMAT_STRUCTURE     *HmatStruct;
1245     ACPI_HMAT_LOCALITY      *HmatLocality;
1246     ACPI_HMAT_CACHE         *HmatCache;
1247     ACPI_DMTABLE_INFO       *InfoTable;
1248     UINT32                  IntPDNumber;
1249     UINT32                  TgtPDNumber;
1250     UINT64                  EntryNumber;
1251     UINT16                  SMBIOSHandleNumber;
1252 
1253 
1254     ParentTable = DtPeekSubtable ();
1255 
1256     Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmat,
1257         &Subtable);
1258     if (ACPI_FAILURE (Status))
1259     {
1260         return (Status);
1261     }
1262     DtInsertSubtable (ParentTable, Subtable);
1263 
1264     while (*PFieldList)
1265     {
1266         /* Compile HMAT structure header */
1267 
1268         SubtableStart = *PFieldList;
1269         Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmatHdr,
1270             &Subtable);
1271         if (ACPI_FAILURE (Status))
1272         {
1273             return (Status);
1274         }
1275         DtInsertSubtable (ParentTable, Subtable);
1276 
1277         HmatStruct = ACPI_CAST_PTR (ACPI_HMAT_STRUCTURE, Subtable->Buffer);
1278         HmatStruct->Length = Subtable->Length;
1279 
1280         /* Compile HMAT structure body */
1281 
1282         switch (HmatStruct->Type)
1283         {
1284         case ACPI_HMAT_TYPE_ADDRESS_RANGE:
1285 
1286             InfoTable = AcpiDmTableInfoHmat0;
1287             break;
1288 
1289         case ACPI_HMAT_TYPE_LOCALITY:
1290 
1291             InfoTable = AcpiDmTableInfoHmat1;
1292             break;
1293 
1294         case ACPI_HMAT_TYPE_CACHE:
1295 
1296             InfoTable = AcpiDmTableInfoHmat2;
1297             break;
1298 
1299         default:
1300 
1301             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HMAT");
1302             return (AE_ERROR);
1303         }
1304 
1305         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1306         if (ACPI_FAILURE (Status))
1307         {
1308             return (Status);
1309         }
1310         DtInsertSubtable (ParentTable, Subtable);
1311         HmatStruct->Length += Subtable->Length;
1312 
1313         /* Compile HMAT structure additionals */
1314 
1315         switch (HmatStruct->Type)
1316         {
1317         case ACPI_HMAT_TYPE_LOCALITY:
1318 
1319             HmatLocality = ACPI_SUB_PTR (ACPI_HMAT_LOCALITY,
1320                 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
1321 
1322             /* Compile initiator proximity domain list */
1323 
1324             IntPDNumber = 0;
1325             while (*PFieldList)
1326             {
1327                 Status = DtCompileTable (PFieldList,
1328                     AcpiDmTableInfoHmat1a, &Subtable);
1329                 if (ACPI_FAILURE (Status))
1330                 {
1331                     return (Status);
1332                 }
1333                 if (!Subtable)
1334                 {
1335                     break;
1336                 }
1337                 DtInsertSubtable (ParentTable, Subtable);
1338                 HmatStruct->Length += Subtable->Length;
1339                 IntPDNumber++;
1340             }
1341             HmatLocality->NumberOfInitiatorPDs = IntPDNumber;
1342 
1343             /* Compile target proximity domain list */
1344 
1345             TgtPDNumber = 0;
1346             while (*PFieldList)
1347             {
1348                 Status = DtCompileTable (PFieldList,
1349                     AcpiDmTableInfoHmat1b, &Subtable);
1350                 if (ACPI_FAILURE (Status))
1351                 {
1352                     return (Status);
1353                 }
1354                 if (!Subtable)
1355                 {
1356                     break;
1357                 }
1358                 DtInsertSubtable (ParentTable, Subtable);
1359                 HmatStruct->Length += Subtable->Length;
1360                 TgtPDNumber++;
1361             }
1362             HmatLocality->NumberOfTargetPDs = TgtPDNumber;
1363 
1364             /* Save start of the entries for reporting errors */
1365 
1366             EntryStart = *PFieldList;
1367 
1368             /* Compile latency/bandwidth entries */
1369 
1370             EntryNumber = 0;
1371             while (*PFieldList)
1372             {
1373                 Status = DtCompileTable (PFieldList,
1374                     AcpiDmTableInfoHmat1c, &Subtable);
1375                 if (ACPI_FAILURE (Status))
1376                 {
1377                     return (Status);
1378                 }
1379                 if (!Subtable)
1380                 {
1381                     break;
1382                 }
1383                 DtInsertSubtable (ParentTable, Subtable);
1384                 HmatStruct->Length += Subtable->Length;
1385                 EntryNumber++;
1386             }
1387 
1388             /* Validate number of entries */
1389 
1390             if (EntryNumber !=
1391                 ((UINT64)IntPDNumber * (UINT64)TgtPDNumber))
1392             {
1393                 DtFatal (ASL_MSG_INVALID_EXPRESSION, EntryStart, "HMAT");
1394                 return (AE_ERROR);
1395             }
1396             break;
1397 
1398         case ACPI_HMAT_TYPE_CACHE:
1399 
1400             /* Compile SMBIOS handles */
1401 
1402             HmatCache = ACPI_SUB_PTR (ACPI_HMAT_CACHE,
1403                 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
1404             SMBIOSHandleNumber = 0;
1405             while (*PFieldList)
1406             {
1407                 Status = DtCompileTable (PFieldList,
1408                     AcpiDmTableInfoHmat2a, &Subtable);
1409                 if (ACPI_FAILURE (Status))
1410                 {
1411                     return (Status);
1412                 }
1413                 if (!Subtable)
1414                 {
1415                     break;
1416                 }
1417                 DtInsertSubtable (ParentTable, Subtable);
1418                 HmatStruct->Length += Subtable->Length;
1419                 SMBIOSHandleNumber++;
1420             }
1421             HmatCache->NumberOfSMBIOSHandles = SMBIOSHandleNumber;
1422             break;
1423 
1424         default:
1425 
1426             break;
1427         }
1428     }
1429 
1430     return (AE_OK);
1431 }
1432 
1433 
1434 /******************************************************************************
1435  *
1436  * FUNCTION:    DtCompileIort
1437  *
1438  * PARAMETERS:  List                - Current field list pointer
1439  *
1440  * RETURN:      Status
1441  *
1442  * DESCRIPTION: Compile IORT.
1443  *
1444  *****************************************************************************/
1445 
1446 ACPI_STATUS
1447 DtCompileIort (
1448     void                    **List)
1449 {
1450     ACPI_STATUS             Status;
1451     DT_SUBTABLE             *Subtable;
1452     DT_SUBTABLE             *ParentTable;
1453     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1454     DT_FIELD                *SubtableStart;
1455     ACPI_TABLE_IORT         *Iort;
1456     ACPI_IORT_NODE          *IortNode;
1457     ACPI_IORT_ITS_GROUP     *IortItsGroup;
1458     ACPI_IORT_SMMU          *IortSmmu;
1459     UINT32                  NodeNumber;
1460     UINT32                  NodeLength;
1461     UINT32                  IdMappingNumber;
1462     UINT32                  ItsNumber;
1463     UINT32                  ContextIrptNumber;
1464     UINT32                  PmuIrptNumber;
1465     UINT32                  PaddingLength;
1466 
1467 
1468     ParentTable = DtPeekSubtable ();
1469 
1470     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort,
1471         &Subtable);
1472     if (ACPI_FAILURE (Status))
1473     {
1474         return (Status);
1475     }
1476     DtInsertSubtable (ParentTable, Subtable);
1477 
1478     /*
1479      * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
1480      * should be taken to avoid accessing ACPI_TABLE_HEADER fields.
1481      */
1482     Iort = ACPI_SUB_PTR (ACPI_TABLE_IORT,
1483         Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
1484 
1485     /*
1486      * OptionalPadding - Variable-length data
1487      * (Optional, size = OffsetToNodes - sizeof (ACPI_TABLE_IORT))
1488      * Optionally allows the generic data types to be used for filling
1489      * this field.
1490      */
1491     Iort->NodeOffset = sizeof (ACPI_TABLE_IORT);
1492     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortPad,
1493         &Subtable);
1494     if (ACPI_FAILURE (Status))
1495     {
1496         return (Status);
1497     }
1498     if (Subtable)
1499     {
1500         DtInsertSubtable (ParentTable, Subtable);
1501         Iort->NodeOffset += Subtable->Length;
1502     }
1503     else
1504     {
1505         Status = DtCompileGeneric (ACPI_CAST_PTR (void *, PFieldList),
1506             AcpiDmTableInfoIortHdr[0].Name, &PaddingLength);
1507         if (ACPI_FAILURE (Status))
1508         {
1509             return (Status);
1510         }
1511         Iort->NodeOffset += PaddingLength;
1512     }
1513 
1514     NodeNumber = 0;
1515     while (*PFieldList)
1516     {
1517         SubtableStart = *PFieldList;
1518         Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr,
1519             &Subtable);
1520         if (ACPI_FAILURE (Status))
1521         {
1522             return (Status);
1523         }
1524 
1525         DtInsertSubtable (ParentTable, Subtable);
1526         IortNode = ACPI_CAST_PTR (ACPI_IORT_NODE, Subtable->Buffer);
1527         NodeLength = ACPI_OFFSET (ACPI_IORT_NODE, NodeData);
1528 
1529         DtPushSubtable (Subtable);
1530         ParentTable = DtPeekSubtable ();
1531 
1532         switch (IortNode->Type)
1533         {
1534         case ACPI_IORT_NODE_ITS_GROUP:
1535 
1536             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0,
1537                 &Subtable);
1538             if (ACPI_FAILURE (Status))
1539             {
1540                 return (Status);
1541             }
1542 
1543             DtInsertSubtable (ParentTable, Subtable);
1544             IortItsGroup = ACPI_CAST_PTR (ACPI_IORT_ITS_GROUP, Subtable->Buffer);
1545             NodeLength += Subtable->Length;
1546 
1547             ItsNumber = 0;
1548             while (*PFieldList)
1549             {
1550                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0a,
1551                     &Subtable);
1552                 if (ACPI_FAILURE (Status))
1553                 {
1554                     return (Status);
1555                 }
1556                 if (!Subtable)
1557                 {
1558                     break;
1559                 }
1560 
1561                 DtInsertSubtable (ParentTable, Subtable);
1562                 NodeLength += Subtable->Length;
1563                 ItsNumber++;
1564             }
1565 
1566             IortItsGroup->ItsCount = ItsNumber;
1567             break;
1568 
1569         case ACPI_IORT_NODE_NAMED_COMPONENT:
1570 
1571             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1,
1572                 &Subtable);
1573             if (ACPI_FAILURE (Status))
1574             {
1575                 return (Status);
1576             }
1577 
1578             DtInsertSubtable (ParentTable, Subtable);
1579             NodeLength += Subtable->Length;
1580 
1581             /*
1582              * Padding - Variable-length data
1583              * Optionally allows the offset of the ID mappings to be used
1584              * for filling this field.
1585              */
1586             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1a,
1587                 &Subtable);
1588             if (ACPI_FAILURE (Status))
1589             {
1590                 return (Status);
1591             }
1592 
1593             if (Subtable)
1594             {
1595                 DtInsertSubtable (ParentTable, Subtable);
1596                 NodeLength += Subtable->Length;
1597             }
1598             else
1599             {
1600                 if (NodeLength > IortNode->MappingOffset)
1601                 {
1602                     return (AE_BAD_DATA);
1603                 }
1604 
1605                 if (NodeLength < IortNode->MappingOffset)
1606                 {
1607                     Status = DtCompilePadding (
1608                         IortNode->MappingOffset - NodeLength,
1609                         &Subtable);
1610                     if (ACPI_FAILURE (Status))
1611                     {
1612                         return (Status);
1613                     }
1614 
1615                     DtInsertSubtable (ParentTable, Subtable);
1616                     NodeLength = IortNode->MappingOffset;
1617                 }
1618             }
1619             break;
1620 
1621         case ACPI_IORT_NODE_PCI_ROOT_COMPLEX:
1622 
1623             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort2,
1624                 &Subtable);
1625             if (ACPI_FAILURE (Status))
1626             {
1627                 return (Status);
1628             }
1629 
1630             DtInsertSubtable (ParentTable, Subtable);
1631             NodeLength += Subtable->Length;
1632             break;
1633 
1634         case ACPI_IORT_NODE_SMMU:
1635 
1636             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3,
1637                 &Subtable);
1638             if (ACPI_FAILURE (Status))
1639             {
1640                 return (Status);
1641             }
1642 
1643             DtInsertSubtable (ParentTable, Subtable);
1644             IortSmmu = ACPI_CAST_PTR (ACPI_IORT_SMMU, Subtable->Buffer);
1645             NodeLength += Subtable->Length;
1646 
1647             /* Compile global interrupt array */
1648 
1649             IortSmmu->GlobalInterruptOffset = NodeLength;
1650             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3a,
1651                 &Subtable);
1652             if (ACPI_FAILURE (Status))
1653             {
1654                 return (Status);
1655             }
1656 
1657             DtInsertSubtable (ParentTable, Subtable);
1658             NodeLength += Subtable->Length;
1659 
1660             /* Compile context interrupt array */
1661 
1662             ContextIrptNumber = 0;
1663             IortSmmu->ContextInterruptOffset = NodeLength;
1664             while (*PFieldList)
1665             {
1666                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3b,
1667                     &Subtable);
1668                 if (ACPI_FAILURE (Status))
1669                 {
1670                     return (Status);
1671                 }
1672 
1673                 if (!Subtable)
1674                 {
1675                     break;
1676                 }
1677 
1678                 DtInsertSubtable (ParentTable, Subtable);
1679                 NodeLength += Subtable->Length;
1680                 ContextIrptNumber++;
1681             }
1682 
1683             IortSmmu->ContextInterruptCount = ContextIrptNumber;
1684 
1685             /* Compile PMU interrupt array */
1686 
1687             PmuIrptNumber = 0;
1688             IortSmmu->PmuInterruptOffset = NodeLength;
1689             while (*PFieldList)
1690             {
1691                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3c,
1692                     &Subtable);
1693                 if (ACPI_FAILURE (Status))
1694                 {
1695                     return (Status);
1696                 }
1697 
1698                 if (!Subtable)
1699                 {
1700                     break;
1701                 }
1702 
1703                 DtInsertSubtable (ParentTable, Subtable);
1704                 NodeLength += Subtable->Length;
1705                 PmuIrptNumber++;
1706             }
1707 
1708             IortSmmu->PmuInterruptCount = PmuIrptNumber;
1709             break;
1710 
1711         case ACPI_IORT_NODE_SMMU_V3:
1712 
1713             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort4,
1714                 &Subtable);
1715             if (ACPI_FAILURE (Status))
1716             {
1717                 return (Status);
1718             }
1719 
1720             DtInsertSubtable (ParentTable, Subtable);
1721             NodeLength += Subtable->Length;
1722             break;
1723 
1724         default:
1725 
1726             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IORT");
1727             return (AE_ERROR);
1728         }
1729 
1730         /* Compile Array of ID mappings */
1731 
1732         IortNode->MappingOffset = NodeLength;
1733         IdMappingNumber = 0;
1734         while (*PFieldList)
1735         {
1736             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortMap,
1737                 &Subtable);
1738             if (ACPI_FAILURE (Status))
1739             {
1740                 return (Status);
1741             }
1742 
1743             if (!Subtable)
1744             {
1745                 break;
1746             }
1747 
1748             DtInsertSubtable (ParentTable, Subtable);
1749             NodeLength += sizeof (ACPI_IORT_ID_MAPPING);
1750             IdMappingNumber++;
1751         }
1752 
1753         IortNode->MappingCount = IdMappingNumber;
1754         if (!IdMappingNumber)
1755         {
1756             IortNode->MappingOffset = 0;
1757         }
1758 
1759         /*
1760          * Node length can be determined by DT_LENGTH option
1761          * IortNode->Length = NodeLength;
1762          */
1763         DtPopSubtable ();
1764         ParentTable = DtPeekSubtable ();
1765         NodeNumber++;
1766     }
1767 
1768     Iort->NodeCount = NodeNumber;
1769     return (AE_OK);
1770 }
1771 
1772 
1773 /******************************************************************************
1774  *
1775  * FUNCTION:    DtCompileIvrs
1776  *
1777  * PARAMETERS:  List                - Current field list pointer
1778  *
1779  * RETURN:      Status
1780  *
1781  * DESCRIPTION: Compile IVRS.
1782  *
1783  *****************************************************************************/
1784 
1785 ACPI_STATUS
1786 DtCompileIvrs (
1787     void                    **List)
1788 {
1789     ACPI_STATUS             Status;
1790     DT_SUBTABLE             *Subtable;
1791     DT_SUBTABLE             *ParentTable;
1792     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1793     DT_FIELD                *SubtableStart;
1794     ACPI_DMTABLE_INFO       *InfoTable;
1795     ACPI_IVRS_HEADER        *IvrsHeader;
1796     UINT8                   EntryType;
1797 
1798 
1799     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrs,
1800         &Subtable);
1801     if (ACPI_FAILURE (Status))
1802     {
1803         return (Status);
1804     }
1805 
1806     ParentTable = DtPeekSubtable ();
1807     DtInsertSubtable (ParentTable, Subtable);
1808 
1809     while (*PFieldList)
1810     {
1811         SubtableStart = *PFieldList;
1812         Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHdr,
1813             &Subtable);
1814         if (ACPI_FAILURE (Status))
1815         {
1816             return (Status);
1817         }
1818 
1819         ParentTable = DtPeekSubtable ();
1820         DtInsertSubtable (ParentTable, Subtable);
1821         DtPushSubtable (Subtable);
1822 
1823         IvrsHeader = ACPI_CAST_PTR (ACPI_IVRS_HEADER, Subtable->Buffer);
1824 
1825         switch (IvrsHeader->Type)
1826         {
1827         case ACPI_IVRS_TYPE_HARDWARE:
1828 
1829             InfoTable = AcpiDmTableInfoIvrs0;
1830             break;
1831 
1832         case ACPI_IVRS_TYPE_MEMORY1:
1833         case ACPI_IVRS_TYPE_MEMORY2:
1834         case ACPI_IVRS_TYPE_MEMORY3:
1835 
1836             InfoTable = AcpiDmTableInfoIvrs1;
1837             break;
1838 
1839         default:
1840 
1841             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IVRS");
1842             return (AE_ERROR);
1843         }
1844 
1845         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1846         if (ACPI_FAILURE (Status))
1847         {
1848             return (Status);
1849         }
1850 
1851         ParentTable = DtPeekSubtable ();
1852         DtInsertSubtable (ParentTable, Subtable);
1853 
1854         if (IvrsHeader->Type == ACPI_IVRS_TYPE_HARDWARE)
1855         {
1856             while (*PFieldList &&
1857                 !strcmp ((*PFieldList)->Name, "Entry Type"))
1858             {
1859                 SubtableStart = *PFieldList;
1860                 DtCompileInteger (&EntryType, *PFieldList, 1, 0);
1861 
1862                 switch (EntryType)
1863                 {
1864                 /* 4-byte device entries */
1865 
1866                 case ACPI_IVRS_TYPE_PAD4:
1867                 case ACPI_IVRS_TYPE_ALL:
1868                 case ACPI_IVRS_TYPE_SELECT:
1869                 case ACPI_IVRS_TYPE_START:
1870                 case ACPI_IVRS_TYPE_END:
1871 
1872                     InfoTable = AcpiDmTableInfoIvrs4;
1873                     break;
1874 
1875                 /* 8-byte entries, type A */
1876 
1877                 case ACPI_IVRS_TYPE_ALIAS_SELECT:
1878                 case ACPI_IVRS_TYPE_ALIAS_START:
1879 
1880                     InfoTable = AcpiDmTableInfoIvrs8a;
1881                     break;
1882 
1883                 /* 8-byte entries, type B */
1884 
1885                 case ACPI_IVRS_TYPE_PAD8:
1886                 case ACPI_IVRS_TYPE_EXT_SELECT:
1887                 case ACPI_IVRS_TYPE_EXT_START:
1888 
1889                     InfoTable = AcpiDmTableInfoIvrs8b;
1890                     break;
1891 
1892                 /* 8-byte entries, type C */
1893 
1894                 case ACPI_IVRS_TYPE_SPECIAL:
1895 
1896                     InfoTable = AcpiDmTableInfoIvrs8c;
1897                     break;
1898 
1899                 default:
1900 
1901                     DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart,
1902                         "IVRS Device Entry");
1903                     return (AE_ERROR);
1904                 }
1905 
1906                 Status = DtCompileTable (PFieldList, InfoTable,
1907                     &Subtable);
1908                 if (ACPI_FAILURE (Status))
1909                 {
1910                     return (Status);
1911                 }
1912 
1913                 DtInsertSubtable (ParentTable, Subtable);
1914             }
1915         }
1916 
1917         DtPopSubtable ();
1918     }
1919 
1920     return (AE_OK);
1921 }
1922