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