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