dtsubtable.c revision 245582
1230557Sjimharris/******************************************************************************
2230557Sjimharris *
3230557Sjimharris * Module Name: dtsubtable.c - handling of subtables within ACPI tables
4230557Sjimharris *
5230557Sjimharris *****************************************************************************/
6230557Sjimharris
7230557Sjimharris/*
8230557Sjimharris * Copyright (C) 2000 - 2013, Intel Corp.
9230557Sjimharris * All rights reserved.
10230557Sjimharris *
11230557Sjimharris * Redistribution and use in source and binary forms, with or without
12230557Sjimharris * modification, are permitted provided that the following conditions
13230557Sjimharris * are met:
14230557Sjimharris * 1. Redistributions of source code must retain the above copyright
15230557Sjimharris *    notice, this list of conditions, and the following disclaimer,
16230557Sjimharris *    without modification.
17230557Sjimharris * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18230557Sjimharris *    substantially similar to the "NO WARRANTY" disclaimer below
19230557Sjimharris *    ("Disclaimer") and any redistribution must be conditioned upon
20230557Sjimharris *    including a substantially similar Disclaimer requirement for further
21230557Sjimharris *    binary redistribution.
22230557Sjimharris * 3. Neither the names of the above-listed copyright holders nor the names
23230557Sjimharris *    of any contributors may be used to endorse or promote products derived
24230557Sjimharris *    from this software without specific prior written permission.
25230557Sjimharris *
26230557Sjimharris * Alternatively, this software may be distributed under the terms of the
27230557Sjimharris * GNU General Public License ("GPL") version 2 as published by the Free
28230557Sjimharris * Software Foundation.
29230557Sjimharris *
30230557Sjimharris * NO WARRANTY
31230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32230557Sjimharris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33230557Sjimharris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34230557Sjimharris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35230557Sjimharris * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36230557Sjimharris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37230557Sjimharris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38230557Sjimharris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39230557Sjimharris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40230557Sjimharris * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41230557Sjimharris * POSSIBILITY OF SUCH DAMAGES.
42230557Sjimharris */
43230557Sjimharris
44230557Sjimharris#define __DTSUBTABLE_C__
45230557Sjimharris
46230557Sjimharris#include <contrib/dev/acpica/compiler/aslcompiler.h>
47230557Sjimharris#include <contrib/dev/acpica/compiler/dtcompiler.h>
48230557Sjimharris
49230557Sjimharris#define _COMPONENT          DT_COMPILER
50230557Sjimharris        ACPI_MODULE_NAME    ("dtsubtable")
51230557Sjimharris
52230557Sjimharris
53230557Sjimharris/******************************************************************************
54230557Sjimharris *
55230557Sjimharris * FUNCTION:    DtCreateSubtable
56230557Sjimharris *
57230557Sjimharris * PARAMETERS:  Buffer              - Input buffer
58230557Sjimharris *              Length              - Buffer length
59230557Sjimharris *              RetSubtable         - Returned newly created subtable
60230557Sjimharris *
61230557Sjimharris * RETURN:      None
62230557Sjimharris *
63230557Sjimharris * DESCRIPTION: Create a subtable that is not listed with ACPI_DMTABLE_INFO
64230557Sjimharris *              For example, FACS has 24 bytes reserved at the end
65230557Sjimharris *              and it's not listed at AcpiDmTableInfoFacs
66230557Sjimharris *
67230557Sjimharris *****************************************************************************/
68230557Sjimharris
69230557Sjimharrisvoid
70230557SjimharrisDtCreateSubtable (
71230557Sjimharris    UINT8                   *Buffer,
72230557Sjimharris    UINT32                  Length,
73230557Sjimharris    DT_SUBTABLE             **RetSubtable)
74230557Sjimharris{
75230557Sjimharris    DT_SUBTABLE             *Subtable;
76230557Sjimharris
77230557Sjimharris
78230557Sjimharris    Subtable = UtLocalCalloc (sizeof (DT_SUBTABLE));
79230557Sjimharris
80230557Sjimharris    /* Create a new buffer for the subtable data */
81230557Sjimharris
82230557Sjimharris    Subtable->Buffer = UtLocalCalloc (Length);
83230557Sjimharris    ACPI_MEMCPY (Subtable->Buffer, Buffer, Length);
84230557Sjimharris
85230557Sjimharris    Subtable->Length = Length;
86230557Sjimharris    Subtable->TotalLength = Length;
87230557Sjimharris
88230557Sjimharris    *RetSubtable = Subtable;
89230557Sjimharris}
90230557Sjimharris
91230557Sjimharris
92230557Sjimharris/******************************************************************************
93230557Sjimharris *
94230557Sjimharris * FUNCTION:    DtInsertSubtable
95230557Sjimharris *
96230557Sjimharris * PARAMETERS:  ParentTable         - The Parent of the new subtable
97230557Sjimharris *              Subtable            - The new subtable to insert
98230557Sjimharris *
99230557Sjimharris * RETURN:      None
100230557Sjimharris *
101230557Sjimharris * DESCRIPTION: Insert the new subtable to the parent table
102230557Sjimharris *
103230557Sjimharris *****************************************************************************/
104230557Sjimharris
105230557Sjimharrisvoid
106230557SjimharrisDtInsertSubtable (
107230557Sjimharris    DT_SUBTABLE             *ParentTable,
108230557Sjimharris    DT_SUBTABLE             *Subtable)
109230557Sjimharris{
110230557Sjimharris    DT_SUBTABLE             *ChildTable;
111230557Sjimharris
112230557Sjimharris
113230557Sjimharris    Subtable->Peer = NULL;
114230557Sjimharris    Subtable->Parent = ParentTable;
115230557Sjimharris    Subtable->Depth = ParentTable->Depth + 1;
116230557Sjimharris
117230557Sjimharris    /* Link the new entry into the child list */
118230557Sjimharris
119230557Sjimharris    if (!ParentTable->Child)
120230557Sjimharris    {
121230557Sjimharris        ParentTable->Child = Subtable;
122230557Sjimharris    }
123230557Sjimharris    else
124230557Sjimharris    {
125230557Sjimharris        /* Walk to the end of the child list */
126230557Sjimharris
127230557Sjimharris        ChildTable = ParentTable->Child;
128230557Sjimharris        while (ChildTable->Peer)
129230557Sjimharris        {
130230557Sjimharris            ChildTable = ChildTable->Peer;
131230557Sjimharris        }
132230557Sjimharris
133230557Sjimharris        /* Add new subtable at the end of the child list */
134230557Sjimharris
135230557Sjimharris        ChildTable->Peer = Subtable;
136230557Sjimharris    }
137230557Sjimharris}
138230557Sjimharris
139230557Sjimharris
140230557Sjimharris/******************************************************************************
141230557Sjimharris *
142230557Sjimharris * FUNCTION:    DtPushSubtable
143230557Sjimharris *
144230557Sjimharris * PARAMETERS:  Subtable            - Subtable to push
145230557Sjimharris *
146230557Sjimharris * RETURN:      None
147230557Sjimharris *
148230557Sjimharris * DESCRIPTION: Push a subtable onto a subtable stack
149230557Sjimharris *
150230557Sjimharris *****************************************************************************/
151230557Sjimharris
152230557Sjimharrisvoid
153230557SjimharrisDtPushSubtable (
154230557Sjimharris    DT_SUBTABLE             *Subtable)
155230557Sjimharris{
156230557Sjimharris
157230557Sjimharris    Subtable->StackTop = Gbl_SubtableStack;
158230557Sjimharris    Gbl_SubtableStack = Subtable;
159230557Sjimharris}
160230557Sjimharris
161230557Sjimharris
162230557Sjimharris/******************************************************************************
163230557Sjimharris *
164230557Sjimharris * FUNCTION:    DtPopSubtable
165230557Sjimharris *
166230557Sjimharris * PARAMETERS:  None
167230557Sjimharris *
168230557Sjimharris * RETURN:      None
169230557Sjimharris *
170230557Sjimharris * DESCRIPTION: Pop a subtable from a subtable stack. Uses global SubtableStack
171230557Sjimharris *
172230557Sjimharris *****************************************************************************/
173230557Sjimharris
174230557Sjimharrisvoid
175230557SjimharrisDtPopSubtable (
176230557Sjimharris    void)
177230557Sjimharris{
178230557Sjimharris    DT_SUBTABLE             *Subtable;
179230557Sjimharris
180230557Sjimharris
181230557Sjimharris    Subtable = Gbl_SubtableStack;
182230557Sjimharris
183230557Sjimharris    if (Subtable)
184230557Sjimharris    {
185230557Sjimharris        Gbl_SubtableStack = Subtable->StackTop;
186230557Sjimharris    }
187230557Sjimharris}
188230557Sjimharris
189230557Sjimharris
190230557Sjimharris/******************************************************************************
191230557Sjimharris *
192230557Sjimharris * FUNCTION:    DtPeekSubtable
193230557Sjimharris *
194230557Sjimharris * PARAMETERS:  None
195230557Sjimharris *
196230557Sjimharris * RETURN:      The subtable on top of stack
197230557Sjimharris *
198230557Sjimharris * DESCRIPTION: Get the subtable on top of stack
199230557Sjimharris *
200230557Sjimharris *****************************************************************************/
201230557Sjimharris
202230557SjimharrisDT_SUBTABLE *
203230557SjimharrisDtPeekSubtable (
204230557Sjimharris    void)
205230557Sjimharris{
206230557Sjimharris
207230557Sjimharris    return (Gbl_SubtableStack);
208230557Sjimharris}
209230557Sjimharris
210230557Sjimharris
211230557Sjimharris/******************************************************************************
212230557Sjimharris *
213230557Sjimharris * FUNCTION:    DtGetNextSubtable
214230557Sjimharris *
215230557Sjimharris * PARAMETERS:  ParentTable         - Parent table whose children we are
216230557Sjimharris *                                    getting
217230557Sjimharris *              ChildTable          - Previous child that was found.
218230557Sjimharris *                                    The NEXT child will be returned
219230557Sjimharris *
220230557Sjimharris * RETURN:      Pointer to the NEXT child or NULL if none is found.
221230557Sjimharris *
222230557Sjimharris * DESCRIPTION: Return the next peer subtable within the tree.
223230557Sjimharris *
224230557Sjimharris *****************************************************************************/
225230557Sjimharris
226230557SjimharrisDT_SUBTABLE *
227230557SjimharrisDtGetNextSubtable (
228230557Sjimharris    DT_SUBTABLE             *ParentTable,
229230557Sjimharris    DT_SUBTABLE             *ChildTable)
230230557Sjimharris{
231230557Sjimharris    ACPI_FUNCTION_ENTRY ();
232230557Sjimharris
233230557Sjimharris
234230557Sjimharris    if (!ChildTable)
235230557Sjimharris    {
236230557Sjimharris        /* It's really the parent's _scope_ that we want */
237230557Sjimharris
238230557Sjimharris        return (ParentTable->Child);
239230557Sjimharris    }
240230557Sjimharris
241230557Sjimharris    /* Otherwise just return the next peer (NULL if at end-of-list) */
242230557Sjimharris
243230557Sjimharris    return (ChildTable->Peer);
244}
245
246
247/******************************************************************************
248 *
249 * FUNCTION:    DtGetParentSubtable
250 *
251 * PARAMETERS:  Subtable            - Current subtable
252 *
253 * RETURN:      Parent of the given subtable
254 *
255 * DESCRIPTION: Get the parent of the given subtable in the tree
256 *
257 *****************************************************************************/
258
259DT_SUBTABLE *
260DtGetParentSubtable (
261    DT_SUBTABLE             *Subtable)
262{
263
264    if (!Subtable)
265    {
266        return (NULL);
267    }
268
269    return (Subtable->Parent);
270}
271
272
273/******************************************************************************
274 *
275 * FUNCTION:    DtGetSubtableLength
276 *
277 * PARAMETERS:  Field               - Current field list pointer
278 *              Info                - Data table info
279 *
280 * RETURN:      Subtable length
281 *
282 * DESCRIPTION: Get length of bytes needed to compile the subtable
283 *
284 *****************************************************************************/
285
286UINT32
287DtGetSubtableLength (
288    DT_FIELD                *Field,
289    ACPI_DMTABLE_INFO       *Info)
290{
291    UINT32                  ByteLength = 0;
292    UINT8                   Step;
293    UINT8                   i;
294
295
296    /* Walk entire Info table; Null name terminates */
297
298    for (; Info->Name; Info++)
299    {
300        if (Info->Opcode == ACPI_DMT_EXTRA_TEXT)
301        {
302            continue;
303        }
304
305        if (!Field)
306        {
307            goto Error;
308        }
309
310        ByteLength += DtGetFieldLength (Field, Info);
311
312        switch (Info->Opcode)
313        {
314        case ACPI_DMT_GAS:
315            Step = 5;
316            break;
317
318        case ACPI_DMT_HESTNTFY:
319            Step = 9;
320            break;
321
322        default:
323            Step = 1;
324            break;
325        }
326
327        for (i = 0; i < Step; i++)
328        {
329            if (!Field)
330            {
331                goto Error;
332            }
333
334            Field = Field->Next;
335        }
336    }
337
338    return (ByteLength);
339
340Error:
341    if (!Field)
342    {
343        sprintf (MsgBuffer, "Found NULL field - Field name \"%s\" needed",
344            Info->Name);
345        DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
346    }
347
348    return (ASL_EOF);
349}
350
351
352/******************************************************************************
353 *
354 * FUNCTION:    DtSetSubtableLength
355 *
356 * PARAMETERS:  Subtable            - Subtable
357 *
358 * RETURN:      None
359 *
360 * DESCRIPTION: Set length of the subtable into its length field
361 *
362 *****************************************************************************/
363
364void
365DtSetSubtableLength (
366    DT_SUBTABLE             *Subtable)
367{
368
369    if (!Subtable->LengthField)
370    {
371        return;
372    }
373
374    ACPI_MEMCPY (Subtable->LengthField, &Subtable->TotalLength,
375        Subtable->SizeOfLengthField);
376}
377