Home | History | Annotate | Line # | Download | only in compiler
dttable1.c revision 1.1.1.17
      1 /******************************************************************************
      2  *
      3  * Module Name: dttable1.c - handling for specific ACPI tables
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2023, 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         default:
   1403 
   1404             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "DMAR");
   1405             return (AE_ERROR);
   1406         }
   1407 
   1408         /* DMAR Subtable */
   1409 
   1410         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
   1411         if (ACPI_FAILURE (Status))
   1412         {
   1413             return (Status);
   1414         }
   1415 
   1416         ParentTable = DtPeekSubtable ();
   1417         DtInsertSubtable (ParentTable, Subtable);
   1418 
   1419         /*
   1420          * Optional Device Scope subtables
   1421          */
   1422         if ((DmarHeader->Type == ACPI_DMAR_TYPE_HARDWARE_AFFINITY) ||
   1423             (DmarHeader->Type == ACPI_DMAR_TYPE_NAMESPACE))
   1424         {
   1425             /* These types do not support device scopes */
   1426 
   1427             DtPopSubtable ();
   1428             continue;
   1429         }
   1430 
   1431         DtPushSubtable (Subtable);
   1432         DeviceScopeLength = DmarHeader->Length - Subtable->Length -
   1433             ParentTable->Length;
   1434         while (DeviceScopeLength)
   1435         {
   1436             Status = DtCompileTable (PFieldList, AcpiDmTableInfoDmarScope,
   1437                 &Subtable);
   1438             if (Status == AE_NOT_FOUND)
   1439             {
   1440                 break;
   1441             }
   1442 
   1443             ParentTable = DtPeekSubtable ();
   1444             DtInsertSubtable (ParentTable, Subtable);
   1445             DtPushSubtable (Subtable);
   1446 
   1447             DmarDeviceScope = ACPI_CAST_PTR (ACPI_DMAR_DEVICE_SCOPE, Subtable->Buffer);
   1448 
   1449             /* Optional PCI Paths */
   1450 
   1451             PciPathLength = DmarDeviceScope->Length - Subtable->Length;
   1452             while (PciPathLength)
   1453             {
   1454                 Status = DtCompileTable (PFieldList, TableInfoDmarPciPath,
   1455                     &Subtable);
   1456                 if (Status == AE_NOT_FOUND)
   1457                 {
   1458                     DtPopSubtable ();
   1459                     break;
   1460                 }
   1461 
   1462                 ParentTable = DtPeekSubtable ();
   1463                 DtInsertSubtable (ParentTable, Subtable);
   1464                 PciPathLength -= Subtable->Length;
   1465             }
   1466 
   1467             DtPopSubtable ();
   1468             DeviceScopeLength -= DmarDeviceScope->Length;
   1469         }
   1470 
   1471         DtPopSubtable ();
   1472         DtPopSubtable ();
   1473     }
   1474 
   1475     return (AE_OK);
   1476 }
   1477 
   1478 
   1479 /******************************************************************************
   1480  *
   1481  * FUNCTION:    DtCompileDrtm
   1482  *
   1483  * PARAMETERS:  List                - Current field list pointer
   1484  *
   1485  * RETURN:      Status
   1486  *
   1487  * DESCRIPTION: Compile DRTM.
   1488  *
   1489  *****************************************************************************/
   1490 
   1491 ACPI_STATUS
   1492 DtCompileDrtm (
   1493     void                    **List)
   1494 {
   1495     ACPI_STATUS             Status;
   1496     DT_SUBTABLE             *Subtable;
   1497     DT_SUBTABLE             *ParentTable;
   1498     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   1499     UINT32                  Count;
   1500     /* ACPI_TABLE_DRTM         *Drtm; */
   1501     ACPI_DRTM_VTABLE_LIST   *DrtmVtl;
   1502     ACPI_DRTM_RESOURCE_LIST *DrtmRl;
   1503     /* ACPI_DRTM_DPS_ID        *DrtmDps; */
   1504 
   1505 
   1506     ParentTable = DtPeekSubtable ();
   1507 
   1508     /* Compile DRTM header */
   1509 
   1510     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm,
   1511         &Subtable);
   1512     if (ACPI_FAILURE (Status))
   1513     {
   1514         return (Status);
   1515     }
   1516     DtInsertSubtable (ParentTable, Subtable);
   1517 
   1518     /*
   1519      * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
   1520      * should be taken to avoid accessing ACPI_TABLE_HADER fields.
   1521      */
   1522 #if 0
   1523     Drtm = ACPI_SUB_PTR (ACPI_TABLE_DRTM,
   1524         Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
   1525 #endif
   1526     /* Compile VTL */
   1527 
   1528     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0,
   1529         &Subtable);
   1530     if (ACPI_FAILURE (Status))
   1531     {
   1532         return (Status);
   1533     }
   1534 
   1535     DtInsertSubtable (ParentTable, Subtable);
   1536     DrtmVtl = ACPI_CAST_PTR (ACPI_DRTM_VTABLE_LIST, Subtable->Buffer);
   1537 
   1538     DtPushSubtable (Subtable);
   1539     ParentTable = DtPeekSubtable ();
   1540     Count = 0;
   1541 
   1542     while (*PFieldList)
   1543     {
   1544         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm0a,
   1545             &Subtable);
   1546         if (ACPI_FAILURE (Status))
   1547         {
   1548             return (Status);
   1549         }
   1550         if (!Subtable)
   1551         {
   1552             break;
   1553         }
   1554         DtInsertSubtable (ParentTable, Subtable);
   1555         Count++;
   1556     }
   1557 
   1558     DrtmVtl->ValidatedTableCount = Count;
   1559     DtPopSubtable ();
   1560     ParentTable = DtPeekSubtable ();
   1561 
   1562     /* Compile RL */
   1563 
   1564     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1,
   1565         &Subtable);
   1566     if (ACPI_FAILURE (Status))
   1567     {
   1568         return (Status);
   1569     }
   1570 
   1571     DtInsertSubtable (ParentTable, Subtable);
   1572     DrtmRl = ACPI_CAST_PTR (ACPI_DRTM_RESOURCE_LIST, Subtable->Buffer);
   1573 
   1574     DtPushSubtable (Subtable);
   1575     ParentTable = DtPeekSubtable ();
   1576     Count = 0;
   1577 
   1578     while (*PFieldList)
   1579     {
   1580         Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm1a,
   1581             &Subtable);
   1582         if (ACPI_FAILURE (Status))
   1583         {
   1584             return (Status);
   1585         }
   1586 
   1587         if (!Subtable)
   1588         {
   1589             break;
   1590         }
   1591 
   1592         DtInsertSubtable (ParentTable, Subtable);
   1593         Count++;
   1594     }
   1595 
   1596     DrtmRl->ResourceCount = Count;
   1597     DtPopSubtable ();
   1598     ParentTable = DtPeekSubtable ();
   1599 
   1600     /* Compile DPS */
   1601 
   1602     Status = DtCompileTable (PFieldList, AcpiDmTableInfoDrtm2,
   1603         &Subtable);
   1604     if (ACPI_FAILURE (Status))
   1605     {
   1606         return (Status);
   1607     }
   1608     DtInsertSubtable (ParentTable, Subtable);
   1609     /* DrtmDps = ACPI_CAST_PTR (ACPI_DRTM_DPS_ID, Subtable->Buffer);*/
   1610 
   1611 
   1612     return (AE_OK);
   1613 }
   1614 
   1615 
   1616 /******************************************************************************
   1617  *
   1618  * FUNCTION:    DtCompileEinj
   1619  *
   1620  * PARAMETERS:  List                - Current field list pointer
   1621  *
   1622  * RETURN:      Status
   1623  *
   1624  * DESCRIPTION: Compile EINJ.
   1625  *
   1626  *****************************************************************************/
   1627 
   1628 ACPI_STATUS
   1629 DtCompileEinj (
   1630     void                    **List)
   1631 {
   1632     ACPI_STATUS             Status;
   1633 
   1634 
   1635     Status = DtCompileTwoSubtables (List,
   1636         AcpiDmTableInfoEinj, AcpiDmTableInfoEinj0);
   1637     return (Status);
   1638 }
   1639 
   1640 
   1641 /******************************************************************************
   1642  *
   1643  * FUNCTION:    DtCompileErst
   1644  *
   1645  * PARAMETERS:  List                - Current field list pointer
   1646  *
   1647  * RETURN:      Status
   1648  *
   1649  * DESCRIPTION: Compile ERST.
   1650  *
   1651  *****************************************************************************/
   1652 
   1653 ACPI_STATUS
   1654 DtCompileErst (
   1655     void                    **List)
   1656 {
   1657     ACPI_STATUS             Status;
   1658 
   1659 
   1660     Status = DtCompileTwoSubtables (List,
   1661         AcpiDmTableInfoErst, AcpiDmTableInfoEinj0);
   1662     return (Status);
   1663 }
   1664 
   1665 
   1666 /******************************************************************************
   1667  *
   1668  * FUNCTION:    DtCompileGtdt
   1669  *
   1670  * PARAMETERS:  List                - Current field list pointer
   1671  *
   1672  * RETURN:      Status
   1673  *
   1674  * DESCRIPTION: Compile GTDT.
   1675  *
   1676  *****************************************************************************/
   1677 
   1678 ACPI_STATUS
   1679 DtCompileGtdt (
   1680     void                    **List)
   1681 {
   1682     ACPI_STATUS             Status;
   1683     DT_SUBTABLE             *Subtable;
   1684     DT_SUBTABLE             *ParentTable;
   1685     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   1686     DT_FIELD                *SubtableStart;
   1687     ACPI_SUBTABLE_HEADER    *GtdtHeader;
   1688     ACPI_DMTABLE_INFO       *InfoTable;
   1689     UINT32                  GtCount;
   1690     ACPI_TABLE_HEADER       *Header;
   1691 
   1692 
   1693     ParentTable = DtPeekSubtable ();
   1694 
   1695     Header = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer);
   1696 
   1697     /* Compile the main table */
   1698 
   1699     Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt,
   1700         &Subtable);
   1701     if (ACPI_FAILURE (Status))
   1702     {
   1703         return (Status);
   1704     }
   1705 
   1706     /* GTDT revision 3 later contains 2 extra fields before subtables */
   1707 
   1708     if (Header->Revision > 2)
   1709     {
   1710         ParentTable = DtPeekSubtable ();
   1711         DtInsertSubtable (ParentTable, Subtable);
   1712 
   1713         Status = DtCompileTable (PFieldList,
   1714             AcpiDmTableInfoGtdtEl2, &Subtable);
   1715         if (ACPI_FAILURE (Status))
   1716         {
   1717             return (Status);
   1718         }
   1719     }
   1720 
   1721     ParentTable = DtPeekSubtable ();
   1722     DtInsertSubtable (ParentTable, Subtable);
   1723 
   1724     while (*PFieldList)
   1725     {
   1726         SubtableStart = *PFieldList;
   1727         Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdtHdr,
   1728             &Subtable);
   1729         if (ACPI_FAILURE (Status))
   1730         {
   1731             return (Status);
   1732         }
   1733 
   1734         ParentTable = DtPeekSubtable ();
   1735         DtInsertSubtable (ParentTable, Subtable);
   1736         DtPushSubtable (Subtable);
   1737 
   1738         GtdtHeader = ACPI_CAST_PTR (ACPI_SUBTABLE_HEADER, Subtable->Buffer);
   1739 
   1740         switch (GtdtHeader->Type)
   1741         {
   1742         case ACPI_GTDT_TYPE_TIMER_BLOCK:
   1743 
   1744             InfoTable = AcpiDmTableInfoGtdt0;
   1745             break;
   1746 
   1747         case ACPI_GTDT_TYPE_WATCHDOG:
   1748 
   1749             InfoTable = AcpiDmTableInfoGtdt1;
   1750             break;
   1751 
   1752         default:
   1753 
   1754             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "GTDT");
   1755             return (AE_ERROR);
   1756         }
   1757 
   1758         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
   1759         if (ACPI_FAILURE (Status))
   1760         {
   1761             return (Status);
   1762         }
   1763 
   1764         ParentTable = DtPeekSubtable ();
   1765         DtInsertSubtable (ParentTable, Subtable);
   1766 
   1767         /*
   1768          * Additional GT block subtable data
   1769          */
   1770 
   1771         switch (GtdtHeader->Type)
   1772         {
   1773         case ACPI_GTDT_TYPE_TIMER_BLOCK:
   1774 
   1775             DtPushSubtable (Subtable);
   1776             ParentTable = DtPeekSubtable ();
   1777 
   1778             GtCount = (ACPI_CAST_PTR (ACPI_GTDT_TIMER_BLOCK,
   1779                 Subtable->Buffer - sizeof(ACPI_GTDT_HEADER)))->TimerCount;
   1780 
   1781             while (GtCount)
   1782             {
   1783                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoGtdt0a,
   1784                     &Subtable);
   1785                 if (ACPI_FAILURE (Status))
   1786                 {
   1787                     return (Status);
   1788                 }
   1789 
   1790                 DtInsertSubtable (ParentTable, Subtable);
   1791                 GtCount--;
   1792             }
   1793 
   1794             DtPopSubtable ();
   1795             break;
   1796 
   1797         default:
   1798 
   1799             break;
   1800         }
   1801 
   1802         DtPopSubtable ();
   1803     }
   1804 
   1805     return (AE_OK);
   1806 }
   1807 
   1808 
   1809 /******************************************************************************
   1810  *
   1811  * FUNCTION:    DtCompileFpdt
   1812  *
   1813  * PARAMETERS:  List                - Current field list pointer
   1814  *
   1815  * RETURN:      Status
   1816  *
   1817  * DESCRIPTION: Compile FPDT.
   1818  *
   1819  *****************************************************************************/
   1820 
   1821 ACPI_STATUS
   1822 DtCompileFpdt (
   1823     void                    **List)
   1824 {
   1825     ACPI_STATUS             Status;
   1826     ACPI_FPDT_HEADER        *FpdtHeader;
   1827     DT_SUBTABLE             *Subtable;
   1828     DT_SUBTABLE             *ParentTable;
   1829     ACPI_DMTABLE_INFO       *InfoTable;
   1830     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   1831     DT_FIELD                *SubtableStart;
   1832 
   1833 
   1834     while (*PFieldList)
   1835     {
   1836         SubtableStart = *PFieldList;
   1837         Status = DtCompileTable (PFieldList, AcpiDmTableInfoFpdtHdr,
   1838             &Subtable);
   1839         if (ACPI_FAILURE (Status))
   1840         {
   1841             return (Status);
   1842         }
   1843 
   1844         ParentTable = DtPeekSubtable ();
   1845         DtInsertSubtable (ParentTable, Subtable);
   1846         DtPushSubtable (Subtable);
   1847 
   1848         FpdtHeader = ACPI_CAST_PTR (ACPI_FPDT_HEADER, Subtable->Buffer);
   1849 
   1850         switch (FpdtHeader->Type)
   1851         {
   1852         case ACPI_FPDT_TYPE_BOOT:
   1853 
   1854             InfoTable = AcpiDmTableInfoFpdt0;
   1855             break;
   1856 
   1857         case ACPI_FPDT_TYPE_S3PERF:
   1858 
   1859             InfoTable = AcpiDmTableInfoFpdt1;
   1860             break;
   1861 
   1862         default:
   1863 
   1864             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "FPDT");
   1865             return (AE_ERROR);
   1866             break;
   1867         }
   1868 
   1869         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
   1870         if (ACPI_FAILURE (Status))
   1871         {
   1872             return (Status);
   1873         }
   1874 
   1875         ParentTable = DtPeekSubtable ();
   1876         DtInsertSubtable (ParentTable, Subtable);
   1877         DtPopSubtable ();
   1878     }
   1879 
   1880     return (AE_OK);
   1881 }
   1882 
   1883 
   1884 /******************************************************************************
   1885  *
   1886  * FUNCTION:    DtCompileHest
   1887  *
   1888  * PARAMETERS:  List                - Current field list pointer
   1889  *
   1890  * RETURN:      Status
   1891  *
   1892  * DESCRIPTION: Compile HEST.
   1893  *
   1894  *****************************************************************************/
   1895 
   1896 ACPI_STATUS
   1897 DtCompileHest (
   1898     void                    **List)
   1899 {
   1900     ACPI_STATUS             Status;
   1901     DT_SUBTABLE             *Subtable;
   1902     DT_SUBTABLE             *ParentTable;
   1903     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   1904     DT_FIELD                *SubtableStart;
   1905     ACPI_DMTABLE_INFO       *InfoTable;
   1906     UINT16                  Type;
   1907     UINT32                  BankCount;
   1908 
   1909 
   1910     Status = DtCompileTable (PFieldList, AcpiDmTableInfoHest,
   1911         &Subtable);
   1912     if (ACPI_FAILURE (Status))
   1913     {
   1914         return (Status);
   1915     }
   1916 
   1917     ParentTable = DtPeekSubtable ();
   1918     DtInsertSubtable (ParentTable, Subtable);
   1919 
   1920     while (*PFieldList)
   1921     {
   1922         /* Get subtable type */
   1923 
   1924         SubtableStart = *PFieldList;
   1925         DtCompileInteger ((UINT8 *) &Type, *PFieldList, 2, 0);
   1926 
   1927         switch (Type)
   1928         {
   1929         case ACPI_HEST_TYPE_IA32_CHECK:
   1930 
   1931             InfoTable = AcpiDmTableInfoHest0;
   1932             break;
   1933 
   1934         case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
   1935 
   1936             InfoTable = AcpiDmTableInfoHest1;
   1937             break;
   1938 
   1939         case ACPI_HEST_TYPE_IA32_NMI:
   1940 
   1941             InfoTable = AcpiDmTableInfoHest2;
   1942             break;
   1943 
   1944         case ACPI_HEST_TYPE_AER_ROOT_PORT:
   1945 
   1946             InfoTable = AcpiDmTableInfoHest6;
   1947             break;
   1948 
   1949         case ACPI_HEST_TYPE_AER_ENDPOINT:
   1950 
   1951             InfoTable = AcpiDmTableInfoHest7;
   1952             break;
   1953 
   1954         case ACPI_HEST_TYPE_AER_BRIDGE:
   1955 
   1956             InfoTable = AcpiDmTableInfoHest8;
   1957             break;
   1958 
   1959         case ACPI_HEST_TYPE_GENERIC_ERROR:
   1960 
   1961             InfoTable = AcpiDmTableInfoHest9;
   1962             break;
   1963 
   1964         case ACPI_HEST_TYPE_GENERIC_ERROR_V2:
   1965 
   1966             InfoTable = AcpiDmTableInfoHest10;
   1967             break;
   1968 
   1969         case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
   1970 
   1971             InfoTable = AcpiDmTableInfoHest11;
   1972             break;
   1973 
   1974         default:
   1975 
   1976             /* Cannot continue on unknown type */
   1977 
   1978             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HEST");
   1979             return (AE_ERROR);
   1980         }
   1981 
   1982         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
   1983         if (ACPI_FAILURE (Status))
   1984         {
   1985             return (Status);
   1986         }
   1987 
   1988         DtInsertSubtable (ParentTable, Subtable);
   1989 
   1990         /*
   1991          * Additional subtable data - IA32 Error Bank(s)
   1992          */
   1993         BankCount = 0;
   1994         switch (Type)
   1995         {
   1996         case ACPI_HEST_TYPE_IA32_CHECK:
   1997 
   1998             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_MACHINE_CHECK,
   1999                 Subtable->Buffer))->NumHardwareBanks;
   2000             break;
   2001 
   2002         case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
   2003 
   2004             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_CORRECTED,
   2005                 Subtable->Buffer))->NumHardwareBanks;
   2006             break;
   2007 
   2008         case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK:
   2009 
   2010             BankCount = (ACPI_CAST_PTR (ACPI_HEST_IA_DEFERRED_CHECK,
   2011                 Subtable->Buffer))->NumHardwareBanks;
   2012             break;
   2013 
   2014         default:
   2015 
   2016             break;
   2017         }
   2018 
   2019         while (BankCount)
   2020         {
   2021             Status = DtCompileTable (PFieldList, AcpiDmTableInfoHestBank,
   2022                 &Subtable);
   2023             if (ACPI_FAILURE (Status))
   2024             {
   2025                 return (Status);
   2026             }
   2027 
   2028             DtInsertSubtable (ParentTable, Subtable);
   2029             BankCount--;
   2030         }
   2031     }
   2032 
   2033     return (AE_OK);
   2034 }
   2035 
   2036 
   2037 /******************************************************************************
   2038  *
   2039  * FUNCTION:    DtCompileHmat
   2040  *
   2041  * PARAMETERS:  List                - Current field list pointer
   2042  *
   2043  * RETURN:      Status
   2044  *
   2045  * DESCRIPTION: Compile HMAT.
   2046  *
   2047  *****************************************************************************/
   2048 
   2049 ACPI_STATUS
   2050 DtCompileHmat (
   2051     void                    **List)
   2052 {
   2053     ACPI_STATUS             Status;
   2054     DT_SUBTABLE             *Subtable;
   2055     DT_SUBTABLE             *ParentTable;
   2056     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   2057     DT_FIELD                *SubtableStart;
   2058     DT_FIELD                *EntryStart;
   2059     ACPI_HMAT_STRUCTURE     *HmatStruct;
   2060     ACPI_HMAT_LOCALITY      *HmatLocality;
   2061     ACPI_HMAT_CACHE         *HmatCache;
   2062     ACPI_DMTABLE_INFO       *InfoTable;
   2063     UINT32                  IntPDNumber;
   2064     UINT32                  TgtPDNumber;
   2065     UINT64                  EntryNumber;
   2066     UINT16                  SMBIOSHandleNumber;
   2067 
   2068 
   2069     ParentTable = DtPeekSubtable ();
   2070 
   2071     Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmat,
   2072         &Subtable);
   2073     if (ACPI_FAILURE (Status))
   2074     {
   2075         return (Status);
   2076     }
   2077     DtInsertSubtable (ParentTable, Subtable);
   2078 
   2079     while (*PFieldList)
   2080     {
   2081         /* Compile HMAT structure header */
   2082 
   2083         SubtableStart = *PFieldList;
   2084         Status = DtCompileTable (PFieldList, AcpiDmTableInfoHmatHdr,
   2085             &Subtable);
   2086         if (ACPI_FAILURE (Status))
   2087         {
   2088             return (Status);
   2089         }
   2090         DtInsertSubtable (ParentTable, Subtable);
   2091 
   2092         HmatStruct = ACPI_CAST_PTR (ACPI_HMAT_STRUCTURE, Subtable->Buffer);
   2093         HmatStruct->Length = Subtable->Length;
   2094 
   2095         /* Compile HMAT structure body */
   2096 
   2097         switch (HmatStruct->Type)
   2098         {
   2099         case ACPI_HMAT_TYPE_ADDRESS_RANGE:
   2100 
   2101             InfoTable = AcpiDmTableInfoHmat0;
   2102             break;
   2103 
   2104         case ACPI_HMAT_TYPE_LOCALITY:
   2105 
   2106             InfoTable = AcpiDmTableInfoHmat1;
   2107             break;
   2108 
   2109         case ACPI_HMAT_TYPE_CACHE:
   2110 
   2111             InfoTable = AcpiDmTableInfoHmat2;
   2112             break;
   2113 
   2114         default:
   2115 
   2116             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "HMAT");
   2117             return (AE_ERROR);
   2118         }
   2119 
   2120         Status = DtCompileTable (PFieldList, InfoTable, &Subtable);
   2121         if (ACPI_FAILURE (Status))
   2122         {
   2123             return (Status);
   2124         }
   2125         DtInsertSubtable (ParentTable, Subtable);
   2126         HmatStruct->Length += Subtable->Length;
   2127 
   2128         /* Compile HMAT structure additional */
   2129 
   2130         switch (HmatStruct->Type)
   2131         {
   2132         case ACPI_HMAT_TYPE_LOCALITY:
   2133 
   2134             HmatLocality = ACPI_SUB_PTR (ACPI_HMAT_LOCALITY,
   2135                 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
   2136 
   2137             /* Compile initiator proximity domain list */
   2138 
   2139             IntPDNumber = 0;
   2140             while (*PFieldList)
   2141             {
   2142                 Status = DtCompileTable (PFieldList,
   2143                     AcpiDmTableInfoHmat1a, &Subtable);
   2144                 if (ACPI_FAILURE (Status))
   2145                 {
   2146                     return (Status);
   2147                 }
   2148                 if (!Subtable)
   2149                 {
   2150                     break;
   2151                 }
   2152                 DtInsertSubtable (ParentTable, Subtable);
   2153                 HmatStruct->Length += Subtable->Length;
   2154                 IntPDNumber++;
   2155             }
   2156             HmatLocality->NumberOfInitiatorPDs = IntPDNumber;
   2157 
   2158             /* Compile target proximity domain list */
   2159 
   2160             TgtPDNumber = 0;
   2161             while (*PFieldList)
   2162             {
   2163                 Status = DtCompileTable (PFieldList,
   2164                     AcpiDmTableInfoHmat1b, &Subtable);
   2165                 if (ACPI_FAILURE (Status))
   2166                 {
   2167                     return (Status);
   2168                 }
   2169                 if (!Subtable)
   2170                 {
   2171                     break;
   2172                 }
   2173                 DtInsertSubtable (ParentTable, Subtable);
   2174                 HmatStruct->Length += Subtable->Length;
   2175                 TgtPDNumber++;
   2176             }
   2177             HmatLocality->NumberOfTargetPDs = TgtPDNumber;
   2178 
   2179             /* Save start of the entries for reporting errors */
   2180 
   2181             EntryStart = *PFieldList;
   2182 
   2183             /* Compile latency/bandwidth entries */
   2184 
   2185             EntryNumber = 0;
   2186             while (*PFieldList)
   2187             {
   2188                 Status = DtCompileTable (PFieldList,
   2189                     AcpiDmTableInfoHmat1c, &Subtable);
   2190                 if (ACPI_FAILURE (Status))
   2191                 {
   2192                     return (Status);
   2193                 }
   2194                 if (!Subtable)
   2195                 {
   2196                     break;
   2197                 }
   2198                 DtInsertSubtable (ParentTable, Subtable);
   2199                 HmatStruct->Length += Subtable->Length;
   2200                 EntryNumber++;
   2201             }
   2202 
   2203             /* Validate number of entries */
   2204 
   2205             if (EntryNumber !=
   2206                 ((UINT64)IntPDNumber * (UINT64)TgtPDNumber))
   2207             {
   2208                 DtFatal (ASL_MSG_INVALID_EXPRESSION, EntryStart, "HMAT");
   2209                 return (AE_ERROR);
   2210             }
   2211             break;
   2212 
   2213         case ACPI_HMAT_TYPE_CACHE:
   2214 
   2215             /* Compile SMBIOS handles */
   2216 
   2217             HmatCache = ACPI_SUB_PTR (ACPI_HMAT_CACHE,
   2218                 Subtable->Buffer, sizeof (ACPI_HMAT_STRUCTURE));
   2219             SMBIOSHandleNumber = 0;
   2220             while (*PFieldList)
   2221             {
   2222                 Status = DtCompileTable (PFieldList,
   2223                     AcpiDmTableInfoHmat2a, &Subtable);
   2224                 if (ACPI_FAILURE (Status))
   2225                 {
   2226                     return (Status);
   2227                 }
   2228                 if (!Subtable)
   2229                 {
   2230                     break;
   2231                 }
   2232                 DtInsertSubtable (ParentTable, Subtable);
   2233                 HmatStruct->Length += Subtable->Length;
   2234                 SMBIOSHandleNumber++;
   2235             }
   2236             HmatCache->NumberOfSMBIOSHandles = SMBIOSHandleNumber;
   2237             break;
   2238 
   2239         default:
   2240 
   2241             break;
   2242         }
   2243     }
   2244 
   2245     return (AE_OK);
   2246 }
   2247 
   2248 
   2249 /******************************************************************************
   2250  *
   2251  * FUNCTION:    DtCompileIort
   2252  *
   2253  * PARAMETERS:  List                - Current field list pointer
   2254  *
   2255  * RETURN:      Status
   2256  *
   2257  * DESCRIPTION: Compile IORT.
   2258  *
   2259  *****************************************************************************/
   2260 
   2261 ACPI_STATUS
   2262 DtCompileIort (
   2263     void                    **List)
   2264 {
   2265     ACPI_STATUS             Status;
   2266     DT_SUBTABLE             *Subtable;
   2267     DT_SUBTABLE             *ParentTable;
   2268     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   2269     DT_FIELD                *SubtableStart;
   2270     ACPI_TABLE_HEADER       *Table;
   2271     ACPI_TABLE_IORT         *Iort;
   2272     ACPI_IORT_NODE          *IortNode;
   2273     ACPI_IORT_ITS_GROUP     *IortItsGroup;
   2274     ACPI_IORT_SMMU          *IortSmmu;
   2275     ACPI_IORT_RMR           *IortRmr;
   2276     UINT32                  NodeNumber;
   2277     UINT32                  NodeLength;
   2278     UINT32                  IdMappingNumber;
   2279     UINT32                  ItsNumber;
   2280     UINT32                  ContextIrptNumber;
   2281     UINT32                  PmuIrptNumber;
   2282     UINT32                  PaddingLength;
   2283     UINT8                   Revision;
   2284     UINT32                  RmrCount;
   2285 
   2286 
   2287     ParentTable = DtPeekSubtable ();
   2288 
   2289     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort,
   2290         &Subtable);
   2291     if (ACPI_FAILURE (Status))
   2292     {
   2293         return (Status);
   2294     }
   2295     DtInsertSubtable (ParentTable, Subtable);
   2296 
   2297     Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ParentTable->Buffer);
   2298     Revision = Table->Revision;
   2299 
   2300     /* IORT Revisions E, E.a & E.c have known issues and are not supported */
   2301 
   2302     if (Revision == 1 || Revision == 2 || Revision == 4)
   2303     {
   2304         DtError (ASL_ERROR, ASL_MSG_UNSUPPORTED, NULL, "IORT table revision");
   2305         return (AE_ERROR);
   2306     }
   2307 
   2308     /*
   2309      * Using ACPI_SUB_PTR, We needn't define a separate structure. Care
   2310      * should be taken to avoid accessing ACPI_TABLE_HEADER fields.
   2311      */
   2312     Iort = ACPI_SUB_PTR (ACPI_TABLE_IORT,
   2313         Subtable->Buffer, sizeof (ACPI_TABLE_HEADER));
   2314 
   2315     /*
   2316      * OptionalPadding - Variable-length data
   2317      * (Optional, size = OffsetToNodes - sizeof (ACPI_TABLE_IORT))
   2318      * Optionally allows the generic data types to be used for filling
   2319      * this field.
   2320      */
   2321     Iort->NodeOffset = sizeof (ACPI_TABLE_IORT);
   2322     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortPad,
   2323         &Subtable);
   2324     if (ACPI_FAILURE (Status))
   2325     {
   2326         return (Status);
   2327     }
   2328     if (Subtable)
   2329     {
   2330         DtInsertSubtable (ParentTable, Subtable);
   2331         Iort->NodeOffset += Subtable->Length;
   2332     }
   2333     else
   2334     {
   2335         Status = DtCompileGeneric (ACPI_CAST_PTR (void *, PFieldList),
   2336             AcpiDmTableInfoIortHdr[0].Name, &PaddingLength);
   2337         if (ACPI_FAILURE (Status))
   2338         {
   2339             return (Status);
   2340         }
   2341         Iort->NodeOffset += PaddingLength;
   2342     }
   2343 
   2344     NodeNumber = 0;
   2345     while (*PFieldList)
   2346     {
   2347         SubtableStart = *PFieldList;
   2348         if (Revision == 0)
   2349         {
   2350             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr,
   2351                 &Subtable);
   2352         }
   2353         else if (Revision >= 3)
   2354         {
   2355             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortHdr3,
   2356                 &Subtable);
   2357         }
   2358 
   2359         if (ACPI_FAILURE (Status))
   2360         {
   2361             return (Status);
   2362         }
   2363 
   2364         DtInsertSubtable (ParentTable, Subtable);
   2365         IortNode = ACPI_CAST_PTR (ACPI_IORT_NODE, Subtable->Buffer);
   2366         NodeLength = ACPI_OFFSET (ACPI_IORT_NODE, NodeData);
   2367 
   2368         DtPushSubtable (Subtable);
   2369         ParentTable = DtPeekSubtable ();
   2370 
   2371         switch (IortNode->Type)
   2372         {
   2373         case ACPI_IORT_NODE_ITS_GROUP:
   2374 
   2375             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0,
   2376                 &Subtable);
   2377             if (ACPI_FAILURE (Status))
   2378             {
   2379                 return (Status);
   2380             }
   2381 
   2382             DtInsertSubtable (ParentTable, Subtable);
   2383             IortItsGroup = ACPI_CAST_PTR (ACPI_IORT_ITS_GROUP, Subtable->Buffer);
   2384             NodeLength += Subtable->Length;
   2385 
   2386             ItsNumber = 0;
   2387             while (*PFieldList)
   2388             {
   2389                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort0a,
   2390                     &Subtable);
   2391                 if (ACPI_FAILURE (Status))
   2392                 {
   2393                     return (Status);
   2394                 }
   2395                 if (!Subtable)
   2396                 {
   2397                     break;
   2398                 }
   2399 
   2400                 DtInsertSubtable (ParentTable, Subtable);
   2401                 NodeLength += Subtable->Length;
   2402                 ItsNumber++;
   2403             }
   2404 
   2405             IortItsGroup->ItsCount = ItsNumber;
   2406             break;
   2407 
   2408         case ACPI_IORT_NODE_NAMED_COMPONENT:
   2409 
   2410             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1,
   2411                 &Subtable);
   2412             if (ACPI_FAILURE (Status))
   2413             {
   2414                 return (Status);
   2415             }
   2416 
   2417             DtInsertSubtable (ParentTable, Subtable);
   2418             NodeLength += Subtable->Length;
   2419 
   2420             /*
   2421              * Padding - Variable-length data
   2422              * Optionally allows the offset of the ID mappings to be used
   2423              * for filling this field.
   2424              */
   2425             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort1a,
   2426                 &Subtable);
   2427             if (ACPI_FAILURE (Status))
   2428             {
   2429                 return (Status);
   2430             }
   2431 
   2432             if (Subtable)
   2433             {
   2434                 DtInsertSubtable (ParentTable, Subtable);
   2435                 NodeLength += Subtable->Length;
   2436             }
   2437             else
   2438             {
   2439                 if (NodeLength > IortNode->MappingOffset)
   2440                 {
   2441                     return (AE_BAD_DATA);
   2442                 }
   2443 
   2444                 if (NodeLength < IortNode->MappingOffset)
   2445                 {
   2446                     Status = DtCompilePadding (
   2447                         IortNode->MappingOffset - NodeLength,
   2448                         &Subtable);
   2449                     if (ACPI_FAILURE (Status))
   2450                     {
   2451                         return (Status);
   2452                     }
   2453 
   2454                     DtInsertSubtable (ParentTable, Subtable);
   2455                     NodeLength = IortNode->MappingOffset;
   2456                 }
   2457             }
   2458             break;
   2459 
   2460         case ACPI_IORT_NODE_PCI_ROOT_COMPLEX:
   2461 
   2462             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort2,
   2463                 &Subtable);
   2464             if (ACPI_FAILURE (Status))
   2465             {
   2466                 return (Status);
   2467             }
   2468 
   2469             DtInsertSubtable (ParentTable, Subtable);
   2470             NodeLength += Subtable->Length;
   2471             break;
   2472 
   2473         case ACPI_IORT_NODE_SMMU:
   2474 
   2475             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3,
   2476                 &Subtable);
   2477             if (ACPI_FAILURE (Status))
   2478             {
   2479                 return (Status);
   2480             }
   2481 
   2482             DtInsertSubtable (ParentTable, Subtable);
   2483             IortSmmu = ACPI_CAST_PTR (ACPI_IORT_SMMU, Subtable->Buffer);
   2484             NodeLength += Subtable->Length;
   2485 
   2486             /* Compile global interrupt array */
   2487 
   2488             IortSmmu->GlobalInterruptOffset = NodeLength;
   2489             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3a,
   2490                 &Subtable);
   2491             if (ACPI_FAILURE (Status))
   2492             {
   2493                 return (Status);
   2494             }
   2495 
   2496             DtInsertSubtable (ParentTable, Subtable);
   2497             NodeLength += Subtable->Length;
   2498 
   2499             /* Compile context interrupt array */
   2500 
   2501             ContextIrptNumber = 0;
   2502             IortSmmu->ContextInterruptOffset = NodeLength;
   2503             while (*PFieldList)
   2504             {
   2505                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3b,
   2506                     &Subtable);
   2507                 if (ACPI_FAILURE (Status))
   2508                 {
   2509                     return (Status);
   2510                 }
   2511 
   2512                 if (!Subtable)
   2513                 {
   2514                     break;
   2515                 }
   2516 
   2517                 DtInsertSubtable (ParentTable, Subtable);
   2518                 NodeLength += Subtable->Length;
   2519                 ContextIrptNumber++;
   2520             }
   2521 
   2522             IortSmmu->ContextInterruptCount = ContextIrptNumber;
   2523 
   2524             /* Compile PMU interrupt array */
   2525 
   2526             PmuIrptNumber = 0;
   2527             IortSmmu->PmuInterruptOffset = NodeLength;
   2528             while (*PFieldList)
   2529             {
   2530                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort3c,
   2531                     &Subtable);
   2532                 if (ACPI_FAILURE (Status))
   2533                 {
   2534                     return (Status);
   2535                 }
   2536 
   2537                 if (!Subtable)
   2538                 {
   2539                     break;
   2540                 }
   2541 
   2542                 DtInsertSubtable (ParentTable, Subtable);
   2543                 NodeLength += Subtable->Length;
   2544                 PmuIrptNumber++;
   2545             }
   2546 
   2547             IortSmmu->PmuInterruptCount = PmuIrptNumber;
   2548             break;
   2549 
   2550         case ACPI_IORT_NODE_SMMU_V3:
   2551 
   2552             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort4,
   2553                 &Subtable);
   2554             if (ACPI_FAILURE (Status))
   2555             {
   2556                 return (Status);
   2557             }
   2558 
   2559             DtInsertSubtable (ParentTable, Subtable);
   2560             NodeLength += Subtable->Length;
   2561             break;
   2562 
   2563         case ACPI_IORT_NODE_PMCG:
   2564 
   2565             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort5,
   2566                 &Subtable);
   2567             if (ACPI_FAILURE (Status))
   2568             {
   2569                 return (Status);
   2570             }
   2571 
   2572             DtInsertSubtable (ParentTable, Subtable);
   2573             NodeLength += Subtable->Length;
   2574             break;
   2575 
   2576         case ACPI_IORT_NODE_RMR:
   2577 
   2578             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6,
   2579                 &Subtable);
   2580             if (ACPI_FAILURE (Status))
   2581             {
   2582                 return (Status);
   2583             }
   2584 
   2585             DtInsertSubtable (ParentTable, Subtable);
   2586             IortRmr = ACPI_CAST_PTR (ACPI_IORT_RMR, Subtable->Buffer);
   2587             NodeLength += Subtable->Length;
   2588 
   2589             /* Compile RMR Descriptors */
   2590 
   2591             RmrCount = 0;
   2592             IortRmr->RmrOffset = NodeLength;
   2593             while (*PFieldList)
   2594             {
   2595                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort6a,
   2596                     &Subtable);
   2597                 if (ACPI_FAILURE (Status))
   2598                 {
   2599                     return (Status);
   2600                 }
   2601 
   2602                 if (!Subtable)
   2603                 {
   2604                     break;
   2605                 }
   2606 
   2607                 DtInsertSubtable (ParentTable, Subtable);
   2608                 NodeLength += sizeof (ACPI_IORT_RMR_DESC);
   2609                 RmrCount++;
   2610             }
   2611 
   2612             IortRmr->RmrCount = RmrCount;
   2613             break;
   2614 
   2615         default:
   2616 
   2617             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IORT");
   2618             return (AE_ERROR);
   2619         }
   2620 
   2621         /* Compile Array of ID mappings */
   2622 
   2623         IortNode->MappingOffset = NodeLength;
   2624         IdMappingNumber = 0;
   2625         while (*PFieldList)
   2626         {
   2627             Status = DtCompileTable (PFieldList, AcpiDmTableInfoIortMap,
   2628                 &Subtable);
   2629             if (ACPI_FAILURE (Status))
   2630             {
   2631                 return (Status);
   2632             }
   2633 
   2634             if (!Subtable)
   2635             {
   2636                 break;
   2637             }
   2638 
   2639             DtInsertSubtable (ParentTable, Subtable);
   2640             NodeLength += sizeof (ACPI_IORT_ID_MAPPING);
   2641             IdMappingNumber++;
   2642         }
   2643 
   2644         IortNode->MappingCount = IdMappingNumber;
   2645         if (!IdMappingNumber)
   2646         {
   2647             IortNode->MappingOffset = 0;
   2648         }
   2649 
   2650         /*
   2651          * Node length can be determined by DT_LENGTH option
   2652          * IortNode->Length = NodeLength;
   2653          */
   2654         DtPopSubtable ();
   2655         ParentTable = DtPeekSubtable ();
   2656         NodeNumber++;
   2657     }
   2658 
   2659     Iort->NodeCount = NodeNumber;
   2660     return (AE_OK);
   2661 }
   2662 
   2663 
   2664 /******************************************************************************
   2665  *
   2666  * FUNCTION:    DtCompileIvrs
   2667  *
   2668  * PARAMETERS:  List                - Current field list pointer
   2669  *
   2670  * RETURN:      Status
   2671  *
   2672  * DESCRIPTION: Compile IVRS. Notes:
   2673  *              The IVRS is essentially a flat table, with the following
   2674  *              structure:
   2675  *              <Main ACPI Table Header>
   2676  *              <Main subtable - virtualization info>
   2677  *              <IVHD>
   2678  *                  <Device Entries>
   2679  *              ...
   2680  *              <IVHD>
   2681  *                  <Device Entries>
   2682  *              <IVMD>
   2683  *              ...
   2684  *
   2685  *****************************************************************************/
   2686 
   2687 ACPI_STATUS
   2688 DtCompileIvrs (
   2689     void                    **List)
   2690 {
   2691     ACPI_STATUS             Status;
   2692     DT_SUBTABLE             *Subtable;
   2693     DT_SUBTABLE             *ParentTable;
   2694     DT_SUBTABLE             *MainSubtable;
   2695     DT_FIELD                **PFieldList = (DT_FIELD **) List;
   2696     DT_FIELD                *SubtableStart;
   2697     ACPI_DMTABLE_INFO       *InfoTable = NULL;
   2698     UINT8                   SubtableType;
   2699     UINT8                   Temp64[16];
   2700     UINT8                   Temp8;
   2701 
   2702 
   2703     /* Main table */
   2704 
   2705     Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrs,
   2706         &Subtable);
   2707     if (ACPI_FAILURE (Status))
   2708     {
   2709         return (Status);
   2710     }
   2711 
   2712     ParentTable = DtPeekSubtable ();
   2713     DtInsertSubtable (ParentTable, Subtable);
   2714     DtPushSubtable (Subtable);
   2715 
   2716     /* Save a pointer to the main subtable */
   2717 
   2718     MainSubtable = Subtable;
   2719 
   2720     while (*PFieldList)
   2721     {
   2722         SubtableStart = *PFieldList;
   2723 
   2724         /* Compile the SubtableType integer */
   2725 
   2726         DtCompileInteger (&SubtableType, *PFieldList, 1, 0);
   2727 
   2728         switch (SubtableType)
   2729         {
   2730 
   2731         /* Type 10h, IVHD (I/O Virtualization Hardware Definition) */
   2732 
   2733         case ACPI_IVRS_TYPE_HARDWARE1:
   2734 
   2735             InfoTable = AcpiDmTableInfoIvrsHware1;
   2736             break;
   2737 
   2738         /* Types 11h, 40h, IVHD (I/O Virtualization Hardware Definition) */
   2739 
   2740         case ACPI_IVRS_TYPE_HARDWARE2:
   2741         case ACPI_IVRS_TYPE_HARDWARE3:
   2742 
   2743             InfoTable = AcpiDmTableInfoIvrsHware23;
   2744             break;
   2745 
   2746         /* Types 20h, 21h, 22h, IVMD (I/O Virtualization Memory Definition Block) */
   2747 
   2748         case ACPI_IVRS_TYPE_MEMORY1:
   2749         case ACPI_IVRS_TYPE_MEMORY2:
   2750         case ACPI_IVRS_TYPE_MEMORY3:
   2751 
   2752             InfoTable = AcpiDmTableInfoIvrsMemory;
   2753             break;
   2754 
   2755         /* 4-byte device entries */
   2756 
   2757         case ACPI_IVRS_TYPE_PAD4:
   2758         case ACPI_IVRS_TYPE_ALL:
   2759         case ACPI_IVRS_TYPE_SELECT:
   2760         case ACPI_IVRS_TYPE_START:
   2761         case ACPI_IVRS_TYPE_END:
   2762 
   2763             InfoTable = AcpiDmTableInfoIvrs4;
   2764             break;
   2765 
   2766         /* 8-byte device entries, type A */
   2767 
   2768         case ACPI_IVRS_TYPE_ALIAS_SELECT:
   2769         case ACPI_IVRS_TYPE_ALIAS_START:
   2770 
   2771             InfoTable = AcpiDmTableInfoIvrs8a;
   2772             break;
   2773 
   2774         /* 8-byte device entries, type B */
   2775 
   2776         case ACPI_IVRS_TYPE_EXT_SELECT:
   2777         case ACPI_IVRS_TYPE_EXT_START:
   2778 
   2779             InfoTable = AcpiDmTableInfoIvrs8b;
   2780             break;
   2781 
   2782         /* 8-byte device entries, type C */
   2783 
   2784         case ACPI_IVRS_TYPE_SPECIAL:
   2785 
   2786             InfoTable = AcpiDmTableInfoIvrs8c;
   2787             break;
   2788 
   2789         /* Variable device entries, type F0h */
   2790 
   2791         case ACPI_IVRS_TYPE_HID:
   2792 
   2793             InfoTable = AcpiDmTableInfoIvrsHid;
   2794             break;
   2795 
   2796         default:
   2797 
   2798             DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart,
   2799                 "IVRS Device Entry");
   2800             return (AE_ERROR);
   2801         }
   2802 
   2803         /* Compile the InfoTable from above */
   2804 
   2805         Status = DtCompileTable (PFieldList, InfoTable,
   2806             &Subtable);
   2807         if (ACPI_FAILURE (Status))
   2808         {
   2809             return (Status);
   2810         }
   2811 
   2812         ParentTable = DtPeekSubtable ();
   2813         if (SubtableType != ACPI_IVRS_TYPE_HARDWARE1 &&
   2814             SubtableType != ACPI_IVRS_TYPE_HARDWARE2 &&
   2815             SubtableType != ACPI_IVRS_TYPE_HARDWARE3 &&
   2816             SubtableType != ACPI_IVRS_TYPE_HID &&
   2817             SubtableType != ACPI_IVRS_TYPE_MEMORY1 &&
   2818             SubtableType != ACPI_IVRS_TYPE_MEMORY2 &&
   2819             SubtableType != ACPI_IVRS_TYPE_MEMORY3)
   2820         {
   2821             if (ParentTable)
   2822                 DtInsertSubtable (ParentTable, Subtable);
   2823         }
   2824 
   2825         switch (SubtableType)
   2826         {
   2827         case ACPI_IVRS_TYPE_HARDWARE1:
   2828         case ACPI_IVRS_TYPE_HARDWARE2:
   2829         case ACPI_IVRS_TYPE_HARDWARE3:
   2830         case ACPI_IVRS_TYPE_MEMORY1:
   2831         case ACPI_IVRS_TYPE_MEMORY2:
   2832         case ACPI_IVRS_TYPE_MEMORY3:
   2833 
   2834             /* Insert these IVHDs/IVMDs at the root subtable */
   2835 
   2836             DtInsertSubtable (MainSubtable, Subtable);
   2837             DtPushSubtable (Subtable);
   2838             break;
   2839 
   2840         case ACPI_IVRS_TYPE_HID:
   2841 
   2842             /* Special handling for the HID named device entry (0xF0) */
   2843 
   2844             if (ParentTable)
   2845             {
   2846                 DtInsertSubtable (ParentTable, Subtable);
   2847             }
   2848 
   2849             /*
   2850              * Process the HID value. First, get the HID value as a string.
   2851              */
   2852             DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0);
   2853 
   2854                /*
   2855                 * Determine if the HID is an integer or a string.
   2856                 * An integer is defined to be 32 bits, with the upper 32 bits
   2857                 * set to zero. (from the ACPI Spec): "The HID can be a 32-bit
   2858                 * integer or a character string. If an integer, the lower
   2859                 * 4 bytes of the field contain the integer and the upper
   2860                 * 4 bytes are padded with 0".
   2861                 */
   2862             if (UtIsIdInteger ((UINT8 *) &Temp64))
   2863             {
   2864                 /* Compile the HID value as an integer */
   2865 
   2866                 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0);
   2867 
   2868                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidInteger,
   2869                     &Subtable);
   2870                 if (ACPI_FAILURE (Status))
   2871                 {
   2872                     return (Status);
   2873                 }
   2874             }
   2875             else
   2876             {
   2877                 /* Compile the HID value as a string */
   2878 
   2879                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsHidString,
   2880                     &Subtable);
   2881                 if (ACPI_FAILURE (Status))
   2882                 {
   2883                     return (Status);
   2884                 }
   2885             }
   2886 
   2887             DtInsertSubtable (ParentTable, Subtable);
   2888 
   2889             /*
   2890              * Process the CID value. First, get the CID value as a string.
   2891              */
   2892             DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 16, DT_FIELD_TYPE_STRING, 0);
   2893 
   2894             if (UtIsIdInteger ((UINT8 *) &Temp64))
   2895             {
   2896                 /* Compile the CID value as an integer */
   2897 
   2898                 DtCompileOneField ((UINT8 *) &Temp64, *PFieldList, 8, DT_FIELD_TYPE_INTEGER, 0);
   2899 
   2900                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidInteger,
   2901                     &Subtable);
   2902                 if (ACPI_FAILURE (Status))
   2903                 {
   2904                     return (Status);
   2905                 }
   2906             }
   2907             else
   2908             {
   2909                 /* Compile the CID value as a string */
   2910 
   2911                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsCidString,
   2912                     &Subtable);
   2913                 if (ACPI_FAILURE (Status))
   2914                 {
   2915                     return (Status);
   2916                 }
   2917             }
   2918 
   2919             DtInsertSubtable (ParentTable, Subtable);
   2920 
   2921             /*
   2922              * Process the UID value. First, get and decode the "UID Format" field (Integer).
   2923              */
   2924             if (!*PFieldList)
   2925             {
   2926                 return (AE_OK);
   2927             }
   2928 
   2929             DtCompileOneField (&Temp8, *PFieldList, 1, DT_FIELD_TYPE_INTEGER, 0);
   2930 
   2931             switch (Temp8)
   2932             {
   2933             case ACPI_IVRS_UID_NOT_PRESENT:
   2934                 break;
   2935 
   2936             case ACPI_IVRS_UID_IS_INTEGER:
   2937 
   2938                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidInteger,
   2939                     &Subtable);
   2940                 if (ACPI_FAILURE (Status))
   2941                 {
   2942                     return (Status);
   2943                 }
   2944                 DtInsertSubtable (ParentTable, Subtable);
   2945                 break;
   2946 
   2947             case ACPI_IVRS_UID_IS_STRING:
   2948 
   2949                 Status = DtCompileTable (PFieldList, AcpiDmTableInfoIvrsUidString,
   2950                     &Subtable);
   2951                 if (ACPI_FAILURE (Status))
   2952                 {
   2953                     return (Status);
   2954                 }
   2955                 DtInsertSubtable (ParentTable, Subtable);
   2956                 break;
   2957 
   2958             default:
   2959 
   2960                 DtFatal (ASL_MSG_UNKNOWN_FORMAT, SubtableStart,
   2961                     "IVRS Device Entry");
   2962                 return (AE_ERROR);
   2963             }
   2964 
   2965         default:
   2966 
   2967             /* All other subtable types come through here */
   2968             break;
   2969         }
   2970     }
   2971 
   2972     return (AE_OK);
   2973 }
   2974