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