dtsubtable.c revision 241973
1/******************************************************************************
2 *
3 * Module Name: dtsubtable.c - handling of subtables within ACPI tables
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2012, 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 MERCHANTIBILITY 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#define __DTSUBTABLE_C__
45
46#include <contrib/dev/acpica/compiler/aslcompiler.h>
47#include <contrib/dev/acpica/compiler/dtcompiler.h>
48
49#define _COMPONENT          DT_COMPILER
50        ACPI_MODULE_NAME    ("dtsubtable")
51
52
53/******************************************************************************
54 *
55 * FUNCTION:    DtCreateSubtable
56 *
57 * PARAMETERS:  Buffer              - Input buffer
58 *              Length              - Buffer length
59 *              RetSubtable         - Returned newly created subtable
60 *
61 * RETURN:      None
62 *
63 * DESCRIPTION: Create a subtable that is not listed with ACPI_DMTABLE_INFO
64 *              For example, FACS has 24 bytes reserved at the end
65 *              and it's not listed at AcpiDmTableInfoFacs
66 *
67 *****************************************************************************/
68
69void
70DtCreateSubtable (
71    UINT8                   *Buffer,
72    UINT32                  Length,
73    DT_SUBTABLE             **RetSubtable)
74{
75    DT_SUBTABLE             *Subtable;
76
77
78    Subtable = UtLocalCalloc (sizeof (DT_SUBTABLE));
79
80    /* Create a new buffer for the subtable data */
81
82    Subtable->Buffer = UtLocalCalloc (Length);
83    ACPI_MEMCPY (Subtable->Buffer, Buffer, Length);
84
85    Subtable->Length = Length;
86    Subtable->TotalLength = Length;
87
88    *RetSubtable = Subtable;
89}
90
91
92/******************************************************************************
93 *
94 * FUNCTION:    DtInsertSubtable
95 *
96 * PARAMETERS:  ParentTable         - The Parent of the new subtable
97 *              Subtable            - The new subtable to insert
98 *
99 * RETURN:      None
100 *
101 * DESCRIPTION: Insert the new subtable to the parent table
102 *
103 *****************************************************************************/
104
105void
106DtInsertSubtable (
107    DT_SUBTABLE             *ParentTable,
108    DT_SUBTABLE             *Subtable)
109{
110    DT_SUBTABLE             *ChildTable;
111
112
113    Subtable->Peer = NULL;
114    Subtable->Parent = ParentTable;
115
116    /* Link the new entry into the child list */
117
118    if (!ParentTable->Child)
119    {
120        ParentTable->Child = Subtable;
121    }
122    else
123    {
124        /* Walk to the end of the child list */
125
126        ChildTable = ParentTable->Child;
127        while (ChildTable->Peer)
128        {
129            ChildTable = ChildTable->Peer;
130        }
131
132        /* Add new subtable at the end of the child list */
133
134        ChildTable->Peer = Subtable;
135    }
136}
137
138
139/******************************************************************************
140 *
141 * FUNCTION:    DtPushSubtable
142 *
143 * PARAMETERS:  Subtable            - Subtable to push
144 *
145 * RETURN:      None
146 *
147 * DESCRIPTION: Push a subtable onto a subtable stack
148 *
149 *****************************************************************************/
150
151void
152DtPushSubtable (
153    DT_SUBTABLE             *Subtable)
154{
155
156    Subtable->StackTop = Gbl_SubtableStack;
157    Gbl_SubtableStack = Subtable;
158}
159
160
161/******************************************************************************
162 *
163 * FUNCTION:    DtPopSubtable
164 *
165 * PARAMETERS:  None
166 *
167 * RETURN:      None
168 *
169 * DESCRIPTION: Pop a subtable from a subtable stack. Uses global SubtableStack
170 *
171 *****************************************************************************/
172
173void
174DtPopSubtable (
175    void)
176{
177    DT_SUBTABLE             *Subtable;
178
179
180    Subtable = Gbl_SubtableStack;
181
182    if (Subtable)
183    {
184        Gbl_SubtableStack = Subtable->StackTop;
185    }
186}
187
188
189/******************************************************************************
190 *
191 * FUNCTION:    DtPeekSubtable
192 *
193 * PARAMETERS:  None
194 *
195 * RETURN:      The subtable on top of stack
196 *
197 * DESCRIPTION: Get the subtable on top of stack
198 *
199 *****************************************************************************/
200
201DT_SUBTABLE *
202DtPeekSubtable (
203    void)
204{
205
206    return (Gbl_SubtableStack);
207}
208
209
210/******************************************************************************
211 *
212 * FUNCTION:    DtGetNextSubtable
213 *
214 * PARAMETERS:  ParentTable         - Parent table whose children we are
215 *                                    getting
216 *              ChildTable          - Previous child that was found.
217 *                                    The NEXT child will be returned
218 *
219 * RETURN:      Pointer to the NEXT child or NULL if none is found.
220 *
221 * DESCRIPTION: Return the next peer subtable within the tree.
222 *
223 *****************************************************************************/
224
225DT_SUBTABLE *
226DtGetNextSubtable (
227    DT_SUBTABLE             *ParentTable,
228    DT_SUBTABLE             *ChildTable)
229{
230    ACPI_FUNCTION_ENTRY ();
231
232
233    if (!ChildTable)
234    {
235        /* It's really the parent's _scope_ that we want */
236
237        return (ParentTable->Child);
238    }
239
240    /* Otherwise just return the next peer (NULL if at end-of-list) */
241
242    return (ChildTable->Peer);
243}
244
245
246/******************************************************************************
247 *
248 * FUNCTION:    DtGetParentSubtable
249 *
250 * PARAMETERS:  Subtable            - Current subtable
251 *
252 * RETURN:      Parent of the given subtable
253 *
254 * DESCRIPTION: Get the parent of the given subtable in the tree
255 *
256 *****************************************************************************/
257
258DT_SUBTABLE *
259DtGetParentSubtable (
260    DT_SUBTABLE             *Subtable)
261{
262
263    if (!Subtable)
264    {
265        return (NULL);
266    }
267
268    return (Subtable->Parent);
269}
270
271
272/******************************************************************************
273 *
274 * FUNCTION:    DtGetSubtableLength
275 *
276 * PARAMETERS:  Field               - Current field list pointer
277 *              Info                - Data table info
278 *
279 * RETURN:      Subtable length
280 *
281 * DESCRIPTION: Get length of bytes needed to compile the subtable
282 *
283 *****************************************************************************/
284
285UINT32
286DtGetSubtableLength (
287    DT_FIELD                *Field,
288    ACPI_DMTABLE_INFO       *Info)
289{
290    UINT32                  ByteLength = 0;
291    UINT8                   Step;
292    UINT8                   i;
293
294
295    /* Walk entire Info table; Null name terminates */
296
297    for (; Info->Name; Info++)
298    {
299        if (Info->Opcode == ACPI_DMT_EXTRA_TEXT)
300        {
301            continue;
302        }
303
304        if (!Field)
305        {
306            goto Error;
307        }
308
309        ByteLength += DtGetFieldLength (Field, Info);
310
311        switch (Info->Opcode)
312        {
313        case ACPI_DMT_GAS:
314            Step = 5;
315            break;
316
317        case ACPI_DMT_HESTNTFY:
318            Step = 9;
319            break;
320
321        default:
322            Step = 1;
323            break;
324        }
325
326        for (i = 0; i < Step; i++)
327        {
328            if (!Field)
329            {
330                goto Error;
331            }
332
333            Field = Field->Next;
334        }
335    }
336
337    return (ByteLength);
338
339Error:
340    if (!Field)
341    {
342        sprintf (MsgBuffer, "Found NULL field - Field name \"%s\" needed",
343            Info->Name);
344        DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
345    }
346
347    return (ASL_EOF);
348}
349
350
351/******************************************************************************
352 *
353 * FUNCTION:    DtSetSubtableLength
354 *
355 * PARAMETERS:  Subtable            - Subtable
356 *
357 * RETURN:      None
358 *
359 * DESCRIPTION: Set length of the subtable into its length field
360 *
361 *****************************************************************************/
362
363void
364DtSetSubtableLength (
365    DT_SUBTABLE             *Subtable)
366{
367
368    if (!Subtable->LengthField)
369    {
370        return;
371    }
372
373    ACPI_MEMCPY (Subtable->LengthField, &Subtable->TotalLength,
374        Subtable->SizeOfLengthField);
375}
376