dtcompile.c revision 259065
10SN/A/******************************************************************************
23880Svromero *
30SN/A * Module Name: dtcompile.c - Front-end for data table compiler
40SN/A *
50SN/A *****************************************************************************/
60SN/A
7553SN/A/*
80SN/A * Copyright (C) 2000 - 2013, Intel Corp.
9553SN/A * All rights reserved.
100SN/A *
110SN/A * Redistribution and use in source and binary forms, with or without
120SN/A * modification, are permitted provided that the following conditions
130SN/A * are met:
140SN/A * 1. Redistributions of source code must retain the above copyright
150SN/A *    notice, this list of conditions, and the following disclaimer,
160SN/A *    without modification.
170SN/A * 2. Redistributions in binary form must reproduce at minimum a disclaimer
180SN/A *    substantially similar to the "NO WARRANTY" disclaimer below
190SN/A *    ("Disclaimer") and any redistribution must be conditioned upon
200SN/A *    including a substantially similar Disclaimer requirement for further
21553SN/A *    binary redistribution.
22553SN/A * 3. Neither the names of the above-listed copyright holders nor the names
23553SN/A *    of any contributors may be used to endorse or promote products derived
240SN/A *    from this software without specific prior written permission.
250SN/A *
260SN/A * Alternatively, this software may be distributed under the terms of the
270SN/A * GNU General Public License ("GPL") version 2 as published by the Free
282877Sjjg * Software Foundation.
292877Sjjg *
302877Sjjg * NO WARRANTY
312877Sjjg * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
322877Sjjg * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
332877Sjjg * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
342883Salundblad * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
352877Sjjg * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
362877Sjjg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
372877Sjjg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
382877Sjjg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
392877Sjjg * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
402877Sjjg * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
412877Sjjg * POSSIBILITY OF SUCH DAMAGES.
422877Sjjg */
431520SN/A
442304SN/A#define __DTCOMPILE_C__
452877Sjjg#define _DECLARE_DT_GLOBALS
462304SN/A
472877Sjjg#include <contrib/dev/acpica/compiler/aslcompiler.h>
483792Salanb#include <contrib/dev/acpica/compiler/dtcompiler.h>
492877Sjjg
503880Svromero#define _COMPONENT          DT_COMPILER
512877Sjjg        ACPI_MODULE_NAME    ("dtcompile")
522877Sjjg
531373SN/Astatic char                 VersionString[9];
541373SN/A
552877Sjjg
562877Sjjg/* Local prototypes */
572877Sjjg
582877Sjjgstatic ACPI_STATUS
593591SjlahodaDtInitialize (
601126SN/A    void);
612877Sjjg
622877Sjjgstatic ACPI_STATUS
632877SjjgDtCompileDataTable (
642877Sjjg    DT_FIELD                **Field);
650SN/A
66580SN/Astatic void
67580SN/ADtInsertCompilerIds (
680SN/A    DT_FIELD                *FieldList);
690SN/A
700SN/A
710SN/A/******************************************************************************
722233SN/A *
730SN/A * FUNCTION:    DtDoCompile
740SN/A *
750SN/A * PARAMETERS:  None
760SN/A *
770SN/A * RETURN:      Status
780SN/A *
790SN/A * DESCRIPTION: Main entry point for the data table compiler.
800SN/A *
812304SN/A * Note: Assumes Gbl_Files[ASL_FILE_INPUT] is initialized and the file is
822877Sjjg *          open at seek offset zero.
832304SN/A *
842877Sjjg *****************************************************************************/
852877Sjjg
862304SN/AACPI_STATUS
872877SjjgDtDoCompile (
882877Sjjg    void)
892877Sjjg{
902877Sjjg    ACPI_STATUS             Status;
912877Sjjg    UINT8                   Event;
922877Sjjg    DT_FIELD                *FieldList;
932877Sjjg
942304SN/A
952877Sjjg    /* Initialize globals */
962877Sjjg
973651Sdlsmith    Status = DtInitialize ();
980SN/A    if (ACPI_FAILURE (Status))
990SN/A    {
1000SN/A        printf ("Error during compiler initialization, 0x%X\n", Status);
1012877Sjjg        return (Status);
1020SN/A    }
1032877Sjjg
1042877Sjjg    /* Preprocessor */
1052877Sjjg
1062877Sjjg    Event = UtBeginEvent ("Preprocess input file");
1070SN/A    PrDoPreprocess ();
1082877Sjjg    UtEndEvent (Event);
1092877Sjjg
110112SN/A    if (Gbl_PreprocessOnly)
1112877Sjjg    {
1122877Sjjg        return (AE_OK);
1132877Sjjg    }
1140SN/A
1152877Sjjg    /*
1162877Sjjg     * Scan the input file (file is already open) and
1172877Sjjg     * build the parse tree
1182877Sjjg     */
1192304SN/A    Event = UtBeginEvent ("Scan and parse input file");
1203651Sdlsmith    FieldList = DtScanFile (Gbl_Files[ASL_FILE_INPUT].Handle);
1213900Sjlahoda    UtEndEvent (Event);
1223900Sjlahoda
1230SN/A    /* Did the parse tree get successfully constructed? */
1240SN/A
1252877Sjjg    if (!FieldList)
1262877Sjjg    {
1270SN/A        /* TBD: temporary error message. Msgs should come from function above */
1282877Sjjg
1292877Sjjg        DtError (ASL_ERROR, ASL_MSG_SYNTAX, NULL,
1302877Sjjg            "Input file does not appear to be an ASL or data table source file");
1310SN/A
1320SN/A        Status = AE_ERROR;
1332877Sjjg        goto CleanupAndExit;
1342877Sjjg    }
1352877Sjjg
1362877Sjjg    Event = UtBeginEvent ("Compile parse tree");
1372877Sjjg
1380SN/A    /*
1390SN/A     * Compile the parse tree
1402135SN/A     */
1412135SN/A    Status = DtCompileDataTable (&FieldList);
1422877Sjjg    UtEndEvent (Event);
1432877Sjjg
1442135SN/A    DtFreeFieldList ();
1452135SN/A
1462877Sjjg    if (ACPI_FAILURE (Status))
1472877Sjjg    {
1482877Sjjg        /* TBD: temporary error message. Msgs should come from function above */
1493900Sjlahoda
1503900Sjlahoda        DtError (ASL_ERROR, ASL_MSG_SYNTAX, NULL,
1513900Sjlahoda            "Could not compile input file");
1523900Sjlahoda
1532877Sjjg        goto CleanupAndExit;
1542877Sjjg    }
1552877Sjjg
1562877Sjjg    /* Create/open the binary output file */
1572877Sjjg
1582877Sjjg    Gbl_Files[ASL_FILE_AML_OUTPUT].Filename = NULL;
1592877Sjjg    Status = FlOpenAmlOutputFile (Gbl_OutputFilenamePrefix);
1602877Sjjg    if (ACPI_FAILURE (Status))
1612877Sjjg    {
1622877Sjjg        goto CleanupAndExit;
1632877Sjjg    }
1642877Sjjg
1652877Sjjg    /* Write the binary, then the optional hex file */
1662877Sjjg
1672877Sjjg    DtOutputBinary (Gbl_RootTable);
1682877Sjjg    HxDoHexOutput ();
1692877Sjjg    DtWriteTableToListing ();
1702877Sjjg
1712877SjjgCleanupAndExit:
1722877Sjjg
1732877Sjjg    CmCleanupAndExit ();
1742877Sjjg    return (Status);
1752877Sjjg}
1762877Sjjg
1770SN/A
1782877Sjjg/******************************************************************************
1792877Sjjg *
1802877Sjjg * FUNCTION:    DtInitialize
1812877Sjjg *
1820SN/A * PARAMETERS:  None
1831520SN/A *
1842132SN/A * RETURN:      Status
1851520SN/A *
1861520SN/A * DESCRIPTION: Initialize data table compiler globals. Enables multiple
1872132SN/A *              compiles per invocation.
1881520SN/A *
1892877Sjjg *****************************************************************************/
1902877Sjjg
1911520SN/Astatic ACPI_STATUS
1922110SN/ADtInitialize (
1932132SN/A    void)
1942110SN/A{
1950SN/A    ACPI_STATUS             Status;
1962877Sjjg
1972877Sjjg
1982877Sjjg    Status = AcpiOsInitialize ();
1992877Sjjg    if (ACPI_FAILURE (Status))
2002877Sjjg    {
2012877Sjjg        return (Status);
2022877Sjjg    }
2032877Sjjg
2042877Sjjg    Status = AcpiUtInitGlobals ();
2052877Sjjg    if (ACPI_FAILURE (Status))
2062877Sjjg    {
2072877Sjjg        return (Status);
2082877Sjjg    }
2092877Sjjg
2102877Sjjg    Gbl_FieldList = NULL;
2112877Sjjg    Gbl_RootTable = NULL;
2122877Sjjg    Gbl_SubtableStack = NULL;
2132877Sjjg
2142877Sjjg    sprintf (VersionString, "%X", (UINT32) ACPI_CA_VERSION);
2152877Sjjg    return (AE_OK);
2162877Sjjg}
2172877Sjjg
2182877Sjjg
2192877Sjjg/******************************************************************************
2202877Sjjg *
2212877Sjjg * FUNCTION:    DtInsertCompilerIds
2222877Sjjg *
2232877Sjjg * PARAMETERS:  FieldList           - Current field list pointer
2242877Sjjg *
2252877Sjjg * RETURN:      None
2262877Sjjg *
2272877Sjjg * DESCRIPTION: Insert the IDs (Name, Version) of the current compiler into
2282877Sjjg *              the original ACPI table header.
2292877Sjjg *
2302877Sjjg *****************************************************************************/
2312877Sjjg
2322877Sjjgstatic void
2332877SjjgDtInsertCompilerIds (
2342877Sjjg    DT_FIELD                *FieldList)
2352877Sjjg{
2362877Sjjg    DT_FIELD                *Next;
2373180Salundblad    UINT32                  i;
2383880Svromero
2393880Svromero
2403880Svromero    /*
2413880Svromero     * Don't insert current compiler ID if requested. Used for compiler
2423880Svromero     * debug/validation only.
2433880Svromero     */
2443880Svromero    if (Gbl_UseOriginalCompilerId)
2453880Svromero    {
2463180Salundblad        return;
2473180Salundblad    }
2483180Salundblad
2493180Salundblad    /* Walk to the Compiler fields at the end of the header */
2503180Salundblad
2513180Salundblad    Next = FieldList;
2523180Salundblad    for (i = 0; i < 7; i++)
2533180Salundblad    {
2543180Salundblad        Next = Next->Next;
2552877Sjjg    }
2563180Salundblad
2572877Sjjg    Next->Value = ASL_CREATOR_ID;
2583180Salundblad    Next->Flags = DT_FIELD_NOT_ALLOCATED;
2593180Salundblad
2603180Salundblad    Next = Next->Next;
2613180Salundblad    Next->Value = VersionString;
2623180Salundblad    Next->Flags = DT_FIELD_NOT_ALLOCATED;
2633180Salundblad}
2643180Salundblad
2653180Salundblad
2662877Sjjg/******************************************************************************
2672877Sjjg *
2682877Sjjg * FUNCTION:    DtCompileDataTable
2693180Salundblad *
2703180Salundblad * PARAMETERS:  FieldList           - Current field list pointer
2713180Salundblad *
2723180Salundblad * RETURN:      Status
2733180Salundblad *
2743180Salundblad * DESCRIPTION: Entry point to compile one data table
2752877Sjjg *
2762877Sjjg *****************************************************************************/
2772877Sjjg
2782877Sjjgstatic ACPI_STATUS
2792877SjjgDtCompileDataTable (
2802877Sjjg    DT_FIELD                **FieldList)
2812877Sjjg{
2822877Sjjg    ACPI_DMTABLE_DATA       *TableData;
2832877Sjjg    DT_SUBTABLE             *Subtable;
2843180Salundblad    char                    *Signature;
2853180Salundblad    ACPI_TABLE_HEADER       *AcpiTableHeader;
2863180Salundblad    ACPI_STATUS             Status;
2873180Salundblad    DT_FIELD                *RootField = *FieldList;
2883180Salundblad
2893180Salundblad
2903180Salundblad    /* Verify that we at least have a table signature and save it */
2913180Salundblad
2922877Sjjg    Signature = DtGetFieldValue (*FieldList);
2932877Sjjg    if (!Signature)
2942877Sjjg    {
2953180Salundblad        sprintf (MsgBuffer, "Expected \"%s\"", "Signature");
2963180Salundblad        DtNameError (ASL_ERROR, ASL_MSG_INVALID_FIELD_NAME,
2973180Salundblad            *FieldList, MsgBuffer);
2983180Salundblad        return (AE_ERROR);
2993180Salundblad    }
3003180Salundblad
3013180Salundblad    Gbl_Signature = UtLocalCalloc (ACPI_STRLEN (Signature) + 1);
3023180Salundblad    strcpy (Gbl_Signature, Signature);
3032877Sjjg
3042877Sjjg    /*
3052877Sjjg     * Handle tables that don't use the common ACPI table header structure.
3062877Sjjg     * Currently, these are the FACS and RSDP. Also check for an OEMx table,
3072877Sjjg     * these tables have user-defined contents.
3082877Sjjg     */
3092877Sjjg    if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS))
3102877Sjjg    {
3112877Sjjg        Status = DtCompileFacs (FieldList);
3122877Sjjg        if (ACPI_FAILURE (Status))
3132877Sjjg        {
3142877Sjjg            return (Status);
3152877Sjjg        }
3162877Sjjg
3172877Sjjg        DtSetTableLength ();
3182900Salundblad        return (Status);
3192900Salundblad    }
3202877Sjjg    else if (ACPI_VALIDATE_RSDP_SIG (Signature))
3212877Sjjg    {
3222877Sjjg        Status = DtCompileRsdp (FieldList);
3232877Sjjg        return (Status);
3242877Sjjg    }
3252877Sjjg    else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_S3PT))
3262877Sjjg    {
3272877Sjjg        Status = DtCompileS3pt (FieldList);
3282877Sjjg        if (ACPI_FAILURE (Status))
3292877Sjjg        {
3302877Sjjg            return (Status);
3312877Sjjg        }
3322877Sjjg
3332877Sjjg        DtSetTableLength ();
3342877Sjjg        return (Status);
3352877Sjjg    }
3362877Sjjg
3372877Sjjg    /*
3382877Sjjg     * All other tables must use the common ACPI table header. Insert the
3392877Sjjg     * current iASL IDs (name, version), and compile the header now.
3402877Sjjg     */
3412877Sjjg    DtInsertCompilerIds (*FieldList);
3423651Sdlsmith
3432877Sjjg    Status = DtCompileTable (FieldList, AcpiDmTableInfoHeader,
3442877Sjjg                &Gbl_RootTable, TRUE);
3452877Sjjg    if (ACPI_FAILURE (Status))
3462877Sjjg    {
3472877Sjjg        return (Status);
3482877Sjjg    }
3492877Sjjg
3502877Sjjg    DtPushSubtable (Gbl_RootTable);
3512877Sjjg
3522877Sjjg    /* Validate the signature via the ACPI table list */
3532877Sjjg
3542877Sjjg    TableData = AcpiDmGetTableData (Signature);
3553792Salanb    if (!TableData || Gbl_CompileGeneric)
3562877Sjjg    {
3573792Salanb        DtCompileGeneric ((void **) FieldList);
3583719Sjjg        goto FinishHeader;
3593719Sjjg    }
3603719Sjjg
3613719Sjjg    /* Dispatch to per-table compile */
3623719Sjjg
3633719Sjjg    if (TableData->CmTableHandler)
3643719Sjjg    {
3652877Sjjg        /* Complex table, has a handler */
3662877Sjjg
3672877Sjjg        Status = TableData->CmTableHandler ((void **) FieldList);
3682877Sjjg        if (ACPI_FAILURE (Status))
3692877Sjjg        {
3702877Sjjg            return (Status);
3712877Sjjg        }
3722877Sjjg    }
3732877Sjjg    else if (TableData->TableInfo)
3742900Salundblad    {
3752877Sjjg        /* Simple table, just walk the info table */
3762877Sjjg
3772877Sjjg        Subtable = NULL;
3782877Sjjg        Status = DtCompileTable (FieldList, TableData->TableInfo,
3792877Sjjg                    &Subtable, TRUE);
3802877Sjjg        if (ACPI_FAILURE (Status))
3812877Sjjg        {
3822877Sjjg            return (Status);
3832877Sjjg        }
3842877Sjjg
3852877Sjjg        DtInsertSubtable (Gbl_RootTable, Subtable);
3862877Sjjg        DtPopSubtable ();
3872877Sjjg    }
3882877Sjjg    else
3890SN/A    {
3900SN/A        DtFatal (ASL_MSG_COMPILER_INTERNAL, *FieldList,
3910SN/A            "Missing table dispatch info");
3922877Sjjg        return (AE_ERROR);
3932877Sjjg    }
3942877Sjjg
3952877SjjgFinishHeader:
3962877Sjjg
3972877Sjjg    /* Set the final table length and then the checksum */
3982877Sjjg
3990SN/A    DtSetTableLength ();
4002877Sjjg    AcpiTableHeader = ACPI_CAST_PTR (
4012877Sjjg        ACPI_TABLE_HEADER, Gbl_RootTable->Buffer);
4022877Sjjg    DtSetTableChecksum (&AcpiTableHeader->Checksum);
4032877Sjjg
4042877Sjjg    DtDumpFieldList (RootField);
4052877Sjjg    DtDumpSubtableList ();
4062877Sjjg    return (AE_OK);
4072877Sjjg}
4082877Sjjg
4092877Sjjg
4102877Sjjg/******************************************************************************
4112877Sjjg *
4122877Sjjg * FUNCTION:    DtCompileTable
4132877Sjjg *
4142877Sjjg * PARAMETERS:  Field               - Current field list pointer
4152877Sjjg *              Info                - Info table for this ACPI table
4162877Sjjg *              RetSubtable         - Compile result of table
4172877Sjjg *              Required            - If this subtable must exist
4182877Sjjg *
4192877Sjjg * RETURN:      Status
4202877Sjjg *
4212877Sjjg * DESCRIPTION: Compile a subtable
4222877Sjjg *
4232877Sjjg *****************************************************************************/
4242877Sjjg
4252877SjjgACPI_STATUS
4262877SjjgDtCompileTable (
4272877Sjjg    DT_FIELD                **Field,
4282877Sjjg    ACPI_DMTABLE_INFO       *Info,
4292877Sjjg    DT_SUBTABLE             **RetSubtable,
4302877Sjjg    BOOLEAN                 Required)
4312877Sjjg{
4322877Sjjg    DT_FIELD                *LocalField;
4332877Sjjg    UINT32                  Length;
4342877Sjjg    DT_SUBTABLE             *Subtable;
4352877Sjjg    DT_SUBTABLE             *InlineSubtable;
4362877Sjjg    UINT32                  FieldLength = 0;
4372877Sjjg    UINT8                   FieldType;
4382877Sjjg    UINT8                   *Buffer;
4390SN/A    UINT8                   *FlagBuffer = NULL;
4400SN/A    UINT32                  CurrentFlagByteOffset = 0;
4411312SN/A    ACPI_STATUS             Status;
4422877Sjjg
4432877Sjjg
4442877Sjjg    if (!Field || !*Field)
4452877Sjjg    {
4462877Sjjg        return (AE_BAD_PARAMETER);
4472877Sjjg    }
4482877Sjjg
4492877Sjjg    Length = DtGetSubtableLength (*Field, Info);
4502877Sjjg    if (Length == ASL_EOF)
4512877Sjjg    {
4522877Sjjg        return (AE_ERROR);
4532877Sjjg    }
4542877Sjjg
4552877Sjjg    Subtable = UtLocalCalloc (sizeof (DT_SUBTABLE));
4562877Sjjg
4572877Sjjg    if (Length > 0)
4582877Sjjg    {
4592877Sjjg        Subtable->Buffer = UtLocalCalloc (Length);
4602877Sjjg    }
4612877Sjjg    Subtable->Length = Length;
4622877Sjjg    Subtable->TotalLength = Length;
4632877Sjjg    Buffer = Subtable->Buffer;
4642877Sjjg
4652877Sjjg    LocalField = *Field;
4662877Sjjg
4672877Sjjg    /*
4682877Sjjg     * Main loop walks the info table for this ACPI table or subtable
4692877Sjjg     */
4702877Sjjg    for (; Info->Name; Info++)
4712877Sjjg    {
4722877Sjjg        if (Info->Opcode == ACPI_DMT_EXTRA_TEXT)
4732877Sjjg        {
4742877Sjjg            continue;
4752877Sjjg        }
4762877Sjjg
4772877Sjjg        if (!LocalField)
4782877Sjjg        {
4792877Sjjg            sprintf (MsgBuffer, "Found NULL field - Field name \"%s\" needed",
4802877Sjjg                Info->Name);
4812877Sjjg            DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
4822877Sjjg            Status = AE_BAD_DATA;
4832877Sjjg            goto Error;
4842877Sjjg        }
4852877Sjjg
4862877Sjjg        /* Maintain table offsets */
4872877Sjjg
4882877Sjjg        LocalField->TableOffset = Gbl_CurrentTableOffset;
4892877Sjjg        FieldLength = DtGetFieldLength (LocalField, Info);
4902877Sjjg        Gbl_CurrentTableOffset += FieldLength;
4912877Sjjg
4922877Sjjg        FieldType = DtGetFieldType (Info);
4932877Sjjg        Gbl_InputFieldCount++;
4942877Sjjg
4952877Sjjg        switch (FieldType)
4962877Sjjg        {
4972877Sjjg        case DT_FIELD_TYPE_FLAGS_INTEGER:
4982877Sjjg            /*
4992877Sjjg             * Start of the definition of a flags field.
5002877Sjjg             * This master flags integer starts at value zero, in preparation
5013828Smcimadamore             * to compile and insert the flag fields from the individual bits
5022877Sjjg             */
5032877Sjjg            LocalField = LocalField->Next;
5042877Sjjg            *Field = LocalField;
5052877Sjjg
5062877Sjjg            FlagBuffer = Buffer;
5072877Sjjg            CurrentFlagByteOffset = Info->Offset;
5082877Sjjg            break;
5092877Sjjg
5102877Sjjg        case DT_FIELD_TYPE_FLAG:
5112877Sjjg
5122877Sjjg            /* Individual Flag field, can be multiple bits */
5132877Sjjg
5142877Sjjg            if (FlagBuffer)
5152877Sjjg            {
5162877Sjjg                /*
5172877Sjjg                 * We must increment the FlagBuffer when we have crossed
5182877Sjjg                 * into the next flags byte within the flags field
5192877Sjjg                 * of type DT_FIELD_TYPE_FLAGS_INTEGER.
5202877Sjjg                 */
5212877Sjjg                FlagBuffer += (Info->Offset - CurrentFlagByteOffset);
5222877Sjjg                CurrentFlagByteOffset = Info->Offset;
5232877Sjjg
5242877Sjjg                DtCompileFlag (FlagBuffer, LocalField, Info);
5252877Sjjg            }
5262877Sjjg            else
5272877Sjjg            {
5282877Sjjg                /* TBD - this is an internal error */
5292877Sjjg            }
5302877Sjjg
5312877Sjjg            LocalField = LocalField->Next;
5322877Sjjg            *Field = LocalField;
5332877Sjjg            break;
5342877Sjjg
5352877Sjjg        case DT_FIELD_TYPE_INLINE_SUBTABLE:
5362877Sjjg            /*
5372877Sjjg             * Recursion (one level max): compile GAS (Generic Address)
5382877Sjjg             * or Notify in-line subtable
5392877Sjjg             */
5402877Sjjg            *Field = LocalField;
5412877Sjjg
5422877Sjjg            if (Info->Opcode == ACPI_DMT_GAS)
5432877Sjjg            {
5442877Sjjg                Status = DtCompileTable (Field, AcpiDmTableInfoGas,
5452877Sjjg                    &InlineSubtable, TRUE);
5462877Sjjg            }
5472877Sjjg            else
5482877Sjjg            {
5492877Sjjg                Status = DtCompileTable (Field, AcpiDmTableInfoHestNotify,
5502877Sjjg                    &InlineSubtable, TRUE);
5512877Sjjg            }
5522877Sjjg
5532877Sjjg            if (ACPI_FAILURE (Status))
5542877Sjjg            {
5552877Sjjg                goto Error;
5562877Sjjg            }
5572877Sjjg
5582877Sjjg            DtSetSubtableLength (InlineSubtable);
5592877Sjjg
5602877Sjjg            ACPI_MEMCPY (Buffer, InlineSubtable->Buffer, FieldLength);
5612877Sjjg            ACPI_FREE (InlineSubtable->Buffer);
5622877Sjjg            ACPI_FREE (InlineSubtable);
5632877Sjjg            LocalField = *Field;
5642877Sjjg            break;
5652877Sjjg
5662877Sjjg        case DT_FIELD_TYPE_LABEL:
5672877Sjjg
5682877Sjjg            DtWriteFieldToListing (Buffer, LocalField, 0);
5692877Sjjg            LocalField = LocalField->Next;
5702877Sjjg            break;
5712877Sjjg
5722877Sjjg        default:
5732877Sjjg
5742877Sjjg            /* Normal case for most field types (Integer, String, etc.) */
5752877Sjjg
5762877Sjjg            DtCompileOneField (Buffer, LocalField,
5772877Sjjg                FieldLength, FieldType, Info->Flags);
5782877Sjjg
5792877Sjjg            DtWriteFieldToListing (Buffer, LocalField, FieldLength);
5802877Sjjg            LocalField = LocalField->Next;
5812877Sjjg
5822877Sjjg            if (Info->Flags & DT_LENGTH)
5832877Sjjg            {
5842877Sjjg                /* Field is an Integer that will contain a subtable length */
5852877Sjjg
5862877Sjjg                Subtable->LengthField = Buffer;
5872877Sjjg                Subtable->SizeOfLengthField = FieldLength;
5882877Sjjg            }
5892877Sjjg
5902877Sjjg            break;
5912877Sjjg        }
5922877Sjjg
5932877Sjjg        Buffer += FieldLength;
5942877Sjjg    }
5952877Sjjg
5962877Sjjg    *Field = LocalField;
5972877Sjjg    *RetSubtable = Subtable;
5982877Sjjg    return (AE_OK);
5992877Sjjg
6002877SjjgError:
6012877Sjjg    ACPI_FREE (Subtable->Buffer);
6022877Sjjg    ACPI_FREE (Subtable);
6032877Sjjg    return (Status);
6042877Sjjg}
6052877Sjjg