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