xref: /freebsd/sys/contrib/dev/acpica/compiler/dttable1.c (revision 7697e6c4df7188ee3a2aa66f73c572c27479bdf2)
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 - 2026, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************
115  *
116  * Alternatively, you may choose to be licensed under the terms of the
117  * following license:
118  *
119  * Redistribution and use in source and binary forms, with or without
120  * modification, are permitted provided that the following conditions
121  * are met:
122  * 1. Redistributions of source code must retain the above copyright
123  *    notice, this list of conditions, and the following disclaimer,
124  *    without modification.
125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126  *    substantially similar to the "NO WARRANTY" disclaimer below
127  *    ("Disclaimer") and any redistribution must be conditioned upon
128  *    including a substantially similar Disclaimer requirement for further
129  *    binary redistribution.
130  * 3. Neither the names of the above-listed copyright holders nor the names
131  *    of any contributors may be used to endorse or promote products derived
132  *    from this software without specific prior written permission.
133  *
134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145  *
146  * Alternatively, you may choose to be licensed under the terms of the
147  * GNU General Public License ("GPL") version 2 as published by the Free
148  * Software Foundation.
149  *
150  *****************************************************************************/
151 
152 /* Compile all complex data tables, signatures starting with A-I */
153 
154 #include <contrib/dev/acpica/compiler/aslcompiler.h>
155 
156 #define _COMPONENT          DT_COMPILER
157         ACPI_MODULE_NAME    ("dttable1")
158 
159 
160 static ACPI_DMTABLE_INFO           TableInfoAsfAddress[] =
161 {
162     {ACPI_DMT_BUFFER,   0,               "Addresses", 0},
163     {ACPI_DMT_EXIT,     0,               NULL, 0}
164 };
165 
166 static ACPI_DMTABLE_INFO           TableInfoDmarPciPath[] =
167 {
168     {ACPI_DMT_PCI_PATH, 0,               "PCI Path", 0},
169     {ACPI_DMT_EXIT,     0,               NULL, 0}
170 };
171 
172 
173 /******************************************************************************
174  *
175  * FUNCTION:    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
DtCompileAest(void ** List)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     ACPI_AEST_NODE_INTERFACE_HEADER *AestNodeHeader;
210     UINT8                   Revision;
211     ACPI_TABLE_HEADER       *Header;
212 
213     ParentTable = DtPeekSubtable ();
214 
215     Header = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer);
216     Revision = Header->Revision;
217 
218     while (*PFieldList)
219     {
220         /* Compile the common error node header */
221 
222         Status = DtCompileTable (PFieldList, AcpiDmTableInfoAestHdr,
223             &Subtable);
224         if (ACPI_FAILURE (Status))
225         {
226             return (Status);
227         }
228 
229         ParentTable = DtPeekSubtable ();
230         DtInsertSubtable (ParentTable, Subtable);
231 
232         /* Everything past the error node header will be a subtable */
233 
234         DtPushSubtable (Subtable);
235 
236         /*
237          * Compile the node-specific structure (Based on the error
238          * node header Type field)
239          */
240         ErrorNodeHeader = ACPI_CAST_PTR (ACPI_AEST_HEADER, Subtable->Buffer);
241 
242         /* Point past the common error node header */
243 
244         Offset = sizeof (ACPI_AEST_HEADER);
245         ErrorNodeHeader->NodeSpecificOffset = Offset;
246 
247         /* Decode the error node type */
248 
249         switch (ErrorNodeHeader->Type)
250         {
251         case ACPI_AEST_PROCESSOR_ERROR_NODE:
252 
253             InfoTable = AcpiDmTableInfoAestProcError;
254             break;
255 
256         case ACPI_AEST_MEMORY_ERROR_NODE:
257 
258             InfoTable = AcpiDmTableInfoAestMemError;
259             break;
260 
261         case ACPI_AEST_SMMU_ERROR_NODE:
262 
263             InfoTable = AcpiDmTableInfoAestSmmuError;
264             break;
265 
266         case ACPI_AEST_VENDOR_ERROR_NODE:
267             switch (Revision)
268             {
269             case 1:
270                 InfoTable = AcpiDmTableInfoAestVendorError;
271                 break;
272 
273             case 2:
274                 InfoTable = AcpiDmTableInfoAestVendorV2Error;
275                 break;
276 
277             default:
278                 AcpiOsPrintf ("Unknown AEST Vendor Error Revision: %X\n",
279                     Revision);
280                 return (AE_ERROR);
281             }
282             break;
283 
284         case ACPI_AEST_GIC_ERROR_NODE:
285 
286             InfoTable = AcpiDmTableInfoAestGicError;
287             break;
288 
289         case ACPI_AEST_PCIE_ERROR_NODE:
290 
291             InfoTable = AcpiDmTableInfoAestPCIeError;
292             break;
293 
294         case ACPI_AEST_PROXY_ERROR_NODE:
295 
296             InfoTable = AcpiDmTableInfoAestProxyError;
297             break;
298 
299         /* Error case below */
300         default:
301             AcpiOsPrintf ("Unknown AEST Subtable Type: %X\n",
302                 ErrorNodeHeader->Type);
303             return (AE_ERROR);
304         }
305 
306         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
307         if (ACPI_FAILURE (Status))
308         {
309             return (Status);
310         }
311 
312         /* Point past the node-specific structure */
313 
314         Offset += Subtable->Length;
315         ErrorNodeHeader->NodeInterfaceOffset = Offset;
316 
317         ParentTable = DtPeekSubtable ();
318         DtInsertSubtable (ParentTable, Subtable);
319 
320         /* Compile any additional node-specific substructures */
321 
322         if (ErrorNodeHeader->Type == ACPI_AEST_PROCESSOR_ERROR_NODE)
323         {
324             /*
325              * Special handling for PROCESSOR_ERROR_NODE subtables
326              * (to handle the Resource Substructure via the ResourceType
327              * field).
328              */
329             AestProcessor = ACPI_CAST_PTR (ACPI_AEST_PROCESSOR,
330                 Subtable->Buffer);
331 
332             switch (AestProcessor->ResourceType)
333             {
334             case ACPI_AEST_CACHE_RESOURCE:
335 
336                 InfoTable = AcpiDmTableInfoAestCacheRsrc;
337                 break;
338 
339             case ACPI_AEST_TLB_RESOURCE:
340 
341                 InfoTable = AcpiDmTableInfoAestTlbRsrc;
342                 break;
343 
344             case ACPI_AEST_GENERIC_RESOURCE:
345 
346                 InfoTable = AcpiDmTableInfoAestGenRsrc;
347                 AcpiOsPrintf ("Generic Resource Type (%X) is not supported at this time\n",
348                     AestProcessor->ResourceType);
349                 return (AE_ERROR);
350 
351             /* Error case below */
352             default:
353                 AcpiOsPrintf ("Unknown AEST Processor Resource Type: %X\n",
354                     AestProcessor->ResourceType);
355                 return (AE_ERROR);
356             }
357 
358             Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
359             if (ACPI_FAILURE (Status))
360             {
361                 return (Status);
362             }
363 
364             /* Point past the resource substructure subtable */
365 
366             Offset += Subtable->Length;
367             ErrorNodeHeader->NodeInterfaceOffset = Offset;
368 
369             ParentTable = DtPeekSubtable ();
370             DtInsertSubtable (ParentTable, Subtable);
371         }
372 
373         /* Compile the (required) node interface structure */
374         if (Revision == 1)
375         {
376             InfoTable = AcpiDmTableInfoAestXface;
377         }
378         else if (Revision == 2)
379         {
380             Status = DtCompileTable (PFieldList, AcpiDmTableInfoAestXfaceHeader,
381                 &Subtable);
382             if (ACPI_FAILURE (Status))
383             {
384                 return (Status);
385             }
386 
387             ParentTable = DtPeekSubtable ();
388             DtInsertSubtable (ParentTable, Subtable);
389 
390             Offset += Subtable->Length;
391 
392             AestNodeHeader = ACPI_CAST_PTR (ACPI_AEST_NODE_INTERFACE_HEADER,
393                     Subtable->Buffer);
394 
395             switch (AestNodeHeader->GroupFormat)
396             {
397             case ACPI_AEST_NODE_GROUP_FORMAT_4K:
398 
399                 InfoTable = AcpiDmTableInfoAestXface4k;
400                 break;
401 
402             case ACPI_AEST_NODE_GROUP_FORMAT_16K:
403 
404                 InfoTable = AcpiDmTableInfoAestXface16k;
405                 break;
406 
407             case ACPI_AEST_NODE_GROUP_FORMAT_64K:
408 
409                 InfoTable = AcpiDmTableInfoAestXface64k;
410                 break;
411 
412             /* Error case below */
413             default:
414                 AcpiOsPrintf ("Unknown AEST Interface Group Format: %X\n",
415                     AestNodeHeader->GroupFormat);
416                 return (AE_ERROR);
417             }
418         }
419         else
420         {
421            AcpiOsPrintf ("Unknown AEST Revision: %X\n", Revision);
422         }
423 
424         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
425         if (ACPI_FAILURE (Status))
426         {
427             return (Status);
428         }
429 
430         ErrorNodeHeader->NodeInterruptOffset = 0;
431         ParentTable = DtPeekSubtable ();
432         DtInsertSubtable (ParentTable, Subtable);
433 
434         /* Compile each of the node interrupt structures */
435 
436         if (ErrorNodeHeader->NodeInterruptCount)
437         {
438             /* Point to the first interrupt structure */
439 
440             Offset += Subtable->Length;
441             ErrorNodeHeader->NodeInterruptOffset = Offset;
442         }
443 
444         /* Compile each of the interrupt structures */
445 
446         for (i = 0; i < ErrorNodeHeader->NodeInterruptCount; i++)
447         {
448             switch (Revision) {
449             case 1:
450 
451                 InfoTable = AcpiDmTableInfoAestXrupt;
452                 break;
453 
454             case 2:
455 
456                 InfoTable = AcpiDmTableInfoAestXruptV2;
457                 break;
458 
459             default:
460                 AcpiOsPrintf ("Unknown AEST Revision: %X\n", Revision);
461                 return (AE_ERROR);
462             }
463             Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
464             if (ACPI_FAILURE (Status))
465             {
466                 return (Status);
467             }
468 
469             ParentTable = DtPeekSubtable ();
470             DtInsertSubtable (ParentTable, Subtable);
471         }
472 
473         /* Prepare for the next AEST Error node */
474 
475         DtPopSubtable ();
476     }
477 
478     return (AE_OK);
479 }
480 
481 
482 /******************************************************************************
483  *
484  * FUNCTION:    DtCompileApmt
485  *
486  * PARAMETERS:  List                - Current field list pointer
487  *
488  * RETURN:      Status
489  *
490  * DESCRIPTION: Compile APMT.
491  *
492  *****************************************************************************/
493 
494 ACPI_STATUS
DtCompileApmt(void ** List)495 DtCompileApmt (
496     void                    **List)
497 {
498     ACPI_STATUS             Status;
499     ACPI_TABLE_HEADER       *Header;
500     ACPI_APMT_NODE          *ApmtNode;
501     ACPI_APMT_NODE          *PeerApmtNode;
502     DT_SUBTABLE             *Subtable;
503     DT_SUBTABLE             *PeerSubtable;
504     DT_SUBTABLE             *ParentTable;
505     DT_FIELD                **PFieldList = (DT_FIELD**)List;
506     DT_FIELD                *SubtableStart;
507     UINT32                  CurLength;
508     char                    MsgBuffer[64] = "";
509 
510     ParentTable = DtPeekSubtable();
511 
512     Header = ACPI_CAST_PTR(ACPI_TABLE_HEADER, ParentTable->Buffer);
513 
514     CurLength = sizeof(ACPI_TABLE_HEADER);
515 
516     /* Walk the parse tree */
517 
518     while (*PFieldList)
519     {
520         /* APMT Node Subtable */
521 
522         SubtableStart = *PFieldList;
523 
524         Status = DtCompileTable(PFieldList, AcpiDmTableInfoApmtNode, &Subtable);
525 
526         if (ACPI_FAILURE(Status))
527         {
528             return (Status);
529         }
530 
531         ApmtNode = ACPI_CAST_PTR(ACPI_APMT_NODE, Subtable->Buffer);
532 
533         if (ApmtNode->Length != sizeof(ACPI_APMT_NODE))
534         {
535             DtFatal(ASL_MSG_INVALID_LENGTH, SubtableStart, "APMT");
536             return (AE_ERROR);
537         }
538 
539         if (ApmtNode->Type >= ACPI_APMT_NODE_TYPE_COUNT)
540         {
541             snprintf(MsgBuffer, 64, "Node Type : 0x%X", ApmtNode->Type);
542             DtFatal(ASL_MSG_INVALID_TYPE, SubtableStart, MsgBuffer);
543             return (AE_ERROR);
544         }
545 
546         PeerSubtable = DtGetNextSubtable(ParentTable, NULL);
547 
548         /* Validate the node id needs to be unique. */
549         while(PeerSubtable)
550         {
551             PeerApmtNode = ACPI_CAST_PTR(ACPI_APMT_NODE, PeerSubtable->Buffer);
552             if (PeerApmtNode->Id == ApmtNode->Id)
553             {
554                 snprintf(MsgBuffer, 64, "Node Id : 0x%X existed", ApmtNode->Id);
555                 DtFatal(ASL_MSG_DUPLICATE_ITEM, SubtableStart, MsgBuffer);
556                 return (AE_ERROR);
557             }
558 
559             PeerSubtable = DtGetNextSubtable(ParentTable, PeerSubtable);
560         }
561 
562         CurLength += ApmtNode->Length;
563 
564         DtInsertSubtable(ParentTable, Subtable);
565     }
566 
567     if (Header->Length != CurLength)
568     {
569         snprintf(MsgBuffer, 64, " - APMT Length : %u (expected: %u)",
570             Header->Length, CurLength);
571         DtFatal(ASL_MSG_INVALID_LENGTH, NULL, MsgBuffer);
572         return (AE_ERROR);
573     }
574 
575     return (AE_OK);
576 }
577 
578 /******************************************************************************
579  *
580  * FUNCTION:    DtCompileAsf
581  *
582  * PARAMETERS:  List                - Current field list pointer
583  *
584  * RETURN:      Status
585  *
586  * DESCRIPTION: Compile ASF!.
587  *
588  *****************************************************************************/
589 
590 ACPI_STATUS
DtCompileAsf(void ** List)591 DtCompileAsf (
592     void                    **List)
593 {
594     ACPI_ASF_INFO           *AsfTable;
595     DT_SUBTABLE             *Subtable;
596     DT_SUBTABLE             *ParentTable;
597     ACPI_DMTABLE_INFO       *InfoTable;
598     ACPI_DMTABLE_INFO       *DataInfoTable = NULL;
599     UINT32                  DataCount = 0;
600     ACPI_STATUS             Status;
601     UINT32                  i;
602     DT_FIELD                **PFieldList = (DT_FIELD **) List;
603     DT_FIELD                *SubtableStart;
604 
605 
606     while (*PFieldList)
607     {
608         SubtableStart = *PFieldList;
609         Status = DtCompileTable (PFieldList, AcpiDmTableInfoAsfHdr,
610             &Subtable);
611         if (ACPI_FAILURE (Status))
612         {
613             return (Status);
614         }
615 
616         ParentTable = DtPeekSubtable ();
617         DtInsertSubtable (ParentTable, Subtable);
618         DtPushSubtable (Subtable);
619 
620         AsfTable = ACPI_CAST_PTR (ACPI_ASF_INFO, Subtable->Buffer);
621 
622         switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */
623         {
624         case ACPI_ASF_TYPE_INFO:
625 
626             InfoTable = AcpiDmTableInfoAsf0;
627             break;
628 
629         case ACPI_ASF_TYPE_ALERT:
630 
631             InfoTable = AcpiDmTableInfoAsf1;
632             break;
633 
634         case ACPI_ASF_TYPE_CONTROL:
635 
636             InfoTable = AcpiDmTableInfoAsf2;
637             break;
638 
639         case ACPI_ASF_TYPE_BOOT:
640 
641             InfoTable = AcpiDmTableInfoAsf3;
642             break;
643 
644         case ACPI_ASF_TYPE_ADDRESS:
645 
646             InfoTable = AcpiDmTableInfoAsf4;
647             break;
648 
649         default:
650 
651             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!");
652             return (AE_ERROR);
653         }
654 
655         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
656         if (ACPI_FAILURE (Status))
657         {
658             return (Status);
659         }
660 
661         ParentTable = DtPeekSubtable ();
662         DtInsertSubtable (ParentTable, Subtable);
663 
664         switch (AsfTable->Header.Type & 0x7F) /* Mask off top bit */
665         {
666         case ACPI_ASF_TYPE_INFO:
667 
668             DataInfoTable = NULL;
669             break;
670 
671         case ACPI_ASF_TYPE_ALERT:
672 
673             DataInfoTable = AcpiDmTableInfoAsf1a;
674             DataCount = ACPI_CAST_PTR (ACPI_ASF_ALERT,
675                 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
676                     sizeof (ACPI_ASF_HEADER)))->Alerts;
677             break;
678 
679         case ACPI_ASF_TYPE_CONTROL:
680 
681             DataInfoTable = AcpiDmTableInfoAsf2a;
682             DataCount = ACPI_CAST_PTR (ACPI_ASF_REMOTE,
683                 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
684                     sizeof (ACPI_ASF_HEADER)))->Controls;
685             break;
686 
687         case ACPI_ASF_TYPE_BOOT:
688 
689             DataInfoTable = NULL;
690             break;
691 
692         case ACPI_ASF_TYPE_ADDRESS:
693 
694             DataInfoTable = TableInfoAsfAddress;
695             DataCount = ACPI_CAST_PTR (ACPI_ASF_ADDRESS,
696                 ACPI_SUB_PTR (UINT8, Subtable->Buffer,
697                     sizeof (ACPI_ASF_HEADER)))->Devices;
698             break;
699 
700         default:
701 
702             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASF!");
703             return (AE_ERROR);
704         }
705 
706         if (DataInfoTable)
707         {
708             switch (AsfTable->Header.Type & 0x7F)
709             {
710             case ACPI_ASF_TYPE_ADDRESS:
711 
712                 while (DataCount > 0)
713                 {
714                     Status = DtCompileTable (PFieldList, DataInfoTable,
715                         &Subtable);
716                     if (ACPI_FAILURE (Status))
717                     {
718                         return (Status);
719                     }
720 
721                     DtInsertSubtable (ParentTable, Subtable);
722                     DataCount = DataCount - Subtable->Length;
723                 }
724                 break;
725 
726             default:
727 
728                 for (i = 0; i < DataCount; i++)
729                 {
730                     Status = DtCompileTable (PFieldList, DataInfoTable,
731                         &Subtable);
732                     if (ACPI_FAILURE (Status))
733                     {
734                         return (Status);
735                     }
736 
737                     DtInsertSubtable (ParentTable, Subtable);
738                 }
739                 break;
740             }
741         }
742 
743         DtPopSubtable ();
744     }
745 
746     return (AE_OK);
747 }
748 
749 /******************************************************************************
750  *
751  * FUNCTION:    DtCompileAspt
752  *
753  * PARAMETERS:  List                - Current field list pointer
754  *
755  * RETURN:      Status
756  *
757  * DESCRIPTION: Compile ASPT.
758  *
759  *****************************************************************************/
760 
761 ACPI_STATUS
DtCompileAspt(void ** List)762 DtCompileAspt (
763     void                    **List)
764 {
765     ACPI_ASPT_HEADER        *AsptTable;
766     DT_SUBTABLE             *Subtable;
767     DT_SUBTABLE             *ParentTable;
768     ACPI_DMTABLE_INFO       *InfoTable;
769     ACPI_STATUS             Status;
770     DT_FIELD                **PFieldList = (DT_FIELD **) List;
771     DT_FIELD                *SubtableStart;
772 
773     Status = DtCompileTable (PFieldList, AcpiDmTableInfoAspt, &Subtable);
774     if (ACPI_FAILURE (Status))
775     {
776         return (Status);
777     }
778 
779     ParentTable = DtPeekSubtable ();
780     DtInsertSubtable (ParentTable, Subtable);
781 
782     while (*PFieldList)
783     {
784         SubtableStart = *PFieldList;
785         Status = DtCompileTable (PFieldList, AcpiDmTableInfoAsptHdr,
786             &Subtable);
787         if (ACPI_FAILURE (Status))
788         {
789             return (Status);
790         }
791 
792         ParentTable = DtPeekSubtable ();
793         DtInsertSubtable (ParentTable, Subtable);
794         DtPushSubtable (Subtable);
795 
796         AsptTable = ACPI_CAST_PTR (ACPI_ASPT_HEADER, Subtable->Buffer);
797 
798         switch (AsptTable->Type) /* Mask off top bit */
799         {
800         case ACPI_ASPT_TYPE_GLOBAL_REGS:
801 
802             InfoTable = AcpiDmTableInfoAspt0;
803             break;
804 
805         case ACPI_ASPT_TYPE_SEV_MBOX_REGS:
806 
807             InfoTable = AcpiDmTableInfoAspt1;
808             break;
809 
810         case ACPI_ASPT_TYPE_ACPI_MBOX_REGS:
811 
812             InfoTable = AcpiDmTableInfoAspt2;
813             break;
814 
815         default:
816 
817             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ASPT");
818             return (AE_ERROR);
819         }
820 
821         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
822         if (ACPI_FAILURE (Status))
823         {
824             return (Status);
825         }
826         ParentTable = DtPeekSubtable ();
827         DtInsertSubtable (ParentTable, Subtable);
828         DtPopSubtable ();
829     }
830 
831     return (AE_OK);
832 }
833 
834 
835 /******************************************************************************
836  *
837  * FUNCTION:    DtCompileCdat
838  *
839  * PARAMETERS:  List                - Current field list pointer
840  *
841  * RETURN:      Status
842  *
843  * DESCRIPTION: Compile CDAT.
844  *
845  *****************************************************************************/
846 
847 ACPI_STATUS
DtCompileCdat(void ** List)848 DtCompileCdat (
849     void                    **List)
850 {
851     ACPI_STATUS             Status = AE_OK;
852     DT_SUBTABLE             *Subtable;
853     DT_SUBTABLE             *ParentTable;
854     DT_FIELD                **PFieldList = (DT_FIELD **) List;
855     ACPI_CDAT_HEADER        *CdatHeader;
856     ACPI_DMTABLE_INFO       *InfoTable = NULL;
857     DT_FIELD                *SubtableStart;
858 
859 
860     /* Walk the parse tree.
861      *
862      * Note: Main table consists of only the CDAT table header
863      * (This is not the standard ACPI table header, however)--
864      * Followed by some number of subtables.
865      */
866     while (*PFieldList)
867     {
868         SubtableStart = *PFieldList;
869 
870         /* Compile the expected CDAT Subtable header */
871 
872         Status = DtCompileTable (PFieldList, AcpiDmTableInfoCdatHeader,
873             &Subtable);
874         if (ACPI_FAILURE (Status))
875         {
876             return (Status);
877         }
878 
879         ParentTable = DtPeekSubtable ();
880         DtInsertSubtable (ParentTable, Subtable);
881         DtPushSubtable (Subtable);
882 
883         CdatHeader = ACPI_CAST_PTR (ACPI_CDAT_HEADER, Subtable->Buffer);
884 
885         /* Decode the subtable by type */
886 
887         switch (CdatHeader->Type)
888         {
889         case ACPI_CDAT_TYPE_DSMAS:
890             InfoTable = AcpiDmTableInfoCdat0;
891             break;
892 
893         case ACPI_CDAT_TYPE_DSLBIS:
894             InfoTable = AcpiDmTableInfoCdat1;
895             break;
896 
897         case ACPI_CDAT_TYPE_DSMSCIS:
898             InfoTable = AcpiDmTableInfoCdat2;
899             break;
900 
901         case ACPI_CDAT_TYPE_DSIS:
902             InfoTable = AcpiDmTableInfoCdat3;
903             break;
904 
905         case ACPI_CDAT_TYPE_DSEMTS:
906             InfoTable = AcpiDmTableInfoCdat4;
907             break;
908 
909         case ACPI_CDAT_TYPE_SSLBIS:
910             InfoTable = AcpiDmTableInfoCdat5;
911             break;
912 
913         default:
914             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "CDAT");
915         }
916 
917         /* Compile the CDAT subtable */
918 
919         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
920         if (ACPI_FAILURE (Status))
921         {
922             return (Status);
923         }
924 
925         ParentTable = DtPeekSubtable ();
926         DtInsertSubtable (ParentTable, Subtable);
927 
928         switch (CdatHeader->Type)
929         {
930         /* Multiple entries supported for this type */
931 
932         case ACPI_CDAT_TYPE_SSLBIS:
933 
934             /*
935              * Check for multiple SSLBEs
936              */
937             while (*PFieldList && !AcpiUtStricmp ((*PFieldList)->Name, "Port X ID"))
938             {
939                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCdatEntries, &Subtable);
940                 if (ACPI_FAILURE (Status))
941                 {
942                     return (Status);
943                 }
944                 ParentTable = DtPeekSubtable ();
945                 DtInsertSubtable (ParentTable, Subtable);
946             }
947             break;
948 
949         default:
950              break;
951         }
952 
953         /* Pop off the CDAT Subtable header subtree */
954 
955         DtPopSubtable ();
956     }
957 
958     return (AE_OK);
959 }
960 
961 
962 /******************************************************************************
963  *
964  * FUNCTION:    DtCompileCedt
965  *
966  * PARAMETERS:  List                - Current field list pointer
967  *
968  * RETURN:      Status
969  *
970  * DESCRIPTION: Compile CEDT.
971  *
972  *****************************************************************************/
973 
974 ACPI_STATUS
DtCompileCedt(void ** List)975 DtCompileCedt (
976     void                    **List)
977 {
978     ACPI_STATUS             Status;
979     DT_SUBTABLE             *Subtable;
980     DT_SUBTABLE             *ParentTable;
981     DT_FIELD                **PFieldList = (DT_FIELD **) List;
982     ACPI_CEDT_HEADER        *CedtHeader;
983     DT_FIELD                *SubtableStart;
984 
985 
986     /* Walk the parse tree */
987 
988     while (*PFieldList)
989     {
990         /* if CFMWS and has more than one target, then set to zero later */
991 
992         int InsertFlag = 1;
993         SubtableStart = *PFieldList;
994 
995         /* CEDT Header */
996 
997         Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedtHdr,
998             &Subtable);
999         if (ACPI_FAILURE (Status))
1000         {
1001             return (Status);
1002         }
1003 
1004         ParentTable = DtPeekSubtable ();
1005         DtInsertSubtable (ParentTable, Subtable);
1006         DtPushSubtable (Subtable);
1007 
1008         CedtHeader = ACPI_CAST_PTR (ACPI_CEDT_HEADER, Subtable->Buffer);
1009 
1010         switch (CedtHeader->Type)
1011         {
1012         case ACPI_CEDT_TYPE_CHBS:
1013             Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt0, &Subtable);
1014             if (ACPI_FAILURE (Status))
1015             {
1016                 return (Status);
1017             }
1018             break;
1019         case ACPI_CEDT_TYPE_CFMWS: {
1020             unsigned char *dump;
1021             unsigned int idx, offset, max = 0;
1022 
1023             /* Compile table with first "Interleave target" */
1024 
1025             Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt1, &Subtable);
1026             if (ACPI_FAILURE (Status))
1027             {
1028                 return (Status);
1029             }
1030 
1031             /* Look in buffer for the number of targets */
1032             offset = (unsigned int) ACPI_OFFSET (ACPI_CEDT_CFMWS, InterleaveWays);
1033             dump = (unsigned char *) Subtable->Buffer - 4;     /* place at beginning of cedt1 */
1034             max = 0x01 << dump[offset];     /* 2^max, so 0=1, 1=2, 2=4, 3=8. 8 is MAX */
1035             if (max > 8)    max=1;          /* Error in encoding Interleaving Ways. */
1036             if (max == 1)                   /* if only one target, then break here. */
1037                 break;                      /* break if only one target. */
1038 
1039             /* We need to add more interleave targets, so write the current Subtable. */
1040 
1041             ParentTable = DtPeekSubtable ();
1042             DtInsertSubtable (ParentTable, Subtable);   /* Insert AcpiDmTableInfoCedt1 table so we can put in */
1043             DtPushSubtable (Subtable);                  /* the targets > the first. */
1044 
1045             /* Now, find out all interleave targets beyond the first. */
1046 
1047             for (idx = 1; idx < max; idx++) {
1048                 ParentTable = DtPeekSubtable ();
1049 
1050                 if (*PFieldList)
1051                 {
1052                     Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt1_te, &Subtable);
1053                     if (ACPI_FAILURE (Status))
1054                     {
1055                         return (Status);
1056                     }
1057                     if (Subtable)
1058                     {
1059                         DtInsertSubtable (ParentTable, Subtable);       /* got a target, so insert table. */
1060                         InsertFlag = 0;
1061                     }
1062                 }
1063             }
1064 
1065             DtPopSubtable ();
1066             ParentTable = DtPeekSubtable ();
1067             break;
1068         }
1069         case ACPI_CEDT_TYPE_CXIMS: {
1070             unsigned char *dump;
1071             unsigned int idx, offset, max = 0;
1072 
1073             /* Compile table with first "Xor map" */
1074 
1075             Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt2, &Subtable);
1076             if (ACPI_FAILURE (Status))
1077             {
1078                 return (Status);
1079             }
1080 
1081             /* Look in buffer for the number of Xor maps */
1082             offset = (unsigned int) ACPI_OFFSET (ACPI_CEDT_CXIMS, NrXormaps);
1083             dump = (unsigned char *) Subtable->Buffer - 4;     /* place at beginning of cedt2 */
1084             max = dump[offset];
1085 
1086             /* We need to add more XOR maps, so write the current Subtable. */
1087 
1088             ParentTable = DtPeekSubtable ();
1089             DtInsertSubtable (ParentTable, Subtable);   /* Insert AcpiDmTableInfoCedt2 table so we can put in */
1090             DtPushSubtable (Subtable);
1091 
1092             /* Now, find out all Xor maps beyond the first. */
1093 
1094             for (idx = 1; idx < max; idx++) {
1095                 ParentTable = DtPeekSubtable ();
1096 
1097                 if (*PFieldList)
1098                 {
1099                     Status = DtCompileTable (PFieldList, AcpiDmTableInfoCedt2_te, &Subtable);
1100                     if (ACPI_FAILURE (Status))
1101                     {
1102                         return (Status);
1103                     }
1104                     if (Subtable)
1105                     {
1106                         DtInsertSubtable (ParentTable, Subtable);       /* got an Xor map, so insert table. */
1107                         InsertFlag = 0;
1108                     }
1109                 }
1110             }
1111 
1112             DtPopSubtable ();
1113             ParentTable = DtPeekSubtable ();
1114             break;
1115         }
1116 
1117         default:
1118             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "CEDT");
1119             return (AE_ERROR);
1120         }
1121 
1122         ParentTable = DtPeekSubtable ();
1123         if (InsertFlag == 1) {
1124                 DtInsertSubtable (ParentTable, Subtable);
1125         }
1126         DtPopSubtable ();
1127     }
1128 
1129     return (AE_OK);
1130 }
1131 
1132 
1133 /******************************************************************************
1134  *
1135  * FUNCTION:    DtCompileCpep
1136  *
1137  * PARAMETERS:  List                - Current field list pointer
1138  *
1139  * RETURN:      Status
1140  *
1141  * DESCRIPTION: Compile CPEP.
1142  *
1143  *****************************************************************************/
1144 
1145 ACPI_STATUS
DtCompileCpep(void ** List)1146 DtCompileCpep (
1147     void                    **List)
1148 {
1149     ACPI_STATUS             Status;
1150 
1151 
1152     Status = DtCompileTwoSubtables (List,
1153         AcpiDmTableInfoCpep, AcpiDmTableInfoCpep0);
1154     return (Status);
1155 }
1156 
1157 
1158 /******************************************************************************
1159  *
1160  * FUNCTION:    DtCompileCsrt
1161  *
1162  * PARAMETERS:  List                - Current field list pointer
1163  *
1164  * RETURN:      Status
1165  *
1166  * DESCRIPTION: Compile CSRT.
1167  *
1168  *****************************************************************************/
1169 
1170 ACPI_STATUS
DtCompileCsrt(void ** List)1171 DtCompileCsrt (
1172     void                    **List)
1173 {
1174     ACPI_STATUS             Status = AE_OK;
1175     DT_SUBTABLE             *Subtable;
1176     DT_SUBTABLE             *ParentTable;
1177     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1178     UINT32                  DescriptorCount;
1179     UINT32                  GroupLength;
1180 
1181 
1182     /* Subtables (Resource Groups) */
1183 
1184     ParentTable = DtPeekSubtable ();
1185     while (*PFieldList)
1186     {
1187         /* Resource group subtable */
1188 
1189         Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt0,
1190             &Subtable);
1191         if (ACPI_FAILURE (Status))
1192         {
1193             return (Status);
1194         }
1195 
1196         /* Compute the number of resource descriptors */
1197 
1198         GroupLength =
1199             (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
1200                 Subtable->Buffer))->Length -
1201             (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
1202                 Subtable->Buffer))->SharedInfoLength -
1203             sizeof (ACPI_CSRT_GROUP);
1204 
1205         DescriptorCount = (GroupLength  /
1206             sizeof (ACPI_CSRT_DESCRIPTOR));
1207 
1208         DtInsertSubtable (ParentTable, Subtable);
1209         DtPushSubtable (Subtable);
1210         ParentTable = DtPeekSubtable ();
1211 
1212         /* Shared info subtable (One per resource group) */
1213 
1214         Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt1,
1215             &Subtable);
1216         if (ACPI_FAILURE (Status))
1217         {
1218             return (Status);
1219         }
1220 
1221         DtInsertSubtable (ParentTable, Subtable);
1222 
1223         /* Sub-Subtables (Resource Descriptors) */
1224 
1225         while (*PFieldList && DescriptorCount)
1226         {
1227 
1228             Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2,
1229                 &Subtable);
1230             if (ACPI_FAILURE (Status))
1231             {
1232                 return (Status);
1233             }
1234 
1235             DtInsertSubtable (ParentTable, Subtable);
1236 
1237             DtPushSubtable (Subtable);
1238             ParentTable = DtPeekSubtable ();
1239             if (*PFieldList)
1240             {
1241                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2a,
1242                     &Subtable);
1243                 if (ACPI_FAILURE (Status))
1244                 {
1245                     return (Status);
1246                 }
1247                 if (Subtable)
1248                 {
1249                     DtInsertSubtable (ParentTable, Subtable);
1250                 }
1251             }
1252 
1253             DtPopSubtable ();
1254             ParentTable = DtPeekSubtable ();
1255             DescriptorCount--;
1256         }
1257 
1258         DtPopSubtable ();
1259         ParentTable = DtPeekSubtable ();
1260     }
1261 
1262     return (Status);
1263 }
1264 
1265 
1266 /******************************************************************************
1267  *
1268  * FUNCTION:    DtCompileDbg2
1269  *
1270  * PARAMETERS:  List                - Current field list pointer
1271  *
1272  * RETURN:      Status
1273  *
1274  * DESCRIPTION: Compile DBG2.
1275  *
1276  *****************************************************************************/
1277 
1278 ACPI_STATUS
DtCompileDbg2(void ** List)1279 DtCompileDbg2 (
1280     void                    **List)
1281 {
1282     ACPI_STATUS             Status;
1283     DT_SUBTABLE             *Subtable;
1284     DT_SUBTABLE             *ParentTable;
1285     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1286     UINT32                  SubtableCount;
1287     ACPI_DBG2_HEADER        *Dbg2Header;
1288     ACPI_DBG2_DEVICE        *DeviceInfo;
1289     UINT16                  CurrentOffset;
1290     UINT32                  i;
1291 
1292 
1293     /* Main table */
1294 
1295     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2, &Subtable);
1296     if (ACPI_FAILURE (Status))
1297     {
1298         return (Status);
1299     }
1300 
1301     ParentTable = DtPeekSubtable ();
1302     DtInsertSubtable (ParentTable, Subtable);
1303 
1304     /* Main table fields */
1305 
1306     Dbg2Header = ACPI_CAST_PTR (ACPI_DBG2_HEADER, Subtable->Buffer);
1307     Dbg2Header->InfoOffset = sizeof (ACPI_TABLE_HEADER) + ACPI_PTR_DIFF (
1308         ACPI_ADD_PTR (UINT8, Dbg2Header, sizeof (ACPI_DBG2_HEADER)), Dbg2Header);
1309 
1310     SubtableCount = Dbg2Header->InfoCount;
1311     DtPushSubtable (Subtable);
1312 
1313     /* Process all Device Information subtables (Count = InfoCount) */
1314 
1315     while (*PFieldList && SubtableCount)
1316     {
1317         /* Subtable: Debug Device Information */
1318 
1319         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Device,
1320             &Subtable);
1321         if (ACPI_FAILURE (Status))
1322         {
1323             return (Status);
1324         }
1325 
1326         DeviceInfo = ACPI_CAST_PTR (ACPI_DBG2_DEVICE, Subtable->Buffer);
1327         CurrentOffset = (UINT16) sizeof (ACPI_DBG2_DEVICE);
1328 
1329         ParentTable = DtPeekSubtable ();
1330         DtInsertSubtable (ParentTable, Subtable);
1331         DtPushSubtable (Subtable);
1332 
1333         ParentTable = DtPeekSubtable ();
1334 
1335         /* BaseAddressRegister GAS array (Required, size is RegisterCount) */
1336 
1337         DeviceInfo->BaseAddressOffset = CurrentOffset;
1338         for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++)
1339         {
1340             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Addr,
1341                 &Subtable);
1342             if (ACPI_FAILURE (Status))
1343             {
1344                 return (Status);
1345             }
1346 
1347             CurrentOffset += (UINT16) sizeof (ACPI_GENERIC_ADDRESS);
1348             DtInsertSubtable (ParentTable, Subtable);
1349         }
1350 
1351         /* AddressSize array (Required, size = RegisterCount) */
1352 
1353         DeviceInfo->AddressSizeOffset = CurrentOffset;
1354         for (i = 0; *PFieldList && (i < DeviceInfo->RegisterCount); i++)
1355         {
1356             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Size,
1357                 &Subtable);
1358             if (ACPI_FAILURE (Status))
1359             {
1360                 return (Status);
1361             }
1362 
1363             CurrentOffset += (UINT16) sizeof (UINT32);
1364             DtInsertSubtable (ParentTable, Subtable);
1365         }
1366 
1367         /* NamespaceString device identifier (Required, size = NamePathLength) */
1368 
1369         DeviceInfo->NamepathOffset = CurrentOffset;
1370         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2Name,
1371             &Subtable);
1372         if (ACPI_FAILURE (Status))
1373         {
1374             return (Status);
1375         }
1376 
1377         /* Update the device info header */
1378 
1379         DeviceInfo->NamepathLength = (UINT16) Subtable->Length;
1380         CurrentOffset += (UINT16) DeviceInfo->NamepathLength;
1381         DtInsertSubtable (ParentTable, Subtable);
1382 
1383         /* OemData - Variable-length data (Optional, size = OemDataLength) */
1384 
1385         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDbg2OemData,
1386             &Subtable);
1387         if (Status == AE_END_OF_TABLE)
1388         {
1389             /* optional field was not found and we're at the end of the file */
1390 
1391             goto subtableDone;
1392         }
1393         else if (ACPI_FAILURE (Status))
1394         {
1395             return (Status);
1396         }
1397 
1398         /* Update the device info header (zeros if no OEM data present) */
1399 
1400         DeviceInfo->OemDataOffset = 0;
1401         DeviceInfo->OemDataLength = 0;
1402 
1403         /* Optional subtable (OemData) */
1404 
1405         if (Subtable && Subtable->Length)
1406         {
1407             DeviceInfo->OemDataOffset = CurrentOffset;
1408             DeviceInfo->OemDataLength = (UINT16) Subtable->Length;
1409 
1410             DtInsertSubtable (ParentTable, Subtable);
1411         }
1412 subtableDone:
1413         SubtableCount--;
1414         DtPopSubtable (); /* Get next Device Information subtable */
1415     }
1416 
1417     DtPopSubtable ();
1418     return (AE_OK);
1419 }
1420 
1421 
1422 /******************************************************************************
1423  *
1424  * FUNCTION:    DtCompileDmar
1425  *
1426  * PARAMETERS:  List                - Current field list pointer
1427  *
1428  * RETURN:      Status
1429  *
1430  * DESCRIPTION: Compile DMAR.
1431  *
1432  *****************************************************************************/
1433 
1434 ACPI_STATUS
DtCompileDmar(void ** List)1435 DtCompileDmar (
1436     void                    **List)
1437 {
1438     ACPI_STATUS             Status;
1439     DT_SUBTABLE             *Subtable;
1440     DT_SUBTABLE             *ParentTable;
1441     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1442     DT_FIELD                *SubtableStart;
1443     ACPI_DMTABLE_INFO       *InfoTable;
1444     ACPI_DMAR_HEADER        *DmarHeader;
1445     ACPI_DMAR_DEVICE_SCOPE  *DmarDeviceScope;
1446     UINT32                  DeviceScopeLength;
1447     UINT32                  PciPathLength;
1448 
1449 
1450     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmar, &Subtable);
1451     if (ACPI_FAILURE (Status))
1452     {
1453         return (Status);
1454     }
1455 
1456     ParentTable = DtPeekSubtable ();
1457     DtInsertSubtable (ParentTable, Subtable);
1458     DtPushSubtable (Subtable);
1459 
1460     while (*PFieldList)
1461     {
1462         /* DMAR Header */
1463 
1464         SubtableStart = *PFieldList;
1465         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarHdr,
1466             &Subtable);
1467         if (ACPI_FAILURE (Status))
1468         {
1469             return (Status);
1470         }
1471 
1472         ParentTable = DtPeekSubtable ();
1473         DtInsertSubtable (ParentTable, Subtable);
1474         DtPushSubtable (Subtable);
1475 
1476         DmarHeader = ACPI_CAST_PTR (ACPI_DMAR_HEADER, Subtable->Buffer);
1477 
1478         switch (DmarHeader->Type)
1479         {
1480         case ACPI_DMAR_TYPE_HARDWARE_UNIT:
1481 
1482             InfoTable = AcpiDmTableInfoDmar0;
1483             break;
1484 
1485         case ACPI_DMAR_TYPE_RESERVED_MEMORY:
1486 
1487             InfoTable = AcpiDmTableInfoDmar1;
1488             break;
1489 
1490         case ACPI_DMAR_TYPE_ROOT_ATS:
1491 
1492             InfoTable = AcpiDmTableInfoDmar2;
1493             break;
1494 
1495         case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
1496 
1497             InfoTable = AcpiDmTableInfoDmar3;
1498             break;
1499 
1500         case ACPI_DMAR_TYPE_NAMESPACE:
1501 
1502             InfoTable = AcpiDmTableInfoDmar4;
1503             break;
1504 
1505         case ACPI_DMAR_TYPE_SATC:
1506 
1507             InfoTable = AcpiDmTableInfoDmar5;
1508             break;
1509 
1510         case ACPI_DMAR_TYPE_SIDP:
1511 
1512             InfoTable = AcpiDmTableInfoDmar6;
1513             break;
1514 
1515         default:
1516 
1517             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "DMAR");
1518             return (AE_ERROR);
1519         }
1520 
1521         /* DMAR Subtable */
1522 
1523         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1524         if (ACPI_FAILURE (Status))
1525         {
1526             return (Status);
1527         }
1528 
1529         ParentTable = DtPeekSubtable ();
1530         DtInsertSubtable (ParentTable, Subtable);
1531 
1532         /*
1533          * Optional Device Scope subtables
1534          */
1535         if ((DmarHeader->Type == ACPI_DMAR_TYPE_HARDWARE_AFFINITY) ||
1536             (DmarHeader->Type == ACPI_DMAR_TYPE_NAMESPACE))
1537         {
1538             /* These types do not support device scopes */
1539 
1540             DtPopSubtable ();
1541             continue;
1542         }
1543 
1544         DtPushSubtable (Subtable);
1545         DeviceScopeLength = DmarHeader->Length - Subtable->Length -
1546             ParentTable->Length;
1547         while (DeviceScopeLength)
1548         {
1549             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarScope,
1550                 &Subtable);
1551             if (Status == AE_NOT_FOUND)
1552             {
1553                 break;
1554             }
1555 
1556             ParentTable = DtPeekSubtable ();
1557             DtInsertSubtable (ParentTable, Subtable);
1558             DtPushSubtable (Subtable);
1559 
1560             DmarDeviceScope = ACPI_CAST_PTR (ACPI_DMAR_DEVICE_SCOPE, Subtable->Buffer);
1561 
1562             /* Optional PCI Paths */
1563 
1564             PciPathLength = DmarDeviceScope->Length - Subtable->Length;
1565             while (PciPathLength)
1566             {
1567                 Status = DtCompileTable (PFieldList, TableInfoDmarPciPath,
1568                     &Subtable);
1569                 if (Status == AE_NOT_FOUND)
1570                 {
1571                     DtPopSubtable ();
1572                     break;
1573                 }
1574 
1575                 ParentTable = DtPeekSubtable ();
1576                 DtInsertSubtable (ParentTable, Subtable);
1577                 PciPathLength -= Subtable->Length;
1578             }
1579 
1580             DtPopSubtable ();
1581             DeviceScopeLength -= DmarDeviceScope->Length;
1582         }
1583 
1584         DtPopSubtable ();
1585         DtPopSubtable ();
1586     }
1587 
1588     return (AE_OK);
1589 }
1590 
1591 
1592 /******************************************************************************
1593  *
1594  * FUNCTION:    DtCompileDrtm
1595  *
1596  * PARAMETERS:  List                - Current field list pointer
1597  *
1598  * RETURN:      Status
1599  *
1600  * DESCRIPTION: Compile DRTM.
1601  *
1602  *****************************************************************************/
1603 
1604 ACPI_STATUS
DtCompileDrtm(void ** List)1605 DtCompileDrtm (
1606     void                    **List)
1607 {
1608     ACPI_STATUS             Status;
1609     DT_SUBTABLE             *Subtable;
1610     DT_SUBTABLE             *ParentTable;
1611     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1612     UINT32                  Count;
1613     /* ACPI_TABLE_DRTM         *Drtm; */
1614     ACPI_DRTM_VTABLE_LIST   *DrtmVtl;
1615     ACPI_DRTM_RESOURCE_LIST *DrtmRl;
1616     /* ACPI_DRTM_DPS_ID        *DrtmDps; */
1617 
1618 
1619     ParentTable = DtPeekSubtable ();
1620 
1621     /* Compile DRTM header */
1622 
1623     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm,
1624         &Subtable);
1625     if (ACPI_FAILURE (Status))
1626     {
1627         return (Status);
1628     }
1629     DtInsertSubtable (ParentTable, Subtable);
1630 
1631     /*
1632      * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
1633      * should be taken to avoid accessing ACPI_TABLE_HADER fields.
1634      */
1635 #if 0
1636     Drtm = ACPI_SUB_PTR (ACPI_TABLE_DRTM,
1637         Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
1638 #endif
1639     /* Compile VTL */
1640 
1641     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0,
1642         &Subtable);
1643     if (ACPI_FAILURE (Status))
1644     {
1645         return (Status);
1646     }
1647 
1648     DtInsertSubtable (ParentTable, Subtable);
1649     DrtmVtl = ACPI_CAST_PTR (ACPI_DRTM_VTABLE_LIST, Subtable->Buffer);
1650 
1651     DtPushSubtable (Subtable);
1652     ParentTable = DtPeekSubtable ();
1653     Count = 0;
1654 
1655     while (*PFieldList)
1656     {
1657         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0a,
1658             &Subtable);
1659         if (ACPI_FAILURE (Status))
1660         {
1661             return (Status);
1662         }
1663         if (!Subtable)
1664         {
1665             break;
1666         }
1667         DtInsertSubtable (ParentTable, Subtable);
1668         Count++;
1669     }
1670 
1671     DrtmVtl->ValidatedTableCount = Count;
1672     DtPopSubtable ();
1673     ParentTable = DtPeekSubtable ();
1674 
1675     /* Compile RL */
1676 
1677     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1,
1678         &Subtable);
1679     if (ACPI_FAILURE (Status))
1680     {
1681         return (Status);
1682     }
1683 
1684     DtInsertSubtable (ParentTable, Subtable);
1685     DrtmRl = ACPI_CAST_PTR (ACPI_DRTM_RESOURCE_LIST, Subtable->Buffer);
1686 
1687     DtPushSubtable (Subtable);
1688     ParentTable = DtPeekSubtable ();
1689     Count = 0;
1690 
1691     while (*PFieldList)
1692     {
1693         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1a,
1694             &Subtable);
1695         if (ACPI_FAILURE (Status))
1696         {
1697             return (Status);
1698         }
1699 
1700         if (!Subtable)
1701         {
1702             break;
1703         }
1704 
1705         DtInsertSubtable (ParentTable, Subtable);
1706         Count++;
1707     }
1708 
1709     DrtmRl->ResourceCount = Count;
1710     DtPopSubtable ();
1711     ParentTable = DtPeekSubtable ();
1712 
1713     /* Compile DPS */
1714 
1715     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm2,
1716         &Subtable);
1717     if (ACPI_FAILURE (Status))
1718     {
1719         return (Status);
1720     }
1721     DtInsertSubtable (ParentTable, Subtable);
1722     /* DrtmDps = ACPI_CAST_PTR (ACPI_DRTM_DPS_ID, Subtable->Buffer);*/
1723 
1724 
1725     return (AE_OK);
1726 }
1727 
1728 
1729 /******************************************************************************
1730  *
1731  * FUNCTION:    DtCompileDtpr
1732  *
1733  * PARAMETERS:  List                - Current field list pointer
1734  *
1735  * RETURN:      Status
1736  *
1737  * DESCRIPTION: Compile DTPR.
1738  *
1739  *****************************************************************************/
1740 
1741 ACPI_STATUS
DtCompileDtpr(void ** List)1742 DtCompileDtpr (
1743     void                    **List)
1744 {
1745     ACPI_STATUS             Status;
1746     DT_SUBTABLE             *Subtable;
1747     DT_SUBTABLE             *ParentTable;
1748     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1749     ACPI_TABLE_DTPR         *Dtpr;
1750     ACPI_TPR_INSTANCE       *TprInst;
1751     UINT32                  i, InsCnt, SrlCnt, TprCnt;
1752 
1753 
1754     ParentTable = DtPeekSubtable ();
1755 
1756     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDtpr, &Subtable);
1757     if (ACPI_FAILURE (Status))
1758     {
1759         return (Status);
1760     }
1761 
1762     DtInsertSubtable (ParentTable, Subtable);
1763 
1764     Dtpr = ACPI_SUB_PTR (ACPI_TABLE_DTPR, Subtable->Buffer,
1765                          sizeof (ACPI_TABLE_HEADER));
1766     if (!Dtpr)
1767     {
1768         AcpiOsPrintf ("DTPR buffer pointer is NULL\n");
1769         return (AE_NULL_OBJECT);
1770     }
1771 
1772     InsCnt = Dtpr->InsCnt;
1773 
1774     while (*PFieldList)
1775     {
1776         for (i = 0; i < InsCnt; i++)
1777         {
1778             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDtprInstance,
1779                                      &Subtable);
1780             if (ACPI_FAILURE (Status))
1781             {
1782                 return (Status);
1783             }
1784 
1785             TprInst = ACPI_CAST_PTR (ACPI_TPR_INSTANCE, Subtable->Buffer);
1786             if (!TprInst)
1787             {
1788                 AcpiOsPrintf ("Tpr Instance buffer pointer is NULL\n");
1789                 return (AE_NULL_OBJECT);
1790             }
1791 
1792             TprCnt = TprInst->TprCnt;
1793             DtInsertSubtable (ParentTable, Subtable);
1794             DtPushSubtable (Subtable);
1795             ParentTable = DtPeekSubtable ();
1796 
1797             while (*PFieldList && TprCnt)
1798             {
1799                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDtprArr,
1800                                          &Subtable);
1801                 if (ACPI_FAILURE (Status))
1802                 {
1803                     return (Status);
1804                 }
1805 
1806                 DtInsertSubtable (ParentTable, Subtable);
1807                 TprCnt--;
1808             }
1809 
1810             DtPopSubtable();
1811             ParentTable = DtPeekSubtable ();
1812         }
1813 
1814         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDtprSerializeReq0,
1815                                  &Subtable);
1816         if (ACPI_FAILURE (Status))
1817         {
1818             return (Status);
1819         }
1820 
1821         SrlCnt = *ACPI_CAST_PTR(UINT32, Subtable->Buffer);
1822         DtInsertSubtable (ParentTable, Subtable);
1823         DtPushSubtable (Subtable);
1824         ParentTable = DtPeekSubtable ();
1825 
1826         while (*PFieldList && SrlCnt)
1827         {
1828             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDtprSerializeReq1,
1829                                      &Subtable);
1830             if (ACPI_FAILURE (Status))
1831             {
1832                 return (Status);
1833             }
1834 
1835             DtInsertSubtable (ParentTable, Subtable);
1836             SrlCnt--;
1837         }
1838 
1839 
1840         DtPopSubtable();
1841         ParentTable = DtPeekSubtable ();
1842     }
1843 
1844     return Status;
1845 }
1846 
1847 /******************************************************************************
1848  *
1849  * FUNCTION:    DtCompileEinj
1850  *
1851  * PARAMETERS:  List                - Current field list pointer
1852  *
1853  * RETURN:      Status
1854  *
1855  * DESCRIPTION: Compile EINJ.
1856  *
1857  *****************************************************************************/
1858 
1859 ACPI_STATUS
DtCompileEinj(void ** List)1860 DtCompileEinj (
1861     void                    **List)
1862 {
1863     ACPI_STATUS             Status;
1864 
1865 
1866     Status = DtCompileTwoSubtables (List,
1867         AcpiDmTableInfoEinj, AcpiDmTableInfoEinj0);
1868     return (Status);
1869 }
1870 
1871 
1872 /******************************************************************************
1873  *
1874  * FUNCTION:    DtCompileErdt
1875  *
1876  * PARAMETERS:  List                - Current field list pointer
1877  *
1878  * RETURN:      Status
1879  *
1880  * DESCRIPTION: Compile ERST. Complex table with subtables and subsubtables.
1881  *
1882  *****************************************************************************/
1883 
1884 ACPI_STATUS
DtCompileErdt(void ** List)1885 DtCompileErdt (
1886     void                    **List)
1887 {
1888     ACPI_STATUS             Status;
1889     DT_SUBTABLE             *Subtable, *RmddSubtable = NULL, *Subsubtable;
1890     DT_SUBTABLE             *ParentTable;
1891     DT_FIELD                **PFieldList = (DT_FIELD **) List;
1892     DT_FIELD                *SubtableStart;
1893     ACPI_SUBTBL_HDR_16      *ErdtHeader;
1894     ACPI_DMTABLE_INFO       *InfoTable;
1895     ACPI_ERDT_MMRC          *Mmrc;
1896     ACPI_ERDT_IBRD          *Ibrd;
1897     UINT32                  NumEntries;
1898     BOOLEAN                 SeenRmdd = FALSE;
1899     BOOLEAN                 SeenSubtable = FALSE;
1900 
1901     Status = DtCompileTable (PFieldList, AcpiDmTableInfoErdt,
1902         &Subtable);
1903     if (ACPI_FAILURE (Status))
1904     {
1905         return (Status);
1906     }
1907 
1908     ParentTable = DtPeekSubtable ();
1909     DtInsertSubtable (ParentTable, Subtable);
1910 
1911     while (*PFieldList)
1912     {
1913         SubtableStart = *PFieldList;
1914         Status = DtCompileTable (PFieldList, AcpiDmTableInfoErdtHdr,
1915             &Subtable);
1916         if (ACPI_FAILURE (Status))
1917         {
1918             return (Status);
1919         }
1920 
1921         ErdtHeader = ACPI_CAST_PTR (ACPI_SUBTBL_HDR_16, Subtable->Buffer);
1922 
1923         /* RMDD tables at top level. All others are subtables of preceeding RMDD */
1924         if (ErdtHeader->Type == ACPI_ERDT_TYPE_RMDD)
1925         {
1926             if (SeenRmdd && SeenSubtable)
1927                 DtPopSubtable ();
1928             SeenRmdd = TRUE;
1929             SeenSubtable = FALSE;
1930             RmddSubtable = Subtable;
1931         }
1932         else
1933         {
1934             if (!SeenSubtable)
1935             {
1936                 DtPushSubtable (RmddSubtable);
1937                 SeenSubtable = TRUE;
1938             }
1939         }
1940 
1941         ParentTable = DtPeekSubtable ();
1942         DtInsertSubtable (ParentTable, Subtable);
1943         DtPushSubtable (Subtable);
1944 
1945         switch (ErdtHeader->Type)
1946         {
1947         case ACPI_ERDT_TYPE_RMDD:
1948             InfoTable = AcpiDmTableInfoErdtRmdd;
1949             break;
1950 
1951         case ACPI_ERDT_TYPE_CACD:
1952              InfoTable = AcpiDmTableInfoErdtCacd;
1953              break;
1954 
1955         case ACPI_ERDT_TYPE_DACD:
1956              InfoTable = AcpiDmTableInfoErdtDacd;
1957              break;
1958 
1959         case ACPI_ERDT_TYPE_CMRC:
1960              InfoTable = AcpiDmTableInfoErdtCmrc;
1961              break;
1962 
1963         case ACPI_ERDT_TYPE_MMRC:
1964              InfoTable = AcpiDmTableInfoErdtMmrc;
1965              break;
1966 
1967         case ACPI_ERDT_TYPE_MARC:
1968              InfoTable = AcpiDmTableInfoErdtMarc;
1969              break;
1970 
1971         case ACPI_ERDT_TYPE_CARC:
1972              InfoTable = AcpiDmTableInfoErdtCarc;
1973              break;
1974 
1975         case ACPI_ERDT_TYPE_CMRD:
1976              InfoTable = AcpiDmTableInfoErdtCmrd;
1977              break;
1978 
1979         case ACPI_ERDT_TYPE_IBRD:
1980              InfoTable = AcpiDmTableInfoErdtIbrd;
1981              break;
1982 
1983         case ACPI_ERDT_TYPE_IBAD:
1984              InfoTable = AcpiDmTableInfoErdtIbad;
1985              break;
1986 
1987         case ACPI_ERDT_TYPE_CARD:
1988              InfoTable = AcpiDmTableInfoErdtCard;
1989              break;
1990 
1991         default:
1992             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ERDT");
1993             return (AE_ERROR);
1994         }
1995 
1996         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
1997         if (ACPI_FAILURE (Status))
1998         {
1999             return (Status);
2000         }
2001 
2002         ParentTable = DtPeekSubtable ();
2003         DtInsertSubtable (ParentTable, Subtable);
2004 
2005         /* Some subtable types end with flex arrays */
2006 
2007         switch (ErdtHeader->Type)
2008         {
2009         case ACPI_ERDT_TYPE_CACD:
2010             while (*PFieldList)
2011             {
2012                 Status = DtCompileTable (PFieldList,
2013                     AcpiDmTableInfoErdtCacdX2apic, &Subtable);
2014                 if (ACPI_FAILURE (Status))
2015                 {
2016                     return (Status);
2017                 }
2018                 if (!Subtable)
2019                 {
2020                     break;
2021                 }
2022 
2023                 ParentTable = DtPeekSubtable ();
2024                 DtInsertSubtable (ParentTable, Subtable);
2025             }
2026             break;
2027 
2028         case ACPI_ERDT_TYPE_DACD:
2029             while (*PFieldList)
2030             {
2031                 Status = DtCompileTable (PFieldList,
2032                     AcpiDmTableInfoErdtDacdScope, &Subtable);
2033                 if (ACPI_FAILURE (Status))
2034                 {
2035                     return (Status);
2036                 }
2037                 if (!Subtable)
2038                 {
2039                     break;
2040                 }
2041 
2042                 DtPushSubtable (Subtable);
2043                 while (*PFieldList)
2044                 {
2045                     Status = DtCompileTable (PFieldList,
2046                         AcpiDmTableInfoErdtDacdPath, &Subsubtable);
2047                     if (ACPI_FAILURE (Status))
2048                     {
2049                         return (Status);
2050                     }
2051                     if (!Subsubtable)
2052                     {
2053                         break;
2054                     }
2055 
2056                     ParentTable = DtPeekSubtable ();
2057                     DtInsertSubtable (ParentTable, Subsubtable);
2058                 }
2059                 DtPopSubtable ();
2060 
2061                 ParentTable = DtPeekSubtable ();
2062                 DtInsertSubtable (ParentTable, Subtable);
2063             }
2064             break;
2065 
2066         case ACPI_ERDT_TYPE_MMRC:
2067             Mmrc = ACPI_SUB_PTR (ACPI_ERDT_MMRC, Subtable->Buffer,
2068                 sizeof(ACPI_SUBTBL_HDR_16));
2069             NumEntries = 0;
2070             while (*PFieldList)
2071             {
2072                 Status = DtCompileTable (PFieldList,
2073                     AcpiDmTableInfoErdtMmrcCorrFactor, &Subtable);
2074                 if (ACPI_FAILURE (Status))
2075                 {
2076                     return (Status);
2077                 }
2078                 if (!Subtable)
2079                 {
2080                     break;
2081                 }
2082 
2083                 ParentTable = DtPeekSubtable ();
2084                 DtInsertSubtable (ParentTable, Subtable);
2085                 NumEntries++;
2086             }
2087             Mmrc->CorrFactorListLen = NumEntries;
2088             break;
2089 
2090         case ACPI_ERDT_TYPE_IBRD:
2091             Ibrd = ACPI_SUB_PTR (ACPI_ERDT_IBRD, Subtable->Buffer,
2092                 sizeof(ACPI_SUBTBL_HDR_16));
2093             NumEntries = 0;
2094             while (*PFieldList)
2095             {
2096                 Status = DtCompileTable (PFieldList,
2097                     AcpiDmTableInfoErdtIbrdCorrFactor, &Subtable);
2098                 if (ACPI_FAILURE (Status))
2099                 {
2100                     return (Status);
2101                 }
2102                 if (!Subtable)
2103                 {
2104                     break;
2105                 }
2106 
2107                 ParentTable = DtPeekSubtable ();
2108                 DtInsertSubtable (ParentTable, Subtable);
2109                 NumEntries++;
2110             }
2111             Ibrd->CorrFactorListLen = NumEntries;
2112             break;
2113 
2114         default:
2115             /* Already checked for valid subtable type above */
2116 
2117             break;
2118         }
2119         DtPopSubtable ();
2120     }
2121 
2122     if (SeenSubtable)
2123     {
2124         DtPopSubtable ();
2125     }
2126 
2127     return (AE_OK);
2128 }
2129 
2130 
2131 /******************************************************************************
2132  *
2133  * FUNCTION:    DtCompileErst
2134  *
2135  * PARAMETERS:  List                - Current field list pointer
2136  *
2137  * RETURN:      Status
2138  *
2139  * DESCRIPTION: Compile ERST.
2140  *
2141  *****************************************************************************/
2142 
2143 ACPI_STATUS
DtCompileErst(void ** List)2144 DtCompileErst (
2145     void                    **List)
2146 {
2147     ACPI_STATUS             Status;
2148 
2149 
2150     Status = DtCompileTwoSubtables (List,
2151         AcpiDmTableInfoErst, AcpiDmTableInfoEinj0);
2152     return (Status);
2153 }
2154 
2155 
2156 /******************************************************************************
2157  *
2158  * FUNCTION:    DtCompileGtdt
2159  *
2160  * PARAMETERS:  List                - Current field list pointer
2161  *
2162  * RETURN:      Status
2163  *
2164  * DESCRIPTION: Compile GTDT.
2165  *
2166  *****************************************************************************/
2167 
2168 ACPI_STATUS
DtCompileGtdt(void ** List)2169 DtCompileGtdt (
2170     void                    **List)
2171 {
2172     ACPI_STATUS             Status;
2173     DT_SUBTABLE             *Subtable;
2174     DT_SUBTABLE             *ParentTable;
2175     DT_FIELD                **PFieldList = (DT_FIELD **) List;
2176     DT_FIELD                *SubtableStart;
2177     ACPI_SUBTABLE_HEADER    *GtdtHeader;
2178     ACPI_DMTABLE_INFO       *InfoTable;
2179     UINT32                  GtCount;
2180     ACPI_TABLE_HEADER       *Header;
2181 
2182 
2183     ParentTable = DtPeekSubtable ();
2184 
2185     Header = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer);
2186 
2187     /* Compile the main table */
2188 
2189     Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt,
2190         &Subtable);
2191     if (ACPI_FAILURE (Status))
2192     {
2193         return (Status);
2194     }
2195 
2196     /* GTDT revision 3 later contains 2 extra fields before subtables */
2197 
2198     if (Header->Revision > 2)
2199     {
2200         ParentTable = DtPeekSubtable ();
2201         DtInsertSubtable (ParentTable, Subtable);
2202 
2203         Status = DtCompileTable (PFieldList,
2204             AcpiDmTableInfoGtdtEl2, &Subtable);
2205         if (ACPI_FAILURE (Status))
2206         {
2207             return (Status);
2208         }
2209     }
2210 
2211     ParentTable = DtPeekSubtable ();
2212     DtInsertSubtable (ParentTable, Subtable);
2213 
2214     while (*PFieldList)
2215     {
2216         SubtableStart = *PFieldList;
2217         Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdtHdr,
2218             &Subtable);
2219         if (ACPI_FAILURE (Status))
2220         {
2221             return (Status);
2222         }
2223 
2224         ParentTable = DtPeekSubtable ();
2225         DtInsertSubtable (ParentTable, Subtable);
2226         DtPushSubtable (Subtable);
2227 
2228         GtdtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer);
2229 
2230         switch (GtdtHeader->Type)
2231         {
2232         case ACPI_GTDT_TYPE_TIMER_BLOCK:
2233 
2234             InfoTable = AcpiDmTableInfoGtdt0;
2235             break;
2236 
2237         case ACPI_GTDT_TYPE_WATCHDOG:
2238 
2239             InfoTable = AcpiDmTableInfoGtdt1;
2240             break;
2241 
2242         default:
2243 
2244             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "GTDT");
2245             return (AE_ERROR);
2246         }
2247 
2248         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
2249         if (ACPI_FAILURE (Status))
2250         {
2251             return (Status);
2252         }
2253 
2254         ParentTable = DtPeekSubtable ();
2255         DtInsertSubtable (ParentTable, Subtable);
2256 
2257         /*
2258          * Additional GT block subtable data
2259          */
2260 
2261         switch (GtdtHeader->Type)
2262         {
2263         case ACPI_GTDT_TYPE_TIMER_BLOCK:
2264 
2265             DtPushSubtable (Subtable);
2266             ParentTable = DtPeekSubtable ();
2267 
2268             GtCount = (ACPI_CAST_PTR (ACPI_GTDT_TIMER_BLOCK,
2269                 Subtable->Buffer - sizeof(ACPI_GTDT_HEADER)))->TimerCount;
2270 
2271             while (GtCount)
2272             {
2273                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt0a,
2274                     &Subtable);
2275                 if (ACPI_FAILURE (Status))
2276                 {
2277                     return (Status);
2278                 }
2279 
2280                 DtInsertSubtable (ParentTable, Subtable);
2281                 GtCount--;
2282             }
2283 
2284             DtPopSubtable ();
2285             break;
2286 
2287         default:
2288 
2289             break;
2290         }
2291 
2292         DtPopSubtable ();
2293     }
2294 
2295     return (AE_OK);
2296 }
2297 
2298 
2299 /******************************************************************************
2300  *
2301  * FUNCTION:    DtCompileFpdt
2302  *
2303  * PARAMETERS:  List                - Current field list pointer
2304  *
2305  * RETURN:      Status
2306  *
2307  * DESCRIPTION: Compile FPDT.
2308  *
2309  *****************************************************************************/
2310 
2311 ACPI_STATUS
DtCompileFpdt(void ** List)2312 DtCompileFpdt (
2313     void                    **List)
2314 {
2315     ACPI_STATUS             Status;
2316     ACPI_FPDT_HEADER        *FpdtHeader;
2317     DT_SUBTABLE             *Subtable;
2318     DT_SUBTABLE             *ParentTable;
2319     ACPI_DMTABLE_INFO       *InfoTable;
2320     DT_FIELD                **PFieldList = (DT_FIELD **) List;
2321     DT_FIELD                *SubtableStart;
2322 
2323 
2324     while (*PFieldList)
2325     {
2326         SubtableStart = *PFieldList;
2327         Status = DtCompileTable (PFieldList, AcpiDmTableInfoFpdtHdr,
2328             &Subtable);
2329         if (ACPI_FAILURE (Status))
2330         {
2331             return (Status);
2332         }
2333 
2334         ParentTable = DtPeekSubtable ();
2335         DtInsertSubtable (ParentTable, Subtable);
2336         DtPushSubtable (Subtable);
2337 
2338         FpdtHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer);
2339 
2340         switch (FpdtHeader->Type)
2341         {
2342         case ACPI_FPDT_TYPE_BOOT:
2343 
2344             InfoTable = AcpiDmTableInfoFpdt0;
2345             break;
2346 
2347         case ACPI_FPDT_TYPE_S3PERF:
2348 
2349             InfoTable = AcpiDmTableInfoFpdt1;
2350             break;
2351 
2352         default:
2353 
2354             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "FPDT");
2355             return (AE_ERROR);
2356             break;
2357         }
2358 
2359         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
2360         if (ACPI_FAILURE (Status))
2361         {
2362             return (Status);
2363         }
2364 
2365         ParentTable = DtPeekSubtable ();
2366         DtInsertSubtable (ParentTable, Subtable);
2367         DtPopSubtable ();
2368     }
2369 
2370     return (AE_OK);
2371 }
2372 
2373 
2374 /******************************************************************************
2375  *
2376  * FUNCTION:    DtCompileHest
2377  *
2378  * PARAMETERS:  List                - Current field list pointer
2379  *
2380  * RETURN:      Status
2381  *
2382  * DESCRIPTION: Compile HEST.
2383  *
2384  *****************************************************************************/
2385 
2386 ACPI_STATUS
DtCompileHest(void ** List)2387 DtCompileHest (
2388     void                    **List)
2389 {
2390     ACPI_STATUS             Status;
2391     DT_SUBTABLE             *Subtable;
2392     DT_SUBTABLE             *ParentTable;
2393     DT_FIELD                **PFieldList = (DT_FIELD **) List;
2394     DT_FIELD                *SubtableStart;
2395     ACPI_DMTABLE_INFO       *InfoTable;
2396     UINT16                  Type;
2397     UINT32                  BankCount;
2398 
2399 
2400     Status = DtCompileTable (PFieldList, AcpiDmTableInfoHest,
2401         &Subtable);
2402     if (ACPI_FAILURE (Status))
2403     {
2404         return (Status);
2405     }
2406 
2407     ParentTable = DtPeekSubtable ();
2408     DtInsertSubtable (ParentTable, Subtable);
2409 
2410     while (*PFieldList)
2411     {
2412         /* Get subtable type */
2413 
2414         SubtableStart = *PFieldList;
2415         DtCompileInteger ((UINT8 *) &Type, *PFieldList, 2, 0);
2416 
2417         switch (Type)
2418         {
2419         case ACPI_HEST_TYPE_IA32_CHECK:
2420 
2421             InfoTable = AcpiDmTableInfoHest0;
2422             break;
2423 
2424         case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
2425 
2426             InfoTable = AcpiDmTableInfoHest1;
2427             break;
2428 
2429         case ACPI_HEST_TYPE_IA32_NMI:
2430 
2431             InfoTable = AcpiDmTableInfoHest2;
2432             break;
2433 
2434         case ACPI_HEST_TYPE_AER_ROOT_PORT:
2435 
2436             InfoTable = AcpiDmTableInfoHest6;
2437             break;
2438 
2439         case ACPI_HEST_TYPE_AER_ENDPOINT:
2440 
2441             InfoTable = AcpiDmTableInfoHest7;
2442             break;
2443 
2444         case ACPI_HEST_TYPE_AER_BRIDGE:
2445 
2446             InfoTable = AcpiDmTableInfoHest8;
2447             break;
2448 
2449         case ACPI_HEST_TYPE_GENERIC_ERROR:
2450 
2451             InfoTable = AcpiDmTableInfoHest9;
2452             break;
2453 
2454         case ACPI_HEST_TYPE_GENERIC_ERROR_V2:
2455 
2456             InfoTable = AcpiDmTableInfoHest10;
2457             break;
2458 
2459         case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
2460 
2461             InfoTable = AcpiDmTableInfoHest11;
2462             break;
2463 
2464         default:
2465 
2466             /* Cannot continue on unknown type */
2467 
2468             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HEST");
2469             return (AE_ERROR);
2470         }
2471 
2472         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
2473         if (ACPI_FAILURE (Status))
2474         {
2475             return (Status);
2476         }
2477 
2478         DtInsertSubtable (ParentTable, Subtable);
2479 
2480         /*
2481          * Additional subtable data - IA32 Error Bank(s)
2482          */
2483         BankCount = 0;
2484         switch (Type)
2485         {
2486         case ACPI_HEST_TYPE_IA32_CHECK:
2487 
2488             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK,
2489                 Subtable->Buffer))->NumHardwareBanks;
2490             break;
2491 
2492         case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
2493 
2494             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED,
2495                 Subtable->Buffer))->NumHardwareBanks;
2496             break;
2497 
2498         case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
2499 
2500             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_DEFERRED_CHECK,
2501                 Subtable->Buffer))->NumHardwareBanks;
2502             break;
2503 
2504         default:
2505 
2506             break;
2507         }
2508 
2509         while (BankCount)
2510         {
2511             Status = DtCompileTable (PFieldList, AcpiDmTableInfoHestBank,
2512                 &Subtable);
2513             if (ACPI_FAILURE (Status))
2514             {
2515                 return (Status);
2516             }
2517 
2518             DtInsertSubtable (ParentTable, Subtable);
2519             BankCount--;
2520         }
2521     }
2522 
2523     return (AE_OK);
2524 }
2525 
2526 
2527 /******************************************************************************
2528  *
2529  * FUNCTION:    DtCompileHmat
2530  *
2531  * PARAMETERS:  List                - Current field list pointer
2532  *
2533  * RETURN:      Status
2534  *
2535  * DESCRIPTION: Compile HMAT.
2536  *
2537  *****************************************************************************/
2538 
2539 ACPI_STATUS
DtCompileHmat(void ** List)2540 DtCompileHmat (
2541     void                    **List)
2542 {
2543     ACPI_STATUS             Status;
2544     DT_SUBTABLE             *Subtable;
2545     DT_SUBTABLE             *ParentTable;
2546     DT_FIELD                **PFieldList = (DT_FIELD **) List;
2547     DT_FIELD                *SubtableStart;
2548     DT_FIELD                *EntryStart;
2549     ACPI_HMAT_STRUCTURE     *HmatStruct;
2550     ACPI_HMAT_LOCALITY      *HmatLocality;
2551     ACPI_HMAT_CACHE         *HmatCache;
2552     ACPI_DMTABLE_INFO       *InfoTable;
2553     UINT32                  IntPDNumber;
2554     UINT32                  TgtPDNumber;
2555     UINT64                  EntryNumber;
2556     UINT16                  SMBIOSHandleNumber;
2557 
2558 
2559     ParentTable = DtPeekSubtable ();
2560 
2561     Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmat,
2562         &Subtable);
2563     if (ACPI_FAILURE (Status))
2564     {
2565         return (Status);
2566     }
2567     DtInsertSubtable (ParentTable, Subtable);
2568 
2569     while (*PFieldList)
2570     {
2571         /* Compile HMAT structure header */
2572 
2573         SubtableStart = *PFieldList;
2574         Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmatHdr,
2575             &Subtable);
2576         if (ACPI_FAILURE (Status))
2577         {
2578             return (Status);
2579         }
2580         DtInsertSubtable (ParentTable, Subtable);
2581 
2582         HmatStruct = ACPI_CAST_PTR (ACPI_HMAT_STRUCTURE, Subtable->Buffer);
2583         HmatStruct->Length = Subtable->Length;
2584 
2585         /* Compile HMAT structure body */
2586 
2587         switch (HmatStruct->Type)
2588         {
2589         case ACPI_HMAT_TYPE_ADDRESS_RANGE:
2590 
2591             InfoTable = AcpiDmTableInfoHmat0;
2592             break;
2593 
2594         case ACPI_HMAT_TYPE_LOCALITY:
2595 
2596             InfoTable = AcpiDmTableInfoHmat1;
2597             break;
2598 
2599         case ACPI_HMAT_TYPE_CACHE:
2600 
2601             InfoTable = AcpiDmTableInfoHmat2;
2602             break;
2603 
2604         default:
2605 
2606             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HMAT");
2607             return (AE_ERROR);
2608         }
2609 
2610         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
2611         if (ACPI_FAILURE (Status))
2612         {
2613             return (Status);
2614         }
2615         DtInsertSubtable (ParentTable, Subtable);
2616         HmatStruct->Length += Subtable->Length;
2617 
2618         /* Compile HMAT structure additional */
2619 
2620         switch (HmatStruct->Type)
2621         {
2622         case ACPI_HMAT_TYPE_LOCALITY:
2623 
2624             HmatLocality = ACPI_SUB_PTR (ACPI_HMAT_LOCALITY,
2625                 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
2626 
2627             /* Compile initiator proximity domain list */
2628 
2629             IntPDNumber = 0;
2630             while (*PFieldList)
2631             {
2632                 Status = DtCompileTable (PFieldList,
2633                     AcpiDmTableInfoHmat1a, &Subtable);
2634                 if (ACPI_FAILURE (Status))
2635                 {
2636                     return (Status);
2637                 }
2638                 if (!Subtable)
2639                 {
2640                     break;
2641                 }
2642                 DtInsertSubtable (ParentTable, Subtable);
2643                 HmatStruct->Length += Subtable->Length;
2644                 IntPDNumber++;
2645             }
2646             HmatLocality->NumberOfInitiatorPDs = IntPDNumber;
2647 
2648             /* Compile target proximity domain list */
2649 
2650             TgtPDNumber = 0;
2651             while (*PFieldList)
2652             {
2653                 Status = DtCompileTable (PFieldList,
2654                     AcpiDmTableInfoHmat1b, &Subtable);
2655                 if (ACPI_FAILURE (Status))
2656                 {
2657                     return (Status);
2658                 }
2659                 if (!Subtable)
2660                 {
2661                     break;
2662                 }
2663                 DtInsertSubtable (ParentTable, Subtable);
2664                 HmatStruct->Length += Subtable->Length;
2665                 TgtPDNumber++;
2666             }
2667             HmatLocality->NumberOfTargetPDs = TgtPDNumber;
2668 
2669             /* Save start of the entries for reporting errors */
2670 
2671             EntryStart = *PFieldList;
2672 
2673             /* Compile latency/bandwidth entries */
2674 
2675             EntryNumber = 0;
2676             while (*PFieldList)
2677             {
2678                 Status = DtCompileTable (PFieldList,
2679                     AcpiDmTableInfoHmat1c, &Subtable);
2680                 if (ACPI_FAILURE (Status))
2681                 {
2682                     return (Status);
2683                 }
2684                 if (!Subtable)
2685                 {
2686                     break;
2687                 }
2688                 DtInsertSubtable (ParentTable, Subtable);
2689                 HmatStruct->Length += Subtable->Length;
2690                 EntryNumber++;
2691             }
2692 
2693             /* Validate number of entries */
2694 
2695             if (EntryNumber !=
2696                 ((UINT64)IntPDNumber * (UINT64)TgtPDNumber))
2697             {
2698                 DtFatal (ASL_MSG_INVALID_EXPRESSION, EntryStart, "HMAT");
2699                 return (AE_ERROR);
2700             }
2701             break;
2702 
2703         case ACPI_HMAT_TYPE_CACHE:
2704 
2705             /* Compile SMBIOS handles */
2706 
2707             HmatCache = ACPI_SUB_PTR (ACPI_HMAT_CACHE,
2708                 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
2709             SMBIOSHandleNumber = 0;
2710             while (*PFieldList)
2711             {
2712                 Status = DtCompileTable (PFieldList,
2713                     AcpiDmTableInfoHmat2a, &Subtable);
2714                 if (ACPI_FAILURE (Status))
2715                 {
2716                     return (Status);
2717                 }
2718                 if (!Subtable)
2719                 {
2720                     break;
2721                 }
2722                 DtInsertSubtable (ParentTable, Subtable);
2723                 HmatStruct->Length += Subtable->Length;
2724                 SMBIOSHandleNumber++;
2725             }
2726             HmatCache->NumberOfSMBIOSHandles = SMBIOSHandleNumber;
2727             break;
2728 
2729         default:
2730 
2731             break;
2732         }
2733     }
2734 
2735     return (AE_OK);
2736 }
2737 
2738 
2739 /******************************************************************************
2740  *
2741  * FUNCTION:    DtCompileIort
2742  *
2743  * PARAMETERS:  List                - Current field list pointer
2744  *
2745  * RETURN:      Status
2746  *
2747  * DESCRIPTION: Compile IORT.
2748  *
2749  *****************************************************************************/
2750 
2751 ACPI_STATUS
DtCompileIort(void ** List)2752 DtCompileIort (
2753     void                    **List)
2754 {
2755     ACPI_STATUS             Status;
2756     DT_SUBTABLE             *Subtable;
2757     DT_SUBTABLE             *ParentTable;
2758     DT_FIELD                **PFieldList = (DT_FIELD **) List;
2759     DT_FIELD                *SubtableStart;
2760     ACPI_TABLE_HEADER       *Table;
2761     ACPI_TABLE_IORT         *Iort;
2762     ACPI_IORT_NODE          *IortNode;
2763     ACPI_IORT_ITS_GROUP     *IortItsGroup;
2764     ACPI_IORT_SMMU          *IortSmmu;
2765     ACPI_IORT_RMR           *IortRmr;
2766     UINT32                  NodeNumber;
2767     UINT32                  NodeLength;
2768     UINT32                  IdMappingNumber;
2769     UINT32                  ItsNumber;
2770     UINT32                  ContextIrptNumber;
2771     UINT32                  PmuIrptNumber;
2772     UINT32                  PaddingLength;
2773     UINT8                   Revision;
2774     UINT32                  RmrCount;
2775 
2776 
2777     ParentTable = DtPeekSubtable ();
2778 
2779     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort,
2780         &Subtable);
2781     if (ACPI_FAILURE (Status))
2782     {
2783         return (Status);
2784     }
2785     DtInsertSubtable (ParentTable, Subtable);
2786 
2787     Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer);
2788     Revision = Table->Revision;
2789 
2790     /* IORT Revisions E, E.a & E.c have known issues and are not supported */
2791 
2792     if (Revision == 1 || Revision == 2 || Revision == 4)
2793     {
2794         DtError (ASL_ERROR, ASL_MSG_UNSUPPORTED, NULL, "IORT table revision");
2795         return (AE_ERROR);
2796     }
2797 
2798     /*
2799      * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
2800      * should be taken to avoid accessing ACPI_TABLE_HEADER fields.
2801      */
2802     Iort = ACPI_SUB_PTR (ACPI_TABLE_IORT,
2803         Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
2804 
2805     /*
2806      * OptionalPadding - Variable-length data
2807      * (Optional, size = OffsetToNodes - sizeof (ACPI_TABLE_IORT))
2808      * Optionally allows the generic data types to be used for filling
2809      * this field.
2810      */
2811     Iort->NodeOffset = sizeof (ACPI_TABLE_IORT);
2812     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortPad,
2813         &Subtable);
2814     if (ACPI_FAILURE (Status))
2815     {
2816         return (Status);
2817     }
2818     if (Subtable)
2819     {
2820         DtInsertSubtable (ParentTable, Subtable);
2821         Iort->NodeOffset += Subtable->Length;
2822     }
2823     else
2824     {
2825         Status = DtCompileGeneric (ACPI_CAST_PTR (void *, PFieldList),
2826             AcpiDmTableInfoIortHdr[0].Name, &PaddingLength);
2827         if (ACPI_FAILURE (Status))
2828         {
2829             return (Status);
2830         }
2831         Iort->NodeOffset += PaddingLength;
2832     }
2833 
2834     NodeNumber = 0;
2835     while (*PFieldList)
2836     {
2837         SubtableStart = *PFieldList;
2838         if (Revision == 0)
2839         {
2840             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr,
2841                 &Subtable);
2842         }
2843         else if (Revision >= 3)
2844         {
2845             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr3,
2846                 &Subtable);
2847         }
2848 
2849         if (ACPI_FAILURE (Status))
2850         {
2851             return (Status);
2852         }
2853 
2854         DtInsertSubtable (ParentTable, Subtable);
2855         IortNode = ACPI_CAST_PTR (ACPI_IORT_NODE, Subtable->Buffer);
2856         NodeLength = ACPI_OFFSET (ACPI_IORT_NODE, NodeData);
2857 
2858         DtPushSubtable (Subtable);
2859         ParentTable = DtPeekSubtable ();
2860 
2861         switch (IortNode->Type)
2862         {
2863         case ACPI_IORT_NODE_ITS_GROUP:
2864 
2865             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0,
2866                 &Subtable);
2867             if (ACPI_FAILURE (Status))
2868             {
2869                 return (Status);
2870             }
2871 
2872             DtInsertSubtable (ParentTable, Subtable);
2873             IortItsGroup = ACPI_CAST_PTR (ACPI_IORT_ITS_GROUP, Subtable->Buffer);
2874             NodeLength += Subtable->Length;
2875 
2876             ItsNumber = 0;
2877             while (*PFieldList)
2878             {
2879                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0a,
2880                     &Subtable);
2881                 if (ACPI_FAILURE (Status))
2882                 {
2883                     return (Status);
2884                 }
2885                 if (!Subtable)
2886                 {
2887                     break;
2888                 }
2889 
2890                 DtInsertSubtable (ParentTable, Subtable);
2891                 NodeLength += Subtable->Length;
2892                 ItsNumber++;
2893             }
2894 
2895             IortItsGroup->ItsCount = ItsNumber;
2896             break;
2897 
2898         case ACPI_IORT_NODE_NAMED_COMPONENT:
2899 
2900             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1,
2901                 &Subtable);
2902             if (ACPI_FAILURE (Status))
2903             {
2904                 return (Status);
2905             }
2906 
2907             DtInsertSubtable (ParentTable, Subtable);
2908             NodeLength += Subtable->Length;
2909 
2910             /*
2911              * Padding - Variable-length data
2912              * Optionally allows the offset of the ID mappings to be used
2913              * for filling this field.
2914              */
2915             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1a,
2916                 &Subtable);
2917             if (ACPI_FAILURE (Status))
2918             {
2919                 return (Status);
2920             }
2921 
2922             if (Subtable)
2923             {
2924                 DtInsertSubtable (ParentTable, Subtable);
2925                 NodeLength += Subtable->Length;
2926             }
2927             else
2928             {
2929                 if (NodeLength > IortNode->MappingOffset)
2930                 {
2931                     return (AE_BAD_DATA);
2932                 }
2933 
2934                 if (NodeLength < IortNode->MappingOffset)
2935                 {
2936                     Status = DtCompilePadding (
2937                         IortNode->MappingOffset - NodeLength,
2938                         &Subtable);
2939                     if (ACPI_FAILURE (Status))
2940                     {
2941                         return (Status);
2942                     }
2943 
2944                     DtInsertSubtable (ParentTable, Subtable);
2945                     NodeLength = IortNode->MappingOffset;
2946                 }
2947             }
2948             break;
2949 
2950         case ACPI_IORT_NODE_PCI_ROOT_COMPLEX:
2951 
2952             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort2,
2953                 &Subtable);
2954             if (ACPI_FAILURE (Status))
2955             {
2956                 return (Status);
2957             }
2958 
2959             DtInsertSubtable (ParentTable, Subtable);
2960             NodeLength += Subtable->Length;
2961             break;
2962 
2963         case ACPI_IORT_NODE_SMMU:
2964 
2965             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3,
2966                 &Subtable);
2967             if (ACPI_FAILURE (Status))
2968             {
2969                 return (Status);
2970             }
2971 
2972             DtInsertSubtable (ParentTable, Subtable);
2973             IortSmmu = ACPI_CAST_PTR (ACPI_IORT_SMMU, Subtable->Buffer);
2974             NodeLength += Subtable->Length;
2975 
2976             /* Compile global interrupt array */
2977 
2978             IortSmmu->GlobalInterruptOffset = NodeLength;
2979             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3a,
2980                 &Subtable);
2981             if (ACPI_FAILURE (Status))
2982             {
2983                 return (Status);
2984             }
2985 
2986             DtInsertSubtable (ParentTable, Subtable);
2987             NodeLength += Subtable->Length;
2988 
2989             /* Compile context interrupt array */
2990 
2991             ContextIrptNumber = 0;
2992             IortSmmu->ContextInterruptOffset = NodeLength;
2993             while (*PFieldList)
2994             {
2995                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3b,
2996                     &Subtable);
2997                 if (ACPI_FAILURE (Status))
2998                 {
2999                     return (Status);
3000                 }
3001 
3002                 if (!Subtable)
3003                 {
3004                     break;
3005                 }
3006 
3007                 DtInsertSubtable (ParentTable, Subtable);
3008                 NodeLength += Subtable->Length;
3009                 ContextIrptNumber++;
3010             }
3011 
3012             IortSmmu->ContextInterruptCount = ContextIrptNumber;
3013 
3014             /* Compile PMU interrupt array */
3015 
3016             PmuIrptNumber = 0;
3017             IortSmmu->PmuInterruptOffset = NodeLength;
3018             while (*PFieldList)
3019             {
3020                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3c,
3021                     &Subtable);
3022                 if (ACPI_FAILURE (Status))
3023                 {
3024                     return (Status);
3025                 }
3026 
3027                 if (!Subtable)
3028                 {
3029                     break;
3030                 }
3031 
3032                 DtInsertSubtable (ParentTable, Subtable);
3033                 NodeLength += Subtable->Length;
3034                 PmuIrptNumber++;
3035             }
3036 
3037             IortSmmu->PmuInterruptCount = PmuIrptNumber;
3038             break;
3039 
3040         case ACPI_IORT_NODE_SMMU_V3:
3041 
3042             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort4,
3043                 &Subtable);
3044             if (ACPI_FAILURE (Status))
3045             {
3046                 return (Status);
3047             }
3048 
3049             DtInsertSubtable (ParentTable, Subtable);
3050             NodeLength += Subtable->Length;
3051             break;
3052 
3053         case ACPI_IORT_NODE_PMCG:
3054 
3055             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort5,
3056                 &Subtable);
3057             if (ACPI_FAILURE (Status))
3058             {
3059                 return (Status);
3060             }
3061 
3062             DtInsertSubtable (ParentTable, Subtable);
3063             NodeLength += Subtable->Length;
3064             break;
3065 
3066         case ACPI_IORT_NODE_RMR:
3067 
3068             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6,
3069                 &Subtable);
3070             if (ACPI_FAILURE (Status))
3071             {
3072                 return (Status);
3073             }
3074 
3075             DtInsertSubtable (ParentTable, Subtable);
3076             IortRmr = ACPI_CAST_PTR (ACPI_IORT_RMR, Subtable->Buffer);
3077             NodeLength += Subtable->Length;
3078 
3079             /* Compile RMR Descriptors */
3080 
3081             RmrCount = 0;
3082             IortRmr->RmrOffset = NodeLength;
3083             while (*PFieldList)
3084             {
3085                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6a,
3086                     &Subtable);
3087                 if (ACPI_FAILURE (Status))
3088                 {
3089                     return (Status);
3090                 }
3091 
3092                 if (!Subtable)
3093                 {
3094                     break;
3095                 }
3096 
3097                 DtInsertSubtable (ParentTable, Subtable);
3098                 NodeLength += sizeof (ACPI_IORT_RMR_DESC);
3099                 RmrCount++;
3100             }
3101 
3102             IortRmr->RmrCount = RmrCount;
3103             break;
3104 
3105         case ACPI_IORT_NODE_IWB:
3106 
3107             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort7,
3108                 &Subtable);
3109             if (ACPI_FAILURE (Status))
3110             {
3111                 return (Status);
3112             }
3113 
3114             DtInsertSubtable (ParentTable, Subtable);
3115             NodeLength += Subtable->Length;
3116             break;
3117 
3118         default:
3119 
3120             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IORT");
3121             return (AE_ERROR);
3122         }
3123 
3124         /* Compile Array of ID mappings */
3125 
3126         IortNode->MappingOffset = NodeLength;
3127         IdMappingNumber = 0;
3128         while (*PFieldList)
3129         {
3130             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortMap,
3131                 &Subtable);
3132             if (ACPI_FAILURE (Status))
3133             {
3134                 return (Status);
3135             }
3136 
3137             if (!Subtable)
3138             {
3139                 break;
3140             }
3141 
3142             DtInsertSubtable (ParentTable, Subtable);
3143             NodeLength += sizeof (ACPI_IORT_ID_MAPPING);
3144             IdMappingNumber++;
3145         }
3146 
3147         IortNode->MappingCount = IdMappingNumber;
3148         if (!IdMappingNumber)
3149         {
3150             IortNode->MappingOffset = 0;
3151         }
3152 
3153         /*
3154          * Node length can be determined by DT_LENGTH option
3155          * IortNode->Length = NodeLength;
3156          */
3157         DtPopSubtable ();
3158         ParentTable = DtPeekSubtable ();
3159         NodeNumber++;
3160     }
3161 
3162     Iort->NodeCount = NodeNumber;
3163     return (AE_OK);
3164 }
3165 
3166 
3167 /******************************************************************************
3168  *
3169  * FUNCTION:    DtCompileIovt
3170  *
3171  * PARAMETERS:  List                - Current field list pointer
3172  *
3173  * RETURN:      Status
3174  *
3175  * DESCRIPTION: Compile Iovt. Notes:
3176  *              The IOVT is essentially a flat table, with the following
3177  *              structure:
3178  *              <Main ACPI Table Header>
3179  *              <Main subtable - virtualization info>
3180  *              <IOVT>
3181  *                  <Device Entries>
3182  *              ...
3183  *              <IOVT>
3184  *              <IOVT>
3185  *              ...
3186  *
3187  *****************************************************************************/
3188 
3189 ACPI_STATUS
DtCompileIovt(void ** List)3190 DtCompileIovt (
3191     void                    **List)
3192 {
3193     ACPI_STATUS             Status;
3194     DT_SUBTABLE             *Subtable;
3195     DT_SUBTABLE             *ParentTable;
3196     DT_FIELD                **PFieldList = (DT_FIELD **) List;
3197     ACPI_TABLE_IOVT         *Iovt;
3198     UINT16                  IommuCount;
3199     ACPI_IOVT_IOMMU         *Iommu;
3200     UINT32                  DeviceEntryNum;
3201 
3202 
3203     ParentTable = DtPeekSubtable ();
3204     /* Main table */
3205 
3206     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIovt,
3207         &Subtable);
3208     if (ACPI_FAILURE (Status))
3209     {
3210         return (Status);
3211     }
3212 
3213     DtInsertSubtable (ParentTable, Subtable);
3214     DtPushSubtable (Subtable);
3215 
3216     Iovt = ACPI_SUB_PTR (ACPI_TABLE_IOVT, Subtable->Buffer,
3217         sizeof (ACPI_TABLE_HEADER));
3218 
3219     for (IommuCount = 0; IommuCount < Iovt->IommuCount; IommuCount++)
3220     {
3221         Status = DtCompileTable (PFieldList, AcpiDmTableInfoIovt0,
3222             &Subtable);
3223         if (ACPI_FAILURE (Status))
3224         {
3225             return (Status);
3226         }
3227 
3228         ParentTable = DtPeekSubtable ();
3229         DtInsertSubtable (ParentTable, Subtable);
3230         DtPushSubtable (Subtable);
3231 
3232         Iommu = ACPI_CAST_PTR(ACPI_IOVT_IOMMU, Subtable->Buffer);
3233         for (DeviceEntryNum = 0; DeviceEntryNum < Iommu->DeviceEntryNum; DeviceEntryNum++)
3234         {
3235             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIovtdev,
3236                 &Subtable);
3237             if (ACPI_FAILURE (Status))
3238             {
3239                 return (Status);
3240             }
3241 
3242             ParentTable = DtPeekSubtable ();
3243             DtInsertSubtable (ParentTable, Subtable);
3244         }
3245         DtPopSubtable();
3246     }
3247 
3248     return (AE_OK);
3249 }
3250 
3251 
3252 /******************************************************************************
3253  *
3254  * FUNCTION:    DtCompileIvrs
3255  *
3256  * PARAMETERS:  List                - Current field list pointer
3257  *
3258  * RETURN:      Status
3259  *
3260  * DESCRIPTION: Compile IVRS. Notes:
3261  *              The IVRS is essentially a flat table, with the following
3262  *              structure:
3263  *              <Main ACPI Table Header>
3264  *              <Main subtable - virtualization info>
3265  *              <IVHD>
3266  *                  <Device Entries>
3267  *              ...
3268  *              <IVHD>
3269  *                  <Device Entries>
3270  *              <IVMD>
3271  *              ...
3272  *
3273  *****************************************************************************/
3274 
3275 ACPI_STATUS
DtCompileIvrs(void ** List)3276 DtCompileIvrs (
3277     void                    **List)
3278 {
3279     ACPI_STATUS             Status;
3280     DT_SUBTABLE             *Subtable;
3281     DT_SUBTABLE             *ParentTable;
3282     DT_SUBTABLE             *MainSubtable;
3283     DT_FIELD                **PFieldList = (DT_FIELD **) List;
3284     DT_FIELD                *SubtableStart;
3285     ACPI_DMTABLE_INFO       *InfoTable = NULL;
3286     UINT8                   SubtableType;
3287     UINT8                   Temp64[16];
3288     UINT8                   Temp8;
3289 
3290 
3291     /* Main table */
3292 
3293     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrs,
3294         &Subtable);
3295     if (ACPI_FAILURE (Status))
3296     {
3297         return (Status);
3298     }
3299 
3300     ParentTable = DtPeekSubtable ();
3301     DtInsertSubtable (ParentTable, Subtable);
3302     DtPushSubtable (Subtable);
3303 
3304     /* Save a pointer to the main subtable */
3305 
3306     MainSubtable = Subtable;
3307 
3308     while (*PFieldList)
3309     {
3310         SubtableStart = *PFieldList;
3311 
3312         /* Compile the SubtableType integer */
3313 
3314         DtCompileInteger (&SubtableType, *PFieldList, 1, 0);
3315 
3316         switch (SubtableType)
3317         {
3318 
3319         /* Type 10h, IVHD (I/O Virtualization Hardware Definition) */
3320 
3321         case ACPI_IVRS_TYPE_HARDWARE1:
3322 
3323             InfoTable = AcpiDmTableInfoIvrsHware1;
3324             break;
3325 
3326         /* Types 11h, 40h, IVHD (I/O Virtualization Hardware Definition) */
3327 
3328         case ACPI_IVRS_TYPE_HARDWARE2:
3329         case ACPI_IVRS_TYPE_HARDWARE3:
3330 
3331             InfoTable = AcpiDmTableInfoIvrsHware23;
3332             break;
3333 
3334         /* Types 20h, 21h, 22h, IVMD (I/O Virtualization Memory Definition Block) */
3335 
3336         case ACPI_IVRS_TYPE_MEMORY1:
3337         case ACPI_IVRS_TYPE_MEMORY2:
3338         case ACPI_IVRS_TYPE_MEMORY3:
3339 
3340             InfoTable = AcpiDmTableInfoIvrsMemory;
3341             break;
3342 
3343         /* 4-byte device entries */
3344 
3345         case ACPI_IVRS_TYPE_PAD4:
3346         case ACPI_IVRS_TYPE_ALL:
3347         case ACPI_IVRS_TYPE_SELECT:
3348         case ACPI_IVRS_TYPE_START:
3349         case ACPI_IVRS_TYPE_END:
3350 
3351             InfoTable = AcpiDmTableInfoIvrs4;
3352             break;
3353 
3354         /* 8-byte device entries, type A */
3355 
3356         case ACPI_IVRS_TYPE_ALIAS_SELECT:
3357         case ACPI_IVRS_TYPE_ALIAS_START:
3358 
3359             InfoTable = AcpiDmTableInfoIvrs8a;
3360             break;
3361 
3362         /* 8-byte device entries, type B */
3363 
3364         case ACPI_IVRS_TYPE_EXT_SELECT:
3365         case ACPI_IVRS_TYPE_EXT_START:
3366 
3367             InfoTable = AcpiDmTableInfoIvrs8b;
3368             break;
3369 
3370         /* 8-byte device entries, type C */
3371 
3372         case ACPI_IVRS_TYPE_SPECIAL:
3373 
3374             InfoTable = AcpiDmTableInfoIvrs8c;
3375             break;
3376 
3377         /* Variable device entries, type F0h */
3378 
3379         case ACPI_IVRS_TYPE_HID:
3380 
3381             InfoTable = AcpiDmTableInfoIvrsHid;
3382             break;
3383 
3384         default:
3385 
3386             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart,
3387                 "IVRS Device Entry");
3388             return (AE_ERROR);
3389         }
3390 
3391         /* Compile the InfoTable from above */
3392 
3393         Status = DtCompileTable (PFieldList, InfoTable,
3394             &Subtable);
3395         if (ACPI_FAILURE (Status))
3396         {
3397             return (Status);
3398         }
3399 
3400         ParentTable = DtPeekSubtable ();
3401         if (SubtableType != ACPI_IVRS_TYPE_HARDWARE1 &&
3402             SubtableType != ACPI_IVRS_TYPE_HARDWARE2 &&
3403             SubtableType != ACPI_IVRS_TYPE_HARDWARE3 &&
3404             SubtableType != ACPI_IVRS_TYPE_HID &&
3405             SubtableType != ACPI_IVRS_TYPE_MEMORY1 &&
3406             SubtableType != ACPI_IVRS_TYPE_MEMORY2 &&
3407             SubtableType != ACPI_IVRS_TYPE_MEMORY3)
3408         {
3409             if (ParentTable)
3410                 DtInsertSubtable (ParentTable, Subtable);
3411         }
3412 
3413         switch (SubtableType)
3414         {
3415         case ACPI_IVRS_TYPE_HARDWARE1:
3416         case ACPI_IVRS_TYPE_HARDWARE2:
3417         case ACPI_IVRS_TYPE_HARDWARE3:
3418         case ACPI_IVRS_TYPE_MEMORY1:
3419         case ACPI_IVRS_TYPE_MEMORY2:
3420         case ACPI_IVRS_TYPE_MEMORY3:
3421 
3422             /* Insert these IVHDs/IVMDs at the root subtable */
3423 
3424             DtInsertSubtable (MainSubtable, Subtable);
3425             DtPushSubtable (Subtable);
3426             break;
3427 
3428         case ACPI_IVRS_TYPE_HID:
3429 
3430             /* Special handling for the HID named device entry (0xF0) */
3431 
3432             if (ParentTable)
3433             {
3434                 DtInsertSubtable (ParentTable, Subtable);
3435             }
3436 
3437             /*
3438              * Process the HID value. First, get the HID value as a string.
3439              */
3440             DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0);
3441 
3442                /*
3443                 * Determine if the HID is an integer or a string.
3444                 * An integer is defined to be 32 bits, with the upper 32 bits
3445                 * set to zero. (from the ACPI Spec): "The HID can be a 32-bit
3446                 * integer or a character string. If an integer, the lower
3447                 * 4 bytes of the field contain the integer and the upper
3448                 * 4 bytes are padded with 0".
3449                 */
3450             if (UtIsIdInteger ((UINT8 *) &Temp64))
3451             {
3452                 /* Compile the HID value as an integer */
3453 
3454                 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0);
3455 
3456                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidInteger,
3457                     &Subtable);
3458                 if (ACPI_FAILURE (Status))
3459                 {
3460                     return (Status);
3461                 }
3462             }
3463             else
3464             {
3465                 /* Compile the HID value as a string */
3466 
3467                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidString,
3468                     &Subtable);
3469                 if (ACPI_FAILURE (Status))
3470                 {
3471                     return (Status);
3472                 }
3473             }
3474 
3475             DtInsertSubtable (ParentTable, Subtable);
3476 
3477             /*
3478              * Process the CID value. First, get the CID value as a string.
3479              */
3480             DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0);
3481 
3482             if (UtIsIdInteger ((UINT8 *) &Temp64))
3483             {
3484                 /* Compile the CID value as an integer */
3485 
3486                 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0);
3487 
3488                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidInteger,
3489                     &Subtable);
3490                 if (ACPI_FAILURE (Status))
3491                 {
3492                     return (Status);
3493                 }
3494             }
3495             else
3496             {
3497                 /* Compile the CID value as a string */
3498 
3499                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidString,
3500                     &Subtable);
3501                 if (ACPI_FAILURE (Status))
3502                 {
3503                     return (Status);
3504                 }
3505             }
3506 
3507             DtInsertSubtable (ParentTable, Subtable);
3508 
3509             /*
3510              * Process the UID value. First, get and decode the "UID Format" field (Integer).
3511              */
3512             if (!*PFieldList)
3513             {
3514                 return (AE_OK);
3515             }
3516 
3517             DtCompileOneField (&Temp8, *PFieldList, 1, DT_FIELD_TYPE_INTEGER, 0);
3518 
3519             switch (Temp8)
3520             {
3521             case ACPI_IVRS_UID_NOT_PRESENT:
3522                 break;
3523 
3524             case ACPI_IVRS_UID_IS_INTEGER:
3525 
3526                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidInteger,
3527                     &Subtable);
3528                 if (ACPI_FAILURE (Status))
3529                 {
3530                     return (Status);
3531                 }
3532                 DtInsertSubtable (ParentTable, Subtable);
3533                 break;
3534 
3535             case ACPI_IVRS_UID_IS_STRING:
3536 
3537                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidString,
3538                     &Subtable);
3539                 if (ACPI_FAILURE (Status))
3540                 {
3541                     return (Status);
3542                 }
3543                 DtInsertSubtable (ParentTable, Subtable);
3544                 break;
3545 
3546             default:
3547 
3548                 DtFatal (ASL_MSG_UNKNOWN_FORMAT, SubtableStart,
3549                     "IVRS Device Entry");
3550                 return (AE_ERROR);
3551             }
3552 
3553         default:
3554 
3555             /* All other subtable types come through here */
3556             break;
3557         }
3558     }
3559 
3560     return (AE_OK);
3561 }
3562 
3563 
3564 /******************************************************************************
3565  *
3566  * FUNCTION:    DtCompileRimt
3567  *
3568  * PARAMETERS:  List                - Current field list pointer
3569  *
3570  * RETURN:      Status
3571  *
3572  * DESCRIPTION: Compile RIMT.
3573  *
3574  *****************************************************************************/
3575 
3576 ACPI_STATUS
DtCompileRimt(void ** List)3577 DtCompileRimt (
3578     void                    **List)
3579 {
3580     ACPI_RIMT_PLATFORM_DEVICE  *PlatDevNode;
3581     ACPI_RIMT_PCIE_RC          *PcieRcNode;
3582     ACPI_TABLE_RIMT            *Rimt;
3583     ACPI_RIMT_IOMMU            *IommuNode;
3584     ACPI_RIMT_NODE             *RimtNode;
3585     ACPI_STATUS                Status;
3586     DT_SUBTABLE                *Subtable;
3587     DT_SUBTABLE                *ParentTable;
3588     DT_FIELD                   **PFieldList = (DT_FIELD **) List;
3589     DT_FIELD                   *SubtableStart;
3590     UINT32                     NodeNumber;
3591     UINT32                     NodeLength;
3592     UINT16                     IdMappingNumber;
3593     UINT32                     i;
3594 
3595 
3596     ParentTable = DtPeekSubtable ();
3597 
3598     Status = DtCompileTable (PFieldList, AcpiDmTableInfoRimt, &Subtable);
3599     if (ACPI_FAILURE (Status))
3600     {
3601         return (Status);
3602     }
3603 
3604     DtInsertSubtable (ParentTable, Subtable);
3605 
3606     /*
3607      * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
3608      * should be taken to avoid accessing ACPI_TABLE_HEADER fields.
3609      */
3610     Rimt = ACPI_SUB_PTR (ACPI_TABLE_RIMT, Subtable->Buffer,
3611                          sizeof (ACPI_TABLE_HEADER));
3612 
3613     NodeNumber = 0;
3614     while (*PFieldList)
3615     {
3616         SubtableStart = *PFieldList;
3617         Status = DtCompileTable (PFieldList, AcpiDmTableInfoRimtNodeHdr, &Subtable);
3618 
3619         if (ACPI_FAILURE (Status))
3620         {
3621             return (Status);
3622         }
3623 
3624         DtInsertSubtable (ParentTable, Subtable);
3625         RimtNode = ACPI_CAST_PTR (ACPI_RIMT_NODE, Subtable->Buffer);
3626         NodeLength = ACPI_OFFSET (ACPI_RIMT_NODE, NodeData);
3627 
3628         DtPushSubtable (Subtable);
3629         ParentTable = DtPeekSubtable ();
3630 
3631         switch (RimtNode->Type)
3632         {
3633         case ACPI_RIMT_NODE_TYPE_IOMMU:
3634 
3635             Status = DtCompileTable (PFieldList, AcpiDmTableInfoRimtIommu,
3636                                      &Subtable);
3637             if (ACPI_FAILURE (Status))
3638             {
3639                 return (Status);
3640             }
3641 
3642             IommuNode = ACPI_CAST_PTR (ACPI_RIMT_IOMMU, Subtable->Buffer);
3643             DtInsertSubtable (ParentTable, Subtable);
3644             NodeLength += Subtable->Length;
3645 
3646             for (i = 0; i < IommuNode->NumInterruptWires; i++)
3647             {
3648                 while (*PFieldList)
3649                 {
3650                     Status = DtCompileTable (PFieldList,
3651                                              AcpiDmTableInfoRimtIommuWire,
3652                                              &Subtable);
3653                     if (ACPI_FAILURE (Status))
3654                     {
3655                         return (Status);
3656                     }
3657                     if (!Subtable)
3658                     {
3659                         break;
3660                     }
3661 
3662                     DtInsertSubtable (ParentTable, Subtable);
3663                     NodeLength += Subtable->Length;
3664                 }
3665             }
3666 
3667             break;
3668 
3669         case ACPI_RIMT_NODE_TYPE_PCIE_ROOT_COMPLEX:
3670 
3671             Status = DtCompileTable (PFieldList, AcpiDmTableInfoRimtPcieRc,
3672                                      &Subtable);
3673             if (ACPI_FAILURE (Status))
3674             {
3675                 return (Status);
3676             }
3677 
3678             DtInsertSubtable (ParentTable, Subtable);
3679             PcieRcNode = ACPI_CAST_PTR (ACPI_RIMT_PCIE_RC, Subtable->Buffer);
3680             NodeLength += Subtable->Length;
3681 
3682             /* Compile Array of ID mappings */
3683 
3684             PcieRcNode->IdMappingOffset = (UINT16) NodeLength;
3685             IdMappingNumber = 0;
3686             while (*PFieldList)
3687             {
3688                 Status = DtCompileTable (PFieldList,
3689                                          AcpiDmTableInfoRimtIdMapping,
3690                                          &Subtable);
3691                 if (ACPI_FAILURE (Status))
3692                 {
3693                     return (Status);
3694                 }
3695 
3696                 if (!Subtable)
3697                 {
3698                     break;
3699                 }
3700 
3701                 DtInsertSubtable (ParentTable, Subtable);
3702                 NodeLength += sizeof (ACPI_RIMT_ID_MAPPING);
3703                 IdMappingNumber++;
3704             }
3705 
3706             PcieRcNode->NumIdMappings = IdMappingNumber;
3707             if (!IdMappingNumber)
3708             {
3709                 PcieRcNode->IdMappingOffset = 0;
3710             }
3711 
3712             break;
3713 
3714         case ACPI_RIMT_NODE_TYPE_PLAT_DEVICE:
3715 
3716             Status = DtCompileTable (PFieldList, AcpiDmTableInfoRimtPlatDev,
3717                                      &Subtable);
3718             if (ACPI_FAILURE (Status))
3719             {
3720                 return (Status);
3721             }
3722 
3723             DtInsertSubtable (ParentTable, Subtable);
3724             PlatDevNode = ACPI_CAST_PTR (ACPI_RIMT_PLATFORM_DEVICE, Subtable->Buffer);
3725             NodeLength += Subtable->Length;
3726 
3727             /*
3728              * Padding - Variable-length data
3729              * Optionally allows the offset of the ID mappings to be used
3730              * for filling this field.
3731              */
3732             Status = DtCompileTable (PFieldList, AcpiDmTableInfoRimtPlatDevPad,
3733                                      &Subtable);
3734             if (ACPI_FAILURE (Status))
3735             {
3736                 return (Status);
3737             }
3738 
3739             if (Subtable)
3740             {
3741                 DtInsertSubtable (ParentTable, Subtable);
3742                 NodeLength += Subtable->Length;
3743             }
3744             else
3745             {
3746                 if (NodeLength > PlatDevNode->IdMappingOffset)
3747                 {
3748                     return (AE_BAD_DATA);
3749                 }
3750 
3751                 if (NodeLength < PlatDevNode->IdMappingOffset)
3752                 {
3753                     Status = DtCompilePadding (
3754                         PlatDevNode->IdMappingOffset - (UINT16) NodeLength,
3755                         &Subtable);
3756                     if (ACPI_FAILURE (Status))
3757                     {
3758                         return (Status);
3759                     }
3760 
3761                     DtInsertSubtable (ParentTable, Subtable);
3762                     NodeLength = PlatDevNode->IdMappingOffset;
3763                 }
3764             }
3765 
3766             /* Compile Array of ID mappings */
3767 
3768             PlatDevNode->IdMappingOffset = (UINT16) NodeLength;
3769             IdMappingNumber = 0;
3770             while (*PFieldList)
3771             {
3772                 Status = DtCompileTable (PFieldList,
3773                                          AcpiDmTableInfoRimtIdMapping,
3774                                          &Subtable);
3775                 if (ACPI_FAILURE (Status))
3776                 {
3777                     return (Status);
3778                 }
3779 
3780                 if (!Subtable)
3781                 {
3782                     break;
3783                 }
3784 
3785                 DtInsertSubtable (ParentTable, Subtable);
3786                 NodeLength += sizeof (ACPI_RIMT_ID_MAPPING);
3787                 IdMappingNumber++;
3788             }
3789 
3790             PlatDevNode->NumIdMappings = IdMappingNumber;
3791             if (!IdMappingNumber)
3792             {
3793                 PlatDevNode->IdMappingOffset = 0;
3794             }
3795 
3796             break;
3797 
3798 
3799         default:
3800 
3801             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "RIMT");
3802             return (AE_ERROR);
3803         }
3804 
3805         DtPopSubtable ();
3806         ParentTable = DtPeekSubtable ();
3807         NodeNumber++;
3808     }
3809 
3810     Rimt->NumNodes = NodeNumber;
3811     return (AE_OK);
3812 }
3813