dtsubtable.c revision 250838
11590Srgrimes/******************************************************************************
2252231Spfg *
31590Srgrimes * Module Name: dtsubtable.c - handling of subtables within ACPI tables
41590Srgrimes *
51590Srgrimes *****************************************************************************/
61590Srgrimes
71590Srgrimes/*
81590Srgrimes * Copyright (C) 2000 - 2013, Intel Corp.
91590Srgrimes * All rights reserved.
101590Srgrimes *
111590Srgrimes * Redistribution and use in source and binary forms, with or without
121590Srgrimes * modification, are permitted provided that the following conditions
131590Srgrimes * are met:
141590Srgrimes * 1. Redistributions of source code must retain the above copyright
151590Srgrimes *    notice, this list of conditions, and the following disclaimer,
161590Srgrimes *    without modification.
171590Srgrimes * 2. Redistributions in binary form must reproduce at minimum a disclaimer
181590Srgrimes *    substantially similar to the "NO WARRANTY" disclaimer below
191590Srgrimes *    ("Disclaimer") and any redistribution must be conditioned upon
201590Srgrimes *    including a substantially similar Disclaimer requirement for further
211590Srgrimes *    binary redistribution.
221590Srgrimes * 3. Neither the names of the above-listed copyright holders nor the names
231590Srgrimes *    of any contributors may be used to endorse or promote products derived
241590Srgrimes *    from this software without specific prior written permission.
251590Srgrimes *
261590Srgrimes * Alternatively, this software may be distributed under the terms of the
271590Srgrimes * GNU General Public License ("GPL") version 2 as published by the Free
281590Srgrimes * Software Foundation.
291590Srgrimes *
301590Srgrimes * NO WARRANTY
311590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
321590Srgrimes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
331590Srgrimes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
341590Srgrimes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3587766Smarkm * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3687766Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3787766Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
381590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3928066Scharnier * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
401590Srgrimes * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
411590Srgrimes * POSSIBILITY OF SUCH DAMAGES.
4287766Smarkm */
431590Srgrimes
441590Srgrimes#define __DTSUBTABLE_C__
4587766Smarkm
4628066Scharnier#include <contrib/dev/acpica/compiler/aslcompiler.h>
471590Srgrimes#include <contrib/dev/acpica/compiler/dtcompiler.h>
4898200Ssobomax
4998200Ssobomax#define _COMPONENT          DT_COMPILER
5096175Sjmallett        ACPI_MODULE_NAME    ("dtsubtable")
5196175Sjmallett
521590Srgrimes
5328066Scharnier/******************************************************************************
541590Srgrimes *
55200462Sdelphij * FUNCTION:    DtCreateSubtable
56141563Sstefanf *
57132145Stjr * PARAMETERS:  Buffer              - Input buffer
5817522Sache *              Length              - Buffer length
591590Srgrimes *              RetSubtable         - Returned newly created subtable
60200462Sdelphij *
61252231Spfg * RETURN:      None
621590Srgrimes *
631590Srgrimes * DESCRIPTION: Create a subtable that is not listed with ACPI_DMTABLE_INFO
641590Srgrimes *              For example, FACS has 24 bytes reserved at the end
651590Srgrimes *              and it's not listed at AcpiDmTableInfoFacs
661590Srgrimes *
671590Srgrimes *****************************************************************************/
681590Srgrimes
691590Srgrimesvoid
701590SrgrimesDtCreateSubtable (
711590Srgrimes    UINT8                   *Buffer,
721590Srgrimes    UINT32                  Length,
731590Srgrimes    DT_SUBTABLE             **RetSubtable)
741590Srgrimes{
751590Srgrimes    DT_SUBTABLE             *Subtable;
761590Srgrimes
771590Srgrimes
781590Srgrimes    Subtable = UtLocalCalloc (sizeof (DT_SUBTABLE));
791590Srgrimes
801590Srgrimes    /* Create a new buffer for the subtable data */
811590Srgrimes
821590Srgrimes    Subtable->Buffer = UtLocalCalloc (Length);
831590Srgrimes    ACPI_MEMCPY (Subtable->Buffer, Buffer, Length);
841590Srgrimes
851590Srgrimes    Subtable->Length = Length;
861590Srgrimes    Subtable->TotalLength = Length;
871590Srgrimes
881590Srgrimes    *RetSubtable = Subtable;
891590Srgrimes}
901590Srgrimes
911590Srgrimes
921590Srgrimes/******************************************************************************
931590Srgrimes *
941590Srgrimes * FUNCTION:    DtInsertSubtable
951590Srgrimes *
961590Srgrimes * PARAMETERS:  ParentTable         - The Parent of the new subtable
971590Srgrimes *              Subtable            - The new subtable to insert
981590Srgrimes *
99122049Sdes * RETURN:      None
100122049Sdes *
10199352Stjr * DESCRIPTION: Insert the new subtable to the parent table
1021590Srgrimes *
10358309Sgreen *****************************************************************************/
10497238Stjr
1051590Srgrimesvoid
106168921SyarDtInsertSubtable (
107168921Syar    DT_SUBTABLE             *ParentTable,
1081590Srgrimes    DT_SUBTABLE             *Subtable)
1091590Srgrimes{
110168921Syar    DT_SUBTABLE             *ChildTable;
111168921Syar
1121590Srgrimes
11387766Smarkm    Subtable->Peer = NULL;
114122049Sdes    Subtable->Parent = ParentTable;
115122049Sdes    Subtable->Depth = ParentTable->Depth + 1;
116122049Sdes
117173437Sdds    /* Link the new entry into the child list */
1181590Srgrimes
1191590Srgrimes    if (!ParentTable->Child)
12092922Simp    {
12192922Simp        ParentTable->Child = Subtable;
12292922Simp    }
1231590Srgrimes    else
1241590Srgrimes    {
125122044Sdes        /* Walk to the end of the child list */
1261590Srgrimes
1271590Srgrimes        ChildTable = ParentTable->Child;
12860394Snsayer        while (ChildTable->Peer)
1291590Srgrimes        {
13017522Sache            ChildTable = ChildTable->Peer;
13117522Sache        }
1321590Srgrimes
13396175Sjmallett        /* Add new subtable at the end of the child list */
13496175Sjmallett
135268019Spfg        ChildTable->Peer = Subtable;
1361590Srgrimes    }
137205992Simp}
13858309Sgreen
13958309Sgreen
14058309Sgreen/******************************************************************************
141168921Syar *
142168921Syar * FUNCTION:    DtPushSubtable
143168921Syar *
144168921Syar * PARAMETERS:  Subtable            - Subtable to push
1451590Srgrimes *
1461590Srgrimes * RETURN:      None
1471590Srgrimes *
1481590Srgrimes * DESCRIPTION: Push a subtable onto a subtable stack
1491590Srgrimes *
15080286Sobrien *****************************************************************************/
15180286Sobrien
15260394Snsayervoid
15360394SnsayerDtPushSubtable (
15460394Snsayer    DT_SUBTABLE             *Subtable)
1551590Srgrimes{
1561590Srgrimes
1571590Srgrimes    Subtable->StackTop = Gbl_SubtableStack;
1581590Srgrimes    Gbl_SubtableStack = Subtable;
1591590Srgrimes}
16096175Sjmallett
16196175Sjmallett
162168921Syar/******************************************************************************
16396175Sjmallett *
164146055Sglebius * FUNCTION:    DtPopSubtable
165268019Spfg *
166268019Spfg * PARAMETERS:  None
167146055Sglebius *
1681590Srgrimes * RETURN:      None
1691590Srgrimes *
1701590Srgrimes * DESCRIPTION: Pop a subtable from a subtable stack. Uses global SubtableStack
171268019Spfg *
172268019Spfg *****************************************************************************/
173268019Spfg
174268019Spfgvoid
1751590SrgrimesDtPopSubtable (
1761590Srgrimes    void)
17728066Scharnier{
1781590Srgrimes    DT_SUBTABLE             *Subtable;
1791590Srgrimes
1801590Srgrimes
1811590Srgrimes    Subtable = Gbl_SubtableStack;
1821590Srgrimes
1831590Srgrimes    if (Subtable)
1841590Srgrimes    {
1851590Srgrimes        Gbl_SubtableStack = Subtable->StackTop;
1861590Srgrimes    }
1871590Srgrimes}
1881590Srgrimes
1891590Srgrimes
1901590Srgrimes/******************************************************************************
1911590Srgrimes *
1921590Srgrimes * FUNCTION:    DtPeekSubtable
1931590Srgrimes *
1941590Srgrimes * PARAMETERS:  None
1951590Srgrimes *
1961590Srgrimes * RETURN:      The subtable on top of stack
1971590Srgrimes *
1981590Srgrimes * DESCRIPTION: Get the subtable on top of stack
19928066Scharnier *
20097238Stjr *****************************************************************************/
2011590Srgrimes
2021590SrgrimesDT_SUBTABLE *
20328066ScharnierDtPeekSubtable (
204122044Sdes    void)
20528066Scharnier{
206268019Spfg
207268325Spfg    return (Gbl_SubtableStack);
208268325Spfg}
209268019Spfg
21028066Scharnier
21128066Scharnier/******************************************************************************
21228066Scharnier *
2131590Srgrimes * FUNCTION:    DtGetNextSubtable
2141590Srgrimes *
2151590Srgrimes * PARAMETERS:  ParentTable         - Parent table whose children we are
2161590Srgrimes *                                    getting
2171590Srgrimes *              ChildTable          - Previous child that was found.
218122044Sdes *                                    The NEXT child will be returned
2191590Srgrimes *
2201590Srgrimes * RETURN:      Pointer to the NEXT child or NULL if none is found.
2211590Srgrimes *
2221590Srgrimes * DESCRIPTION: Return the next peer subtable within the tree.
2231590Srgrimes *
2241590Srgrimes *****************************************************************************/
2251590Srgrimes
2261590SrgrimesDT_SUBTABLE *
2271590SrgrimesDtGetNextSubtable (
2281590Srgrimes    DT_SUBTABLE             *ParentTable,
22941602Sarchie    DT_SUBTABLE             *ChildTable)
23041602Sarchie{
23141602Sarchie    ACPI_FUNCTION_ENTRY ();
2321590Srgrimes
23341602Sarchie
2341590Srgrimes    if (!ChildTable)
2351590Srgrimes    {
2361590Srgrimes        /* It's really the parent's _scope_ that we want */
2371590Srgrimes
23828066Scharnier        return (ParentTable->Child);
2391590Srgrimes    }
2401590Srgrimes
2411590Srgrimes    /* Otherwise just return the next peer (NULL if at end-of-list) */
2421590Srgrimes
243176126Sdwmalone    return (ChildTable->Peer);
2441590Srgrimes}
2451590Srgrimes
2461590Srgrimes
2471590Srgrimes/******************************************************************************
2481590Srgrimes *
2491590Srgrimes * FUNCTION:    DtGetParentSubtable
2501590Srgrimes *
2511590Srgrimes * PARAMETERS:  Subtable            - Current subtable
2521590Srgrimes *
2531590Srgrimes * RETURN:      Parent of the given subtable
2541590Srgrimes *
2551590Srgrimes * DESCRIPTION: Get the parent of the given subtable in the tree
2561590Srgrimes *
2571590Srgrimes *****************************************************************************/
25841602Sarchie
25941602SarchieDT_SUBTABLE *
2601590SrgrimesDtGetParentSubtable (
2611590Srgrimes    DT_SUBTABLE             *Subtable)
2621590Srgrimes{
2631590Srgrimes
2641590Srgrimes    if (!Subtable)
2651590Srgrimes    {
2661590Srgrimes        return (NULL);
2671590Srgrimes    }
2681590Srgrimes
2691590Srgrimes    return (Subtable->Parent);
2701590Srgrimes}
2711590Srgrimes
2721590Srgrimes
2731590Srgrimes/******************************************************************************
27441602Sarchie *
27541602Sarchie * FUNCTION:    DtGetSubtableLength
2761590Srgrimes *
2771590Srgrimes * PARAMETERS:  Field               - Current field list pointer
2781590Srgrimes *              Info                - Data table info
2791590Srgrimes *
2801590Srgrimes * RETURN:      Subtable length
2811590Srgrimes *
2821590Srgrimes * DESCRIPTION: Get length of bytes needed to compile the subtable
2831590Srgrimes *
2841590Srgrimes *****************************************************************************/
2851590Srgrimes
2861590SrgrimesUINT32
2871590SrgrimesDtGetSubtableLength (
28841602Sarchie    DT_FIELD                *Field,
28941602Sarchie    ACPI_DMTABLE_INFO       *Info)
2901590Srgrimes{
2911590Srgrimes    UINT32                  ByteLength = 0;
2921590Srgrimes    UINT8                   Step;
2931590Srgrimes    UINT8                   i;
2941590Srgrimes
2951590Srgrimes
2961590Srgrimes    /* Walk entire Info table; Null name terminates */
29741602Sarchie
29841602Sarchie    for (; Info->Name; Info++)
2991590Srgrimes    {
3001590Srgrimes        if (Info->Opcode == ACPI_DMT_EXTRA_TEXT)
3011590Srgrimes        {
3021590Srgrimes            continue;
3031590Srgrimes        }
3041590Srgrimes
3051590Srgrimes        if (!Field)
30628066Scharnier        {
3071590Srgrimes            goto Error;
3081590Srgrimes        }
3091590Srgrimes
3101590Srgrimes        ByteLength += DtGetFieldLength (Field, Info);
3111590Srgrimes
3121590Srgrimes        switch (Info->Opcode)
3131590Srgrimes        {
314122044Sdes        case ACPI_DMT_GAS:
3151590Srgrimes
316122049Sdes            Step = 5;
317252231Spfg            break;
318252231Spfg
319252231Spfg        case ACPI_DMT_HESTNTFY:
32019829Swosch
32198200Ssobomax            Step = 9;
3221590Srgrimes            break;
323122049Sdes
32498200Ssobomax        default:
32598200Ssobomax
32698200Ssobomax            Step = 1;
327168921Syar            break;
328122049Sdes        }
32998200Ssobomax
330122049Sdes        for (i = 0; i < Step; i++)
331122049Sdes        {
33298200Ssobomax            if (!Field)
33398200Ssobomax            {
33498200Ssobomax                goto Error;
33598200Ssobomax            }
33698200Ssobomax
337122049Sdes            Field = Field->Next;
338122049Sdes        }
33998200Ssobomax    }
34098200Ssobomax
34198200Ssobomax    return (ByteLength);
342122049Sdes
34398294StjrError:
34498200Ssobomax    if (!Field)
34598200Ssobomax    {
346122049Sdes        sprintf (MsgBuffer, "Found NULL field - Field name \"%s\" needed",
347122049Sdes            Info->Name);
348130039Sbrian        DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
349217133Sjilles    }
350217133Sjilles
351217133Sjilles    return (ASL_EOF);
352217133Sjilles}
353217133Sjilles
354217133Sjilles
355217133Sjilles/******************************************************************************
356217133Sjilles *
357130039Sbrian * FUNCTION:    DtSetSubtableLength
358217133Sjilles *
359217133Sjilles * PARAMETERS:  Subtable            - Subtable
360130039Sbrian *
361130039Sbrian * RETURN:      None
362130039Sbrian *
363122049Sdes * DESCRIPTION: Set length of the subtable into its length field
364130039Sbrian *
365130039Sbrian *****************************************************************************/
366217133Sjilles
367217133Sjillesvoid
368217133SjillesDtSetSubtableLength (
369217133Sjilles    DT_SUBTABLE             *Subtable)
370217133Sjilles{
371130039Sbrian
372217133Sjilles    if (!Subtable->LengthField)
373217133Sjilles    {
374217133Sjilles        return;
375217133Sjilles    }
376217133Sjilles
377217133Sjilles    ACPI_MEMCPY (Subtable->LengthField, &Subtable->TotalLength,
378130039Sbrian        Subtable->SizeOfLengthField);
379130039Sbrian}
380122049Sdes