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