xref: /freebsd/sys/contrib/dev/acpica/compiler/dttable1.c (revision a7dea1671b87c07d2d266f836bfa8b58efc7c134)
1 /******************************************************************************
2  *
3  * Module Name: dttable1.c - handling for specific ACPI tables
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2020, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************
115  *
116  * Alternatively, you may choose to be licensed under the terms of the
117  * following license:
118  *
119  * Redistribution and use in source and binary forms, with or without
120  * modification, are permitted provided that the following conditions
121  * are met:
122  * 1. Redistributions of source code must retain the above copyright
123  *    notice, this list of conditions, and the following disclaimer,
124  *    without modification.
125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126  *    substantially similar to the "NO WARRANTY" disclaimer below
127  *    ("Disclaimer") and any redistribution must be conditioned upon
128  *    including a substantially similar Disclaimer requirement for further
129  *    binary redistribution.
130  * 3. Neither the names of the above-listed copyright holders nor the names
131  *    of any contributors may be used to endorse or promote products derived
132  *    from this software without specific prior written permission.
133  *
134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145  *
146  * Alternatively, you may choose to be licensed under the terms of the
147  * GNU General Public License ("GPL") version 2 as published by the Free
148  * Software Foundation.
149  *
150  *****************************************************************************/
151 
152 /* Compile all complex data tables, signatures starting with A-I */
153 
154 #include <contrib/dev/acpica/compiler/aslcompiler.h>
155 
156 #define _COMPONENT          DT_COMPILER
157         ACPI_MODULE_NAME    ("dttable1")
158 
159 
160 static ACPI_DMTABLE_INFO           TableInfoAsfAddress[] =
161 {
162     {ACPI_DMT_BUFFER,   0,               "Addresses", 0},
163     {ACPI_DMT_EXIT,     0,               NULL, 0}
164 };
165 
166 static ACPI_DMTABLE_INFO           TableInfoDmarPciPath[] =
167 {
168     {ACPI_DMT_PCI_PATH, 0,               "PCI Path", 0},
169     {ACPI_DMT_EXIT,     0,               NULL, 0}
170 };
171 
172 
173 /******************************************************************************
174  *
175  * FUNCTION:    DtCompileAsf
176  *
177  * PARAMETERS:  List                - Current field list pointer
178  *
179  * RETURN:      Status
180  *
181  * DESCRIPTION: Compile ASF!.
182  *
183  *****************************************************************************/
184 
185 ACPI_STATUS
186 DtCompileAsf (
187     void                    **List)
188 {
189     ACPI_ASF_INFO           *AsfTable;
190     DT_SUBTABLE             *Subtable;
191     DT_SUBTABLE             *ParentTable;
192     ACPI_DMTABLE_INFO       *InfoTable;
193     ACPI_DMTABLE_INFO       *DataInfoTable = NULL;
194     UINT32                  DataCount = 0;
195     ACPI_STATUS             Status;
196     UINT32                  i;
197     DT_FIELD                **PFieldList = (DT_FIELD **) List;
198     DT_FIELD                *SubtableStart;
199 
200 
201     while (*PFieldList)
202     {
203         SubtableStart = *PFieldList;
204         Status = DtCompileTable (PFieldList, AcpiDmTableInfoAsfHdr,
205             &Subtable);
206         if (ACPI_FAILURE (Status))
207         {
208             return (Status);
209         }
210 
211         ParentTable = DtPeekSubtable ();
212         DtInsertSubtable (ParentTable, Subtable);
213         DtPushSubtable (Subtable);
214 
215         AsfTable = ACPI_CAST_PTR (ACPI_ASF_INFO, Subtable->Buffer);
216 
217         switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */
218         {
219         case ACPI_ASF_TYPE_INFO:
220 
221             InfoTable = AcpiDmTableInfoAsf0;
222             break;
223 
224         case ACPI_ASF_TYPE_ALERT:
225 
226             InfoTable = AcpiDmTableInfoAsf1;
227             break;
228 
229         case ACPI_ASF_TYPE_CONTROL:
230 
231             InfoTable = AcpiDmTableInfoAsf2;
232             break;
233 
234         case ACPI_ASF_TYPE_BOOT:
235 
236             InfoTable = AcpiDmTableInfoAsf3;
237             break;
238 
239         case ACPI_ASF_TYPE_ADDRESS:
240 
241             InfoTable = AcpiDmTableInfoAsf4;
242             break;
243 
244         default:
245 
246             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!");
247             return (AE_ERROR);
248         }
249 
250         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
251         if (ACPI_FAILURE (Status))
252         {
253             return (Status);
254         }
255 
256         ParentTable = DtPeekSubtable ();
257         DtInsertSubtable (ParentTable, Subtable);
258 
259         switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */
260         {
261         case ACPI_ASF_TYPE_INFO:
262 
263             DataInfoTable = NULL;
264             break;
265 
266         case ACPI_ASF_TYPE_ALERT:
267 
268             DataInfoTable = AcpiDmTableInfoAsf1a;
269             DataCount = ACPI_CAST_PTR (ACPI_ASF_ALERT,
270                 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
271                     sizeof (ACPI_ASF_HEADER)))->Alerts;
272             break;
273 
274         case ACPI_ASF_TYPE_CONTROL:
275 
276             DataInfoTable = AcpiDmTableInfoAsf2a;
277             DataCount = ACPI_CAST_PTR (ACPI_ASF_REMOTE,
278                 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
279                     sizeof (ACPI_ASF_HEADER)))->Controls;
280             break;
281 
282         case ACPI_ASF_TYPE_BOOT:
283 
284             DataInfoTable = NULL;
285             break;
286 
287         case ACPI_ASF_TYPE_ADDRESS:
288 
289             DataInfoTable = TableInfoAsfAddress;
290             DataCount = ACPI_CAST_PTR (ACPI_ASF_ADDRESS,
291                 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
292                     sizeof (ACPI_ASF_HEADER)))->Devices;
293             break;
294 
295         default:
296 
297             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!");
298             return (AE_ERROR);
299         }
300 
301         if (DataInfoTable)
302         {
303             switch (AsfTable->Header.Type & 0x7F)
304             {
305             case ACPI_ASF_TYPE_ADDRESS:
306 
307                 while (DataCount > 0)
308                 {
309                     Status = DtCompileTable (PFieldList, DataInfoTable,
310                         &Subtable);
311                     if (ACPI_FAILURE (Status))
312                     {
313                         return (Status);
314                     }
315 
316                     DtInsertSubtable (ParentTable, Subtable);
317                     DataCount = DataCount - Subtable->Length;
318                 }
319                 break;
320 
321             default:
322 
323                 for (i = 0; i < DataCount; i++)
324                 {
325                     Status = DtCompileTable (PFieldList, DataInfoTable,
326                         &Subtable);
327                     if (ACPI_FAILURE (Status))
328                     {
329                         return (Status);
330                     }
331 
332                     DtInsertSubtable (ParentTable, Subtable);
333                 }
334                 break;
335             }
336         }
337 
338         DtPopSubtable ();
339     }
340 
341     return (AE_OK);
342 }
343 
344 
345 /******************************************************************************
346  *
347  * FUNCTION:    DtCompileCpep
348  *
349  * PARAMETERS:  List                - Current field list pointer
350  *
351  * RETURN:      Status
352  *
353  * DESCRIPTION: Compile CPEP.
354  *
355  *****************************************************************************/
356 
357 ACPI_STATUS
358 DtCompileCpep (
359     void                    **List)
360 {
361     ACPI_STATUS             Status;
362 
363 
364     Status = DtCompileTwoSubtables (List,
365         AcpiDmTableInfoCpep, AcpiDmTableInfoCpep0);
366     return (Status);
367 }
368 
369 
370 /******************************************************************************
371  *
372  * FUNCTION:    DtCompileCsrt
373  *
374  * PARAMETERS:  List                - Current field list pointer
375  *
376  * RETURN:      Status
377  *
378  * DESCRIPTION: Compile CSRT.
379  *
380  *****************************************************************************/
381 
382 ACPI_STATUS
383 DtCompileCsrt (
384     void                    **List)
385 {
386     ACPI_STATUS             Status = AE_OK;
387     DT_SUBTABLE             *Subtable;
388     DT_SUBTABLE             *ParentTable;
389     DT_FIELD                **PFieldList = (DT_FIELD **) List;
390     UINT32                  DescriptorCount;
391     UINT32                  GroupLength;
392 
393 
394     /* Subtables (Resource Groups) */
395 
396     ParentTable = DtPeekSubtable ();
397     while (*PFieldList)
398     {
399         /* Resource group subtable */
400 
401         Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt0,
402             &Subtable);
403         if (ACPI_FAILURE (Status))
404         {
405             return (Status);
406         }
407 
408         /* Compute the number of resource descriptors */
409 
410         GroupLength =
411             (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
412                 Subtable->Buffer))->Length -
413             (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
414                 Subtable->Buffer))->SharedInfoLength -
415             sizeof (ACPI_CSRT_GROUP);
416 
417         DescriptorCount = (GroupLength  /
418             sizeof (ACPI_CSRT_DESCRIPTOR));
419 
420         DtInsertSubtable (ParentTable, Subtable);
421         DtPushSubtable (Subtable);
422         ParentTable = DtPeekSubtable ();
423 
424         /* Shared info subtable (One per resource group) */
425 
426         Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt1,
427             &Subtable);
428         if (ACPI_FAILURE (Status))
429         {
430             return (Status);
431         }
432 
433         DtInsertSubtable (ParentTable, Subtable);
434 
435         /* Sub-Subtables (Resource Descriptors) */
436 
437         while (*PFieldList && DescriptorCount)
438         {
439 
440             Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2,
441                 &Subtable);
442             if (ACPI_FAILURE (Status))
443             {
444                 return (Status);
445             }
446 
447             DtInsertSubtable (ParentTable, Subtable);
448 
449             DtPushSubtable (Subtable);
450             ParentTable = DtPeekSubtable ();
451             if (*PFieldList)
452             {
453                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2a,
454                     &Subtable);
455                 if (ACPI_FAILURE (Status))
456                 {
457                     return (Status);
458                 }
459                 if (Subtable)
460                 {
461                     DtInsertSubtable (ParentTable, Subtable);
462                 }
463             }
464 
465             DtPopSubtable ();
466             ParentTable = DtPeekSubtable ();
467             DescriptorCount--;
468         }
469 
470         DtPopSubtable ();
471         ParentTable = DtPeekSubtable ();
472     }
473 
474     return (Status);
475 }
476 
477 
478 /******************************************************************************
479  *
480  * FUNCTION:    DtCompileDbg2
481  *
482  * PARAMETERS:  List                - Current field list pointer
483  *
484  * RETURN:      Status
485  *
486  * DESCRIPTION: Compile DBG2.
487  *
488  *****************************************************************************/
489 
490 ACPI_STATUS
491 DtCompileDbg2 (
492     void                    **List)
493 {
494     ACPI_STATUS             Status;
495     DT_SUBTABLE             *Subtable;
496     DT_SUBTABLE             *ParentTable;
497     DT_FIELD                **PFieldList = (DT_FIELD **) List;
498     UINT32                  SubtableCount;
499     ACPI_DBG2_HEADER        *Dbg2Header;
500     ACPI_DBG2_DEVICE        *DeviceInfo;
501     UINT16                  CurrentOffset;
502     UINT32                  i;
503 
504 
505     /* Main table */
506 
507     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2, &Subtable);
508     if (ACPI_FAILURE (Status))
509     {
510         return (Status);
511     }
512 
513     ParentTable = DtPeekSubtable ();
514     DtInsertSubtable (ParentTable, Subtable);
515 
516     /* Main table fields */
517 
518     Dbg2Header = ACPI_CAST_PTR (ACPI_DBG2_HEADER, Subtable->Buffer);
519     Dbg2Header->InfoOffset = sizeof (ACPI_TABLE_HEADER) + ACPI_PTR_DIFF (
520         ACPI_ADD_PTR (UINT8, Dbg2Header, sizeof (ACPI_DBG2_HEADER)), Dbg2Header);
521 
522     SubtableCount = Dbg2Header->InfoCount;
523     DtPushSubtable (Subtable);
524 
525     /* Process all Device Information subtables (Count = InfoCount) */
526 
527     while (*PFieldList && SubtableCount)
528     {
529         /* Subtable: Debug Device Information */
530 
531         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Device,
532             &Subtable);
533         if (ACPI_FAILURE (Status))
534         {
535             return (Status);
536         }
537 
538         DeviceInfo = ACPI_CAST_PTR (ACPI_DBG2_DEVICE, Subtable->Buffer);
539         CurrentOffset = (UINT16) sizeof (ACPI_DBG2_DEVICE);
540 
541         ParentTable = DtPeekSubtable ();
542         DtInsertSubtable (ParentTable, Subtable);
543         DtPushSubtable (Subtable);
544 
545         ParentTable = DtPeekSubtable ();
546 
547         /* BaseAddressRegister GAS array (Required, size is RegisterCount) */
548 
549         DeviceInfo->BaseAddressOffset = CurrentOffset;
550         for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++)
551         {
552             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Addr,
553                 &Subtable);
554             if (ACPI_FAILURE (Status))
555             {
556                 return (Status);
557             }
558 
559             CurrentOffset += (UINT16) sizeof (ACPI_GENERIC_ADDRESS);
560             DtInsertSubtable (ParentTable, Subtable);
561         }
562 
563         /* AddressSize array (Required, size = RegisterCount) */
564 
565         DeviceInfo->AddressSizeOffset = CurrentOffset;
566         for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++)
567         {
568             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Size,
569                 &Subtable);
570             if (ACPI_FAILURE (Status))
571             {
572                 return (Status);
573             }
574 
575             CurrentOffset += (UINT16) sizeof (UINT32);
576             DtInsertSubtable (ParentTable, Subtable);
577         }
578 
579         /* NamespaceString device identifier (Required, size = NamePathLength) */
580 
581         DeviceInfo->NamepathOffset = CurrentOffset;
582         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Name,
583             &Subtable);
584         if (ACPI_FAILURE (Status))
585         {
586             return (Status);
587         }
588 
589         /* Update the device info header */
590 
591         DeviceInfo->NamepathLength = (UINT16) Subtable->Length;
592         CurrentOffset += (UINT16) DeviceInfo->NamepathLength;
593         DtInsertSubtable (ParentTable, Subtable);
594 
595         /* OemData - Variable-length data (Optional, size = OemDataLength) */
596 
597         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2OemData,
598             &Subtable);
599         if (Status == AE_END_OF_TABLE)
600         {
601             /* optional field was not found and we're at the end of the file */
602 
603             goto subtableDone;
604         }
605         else if (ACPI_FAILURE (Status))
606         {
607             return (Status);
608         }
609 
610         /* Update the device info header (zeros if no OEM data present) */
611 
612         DeviceInfo->OemDataOffset = 0;
613         DeviceInfo->OemDataLength = 0;
614 
615         /* Optional subtable (OemData) */
616 
617         if (Subtable && Subtable->Length)
618         {
619             DeviceInfo->OemDataOffset = CurrentOffset;
620             DeviceInfo->OemDataLength = (UINT16) Subtable->Length;
621 
622             DtInsertSubtable (ParentTable, Subtable);
623         }
624 subtableDone:
625         SubtableCount--;
626         DtPopSubtable (); /* Get next Device Information subtable */
627     }
628 
629     DtPopSubtable ();
630     return (AE_OK);
631 }
632 
633 
634 /******************************************************************************
635  *
636  * FUNCTION:    DtCompileDmar
637  *
638  * PARAMETERS:  List                - Current field list pointer
639  *
640  * RETURN:      Status
641  *
642  * DESCRIPTION: Compile DMAR.
643  *
644  *****************************************************************************/
645 
646 ACPI_STATUS
647 DtCompileDmar (
648     void                    **List)
649 {
650     ACPI_STATUS             Status;
651     DT_SUBTABLE             *Subtable;
652     DT_SUBTABLE             *ParentTable;
653     DT_FIELD                **PFieldList = (DT_FIELD **) List;
654     DT_FIELD                *SubtableStart;
655     ACPI_DMTABLE_INFO       *InfoTable;
656     ACPI_DMAR_HEADER        *DmarHeader;
657     ACPI_DMAR_DEVICE_SCOPE  *DmarDeviceScope;
658     UINT32                  DeviceScopeLength;
659     UINT32                  PciPathLength;
660 
661 
662     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmar, &Subtable);
663     if (ACPI_FAILURE (Status))
664     {
665         return (Status);
666     }
667 
668     ParentTable = DtPeekSubtable ();
669     DtInsertSubtable (ParentTable, Subtable);
670     DtPushSubtable (Subtable);
671 
672     while (*PFieldList)
673     {
674         /* DMAR Header */
675 
676         SubtableStart = *PFieldList;
677         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarHdr,
678             &Subtable);
679         if (ACPI_FAILURE (Status))
680         {
681             return (Status);
682         }
683 
684         ParentTable = DtPeekSubtable ();
685         DtInsertSubtable (ParentTable, Subtable);
686         DtPushSubtable (Subtable);
687 
688         DmarHeader = ACPI_CAST_PTR (ACPI_DMAR_HEADER, Subtable->Buffer);
689 
690         switch (DmarHeader->Type)
691         {
692         case ACPI_DMAR_TYPE_HARDWARE_UNIT:
693 
694             InfoTable = AcpiDmTableInfoDmar0;
695             break;
696 
697         case ACPI_DMAR_TYPE_RESERVED_MEMORY:
698 
699             InfoTable = AcpiDmTableInfoDmar1;
700             break;
701 
702         case ACPI_DMAR_TYPE_ROOT_ATS:
703 
704             InfoTable = AcpiDmTableInfoDmar2;
705             break;
706 
707         case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
708 
709             InfoTable = AcpiDmTableInfoDmar3;
710             break;
711 
712         case ACPI_DMAR_TYPE_NAMESPACE:
713 
714             InfoTable = AcpiDmTableInfoDmar4;
715             break;
716 
717         default:
718 
719             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "DMAR");
720             return (AE_ERROR);
721         }
722 
723         /* DMAR Subtable */
724 
725         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
726         if (ACPI_FAILURE (Status))
727         {
728             return (Status);
729         }
730 
731         ParentTable = DtPeekSubtable ();
732         DtInsertSubtable (ParentTable, Subtable);
733 
734         /*
735          * Optional Device Scope subtables
736          */
737         if ((DmarHeader->Type == ACPI_DMAR_TYPE_HARDWARE_AFFINITY) ||
738             (DmarHeader->Type == ACPI_DMAR_TYPE_NAMESPACE))
739         {
740             /* These types do not support device scopes */
741 
742             DtPopSubtable ();
743             continue;
744         }
745 
746         DtPushSubtable (Subtable);
747         DeviceScopeLength = DmarHeader->Length - Subtable->Length -
748             ParentTable->Length;
749         while (DeviceScopeLength)
750         {
751             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarScope,
752                 &Subtable);
753             if (Status == AE_NOT_FOUND)
754             {
755                 break;
756             }
757 
758             ParentTable = DtPeekSubtable ();
759             DtInsertSubtable (ParentTable, Subtable);
760             DtPushSubtable (Subtable);
761 
762             DmarDeviceScope = ACPI_CAST_PTR (ACPI_DMAR_DEVICE_SCOPE, Subtable->Buffer);
763 
764             /* Optional PCI Paths */
765 
766             PciPathLength = DmarDeviceScope->Length - Subtable->Length;
767             while (PciPathLength)
768             {
769                 Status = DtCompileTable (PFieldList, TableInfoDmarPciPath,
770                     &Subtable);
771                 if (Status == AE_NOT_FOUND)
772                 {
773                     DtPopSubtable ();
774                     break;
775                 }
776 
777                 ParentTable = DtPeekSubtable ();
778                 DtInsertSubtable (ParentTable, Subtable);
779                 PciPathLength -= Subtable->Length;
780             }
781 
782             DtPopSubtable ();
783             DeviceScopeLength -= DmarDeviceScope->Length;
784         }
785 
786         DtPopSubtable ();
787         DtPopSubtable ();
788     }
789 
790     return (AE_OK);
791 }
792 
793 
794 /******************************************************************************
795  *
796  * FUNCTION:    DtCompileDrtm
797  *
798  * PARAMETERS:  List                - Current field list pointer
799  *
800  * RETURN:      Status
801  *
802  * DESCRIPTION: Compile DRTM.
803  *
804  *****************************************************************************/
805 
806 ACPI_STATUS
807 DtCompileDrtm (
808     void                    **List)
809 {
810     ACPI_STATUS             Status;
811     DT_SUBTABLE             *Subtable;
812     DT_SUBTABLE             *ParentTable;
813     DT_FIELD                **PFieldList = (DT_FIELD **) List;
814     UINT32                  Count;
815     /* ACPI_TABLE_DRTM         *Drtm; */
816     ACPI_DRTM_VTABLE_LIST   *DrtmVtl;
817     ACPI_DRTM_RESOURCE_LIST *DrtmRl;
818     /* ACPI_DRTM_DPS_ID        *DrtmDps; */
819 
820 
821     ParentTable = DtPeekSubtable ();
822 
823     /* Compile DRTM header */
824 
825     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm,
826         &Subtable);
827     if (ACPI_FAILURE (Status))
828     {
829         return (Status);
830     }
831     DtInsertSubtable (ParentTable, Subtable);
832 
833     /*
834      * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
835      * should be taken to avoid accessing ACPI_TABLE_HADER fields.
836      */
837 #if 0
838     Drtm = ACPI_SUB_PTR (ACPI_TABLE_DRTM,
839         Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
840 #endif
841     /* Compile VTL */
842 
843     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0,
844         &Subtable);
845     if (ACPI_FAILURE (Status))
846     {
847         return (Status);
848     }
849 
850     DtInsertSubtable (ParentTable, Subtable);
851     DrtmVtl = ACPI_CAST_PTR (ACPI_DRTM_VTABLE_LIST, Subtable->Buffer);
852 
853     DtPushSubtable (Subtable);
854     ParentTable = DtPeekSubtable ();
855     Count = 0;
856 
857     while (*PFieldList)
858     {
859         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0a,
860             &Subtable);
861         if (ACPI_FAILURE (Status))
862         {
863             return (Status);
864         }
865         if (!Subtable)
866         {
867             break;
868         }
869         DtInsertSubtable (ParentTable, Subtable);
870         Count++;
871     }
872 
873     DrtmVtl->ValidatedTableCount = Count;
874     DtPopSubtable ();
875     ParentTable = DtPeekSubtable ();
876 
877     /* Compile RL */
878 
879     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1,
880         &Subtable);
881     if (ACPI_FAILURE (Status))
882     {
883         return (Status);
884     }
885 
886     DtInsertSubtable (ParentTable, Subtable);
887     DrtmRl = ACPI_CAST_PTR (ACPI_DRTM_RESOURCE_LIST, Subtable->Buffer);
888 
889     DtPushSubtable (Subtable);
890     ParentTable = DtPeekSubtable ();
891     Count = 0;
892 
893     while (*PFieldList)
894     {
895         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1a,
896             &Subtable);
897         if (ACPI_FAILURE (Status))
898         {
899             return (Status);
900         }
901 
902         if (!Subtable)
903         {
904             break;
905         }
906 
907         DtInsertSubtable (ParentTable, Subtable);
908         Count++;
909     }
910 
911     DrtmRl->ResourceCount = Count;
912     DtPopSubtable ();
913     ParentTable = DtPeekSubtable ();
914 
915     /* Compile DPS */
916 
917     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm2,
918         &Subtable);
919     if (ACPI_FAILURE (Status))
920     {
921         return (Status);
922     }
923     DtInsertSubtable (ParentTable, Subtable);
924     /* DrtmDps = ACPI_CAST_PTR (ACPI_DRTM_DPS_ID, Subtable->Buffer);*/
925 
926 
927     return (AE_OK);
928 }
929 
930 
931 /******************************************************************************
932  *
933  * FUNCTION:    DtCompileEinj
934  *
935  * PARAMETERS:  List                - Current field list pointer
936  *
937  * RETURN:      Status
938  *
939  * DESCRIPTION: Compile EINJ.
940  *
941  *****************************************************************************/
942 
943 ACPI_STATUS
944 DtCompileEinj (
945     void                    **List)
946 {
947     ACPI_STATUS             Status;
948 
949 
950     Status = DtCompileTwoSubtables (List,
951         AcpiDmTableInfoEinj, AcpiDmTableInfoEinj0);
952     return (Status);
953 }
954 
955 
956 /******************************************************************************
957  *
958  * FUNCTION:    DtCompileErst
959  *
960  * PARAMETERS:  List                - Current field list pointer
961  *
962  * RETURN:      Status
963  *
964  * DESCRIPTION: Compile ERST.
965  *
966  *****************************************************************************/
967 
968 ACPI_STATUS
969 DtCompileErst (
970     void                    **List)
971 {
972     ACPI_STATUS             Status;
973 
974 
975     Status = DtCompileTwoSubtables (List,
976         AcpiDmTableInfoErst, AcpiDmTableInfoEinj0);
977     return (Status);
978 }
979 
980 
981 /******************************************************************************
982  *
983  * FUNCTION:    DtCompileGtdt
984  *
985  * PARAMETERS:  List                - Current field list pointer
986  *
987  * RETURN:      Status
988  *
989  * DESCRIPTION: Compile GTDT.
990  *
991  *****************************************************************************/
992 
993 ACPI_STATUS
994 DtCompileGtdt (
995     void                    **List)
996 {
997     ACPI_STATUS             Status;
998     DT_SUBTABLE             *Subtable;
999     DT_SUBTABLE             *ParentTable;
1000     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1001     DT_FIELD                *SubtableStart;
1002     ACPI_SUBTABLE_HEADER    *GtdtHeader;
1003     ACPI_DMTABLE_INFO       *InfoTable;
1004     UINT32                  GtCount;
1005     ACPI_TABLE_HEADER       *Header;
1006 
1007 
1008     ParentTable = DtPeekSubtable ();
1009 
1010     Header = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer);
1011 
1012     /* Compile the main table */
1013 
1014     Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt,
1015         &Subtable);
1016     if (ACPI_FAILURE (Status))
1017     {
1018         return (Status);
1019     }
1020 
1021     /* GTDT revision 3 later contains 2 extra fields before subtables */
1022 
1023     if (Header->Revision > 2)
1024     {
1025         ParentTable = DtPeekSubtable ();
1026         DtInsertSubtable (ParentTable, Subtable);
1027 
1028         Status = DtCompileTable (PFieldList,
1029             AcpiDmTableInfoGtdtEl2, &Subtable);
1030         if (ACPI_FAILURE (Status))
1031         {
1032             return (Status);
1033         }
1034     }
1035 
1036     ParentTable = DtPeekSubtable ();
1037     DtInsertSubtable (ParentTable, Subtable);
1038 
1039     while (*PFieldList)
1040     {
1041         SubtableStart = *PFieldList;
1042         Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdtHdr,
1043             &Subtable);
1044         if (ACPI_FAILURE (Status))
1045         {
1046             return (Status);
1047         }
1048 
1049         ParentTable = DtPeekSubtable ();
1050         DtInsertSubtable (ParentTable, Subtable);
1051         DtPushSubtable (Subtable);
1052 
1053         GtdtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer);
1054 
1055         switch (GtdtHeader->Type)
1056         {
1057         case ACPI_GTDT_TYPE_TIMER_BLOCK:
1058 
1059             InfoTable = AcpiDmTableInfoGtdt0;
1060             break;
1061 
1062         case ACPI_GTDT_TYPE_WATCHDOG:
1063 
1064             InfoTable = AcpiDmTableInfoGtdt1;
1065             break;
1066 
1067         default:
1068 
1069             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "GTDT");
1070             return (AE_ERROR);
1071         }
1072 
1073         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1074         if (ACPI_FAILURE (Status))
1075         {
1076             return (Status);
1077         }
1078 
1079         ParentTable = DtPeekSubtable ();
1080         DtInsertSubtable (ParentTable, Subtable);
1081 
1082         /*
1083          * Additional GT block subtable data
1084          */
1085 
1086         switch (GtdtHeader->Type)
1087         {
1088         case ACPI_GTDT_TYPE_TIMER_BLOCK:
1089 
1090             DtPushSubtable (Subtable);
1091             ParentTable = DtPeekSubtable ();
1092 
1093             GtCount = (ACPI_CAST_PTR (ACPI_GTDT_TIMER_BLOCK,
1094                 Subtable->Buffer - sizeof(ACPI_GTDT_HEADER)))->TimerCount;
1095 
1096             while (GtCount)
1097             {
1098                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt0a,
1099                     &Subtable);
1100                 if (ACPI_FAILURE (Status))
1101                 {
1102                     return (Status);
1103                 }
1104 
1105                 DtInsertSubtable (ParentTable, Subtable);
1106                 GtCount--;
1107             }
1108 
1109             DtPopSubtable ();
1110             break;
1111 
1112         default:
1113 
1114             break;
1115         }
1116 
1117         DtPopSubtable ();
1118     }
1119 
1120     return (AE_OK);
1121 }
1122 
1123 
1124 /******************************************************************************
1125  *
1126  * FUNCTION:    DtCompileFpdt
1127  *
1128  * PARAMETERS:  List                - Current field list pointer
1129  *
1130  * RETURN:      Status
1131  *
1132  * DESCRIPTION: Compile FPDT.
1133  *
1134  *****************************************************************************/
1135 
1136 ACPI_STATUS
1137 DtCompileFpdt (
1138     void                    **List)
1139 {
1140     ACPI_STATUS             Status;
1141     ACPI_FPDT_HEADER        *FpdtHeader;
1142     DT_SUBTABLE             *Subtable;
1143     DT_SUBTABLE             *ParentTable;
1144     ACPI_DMTABLE_INFO       *InfoTable;
1145     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1146     DT_FIELD                *SubtableStart;
1147 
1148 
1149     while (*PFieldList)
1150     {
1151         SubtableStart = *PFieldList;
1152         Status = DtCompileTable (PFieldList, AcpiDmTableInfoFpdtHdr,
1153             &Subtable);
1154         if (ACPI_FAILURE (Status))
1155         {
1156             return (Status);
1157         }
1158 
1159         ParentTable = DtPeekSubtable ();
1160         DtInsertSubtable (ParentTable, Subtable);
1161         DtPushSubtable (Subtable);
1162 
1163         FpdtHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer);
1164 
1165         switch (FpdtHeader->Type)
1166         {
1167         case ACPI_FPDT_TYPE_BOOT:
1168 
1169             InfoTable = AcpiDmTableInfoFpdt0;
1170             break;
1171 
1172         case ACPI_FPDT_TYPE_S3PERF:
1173 
1174             InfoTable = AcpiDmTableInfoFpdt1;
1175             break;
1176 
1177         default:
1178 
1179             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "FPDT");
1180             return (AE_ERROR);
1181             break;
1182         }
1183 
1184         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1185         if (ACPI_FAILURE (Status))
1186         {
1187             return (Status);
1188         }
1189 
1190         ParentTable = DtPeekSubtable ();
1191         DtInsertSubtable (ParentTable, Subtable);
1192         DtPopSubtable ();
1193     }
1194 
1195     return (AE_OK);
1196 }
1197 
1198 
1199 /******************************************************************************
1200  *
1201  * FUNCTION:    DtCompileHest
1202  *
1203  * PARAMETERS:  List                - Current field list pointer
1204  *
1205  * RETURN:      Status
1206  *
1207  * DESCRIPTION: Compile HEST.
1208  *
1209  *****************************************************************************/
1210 
1211 ACPI_STATUS
1212 DtCompileHest (
1213     void                    **List)
1214 {
1215     ACPI_STATUS             Status;
1216     DT_SUBTABLE             *Subtable;
1217     DT_SUBTABLE             *ParentTable;
1218     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1219     DT_FIELD                *SubtableStart;
1220     ACPI_DMTABLE_INFO       *InfoTable;
1221     UINT16                  Type;
1222     UINT32                  BankCount;
1223 
1224 
1225     Status = DtCompileTable (PFieldList, AcpiDmTableInfoHest,
1226         &Subtable);
1227     if (ACPI_FAILURE (Status))
1228     {
1229         return (Status);
1230     }
1231 
1232     ParentTable = DtPeekSubtable ();
1233     DtInsertSubtable (ParentTable, Subtable);
1234 
1235     while (*PFieldList)
1236     {
1237         /* Get subtable type */
1238 
1239         SubtableStart = *PFieldList;
1240         DtCompileInteger ((UINT8 *) &Type, *PFieldList, 2, 0);
1241 
1242         switch (Type)
1243         {
1244         case ACPI_HEST_TYPE_IA32_CHECK:
1245 
1246             InfoTable = AcpiDmTableInfoHest0;
1247             break;
1248 
1249         case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
1250 
1251             InfoTable = AcpiDmTableInfoHest1;
1252             break;
1253 
1254         case ACPI_HEST_TYPE_IA32_NMI:
1255 
1256             InfoTable = AcpiDmTableInfoHest2;
1257             break;
1258 
1259         case ACPI_HEST_TYPE_AER_ROOT_PORT:
1260 
1261             InfoTable = AcpiDmTableInfoHest6;
1262             break;
1263 
1264         case ACPI_HEST_TYPE_AER_ENDPOINT:
1265 
1266             InfoTable = AcpiDmTableInfoHest7;
1267             break;
1268 
1269         case ACPI_HEST_TYPE_AER_BRIDGE:
1270 
1271             InfoTable = AcpiDmTableInfoHest8;
1272             break;
1273 
1274         case ACPI_HEST_TYPE_GENERIC_ERROR:
1275 
1276             InfoTable = AcpiDmTableInfoHest9;
1277             break;
1278 
1279         case ACPI_HEST_TYPE_GENERIC_ERROR_V2:
1280 
1281             InfoTable = AcpiDmTableInfoHest10;
1282             break;
1283 
1284         case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
1285 
1286             InfoTable = AcpiDmTableInfoHest11;
1287             break;
1288 
1289         default:
1290 
1291             /* Cannot continue on unknown type */
1292 
1293             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HEST");
1294             return (AE_ERROR);
1295         }
1296 
1297         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1298         if (ACPI_FAILURE (Status))
1299         {
1300             return (Status);
1301         }
1302 
1303         DtInsertSubtable (ParentTable, Subtable);
1304 
1305         /*
1306          * Additional subtable data - IA32 Error Bank(s)
1307          */
1308         BankCount = 0;
1309         switch (Type)
1310         {
1311         case ACPI_HEST_TYPE_IA32_CHECK:
1312 
1313             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK,
1314                 Subtable->Buffer))->NumHardwareBanks;
1315             break;
1316 
1317         case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
1318 
1319             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED,
1320                 Subtable->Buffer))->NumHardwareBanks;
1321             break;
1322 
1323         case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
1324 
1325             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_DEFERRED_CHECK,
1326                 Subtable->Buffer))->NumHardwareBanks;
1327             break;
1328 
1329         default:
1330 
1331             break;
1332         }
1333 
1334         while (BankCount)
1335         {
1336             Status = DtCompileTable (PFieldList, AcpiDmTableInfoHestBank,
1337                 &Subtable);
1338             if (ACPI_FAILURE (Status))
1339             {
1340                 return (Status);
1341             }
1342 
1343             DtInsertSubtable (ParentTable, Subtable);
1344             BankCount--;
1345         }
1346     }
1347 
1348     return (AE_OK);
1349 }
1350 
1351 
1352 /******************************************************************************
1353  *
1354  * FUNCTION:    DtCompileHmat
1355  *
1356  * PARAMETERS:  List                - Current field list pointer
1357  *
1358  * RETURN:      Status
1359  *
1360  * DESCRIPTION: Compile HMAT.
1361  *
1362  *****************************************************************************/
1363 
1364 ACPI_STATUS
1365 DtCompileHmat (
1366     void                    **List)
1367 {
1368     ACPI_STATUS             Status;
1369     DT_SUBTABLE             *Subtable;
1370     DT_SUBTABLE             *ParentTable;
1371     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1372     DT_FIELD                *SubtableStart;
1373     DT_FIELD                *EntryStart;
1374     ACPI_HMAT_STRUCTURE     *HmatStruct;
1375     ACPI_HMAT_LOCALITY      *HmatLocality;
1376     ACPI_HMAT_CACHE         *HmatCache;
1377     ACPI_DMTABLE_INFO       *InfoTable;
1378     UINT32                  IntPDNumber;
1379     UINT32                  TgtPDNumber;
1380     UINT64                  EntryNumber;
1381     UINT16                  SMBIOSHandleNumber;
1382 
1383 
1384     ParentTable = DtPeekSubtable ();
1385 
1386     Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmat,
1387         &Subtable);
1388     if (ACPI_FAILURE (Status))
1389     {
1390         return (Status);
1391     }
1392     DtInsertSubtable (ParentTable, Subtable);
1393 
1394     while (*PFieldList)
1395     {
1396         /* Compile HMAT structure header */
1397 
1398         SubtableStart = *PFieldList;
1399         Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmatHdr,
1400             &Subtable);
1401         if (ACPI_FAILURE (Status))
1402         {
1403             return (Status);
1404         }
1405         DtInsertSubtable (ParentTable, Subtable);
1406 
1407         HmatStruct = ACPI_CAST_PTR (ACPI_HMAT_STRUCTURE, Subtable->Buffer);
1408         HmatStruct->Length = Subtable->Length;
1409 
1410         /* Compile HMAT structure body */
1411 
1412         switch (HmatStruct->Type)
1413         {
1414         case ACPI_HMAT_TYPE_ADDRESS_RANGE:
1415 
1416             InfoTable = AcpiDmTableInfoHmat0;
1417             break;
1418 
1419         case ACPI_HMAT_TYPE_LOCALITY:
1420 
1421             InfoTable = AcpiDmTableInfoHmat1;
1422             break;
1423 
1424         case ACPI_HMAT_TYPE_CACHE:
1425 
1426             InfoTable = AcpiDmTableInfoHmat2;
1427             break;
1428 
1429         default:
1430 
1431             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HMAT");
1432             return (AE_ERROR);
1433         }
1434 
1435         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1436         if (ACPI_FAILURE (Status))
1437         {
1438             return (Status);
1439         }
1440         DtInsertSubtable (ParentTable, Subtable);
1441         HmatStruct->Length += Subtable->Length;
1442 
1443         /* Compile HMAT structure additionals */
1444 
1445         switch (HmatStruct->Type)
1446         {
1447         case ACPI_HMAT_TYPE_LOCALITY:
1448 
1449             HmatLocality = ACPI_SUB_PTR (ACPI_HMAT_LOCALITY,
1450                 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
1451 
1452             /* Compile initiator proximity domain list */
1453 
1454             IntPDNumber = 0;
1455             while (*PFieldList)
1456             {
1457                 Status = DtCompileTable (PFieldList,
1458                     AcpiDmTableInfoHmat1a, &Subtable);
1459                 if (ACPI_FAILURE (Status))
1460                 {
1461                     return (Status);
1462                 }
1463                 if (!Subtable)
1464                 {
1465                     break;
1466                 }
1467                 DtInsertSubtable (ParentTable, Subtable);
1468                 HmatStruct->Length += Subtable->Length;
1469                 IntPDNumber++;
1470             }
1471             HmatLocality->NumberOfInitiatorPDs = IntPDNumber;
1472 
1473             /* Compile target proximity domain list */
1474 
1475             TgtPDNumber = 0;
1476             while (*PFieldList)
1477             {
1478                 Status = DtCompileTable (PFieldList,
1479                     AcpiDmTableInfoHmat1b, &Subtable);
1480                 if (ACPI_FAILURE (Status))
1481                 {
1482                     return (Status);
1483                 }
1484                 if (!Subtable)
1485                 {
1486                     break;
1487                 }
1488                 DtInsertSubtable (ParentTable, Subtable);
1489                 HmatStruct->Length += Subtable->Length;
1490                 TgtPDNumber++;
1491             }
1492             HmatLocality->NumberOfTargetPDs = TgtPDNumber;
1493 
1494             /* Save start of the entries for reporting errors */
1495 
1496             EntryStart = *PFieldList;
1497 
1498             /* Compile latency/bandwidth entries */
1499 
1500             EntryNumber = 0;
1501             while (*PFieldList)
1502             {
1503                 Status = DtCompileTable (PFieldList,
1504                     AcpiDmTableInfoHmat1c, &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                 EntryNumber++;
1516             }
1517 
1518             /* Validate number of entries */
1519 
1520             if (EntryNumber !=
1521                 ((UINT64)IntPDNumber * (UINT64)TgtPDNumber))
1522             {
1523                 DtFatal (ASL_MSG_INVALID_EXPRESSION, EntryStart, "HMAT");
1524                 return (AE_ERROR);
1525             }
1526             break;
1527 
1528         case ACPI_HMAT_TYPE_CACHE:
1529 
1530             /* Compile SMBIOS handles */
1531 
1532             HmatCache = ACPI_SUB_PTR (ACPI_HMAT_CACHE,
1533                 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
1534             SMBIOSHandleNumber = 0;
1535             while (*PFieldList)
1536             {
1537                 Status = DtCompileTable (PFieldList,
1538                     AcpiDmTableInfoHmat2a, &Subtable);
1539                 if (ACPI_FAILURE (Status))
1540                 {
1541                     return (Status);
1542                 }
1543                 if (!Subtable)
1544                 {
1545                     break;
1546                 }
1547                 DtInsertSubtable (ParentTable, Subtable);
1548                 HmatStruct->Length += Subtable->Length;
1549                 SMBIOSHandleNumber++;
1550             }
1551             HmatCache->NumberOfSMBIOSHandles = SMBIOSHandleNumber;
1552             break;
1553 
1554         default:
1555 
1556             break;
1557         }
1558     }
1559 
1560     return (AE_OK);
1561 }
1562 
1563 
1564 /******************************************************************************
1565  *
1566  * FUNCTION:    DtCompileIort
1567  *
1568  * PARAMETERS:  List                - Current field list pointer
1569  *
1570  * RETURN:      Status
1571  *
1572  * DESCRIPTION: Compile IORT.
1573  *
1574  *****************************************************************************/
1575 
1576 ACPI_STATUS
1577 DtCompileIort (
1578     void                    **List)
1579 {
1580     ACPI_STATUS             Status;
1581     DT_SUBTABLE             *Subtable;
1582     DT_SUBTABLE             *ParentTable;
1583     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1584     DT_FIELD                *SubtableStart;
1585     ACPI_TABLE_IORT         *Iort;
1586     ACPI_IORT_NODE          *IortNode;
1587     ACPI_IORT_ITS_GROUP     *IortItsGroup;
1588     ACPI_IORT_SMMU          *IortSmmu;
1589     UINT32                  NodeNumber;
1590     UINT32                  NodeLength;
1591     UINT32                  IdMappingNumber;
1592     UINT32                  ItsNumber;
1593     UINT32                  ContextIrptNumber;
1594     UINT32                  PmuIrptNumber;
1595     UINT32                  PaddingLength;
1596 
1597 
1598     ParentTable = DtPeekSubtable ();
1599 
1600     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort,
1601         &Subtable);
1602     if (ACPI_FAILURE (Status))
1603     {
1604         return (Status);
1605     }
1606     DtInsertSubtable (ParentTable, Subtable);
1607 
1608     /*
1609      * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
1610      * should be taken to avoid accessing ACPI_TABLE_HEADER fields.
1611      */
1612     Iort = ACPI_SUB_PTR (ACPI_TABLE_IORT,
1613         Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
1614 
1615     /*
1616      * OptionalPadding - Variable-length data
1617      * (Optional, size = OffsetToNodes - sizeof (ACPI_TABLE_IORT))
1618      * Optionally allows the generic data types to be used for filling
1619      * this field.
1620      */
1621     Iort->NodeOffset = sizeof (ACPI_TABLE_IORT);
1622     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortPad,
1623         &Subtable);
1624     if (ACPI_FAILURE (Status))
1625     {
1626         return (Status);
1627     }
1628     if (Subtable)
1629     {
1630         DtInsertSubtable (ParentTable, Subtable);
1631         Iort->NodeOffset += Subtable->Length;
1632     }
1633     else
1634     {
1635         Status = DtCompileGeneric (ACPI_CAST_PTR (void *, PFieldList),
1636             AcpiDmTableInfoIortHdr[0].Name, &PaddingLength);
1637         if (ACPI_FAILURE (Status))
1638         {
1639             return (Status);
1640         }
1641         Iort->NodeOffset += PaddingLength;
1642     }
1643 
1644     NodeNumber = 0;
1645     while (*PFieldList)
1646     {
1647         SubtableStart = *PFieldList;
1648         Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr,
1649             &Subtable);
1650         if (ACPI_FAILURE (Status))
1651         {
1652             return (Status);
1653         }
1654 
1655         DtInsertSubtable (ParentTable, Subtable);
1656         IortNode = ACPI_CAST_PTR (ACPI_IORT_NODE, Subtable->Buffer);
1657         NodeLength = ACPI_OFFSET (ACPI_IORT_NODE, NodeData);
1658 
1659         DtPushSubtable (Subtable);
1660         ParentTable = DtPeekSubtable ();
1661 
1662         switch (IortNode->Type)
1663         {
1664         case ACPI_IORT_NODE_ITS_GROUP:
1665 
1666             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0,
1667                 &Subtable);
1668             if (ACPI_FAILURE (Status))
1669             {
1670                 return (Status);
1671             }
1672 
1673             DtInsertSubtable (ParentTable, Subtable);
1674             IortItsGroup = ACPI_CAST_PTR (ACPI_IORT_ITS_GROUP, Subtable->Buffer);
1675             NodeLength += Subtable->Length;
1676 
1677             ItsNumber = 0;
1678             while (*PFieldList)
1679             {
1680                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0a,
1681                     &Subtable);
1682                 if (ACPI_FAILURE (Status))
1683                 {
1684                     return (Status);
1685                 }
1686                 if (!Subtable)
1687                 {
1688                     break;
1689                 }
1690 
1691                 DtInsertSubtable (ParentTable, Subtable);
1692                 NodeLength += Subtable->Length;
1693                 ItsNumber++;
1694             }
1695 
1696             IortItsGroup->ItsCount = ItsNumber;
1697             break;
1698 
1699         case ACPI_IORT_NODE_NAMED_COMPONENT:
1700 
1701             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1,
1702                 &Subtable);
1703             if (ACPI_FAILURE (Status))
1704             {
1705                 return (Status);
1706             }
1707 
1708             DtInsertSubtable (ParentTable, Subtable);
1709             NodeLength += Subtable->Length;
1710 
1711             /*
1712              * Padding - Variable-length data
1713              * Optionally allows the offset of the ID mappings to be used
1714              * for filling this field.
1715              */
1716             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1a,
1717                 &Subtable);
1718             if (ACPI_FAILURE (Status))
1719             {
1720                 return (Status);
1721             }
1722 
1723             if (Subtable)
1724             {
1725                 DtInsertSubtable (ParentTable, Subtable);
1726                 NodeLength += Subtable->Length;
1727             }
1728             else
1729             {
1730                 if (NodeLength > IortNode->MappingOffset)
1731                 {
1732                     return (AE_BAD_DATA);
1733                 }
1734 
1735                 if (NodeLength < IortNode->MappingOffset)
1736                 {
1737                     Status = DtCompilePadding (
1738                         IortNode->MappingOffset - NodeLength,
1739                         &Subtable);
1740                     if (ACPI_FAILURE (Status))
1741                     {
1742                         return (Status);
1743                     }
1744 
1745                     DtInsertSubtable (ParentTable, Subtable);
1746                     NodeLength = IortNode->MappingOffset;
1747                 }
1748             }
1749             break;
1750 
1751         case ACPI_IORT_NODE_PCI_ROOT_COMPLEX:
1752 
1753             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort2,
1754                 &Subtable);
1755             if (ACPI_FAILURE (Status))
1756             {
1757                 return (Status);
1758             }
1759 
1760             DtInsertSubtable (ParentTable, Subtable);
1761             NodeLength += Subtable->Length;
1762             break;
1763 
1764         case ACPI_IORT_NODE_SMMU:
1765 
1766             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3,
1767                 &Subtable);
1768             if (ACPI_FAILURE (Status))
1769             {
1770                 return (Status);
1771             }
1772 
1773             DtInsertSubtable (ParentTable, Subtable);
1774             IortSmmu = ACPI_CAST_PTR (ACPI_IORT_SMMU, Subtable->Buffer);
1775             NodeLength += Subtable->Length;
1776 
1777             /* Compile global interrupt array */
1778 
1779             IortSmmu->GlobalInterruptOffset = NodeLength;
1780             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3a,
1781                 &Subtable);
1782             if (ACPI_FAILURE (Status))
1783             {
1784                 return (Status);
1785             }
1786 
1787             DtInsertSubtable (ParentTable, Subtable);
1788             NodeLength += Subtable->Length;
1789 
1790             /* Compile context interrupt array */
1791 
1792             ContextIrptNumber = 0;
1793             IortSmmu->ContextInterruptOffset = NodeLength;
1794             while (*PFieldList)
1795             {
1796                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3b,
1797                     &Subtable);
1798                 if (ACPI_FAILURE (Status))
1799                 {
1800                     return (Status);
1801                 }
1802 
1803                 if (!Subtable)
1804                 {
1805                     break;
1806                 }
1807 
1808                 DtInsertSubtable (ParentTable, Subtable);
1809                 NodeLength += Subtable->Length;
1810                 ContextIrptNumber++;
1811             }
1812 
1813             IortSmmu->ContextInterruptCount = ContextIrptNumber;
1814 
1815             /* Compile PMU interrupt array */
1816 
1817             PmuIrptNumber = 0;
1818             IortSmmu->PmuInterruptOffset = NodeLength;
1819             while (*PFieldList)
1820             {
1821                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3c,
1822                     &Subtable);
1823                 if (ACPI_FAILURE (Status))
1824                 {
1825                     return (Status);
1826                 }
1827 
1828                 if (!Subtable)
1829                 {
1830                     break;
1831                 }
1832 
1833                 DtInsertSubtable (ParentTable, Subtable);
1834                 NodeLength += Subtable->Length;
1835                 PmuIrptNumber++;
1836             }
1837 
1838             IortSmmu->PmuInterruptCount = PmuIrptNumber;
1839             break;
1840 
1841         case ACPI_IORT_NODE_SMMU_V3:
1842 
1843             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort4,
1844                 &Subtable);
1845             if (ACPI_FAILURE (Status))
1846             {
1847                 return (Status);
1848             }
1849 
1850             DtInsertSubtable (ParentTable, Subtable);
1851             NodeLength += Subtable->Length;
1852             break;
1853 
1854         case ACPI_IORT_NODE_PMCG:
1855 
1856             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort5,
1857                 &Subtable);
1858             if (ACPI_FAILURE (Status))
1859             {
1860                 return (Status);
1861             }
1862 
1863             DtInsertSubtable (ParentTable, Subtable);
1864             NodeLength += Subtable->Length;
1865             break;
1866 
1867         default:
1868 
1869             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IORT");
1870             return (AE_ERROR);
1871         }
1872 
1873         /* Compile Array of ID mappings */
1874 
1875         IortNode->MappingOffset = NodeLength;
1876         IdMappingNumber = 0;
1877         while (*PFieldList)
1878         {
1879             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortMap,
1880                 &Subtable);
1881             if (ACPI_FAILURE (Status))
1882             {
1883                 return (Status);
1884             }
1885 
1886             if (!Subtable)
1887             {
1888                 break;
1889             }
1890 
1891             DtInsertSubtable (ParentTable, Subtable);
1892             NodeLength += sizeof (ACPI_IORT_ID_MAPPING);
1893             IdMappingNumber++;
1894         }
1895 
1896         IortNode->MappingCount = IdMappingNumber;
1897         if (!IdMappingNumber)
1898         {
1899             IortNode->MappingOffset = 0;
1900         }
1901 
1902         /*
1903          * Node length can be determined by DT_LENGTH option
1904          * IortNode->Length = NodeLength;
1905          */
1906         DtPopSubtable ();
1907         ParentTable = DtPeekSubtable ();
1908         NodeNumber++;
1909     }
1910 
1911     Iort->NodeCount = NodeNumber;
1912     return (AE_OK);
1913 }
1914 
1915 
1916 /******************************************************************************
1917  *
1918  * FUNCTION:    DtCompileIvrs
1919  *
1920  * PARAMETERS:  List                - Current field list pointer
1921  *
1922  * RETURN:      Status
1923  *
1924  * DESCRIPTION: Compile IVRS.
1925  *
1926  *****************************************************************************/
1927 
1928 ACPI_STATUS
1929 DtCompileIvrs (
1930     void                    **List)
1931 {
1932     ACPI_STATUS             Status;
1933     DT_SUBTABLE             *Subtable;
1934     DT_SUBTABLE             *ParentTable;
1935     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1936     DT_FIELD                *SubtableStart;
1937     ACPI_DMTABLE_INFO       *InfoTable;
1938     ACPI_IVRS_HEADER        *IvrsHeader;
1939     UINT8                   EntryType;
1940 
1941 
1942     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrs,
1943         &Subtable);
1944     if (ACPI_FAILURE (Status))
1945     {
1946         return (Status);
1947     }
1948 
1949     ParentTable = DtPeekSubtable ();
1950     DtInsertSubtable (ParentTable, Subtable);
1951 
1952     while (*PFieldList)
1953     {
1954         SubtableStart = *PFieldList;
1955         Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHdr,
1956             &Subtable);
1957         if (ACPI_FAILURE (Status))
1958         {
1959             return (Status);
1960         }
1961 
1962         ParentTable = DtPeekSubtable ();
1963         DtInsertSubtable (ParentTable, Subtable);
1964         DtPushSubtable (Subtable);
1965 
1966         IvrsHeader = ACPI_CAST_PTR (ACPI_IVRS_HEADER, Subtable->Buffer);
1967 
1968         switch (IvrsHeader->Type)
1969         {
1970         case ACPI_IVRS_TYPE_HARDWARE:
1971 
1972             InfoTable = AcpiDmTableInfoIvrs0;
1973             break;
1974 
1975         case ACPI_IVRS_TYPE_MEMORY1:
1976         case ACPI_IVRS_TYPE_MEMORY2:
1977         case ACPI_IVRS_TYPE_MEMORY3:
1978 
1979             InfoTable = AcpiDmTableInfoIvrs1;
1980             break;
1981 
1982         default:
1983 
1984             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IVRS");
1985             return (AE_ERROR);
1986         }
1987 
1988         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1989         if (ACPI_FAILURE (Status))
1990         {
1991             return (Status);
1992         }
1993 
1994         ParentTable = DtPeekSubtable ();
1995         DtInsertSubtable (ParentTable, Subtable);
1996 
1997         if (IvrsHeader->Type == ACPI_IVRS_TYPE_HARDWARE)
1998         {
1999             while (*PFieldList &&
2000                 !strcmp ((*PFieldList)->Name, "Entry Type"))
2001             {
2002                 SubtableStart = *PFieldList;
2003                 DtCompileInteger (&EntryType, *PFieldList, 1, 0);
2004 
2005                 switch (EntryType)
2006                 {
2007                 /* 4-byte device entries */
2008 
2009                 case ACPI_IVRS_TYPE_PAD4:
2010                 case ACPI_IVRS_TYPE_ALL:
2011                 case ACPI_IVRS_TYPE_SELECT:
2012                 case ACPI_IVRS_TYPE_START:
2013                 case ACPI_IVRS_TYPE_END:
2014 
2015                     InfoTable = AcpiDmTableInfoIvrs4;
2016                     break;
2017 
2018                 /* 8-byte entries, type A */
2019 
2020                 case ACPI_IVRS_TYPE_ALIAS_SELECT:
2021                 case ACPI_IVRS_TYPE_ALIAS_START:
2022 
2023                     InfoTable = AcpiDmTableInfoIvrs8a;
2024                     break;
2025 
2026                 /* 8-byte entries, type B */
2027 
2028                 case ACPI_IVRS_TYPE_PAD8:
2029                 case ACPI_IVRS_TYPE_EXT_SELECT:
2030                 case ACPI_IVRS_TYPE_EXT_START:
2031 
2032                     InfoTable = AcpiDmTableInfoIvrs8b;
2033                     break;
2034 
2035                 /* 8-byte entries, type C */
2036 
2037                 case ACPI_IVRS_TYPE_SPECIAL:
2038 
2039                     InfoTable = AcpiDmTableInfoIvrs8c;
2040                     break;
2041 
2042                 default:
2043 
2044                     DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart,
2045                         "IVRS Device Entry");
2046                     return (AE_ERROR);
2047                 }
2048 
2049                 Status = DtCompileTable (PFieldList, InfoTable,
2050                     &Subtable);
2051                 if (ACPI_FAILURE (Status))
2052                 {
2053                     return (Status);
2054                 }
2055 
2056                 DtInsertSubtable (ParentTable, Subtable);
2057             }
2058         }
2059 
2060         DtPopSubtable ();
2061     }
2062 
2063     return (AE_OK);
2064 }
2065