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 - 2026, 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:    DtCompileDtpr
   1624  *
   1625  * PARAMETERS:  List                - Current field list pointer
   1626  *
   1627  * RETURN:      Status
   1628  *
   1629  * DESCRIPTION: Compile DTPR.
   1630  *
   1631  *****************************************************************************/
   1632 
   1633 ACPI_STATUS
   1634 DtCompileDtpr (
   1635     void                    **List)
   1636 {
   1637     ACPI_STATUS             Status;
   1638     DT_SUBTABLE             *Subtable;
   1639     DT_SUBTABLE             *ParentTable;
   1640     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   1641     ACPI_TABLE_DTPR         *Dtpr;
   1642     ACPI_TPR_INSTANCE       *TprInst;
   1643     UINT32                  i, InsCnt, SrlCnt, TprCnt;
   1644 
   1645 
   1646     ParentTable = DtPeekSubtable ();
   1647 
   1648     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDtpr, &Subtable);
   1649     if (ACPI_FAILURE (Status))
   1650     {
   1651         return (Status);
   1652     }
   1653 
   1654     DtInsertSubtable (ParentTable, Subtable);
   1655 
   1656     Dtpr = ACPI_SUB_PTR (ACPI_TABLE_DTPR, Subtable->Buffer,
   1657                          sizeof (ACPI_TABLE_HEADER));
   1658     if (!Dtpr)
   1659     {
   1660         AcpiOsPrintf ("DTPR buffer pointer is NULL\n");
   1661         return (AE_NULL_OBJECT);
   1662     }
   1663 
   1664     InsCnt = Dtpr->InsCnt;
   1665 
   1666     while (*PFieldList)
   1667     {
   1668         for (i = 0; i < InsCnt; i++)
   1669         {
   1670             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDtprInstance,
   1671                                      &Subtable);
   1672             if (ACPI_FAILURE (Status))
   1673             {
   1674                 return (Status);
   1675             }
   1676 
   1677             TprInst = ACPI_CAST_PTR (ACPI_TPR_INSTANCE, Subtable->Buffer);
   1678             if (!TprInst)
   1679             {
   1680                 AcpiOsPrintf ("Tpr Instance buffer pointer is NULL\n");
   1681                 return (AE_NULL_OBJECT);
   1682             }
   1683 
   1684             TprCnt = TprInst->TprCnt;
   1685             DtInsertSubtable (ParentTable, Subtable);
   1686             DtPushSubtable (Subtable);
   1687             ParentTable = DtPeekSubtable ();
   1688 
   1689             while (*PFieldList && TprCnt)
   1690             {
   1691                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoDtprArr,
   1692                                          &Subtable);
   1693                 if (ACPI_FAILURE (Status))
   1694                 {
   1695                     return (Status);
   1696                 }
   1697 
   1698                 DtInsertSubtable (ParentTable, Subtable);
   1699                 TprCnt--;
   1700             }
   1701 
   1702             DtPopSubtable();
   1703             ParentTable = DtPeekSubtable ();
   1704         }
   1705 
   1706         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDtprSerializeReq0,
   1707                                  &Subtable);
   1708         if (ACPI_FAILURE (Status))
   1709         {
   1710             return (Status);
   1711         }
   1712 
   1713         SrlCnt = *ACPI_CAST_PTR(UINT32, Subtable->Buffer);
   1714         DtInsertSubtable (ParentTable, Subtable);
   1715         DtPushSubtable (Subtable);
   1716         ParentTable = DtPeekSubtable ();
   1717 
   1718         while (*PFieldList && SrlCnt)
   1719         {
   1720             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDtprSerializeReq1,
   1721                                      &Subtable);
   1722             if (ACPI_FAILURE (Status))
   1723             {
   1724                 return (Status);
   1725             }
   1726 
   1727             DtInsertSubtable (ParentTable, Subtable);
   1728             SrlCnt--;
   1729         }
   1730 
   1731 
   1732         DtPopSubtable();
   1733         ParentTable = DtPeekSubtable ();
   1734     }
   1735 
   1736     return Status;
   1737 }
   1738 
   1739 /******************************************************************************
   1740  *
   1741  * FUNCTION:    DtCompileEinj
   1742  *
   1743  * PARAMETERS:  List                - Current field list pointer
   1744  *
   1745  * RETURN:      Status
   1746  *
   1747  * DESCRIPTION: Compile EINJ.
   1748  *
   1749  *****************************************************************************/
   1750 
   1751 ACPI_STATUS
   1752 DtCompileEinj (
   1753     void                    **List)
   1754 {
   1755     ACPI_STATUS             Status;
   1756 
   1757 
   1758     Status = DtCompileTwoSubtables (List,
   1759         AcpiDmTableInfoEinj, AcpiDmTableInfoEinj0);
   1760     return (Status);
   1761 }
   1762 
   1763 
   1764 /******************************************************************************
   1765  *
   1766  * FUNCTION:    DtCompileErdt
   1767  *
   1768  * PARAMETERS:  List                - Current field list pointer
   1769  *
   1770  * RETURN:      Status
   1771  *
   1772  * DESCRIPTION: Compile ERST. Complex table with subtables and subsubtables.
   1773  *
   1774  *****************************************************************************/
   1775 
   1776 ACPI_STATUS
   1777 DtCompileErdt (
   1778     void                    **List)
   1779 {
   1780     ACPI_STATUS             Status;
   1781     DT_SUBTABLE             *Subtable, *RmddSubtable = NULL, *Subsubtable;
   1782     DT_SUBTABLE             *ParentTable;
   1783     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   1784     DT_FIELD                *SubtableStart;
   1785     ACPI_SUBTBL_HDR_16      *ErdtHeader;
   1786     ACPI_DMTABLE_INFO       *InfoTable;
   1787     ACPI_ERDT_MMRC          *Mmrc;
   1788     ACPI_ERDT_IBRD          *Ibrd;
   1789     UINT32                  NumEntries;
   1790     BOOLEAN                 SeenRmdd = FALSE;
   1791     BOOLEAN                 SeenSubtable = FALSE;
   1792 
   1793     Status = DtCompileTable (PFieldList, AcpiDmTableInfoErdt,
   1794         &Subtable);
   1795     if (ACPI_FAILURE (Status))
   1796     {
   1797         return (Status);
   1798     }
   1799 
   1800     ParentTable = DtPeekSubtable ();
   1801     DtInsertSubtable (ParentTable, Subtable);
   1802 
   1803     while (*PFieldList)
   1804     {
   1805         SubtableStart = *PFieldList;
   1806         Status = DtCompileTable (PFieldList, AcpiDmTableInfoErdtHdr,
   1807             &Subtable);
   1808         if (ACPI_FAILURE (Status))
   1809         {
   1810             return (Status);
   1811         }
   1812 
   1813         ErdtHeader = ACPI_CAST_PTR (ACPI_SUBTBL_HDR_16, Subtable->Buffer);
   1814 
   1815         /* RMDD tables at top level. All others are subtables of preceeding RMDD */
   1816         if (ErdtHeader->Type == ACPI_ERDT_TYPE_RMDD)
   1817         {
   1818             if (SeenRmdd && SeenSubtable)
   1819                 DtPopSubtable ();
   1820             SeenRmdd = TRUE;
   1821             SeenSubtable = FALSE;
   1822             RmddSubtable = Subtable;
   1823         }
   1824         else
   1825         {
   1826             if (!SeenSubtable)
   1827             {
   1828                 DtPushSubtable (RmddSubtable);
   1829                 SeenSubtable = TRUE;
   1830             }
   1831         }
   1832 
   1833         ParentTable = DtPeekSubtable ();
   1834         DtInsertSubtable (ParentTable, Subtable);
   1835         DtPushSubtable (Subtable);
   1836 
   1837         switch (ErdtHeader->Type)
   1838         {
   1839         case ACPI_ERDT_TYPE_RMDD:
   1840             InfoTable = AcpiDmTableInfoErdtRmdd;
   1841             break;
   1842 
   1843         case ACPI_ERDT_TYPE_CACD:
   1844              InfoTable = AcpiDmTableInfoErdtCacd;
   1845              break;
   1846 
   1847         case ACPI_ERDT_TYPE_DACD:
   1848              InfoTable = AcpiDmTableInfoErdtDacd;
   1849              break;
   1850 
   1851         case ACPI_ERDT_TYPE_CMRC:
   1852              InfoTable = AcpiDmTableInfoErdtCmrc;
   1853              break;
   1854 
   1855         case ACPI_ERDT_TYPE_MMRC:
   1856              InfoTable = AcpiDmTableInfoErdtMmrc;
   1857              break;
   1858 
   1859         case ACPI_ERDT_TYPE_MARC:
   1860              InfoTable = AcpiDmTableInfoErdtMarc;
   1861              break;
   1862 
   1863         case ACPI_ERDT_TYPE_CARC:
   1864              InfoTable = AcpiDmTableInfoErdtCarc;
   1865              break;
   1866 
   1867         case ACPI_ERDT_TYPE_CMRD:
   1868              InfoTable = AcpiDmTableInfoErdtCmrd;
   1869              break;
   1870 
   1871         case ACPI_ERDT_TYPE_IBRD:
   1872              InfoTable = AcpiDmTableInfoErdtIbrd;
   1873              break;
   1874 
   1875         case ACPI_ERDT_TYPE_IBAD:
   1876              InfoTable = AcpiDmTableInfoErdtIbad;
   1877              break;
   1878 
   1879         case ACPI_ERDT_TYPE_CARD:
   1880              InfoTable = AcpiDmTableInfoErdtCard;
   1881              break;
   1882 
   1883         default:
   1884             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "ERDT");
   1885             return (AE_ERROR);
   1886         }
   1887 
   1888         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
   1889         if (ACPI_FAILURE (Status))
   1890         {
   1891             return (Status);
   1892         }
   1893 
   1894         ParentTable = DtPeekSubtable ();
   1895         DtInsertSubtable (ParentTable, Subtable);
   1896 
   1897         /* Some subtable types end with flex arrays */
   1898 
   1899         switch (ErdtHeader->Type)
   1900         {
   1901         case ACPI_ERDT_TYPE_CACD:
   1902             while (*PFieldList)
   1903             {
   1904                 Status = DtCompileTable (PFieldList,
   1905                     AcpiDmTableInfoErdtCacdX2apic, &Subtable);
   1906                 if (ACPI_FAILURE (Status))
   1907                 {
   1908                     return (Status);
   1909                 }
   1910                 if (!Subtable)
   1911                 {
   1912                     break;
   1913                 }
   1914 
   1915                 ParentTable = DtPeekSubtable ();
   1916                 DtInsertSubtable (ParentTable, Subtable);
   1917             }
   1918             break;
   1919 
   1920         case ACPI_ERDT_TYPE_DACD:
   1921             while (*PFieldList)
   1922             {
   1923                 Status = DtCompileTable (PFieldList,
   1924                     AcpiDmTableInfoErdtDacdScope, &Subtable);
   1925                 if (ACPI_FAILURE (Status))
   1926                 {
   1927                     return (Status);
   1928                 }
   1929                 if (!Subtable)
   1930                 {
   1931                     break;
   1932                 }
   1933 
   1934                 DtPushSubtable (Subtable);
   1935                 while (*PFieldList)
   1936                 {
   1937                     Status = DtCompileTable (PFieldList,
   1938                         AcpiDmTableInfoErdtDacdPath, &Subsubtable);
   1939                     if (ACPI_FAILURE (Status))
   1940                     {
   1941                         return (Status);
   1942                     }
   1943                     if (!Subsubtable)
   1944                     {
   1945                         break;
   1946                     }
   1947 
   1948                     ParentTable = DtPeekSubtable ();
   1949                     DtInsertSubtable (ParentTable, Subsubtable);
   1950                 }
   1951                 DtPopSubtable ();
   1952 
   1953                 ParentTable = DtPeekSubtable ();
   1954                 DtInsertSubtable (ParentTable, Subtable);
   1955             }
   1956             break;
   1957 
   1958         case ACPI_ERDT_TYPE_MMRC:
   1959             Mmrc = ACPI_SUB_PTR (ACPI_ERDT_MMRC, Subtable->Buffer,
   1960                 sizeof(ACPI_SUBTBL_HDR_16));
   1961             NumEntries = 0;
   1962             while (*PFieldList)
   1963             {
   1964                 Status = DtCompileTable (PFieldList,
   1965                     AcpiDmTableInfoErdtMmrcCorrFactor, &Subtable);
   1966                 if (ACPI_FAILURE (Status))
   1967                 {
   1968                     return (Status);
   1969                 }
   1970                 if (!Subtable)
   1971                 {
   1972                     break;
   1973                 }
   1974 
   1975                 ParentTable = DtPeekSubtable ();
   1976                 DtInsertSubtable (ParentTable, Subtable);
   1977                 NumEntries++;
   1978             }
   1979             Mmrc->CorrFactorListLen = NumEntries;
   1980             break;
   1981 
   1982         case ACPI_ERDT_TYPE_IBRD:
   1983             Ibrd = ACPI_SUB_PTR (ACPI_ERDT_IBRD, Subtable->Buffer,
   1984                 sizeof(ACPI_SUBTBL_HDR_16));
   1985             NumEntries = 0;
   1986             while (*PFieldList)
   1987             {
   1988                 Status = DtCompileTable (PFieldList,
   1989                     AcpiDmTableInfoErdtIbrdCorrFactor, &Subtable);
   1990                 if (ACPI_FAILURE (Status))
   1991                 {
   1992                     return (Status);
   1993                 }
   1994                 if (!Subtable)
   1995                 {
   1996                     break;
   1997                 }
   1998 
   1999                 ParentTable = DtPeekSubtable ();
   2000                 DtInsertSubtable (ParentTable, Subtable);
   2001                 NumEntries++;
   2002             }
   2003             Ibrd->CorrFactorListLen = NumEntries;
   2004             break;
   2005 
   2006         default:
   2007             /* Already checked for valid subtable type above */
   2008 
   2009             break;
   2010         }
   2011         DtPopSubtable ();
   2012     }
   2013 
   2014     if (SeenSubtable)
   2015     {
   2016         DtPopSubtable ();
   2017     }
   2018 
   2019     return (AE_OK);
   2020 }
   2021 
   2022 
   2023 /******************************************************************************
   2024  *
   2025  * FUNCTION:    DtCompileErst
   2026  *
   2027  * PARAMETERS:  List                - Current field list pointer
   2028  *
   2029  * RETURN:      Status
   2030  *
   2031  * DESCRIPTION: Compile ERST.
   2032  *
   2033  *****************************************************************************/
   2034 
   2035 ACPI_STATUS
   2036 DtCompileErst (
   2037     void                    **List)
   2038 {
   2039     ACPI_STATUS             Status;
   2040 
   2041 
   2042     Status = DtCompileTwoSubtables (List,
   2043         AcpiDmTableInfoErst, AcpiDmTableInfoEinj0);
   2044     return (Status);
   2045 }
   2046 
   2047 
   2048 /******************************************************************************
   2049  *
   2050  * FUNCTION:    DtCompileGtdt
   2051  *
   2052  * PARAMETERS:  List                - Current field list pointer
   2053  *
   2054  * RETURN:      Status
   2055  *
   2056  * DESCRIPTION: Compile GTDT.
   2057  *
   2058  *****************************************************************************/
   2059 
   2060 ACPI_STATUS
   2061 DtCompileGtdt (
   2062     void                    **List)
   2063 {
   2064     ACPI_STATUS             Status;
   2065     DT_SUBTABLE             *Subtable;
   2066     DT_SUBTABLE             *ParentTable;
   2067     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   2068     DT_FIELD                *SubtableStart;
   2069     ACPI_SUBTABLE_HEADER    *GtdtHeader;
   2070     ACPI_DMTABLE_INFO       *InfoTable;
   2071     UINT32                  GtCount;
   2072     ACPI_TABLE_HEADER       *Header;
   2073 
   2074 
   2075     ParentTable = DtPeekSubtable ();
   2076 
   2077     Header = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer);
   2078 
   2079     /* Compile the main table */
   2080 
   2081     Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt,
   2082         &Subtable);
   2083     if (ACPI_FAILURE (Status))
   2084     {
   2085         return (Status);
   2086     }
   2087 
   2088     /* GTDT revision 3 later contains 2 extra fields before subtables */
   2089 
   2090     if (Header->Revision > 2)
   2091     {
   2092         ParentTable = DtPeekSubtable ();
   2093         DtInsertSubtable (ParentTable, Subtable);
   2094 
   2095         Status = DtCompileTable (PFieldList,
   2096             AcpiDmTableInfoGtdtEl2, &Subtable);
   2097         if (ACPI_FAILURE (Status))
   2098         {
   2099             return (Status);
   2100         }
   2101     }
   2102 
   2103     ParentTable = DtPeekSubtable ();
   2104     DtInsertSubtable (ParentTable, Subtable);
   2105 
   2106     while (*PFieldList)
   2107     {
   2108         SubtableStart = *PFieldList;
   2109         Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdtHdr,
   2110             &Subtable);
   2111         if (ACPI_FAILURE (Status))
   2112         {
   2113             return (Status);
   2114         }
   2115 
   2116         ParentTable = DtPeekSubtable ();
   2117         DtInsertSubtable (ParentTable, Subtable);
   2118         DtPushSubtable (Subtable);
   2119 
   2120         GtdtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer);
   2121 
   2122         switch (GtdtHeader->Type)
   2123         {
   2124         case ACPI_GTDT_TYPE_TIMER_BLOCK:
   2125 
   2126             InfoTable = AcpiDmTableInfoGtdt0;
   2127             break;
   2128 
   2129         case ACPI_GTDT_TYPE_WATCHDOG:
   2130 
   2131             InfoTable = AcpiDmTableInfoGtdt1;
   2132             break;
   2133 
   2134         default:
   2135 
   2136             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "GTDT");
   2137             return (AE_ERROR);
   2138         }
   2139 
   2140         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
   2141         if (ACPI_FAILURE (Status))
   2142         {
   2143             return (Status);
   2144         }
   2145 
   2146         ParentTable = DtPeekSubtable ();
   2147         DtInsertSubtable (ParentTable, Subtable);
   2148 
   2149         /*
   2150          * Additional GT block subtable data
   2151          */
   2152 
   2153         switch (GtdtHeader->Type)
   2154         {
   2155         case ACPI_GTDT_TYPE_TIMER_BLOCK:
   2156 
   2157             DtPushSubtable (Subtable);
   2158             ParentTable = DtPeekSubtable ();
   2159 
   2160             GtCount = (ACPI_CAST_PTR (ACPI_GTDT_TIMER_BLOCK,
   2161                 Subtable->Buffer - sizeof(ACPI_GTDT_HEADER)))->TimerCount;
   2162 
   2163             while (GtCount)
   2164             {
   2165                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt0a,
   2166                     &Subtable);
   2167                 if (ACPI_FAILURE (Status))
   2168                 {
   2169                     return (Status);
   2170                 }
   2171 
   2172                 DtInsertSubtable (ParentTable, Subtable);
   2173                 GtCount--;
   2174             }
   2175 
   2176             DtPopSubtable ();
   2177             break;
   2178 
   2179         default:
   2180 
   2181             break;
   2182         }
   2183 
   2184         DtPopSubtable ();
   2185     }
   2186 
   2187     return (AE_OK);
   2188 }
   2189 
   2190 
   2191 /******************************************************************************
   2192  *
   2193  * FUNCTION:    DtCompileFpdt
   2194  *
   2195  * PARAMETERS:  List                - Current field list pointer
   2196  *
   2197  * RETURN:      Status
   2198  *
   2199  * DESCRIPTION: Compile FPDT.
   2200  *
   2201  *****************************************************************************/
   2202 
   2203 ACPI_STATUS
   2204 DtCompileFpdt (
   2205     void                    **List)
   2206 {
   2207     ACPI_STATUS             Status;
   2208     ACPI_FPDT_HEADER        *FpdtHeader;
   2209     DT_SUBTABLE             *Subtable;
   2210     DT_SUBTABLE             *ParentTable;
   2211     ACPI_DMTABLE_INFO       *InfoTable;
   2212     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   2213     DT_FIELD                *SubtableStart;
   2214 
   2215 
   2216     while (*PFieldList)
   2217     {
   2218         SubtableStart = *PFieldList;
   2219         Status = DtCompileTable (PFieldList, AcpiDmTableInfoFpdtHdr,
   2220             &Subtable);
   2221         if (ACPI_FAILURE (Status))
   2222         {
   2223             return (Status);
   2224         }
   2225 
   2226         ParentTable = DtPeekSubtable ();
   2227         DtInsertSubtable (ParentTable, Subtable);
   2228         DtPushSubtable (Subtable);
   2229 
   2230         FpdtHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer);
   2231 
   2232         switch (FpdtHeader->Type)
   2233         {
   2234         case ACPI_FPDT_TYPE_BOOT:
   2235 
   2236             InfoTable = AcpiDmTableInfoFpdt0;
   2237             break;
   2238 
   2239         case ACPI_FPDT_TYPE_S3PERF:
   2240 
   2241             InfoTable = AcpiDmTableInfoFpdt1;
   2242             break;
   2243 
   2244         default:
   2245 
   2246             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "FPDT");
   2247             return (AE_ERROR);
   2248             break;
   2249         }
   2250 
   2251         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
   2252         if (ACPI_FAILURE (Status))
   2253         {
   2254             return (Status);
   2255         }
   2256 
   2257         ParentTable = DtPeekSubtable ();
   2258         DtInsertSubtable (ParentTable, Subtable);
   2259         DtPopSubtable ();
   2260     }
   2261 
   2262     return (AE_OK);
   2263 }
   2264 
   2265 
   2266 /******************************************************************************
   2267  *
   2268  * FUNCTION:    DtCompileHest
   2269  *
   2270  * PARAMETERS:  List                - Current field list pointer
   2271  *
   2272  * RETURN:      Status
   2273  *
   2274  * DESCRIPTION: Compile HEST.
   2275  *
   2276  *****************************************************************************/
   2277 
   2278 ACPI_STATUS
   2279 DtCompileHest (
   2280     void                    **List)
   2281 {
   2282     ACPI_STATUS             Status;
   2283     DT_SUBTABLE             *Subtable;
   2284     DT_SUBTABLE             *ParentTable;
   2285     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   2286     DT_FIELD                *SubtableStart;
   2287     ACPI_DMTABLE_INFO       *InfoTable;
   2288     UINT16                  Type;
   2289     UINT32                  BankCount;
   2290 
   2291 
   2292     Status = DtCompileTable (PFieldList, AcpiDmTableInfoHest,
   2293         &Subtable);
   2294     if (ACPI_FAILURE (Status))
   2295     {
   2296         return (Status);
   2297     }
   2298 
   2299     ParentTable = DtPeekSubtable ();
   2300     DtInsertSubtable (ParentTable, Subtable);
   2301 
   2302     while (*PFieldList)
   2303     {
   2304         /* Get subtable type */
   2305 
   2306         SubtableStart = *PFieldList;
   2307         DtCompileInteger ((UINT8 *) &Type, *PFieldList, 2, 0);
   2308 
   2309         switch (Type)
   2310         {
   2311         case ACPI_HEST_TYPE_IA32_CHECK:
   2312 
   2313             InfoTable = AcpiDmTableInfoHest0;
   2314             break;
   2315 
   2316         case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
   2317 
   2318             InfoTable = AcpiDmTableInfoHest1;
   2319             break;
   2320 
   2321         case ACPI_HEST_TYPE_IA32_NMI:
   2322 
   2323             InfoTable = AcpiDmTableInfoHest2;
   2324             break;
   2325 
   2326         case ACPI_HEST_TYPE_AER_ROOT_PORT:
   2327 
   2328             InfoTable = AcpiDmTableInfoHest6;
   2329             break;
   2330 
   2331         case ACPI_HEST_TYPE_AER_ENDPOINT:
   2332 
   2333             InfoTable = AcpiDmTableInfoHest7;
   2334             break;
   2335 
   2336         case ACPI_HEST_TYPE_AER_BRIDGE:
   2337 
   2338             InfoTable = AcpiDmTableInfoHest8;
   2339             break;
   2340 
   2341         case ACPI_HEST_TYPE_GENERIC_ERROR:
   2342 
   2343             InfoTable = AcpiDmTableInfoHest9;
   2344             break;
   2345 
   2346         case ACPI_HEST_TYPE_GENERIC_ERROR_V2:
   2347 
   2348             InfoTable = AcpiDmTableInfoHest10;
   2349             break;
   2350 
   2351         case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
   2352 
   2353             InfoTable = AcpiDmTableInfoHest11;
   2354             break;
   2355 
   2356         default:
   2357 
   2358             /* Cannot continue on unknown type */
   2359 
   2360             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HEST");
   2361             return (AE_ERROR);
   2362         }
   2363 
   2364         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
   2365         if (ACPI_FAILURE (Status))
   2366         {
   2367             return (Status);
   2368         }
   2369 
   2370         DtInsertSubtable (ParentTable, Subtable);
   2371 
   2372         /*
   2373          * Additional subtable data - IA32 Error Bank(s)
   2374          */
   2375         BankCount = 0;
   2376         switch (Type)
   2377         {
   2378         case ACPI_HEST_TYPE_IA32_CHECK:
   2379 
   2380             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK,
   2381                 Subtable->Buffer))->NumHardwareBanks;
   2382             break;
   2383 
   2384         case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
   2385 
   2386             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED,
   2387                 Subtable->Buffer))->NumHardwareBanks;
   2388             break;
   2389 
   2390         case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
   2391 
   2392             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_DEFERRED_CHECK,
   2393                 Subtable->Buffer))->NumHardwareBanks;
   2394             break;
   2395 
   2396         default:
   2397 
   2398             break;
   2399         }
   2400 
   2401         while (BankCount)
   2402         {
   2403             Status = DtCompileTable (PFieldList, AcpiDmTableInfoHestBank,
   2404                 &Subtable);
   2405             if (ACPI_FAILURE (Status))
   2406             {
   2407                 return (Status);
   2408             }
   2409 
   2410             DtInsertSubtable (ParentTable, Subtable);
   2411             BankCount--;
   2412         }
   2413     }
   2414 
   2415     return (AE_OK);
   2416 }
   2417 
   2418 
   2419 /******************************************************************************
   2420  *
   2421  * FUNCTION:    DtCompileHmat
   2422  *
   2423  * PARAMETERS:  List                - Current field list pointer
   2424  *
   2425  * RETURN:      Status
   2426  *
   2427  * DESCRIPTION: Compile HMAT.
   2428  *
   2429  *****************************************************************************/
   2430 
   2431 ACPI_STATUS
   2432 DtCompileHmat (
   2433     void                    **List)
   2434 {
   2435     ACPI_STATUS             Status;
   2436     DT_SUBTABLE             *Subtable;
   2437     DT_SUBTABLE             *ParentTable;
   2438     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   2439     DT_FIELD                *SubtableStart;
   2440     DT_FIELD                *EntryStart;
   2441     ACPI_HMAT_STRUCTURE     *HmatStruct;
   2442     ACPI_HMAT_LOCALITY      *HmatLocality;
   2443     ACPI_HMAT_CACHE         *HmatCache;
   2444     ACPI_DMTABLE_INFO       *InfoTable;
   2445     UINT32                  IntPDNumber;
   2446     UINT32                  TgtPDNumber;
   2447     UINT64                  EntryNumber;
   2448     UINT16                  SMBIOSHandleNumber;
   2449 
   2450 
   2451     ParentTable = DtPeekSubtable ();
   2452 
   2453     Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmat,
   2454         &Subtable);
   2455     if (ACPI_FAILURE (Status))
   2456     {
   2457         return (Status);
   2458     }
   2459     DtInsertSubtable (ParentTable, Subtable);
   2460 
   2461     while (*PFieldList)
   2462     {
   2463         /* Compile HMAT structure header */
   2464 
   2465         SubtableStart = *PFieldList;
   2466         Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmatHdr,
   2467             &Subtable);
   2468         if (ACPI_FAILURE (Status))
   2469         {
   2470             return (Status);
   2471         }
   2472         DtInsertSubtable (ParentTable, Subtable);
   2473 
   2474         HmatStruct = ACPI_CAST_PTR (ACPI_HMAT_STRUCTURE, Subtable->Buffer);
   2475         HmatStruct->Length = Subtable->Length;
   2476 
   2477         /* Compile HMAT structure body */
   2478 
   2479         switch (HmatStruct->Type)
   2480         {
   2481         case ACPI_HMAT_TYPE_ADDRESS_RANGE:
   2482 
   2483             InfoTable = AcpiDmTableInfoHmat0;
   2484             break;
   2485 
   2486         case ACPI_HMAT_TYPE_LOCALITY:
   2487 
   2488             InfoTable = AcpiDmTableInfoHmat1;
   2489             break;
   2490 
   2491         case ACPI_HMAT_TYPE_CACHE:
   2492 
   2493             InfoTable = AcpiDmTableInfoHmat2;
   2494             break;
   2495 
   2496         default:
   2497 
   2498             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HMAT");
   2499             return (AE_ERROR);
   2500         }
   2501 
   2502         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
   2503         if (ACPI_FAILURE (Status))
   2504         {
   2505             return (Status);
   2506         }
   2507         DtInsertSubtable (ParentTable, Subtable);
   2508         HmatStruct->Length += Subtable->Length;
   2509 
   2510         /* Compile HMAT structure additional */
   2511 
   2512         switch (HmatStruct->Type)
   2513         {
   2514         case ACPI_HMAT_TYPE_LOCALITY:
   2515 
   2516             HmatLocality = ACPI_SUB_PTR (ACPI_HMAT_LOCALITY,
   2517                 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
   2518 
   2519             /* Compile initiator proximity domain list */
   2520 
   2521             IntPDNumber = 0;
   2522             while (*PFieldList)
   2523             {
   2524                 Status = DtCompileTable (PFieldList,
   2525                     AcpiDmTableInfoHmat1a, &Subtable);
   2526                 if (ACPI_FAILURE (Status))
   2527                 {
   2528                     return (Status);
   2529                 }
   2530                 if (!Subtable)
   2531                 {
   2532                     break;
   2533                 }
   2534                 DtInsertSubtable (ParentTable, Subtable);
   2535                 HmatStruct->Length += Subtable->Length;
   2536                 IntPDNumber++;
   2537             }
   2538             HmatLocality->NumberOfInitiatorPDs = IntPDNumber;
   2539 
   2540             /* Compile target proximity domain list */
   2541 
   2542             TgtPDNumber = 0;
   2543             while (*PFieldList)
   2544             {
   2545                 Status = DtCompileTable (PFieldList,
   2546                     AcpiDmTableInfoHmat1b, &Subtable);
   2547                 if (ACPI_FAILURE (Status))
   2548                 {
   2549                     return (Status);
   2550                 }
   2551                 if (!Subtable)
   2552                 {
   2553                     break;
   2554                 }
   2555                 DtInsertSubtable (ParentTable, Subtable);
   2556                 HmatStruct->Length += Subtable->Length;
   2557                 TgtPDNumber++;
   2558             }
   2559             HmatLocality->NumberOfTargetPDs = TgtPDNumber;
   2560 
   2561             /* Save start of the entries for reporting errors */
   2562 
   2563             EntryStart = *PFieldList;
   2564 
   2565             /* Compile latency/bandwidth entries */
   2566 
   2567             EntryNumber = 0;
   2568             while (*PFieldList)
   2569             {
   2570                 Status = DtCompileTable (PFieldList,
   2571                     AcpiDmTableInfoHmat1c, &Subtable);
   2572                 if (ACPI_FAILURE (Status))
   2573                 {
   2574                     return (Status);
   2575                 }
   2576                 if (!Subtable)
   2577                 {
   2578                     break;
   2579                 }
   2580                 DtInsertSubtable (ParentTable, Subtable);
   2581                 HmatStruct->Length += Subtable->Length;
   2582                 EntryNumber++;
   2583             }
   2584 
   2585             /* Validate number of entries */
   2586 
   2587             if (EntryNumber !=
   2588                 ((UINT64)IntPDNumber * (UINT64)TgtPDNumber))
   2589             {
   2590                 DtFatal (ASL_MSG_INVALID_EXPRESSION, EntryStart, "HMAT");
   2591                 return (AE_ERROR);
   2592             }
   2593             break;
   2594 
   2595         case ACPI_HMAT_TYPE_CACHE:
   2596 
   2597             /* Compile SMBIOS handles */
   2598 
   2599             HmatCache = ACPI_SUB_PTR (ACPI_HMAT_CACHE,
   2600                 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
   2601             SMBIOSHandleNumber = 0;
   2602             while (*PFieldList)
   2603             {
   2604                 Status = DtCompileTable (PFieldList,
   2605                     AcpiDmTableInfoHmat2a, &Subtable);
   2606                 if (ACPI_FAILURE (Status))
   2607                 {
   2608                     return (Status);
   2609                 }
   2610                 if (!Subtable)
   2611                 {
   2612                     break;
   2613                 }
   2614                 DtInsertSubtable (ParentTable, Subtable);
   2615                 HmatStruct->Length += Subtable->Length;
   2616                 SMBIOSHandleNumber++;
   2617             }
   2618             HmatCache->NumberOfSMBIOSHandles = SMBIOSHandleNumber;
   2619             break;
   2620 
   2621         default:
   2622 
   2623             break;
   2624         }
   2625     }
   2626 
   2627     return (AE_OK);
   2628 }
   2629 
   2630 
   2631 /******************************************************************************
   2632  *
   2633  * FUNCTION:    DtCompileIort
   2634  *
   2635  * PARAMETERS:  List                - Current field list pointer
   2636  *
   2637  * RETURN:      Status
   2638  *
   2639  * DESCRIPTION: Compile IORT.
   2640  *
   2641  *****************************************************************************/
   2642 
   2643 ACPI_STATUS
   2644 DtCompileIort (
   2645     void                    **List)
   2646 {
   2647     ACPI_STATUS             Status;
   2648     DT_SUBTABLE             *Subtable;
   2649     DT_SUBTABLE             *ParentTable;
   2650     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   2651     DT_FIELD                *SubtableStart;
   2652     ACPI_TABLE_HEADER       *Table;
   2653     ACPI_TABLE_IORT         *Iort;
   2654     ACPI_IORT_NODE          *IortNode;
   2655     ACPI_IORT_ITS_GROUP     *IortItsGroup;
   2656     ACPI_IORT_SMMU          *IortSmmu;
   2657     ACPI_IORT_RMR           *IortRmr;
   2658     UINT32                  NodeNumber;
   2659     UINT32                  NodeLength;
   2660     UINT32                  IdMappingNumber;
   2661     UINT32                  ItsNumber;
   2662     UINT32                  ContextIrptNumber;
   2663     UINT32                  PmuIrptNumber;
   2664     UINT32                  PaddingLength;
   2665     UINT8                   Revision;
   2666     UINT32                  RmrCount;
   2667 
   2668 
   2669     ParentTable = DtPeekSubtable ();
   2670 
   2671     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort,
   2672         &Subtable);
   2673     if (ACPI_FAILURE (Status))
   2674     {
   2675         return (Status);
   2676     }
   2677     DtInsertSubtable (ParentTable, Subtable);
   2678 
   2679     Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer);
   2680     Revision = Table->Revision;
   2681 
   2682     /* IORT Revisions E, E.a & E.c have known issues and are not supported */
   2683 
   2684     if (Revision == 1 || Revision == 2 || Revision == 4)
   2685     {
   2686         DtError (ASL_ERROR, ASL_MSG_UNSUPPORTED, NULL, "IORT table revision");
   2687         return (AE_ERROR);
   2688     }
   2689 
   2690     /*
   2691      * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
   2692      * should be taken to avoid accessing ACPI_TABLE_HEADER fields.
   2693      */
   2694     Iort = ACPI_SUB_PTR (ACPI_TABLE_IORT,
   2695         Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
   2696 
   2697     /*
   2698      * OptionalPadding - Variable-length data
   2699      * (Optional, size = OffsetToNodes - sizeof (ACPI_TABLE_IORT))
   2700      * Optionally allows the generic data types to be used for filling
   2701      * this field.
   2702      */
   2703     Iort->NodeOffset = sizeof (ACPI_TABLE_IORT);
   2704     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortPad,
   2705         &Subtable);
   2706     if (ACPI_FAILURE (Status))
   2707     {
   2708         return (Status);
   2709     }
   2710     if (Subtable)
   2711     {
   2712         DtInsertSubtable (ParentTable, Subtable);
   2713         Iort->NodeOffset += Subtable->Length;
   2714     }
   2715     else
   2716     {
   2717         Status = DtCompileGeneric (ACPI_CAST_PTR (void *, PFieldList),
   2718             AcpiDmTableInfoIortHdr[0].Name, &PaddingLength);
   2719         if (ACPI_FAILURE (Status))
   2720         {
   2721             return (Status);
   2722         }
   2723         Iort->NodeOffset += PaddingLength;
   2724     }
   2725 
   2726     NodeNumber = 0;
   2727     while (*PFieldList)
   2728     {
   2729         SubtableStart = *PFieldList;
   2730         if (Revision == 0)
   2731         {
   2732             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr,
   2733                 &Subtable);
   2734         }
   2735         else if (Revision >= 3)
   2736         {
   2737             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr3,
   2738                 &Subtable);
   2739         }
   2740 
   2741         if (ACPI_FAILURE (Status))
   2742         {
   2743             return (Status);
   2744         }
   2745 
   2746         DtInsertSubtable (ParentTable, Subtable);
   2747         IortNode = ACPI_CAST_PTR (ACPI_IORT_NODE, Subtable->Buffer);
   2748         NodeLength = ACPI_OFFSET (ACPI_IORT_NODE, NodeData);
   2749 
   2750         DtPushSubtable (Subtable);
   2751         ParentTable = DtPeekSubtable ();
   2752 
   2753         switch (IortNode->Type)
   2754         {
   2755         case ACPI_IORT_NODE_ITS_GROUP:
   2756 
   2757             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0,
   2758                 &Subtable);
   2759             if (ACPI_FAILURE (Status))
   2760             {
   2761                 return (Status);
   2762             }
   2763 
   2764             DtInsertSubtable (ParentTable, Subtable);
   2765             IortItsGroup = ACPI_CAST_PTR (ACPI_IORT_ITS_GROUP, Subtable->Buffer);
   2766             NodeLength += Subtable->Length;
   2767 
   2768             ItsNumber = 0;
   2769             while (*PFieldList)
   2770             {
   2771                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0a,
   2772                     &Subtable);
   2773                 if (ACPI_FAILURE (Status))
   2774                 {
   2775                     return (Status);
   2776                 }
   2777                 if (!Subtable)
   2778                 {
   2779                     break;
   2780                 }
   2781 
   2782                 DtInsertSubtable (ParentTable, Subtable);
   2783                 NodeLength += Subtable->Length;
   2784                 ItsNumber++;
   2785             }
   2786 
   2787             IortItsGroup->ItsCount = ItsNumber;
   2788             break;
   2789 
   2790         case ACPI_IORT_NODE_NAMED_COMPONENT:
   2791 
   2792             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1,
   2793                 &Subtable);
   2794             if (ACPI_FAILURE (Status))
   2795             {
   2796                 return (Status);
   2797             }
   2798 
   2799             DtInsertSubtable (ParentTable, Subtable);
   2800             NodeLength += Subtable->Length;
   2801 
   2802             /*
   2803              * Padding - Variable-length data
   2804              * Optionally allows the offset of the ID mappings to be used
   2805              * for filling this field.
   2806              */
   2807             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1a,
   2808                 &Subtable);
   2809             if (ACPI_FAILURE (Status))
   2810             {
   2811                 return (Status);
   2812             }
   2813 
   2814             if (Subtable)
   2815             {
   2816                 DtInsertSubtable (ParentTable, Subtable);
   2817                 NodeLength += Subtable->Length;
   2818             }
   2819             else
   2820             {
   2821                 if (NodeLength > IortNode->MappingOffset)
   2822                 {
   2823                     return (AE_BAD_DATA);
   2824                 }
   2825 
   2826                 if (NodeLength < IortNode->MappingOffset)
   2827                 {
   2828                     Status = DtCompilePadding (
   2829                         IortNode->MappingOffset - NodeLength,
   2830                         &Subtable);
   2831                     if (ACPI_FAILURE (Status))
   2832                     {
   2833                         return (Status);
   2834                     }
   2835 
   2836                     DtInsertSubtable (ParentTable, Subtable);
   2837                     NodeLength = IortNode->MappingOffset;
   2838                 }
   2839             }
   2840             break;
   2841 
   2842         case ACPI_IORT_NODE_PCI_ROOT_COMPLEX:
   2843 
   2844             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort2,
   2845                 &Subtable);
   2846             if (ACPI_FAILURE (Status))
   2847             {
   2848                 return (Status);
   2849             }
   2850 
   2851             DtInsertSubtable (ParentTable, Subtable);
   2852             NodeLength += Subtable->Length;
   2853             break;
   2854 
   2855         case ACPI_IORT_NODE_SMMU:
   2856 
   2857             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3,
   2858                 &Subtable);
   2859             if (ACPI_FAILURE (Status))
   2860             {
   2861                 return (Status);
   2862             }
   2863 
   2864             DtInsertSubtable (ParentTable, Subtable);
   2865             IortSmmu = ACPI_CAST_PTR (ACPI_IORT_SMMU, Subtable->Buffer);
   2866             NodeLength += Subtable->Length;
   2867 
   2868             /* Compile global interrupt array */
   2869 
   2870             IortSmmu->GlobalInterruptOffset = NodeLength;
   2871             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3a,
   2872                 &Subtable);
   2873             if (ACPI_FAILURE (Status))
   2874             {
   2875                 return (Status);
   2876             }
   2877 
   2878             DtInsertSubtable (ParentTable, Subtable);
   2879             NodeLength += Subtable->Length;
   2880 
   2881             /* Compile context interrupt array */
   2882 
   2883             ContextIrptNumber = 0;
   2884             IortSmmu->ContextInterruptOffset = NodeLength;
   2885             while (*PFieldList)
   2886             {
   2887                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3b,
   2888                     &Subtable);
   2889                 if (ACPI_FAILURE (Status))
   2890                 {
   2891                     return (Status);
   2892                 }
   2893 
   2894                 if (!Subtable)
   2895                 {
   2896                     break;
   2897                 }
   2898 
   2899                 DtInsertSubtable (ParentTable, Subtable);
   2900                 NodeLength += Subtable->Length;
   2901                 ContextIrptNumber++;
   2902             }
   2903 
   2904             IortSmmu->ContextInterruptCount = ContextIrptNumber;
   2905 
   2906             /* Compile PMU interrupt array */
   2907 
   2908             PmuIrptNumber = 0;
   2909             IortSmmu->PmuInterruptOffset = NodeLength;
   2910             while (*PFieldList)
   2911             {
   2912                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3c,
   2913                     &Subtable);
   2914                 if (ACPI_FAILURE (Status))
   2915                 {
   2916                     return (Status);
   2917                 }
   2918 
   2919                 if (!Subtable)
   2920                 {
   2921                     break;
   2922                 }
   2923 
   2924                 DtInsertSubtable (ParentTable, Subtable);
   2925                 NodeLength += Subtable->Length;
   2926                 PmuIrptNumber++;
   2927             }
   2928 
   2929             IortSmmu->PmuInterruptCount = PmuIrptNumber;
   2930             break;
   2931 
   2932         case ACPI_IORT_NODE_SMMU_V3:
   2933 
   2934             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort4,
   2935                 &Subtable);
   2936             if (ACPI_FAILURE (Status))
   2937             {
   2938                 return (Status);
   2939             }
   2940 
   2941             DtInsertSubtable (ParentTable, Subtable);
   2942             NodeLength += Subtable->Length;
   2943             break;
   2944 
   2945         case ACPI_IORT_NODE_PMCG:
   2946 
   2947             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort5,
   2948                 &Subtable);
   2949             if (ACPI_FAILURE (Status))
   2950             {
   2951                 return (Status);
   2952             }
   2953 
   2954             DtInsertSubtable (ParentTable, Subtable);
   2955             NodeLength += Subtable->Length;
   2956             break;
   2957 
   2958         case ACPI_IORT_NODE_RMR:
   2959 
   2960             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6,
   2961                 &Subtable);
   2962             if (ACPI_FAILURE (Status))
   2963             {
   2964                 return (Status);
   2965             }
   2966 
   2967             DtInsertSubtable (ParentTable, Subtable);
   2968             IortRmr = ACPI_CAST_PTR (ACPI_IORT_RMR, Subtable->Buffer);
   2969             NodeLength += Subtable->Length;
   2970 
   2971             /* Compile RMR Descriptors */
   2972 
   2973             RmrCount = 0;
   2974             IortRmr->RmrOffset = NodeLength;
   2975             while (*PFieldList)
   2976             {
   2977                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6a,
   2978                     &Subtable);
   2979                 if (ACPI_FAILURE (Status))
   2980                 {
   2981                     return (Status);
   2982                 }
   2983 
   2984                 if (!Subtable)
   2985                 {
   2986                     break;
   2987                 }
   2988 
   2989                 DtInsertSubtable (ParentTable, Subtable);
   2990                 NodeLength += sizeof (ACPI_IORT_RMR_DESC);
   2991                 RmrCount++;
   2992             }
   2993 
   2994             IortRmr->RmrCount = RmrCount;
   2995             break;
   2996 
   2997         case ACPI_IORT_NODE_IWB:
   2998 
   2999             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort7,
   3000                 &Subtable);
   3001             if (ACPI_FAILURE (Status))
   3002             {
   3003                 return (Status);
   3004             }
   3005 
   3006             DtInsertSubtable (ParentTable, Subtable);
   3007             NodeLength += Subtable->Length;
   3008             break;
   3009 
   3010         default:
   3011 
   3012             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IORT");
   3013             return (AE_ERROR);
   3014         }
   3015 
   3016         /* Compile Array of ID mappings */
   3017 
   3018         IortNode->MappingOffset = NodeLength;
   3019         IdMappingNumber = 0;
   3020         while (*PFieldList)
   3021         {
   3022             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortMap,
   3023                 &Subtable);
   3024             if (ACPI_FAILURE (Status))
   3025             {
   3026                 return (Status);
   3027             }
   3028 
   3029             if (!Subtable)
   3030             {
   3031                 break;
   3032             }
   3033 
   3034             DtInsertSubtable (ParentTable, Subtable);
   3035             NodeLength += sizeof (ACPI_IORT_ID_MAPPING);
   3036             IdMappingNumber++;
   3037         }
   3038 
   3039         IortNode->MappingCount = IdMappingNumber;
   3040         if (!IdMappingNumber)
   3041         {
   3042             IortNode->MappingOffset = 0;
   3043         }
   3044 
   3045         /*
   3046          * Node length can be determined by DT_LENGTH option
   3047          * IortNode->Length = NodeLength;
   3048          */
   3049         DtPopSubtable ();
   3050         ParentTable = DtPeekSubtable ();
   3051         NodeNumber++;
   3052     }
   3053 
   3054     Iort->NodeCount = NodeNumber;
   3055     return (AE_OK);
   3056 }
   3057 
   3058 
   3059 /******************************************************************************
   3060  *
   3061  * FUNCTION:    DtCompileIovt
   3062  *
   3063  * PARAMETERS:  List                - Current field list pointer
   3064  *
   3065  * RETURN:      Status
   3066  *
   3067  * DESCRIPTION: Compile Iovt. Notes:
   3068  *              The IOVT is essentially a flat table, with the following
   3069  *              structure:
   3070  *              <Main ACPI Table Header>
   3071  *              <Main subtable - virtualization info>
   3072  *              <IOVT>
   3073  *                  <Device Entries>
   3074  *              ...
   3075  *              <IOVT>
   3076  *              <IOVT>
   3077  *              ...
   3078  *
   3079  *****************************************************************************/
   3080 
   3081 ACPI_STATUS
   3082 DtCompileIovt (
   3083     void                    **List)
   3084 {
   3085     ACPI_STATUS             Status;
   3086     DT_SUBTABLE             *Subtable;
   3087     DT_SUBTABLE             *ParentTable;
   3088     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   3089     ACPI_TABLE_IOVT         *Iovt;
   3090     UINT16                  IommuCount;
   3091     ACPI_IOVT_IOMMU         *Iommu;
   3092     UINT32                  DeviceEntryNum;
   3093 
   3094 
   3095     ParentTable = DtPeekSubtable ();
   3096     /* Main table */
   3097 
   3098     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIovt,
   3099         &Subtable);
   3100     if (ACPI_FAILURE (Status))
   3101     {
   3102         return (Status);
   3103     }
   3104 
   3105     DtInsertSubtable (ParentTable, Subtable);
   3106     DtPushSubtable (Subtable);
   3107 
   3108     Iovt = ACPI_SUB_PTR (ACPI_TABLE_IOVT, Subtable->Buffer,
   3109         sizeof (ACPI_TABLE_HEADER));
   3110 
   3111     for (IommuCount = 0; IommuCount < Iovt->IommuCount; IommuCount++)
   3112     {
   3113         Status = DtCompileTable (PFieldList, AcpiDmTableInfoIovt0,
   3114             &Subtable);
   3115         if (ACPI_FAILURE (Status))
   3116         {
   3117             return (Status);
   3118         }
   3119 
   3120         ParentTable = DtPeekSubtable ();
   3121         DtInsertSubtable (ParentTable, Subtable);
   3122         DtPushSubtable (Subtable);
   3123 
   3124         Iommu = ACPI_CAST_PTR(ACPI_IOVT_IOMMU, Subtable->Buffer);
   3125         for (DeviceEntryNum = 0; DeviceEntryNum < Iommu->DeviceEntryNum; DeviceEntryNum++)
   3126         {
   3127             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIovtdev,
   3128                 &Subtable);
   3129             if (ACPI_FAILURE (Status))
   3130             {
   3131                 return (Status);
   3132             }
   3133 
   3134             ParentTable = DtPeekSubtable ();
   3135             DtInsertSubtable (ParentTable, Subtable);
   3136         }
   3137         DtPopSubtable();
   3138     }
   3139 
   3140     return (AE_OK);
   3141 }
   3142 
   3143 
   3144 /******************************************************************************
   3145  *
   3146  * FUNCTION:    DtCompileIvrs
   3147  *
   3148  * PARAMETERS:  List                - Current field list pointer
   3149  *
   3150  * RETURN:      Status
   3151  *
   3152  * DESCRIPTION: Compile IVRS. Notes:
   3153  *              The IVRS is essentially a flat table, with the following
   3154  *              structure:
   3155  *              <Main ACPI Table Header>
   3156  *              <Main subtable - virtualization info>
   3157  *              <IVHD>
   3158  *                  <Device Entries>
   3159  *              ...
   3160  *              <IVHD>
   3161  *                  <Device Entries>
   3162  *              <IVMD>
   3163  *              ...
   3164  *
   3165  *****************************************************************************/
   3166 
   3167 ACPI_STATUS
   3168 DtCompileIvrs (
   3169     void                    **List)
   3170 {
   3171     ACPI_STATUS             Status;
   3172     DT_SUBTABLE             *Subtable;
   3173     DT_SUBTABLE             *ParentTable;
   3174     DT_SUBTABLE             *MainSubtable;
   3175     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   3176     DT_FIELD                *SubtableStart;
   3177     ACPI_DMTABLE_INFO       *InfoTable = NULL;
   3178     UINT8                   SubtableType;
   3179     UINT8                   Temp64[16];
   3180     UINT8                   Temp8;
   3181 
   3182 
   3183     /* Main table */
   3184 
   3185     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrs,
   3186         &Subtable);
   3187     if (ACPI_FAILURE (Status))
   3188     {
   3189         return (Status);
   3190     }
   3191 
   3192     ParentTable = DtPeekSubtable ();
   3193     DtInsertSubtable (ParentTable, Subtable);
   3194     DtPushSubtable (Subtable);
   3195 
   3196     /* Save a pointer to the main subtable */
   3197 
   3198     MainSubtable = Subtable;
   3199 
   3200     while (*PFieldList)
   3201     {
   3202         SubtableStart = *PFieldList;
   3203 
   3204         /* Compile the SubtableType integer */
   3205 
   3206         DtCompileInteger (&SubtableType, *PFieldList, 1, 0);
   3207 
   3208         switch (SubtableType)
   3209         {
   3210 
   3211         /* Type 10h, IVHD (I/O Virtualization Hardware Definition) */
   3212 
   3213         case ACPI_IVRS_TYPE_HARDWARE1:
   3214 
   3215             InfoTable = AcpiDmTableInfoIvrsHware1;
   3216             break;
   3217 
   3218         /* Types 11h, 40h, IVHD (I/O Virtualization Hardware Definition) */
   3219 
   3220         case ACPI_IVRS_TYPE_HARDWARE2:
   3221         case ACPI_IVRS_TYPE_HARDWARE3:
   3222 
   3223             InfoTable = AcpiDmTableInfoIvrsHware23;
   3224             break;
   3225 
   3226         /* Types 20h, 21h, 22h, IVMD (I/O Virtualization Memory Definition Block) */
   3227 
   3228         case ACPI_IVRS_TYPE_MEMORY1:
   3229         case ACPI_IVRS_TYPE_MEMORY2:
   3230         case ACPI_IVRS_TYPE_MEMORY3:
   3231 
   3232             InfoTable = AcpiDmTableInfoIvrsMemory;
   3233             break;
   3234 
   3235         /* 4-byte device entries */
   3236 
   3237         case ACPI_IVRS_TYPE_PAD4:
   3238         case ACPI_IVRS_TYPE_ALL:
   3239         case ACPI_IVRS_TYPE_SELECT:
   3240         case ACPI_IVRS_TYPE_START:
   3241         case ACPI_IVRS_TYPE_END:
   3242 
   3243             InfoTable = AcpiDmTableInfoIvrs4;
   3244             break;
   3245 
   3246         /* 8-byte device entries, type A */
   3247 
   3248         case ACPI_IVRS_TYPE_ALIAS_SELECT:
   3249         case ACPI_IVRS_TYPE_ALIAS_START:
   3250 
   3251             InfoTable = AcpiDmTableInfoIvrs8a;
   3252             break;
   3253 
   3254         /* 8-byte device entries, type B */
   3255 
   3256         case ACPI_IVRS_TYPE_EXT_SELECT:
   3257         case ACPI_IVRS_TYPE_EXT_START:
   3258 
   3259             InfoTable = AcpiDmTableInfoIvrs8b;
   3260             break;
   3261 
   3262         /* 8-byte device entries, type C */
   3263 
   3264         case ACPI_IVRS_TYPE_SPECIAL:
   3265 
   3266             InfoTable = AcpiDmTableInfoIvrs8c;
   3267             break;
   3268 
   3269         /* Variable device entries, type F0h */
   3270 
   3271         case ACPI_IVRS_TYPE_HID:
   3272 
   3273             InfoTable = AcpiDmTableInfoIvrsHid;
   3274             break;
   3275 
   3276         default:
   3277 
   3278             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart,
   3279                 "IVRS Device Entry");
   3280             return (AE_ERROR);
   3281         }
   3282 
   3283         /* Compile the InfoTable from above */
   3284 
   3285         Status = DtCompileTable (PFieldList, InfoTable,
   3286             &Subtable);
   3287         if (ACPI_FAILURE (Status))
   3288         {
   3289             return (Status);
   3290         }
   3291 
   3292         ParentTable = DtPeekSubtable ();
   3293         if (SubtableType != ACPI_IVRS_TYPE_HARDWARE1 &&
   3294             SubtableType != ACPI_IVRS_TYPE_HARDWARE2 &&
   3295             SubtableType != ACPI_IVRS_TYPE_HARDWARE3 &&
   3296             SubtableType != ACPI_IVRS_TYPE_HID &&
   3297             SubtableType != ACPI_IVRS_TYPE_MEMORY1 &&
   3298             SubtableType != ACPI_IVRS_TYPE_MEMORY2 &&
   3299             SubtableType != ACPI_IVRS_TYPE_MEMORY3)
   3300         {
   3301             if (ParentTable)
   3302                 DtInsertSubtable (ParentTable, Subtable);
   3303         }
   3304 
   3305         switch (SubtableType)
   3306         {
   3307         case ACPI_IVRS_TYPE_HARDWARE1:
   3308         case ACPI_IVRS_TYPE_HARDWARE2:
   3309         case ACPI_IVRS_TYPE_HARDWARE3:
   3310         case ACPI_IVRS_TYPE_MEMORY1:
   3311         case ACPI_IVRS_TYPE_MEMORY2:
   3312         case ACPI_IVRS_TYPE_MEMORY3:
   3313 
   3314             /* Insert these IVHDs/IVMDs at the root subtable */
   3315 
   3316             DtInsertSubtable (MainSubtable, Subtable);
   3317             DtPushSubtable (Subtable);
   3318             break;
   3319 
   3320         case ACPI_IVRS_TYPE_HID:
   3321 
   3322             /* Special handling for the HID named device entry (0xF0) */
   3323 
   3324             if (ParentTable)
   3325             {
   3326                 DtInsertSubtable (ParentTable, Subtable);
   3327             }
   3328 
   3329             /*
   3330              * Process the HID value. First, get the HID value as a string.
   3331              */
   3332             DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0);
   3333 
   3334                /*
   3335                 * Determine if the HID is an integer or a string.
   3336                 * An integer is defined to be 32 bits, with the upper 32 bits
   3337                 * set to zero. (from the ACPI Spec): "The HID can be a 32-bit
   3338                 * integer or a character string. If an integer, the lower
   3339                 * 4 bytes of the field contain the integer and the upper
   3340                 * 4 bytes are padded with 0".
   3341                 */
   3342             if (UtIsIdInteger ((UINT8 *) &Temp64))
   3343             {
   3344                 /* Compile the HID value as an integer */
   3345 
   3346                 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0);
   3347 
   3348                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidInteger,
   3349                     &Subtable);
   3350                 if (ACPI_FAILURE (Status))
   3351                 {
   3352                     return (Status);
   3353                 }
   3354             }
   3355             else
   3356             {
   3357                 /* Compile the HID value as a string */
   3358 
   3359                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidString,
   3360                     &Subtable);
   3361                 if (ACPI_FAILURE (Status))
   3362                 {
   3363                     return (Status);
   3364                 }
   3365             }
   3366 
   3367             DtInsertSubtable (ParentTable, Subtable);
   3368 
   3369             /*
   3370              * Process the CID value. First, get the CID value as a string.
   3371              */
   3372             DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0);
   3373 
   3374             if (UtIsIdInteger ((UINT8 *) &Temp64))
   3375             {
   3376                 /* Compile the CID value as an integer */
   3377 
   3378                 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0);
   3379 
   3380                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidInteger,
   3381                     &Subtable);
   3382                 if (ACPI_FAILURE (Status))
   3383                 {
   3384                     return (Status);
   3385                 }
   3386             }
   3387             else
   3388             {
   3389                 /* Compile the CID value as a string */
   3390 
   3391                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidString,
   3392                     &Subtable);
   3393                 if (ACPI_FAILURE (Status))
   3394                 {
   3395                     return (Status);
   3396                 }
   3397             }
   3398 
   3399             DtInsertSubtable (ParentTable, Subtable);
   3400 
   3401             /*
   3402              * Process the UID value. First, get and decode the "UID Format" field (Integer).
   3403              */
   3404             if (!*PFieldList)
   3405             {
   3406                 return (AE_OK);
   3407             }
   3408 
   3409             DtCompileOneField (&Temp8, *PFieldList, 1, DT_FIELD_TYPE_INTEGER, 0);
   3410 
   3411             switch (Temp8)
   3412             {
   3413             case ACPI_IVRS_UID_NOT_PRESENT:
   3414                 break;
   3415 
   3416             case ACPI_IVRS_UID_IS_INTEGER:
   3417 
   3418                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidInteger,
   3419                     &Subtable);
   3420                 if (ACPI_FAILURE (Status))
   3421                 {
   3422                     return (Status);
   3423                 }
   3424                 DtInsertSubtable (ParentTable, Subtable);
   3425                 break;
   3426 
   3427             case ACPI_IVRS_UID_IS_STRING:
   3428 
   3429                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidString,
   3430                     &Subtable);
   3431                 if (ACPI_FAILURE (Status))
   3432                 {
   3433                     return (Status);
   3434                 }
   3435                 DtInsertSubtable (ParentTable, Subtable);
   3436                 break;
   3437 
   3438             default:
   3439 
   3440                 DtFatal (ASL_MSG_UNKNOWN_FORMAT, SubtableStart,
   3441                     "IVRS Device Entry");
   3442                 return (AE_ERROR);
   3443             }
   3444 
   3445         default:
   3446 
   3447             /* All other subtable types come through here */
   3448             break;
   3449         }
   3450     }
   3451 
   3452     return (AE_OK);
   3453 }
   3454 
   3455 
   3456 /******************************************************************************
   3457  *
   3458  * FUNCTION:    DtCompileRimt
   3459  *
   3460  * PARAMETERS:  List                - Current field list pointer
   3461  *
   3462  * RETURN:      Status
   3463  *
   3464  * DESCRIPTION: Compile RIMT.
   3465  *
   3466  *****************************************************************************/
   3467 
   3468 ACPI_STATUS
   3469 DtCompileRimt (
   3470     void                    **List)
   3471 {
   3472     ACPI_RIMT_PLATFORM_DEVICE  *PlatDevNode;
   3473     ACPI_RIMT_PCIE_RC          *PcieRcNode;
   3474     ACPI_TABLE_RIMT            *Rimt;
   3475     ACPI_RIMT_IOMMU            *IommuNode;
   3476     ACPI_RIMT_NODE             *RimtNode;
   3477     ACPI_STATUS                Status;
   3478     DT_SUBTABLE                *Subtable;
   3479     DT_SUBTABLE                *ParentTable;
   3480     DT_FIELD                   **PFieldList = (DT_FIELD **) List;
   3481     DT_FIELD                   *SubtableStart;
   3482     UINT32                     NodeNumber;
   3483     UINT32                     NodeLength;
   3484     UINT16                     IdMappingNumber;
   3485     UINT32                     i;
   3486 
   3487 
   3488     ParentTable = DtPeekSubtable ();
   3489 
   3490     Status = DtCompileTable (PFieldList, AcpiDmTableInfoRimt, &Subtable);
   3491     if (ACPI_FAILURE (Status))
   3492     {
   3493         return (Status);
   3494     }
   3495 
   3496     DtInsertSubtable (ParentTable, Subtable);
   3497 
   3498     /*
   3499      * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
   3500      * should be taken to avoid accessing ACPI_TABLE_HEADER fields.
   3501      */
   3502     Rimt = ACPI_SUB_PTR (ACPI_TABLE_RIMT, Subtable->Buffer,
   3503                          sizeof (ACPI_TABLE_HEADER));
   3504 
   3505     NodeNumber = 0;
   3506     while (*PFieldList)
   3507     {
   3508         SubtableStart = *PFieldList;
   3509         Status = DtCompileTable (PFieldList, AcpiDmTableInfoRimtNodeHdr, &Subtable);
   3510 
   3511         if (ACPI_FAILURE (Status))
   3512         {
   3513             return (Status);
   3514         }
   3515 
   3516         DtInsertSubtable (ParentTable, Subtable);
   3517         RimtNode = ACPI_CAST_PTR (ACPI_RIMT_NODE, Subtable->Buffer);
   3518         NodeLength = ACPI_OFFSET (ACPI_RIMT_NODE, NodeData);
   3519 
   3520         DtPushSubtable (Subtable);
   3521         ParentTable = DtPeekSubtable ();
   3522 
   3523         switch (RimtNode->Type)
   3524         {
   3525         case ACPI_RIMT_NODE_TYPE_IOMMU:
   3526 
   3527             Status = DtCompileTable (PFieldList, AcpiDmTableInfoRimtIommu,
   3528                                      &Subtable);
   3529             if (ACPI_FAILURE (Status))
   3530             {
   3531                 return (Status);
   3532             }
   3533 
   3534             IommuNode = ACPI_CAST_PTR (ACPI_RIMT_IOMMU, Subtable->Buffer);
   3535             DtInsertSubtable (ParentTable, Subtable);
   3536             NodeLength += Subtable->Length;
   3537 
   3538             for (i = 0; i < IommuNode->NumInterruptWires; i++)
   3539             {
   3540                 while (*PFieldList)
   3541                 {
   3542                     Status = DtCompileTable (PFieldList,
   3543                                              AcpiDmTableInfoRimtIommuWire,
   3544                                              &Subtable);
   3545                     if (ACPI_FAILURE (Status))
   3546                     {
   3547                         return (Status);
   3548                     }
   3549                     if (!Subtable)
   3550                     {
   3551                         break;
   3552                     }
   3553 
   3554                     DtInsertSubtable (ParentTable, Subtable);
   3555                     NodeLength += Subtable->Length;
   3556                 }
   3557             }
   3558 
   3559             break;
   3560 
   3561         case ACPI_RIMT_NODE_TYPE_PCIE_ROOT_COMPLEX:
   3562 
   3563             Status = DtCompileTable (PFieldList, AcpiDmTableInfoRimtPcieRc,
   3564                                      &Subtable);
   3565             if (ACPI_FAILURE (Status))
   3566             {
   3567                 return (Status);
   3568             }
   3569 
   3570             DtInsertSubtable (ParentTable, Subtable);
   3571             PcieRcNode = ACPI_CAST_PTR (ACPI_RIMT_PCIE_RC, Subtable->Buffer);
   3572             NodeLength += Subtable->Length;
   3573 
   3574             /* Compile Array of ID mappings */
   3575 
   3576             PcieRcNode->IdMappingOffset = (UINT16) NodeLength;
   3577             IdMappingNumber = 0;
   3578             while (*PFieldList)
   3579             {
   3580                 Status = DtCompileTable (PFieldList,
   3581                                          AcpiDmTableInfoRimtIdMapping,
   3582                                          &Subtable);
   3583                 if (ACPI_FAILURE (Status))
   3584                 {
   3585                     return (Status);
   3586                 }
   3587 
   3588                 if (!Subtable)
   3589                 {
   3590                     break;
   3591                 }
   3592 
   3593                 DtInsertSubtable (ParentTable, Subtable);
   3594                 NodeLength += sizeof (ACPI_RIMT_ID_MAPPING);
   3595                 IdMappingNumber++;
   3596             }
   3597 
   3598             PcieRcNode->NumIdMappings = IdMappingNumber;
   3599             if (!IdMappingNumber)
   3600             {
   3601                 PcieRcNode->IdMappingOffset = 0;
   3602             }
   3603 
   3604             break;
   3605 
   3606         case ACPI_RIMT_NODE_TYPE_PLAT_DEVICE:
   3607 
   3608             Status = DtCompileTable (PFieldList, AcpiDmTableInfoRimtPlatDev,
   3609                                      &Subtable);
   3610             if (ACPI_FAILURE (Status))
   3611             {
   3612                 return (Status);
   3613             }
   3614 
   3615             DtInsertSubtable (ParentTable, Subtable);
   3616             PlatDevNode = ACPI_CAST_PTR (ACPI_RIMT_PLATFORM_DEVICE, Subtable->Buffer);
   3617             NodeLength += Subtable->Length;
   3618 
   3619             /*
   3620              * Padding - Variable-length data
   3621              * Optionally allows the offset of the ID mappings to be used
   3622              * for filling this field.
   3623              */
   3624             Status = DtCompileTable (PFieldList, AcpiDmTableInfoRimtPlatDevPad,
   3625                                      &Subtable);
   3626             if (ACPI_FAILURE (Status))
   3627             {
   3628                 return (Status);
   3629             }
   3630 
   3631             if (Subtable)
   3632             {
   3633                 DtInsertSubtable (ParentTable, Subtable);
   3634                 NodeLength += Subtable->Length;
   3635             }
   3636             else
   3637             {
   3638                 if (NodeLength > PlatDevNode->IdMappingOffset)
   3639                 {
   3640                     return (AE_BAD_DATA);
   3641                 }
   3642 
   3643                 if (NodeLength < PlatDevNode->IdMappingOffset)
   3644                 {
   3645                     Status = DtCompilePadding (
   3646                         PlatDevNode->IdMappingOffset - (UINT16) NodeLength,
   3647                         &Subtable);
   3648                     if (ACPI_FAILURE (Status))
   3649                     {
   3650                         return (Status);
   3651                     }
   3652 
   3653                     DtInsertSubtable (ParentTable, Subtable);
   3654                     NodeLength = PlatDevNode->IdMappingOffset;
   3655                 }
   3656             }
   3657 
   3658             /* Compile Array of ID mappings */
   3659 
   3660             PlatDevNode->IdMappingOffset = (UINT16) NodeLength;
   3661             IdMappingNumber = 0;
   3662             while (*PFieldList)
   3663             {
   3664                 Status = DtCompileTable (PFieldList,
   3665                                          AcpiDmTableInfoRimtIdMapping,
   3666                                          &Subtable);
   3667                 if (ACPI_FAILURE (Status))
   3668                 {
   3669                     return (Status);
   3670                 }
   3671 
   3672                 if (!Subtable)
   3673                 {
   3674                     break;
   3675                 }
   3676 
   3677                 DtInsertSubtable (ParentTable, Subtable);
   3678                 NodeLength += sizeof (ACPI_RIMT_ID_MAPPING);
   3679                 IdMappingNumber++;
   3680             }
   3681 
   3682             PlatDevNode->NumIdMappings = IdMappingNumber;
   3683             if (!IdMappingNumber)
   3684             {
   3685                 PlatDevNode->IdMappingOffset = 0;
   3686             }
   3687 
   3688             break;
   3689 
   3690 
   3691         default:
   3692 
   3693             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "RIMT");
   3694             return (AE_ERROR);
   3695         }
   3696 
   3697         DtPopSubtable ();
   3698         ParentTable = DtPeekSubtable ();
   3699         NodeNumber++;
   3700     }
   3701 
   3702     Rimt->NumNodes = NodeNumber;
   3703     return (AE_OK);
   3704 }
   3705