dtsubtable.c revision 228110
1208625Sjkim/******************************************************************************
2208625Sjkim *
3208625Sjkim * Module Name: dtsubtable.c - handling of subtables within ACPI tables
4208625Sjkim *
5208625Sjkim *****************************************************************************/
6208625Sjkim
7217365Sjkim/*
8217365Sjkim * Copyright (C) 2000 - 2011, Intel Corp.
9208625Sjkim * All rights reserved.
10208625Sjkim *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
25208625Sjkim *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
29208625Sjkim *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
43208625Sjkim
44208625Sjkim#define __DTSUBTABLE_C__
45208625Sjkim
46209746Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h>
47209746Sjkim#include <contrib/dev/acpica/compiler/dtcompiler.h>
48208625Sjkim
49208625Sjkim#define _COMPONENT          DT_COMPILER
50208625Sjkim        ACPI_MODULE_NAME    ("dtsubtable")
51208625Sjkim
52208625Sjkim
53208625Sjkim/******************************************************************************
54208625Sjkim *
55208625Sjkim * FUNCTION:    DtCreateSubtable
56208625Sjkim *
57208625Sjkim * PARAMETERS:  Buffer              - Input buffer
58208625Sjkim *              Length              - Buffer length
59208625Sjkim *              RetSubtable         - Returned newly created subtable
60208625Sjkim *
61208625Sjkim * RETURN:      None
62208625Sjkim *
63208625Sjkim * DESCRIPTION: Create a subtable that is not listed with ACPI_DMTABLE_INFO
64208625Sjkim *              For example, FACS has 24 bytes reserved at the end
65208625Sjkim *              and it's not listed at AcpiDmTableInfoFacs
66208625Sjkim *
67208625Sjkim *****************************************************************************/
68208625Sjkim
69208625Sjkimvoid
70208625SjkimDtCreateSubtable (
71208625Sjkim    UINT8                   *Buffer,
72208625Sjkim    UINT32                  Length,
73208625Sjkim    DT_SUBTABLE             **RetSubtable)
74208625Sjkim{
75208625Sjkim    DT_SUBTABLE             *Subtable;
76208625Sjkim
77208625Sjkim
78208625Sjkim    Subtable = UtLocalCalloc (sizeof (DT_SUBTABLE));
79208625Sjkim
80208625Sjkim    /* Create a new buffer for the subtable data */
81208625Sjkim
82208625Sjkim    Subtable->Buffer = UtLocalCalloc (Length);
83208625Sjkim    ACPI_MEMCPY (Subtable->Buffer, Buffer, Length);
84208625Sjkim
85208625Sjkim    Subtable->Length = Length;
86208625Sjkim    Subtable->TotalLength = Length;
87208625Sjkim
88208625Sjkim    *RetSubtable = Subtable;
89208625Sjkim}
90208625Sjkim
91208625Sjkim
92208625Sjkim/******************************************************************************
93208625Sjkim *
94208625Sjkim * FUNCTION:    DtInsertSubtable
95208625Sjkim *
96208625Sjkim * PARAMETERS:  ParentTable         - The Parent of the new subtable
97208625Sjkim *              Subtable            - The new subtable to insert
98208625Sjkim *
99208625Sjkim * RETURN:      None
100208625Sjkim *
101208625Sjkim * DESCRIPTION: Insert the new subtable to the parent table
102208625Sjkim *
103208625Sjkim *****************************************************************************/
104208625Sjkim
105208625Sjkimvoid
106208625SjkimDtInsertSubtable (
107208625Sjkim    DT_SUBTABLE             *ParentTable,
108208625Sjkim    DT_SUBTABLE             *Subtable)
109208625Sjkim{
110208625Sjkim    DT_SUBTABLE             *ChildTable;
111208625Sjkim
112208625Sjkim
113208625Sjkim    Subtable->Peer = NULL;
114208625Sjkim    Subtable->Parent = ParentTable;
115208625Sjkim
116208625Sjkim    /* Link the new entry into the child list */
117208625Sjkim
118208625Sjkim    if (!ParentTable->Child)
119208625Sjkim    {
120208625Sjkim        ParentTable->Child = Subtable;
121208625Sjkim    }
122208625Sjkim    else
123208625Sjkim    {
124208625Sjkim        /* Walk to the end of the child list */
125208625Sjkim
126208625Sjkim        ChildTable = ParentTable->Child;
127208625Sjkim        while (ChildTable->Peer)
128208625Sjkim        {
129208625Sjkim            ChildTable = ChildTable->Peer;
130208625Sjkim        }
131208625Sjkim
132208625Sjkim        /* Add new subtable at the end of the child list */
133208625Sjkim
134208625Sjkim        ChildTable->Peer = Subtable;
135208625Sjkim    }
136208625Sjkim}
137208625Sjkim
138208625Sjkim
139208625Sjkim/******************************************************************************
140208625Sjkim *
141208625Sjkim * FUNCTION:    DtPushSubtable
142208625Sjkim *
143208625Sjkim * PARAMETERS:  Subtable            - Subtable to push
144208625Sjkim *
145208625Sjkim * RETURN:      None
146208625Sjkim *
147208625Sjkim * DESCRIPTION: Push a subtable onto a subtable stack
148208625Sjkim *
149208625Sjkim *****************************************************************************/
150208625Sjkim
151208625Sjkimvoid
152208625SjkimDtPushSubtable (
153208625Sjkim    DT_SUBTABLE             *Subtable)
154208625Sjkim{
155208625Sjkim
156208625Sjkim    Subtable->StackTop = Gbl_SubtableStack;
157208625Sjkim    Gbl_SubtableStack = Subtable;
158208625Sjkim}
159208625Sjkim
160208625Sjkim
161208625Sjkim/******************************************************************************
162208625Sjkim *
163208625Sjkim * FUNCTION:    DtPopSubtable
164208625Sjkim *
165208625Sjkim * PARAMETERS:  None
166208625Sjkim *
167208625Sjkim * RETURN:      None
168208625Sjkim *
169208625Sjkim * DESCRIPTION: Pop a subtable from a subtable stack. Uses global SubtableStack
170208625Sjkim *
171208625Sjkim *****************************************************************************/
172208625Sjkim
173208625Sjkimvoid
174208625SjkimDtPopSubtable (
175208625Sjkim    void)
176208625Sjkim{
177208625Sjkim    DT_SUBTABLE             *Subtable;
178208625Sjkim
179208625Sjkim
180208625Sjkim    Subtable = Gbl_SubtableStack;
181208625Sjkim
182208625Sjkim    if (Subtable)
183208625Sjkim    {
184208625Sjkim        Gbl_SubtableStack = Subtable->StackTop;
185208625Sjkim    }
186208625Sjkim}
187208625Sjkim
188208625Sjkim
189208625Sjkim/******************************************************************************
190208625Sjkim *
191208625Sjkim * FUNCTION:    DtPeekSubtable
192208625Sjkim *
193208625Sjkim * PARAMETERS:  None
194208625Sjkim *
195208625Sjkim * RETURN:      The subtable on top of stack
196208625Sjkim *
197208625Sjkim * DESCRIPTION: Get the subtable on top of stack
198208625Sjkim *
199208625Sjkim *****************************************************************************/
200208625Sjkim
201208625SjkimDT_SUBTABLE *
202208625SjkimDtPeekSubtable (
203208625Sjkim    void)
204208625Sjkim{
205208625Sjkim
206208625Sjkim    return (Gbl_SubtableStack);
207208625Sjkim}
208208625Sjkim
209208625Sjkim
210208625Sjkim/******************************************************************************
211208625Sjkim *
212208625Sjkim * FUNCTION:    DtGetNextSubtable
213208625Sjkim *
214208625Sjkim * PARAMETERS:  ParentTable         - Parent table whose children we are
215208625Sjkim *                                    getting
216208625Sjkim *              ChildTable          - Previous child that was found.
217208625Sjkim *                                    The NEXT child will be returned
218208625Sjkim *
219208625Sjkim * RETURN:      Pointer to the NEXT child or NULL if none is found.
220208625Sjkim *
221208625Sjkim * DESCRIPTION: Return the next peer subtable within the tree.
222208625Sjkim *
223208625Sjkim *****************************************************************************/
224208625Sjkim
225208625SjkimDT_SUBTABLE *
226208625SjkimDtGetNextSubtable (
227208625Sjkim    DT_SUBTABLE             *ParentTable,
228208625Sjkim    DT_SUBTABLE             *ChildTable)
229208625Sjkim{
230208625Sjkim    ACPI_FUNCTION_ENTRY ();
231208625Sjkim
232208625Sjkim
233208625Sjkim    if (!ChildTable)
234208625Sjkim    {
235208625Sjkim        /* It's really the parent's _scope_ that we want */
236208625Sjkim
237208625Sjkim        return (ParentTable->Child);
238208625Sjkim    }
239208625Sjkim
240208625Sjkim    /* Otherwise just return the next peer (NULL if at end-of-list) */
241208625Sjkim
242208625Sjkim    return (ChildTable->Peer);
243208625Sjkim}
244208625Sjkim
245208625Sjkim
246208625Sjkim/******************************************************************************
247208625Sjkim *
248208625Sjkim * FUNCTION:    DtGetParentSubtable
249208625Sjkim *
250208625Sjkim * PARAMETERS:  Subtable            - Current subtable
251208625Sjkim *
252208625Sjkim * RETURN:      Parent of the given subtable
253208625Sjkim *
254208625Sjkim * DESCRIPTION: Get the parent of the given subtable in the tree
255208625Sjkim *
256208625Sjkim *****************************************************************************/
257208625Sjkim
258208625SjkimDT_SUBTABLE *
259208625SjkimDtGetParentSubtable (
260208625Sjkim    DT_SUBTABLE             *Subtable)
261208625Sjkim{
262208625Sjkim
263208625Sjkim    if (!Subtable)
264208625Sjkim    {
265208625Sjkim        return (NULL);
266208625Sjkim    }
267208625Sjkim
268208625Sjkim    return (Subtable->Parent);
269208625Sjkim}
270208625Sjkim
271208625Sjkim
272208625Sjkim/******************************************************************************
273208625Sjkim *
274208625Sjkim * FUNCTION:    DtGetSubtableLength
275208625Sjkim *
276208625Sjkim * PARAMETERS:  Field               - Current field list pointer
277208625Sjkim *              Info                - Data table info
278208625Sjkim *
279208625Sjkim * RETURN:      Subtable length
280208625Sjkim *
281208625Sjkim * DESCRIPTION: Get length of bytes needed to compile the subtable
282208625Sjkim *
283208625Sjkim *****************************************************************************/
284208625Sjkim
285208625SjkimUINT32
286208625SjkimDtGetSubtableLength (
287208625Sjkim    DT_FIELD                *Field,
288208625Sjkim    ACPI_DMTABLE_INFO       *Info)
289208625Sjkim{
290208625Sjkim    UINT32                  ByteLength = 0;
291220663Sjkim    UINT8                   Step;
292220663Sjkim    UINT8                   i;
293208625Sjkim
294208625Sjkim
295208625Sjkim    /* Walk entire Info table; Null name terminates */
296208625Sjkim
297208625Sjkim    for (; Info->Name; Info++)
298208625Sjkim    {
299228110Sjkim        if (Info->Opcode == ACPI_DMT_EXTRA_TEXT)
300228110Sjkim        {
301228110Sjkim            continue;
302228110Sjkim        }
303228110Sjkim
304220663Sjkim        if (!Field)
305220663Sjkim        {
306220663Sjkim            goto Error;
307220663Sjkim        }
308220663Sjkim
309208625Sjkim        ByteLength += DtGetFieldLength (Field, Info);
310220663Sjkim
311220663Sjkim        switch (Info->Opcode)
312220663Sjkim        {
313220663Sjkim        case ACPI_DMT_GAS:
314220663Sjkim            Step = 5;
315220663Sjkim            break;
316220663Sjkim
317220663Sjkim        case ACPI_DMT_HESTNTFY:
318220663Sjkim            Step = 9;
319220663Sjkim            break;
320220663Sjkim
321220663Sjkim        default:
322220663Sjkim            Step = 1;
323220663Sjkim            break;
324220663Sjkim        }
325220663Sjkim
326220663Sjkim        for (i = 0; i < Step; i++)
327220663Sjkim        {
328220663Sjkim            if (!Field)
329220663Sjkim            {
330220663Sjkim                goto Error;
331220663Sjkim            }
332220663Sjkim
333220663Sjkim            Field = Field->Next;
334220663Sjkim        }
335208625Sjkim    }
336208625Sjkim
337208625Sjkim    return (ByteLength);
338220663Sjkim
339220663SjkimError:
340220663Sjkim    if (!Field)
341220663Sjkim    {
342220663Sjkim        sprintf (MsgBuffer, "Found NULL field - Field name \"%s\" needed",
343220663Sjkim            Info->Name);
344220663Sjkim        DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
345220663Sjkim    }
346220663Sjkim
347220663Sjkim    return (ASL_EOF);
348208625Sjkim}
349208625Sjkim
350208625Sjkim
351208625Sjkim/******************************************************************************
352208625Sjkim *
353208625Sjkim * FUNCTION:    DtSetSubtableLength
354208625Sjkim *
355208625Sjkim * PARAMETERS:  Subtable            - Subtable
356208625Sjkim *
357208625Sjkim * RETURN:      None
358208625Sjkim *
359208625Sjkim * DESCRIPTION: Set length of the subtable into its length field
360208625Sjkim *
361208625Sjkim *****************************************************************************/
362208625Sjkim
363208625Sjkimvoid
364208625SjkimDtSetSubtableLength (
365208625Sjkim    DT_SUBTABLE             *Subtable)
366208625Sjkim{
367208625Sjkim
368208625Sjkim    if (!Subtable->LengthField)
369208625Sjkim    {
370208625Sjkim        return;
371208625Sjkim    }
372208625Sjkim
373208625Sjkim    ACPI_MEMCPY (Subtable->LengthField, &Subtable->TotalLength,
374208625Sjkim        Subtable->SizeOfLengthField);
375208625Sjkim}
376