xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/dttable1.c (revision dd3ee07da436799d8de85f3055253118b76bf345)
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:    DtCompileAest
68  *
69  * PARAMETERS:  List                - Current field list pointer
70  *
71  * RETURN:      Status
72  *
73  * DESCRIPTION: Compile AEST.
74  *
75  * NOTE: Assumes the following table structure:
76  *      For all AEST Error Nodes:
77  *          1) An AEST Error Node, followed immediately by:
78  *          2) Any node-specific data
79  *          3) An Interface Structure (one)
80  *          4) A list (array) of Interrupt Structures, the count as specified
81  *              in the NodeInterruptCount field of the Error Node header.
82  *
83  * AEST - ARM Error Source table. Conforms to:
84  * ACPI for the Armv8 RAS Extensions 1.1 Platform Design Document Sep 2020
85  *
86  *****************************************************************************/
87 
88 ACPI_STATUS
89 DtCompileAest (
90     void                    **List)
91 {
92     ACPI_AEST_HEADER        *ErrorNodeHeader;
93     ACPI_AEST_PROCESSOR     *AestProcessor;
94     DT_SUBTABLE             *Subtable;
95     DT_SUBTABLE             *ParentTable;
96     ACPI_DMTABLE_INFO       *InfoTable;
97     ACPI_STATUS             Status;
98     UINT32                  i;
99     UINT32                  Offset;
100     DT_FIELD                **PFieldList = (DT_FIELD **) List;
101 
102 
103     while (*PFieldList)
104     {
105         /* Compile the common error node header */
106 
107         Status = DtCompileTable (PFieldList, AcpiDmTableInfoAestHdr,
108             &Subtable);
109         if (ACPI_FAILURE (Status))
110         {
111             return (Status);
112         }
113 
114         ParentTable = DtPeekSubtable ();
115         DtInsertSubtable (ParentTable, Subtable);
116 
117         /* Everything past the error node header will be a subtable */
118 
119         DtPushSubtable (Subtable);
120 
121         /*
122          * Compile the node-specific structure (Based on the error
123          * node header Type field)
124          */
125         ErrorNodeHeader = ACPI_CAST_PTR (ACPI_AEST_HEADER, Subtable->Buffer);
126 
127         /* Point past the common error node header */
128 
129         Offset = sizeof (ACPI_AEST_HEADER);
130         ErrorNodeHeader->NodeSpecificOffset = Offset;
131 
132         /* Decode the error node type */
133 
134         switch (ErrorNodeHeader->Type)
135         {
136         case ACPI_AEST_PROCESSOR_ERROR_NODE:
137 
138             InfoTable = AcpiDmTableInfoAestProcError;
139             break;
140 
141         case ACPI_AEST_MEMORY_ERROR_NODE:
142 
143             InfoTable = AcpiDmTableInfoAestMemError;
144             break;
145 
146         case ACPI_AEST_SMMU_ERROR_NODE:
147 
148             InfoTable = AcpiDmTableInfoAestSmmuError;
149             break;
150 
151         case ACPI_AEST_VENDOR_ERROR_NODE:
152 
153             InfoTable = AcpiDmTableInfoAestVendorError;
154             break;
155 
156         case ACPI_AEST_GIC_ERROR_NODE:
157 
158             InfoTable = AcpiDmTableInfoAestGicError;
159             break;
160 
161         /* Error case below */
162         default:
163             AcpiOsPrintf ("Unknown AEST Subtable Type: %X\n",
164                 ErrorNodeHeader->Type);
165             return (AE_ERROR);
166         }
167 
168         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
169         if (ACPI_FAILURE (Status))
170         {
171             return (Status);
172         }
173 
174         /* Point past the node-specific structure */
175 
176         Offset += Subtable->Length;
177         ErrorNodeHeader->NodeInterfaceOffset = Offset;
178 
179         ParentTable = DtPeekSubtable ();
180         DtInsertSubtable (ParentTable, Subtable);
181 
182         /* Compile any additional node-specific substructures */
183 
184         if (ErrorNodeHeader->Type == ACPI_AEST_PROCESSOR_ERROR_NODE)
185         {
186             /*
187              * Special handling for PROCESSOR_ERROR_NODE subtables
188              * (to handle the Resource Substructure via the ResourceType
189              * field).
190              */
191             AestProcessor = ACPI_CAST_PTR (ACPI_AEST_PROCESSOR,
192                 Subtable->Buffer);
193 
194             switch (AestProcessor->ResourceType)
195             {
196             case ACPI_AEST_CACHE_RESOURCE:
197 
198                 InfoTable = AcpiDmTableInfoAestCacheRsrc;
199                 break;
200 
201             case ACPI_AEST_TLB_RESOURCE:
202 
203                 InfoTable = AcpiDmTableInfoAestTlbRsrc;
204                 break;
205 
206             case ACPI_AEST_GENERIC_RESOURCE:
207 
208                 InfoTable = AcpiDmTableInfoAestGenRsrc;
209                 AcpiOsPrintf ("Generic Resource Type (%X) is not supported at this time\n",
210                     AestProcessor->ResourceType);
211                 return (AE_ERROR);
212 
213             /* Error case below */
214             default:
215                 AcpiOsPrintf ("Unknown AEST Processor Resource Type: %X\n",
216                     AestProcessor->ResourceType);
217                 return (AE_ERROR);
218             }
219 
220             Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
221             if (ACPI_FAILURE (Status))
222             {
223                 return (Status);
224             }
225 
226             /* Point past the resource substructure subtable */
227 
228             Offset += Subtable->Length;
229             ErrorNodeHeader->NodeInterfaceOffset = Offset;
230 
231             ParentTable = DtPeekSubtable ();
232             DtInsertSubtable (ParentTable, Subtable);
233         }
234 
235         /* Compile the (required) node interface structure */
236 
237         Status = DtCompileTable (PFieldList, AcpiDmTableInfoAestXface,
238             &Subtable);
239         if (ACPI_FAILURE (Status))
240         {
241             return (Status);
242         }
243 
244         ErrorNodeHeader->NodeInterruptOffset = 0;
245         ParentTable = DtPeekSubtable ();
246         DtInsertSubtable (ParentTable, Subtable);
247 
248         /* Compile each of the node interrupt structures */
249 
250         if (ErrorNodeHeader->NodeInterruptCount)
251         {
252             /* Point to the first interrupt structure */
253 
254             Offset += Subtable->Length;
255             ErrorNodeHeader->NodeInterruptOffset = Offset;
256         }
257 
258         /* Compile each of the interrupt structures */
259 
260         for (i = 0; i < ErrorNodeHeader->NodeInterruptCount; i++)
261         {
262             Status = DtCompileTable (PFieldList, AcpiDmTableInfoAestXrupt,
263                 &Subtable);
264             if (ACPI_FAILURE (Status))
265             {
266                 return (Status);
267             }
268 
269             ParentTable = DtPeekSubtable ();
270             DtInsertSubtable (ParentTable, Subtable);
271         }
272 
273         /* Prepare for the next AEST Error node */
274 
275         DtPopSubtable ();
276     }
277 
278     return (AE_OK);
279 }
280 
281 
282 /******************************************************************************
283  *
284  * FUNCTION:    DtCompileAsf
285  *
286  * PARAMETERS:  List                - Current field list pointer
287  *
288  * RETURN:      Status
289  *
290  * DESCRIPTION: Compile ASF!.
291  *
292  *****************************************************************************/
293 
294 ACPI_STATUS
295 DtCompileAsf (
296     void                    **List)
297 {
298     ACPI_ASF_INFO           *AsfTable;
299     DT_SUBTABLE             *Subtable;
300     DT_SUBTABLE             *ParentTable;
301     ACPI_DMTABLE_INFO       *InfoTable;
302     ACPI_DMTABLE_INFO       *DataInfoTable = NULL;
303     UINT32                  DataCount = 0;
304     ACPI_STATUS             Status;
305     UINT32                  i;
306     DT_FIELD                **PFieldList = (DT_FIELD **) List;
307     DT_FIELD                *SubtableStart;
308 
309 
310     while (*PFieldList)
311     {
312         SubtableStart = *PFieldList;
313         Status = DtCompileTable (PFieldList, AcpiDmTableInfoAsfHdr,
314             &Subtable);
315         if (ACPI_FAILURE (Status))
316         {
317             return (Status);
318         }
319 
320         ParentTable = DtPeekSubtable ();
321         DtInsertSubtable (ParentTable, Subtable);
322         DtPushSubtable (Subtable);
323 
324         AsfTable = ACPI_CAST_PTR (ACPI_ASF_INFO, Subtable->Buffer);
325 
326         switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */
327         {
328         case ACPI_ASF_TYPE_INFO:
329 
330             InfoTable = AcpiDmTableInfoAsf0;
331             break;
332 
333         case ACPI_ASF_TYPE_ALERT:
334 
335             InfoTable = AcpiDmTableInfoAsf1;
336             break;
337 
338         case ACPI_ASF_TYPE_CONTROL:
339 
340             InfoTable = AcpiDmTableInfoAsf2;
341             break;
342 
343         case ACPI_ASF_TYPE_BOOT:
344 
345             InfoTable = AcpiDmTableInfoAsf3;
346             break;
347 
348         case ACPI_ASF_TYPE_ADDRESS:
349 
350             InfoTable = AcpiDmTableInfoAsf4;
351             break;
352 
353         default:
354 
355             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!");
356             return (AE_ERROR);
357         }
358 
359         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
360         if (ACPI_FAILURE (Status))
361         {
362             return (Status);
363         }
364 
365         ParentTable = DtPeekSubtable ();
366         DtInsertSubtable (ParentTable, Subtable);
367 
368         switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */
369         {
370         case ACPI_ASF_TYPE_INFO:
371 
372             DataInfoTable = NULL;
373             break;
374 
375         case ACPI_ASF_TYPE_ALERT:
376 
377             DataInfoTable = AcpiDmTableInfoAsf1a;
378             DataCount = ACPI_CAST_PTR (ACPI_ASF_ALERT,
379                 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
380                     sizeof (ACPI_ASF_HEADER)))->Alerts;
381             break;
382 
383         case ACPI_ASF_TYPE_CONTROL:
384 
385             DataInfoTable = AcpiDmTableInfoAsf2a;
386             DataCount = ACPI_CAST_PTR (ACPI_ASF_REMOTE,
387                 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
388                     sizeof (ACPI_ASF_HEADER)))->Controls;
389             break;
390 
391         case ACPI_ASF_TYPE_BOOT:
392 
393             DataInfoTable = NULL;
394             break;
395 
396         case ACPI_ASF_TYPE_ADDRESS:
397 
398             DataInfoTable = TableInfoAsfAddress;
399             DataCount = ACPI_CAST_PTR (ACPI_ASF_ADDRESS,
400                 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
401                     sizeof (ACPI_ASF_HEADER)))->Devices;
402             break;
403 
404         default:
405 
406             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!");
407             return (AE_ERROR);
408         }
409 
410         if (DataInfoTable)
411         {
412             switch (AsfTable->Header.Type & 0x7F)
413             {
414             case ACPI_ASF_TYPE_ADDRESS:
415 
416                 while (DataCount > 0)
417                 {
418                     Status = DtCompileTable (PFieldList, DataInfoTable,
419                         &Subtable);
420                     if (ACPI_FAILURE (Status))
421                     {
422                         return (Status);
423                     }
424 
425                     DtInsertSubtable (ParentTable, Subtable);
426                     DataCount = DataCount - Subtable->Length;
427                 }
428                 break;
429 
430             default:
431 
432                 for (i = 0; i < DataCount; i++)
433                 {
434                     Status = DtCompileTable (PFieldList, DataInfoTable,
435                         &Subtable);
436                     if (ACPI_FAILURE (Status))
437                     {
438                         return (Status);
439                     }
440 
441                     DtInsertSubtable (ParentTable, Subtable);
442                 }
443                 break;
444             }
445         }
446 
447         DtPopSubtable ();
448     }
449 
450     return (AE_OK);
451 }
452 
453 
454 /******************************************************************************
455  *
456  * FUNCTION:    DtCompileCedt
457  *
458  * PARAMETERS:  List                - Current field list pointer
459  *
460  * RETURN:      Status
461  *
462  * DESCRIPTION: Compile CEDT.
463  *
464  *****************************************************************************/
465 
466 ACPI_STATUS
467 DtCompileCedt (
468     void                    **List)
469 {
470     ACPI_STATUS             Status;
471     DT_SUBTABLE             *Subtable;
472     DT_SUBTABLE             *ParentTable;
473     DT_FIELD                **PFieldList = (DT_FIELD **) List;
474     ACPI_CEDT_HEADER        *CedtHeader;
475     DT_FIELD                *SubtableStart;
476 
477 
478     /* Walk the parse tree */
479 
480     while (*PFieldList)
481     {
482         SubtableStart = *PFieldList;
483 
484         /* CEDT Header */
485 
486         Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedtHdr,
487             &Subtable);
488         if (ACPI_FAILURE (Status))
489         {
490             return (Status);
491         }
492 
493         ParentTable = DtPeekSubtable ();
494         DtInsertSubtable (ParentTable, Subtable);
495         DtPushSubtable (Subtable);
496 
497         CedtHeader = ACPI_CAST_PTR (ACPI_CEDT_HEADER, Subtable->Buffer);
498 
499         switch (CedtHeader->Type)
500         {
501         case ACPI_CEDT_TYPE_CHBS:
502 
503             break;
504 
505         default:
506 
507             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "CEDT");
508             return (AE_ERROR);
509         }
510 
511         /* CEDT Subtable */
512 
513         Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt0, &Subtable);
514         if (ACPI_FAILURE (Status))
515         {
516             return (Status);
517         }
518 
519         ParentTable = DtPeekSubtable ();
520         DtInsertSubtable (ParentTable, Subtable);
521         DtPopSubtable ();
522     }
523 
524     return (AE_OK);
525 }
526 
527 
528 /******************************************************************************
529  *
530  * FUNCTION:    DtCompileCpep
531  *
532  * PARAMETERS:  List                - Current field list pointer
533  *
534  * RETURN:      Status
535  *
536  * DESCRIPTION: Compile CPEP.
537  *
538  *****************************************************************************/
539 
540 ACPI_STATUS
541 DtCompileCpep (
542     void                    **List)
543 {
544     ACPI_STATUS             Status;
545 
546 
547     Status = DtCompileTwoSubtables (List,
548         AcpiDmTableInfoCpep, AcpiDmTableInfoCpep0);
549     return (Status);
550 }
551 
552 
553 /******************************************************************************
554  *
555  * FUNCTION:    DtCompileCsrt
556  *
557  * PARAMETERS:  List                - Current field list pointer
558  *
559  * RETURN:      Status
560  *
561  * DESCRIPTION: Compile CSRT.
562  *
563  *****************************************************************************/
564 
565 ACPI_STATUS
566 DtCompileCsrt (
567     void                    **List)
568 {
569     ACPI_STATUS             Status = AE_OK;
570     DT_SUBTABLE             *Subtable;
571     DT_SUBTABLE             *ParentTable;
572     DT_FIELD                **PFieldList = (DT_FIELD **) List;
573     UINT32                  DescriptorCount;
574     UINT32                  GroupLength;
575 
576 
577     /* Subtables (Resource Groups) */
578 
579     ParentTable = DtPeekSubtable ();
580     while (*PFieldList)
581     {
582         /* Resource group subtable */
583 
584         Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt0,
585             &Subtable);
586         if (ACPI_FAILURE (Status))
587         {
588             return (Status);
589         }
590 
591         /* Compute the number of resource descriptors */
592 
593         GroupLength =
594             (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
595                 Subtable->Buffer))->Length -
596             (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
597                 Subtable->Buffer))->SharedInfoLength -
598             sizeof (ACPI_CSRT_GROUP);
599 
600         DescriptorCount = (GroupLength  /
601             sizeof (ACPI_CSRT_DESCRIPTOR));
602 
603         DtInsertSubtable (ParentTable, Subtable);
604         DtPushSubtable (Subtable);
605         ParentTable = DtPeekSubtable ();
606 
607         /* Shared info subtable (One per resource group) */
608 
609         Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt1,
610             &Subtable);
611         if (ACPI_FAILURE (Status))
612         {
613             return (Status);
614         }
615 
616         DtInsertSubtable (ParentTable, Subtable);
617 
618         /* Sub-Subtables (Resource Descriptors) */
619 
620         while (*PFieldList && DescriptorCount)
621         {
622 
623             Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2,
624                 &Subtable);
625             if (ACPI_FAILURE (Status))
626             {
627                 return (Status);
628             }
629 
630             DtInsertSubtable (ParentTable, Subtable);
631 
632             DtPushSubtable (Subtable);
633             ParentTable = DtPeekSubtable ();
634             if (*PFieldList)
635             {
636                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2a,
637                     &Subtable);
638                 if (ACPI_FAILURE (Status))
639                 {
640                     return (Status);
641                 }
642                 if (Subtable)
643                 {
644                     DtInsertSubtable (ParentTable, Subtable);
645                 }
646             }
647 
648             DtPopSubtable ();
649             ParentTable = DtPeekSubtable ();
650             DescriptorCount--;
651         }
652 
653         DtPopSubtable ();
654         ParentTable = DtPeekSubtable ();
655     }
656 
657     return (Status);
658 }
659 
660 
661 /******************************************************************************
662  *
663  * FUNCTION:    DtCompileDbg2
664  *
665  * PARAMETERS:  List                - Current field list pointer
666  *
667  * RETURN:      Status
668  *
669  * DESCRIPTION: Compile DBG2.
670  *
671  *****************************************************************************/
672 
673 ACPI_STATUS
674 DtCompileDbg2 (
675     void                    **List)
676 {
677     ACPI_STATUS             Status;
678     DT_SUBTABLE             *Subtable;
679     DT_SUBTABLE             *ParentTable;
680     DT_FIELD                **PFieldList = (DT_FIELD **) List;
681     UINT32                  SubtableCount;
682     ACPI_DBG2_HEADER        *Dbg2Header;
683     ACPI_DBG2_DEVICE        *DeviceInfo;
684     UINT16                  CurrentOffset;
685     UINT32                  i;
686 
687 
688     /* Main table */
689 
690     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2, &Subtable);
691     if (ACPI_FAILURE (Status))
692     {
693         return (Status);
694     }
695 
696     ParentTable = DtPeekSubtable ();
697     DtInsertSubtable (ParentTable, Subtable);
698 
699     /* Main table fields */
700 
701     Dbg2Header = ACPI_CAST_PTR (ACPI_DBG2_HEADER, Subtable->Buffer);
702     Dbg2Header->InfoOffset = sizeof (ACPI_TABLE_HEADER) + ACPI_PTR_DIFF (
703         ACPI_ADD_PTR (UINT8, Dbg2Header, sizeof (ACPI_DBG2_HEADER)), Dbg2Header);
704 
705     SubtableCount = Dbg2Header->InfoCount;
706     DtPushSubtable (Subtable);
707 
708     /* Process all Device Information subtables (Count = InfoCount) */
709 
710     while (*PFieldList && SubtableCount)
711     {
712         /* Subtable: Debug Device Information */
713 
714         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Device,
715             &Subtable);
716         if (ACPI_FAILURE (Status))
717         {
718             return (Status);
719         }
720 
721         DeviceInfo = ACPI_CAST_PTR (ACPI_DBG2_DEVICE, Subtable->Buffer);
722         CurrentOffset = (UINT16) sizeof (ACPI_DBG2_DEVICE);
723 
724         ParentTable = DtPeekSubtable ();
725         DtInsertSubtable (ParentTable, Subtable);
726         DtPushSubtable (Subtable);
727 
728         ParentTable = DtPeekSubtable ();
729 
730         /* BaseAddressRegister GAS array (Required, size is RegisterCount) */
731 
732         DeviceInfo->BaseAddressOffset = CurrentOffset;
733         for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++)
734         {
735             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Addr,
736                 &Subtable);
737             if (ACPI_FAILURE (Status))
738             {
739                 return (Status);
740             }
741 
742             CurrentOffset += (UINT16) sizeof (ACPI_GENERIC_ADDRESS);
743             DtInsertSubtable (ParentTable, Subtable);
744         }
745 
746         /* AddressSize array (Required, size = RegisterCount) */
747 
748         DeviceInfo->AddressSizeOffset = CurrentOffset;
749         for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++)
750         {
751             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Size,
752                 &Subtable);
753             if (ACPI_FAILURE (Status))
754             {
755                 return (Status);
756             }
757 
758             CurrentOffset += (UINT16) sizeof (UINT32);
759             DtInsertSubtable (ParentTable, Subtable);
760         }
761 
762         /* NamespaceString device identifier (Required, size = NamePathLength) */
763 
764         DeviceInfo->NamepathOffset = CurrentOffset;
765         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Name,
766             &Subtable);
767         if (ACPI_FAILURE (Status))
768         {
769             return (Status);
770         }
771 
772         /* Update the device info header */
773 
774         DeviceInfo->NamepathLength = (UINT16) Subtable->Length;
775         CurrentOffset += (UINT16) DeviceInfo->NamepathLength;
776         DtInsertSubtable (ParentTable, Subtable);
777 
778         /* OemData - Variable-length data (Optional, size = OemDataLength) */
779 
780         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2OemData,
781             &Subtable);
782         if (Status == AE_END_OF_TABLE)
783         {
784             /* optional field was not found and we're at the end of the file */
785 
786             goto subtableDone;
787         }
788         else if (ACPI_FAILURE (Status))
789         {
790             return (Status);
791         }
792 
793         /* Update the device info header (zeros if no OEM data present) */
794 
795         DeviceInfo->OemDataOffset = 0;
796         DeviceInfo->OemDataLength = 0;
797 
798         /* Optional subtable (OemData) */
799 
800         if (Subtable && Subtable->Length)
801         {
802             DeviceInfo->OemDataOffset = CurrentOffset;
803             DeviceInfo->OemDataLength = (UINT16) Subtable->Length;
804 
805             DtInsertSubtable (ParentTable, Subtable);
806         }
807 subtableDone:
808         SubtableCount--;
809         DtPopSubtable (); /* Get next Device Information subtable */
810     }
811 
812     DtPopSubtable ();
813     return (AE_OK);
814 }
815 
816 
817 /******************************************************************************
818  *
819  * FUNCTION:    DtCompileDmar
820  *
821  * PARAMETERS:  List                - Current field list pointer
822  *
823  * RETURN:      Status
824  *
825  * DESCRIPTION: Compile DMAR.
826  *
827  *****************************************************************************/
828 
829 ACPI_STATUS
830 DtCompileDmar (
831     void                    **List)
832 {
833     ACPI_STATUS             Status;
834     DT_SUBTABLE             *Subtable;
835     DT_SUBTABLE             *ParentTable;
836     DT_FIELD                **PFieldList = (DT_FIELD **) List;
837     DT_FIELD                *SubtableStart;
838     ACPI_DMTABLE_INFO       *InfoTable;
839     ACPI_DMAR_HEADER        *DmarHeader;
840     ACPI_DMAR_DEVICE_SCOPE  *DmarDeviceScope;
841     UINT32                  DeviceScopeLength;
842     UINT32                  PciPathLength;
843 
844 
845     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmar, &Subtable);
846     if (ACPI_FAILURE (Status))
847     {
848         return (Status);
849     }
850 
851     ParentTable = DtPeekSubtable ();
852     DtInsertSubtable (ParentTable, Subtable);
853     DtPushSubtable (Subtable);
854 
855     while (*PFieldList)
856     {
857         /* DMAR Header */
858 
859         SubtableStart = *PFieldList;
860         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarHdr,
861             &Subtable);
862         if (ACPI_FAILURE (Status))
863         {
864             return (Status);
865         }
866 
867         ParentTable = DtPeekSubtable ();
868         DtInsertSubtable (ParentTable, Subtable);
869         DtPushSubtable (Subtable);
870 
871         DmarHeader = ACPI_CAST_PTR (ACPI_DMAR_HEADER, Subtable->Buffer);
872 
873         switch (DmarHeader->Type)
874         {
875         case ACPI_DMAR_TYPE_HARDWARE_UNIT:
876 
877             InfoTable = AcpiDmTableInfoDmar0;
878             break;
879 
880         case ACPI_DMAR_TYPE_RESERVED_MEMORY:
881 
882             InfoTable = AcpiDmTableInfoDmar1;
883             break;
884 
885         case ACPI_DMAR_TYPE_ROOT_ATS:
886 
887             InfoTable = AcpiDmTableInfoDmar2;
888             break;
889 
890         case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
891 
892             InfoTable = AcpiDmTableInfoDmar3;
893             break;
894 
895         case ACPI_DMAR_TYPE_NAMESPACE:
896 
897             InfoTable = AcpiDmTableInfoDmar4;
898             break;
899 
900         default:
901 
902             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "DMAR");
903             return (AE_ERROR);
904         }
905 
906         /* DMAR Subtable */
907 
908         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
909         if (ACPI_FAILURE (Status))
910         {
911             return (Status);
912         }
913 
914         ParentTable = DtPeekSubtable ();
915         DtInsertSubtable (ParentTable, Subtable);
916 
917         /*
918          * Optional Device Scope subtables
919          */
920         if ((DmarHeader->Type == ACPI_DMAR_TYPE_HARDWARE_AFFINITY) ||
921             (DmarHeader->Type == ACPI_DMAR_TYPE_NAMESPACE))
922         {
923             /* These types do not support device scopes */
924 
925             DtPopSubtable ();
926             continue;
927         }
928 
929         DtPushSubtable (Subtable);
930         DeviceScopeLength = DmarHeader->Length - Subtable->Length -
931             ParentTable->Length;
932         while (DeviceScopeLength)
933         {
934             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarScope,
935                 &Subtable);
936             if (Status == AE_NOT_FOUND)
937             {
938                 break;
939             }
940 
941             ParentTable = DtPeekSubtable ();
942             DtInsertSubtable (ParentTable, Subtable);
943             DtPushSubtable (Subtable);
944 
945             DmarDeviceScope = ACPI_CAST_PTR (ACPI_DMAR_DEVICE_SCOPE, Subtable->Buffer);
946 
947             /* Optional PCI Paths */
948 
949             PciPathLength = DmarDeviceScope->Length - Subtable->Length;
950             while (PciPathLength)
951             {
952                 Status = DtCompileTable (PFieldList, TableInfoDmarPciPath,
953                     &Subtable);
954                 if (Status == AE_NOT_FOUND)
955                 {
956                     DtPopSubtable ();
957                     break;
958                 }
959 
960                 ParentTable = DtPeekSubtable ();
961                 DtInsertSubtable (ParentTable, Subtable);
962                 PciPathLength -= Subtable->Length;
963             }
964 
965             DtPopSubtable ();
966             DeviceScopeLength -= DmarDeviceScope->Length;
967         }
968 
969         DtPopSubtable ();
970         DtPopSubtable ();
971     }
972 
973     return (AE_OK);
974 }
975 
976 
977 /******************************************************************************
978  *
979  * FUNCTION:    DtCompileDrtm
980  *
981  * PARAMETERS:  List                - Current field list pointer
982  *
983  * RETURN:      Status
984  *
985  * DESCRIPTION: Compile DRTM.
986  *
987  *****************************************************************************/
988 
989 ACPI_STATUS
990 DtCompileDrtm (
991     void                    **List)
992 {
993     ACPI_STATUS             Status;
994     DT_SUBTABLE             *Subtable;
995     DT_SUBTABLE             *ParentTable;
996     DT_FIELD                **PFieldList = (DT_FIELD **) List;
997     UINT32                  Count;
998     /* ACPI_TABLE_DRTM         *Drtm; */
999     ACPI_DRTM_VTABLE_LIST   *DrtmVtl;
1000     ACPI_DRTM_RESOURCE_LIST *DrtmRl;
1001     /* ACPI_DRTM_DPS_ID        *DrtmDps; */
1002 
1003 
1004     ParentTable = DtPeekSubtable ();
1005 
1006     /* Compile DRTM header */
1007 
1008     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm,
1009         &Subtable);
1010     if (ACPI_FAILURE (Status))
1011     {
1012         return (Status);
1013     }
1014     DtInsertSubtable (ParentTable, Subtable);
1015 
1016     /*
1017      * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
1018      * should be taken to avoid accessing ACPI_TABLE_HADER fields.
1019      */
1020 #if 0
1021     Drtm = ACPI_SUB_PTR (ACPI_TABLE_DRTM,
1022         Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
1023 #endif
1024     /* Compile VTL */
1025 
1026     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0,
1027         &Subtable);
1028     if (ACPI_FAILURE (Status))
1029     {
1030         return (Status);
1031     }
1032 
1033     DtInsertSubtable (ParentTable, Subtable);
1034     DrtmVtl = ACPI_CAST_PTR (ACPI_DRTM_VTABLE_LIST, Subtable->Buffer);
1035 
1036     DtPushSubtable (Subtable);
1037     ParentTable = DtPeekSubtable ();
1038     Count = 0;
1039 
1040     while (*PFieldList)
1041     {
1042         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0a,
1043             &Subtable);
1044         if (ACPI_FAILURE (Status))
1045         {
1046             return (Status);
1047         }
1048         if (!Subtable)
1049         {
1050             break;
1051         }
1052         DtInsertSubtable (ParentTable, Subtable);
1053         Count++;
1054     }
1055 
1056     DrtmVtl->ValidatedTableCount = Count;
1057     DtPopSubtable ();
1058     ParentTable = DtPeekSubtable ();
1059 
1060     /* Compile RL */
1061 
1062     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1,
1063         &Subtable);
1064     if (ACPI_FAILURE (Status))
1065     {
1066         return (Status);
1067     }
1068 
1069     DtInsertSubtable (ParentTable, Subtable);
1070     DrtmRl = ACPI_CAST_PTR (ACPI_DRTM_RESOURCE_LIST, Subtable->Buffer);
1071 
1072     DtPushSubtable (Subtable);
1073     ParentTable = DtPeekSubtable ();
1074     Count = 0;
1075 
1076     while (*PFieldList)
1077     {
1078         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1a,
1079             &Subtable);
1080         if (ACPI_FAILURE (Status))
1081         {
1082             return (Status);
1083         }
1084 
1085         if (!Subtable)
1086         {
1087             break;
1088         }
1089 
1090         DtInsertSubtable (ParentTable, Subtable);
1091         Count++;
1092     }
1093 
1094     DrtmRl->ResourceCount = Count;
1095     DtPopSubtable ();
1096     ParentTable = DtPeekSubtable ();
1097 
1098     /* Compile DPS */
1099 
1100     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm2,
1101         &Subtable);
1102     if (ACPI_FAILURE (Status))
1103     {
1104         return (Status);
1105     }
1106     DtInsertSubtable (ParentTable, Subtable);
1107     /* DrtmDps = ACPI_CAST_PTR (ACPI_DRTM_DPS_ID, Subtable->Buffer);*/
1108 
1109 
1110     return (AE_OK);
1111 }
1112 
1113 
1114 /******************************************************************************
1115  *
1116  * FUNCTION:    DtCompileEinj
1117  *
1118  * PARAMETERS:  List                - Current field list pointer
1119  *
1120  * RETURN:      Status
1121  *
1122  * DESCRIPTION: Compile EINJ.
1123  *
1124  *****************************************************************************/
1125 
1126 ACPI_STATUS
1127 DtCompileEinj (
1128     void                    **List)
1129 {
1130     ACPI_STATUS             Status;
1131 
1132 
1133     Status = DtCompileTwoSubtables (List,
1134         AcpiDmTableInfoEinj, AcpiDmTableInfoEinj0);
1135     return (Status);
1136 }
1137 
1138 
1139 /******************************************************************************
1140  *
1141  * FUNCTION:    DtCompileErst
1142  *
1143  * PARAMETERS:  List                - Current field list pointer
1144  *
1145  * RETURN:      Status
1146  *
1147  * DESCRIPTION: Compile ERST.
1148  *
1149  *****************************************************************************/
1150 
1151 ACPI_STATUS
1152 DtCompileErst (
1153     void                    **List)
1154 {
1155     ACPI_STATUS             Status;
1156 
1157 
1158     Status = DtCompileTwoSubtables (List,
1159         AcpiDmTableInfoErst, AcpiDmTableInfoEinj0);
1160     return (Status);
1161 }
1162 
1163 
1164 /******************************************************************************
1165  *
1166  * FUNCTION:    DtCompileGtdt
1167  *
1168  * PARAMETERS:  List                - Current field list pointer
1169  *
1170  * RETURN:      Status
1171  *
1172  * DESCRIPTION: Compile GTDT.
1173  *
1174  *****************************************************************************/
1175 
1176 ACPI_STATUS
1177 DtCompileGtdt (
1178     void                    **List)
1179 {
1180     ACPI_STATUS             Status;
1181     DT_SUBTABLE             *Subtable;
1182     DT_SUBTABLE             *ParentTable;
1183     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1184     DT_FIELD                *SubtableStart;
1185     ACPI_SUBTABLE_HEADER    *GtdtHeader;
1186     ACPI_DMTABLE_INFO       *InfoTable;
1187     UINT32                  GtCount;
1188     ACPI_TABLE_HEADER       *Header;
1189 
1190 
1191     ParentTable = DtPeekSubtable ();
1192 
1193     Header = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer);
1194 
1195     /* Compile the main table */
1196 
1197     Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt,
1198         &Subtable);
1199     if (ACPI_FAILURE (Status))
1200     {
1201         return (Status);
1202     }
1203 
1204     /* GTDT revision 3 later contains 2 extra fields before subtables */
1205 
1206     if (Header->Revision > 2)
1207     {
1208         ParentTable = DtPeekSubtable ();
1209         DtInsertSubtable (ParentTable, Subtable);
1210 
1211         Status = DtCompileTable (PFieldList,
1212             AcpiDmTableInfoGtdtEl2, &Subtable);
1213         if (ACPI_FAILURE (Status))
1214         {
1215             return (Status);
1216         }
1217     }
1218 
1219     ParentTable = DtPeekSubtable ();
1220     DtInsertSubtable (ParentTable, Subtable);
1221 
1222     while (*PFieldList)
1223     {
1224         SubtableStart = *PFieldList;
1225         Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdtHdr,
1226             &Subtable);
1227         if (ACPI_FAILURE (Status))
1228         {
1229             return (Status);
1230         }
1231 
1232         ParentTable = DtPeekSubtable ();
1233         DtInsertSubtable (ParentTable, Subtable);
1234         DtPushSubtable (Subtable);
1235 
1236         GtdtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer);
1237 
1238         switch (GtdtHeader->Type)
1239         {
1240         case ACPI_GTDT_TYPE_TIMER_BLOCK:
1241 
1242             InfoTable = AcpiDmTableInfoGtdt0;
1243             break;
1244 
1245         case ACPI_GTDT_TYPE_WATCHDOG:
1246 
1247             InfoTable = AcpiDmTableInfoGtdt1;
1248             break;
1249 
1250         default:
1251 
1252             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "GTDT");
1253             return (AE_ERROR);
1254         }
1255 
1256         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1257         if (ACPI_FAILURE (Status))
1258         {
1259             return (Status);
1260         }
1261 
1262         ParentTable = DtPeekSubtable ();
1263         DtInsertSubtable (ParentTable, Subtable);
1264 
1265         /*
1266          * Additional GT block subtable data
1267          */
1268 
1269         switch (GtdtHeader->Type)
1270         {
1271         case ACPI_GTDT_TYPE_TIMER_BLOCK:
1272 
1273             DtPushSubtable (Subtable);
1274             ParentTable = DtPeekSubtable ();
1275 
1276             GtCount = (ACPI_CAST_PTR (ACPI_GTDT_TIMER_BLOCK,
1277                 Subtable->Buffer - sizeof(ACPI_GTDT_HEADER)))->TimerCount;
1278 
1279             while (GtCount)
1280             {
1281                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt0a,
1282                     &Subtable);
1283                 if (ACPI_FAILURE (Status))
1284                 {
1285                     return (Status);
1286                 }
1287 
1288                 DtInsertSubtable (ParentTable, Subtable);
1289                 GtCount--;
1290             }
1291 
1292             DtPopSubtable ();
1293             break;
1294 
1295         default:
1296 
1297             break;
1298         }
1299 
1300         DtPopSubtable ();
1301     }
1302 
1303     return (AE_OK);
1304 }
1305 
1306 
1307 /******************************************************************************
1308  *
1309  * FUNCTION:    DtCompileFpdt
1310  *
1311  * PARAMETERS:  List                - Current field list pointer
1312  *
1313  * RETURN:      Status
1314  *
1315  * DESCRIPTION: Compile FPDT.
1316  *
1317  *****************************************************************************/
1318 
1319 ACPI_STATUS
1320 DtCompileFpdt (
1321     void                    **List)
1322 {
1323     ACPI_STATUS             Status;
1324     ACPI_FPDT_HEADER        *FpdtHeader;
1325     DT_SUBTABLE             *Subtable;
1326     DT_SUBTABLE             *ParentTable;
1327     ACPI_DMTABLE_INFO       *InfoTable;
1328     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1329     DT_FIELD                *SubtableStart;
1330 
1331 
1332     while (*PFieldList)
1333     {
1334         SubtableStart = *PFieldList;
1335         Status = DtCompileTable (PFieldList, AcpiDmTableInfoFpdtHdr,
1336             &Subtable);
1337         if (ACPI_FAILURE (Status))
1338         {
1339             return (Status);
1340         }
1341 
1342         ParentTable = DtPeekSubtable ();
1343         DtInsertSubtable (ParentTable, Subtable);
1344         DtPushSubtable (Subtable);
1345 
1346         FpdtHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer);
1347 
1348         switch (FpdtHeader->Type)
1349         {
1350         case ACPI_FPDT_TYPE_BOOT:
1351 
1352             InfoTable = AcpiDmTableInfoFpdt0;
1353             break;
1354 
1355         case ACPI_FPDT_TYPE_S3PERF:
1356 
1357             InfoTable = AcpiDmTableInfoFpdt1;
1358             break;
1359 
1360         default:
1361 
1362             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "FPDT");
1363             return (AE_ERROR);
1364             break;
1365         }
1366 
1367         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1368         if (ACPI_FAILURE (Status))
1369         {
1370             return (Status);
1371         }
1372 
1373         ParentTable = DtPeekSubtable ();
1374         DtInsertSubtable (ParentTable, Subtable);
1375         DtPopSubtable ();
1376     }
1377 
1378     return (AE_OK);
1379 }
1380 
1381 
1382 /******************************************************************************
1383  *
1384  * FUNCTION:    DtCompileHest
1385  *
1386  * PARAMETERS:  List                - Current field list pointer
1387  *
1388  * RETURN:      Status
1389  *
1390  * DESCRIPTION: Compile HEST.
1391  *
1392  *****************************************************************************/
1393 
1394 ACPI_STATUS
1395 DtCompileHest (
1396     void                    **List)
1397 {
1398     ACPI_STATUS             Status;
1399     DT_SUBTABLE             *Subtable;
1400     DT_SUBTABLE             *ParentTable;
1401     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1402     DT_FIELD                *SubtableStart;
1403     ACPI_DMTABLE_INFO       *InfoTable;
1404     UINT16                  Type;
1405     UINT32                  BankCount;
1406 
1407 
1408     Status = DtCompileTable (PFieldList, AcpiDmTableInfoHest,
1409         &Subtable);
1410     if (ACPI_FAILURE (Status))
1411     {
1412         return (Status);
1413     }
1414 
1415     ParentTable = DtPeekSubtable ();
1416     DtInsertSubtable (ParentTable, Subtable);
1417 
1418     while (*PFieldList)
1419     {
1420         /* Get subtable type */
1421 
1422         SubtableStart = *PFieldList;
1423         DtCompileInteger ((UINT8 *) &Type, *PFieldList, 2, 0);
1424 
1425         switch (Type)
1426         {
1427         case ACPI_HEST_TYPE_IA32_CHECK:
1428 
1429             InfoTable = AcpiDmTableInfoHest0;
1430             break;
1431 
1432         case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
1433 
1434             InfoTable = AcpiDmTableInfoHest1;
1435             break;
1436 
1437         case ACPI_HEST_TYPE_IA32_NMI:
1438 
1439             InfoTable = AcpiDmTableInfoHest2;
1440             break;
1441 
1442         case ACPI_HEST_TYPE_AER_ROOT_PORT:
1443 
1444             InfoTable = AcpiDmTableInfoHest6;
1445             break;
1446 
1447         case ACPI_HEST_TYPE_AER_ENDPOINT:
1448 
1449             InfoTable = AcpiDmTableInfoHest7;
1450             break;
1451 
1452         case ACPI_HEST_TYPE_AER_BRIDGE:
1453 
1454             InfoTable = AcpiDmTableInfoHest8;
1455             break;
1456 
1457         case ACPI_HEST_TYPE_GENERIC_ERROR:
1458 
1459             InfoTable = AcpiDmTableInfoHest9;
1460             break;
1461 
1462         case ACPI_HEST_TYPE_GENERIC_ERROR_V2:
1463 
1464             InfoTable = AcpiDmTableInfoHest10;
1465             break;
1466 
1467         case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
1468 
1469             InfoTable = AcpiDmTableInfoHest11;
1470             break;
1471 
1472         default:
1473 
1474             /* Cannot continue on unknown type */
1475 
1476             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HEST");
1477             return (AE_ERROR);
1478         }
1479 
1480         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1481         if (ACPI_FAILURE (Status))
1482         {
1483             return (Status);
1484         }
1485 
1486         DtInsertSubtable (ParentTable, Subtable);
1487 
1488         /*
1489          * Additional subtable data - IA32 Error Bank(s)
1490          */
1491         BankCount = 0;
1492         switch (Type)
1493         {
1494         case ACPI_HEST_TYPE_IA32_CHECK:
1495 
1496             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK,
1497                 Subtable->Buffer))->NumHardwareBanks;
1498             break;
1499 
1500         case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
1501 
1502             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED,
1503                 Subtable->Buffer))->NumHardwareBanks;
1504             break;
1505 
1506         case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
1507 
1508             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_DEFERRED_CHECK,
1509                 Subtable->Buffer))->NumHardwareBanks;
1510             break;
1511 
1512         default:
1513 
1514             break;
1515         }
1516 
1517         while (BankCount)
1518         {
1519             Status = DtCompileTable (PFieldList, AcpiDmTableInfoHestBank,
1520                 &Subtable);
1521             if (ACPI_FAILURE (Status))
1522             {
1523                 return (Status);
1524             }
1525 
1526             DtInsertSubtable (ParentTable, Subtable);
1527             BankCount--;
1528         }
1529     }
1530 
1531     return (AE_OK);
1532 }
1533 
1534 
1535 /******************************************************************************
1536  *
1537  * FUNCTION:    DtCompileHmat
1538  *
1539  * PARAMETERS:  List                - Current field list pointer
1540  *
1541  * RETURN:      Status
1542  *
1543  * DESCRIPTION: Compile HMAT.
1544  *
1545  *****************************************************************************/
1546 
1547 ACPI_STATUS
1548 DtCompileHmat (
1549     void                    **List)
1550 {
1551     ACPI_STATUS             Status;
1552     DT_SUBTABLE             *Subtable;
1553     DT_SUBTABLE             *ParentTable;
1554     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1555     DT_FIELD                *SubtableStart;
1556     DT_FIELD                *EntryStart;
1557     ACPI_HMAT_STRUCTURE     *HmatStruct;
1558     ACPI_HMAT_LOCALITY      *HmatLocality;
1559     ACPI_HMAT_CACHE         *HmatCache;
1560     ACPI_DMTABLE_INFO       *InfoTable;
1561     UINT32                  IntPDNumber;
1562     UINT32                  TgtPDNumber;
1563     UINT64                  EntryNumber;
1564     UINT16                  SMBIOSHandleNumber;
1565 
1566 
1567     ParentTable = DtPeekSubtable ();
1568 
1569     Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmat,
1570         &Subtable);
1571     if (ACPI_FAILURE (Status))
1572     {
1573         return (Status);
1574     }
1575     DtInsertSubtable (ParentTable, Subtable);
1576 
1577     while (*PFieldList)
1578     {
1579         /* Compile HMAT structure header */
1580 
1581         SubtableStart = *PFieldList;
1582         Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmatHdr,
1583             &Subtable);
1584         if (ACPI_FAILURE (Status))
1585         {
1586             return (Status);
1587         }
1588         DtInsertSubtable (ParentTable, Subtable);
1589 
1590         HmatStruct = ACPI_CAST_PTR (ACPI_HMAT_STRUCTURE, Subtable->Buffer);
1591         HmatStruct->Length = Subtable->Length;
1592 
1593         /* Compile HMAT structure body */
1594 
1595         switch (HmatStruct->Type)
1596         {
1597         case ACPI_HMAT_TYPE_ADDRESS_RANGE:
1598 
1599             InfoTable = AcpiDmTableInfoHmat0;
1600             break;
1601 
1602         case ACPI_HMAT_TYPE_LOCALITY:
1603 
1604             InfoTable = AcpiDmTableInfoHmat1;
1605             break;
1606 
1607         case ACPI_HMAT_TYPE_CACHE:
1608 
1609             InfoTable = AcpiDmTableInfoHmat2;
1610             break;
1611 
1612         default:
1613 
1614             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HMAT");
1615             return (AE_ERROR);
1616         }
1617 
1618         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1619         if (ACPI_FAILURE (Status))
1620         {
1621             return (Status);
1622         }
1623         DtInsertSubtable (ParentTable, Subtable);
1624         HmatStruct->Length += Subtable->Length;
1625 
1626         /* Compile HMAT structure additionals */
1627 
1628         switch (HmatStruct->Type)
1629         {
1630         case ACPI_HMAT_TYPE_LOCALITY:
1631 
1632             HmatLocality = ACPI_SUB_PTR (ACPI_HMAT_LOCALITY,
1633                 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
1634 
1635             /* Compile initiator proximity domain list */
1636 
1637             IntPDNumber = 0;
1638             while (*PFieldList)
1639             {
1640                 Status = DtCompileTable (PFieldList,
1641                     AcpiDmTableInfoHmat1a, &Subtable);
1642                 if (ACPI_FAILURE (Status))
1643                 {
1644                     return (Status);
1645                 }
1646                 if (!Subtable)
1647                 {
1648                     break;
1649                 }
1650                 DtInsertSubtable (ParentTable, Subtable);
1651                 HmatStruct->Length += Subtable->Length;
1652                 IntPDNumber++;
1653             }
1654             HmatLocality->NumberOfInitiatorPDs = IntPDNumber;
1655 
1656             /* Compile target proximity domain list */
1657 
1658             TgtPDNumber = 0;
1659             while (*PFieldList)
1660             {
1661                 Status = DtCompileTable (PFieldList,
1662                     AcpiDmTableInfoHmat1b, &Subtable);
1663                 if (ACPI_FAILURE (Status))
1664                 {
1665                     return (Status);
1666                 }
1667                 if (!Subtable)
1668                 {
1669                     break;
1670                 }
1671                 DtInsertSubtable (ParentTable, Subtable);
1672                 HmatStruct->Length += Subtable->Length;
1673                 TgtPDNumber++;
1674             }
1675             HmatLocality->NumberOfTargetPDs = TgtPDNumber;
1676 
1677             /* Save start of the entries for reporting errors */
1678 
1679             EntryStart = *PFieldList;
1680 
1681             /* Compile latency/bandwidth entries */
1682 
1683             EntryNumber = 0;
1684             while (*PFieldList)
1685             {
1686                 Status = DtCompileTable (PFieldList,
1687                     AcpiDmTableInfoHmat1c, &Subtable);
1688                 if (ACPI_FAILURE (Status))
1689                 {
1690                     return (Status);
1691                 }
1692                 if (!Subtable)
1693                 {
1694                     break;
1695                 }
1696                 DtInsertSubtable (ParentTable, Subtable);
1697                 HmatStruct->Length += Subtable->Length;
1698                 EntryNumber++;
1699             }
1700 
1701             /* Validate number of entries */
1702 
1703             if (EntryNumber !=
1704                 ((UINT64)IntPDNumber * (UINT64)TgtPDNumber))
1705             {
1706                 DtFatal (ASL_MSG_INVALID_EXPRESSION, EntryStart, "HMAT");
1707                 return (AE_ERROR);
1708             }
1709             break;
1710 
1711         case ACPI_HMAT_TYPE_CACHE:
1712 
1713             /* Compile SMBIOS handles */
1714 
1715             HmatCache = ACPI_SUB_PTR (ACPI_HMAT_CACHE,
1716                 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
1717             SMBIOSHandleNumber = 0;
1718             while (*PFieldList)
1719             {
1720                 Status = DtCompileTable (PFieldList,
1721                     AcpiDmTableInfoHmat2a, &Subtable);
1722                 if (ACPI_FAILURE (Status))
1723                 {
1724                     return (Status);
1725                 }
1726                 if (!Subtable)
1727                 {
1728                     break;
1729                 }
1730                 DtInsertSubtable (ParentTable, Subtable);
1731                 HmatStruct->Length += Subtable->Length;
1732                 SMBIOSHandleNumber++;
1733             }
1734             HmatCache->NumberOfSMBIOSHandles = SMBIOSHandleNumber;
1735             break;
1736 
1737         default:
1738 
1739             break;
1740         }
1741     }
1742 
1743     return (AE_OK);
1744 }
1745 
1746 
1747 /******************************************************************************
1748  *
1749  * FUNCTION:    DtCompileIort
1750  *
1751  * PARAMETERS:  List                - Current field list pointer
1752  *
1753  * RETURN:      Status
1754  *
1755  * DESCRIPTION: Compile IORT.
1756  *
1757  *****************************************************************************/
1758 
1759 ACPI_STATUS
1760 DtCompileIort (
1761     void                    **List)
1762 {
1763     ACPI_STATUS             Status;
1764     DT_SUBTABLE             *Subtable;
1765     DT_SUBTABLE             *ParentTable;
1766     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1767     DT_FIELD                *SubtableStart;
1768     ACPI_TABLE_HEADER       *Table;
1769     ACPI_TABLE_IORT         *Iort;
1770     ACPI_IORT_NODE          *IortNode;
1771     ACPI_IORT_ITS_GROUP     *IortItsGroup;
1772     ACPI_IORT_SMMU          *IortSmmu;
1773     ACPI_IORT_RMR           *IortRmr;
1774     UINT32                  NodeNumber;
1775     UINT32                  NodeLength;
1776     UINT32                  IdMappingNumber;
1777     UINT32                  ItsNumber;
1778     UINT32                  ContextIrptNumber;
1779     UINT32                  PmuIrptNumber;
1780     UINT32                  PaddingLength;
1781     UINT8                   Revision;
1782     UINT32                  RmrCount;
1783 
1784 
1785     ParentTable = DtPeekSubtable ();
1786 
1787     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort,
1788         &Subtable);
1789     if (ACPI_FAILURE (Status))
1790     {
1791         return (Status);
1792     }
1793     DtInsertSubtable (ParentTable, Subtable);
1794 
1795     Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer);
1796     Revision = Table->Revision;
1797 
1798     /* Both IORT Rev E and E.a have known issues and are not supported */
1799 
1800     if (Revision == 1 || Revision == 2)
1801     {
1802         DtError (ASL_ERROR, ASL_MSG_UNSUPPORTED, NULL, "IORT table revision");
1803         return (AE_ERROR);
1804     }
1805 
1806     /*
1807      * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
1808      * should be taken to avoid accessing ACPI_TABLE_HEADER fields.
1809      */
1810     Iort = ACPI_SUB_PTR (ACPI_TABLE_IORT,
1811         Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
1812 
1813     /*
1814      * OptionalPadding - Variable-length data
1815      * (Optional, size = OffsetToNodes - sizeof (ACPI_TABLE_IORT))
1816      * Optionally allows the generic data types to be used for filling
1817      * this field.
1818      */
1819     Iort->NodeOffset = sizeof (ACPI_TABLE_IORT);
1820     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortPad,
1821         &Subtable);
1822     if (ACPI_FAILURE (Status))
1823     {
1824         return (Status);
1825     }
1826     if (Subtable)
1827     {
1828         DtInsertSubtable (ParentTable, Subtable);
1829         Iort->NodeOffset += Subtable->Length;
1830     }
1831     else
1832     {
1833         Status = DtCompileGeneric (ACPI_CAST_PTR (void *, PFieldList),
1834             AcpiDmTableInfoIortHdr[0].Name, &PaddingLength);
1835         if (ACPI_FAILURE (Status))
1836         {
1837             return (Status);
1838         }
1839         Iort->NodeOffset += PaddingLength;
1840     }
1841 
1842     NodeNumber = 0;
1843     while (*PFieldList)
1844     {
1845         SubtableStart = *PFieldList;
1846         if (Revision == 0)
1847         {
1848             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr,
1849                 &Subtable);
1850         }
1851         else if (Revision >= 3)
1852         {
1853             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr3,
1854                 &Subtable);
1855         }
1856 
1857         if (ACPI_FAILURE (Status))
1858         {
1859             return (Status);
1860         }
1861 
1862         DtInsertSubtable (ParentTable, Subtable);
1863         IortNode = ACPI_CAST_PTR (ACPI_IORT_NODE, Subtable->Buffer);
1864         NodeLength = ACPI_OFFSET (ACPI_IORT_NODE, NodeData);
1865 
1866         DtPushSubtable (Subtable);
1867         ParentTable = DtPeekSubtable ();
1868 
1869         switch (IortNode->Type)
1870         {
1871         case ACPI_IORT_NODE_ITS_GROUP:
1872 
1873             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0,
1874                 &Subtable);
1875             if (ACPI_FAILURE (Status))
1876             {
1877                 return (Status);
1878             }
1879 
1880             DtInsertSubtable (ParentTable, Subtable);
1881             IortItsGroup = ACPI_CAST_PTR (ACPI_IORT_ITS_GROUP, Subtable->Buffer);
1882             NodeLength += Subtable->Length;
1883 
1884             ItsNumber = 0;
1885             while (*PFieldList)
1886             {
1887                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0a,
1888                     &Subtable);
1889                 if (ACPI_FAILURE (Status))
1890                 {
1891                     return (Status);
1892                 }
1893                 if (!Subtable)
1894                 {
1895                     break;
1896                 }
1897 
1898                 DtInsertSubtable (ParentTable, Subtable);
1899                 NodeLength += Subtable->Length;
1900                 ItsNumber++;
1901             }
1902 
1903             IortItsGroup->ItsCount = ItsNumber;
1904             break;
1905 
1906         case ACPI_IORT_NODE_NAMED_COMPONENT:
1907 
1908             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1,
1909                 &Subtable);
1910             if (ACPI_FAILURE (Status))
1911             {
1912                 return (Status);
1913             }
1914 
1915             DtInsertSubtable (ParentTable, Subtable);
1916             NodeLength += Subtable->Length;
1917 
1918             /*
1919              * Padding - Variable-length data
1920              * Optionally allows the offset of the ID mappings to be used
1921              * for filling this field.
1922              */
1923             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1a,
1924                 &Subtable);
1925             if (ACPI_FAILURE (Status))
1926             {
1927                 return (Status);
1928             }
1929 
1930             if (Subtable)
1931             {
1932                 DtInsertSubtable (ParentTable, Subtable);
1933                 NodeLength += Subtable->Length;
1934             }
1935             else
1936             {
1937                 if (NodeLength > IortNode->MappingOffset)
1938                 {
1939                     return (AE_BAD_DATA);
1940                 }
1941 
1942                 if (NodeLength < IortNode->MappingOffset)
1943                 {
1944                     Status = DtCompilePadding (
1945                         IortNode->MappingOffset - NodeLength,
1946                         &Subtable);
1947                     if (ACPI_FAILURE (Status))
1948                     {
1949                         return (Status);
1950                     }
1951 
1952                     DtInsertSubtable (ParentTable, Subtable);
1953                     NodeLength = IortNode->MappingOffset;
1954                 }
1955             }
1956             break;
1957 
1958         case ACPI_IORT_NODE_PCI_ROOT_COMPLEX:
1959 
1960             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort2,
1961                 &Subtable);
1962             if (ACPI_FAILURE (Status))
1963             {
1964                 return (Status);
1965             }
1966 
1967             DtInsertSubtable (ParentTable, Subtable);
1968             NodeLength += Subtable->Length;
1969             break;
1970 
1971         case ACPI_IORT_NODE_SMMU:
1972 
1973             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3,
1974                 &Subtable);
1975             if (ACPI_FAILURE (Status))
1976             {
1977                 return (Status);
1978             }
1979 
1980             DtInsertSubtable (ParentTable, Subtable);
1981             IortSmmu = ACPI_CAST_PTR (ACPI_IORT_SMMU, Subtable->Buffer);
1982             NodeLength += Subtable->Length;
1983 
1984             /* Compile global interrupt array */
1985 
1986             IortSmmu->GlobalInterruptOffset = NodeLength;
1987             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3a,
1988                 &Subtable);
1989             if (ACPI_FAILURE (Status))
1990             {
1991                 return (Status);
1992             }
1993 
1994             DtInsertSubtable (ParentTable, Subtable);
1995             NodeLength += Subtable->Length;
1996 
1997             /* Compile context interrupt array */
1998 
1999             ContextIrptNumber = 0;
2000             IortSmmu->ContextInterruptOffset = NodeLength;
2001             while (*PFieldList)
2002             {
2003                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3b,
2004                     &Subtable);
2005                 if (ACPI_FAILURE (Status))
2006                 {
2007                     return (Status);
2008                 }
2009 
2010                 if (!Subtable)
2011                 {
2012                     break;
2013                 }
2014 
2015                 DtInsertSubtable (ParentTable, Subtable);
2016                 NodeLength += Subtable->Length;
2017                 ContextIrptNumber++;
2018             }
2019 
2020             IortSmmu->ContextInterruptCount = ContextIrptNumber;
2021 
2022             /* Compile PMU interrupt array */
2023 
2024             PmuIrptNumber = 0;
2025             IortSmmu->PmuInterruptOffset = NodeLength;
2026             while (*PFieldList)
2027             {
2028                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3c,
2029                     &Subtable);
2030                 if (ACPI_FAILURE (Status))
2031                 {
2032                     return (Status);
2033                 }
2034 
2035                 if (!Subtable)
2036                 {
2037                     break;
2038                 }
2039 
2040                 DtInsertSubtable (ParentTable, Subtable);
2041                 NodeLength += Subtable->Length;
2042                 PmuIrptNumber++;
2043             }
2044 
2045             IortSmmu->PmuInterruptCount = PmuIrptNumber;
2046             break;
2047 
2048         case ACPI_IORT_NODE_SMMU_V3:
2049 
2050             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort4,
2051                 &Subtable);
2052             if (ACPI_FAILURE (Status))
2053             {
2054                 return (Status);
2055             }
2056 
2057             DtInsertSubtable (ParentTable, Subtable);
2058             NodeLength += Subtable->Length;
2059             break;
2060 
2061         case ACPI_IORT_NODE_PMCG:
2062 
2063             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort5,
2064                 &Subtable);
2065             if (ACPI_FAILURE (Status))
2066             {
2067                 return (Status);
2068             }
2069 
2070             DtInsertSubtable (ParentTable, Subtable);
2071             NodeLength += Subtable->Length;
2072             break;
2073 
2074         case ACPI_IORT_NODE_RMR:
2075 
2076             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6,
2077                 &Subtable);
2078             if (ACPI_FAILURE (Status))
2079             {
2080                 return (Status);
2081             }
2082 
2083             DtInsertSubtable (ParentTable, Subtable);
2084             IortRmr = ACPI_CAST_PTR (ACPI_IORT_RMR, Subtable->Buffer);
2085             NodeLength += Subtable->Length;
2086 
2087             /* Compile RMR Descriptors */
2088 
2089             RmrCount = 0;
2090             IortRmr->RmrOffset = NodeLength;
2091             while (*PFieldList)
2092             {
2093                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6a,
2094                     &Subtable);
2095                 if (ACPI_FAILURE (Status))
2096                 {
2097                     return (Status);
2098                 }
2099 
2100                 if (!Subtable)
2101                 {
2102                     break;
2103                 }
2104 
2105                 DtInsertSubtable (ParentTable, Subtable);
2106                 NodeLength += sizeof (ACPI_IORT_RMR_DESC);
2107                 RmrCount++;
2108             }
2109 
2110             IortRmr->RmrCount = RmrCount;
2111             break;
2112 
2113 	default:
2114 
2115             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IORT");
2116             return (AE_ERROR);
2117         }
2118 
2119         /* Compile Array of ID mappings */
2120 
2121         IortNode->MappingOffset = NodeLength;
2122         IdMappingNumber = 0;
2123         while (*PFieldList)
2124         {
2125             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortMap,
2126                 &Subtable);
2127             if (ACPI_FAILURE (Status))
2128             {
2129                 return (Status);
2130             }
2131 
2132             if (!Subtable)
2133             {
2134                 break;
2135             }
2136 
2137             DtInsertSubtable (ParentTable, Subtable);
2138             NodeLength += sizeof (ACPI_IORT_ID_MAPPING);
2139             IdMappingNumber++;
2140         }
2141 
2142         IortNode->MappingCount = IdMappingNumber;
2143         if (!IdMappingNumber)
2144         {
2145             IortNode->MappingOffset = 0;
2146         }
2147 
2148         /*
2149          * Node length can be determined by DT_LENGTH option
2150          * IortNode->Length = NodeLength;
2151          */
2152         DtPopSubtable ();
2153         ParentTable = DtPeekSubtable ();
2154         NodeNumber++;
2155     }
2156 
2157     Iort->NodeCount = NodeNumber;
2158     return (AE_OK);
2159 }
2160 
2161 
2162 /******************************************************************************
2163  *
2164  * FUNCTION:    DtCompileIvrs
2165  *
2166  * PARAMETERS:  List                - Current field list pointer
2167  *
2168  * RETURN:      Status
2169  *
2170  * DESCRIPTION: Compile IVRS. Notes:
2171  *              The IVRS is essentially a flat table, with the following
2172  *              structure:
2173  *              <Main ACPI Table Header>
2174  *              <Main subtable - virtualization info>
2175  *              <IVHD>
2176  *                  <Device Entries>
2177  *              ...
2178  *              <IVHD>
2179  *                  <Device Entries>
2180  *              <IVMD>
2181  *              ...
2182  *
2183  *****************************************************************************/
2184 
2185 ACPI_STATUS
2186 DtCompileIvrs (
2187     void                    **List)
2188 {
2189     ACPI_STATUS             Status;
2190     DT_SUBTABLE             *Subtable;
2191     DT_SUBTABLE             *ParentTable;
2192     DT_SUBTABLE             *MainSubtable;
2193     DT_FIELD                **PFieldList = (DT_FIELD **) List;
2194     DT_FIELD                *SubtableStart;
2195     ACPI_DMTABLE_INFO       *InfoTable = NULL;
2196     UINT8                   SubtableType;
2197     UINT8                   Temp64[16];
2198     UINT8                   Temp8;
2199 
2200 
2201     /* Main table */
2202 
2203     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrs,
2204         &Subtable);
2205     if (ACPI_FAILURE (Status))
2206     {
2207         return (Status);
2208     }
2209 
2210     ParentTable = DtPeekSubtable ();
2211     DtInsertSubtable (ParentTable, Subtable);
2212     DtPushSubtable (Subtable);
2213 
2214     /* Save a pointer to the main subtable */
2215 
2216     MainSubtable = Subtable;
2217 
2218     while (*PFieldList)
2219     {
2220         SubtableStart = *PFieldList;
2221 
2222         /* Compile the SubtableType integer */
2223 
2224         DtCompileInteger (&SubtableType, *PFieldList, 1, 0);
2225 
2226         switch (SubtableType)
2227         {
2228 
2229         /* Type 10h, IVHD (I/O Virtualization Hardware Definition) */
2230 
2231         case ACPI_IVRS_TYPE_HARDWARE1:
2232 
2233             InfoTable = AcpiDmTableInfoIvrsHware1;
2234             break;
2235 
2236         /* Types 11h, 40h, IVHD (I/O Virtualization Hardware Definition) */
2237 
2238         case ACPI_IVRS_TYPE_HARDWARE2:
2239         case ACPI_IVRS_TYPE_HARDWARE3:
2240 
2241             InfoTable = AcpiDmTableInfoIvrsHware23;
2242             break;
2243 
2244         /* Types 20h, 21h, 22h, IVMD (I/O Virtualization Memory Definition Block) */
2245 
2246         case ACPI_IVRS_TYPE_MEMORY1:
2247         case ACPI_IVRS_TYPE_MEMORY2:
2248         case ACPI_IVRS_TYPE_MEMORY3:
2249 
2250             InfoTable = AcpiDmTableInfoIvrsMemory;
2251             break;
2252 
2253         /* 4-byte device entries */
2254 
2255         case ACPI_IVRS_TYPE_PAD4:
2256         case ACPI_IVRS_TYPE_ALL:
2257         case ACPI_IVRS_TYPE_SELECT:
2258         case ACPI_IVRS_TYPE_START:
2259         case ACPI_IVRS_TYPE_END:
2260 
2261             InfoTable = AcpiDmTableInfoIvrs4;
2262             break;
2263 
2264         /* 8-byte device entries, type A */
2265 
2266         case ACPI_IVRS_TYPE_ALIAS_SELECT:
2267         case ACPI_IVRS_TYPE_ALIAS_START:
2268 
2269             InfoTable = AcpiDmTableInfoIvrs8a;
2270             break;
2271 
2272         /* 8-byte device entries, type B */
2273 
2274         case ACPI_IVRS_TYPE_EXT_SELECT:
2275         case ACPI_IVRS_TYPE_EXT_START:
2276 
2277             InfoTable = AcpiDmTableInfoIvrs8b;
2278             break;
2279 
2280         /* 8-byte device entries, type C */
2281 
2282         case ACPI_IVRS_TYPE_SPECIAL:
2283 
2284             InfoTable = AcpiDmTableInfoIvrs8c;
2285             break;
2286 
2287         /* Variable device entries, type F0h */
2288 
2289         case ACPI_IVRS_TYPE_HID:
2290 
2291             InfoTable = AcpiDmTableInfoIvrsHid;
2292             break;
2293 
2294         default:
2295 
2296             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart,
2297                 "IVRS Device Entry");
2298             return (AE_ERROR);
2299         }
2300 
2301         /* Compile the InfoTable from above */
2302 
2303         Status = DtCompileTable (PFieldList, InfoTable,
2304             &Subtable);
2305         if (ACPI_FAILURE (Status))
2306         {
2307             return (Status);
2308         }
2309 
2310         ParentTable = DtPeekSubtable ();
2311         if (SubtableType != ACPI_IVRS_TYPE_HARDWARE1 &&
2312             SubtableType != ACPI_IVRS_TYPE_HARDWARE2 &&
2313             SubtableType != ACPI_IVRS_TYPE_HARDWARE3 &&
2314             SubtableType != ACPI_IVRS_TYPE_HID &&
2315             SubtableType != ACPI_IVRS_TYPE_MEMORY1 &&
2316             SubtableType != ACPI_IVRS_TYPE_MEMORY2 &&
2317             SubtableType != ACPI_IVRS_TYPE_MEMORY3)
2318         {
2319             if (ParentTable)
2320                 DtInsertSubtable (ParentTable, Subtable);
2321         }
2322 
2323         switch (SubtableType)
2324         {
2325         case ACPI_IVRS_TYPE_HARDWARE1:
2326         case ACPI_IVRS_TYPE_HARDWARE2:
2327         case ACPI_IVRS_TYPE_HARDWARE3:
2328         case ACPI_IVRS_TYPE_MEMORY1:
2329         case ACPI_IVRS_TYPE_MEMORY2:
2330         case ACPI_IVRS_TYPE_MEMORY3:
2331 
2332             /* Insert these IVHDs/IVMDs at the root subtable */
2333 
2334             DtInsertSubtable (MainSubtable, Subtable);
2335             DtPushSubtable (Subtable);
2336             ParentTable = MainSubtable;
2337             break;
2338 
2339         case ACPI_IVRS_TYPE_HID:
2340 
2341             /* Special handling for the HID named device entry (0xF0) */
2342 
2343             if (ParentTable)
2344             {
2345                 DtInsertSubtable (ParentTable, Subtable);
2346             }
2347 
2348             /*
2349              * Process the HID value. First, get the HID value as a string.
2350              */
2351             DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0);
2352 
2353                /*
2354                 * Determine if the HID is an integer or a string.
2355                 * An integer is defined to be 32 bits, with the upper 32 bits
2356                 * set to zero. (from the ACPI Spec): "The HID can be a 32-bit
2357                 * integer or a character string. If an integer, the lower
2358                 * 4 bytes of the field contain the integer and the upper
2359                 * 4 bytes are padded with 0".
2360                 */
2361             if (UtIsIdInteger ((UINT8 *) &Temp64))
2362             {
2363                 /* Compile the HID value as an integer */
2364 
2365                 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0);
2366 
2367                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidInteger,
2368                     &Subtable);
2369                 if (ACPI_FAILURE (Status))
2370                 {
2371                     return (Status);
2372                 }
2373             }
2374             else
2375             {
2376                 /* Compile the HID value as a string */
2377 
2378                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidString,
2379                     &Subtable);
2380                 if (ACPI_FAILURE (Status))
2381                 {
2382                     return (Status);
2383                 }
2384             }
2385 
2386             DtInsertSubtable (ParentTable, Subtable);
2387 
2388             /*
2389              * Process the CID value. First, get the CID value as a string.
2390              */
2391             DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0);
2392 
2393             if (UtIsIdInteger ((UINT8 *) &Temp64))
2394             {
2395                 /* Compile the CID value as an integer */
2396 
2397                 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0);
2398 
2399                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidInteger,
2400                     &Subtable);
2401                 if (ACPI_FAILURE (Status))
2402                 {
2403                     return (Status);
2404                 }
2405             }
2406             else
2407             {
2408                 /* Compile the CID value as a string */
2409 
2410                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidString,
2411                     &Subtable);
2412                 if (ACPI_FAILURE (Status))
2413                 {
2414                     return (Status);
2415                 }
2416             }
2417 
2418             DtInsertSubtable (ParentTable, Subtable);
2419 
2420             /*
2421              * Process the UID value. First, get and decode the "UID Format" field (Integer).
2422              */
2423             if (!*PFieldList)
2424             {
2425                 return (AE_OK);
2426             }
2427 
2428             DtCompileOneField (&Temp8, *PFieldList, 1, DT_FIELD_TYPE_INTEGER, 0);
2429 
2430             switch (Temp8)
2431             {
2432             case ACPI_IVRS_UID_NOT_PRESENT:
2433                 break;
2434 
2435             case ACPI_IVRS_UID_IS_INTEGER:
2436 
2437                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidInteger,
2438                     &Subtable);
2439                 if (ACPI_FAILURE (Status))
2440                 {
2441                     return (Status);
2442                 }
2443                 DtInsertSubtable (ParentTable, Subtable);
2444                 break;
2445 
2446             case ACPI_IVRS_UID_IS_STRING:
2447 
2448                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidString,
2449                     &Subtable);
2450                 if (ACPI_FAILURE (Status))
2451                 {
2452                     return (Status);
2453                 }
2454                 DtInsertSubtable (ParentTable, Subtable);
2455                 break;
2456 
2457             default:
2458 
2459                 DtFatal (ASL_MSG_UNKNOWN_FORMAT, SubtableStart,
2460                     "IVRS Device Entry");
2461                 return (AE_ERROR);
2462             }
2463 
2464         default:
2465 
2466             /* All other subtable types come through here */
2467             break;
2468         }
2469     }
2470 
2471     return (AE_OK);
2472 }
2473