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