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