1208625Sjkim/******************************************************************************
2208625Sjkim *
3208625Sjkim * Module Name: dtsubtable.c - handling of subtables within ACPI tables
4208625Sjkim *
5208625Sjkim *****************************************************************************/
6208625Sjkim
7217365Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, 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
44209746Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h>
45209746Sjkim#include <contrib/dev/acpica/compiler/dtcompiler.h>
46208625Sjkim
47208625Sjkim#define _COMPONENT          DT_COMPILER
48208625Sjkim        ACPI_MODULE_NAME    ("dtsubtable")
49208625Sjkim
50208625Sjkim
51208625Sjkim/******************************************************************************
52208625Sjkim *
53208625Sjkim * FUNCTION:    DtCreateSubtable
54208625Sjkim *
55208625Sjkim * PARAMETERS:  Buffer              - Input buffer
56208625Sjkim *              Length              - Buffer length
57208625Sjkim *              RetSubtable         - Returned newly created subtable
58208625Sjkim *
59208625Sjkim * RETURN:      None
60208625Sjkim *
61208625Sjkim * DESCRIPTION: Create a subtable that is not listed with ACPI_DMTABLE_INFO
62208625Sjkim *              For example, FACS has 24 bytes reserved at the end
63208625Sjkim *              and it's not listed at AcpiDmTableInfoFacs
64208625Sjkim *
65208625Sjkim *****************************************************************************/
66208625Sjkim
67208625Sjkimvoid
68208625SjkimDtCreateSubtable (
69208625Sjkim    UINT8                   *Buffer,
70208625Sjkim    UINT32                  Length,
71208625Sjkim    DT_SUBTABLE             **RetSubtable)
72208625Sjkim{
73208625Sjkim    DT_SUBTABLE             *Subtable;
74281075Sdim    char                    *String;
75208625Sjkim
76208625Sjkim
77281075Sdim    Subtable = UtSubtableCacheCalloc ();
78208625Sjkim
79208625Sjkim    /* Create a new buffer for the subtable data */
80208625Sjkim
81281075Sdim    String = UtStringCacheCalloc (Length);
82281075Sdim    Subtable->Buffer = ACPI_CAST_PTR (UINT8, String);
83306536Sjkim    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;
115245582Sjkim    Subtable->Depth = ParentTable->Depth + 1;
116208625Sjkim
117208625Sjkim    /* Link the new entry into the child list */
118208625Sjkim
119208625Sjkim    if (!ParentTable->Child)
120208625Sjkim    {
121208625Sjkim        ParentTable->Child = Subtable;
122208625Sjkim    }
123208625Sjkim    else
124208625Sjkim    {
125208625Sjkim        /* Walk to the end of the child list */
126208625Sjkim
127208625Sjkim        ChildTable = ParentTable->Child;
128208625Sjkim        while (ChildTable->Peer)
129208625Sjkim        {
130208625Sjkim            ChildTable = ChildTable->Peer;
131208625Sjkim        }
132208625Sjkim
133208625Sjkim        /* Add new subtable at the end of the child list */
134208625Sjkim
135208625Sjkim        ChildTable->Peer = Subtable;
136208625Sjkim    }
137208625Sjkim}
138208625Sjkim
139208625Sjkim
140208625Sjkim/******************************************************************************
141208625Sjkim *
142208625Sjkim * FUNCTION:    DtPushSubtable
143208625Sjkim *
144208625Sjkim * PARAMETERS:  Subtable            - Subtable to push
145208625Sjkim *
146208625Sjkim * RETURN:      None
147208625Sjkim *
148208625Sjkim * DESCRIPTION: Push a subtable onto a subtable stack
149208625Sjkim *
150208625Sjkim *****************************************************************************/
151208625Sjkim
152208625Sjkimvoid
153208625SjkimDtPushSubtable (
154208625Sjkim    DT_SUBTABLE             *Subtable)
155208625Sjkim{
156208625Sjkim
157208625Sjkim    Subtable->StackTop = Gbl_SubtableStack;
158208625Sjkim    Gbl_SubtableStack = Subtable;
159208625Sjkim}
160208625Sjkim
161208625Sjkim
162208625Sjkim/******************************************************************************
163208625Sjkim *
164208625Sjkim * FUNCTION:    DtPopSubtable
165208625Sjkim *
166208625Sjkim * PARAMETERS:  None
167208625Sjkim *
168208625Sjkim * RETURN:      None
169208625Sjkim *
170208625Sjkim * DESCRIPTION: Pop a subtable from a subtable stack. Uses global SubtableStack
171208625Sjkim *
172208625Sjkim *****************************************************************************/
173208625Sjkim
174208625Sjkimvoid
175208625SjkimDtPopSubtable (
176208625Sjkim    void)
177208625Sjkim{
178208625Sjkim    DT_SUBTABLE             *Subtable;
179208625Sjkim
180208625Sjkim
181208625Sjkim    Subtable = Gbl_SubtableStack;
182208625Sjkim
183208625Sjkim    if (Subtable)
184208625Sjkim    {
185208625Sjkim        Gbl_SubtableStack = Subtable->StackTop;
186208625Sjkim    }
187208625Sjkim}
188208625Sjkim
189208625Sjkim
190208625Sjkim/******************************************************************************
191208625Sjkim *
192208625Sjkim * FUNCTION:    DtPeekSubtable
193208625Sjkim *
194208625Sjkim * PARAMETERS:  None
195208625Sjkim *
196208625Sjkim * RETURN:      The subtable on top of stack
197208625Sjkim *
198208625Sjkim * DESCRIPTION: Get the subtable on top of stack
199208625Sjkim *
200208625Sjkim *****************************************************************************/
201208625Sjkim
202208625SjkimDT_SUBTABLE *
203208625SjkimDtPeekSubtable (
204208625Sjkim    void)
205208625Sjkim{
206208625Sjkim
207208625Sjkim    return (Gbl_SubtableStack);
208208625Sjkim}
209208625Sjkim
210208625Sjkim
211208625Sjkim/******************************************************************************
212208625Sjkim *
213208625Sjkim * FUNCTION:    DtGetNextSubtable
214208625Sjkim *
215208625Sjkim * PARAMETERS:  ParentTable         - Parent table whose children we are
216208625Sjkim *                                    getting
217208625Sjkim *              ChildTable          - Previous child that was found.
218208625Sjkim *                                    The NEXT child will be returned
219208625Sjkim *
220208625Sjkim * RETURN:      Pointer to the NEXT child or NULL if none is found.
221208625Sjkim *
222208625Sjkim * DESCRIPTION: Return the next peer subtable within the tree.
223208625Sjkim *
224208625Sjkim *****************************************************************************/
225208625Sjkim
226208625SjkimDT_SUBTABLE *
227208625SjkimDtGetNextSubtable (
228208625Sjkim    DT_SUBTABLE             *ParentTable,
229208625Sjkim    DT_SUBTABLE             *ChildTable)
230208625Sjkim{
231208625Sjkim    ACPI_FUNCTION_ENTRY ();
232208625Sjkim
233208625Sjkim
234208625Sjkim    if (!ChildTable)
235208625Sjkim    {
236208625Sjkim        /* It's really the parent's _scope_ that we want */
237208625Sjkim
238208625Sjkim        return (ParentTable->Child);
239208625Sjkim    }
240208625Sjkim
241208625Sjkim    /* Otherwise just return the next peer (NULL if at end-of-list) */
242208625Sjkim
243208625Sjkim    return (ChildTable->Peer);
244208625Sjkim}
245208625Sjkim
246208625Sjkim
247208625Sjkim/******************************************************************************
248208625Sjkim *
249208625Sjkim * FUNCTION:    DtGetParentSubtable
250208625Sjkim *
251208625Sjkim * PARAMETERS:  Subtable            - Current subtable
252208625Sjkim *
253208625Sjkim * RETURN:      Parent of the given subtable
254208625Sjkim *
255208625Sjkim * DESCRIPTION: Get the parent of the given subtable in the tree
256208625Sjkim *
257208625Sjkim *****************************************************************************/
258208625Sjkim
259208625SjkimDT_SUBTABLE *
260208625SjkimDtGetParentSubtable (
261208625Sjkim    DT_SUBTABLE             *Subtable)
262208625Sjkim{
263208625Sjkim
264208625Sjkim    if (!Subtable)
265208625Sjkim    {
266208625Sjkim        return (NULL);
267208625Sjkim    }
268208625Sjkim
269208625Sjkim    return (Subtable->Parent);
270208625Sjkim}
271208625Sjkim
272208625Sjkim
273208625Sjkim/******************************************************************************
274208625Sjkim *
275208625Sjkim * FUNCTION:    DtGetSubtableLength
276208625Sjkim *
277208625Sjkim * PARAMETERS:  Field               - Current field list pointer
278208625Sjkim *              Info                - Data table info
279208625Sjkim *
280208625Sjkim * RETURN:      Subtable length
281208625Sjkim *
282208625Sjkim * DESCRIPTION: Get length of bytes needed to compile the subtable
283208625Sjkim *
284208625Sjkim *****************************************************************************/
285208625Sjkim
286208625SjkimUINT32
287208625SjkimDtGetSubtableLength (
288208625Sjkim    DT_FIELD                *Field,
289208625Sjkim    ACPI_DMTABLE_INFO       *Info)
290208625Sjkim{
291208625Sjkim    UINT32                  ByteLength = 0;
292220663Sjkim    UINT8                   Step;
293220663Sjkim    UINT8                   i;
294208625Sjkim
295208625Sjkim
296208625Sjkim    /* Walk entire Info table; Null name terminates */
297208625Sjkim
298208625Sjkim    for (; Info->Name; Info++)
299208625Sjkim    {
300228110Sjkim        if (Info->Opcode == ACPI_DMT_EXTRA_TEXT)
301228110Sjkim        {
302228110Sjkim            continue;
303228110Sjkim        }
304228110Sjkim
305220663Sjkim        if (!Field)
306220663Sjkim        {
307220663Sjkim            goto Error;
308220663Sjkim        }
309220663Sjkim
310208625Sjkim        ByteLength += DtGetFieldLength (Field, Info);
311220663Sjkim
312220663Sjkim        switch (Info->Opcode)
313220663Sjkim        {
314220663Sjkim        case ACPI_DMT_GAS:
315250838Sjkim
316220663Sjkim            Step = 5;
317220663Sjkim            break;
318220663Sjkim
319220663Sjkim        case ACPI_DMT_HESTNTFY:
320250838Sjkim
321220663Sjkim            Step = 9;
322220663Sjkim            break;
323220663Sjkim
324284460Sjkim        case ACPI_DMT_IORTMEM:
325284460Sjkim
326284460Sjkim            Step = 10;
327284460Sjkim            break;
328284460Sjkim
329220663Sjkim        default:
330250838Sjkim
331220663Sjkim            Step = 1;
332220663Sjkim            break;
333220663Sjkim        }
334220663Sjkim
335220663Sjkim        for (i = 0; i < Step; i++)
336220663Sjkim        {
337220663Sjkim            if (!Field)
338220663Sjkim            {
339220663Sjkim                goto Error;
340220663Sjkim            }
341220663Sjkim
342220663Sjkim            Field = Field->Next;
343220663Sjkim        }
344208625Sjkim    }
345208625Sjkim
346208625Sjkim    return (ByteLength);
347220663Sjkim
348220663SjkimError:
349220663Sjkim    if (!Field)
350220663Sjkim    {
351220663Sjkim        sprintf (MsgBuffer, "Found NULL field - Field name \"%s\" needed",
352220663Sjkim            Info->Name);
353220663Sjkim        DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
354220663Sjkim    }
355220663Sjkim
356220663Sjkim    return (ASL_EOF);
357208625Sjkim}
358208625Sjkim
359208625Sjkim
360208625Sjkim/******************************************************************************
361208625Sjkim *
362208625Sjkim * FUNCTION:    DtSetSubtableLength
363208625Sjkim *
364208625Sjkim * PARAMETERS:  Subtable            - Subtable
365208625Sjkim *
366208625Sjkim * RETURN:      None
367208625Sjkim *
368208625Sjkim * DESCRIPTION: Set length of the subtable into its length field
369208625Sjkim *
370208625Sjkim *****************************************************************************/
371208625Sjkim
372208625Sjkimvoid
373208625SjkimDtSetSubtableLength (
374208625Sjkim    DT_SUBTABLE             *Subtable)
375208625Sjkim{
376208625Sjkim
377208625Sjkim    if (!Subtable->LengthField)
378208625Sjkim    {
379208625Sjkim        return;
380208625Sjkim    }
381208625Sjkim
382306536Sjkim    memcpy (Subtable->LengthField, &Subtable->TotalLength,
383208625Sjkim        Subtable->SizeOfLengthField);
384208625Sjkim}
385